feat(FN-1118): add mobile sharing and deep-link managers
- Implement ShareManager with native Capacitor sharing, web share fallback, and clipboard fallback plus typed share lifecycle events - Implement DeepLinkManager with native appUrlOpen and browser hash listeners, URL parsing for fusion schemes and universal links, and error events - Wire plugin exports and initializePlugins support for share/deepLinks options, and configure Capacitor iOS/Android fusion URL schemes - Add comprehensive Vitest coverage for sharing and deep-link behavior and document usage in the mobile package README
This commit is contained in:
@@ -59,3 +59,103 @@ Use `manager.getDeviceToken()` after registration to retrieve the native device
|
||||
This package currently handles **receiving** push notifications and in-app routing events only.
|
||||
|
||||
Server-side FCM/APNs delivery infrastructure (token storage, provider credentials, push sending services) is intentionally out of scope for this feature.
|
||||
|
||||
## Native Sharing & Deep Links
|
||||
|
||||
### ShareManager
|
||||
|
||||
`ShareManager` opens platform-native sharing when available and always includes a Fusion deep link in the shared payload.
|
||||
|
||||
```ts
|
||||
import { ShareManager } from "@fusion/mobile";
|
||||
|
||||
const manager = new ShareManager();
|
||||
await manager.initialize();
|
||||
|
||||
await manager.shareTask({
|
||||
id: "FN-1118",
|
||||
title: "Mobile Plugins - Native Sharing & Deep Links",
|
||||
description: "Implements native share sheet support and deep link parsing.",
|
||||
});
|
||||
```
|
||||
|
||||
#### Share behavior + fallbacks
|
||||
|
||||
- Builds a payload with:
|
||||
- `title`: `task.title` or fallback `Task {id}`
|
||||
- `text`: task description (truncated to 200 chars with `...` when needed)
|
||||
- `url`: `${deepLinkBaseUrl}{task.id}` (default base: `fusion://task/`)
|
||||
- **Native (Capacitor)**: uses `@capacitor/share`
|
||||
- **Web fallback**: uses `navigator.share(...)` when available
|
||||
- **Final fallback**: copies the deep-link URL to `navigator.clipboard.writeText(...)`
|
||||
|
||||
#### Share events
|
||||
|
||||
- `share:success` → `{ taskId }`
|
||||
- `share:cancelled` → `{ taskId }`
|
||||
- `share:error` → `{ taskId, error }`
|
||||
|
||||
### DeepLinkManager
|
||||
|
||||
`DeepLinkManager` handles incoming links and emits parsed payloads for app-level navigation.
|
||||
|
||||
```ts
|
||||
import { DeepLinkManager } from "@fusion/mobile";
|
||||
|
||||
const deepLinks = new DeepLinkManager({
|
||||
scheme: "fusion://",
|
||||
universalLinkHosts: ["app.fusion.dev"],
|
||||
});
|
||||
|
||||
await deepLinks.initialize();
|
||||
|
||||
deepLinks.on("deeplink:received", (payload) => {
|
||||
// route to screen/task/project in app UI
|
||||
console.log(payload);
|
||||
});
|
||||
```
|
||||
|
||||
#### Supported URL patterns
|
||||
|
||||
- `fusion://task/{taskId}`
|
||||
- `fusion://project/{projectId}`
|
||||
- `fusion://project/{projectId}/task/{taskId}`
|
||||
- `fusion://settings`
|
||||
- `fusion://agents`
|
||||
- Query params are preserved in `payload.params` for custom-scheme links
|
||||
|
||||
Universal links are supported when the host is allowed in `universalLinkHosts`, e.g.:
|
||||
|
||||
- `https://app.fusion.dev/?task=FN-123`
|
||||
- `https://app.fusion.dev/?project=my-project&task=FN-123&target=task`
|
||||
|
||||
#### Deep link events
|
||||
|
||||
- `deeplink:received` → parsed `DeepLinkPayload`
|
||||
- `deeplink:error` → `{ url, error }`
|
||||
|
||||
Use `handleUrl(url)` for programmatic handling (for example, push-notification tap flows that already provide a URL string).
|
||||
|
||||
### Integration flow: share -> open -> navigate
|
||||
|
||||
A common flow is:
|
||||
|
||||
1. Use `ShareManager.shareTask(...)` to share a task link like `fusion://task/FN-123`
|
||||
2. Recipient opens that link on mobile
|
||||
3. `DeepLinkManager` receives/parses the URL
|
||||
4. Your UI listens to `deeplink:received` and navigates to the matching task view
|
||||
|
||||
### Capacitor deep-link scheme registration
|
||||
|
||||
The Fusion mobile app registers the custom URL scheme in `packages/dashboard/capacitor.config.ts`:
|
||||
|
||||
- `server.iosScheme = "fusion"`
|
||||
- `server.androidScheme = "fusion"`
|
||||
|
||||
### Browser hash listener (development/testing)
|
||||
|
||||
On non-native platforms, `DeepLinkManager` listens for hash changes in the form:
|
||||
|
||||
- `#deeplink=<encoded-url>`
|
||||
|
||||
This hash-based behavior is intended for development/testing only and is not a production universal-link replacement.
|
||||
|
||||
Reference in New Issue
Block a user