@proveanything/smartlinks 1.11.2 → 1.11.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/docs/API_SUMMARY.md +1 -1
- package/dist/docs/mobile-admin-container.md +28 -14
- package/dist/index.d.ts +3 -1
- package/dist/mobile-admin/errors.d.ts +8 -7
- package/dist/mobile-admin/types.d.ts +44 -9
- package/docs/API_SUMMARY.md +1 -1
- package/docs/mobile-admin-container.md +28 -14
- package/package.json +1 -1
package/dist/docs/API_SUMMARY.md
CHANGED
|
@@ -58,7 +58,7 @@ Your container **never** detects the host directly. It receives a `host` prop fr
|
|
|
58
58
|
|
|
59
59
|
Every container mounted by the SmartLinks Mobile launcher receives a single `host` prop — `AdminMobileHostContext`. Do not reach for `window.SmartlinksScanner` or `window.Capacitor` directly; both are wrapped here.
|
|
60
60
|
|
|
61
|
-
> **SDK export** — `AdminMobileHostContext`, `AdminMobileCapability`, `AdminMobileHostId`, `AdminMobileEvent`, `
|
|
61
|
+
> **SDK export** — `AdminMobileHostContext`, `AdminMobileCapability`, `ActionableCapability`, `AdminMobileHostId`, `AdminMobileEvent`, `AdminMobileEventCallback`, `AdminMobileEventSubscriber`, `AdminMobileComponentManifest`, and `AdminMobileBundleManifest` are all exported from `@proveanything/smartlinks`. Import via `import type { AdminMobileHostContext } from '@proveanything/smartlinks'` — no local mirror needed. `ScannerEventSubscriber`, `MobileAdminComponentManifest`, and `MobileAdminBundleManifest` still export as deprecated aliases.
|
|
62
62
|
|
|
63
63
|
```typescript
|
|
64
64
|
interface AdminMobileHostContext {
|
|
@@ -82,8 +82,8 @@ interface AdminMobileHostContext {
|
|
|
82
82
|
keyboard: boolean
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
// Unified hardware event stream
|
|
86
|
-
events: { subscribe:
|
|
85
|
+
// Unified hardware event stream — callback type: AdminMobileEventCallback
|
|
86
|
+
events: { subscribe: (cb: AdminMobileEventCallback) => () => void }
|
|
87
87
|
|
|
88
88
|
// Promise-based hardware actions — reject with a structured error when unavailable
|
|
89
89
|
actions: {
|
|
@@ -97,12 +97,12 @@ interface AdminMobileHostContext {
|
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
// Host-provided UI helpers
|
|
100
|
+
// Host-provided UI helpers — all optional, see §3 note
|
|
101
101
|
ui: {
|
|
102
|
-
toast
|
|
103
|
-
haptic
|
|
104
|
-
setHeaderTitle
|
|
105
|
-
navigateBack
|
|
102
|
+
toast?: (opts: { title: string; description?: string; variant?: 'default' | 'destructive' }) => void
|
|
103
|
+
haptic?: (style?: 'light' | 'success' | 'error') => void
|
|
104
|
+
setHeaderTitle?: (title: string | null) => void
|
|
105
|
+
navigateBack?: () => void
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
// Network & device info
|
|
@@ -143,9 +143,10 @@ if (host.hardware.nfc) {
|
|
|
143
143
|
|
|
144
144
|
### `host.ui` — native helpers vs. your own components
|
|
145
145
|
|
|
146
|
-
|
|
146
|
+
All four `host.ui` methods are **optional by design**. A container may run in the Sidekick mobile shell, a standalone PWA or browser tab, Storybook, or a screenshot harness — none of those environments is guaranteed to have a native toast system, a managed header, or a back stack. Forcing every host implementer to provide them would exclude the web and desktop use-cases the rest of the contract explicitly supports. Always guard with `?.`:
|
|
147
147
|
|
|
148
|
-
`host.ui.toast()`
|
|
148
|
+
- `host.ui.toast?.({...})` / `host.ui.haptic?.('success')` — optional native feedback. Fall back to your own `<Toaster />` when absent.
|
|
149
|
+
- `host.ui.setHeaderTitle?.('Scanning…')` / `host.ui.navigateBack?.()` — host-shell integrations with no in-container equivalent. Silently no-op when the host doesn't implement them.
|
|
149
150
|
|
|
150
151
|
**Stub pattern for testing and Storybook:**
|
|
151
152
|
|
|
@@ -222,12 +223,23 @@ The custom Kotlin shell and both Capacitor shells ship the same baseline plugin
|
|
|
222
223
|
| `@capacitor/device` | `host.device.info()` |
|
|
223
224
|
| `@capacitor/share` | `host.actions.share()` |
|
|
224
225
|
| `@capacitor/clipboard` | `host.actions.clipboard.*` |
|
|
225
|
-
| `@capacitor/preferences` | `host.storage.*` *(planned)* |
|
|
226
|
+
| `@capacitor/preferences` | `host.storage.*` *(planned — see note below)* |
|
|
226
227
|
| `@capacitor/app` | host-managed (back button, deep links) |
|
|
227
228
|
| `@capacitor/status-bar` | host-managed |
|
|
228
229
|
| `@capacitor/keyboard` | host-managed |
|
|
229
230
|
| `@capacitor/toast` | wired into `host.ui.toast()` |
|
|
230
231
|
|
|
232
|
+
> **`host.storage` — planned shape.** Once released, the surface will wrap `@capacitor/preferences` directly:
|
|
233
|
+
> ```ts
|
|
234
|
+
> host.storage: {
|
|
235
|
+
> get(key: string): Promise<string | null>
|
|
236
|
+
> set(key: string, value: string): Promise<void>
|
|
237
|
+
> remove(key: string): Promise<void>
|
|
238
|
+
> keys(): Promise<string[]>
|
|
239
|
+
> }
|
|
240
|
+
> ```
|
|
241
|
+
> Until then: `localStorage` works on web hosts; use `@capacitor/preferences` directly (bundle it in) on native.
|
|
242
|
+
|
|
231
243
|
### Tier 2 — capability-gated (declare in manifest)
|
|
232
244
|
|
|
233
245
|
| Plugin | Capability flag |
|
|
@@ -385,7 +397,9 @@ try {
|
|
|
385
397
|
| `lifecycle: 'pause'` | App backgrounded | Pause readers to save battery |
|
|
386
398
|
| `lifecycle: 'resume'` | App foregrounded | Resubscribe; refresh stale data |
|
|
387
399
|
|
|
388
|
-
Use `host.events.subscribe` for all lifecycle events —
|
|
400
|
+
Use `host.events.subscribe` for all lifecycle events — all five host types (`custom-android`, `capacitor-ios`, `capacitor-android`, `pwa`, `browser`) are guaranteed to emit every `'pause'`/`'resume'`/`'offline'`/`'online'` phase. No `window.addEventListener('online')` fallback is needed.
|
|
401
|
+
|
|
402
|
+
> **Planned** — `phase: 'mount' | 'unmount'` events are on the roadmap. These will fire when the container becomes visible / is removed from the host view stack, enabling deferred reader start-up without a `useEffect` dependency.
|
|
389
403
|
|
|
390
404
|
---
|
|
391
405
|
|
|
@@ -521,8 +535,8 @@ export const MOBILE_ADMIN_MANIFEST = {
|
|
|
521
535
|
|
|
522
536
|
- **Always check `host.hardware.X` before calling `host.actions.X`** — never assume a capability is available.
|
|
523
537
|
- **Always wrap action calls in try/catch** — handle `HostPermissionDeniedError`, `HostTimeoutError`, and `HostCapabilityUnavailableError`.
|
|
524
|
-
- **
|
|
525
|
-
- **`host.ui.
|
|
538
|
+
- **All four `host.ui` methods are optional** (`toast`, `haptic`, `setHeaderTitle`, `navigateBack`) — guard every call with `?.`. See the `host.ui` section above.
|
|
539
|
+
- **`host.ui.setHeaderTitle` and `host.ui.navigateBack`** integrate with the host shell and have no in-container equivalent; call with `?.`.
|
|
526
540
|
- **Use `host.events.subscribe` for lifecycle events** — `'offline'`/`'online'`/`'pause'`/`'resume'` fire consistently on every host.
|
|
527
541
|
- **Never call `initializeApi`, never use top-level SDK imports for API calls** — `host.SL` is already configured. `SL.method()` instead of `host.SL.method()` silently uses the wrong baseURL.
|
|
528
542
|
- **Bundle Capacitor plugins in** (do not externalise) — so the component degrades gracefully on PWA/browser without crashing.
|
package/dist/index.d.ts
CHANGED
|
@@ -23,5 +23,7 @@ export type { Collection, CollectionResponse, CollectionCreateRequest, Collectio
|
|
|
23
23
|
export type { Proof, ProofResponse, ProofCreateRequest, ProofUpdateRequest, ProofClaimRequest, } from "./types/proof";
|
|
24
24
|
export type { QrShortCodeLookupResponse, } from "./types/qr";
|
|
25
25
|
export type { ReverseTagLookupParams, ReverseTagLookupResponse, } from "./types/tags";
|
|
26
|
-
export type { AdminMobileCapability, AdminMobileHostId, AdminMobileEvent,
|
|
26
|
+
export type { AdminMobileCapability, ActionableCapability, AdminMobileHostId, AdminMobileEvent, AdminMobileEventCallback, AdminMobileEventSubscriber, ScannerEventSubscriber, // @deprecated — use AdminMobileEventCallback
|
|
27
|
+
AdminMobileHostContext, AdminMobileComponentManifest, AdminMobileBundleManifest, MobileAdminComponentManifest, // @deprecated — use AdminMobileComponentManifest
|
|
28
|
+
MobileAdminBundleManifest, } from './mobile-admin/types';
|
|
27
29
|
export { HostCapabilityUnavailableError, HostPermissionDeniedError, HostTimeoutError, } from './mobile-admin/errors';
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* All three classes call `Object.setPrototypeOf(this, new.target.prototype)` so
|
|
6
6
|
* `instanceof` works correctly when transpiled to ES5.
|
|
7
7
|
*/
|
|
8
|
+
import type { ActionableCapability, AdminMobileHostId } from './types';
|
|
8
9
|
/**
|
|
9
10
|
* Thrown when a container requests a hardware action that the current host
|
|
10
11
|
* does not support (e.g. calling `requestNfcTap` on a `'pwa'` host).
|
|
@@ -20,10 +21,10 @@
|
|
|
20
21
|
*/
|
|
21
22
|
export declare class HostCapabilityUnavailableError extends Error {
|
|
22
23
|
/** The capability that was requested but is unavailable. */
|
|
23
|
-
capability:
|
|
24
|
-
/**
|
|
25
|
-
host:
|
|
26
|
-
constructor(capability:
|
|
24
|
+
capability: ActionableCapability;
|
|
25
|
+
/** The host on which the capability is unavailable. */
|
|
26
|
+
host: AdminMobileHostId;
|
|
27
|
+
constructor(capability: ActionableCapability, host: AdminMobileHostId);
|
|
27
28
|
}
|
|
28
29
|
/**
|
|
29
30
|
* Thrown when the user denies a runtime permission request (e.g. camera or
|
|
@@ -40,8 +41,8 @@ export declare class HostCapabilityUnavailableError extends Error {
|
|
|
40
41
|
*/
|
|
41
42
|
export declare class HostPermissionDeniedError extends Error {
|
|
42
43
|
/** The capability for which permission was denied. */
|
|
43
|
-
capability:
|
|
44
|
-
constructor(capability:
|
|
44
|
+
capability: ActionableCapability;
|
|
45
|
+
constructor(capability: ActionableCapability);
|
|
45
46
|
}
|
|
46
47
|
/**
|
|
47
48
|
* Thrown when a time-bounded host action (NFC tap, QR scan) exceeds its
|
|
@@ -58,7 +59,7 @@ export declare class HostPermissionDeniedError extends Error {
|
|
|
58
59
|
*/
|
|
59
60
|
export declare class HostTimeoutError extends Error {
|
|
60
61
|
/** The capability that timed out. */
|
|
61
|
-
capability: 'nfc' | 'qr'
|
|
62
|
+
capability: Extract<ActionableCapability, 'nfc' | 'qr' | 'geolocation'>;
|
|
62
63
|
/** The timeout threshold in milliseconds. */
|
|
63
64
|
timeoutMs: number;
|
|
64
65
|
constructor(capability: HostTimeoutError['capability'], timeoutMs: number);
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Hardware/software capability tokens a mobile admin host may advertise.
|
|
3
3
|
* Passed to `AdminMobileHostContext.capabilities` and to
|
|
4
|
-
* `
|
|
4
|
+
* `AdminMobileComponentManifest.capabilities`.
|
|
5
5
|
*/
|
|
6
6
|
export type AdminMobileCapability = 'nfc' | 'nfc-advanced' | 'rfid' | 'qr' | 'camera' | 'keyboard' | 'geolocation' | 'push';
|
|
7
|
+
/**
|
|
8
|
+
* Subset of `AdminMobileCapability` that can be the subject of a structured
|
|
9
|
+
* error. `'keyboard'` is excluded — it is a passive event source with no
|
|
10
|
+
* request method that can fail.
|
|
11
|
+
*/
|
|
12
|
+
export type ActionableCapability = Exclude<AdminMobileCapability, 'keyboard'>;
|
|
7
13
|
/**
|
|
8
14
|
* Canonical identifiers for mobile admin host environments.
|
|
9
15
|
* Use for display / diagnostics only — feature-detect at runtime via
|
|
@@ -31,8 +37,19 @@ export type AdminMobileEvent = {
|
|
|
31
37
|
type: 'lifecycle';
|
|
32
38
|
phase: 'pause' | 'resume' | 'offline' | 'online';
|
|
33
39
|
};
|
|
34
|
-
/** Callback
|
|
35
|
-
export type
|
|
40
|
+
/** Callback invoked for every hardware event emitted by the host. */
|
|
41
|
+
export type AdminMobileEventCallback = (event: AdminMobileEvent) => void;
|
|
42
|
+
/**
|
|
43
|
+
* The full type of `AdminMobileHostContext.events.subscribe` —
|
|
44
|
+
* takes a callback and returns a cleanup function.
|
|
45
|
+
*/
|
|
46
|
+
export type AdminMobileEventSubscriber = (cb: AdminMobileEventCallback) => () => void;
|
|
47
|
+
/**
|
|
48
|
+
* @deprecated Renamed to `AdminMobileEventCallback` in 1.12.
|
|
49
|
+
* Will be removed in a future minor release.
|
|
50
|
+
* @see AdminMobileEventCallback
|
|
51
|
+
*/
|
|
52
|
+
export type ScannerEventSubscriber = AdminMobileEventCallback;
|
|
36
53
|
/**
|
|
37
54
|
* The `host` prop passed to every mobile admin container component.
|
|
38
55
|
*
|
|
@@ -82,7 +99,7 @@ export interface AdminMobileHostContext {
|
|
|
82
99
|
* @param cb - Called for every incoming `AdminMobileEvent`.
|
|
83
100
|
* @returns Cleanup function — call inside `useEffect` return.
|
|
84
101
|
*/
|
|
85
|
-
subscribe: (cb:
|
|
102
|
+
subscribe: (cb: AdminMobileEventCallback) => () => void;
|
|
86
103
|
};
|
|
87
104
|
/** Imperative hardware actions. */
|
|
88
105
|
actions: {
|
|
@@ -137,8 +154,16 @@ export interface AdminMobileHostContext {
|
|
|
137
154
|
}) => void;
|
|
138
155
|
/** Trigger a haptic pulse. Optional — see interface note. */
|
|
139
156
|
haptic?: (style?: 'light' | 'success' | 'error') => void;
|
|
140
|
-
|
|
141
|
-
|
|
157
|
+
/**
|
|
158
|
+
* Optional — host shell may not provide a managed header
|
|
159
|
+
* (browser tabs, Storybook, desktop views). Guard with `?.`.
|
|
160
|
+
*/
|
|
161
|
+
setHeaderTitle?: (title: string | null) => void;
|
|
162
|
+
/**
|
|
163
|
+
* Optional — host shell may not have a native back stack
|
|
164
|
+
* (browser tabs, Storybook, desktop views). Guard with `?.`.
|
|
165
|
+
*/
|
|
166
|
+
navigateBack?: () => void;
|
|
142
167
|
};
|
|
143
168
|
/** Network connectivity helpers. */
|
|
144
169
|
network: {
|
|
@@ -162,7 +187,7 @@ export interface AdminMobileHostContext {
|
|
|
162
187
|
_version: number;
|
|
163
188
|
}
|
|
164
189
|
/** Manifest metadata for a single mobile admin container component. */
|
|
165
|
-
export interface
|
|
190
|
+
export interface AdminMobileComponentManifest {
|
|
166
191
|
/** Component export name (matches the export in the bundle). */
|
|
167
192
|
name: string;
|
|
168
193
|
/** Human-readable description shown in the host launcher UI. */
|
|
@@ -184,7 +209,7 @@ export interface MobileAdminComponentManifest {
|
|
|
184
209
|
* Shape of the `mobileAdmin` key inside `app.manifest.json`.
|
|
185
210
|
* Describes the bundle files and the components it exports.
|
|
186
211
|
*/
|
|
187
|
-
export interface
|
|
212
|
+
export interface AdminMobileBundleManifest {
|
|
188
213
|
files: {
|
|
189
214
|
js: {
|
|
190
215
|
/** UMD bundle path (relative to dist root). Used by the custom-android host. */
|
|
@@ -195,5 +220,15 @@ export interface MobileAdminBundleManifest {
|
|
|
195
220
|
/** CSS bundle path, or `null` if the component ships no styles. */
|
|
196
221
|
css: string | null;
|
|
197
222
|
};
|
|
198
|
-
components:
|
|
223
|
+
components: AdminMobileComponentManifest[];
|
|
199
224
|
}
|
|
225
|
+
/**
|
|
226
|
+
* @deprecated Renamed to `AdminMobileComponentManifest` in 1.12.
|
|
227
|
+
* @see AdminMobileComponentManifest
|
|
228
|
+
*/
|
|
229
|
+
export type MobileAdminComponentManifest = AdminMobileComponentManifest;
|
|
230
|
+
/**
|
|
231
|
+
* @deprecated Renamed to `AdminMobileBundleManifest` in 1.12.
|
|
232
|
+
* @see AdminMobileBundleManifest
|
|
233
|
+
*/
|
|
234
|
+
export type MobileAdminBundleManifest = AdminMobileBundleManifest;
|
package/docs/API_SUMMARY.md
CHANGED
|
@@ -58,7 +58,7 @@ Your container **never** detects the host directly. It receives a `host` prop fr
|
|
|
58
58
|
|
|
59
59
|
Every container mounted by the SmartLinks Mobile launcher receives a single `host` prop — `AdminMobileHostContext`. Do not reach for `window.SmartlinksScanner` or `window.Capacitor` directly; both are wrapped here.
|
|
60
60
|
|
|
61
|
-
> **SDK export** — `AdminMobileHostContext`, `AdminMobileCapability`, `AdminMobileHostId`, `AdminMobileEvent`, `
|
|
61
|
+
> **SDK export** — `AdminMobileHostContext`, `AdminMobileCapability`, `ActionableCapability`, `AdminMobileHostId`, `AdminMobileEvent`, `AdminMobileEventCallback`, `AdminMobileEventSubscriber`, `AdminMobileComponentManifest`, and `AdminMobileBundleManifest` are all exported from `@proveanything/smartlinks`. Import via `import type { AdminMobileHostContext } from '@proveanything/smartlinks'` — no local mirror needed. `ScannerEventSubscriber`, `MobileAdminComponentManifest`, and `MobileAdminBundleManifest` still export as deprecated aliases.
|
|
62
62
|
|
|
63
63
|
```typescript
|
|
64
64
|
interface AdminMobileHostContext {
|
|
@@ -82,8 +82,8 @@ interface AdminMobileHostContext {
|
|
|
82
82
|
keyboard: boolean
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
// Unified hardware event stream
|
|
86
|
-
events: { subscribe:
|
|
85
|
+
// Unified hardware event stream — callback type: AdminMobileEventCallback
|
|
86
|
+
events: { subscribe: (cb: AdminMobileEventCallback) => () => void }
|
|
87
87
|
|
|
88
88
|
// Promise-based hardware actions — reject with a structured error when unavailable
|
|
89
89
|
actions: {
|
|
@@ -97,12 +97,12 @@ interface AdminMobileHostContext {
|
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
// Host-provided UI helpers
|
|
100
|
+
// Host-provided UI helpers — all optional, see §3 note
|
|
101
101
|
ui: {
|
|
102
|
-
toast
|
|
103
|
-
haptic
|
|
104
|
-
setHeaderTitle
|
|
105
|
-
navigateBack
|
|
102
|
+
toast?: (opts: { title: string; description?: string; variant?: 'default' | 'destructive' }) => void
|
|
103
|
+
haptic?: (style?: 'light' | 'success' | 'error') => void
|
|
104
|
+
setHeaderTitle?: (title: string | null) => void
|
|
105
|
+
navigateBack?: () => void
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
// Network & device info
|
|
@@ -143,9 +143,10 @@ if (host.hardware.nfc) {
|
|
|
143
143
|
|
|
144
144
|
### `host.ui` — native helpers vs. your own components
|
|
145
145
|
|
|
146
|
-
|
|
146
|
+
All four `host.ui` methods are **optional by design**. A container may run in the Sidekick mobile shell, a standalone PWA or browser tab, Storybook, or a screenshot harness — none of those environments is guaranteed to have a native toast system, a managed header, or a back stack. Forcing every host implementer to provide them would exclude the web and desktop use-cases the rest of the contract explicitly supports. Always guard with `?.`:
|
|
147
147
|
|
|
148
|
-
`host.ui.toast()`
|
|
148
|
+
- `host.ui.toast?.({...})` / `host.ui.haptic?.('success')` — optional native feedback. Fall back to your own `<Toaster />` when absent.
|
|
149
|
+
- `host.ui.setHeaderTitle?.('Scanning…')` / `host.ui.navigateBack?.()` — host-shell integrations with no in-container equivalent. Silently no-op when the host doesn't implement them.
|
|
149
150
|
|
|
150
151
|
**Stub pattern for testing and Storybook:**
|
|
151
152
|
|
|
@@ -222,12 +223,23 @@ The custom Kotlin shell and both Capacitor shells ship the same baseline plugin
|
|
|
222
223
|
| `@capacitor/device` | `host.device.info()` |
|
|
223
224
|
| `@capacitor/share` | `host.actions.share()` |
|
|
224
225
|
| `@capacitor/clipboard` | `host.actions.clipboard.*` |
|
|
225
|
-
| `@capacitor/preferences` | `host.storage.*` *(planned)* |
|
|
226
|
+
| `@capacitor/preferences` | `host.storage.*` *(planned — see note below)* |
|
|
226
227
|
| `@capacitor/app` | host-managed (back button, deep links) |
|
|
227
228
|
| `@capacitor/status-bar` | host-managed |
|
|
228
229
|
| `@capacitor/keyboard` | host-managed |
|
|
229
230
|
| `@capacitor/toast` | wired into `host.ui.toast()` |
|
|
230
231
|
|
|
232
|
+
> **`host.storage` — planned shape.** Once released, the surface will wrap `@capacitor/preferences` directly:
|
|
233
|
+
> ```ts
|
|
234
|
+
> host.storage: {
|
|
235
|
+
> get(key: string): Promise<string | null>
|
|
236
|
+
> set(key: string, value: string): Promise<void>
|
|
237
|
+
> remove(key: string): Promise<void>
|
|
238
|
+
> keys(): Promise<string[]>
|
|
239
|
+
> }
|
|
240
|
+
> ```
|
|
241
|
+
> Until then: `localStorage` works on web hosts; use `@capacitor/preferences` directly (bundle it in) on native.
|
|
242
|
+
|
|
231
243
|
### Tier 2 — capability-gated (declare in manifest)
|
|
232
244
|
|
|
233
245
|
| Plugin | Capability flag |
|
|
@@ -385,7 +397,9 @@ try {
|
|
|
385
397
|
| `lifecycle: 'pause'` | App backgrounded | Pause readers to save battery |
|
|
386
398
|
| `lifecycle: 'resume'` | App foregrounded | Resubscribe; refresh stale data |
|
|
387
399
|
|
|
388
|
-
Use `host.events.subscribe` for all lifecycle events —
|
|
400
|
+
Use `host.events.subscribe` for all lifecycle events — all five host types (`custom-android`, `capacitor-ios`, `capacitor-android`, `pwa`, `browser`) are guaranteed to emit every `'pause'`/`'resume'`/`'offline'`/`'online'` phase. No `window.addEventListener('online')` fallback is needed.
|
|
401
|
+
|
|
402
|
+
> **Planned** — `phase: 'mount' | 'unmount'` events are on the roadmap. These will fire when the container becomes visible / is removed from the host view stack, enabling deferred reader start-up without a `useEffect` dependency.
|
|
389
403
|
|
|
390
404
|
---
|
|
391
405
|
|
|
@@ -521,8 +535,8 @@ export const MOBILE_ADMIN_MANIFEST = {
|
|
|
521
535
|
|
|
522
536
|
- **Always check `host.hardware.X` before calling `host.actions.X`** — never assume a capability is available.
|
|
523
537
|
- **Always wrap action calls in try/catch** — handle `HostPermissionDeniedError`, `HostTimeoutError`, and `HostCapabilityUnavailableError`.
|
|
524
|
-
- **
|
|
525
|
-
- **`host.ui.
|
|
538
|
+
- **All four `host.ui` methods are optional** (`toast`, `haptic`, `setHeaderTitle`, `navigateBack`) — guard every call with `?.`. See the `host.ui` section above.
|
|
539
|
+
- **`host.ui.setHeaderTitle` and `host.ui.navigateBack`** integrate with the host shell and have no in-container equivalent; call with `?.`.
|
|
526
540
|
- **Use `host.events.subscribe` for lifecycle events** — `'offline'`/`'online'`/`'pause'`/`'resume'` fire consistently on every host.
|
|
527
541
|
- **Never call `initializeApi`, never use top-level SDK imports for API calls** — `host.SL` is already configured. `SL.method()` instead of `host.SL.method()` silently uses the wrong baseURL.
|
|
528
542
|
- **Bundle Capacitor plugins in** (do not externalise) — so the component degrades gracefully on PWA/browser without crashing.
|