/** * Push Opt-In Registry * * The seam that lets shell chrome offer a push toggle without importing * `shell-native` — and therefore without dragging Capacitor into every * microfrontend. * * ── Why a registry and not a direct import ───────────────────────────────── * `chrome` is statically imported by most MFEs (`microfe-auth`, * `microfe-billing`, `microfe-conversations`, …). `shell-native` resolves * `@capacitor/*`, which those packages must never pull in — the rule the * shell-native docblock states as "never re-export shell-native from * shared/native". A toggle living in chrome therefore cannot import the push * implementation; it has to be handed one. * * So the app shell registers a controller during `bootNativeShell()`, and * chrome asks for whatever is registered. On a surface where nothing registers * — an MFE rendered in isolation, a Storybook story, a test — `getPushOptInController()` * returns null and the toggle renders nothing rather than throwing. * * The same indirection is what lets one component serve both platforms: the * shell registers the Capacitor implementation on native and the Web Push one * in a browser, and chrome does not need to know which it got. * * @module shared/native/push-optin */ /** Where a push opt-in currently stands, from the UI's point of view. */ export type PushOptInState = /** No push support at all — no controller, or the browser lacks the APIs. */ 'unsupported' /** Supported, never asked. Showing the control is safe; it will prompt. */ | 'default' /** Permission granted AND a live subscription/token exists. */ | 'enabled' /** Permission granted but not currently subscribed. */ | 'disabled' /** Permission refused. Cannot be re-prompted from script — see below. */ | 'denied'; /** * The capability chrome needs, implemented by the shell. * * `enable()` MUST be called from a user gesture. The permission prompt is * one-shot on iOS and sticky everywhere, so a denied prompt is unrecoverable * in-page: the user has to change it in browser or OS settings. That is why * there is a distinct `denied` state rather than an error. */ export interface PushOptInController { /** Current state. Cheap and synchronous — safe to call during render. */ getState(): PushOptInState; /** Prompt if needed, then subscribe. Resolves to the resulting state. */ enable(): Promise; /** Drop the subscription and revoke the device registration. */ disable(): Promise; /** Subscribe to state changes; returns an unsubscribe function. */ subscribe(listener: (state: PushOptInState) => void): () => void; } /** * Install the shell's implementation. Called by `bootNativeShell()`. * * Last registration wins, and passing `null` clears it — a test that installs a * fake can restore the previous state without reloading the module. */ export declare function registerPushOptInController(next: PushOptInController | null): void; /** The registered controller, or `null` when the surface has no push support. */ export declare function getPushOptInController(): PushOptInController | null; //# sourceMappingURL=push-optin.d.ts.map