@marktiderman/genesis-native 0.1.0 → 0.3.0

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.
Files changed (87) hide show
  1. package/README.md +354 -10
  2. package/dist/block-C5-noMhB.d.ts +223 -0
  3. package/dist/blocks-a1YQ1Elf.d.ts +1540 -0
  4. package/dist/chunk-65P7RU4V.js +49 -0
  5. package/dist/chunk-65P7RU4V.js.map +1 -0
  6. package/dist/chunk-6BT4PTGH.js +37 -0
  7. package/dist/chunk-6BT4PTGH.js.map +1 -0
  8. package/dist/chunk-75YP72G6.js +374 -0
  9. package/dist/chunk-75YP72G6.js.map +1 -0
  10. package/dist/chunk-NGYNYJPL.js +90 -0
  11. package/dist/chunk-NGYNYJPL.js.map +1 -0
  12. package/dist/chunk-VKTIHNAV.js +95 -0
  13. package/dist/chunk-VKTIHNAV.js.map +1 -0
  14. package/dist/{chunk-MMTPWUWI.js → chunk-VTJDIKFC.js} +9 -6
  15. package/dist/chunk-VTJDIKFC.js.map +1 -0
  16. package/dist/chunk-XE7LC7K6.js +29 -0
  17. package/dist/chunk-XE7LC7K6.js.map +1 -0
  18. package/dist/dev-warnings.d.ts +34 -0
  19. package/dist/dev-warnings.js +15 -0
  20. package/dist/dev-warnings.js.map +1 -0
  21. package/dist/devtools.d.ts +144 -0
  22. package/dist/devtools.js +390 -0
  23. package/dist/devtools.js.map +1 -0
  24. package/dist/index.d.ts +12 -368
  25. package/dist/index.js +88 -191
  26. package/dist/index.js.map +1 -1
  27. package/dist/observability.d.ts +170 -0
  28. package/dist/observability.js +123 -0
  29. package/dist/observability.js.map +1 -0
  30. package/dist/persist.d.ts +1 -1
  31. package/dist/persist.js +1 -1
  32. package/dist/push.d.ts +169 -0
  33. package/dist/push.js +996 -0
  34. package/dist/push.js.map +1 -0
  35. package/dist/{query-DhH3lLFa.d.ts → query-DUmVAfsF.d.ts} +11 -6
  36. package/dist/updates.d.ts +8 -1
  37. package/dist/updates.js +44 -69
  38. package/dist/updates.js.map +1 -1
  39. package/package.json +222 -5
  40. package/src/app.tsx +491 -0
  41. package/src/auth.tsx +176 -0
  42. package/src/blocks.tsx +144 -0
  43. package/src/boot.tsx +188 -0
  44. package/src/dev-warnings.ts +43 -0
  45. package/src/devtools/block.tsx +488 -0
  46. package/src/devtools/gestures.ts +107 -0
  47. package/src/devtools/index.ts +22 -0
  48. package/src/devtools/info.ts +45 -0
  49. package/src/devtools/slots.ts +21 -0
  50. package/src/errors.tsx +195 -0
  51. package/src/held-link.ts +90 -0
  52. package/src/hydration-gate.ts +88 -0
  53. package/src/index.ts +83 -0
  54. package/src/links.ts +140 -0
  55. package/src/nativewind.d.ts +41 -0
  56. package/src/observability/block.tsx +300 -0
  57. package/src/observability/events.ts +89 -0
  58. package/src/observability/index.ts +44 -0
  59. package/src/observability/scrub.ts +166 -0
  60. package/src/observability/sentry.ts +222 -0
  61. package/src/observability/sink.ts +147 -0
  62. package/src/persist.ts +83 -0
  63. package/src/push/backend.ts +129 -0
  64. package/src/push/block.tsx +545 -0
  65. package/src/push/index.ts +102 -0
  66. package/src/push/modules.ts +111 -0
  67. package/src/push/permission.ts +191 -0
  68. package/src/push/preferences.ts +136 -0
  69. package/src/push/quiet-hours.ts +71 -0
  70. package/src/push/registration.ts +189 -0
  71. package/src/push/routing.ts +27 -0
  72. package/src/push/screens.tsx +46 -0
  73. package/src/push/settings.tsx +378 -0
  74. package/src/query.ts +100 -0
  75. package/src/updates/block.tsx +442 -0
  76. package/src/updates/channels.ts +131 -0
  77. package/src/updates/checker.ts +190 -0
  78. package/src/updates/index.ts +87 -0
  79. package/src/updates/modules.ts +64 -0
  80. package/src/updates/policy.ts +314 -0
  81. package/src/updates/screens.tsx +159 -0
  82. package/src/updates/signature.ts +80 -0
  83. package/src/updates/store.ts +33 -0
  84. package/src/updates/version.ts +39 -0
  85. package/src/updates/whats-new.ts +122 -0
  86. package/dist/block-Dh5ny06W.d.ts +0 -535
  87. package/dist/chunk-MMTPWUWI.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/push/modules.ts","../src/push/permission.ts","../src/push/backend.ts","../src/push/quiet-hours.ts","../src/push/preferences.ts","../src/push/registration.ts","../src/push/routing.ts","../src/push/screens.tsx","../src/push/block.tsx","../src/push/settings.tsx"],"names":["clock","jsx","jsxs","View","hold","useSyncExternalStore","useEffect"],"mappings":"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","file":"push.js","sourcesContent":["/**\n * What the push block reads from `expo-notifications` (SDK 58) and the app's\n * backend, as the shapes it needs. Pass the real module\n * (`import * as Notifications from \"expo-notifications\"`); tests pass fakes.\n * Every call here was checked against expo-notifications 58.1's own type\n * declarations.\n */\n\n/** `{ remove() }`, as every expo-notifications listener returns. */\nexport interface SubscriptionLike {\n remove(): void;\n}\n\n/** `NotificationPermissionsStatus`: Expo's `PermissionResponse` plus the iOS detail. */\nexport interface PermissionStatusLike {\n status: \"granted\" | \"denied\" | \"undetermined\" | string;\n granted: boolean;\n canAskAgain: boolean;\n /** `IosAuthorizationStatus`: 0 not determined, 1 denied, 2 authorized, 3 provisional, 4 ephemeral. */\n ios?: { status: number } | null;\n}\n\n/** `NotificationPermissionsRequest`: iOS options; Android asks for posting notifications. */\nexport interface PermissionRequestLike {\n ios?: { allowAlert?: boolean; allowBadge?: boolean; allowSound?: boolean; allowProvisional?: boolean };\n}\n\n/** The parts of a received notification the block reads. */\nexport interface NotificationLike {\n request: {\n identifier: string;\n content: { data?: Record<string, unknown> | null; title?: string | null };\n };\n}\n\n/** A tap (or an action) on a notification. */\nexport interface NotificationResponseLike {\n notification: NotificationLike;\n actionIdentifier: string;\n}\n\n/** `NotificationBehavior` without the deprecated `shouldShowAlert`. */\nexport interface NotificationBehaviorLike {\n shouldShowBanner: boolean;\n shouldShowList: boolean;\n shouldPlaySound: boolean;\n shouldSetBadge: boolean;\n}\n\n/** `NotificationChannelInput`, the fields the block sets. Importance and visibility are Expo's enum numbers. */\nexport interface ChannelInputLike {\n name: string;\n importance: number;\n description?: string | null;\n /** `AndroidNotificationVisibility`: 1 public, 2 private (content hidden on a secure lock screen), 3 secret. */\n lockscreenVisibility?: number;\n showBadge?: boolean;\n}\n\n/** `expo-notifications` (SDK 58). */\nexport interface NotificationsModuleLike {\n getPermissionsAsync(): Promise<PermissionStatusLike>;\n requestPermissionsAsync(request?: PermissionRequestLike): Promise<PermissionStatusLike>;\n /** Pass the EAS project id: without one there is no Expo push token. */\n getExpoPushTokenAsync(options: { projectId: string }): Promise<{ data: string }>;\n /** Fires when the OS hands the app a new device token; the Expo token is fetched again then. */\n addPushTokenListener(listener: (token: unknown) => void): SubscriptionLike;\n /** Android only (a no-op elsewhere). Must run before the permission prompt and the token on Android 13+. */\n setNotificationChannelAsync(channelId: string, channel: ChannelInputLike): Promise<unknown>;\n setNotificationHandler(handler: { handleNotification: (notification: NotificationLike) => Promise<NotificationBehaviorLike> } | null): void;\n addNotificationResponseReceivedListener(listener: (response: NotificationResponseLike) => void): SubscriptionLike;\n /** The tap that launched the app (synchronous since SDK 53). */\n getLastNotificationResponse(): NotificationResponseLike | null;\n clearLastNotificationResponse(): void;\n setBadgeCountAsync(count: number): Promise<boolean>;\n getBadgeCountAsync(): Promise<number>;\n /** `\"expo.modules.notifications.actions.DEFAULT\"`: the person tapped the notification itself. */\n DEFAULT_ACTION_IDENTIFIER: string;\n}\n\n/** AsyncStorage, MMKV's async adapter, or a stand-in. */\nexport interface PushStorageLike {\n getItem(key: string): Promise<string | null>;\n setItem(key: string, value: string): Promise<void>;\n removeItem?(key: string): Promise<void>;\n}\n\n/** React Native's `AppState`. */\nexport interface PushAppStateLike {\n addEventListener(type: \"change\", listener: (state: string) => void): { remove(): void };\n}\n\n/** Where a reported error came from. */\nexport type PushErrorSource = \"permission\" | \"register\" | \"forget\" | \"preferences\" | \"badge\" | \"channels\" | \"routing\" | \"storage\" | \"setup\";\n\nexport type PushOnError = (error: Error, source: PushErrorSource) => void;\n\nexport function toError(value: unknown): Error {\n if (value instanceof Error) return value;\n const message = (value as { message?: unknown } | null)?.message;\n return new Error(typeof message === \"string\" ? message : typeof value === \"string\" ? value : \"Unknown error\");\n}\n\n/** Calls the reporter, never letting a failing one break the block. */\nexport function report(onError: PushOnError | undefined, error: unknown, source: PushErrorSource) {\n try {\n onError?.(toError(error), source);\n } catch {\n // ignore a failing reporter\n }\n}\n","/**\n * Notification permission, and the soft pre-prompt that comes before the\n * system's.\n *\n * The system prompt can be shown once: a person who says no there has to find\n * the app in Settings to change it. So the block never asks at launch. The\n * app calls `prompt.offer()` at the moment push is worth it (they sent their\n * first message, set a reminder) and the block shows its own sheet first,\n * saying why; only \"Turn on\" in that sheet (a tap) brings up the system\n * prompt. \"Not now\" waits `cooldownMs` before the sheet can show again, and\n * after `maxDeclines` it never offers again (Settings still can).\n */\nimport { createStore, type Store } from \"../updates/store\";\nimport { report, type NotificationsModuleLike, type PermissionRequestLike, type PermissionStatusLike, type PushOnError, type PushStorageLike } from \"./modules\";\n\n/**\n * `unknown` before the first read; `undetermined` the system can still ask;\n * `granted`; `provisional` (iOS delivers quietly to Notification Center);\n * `denied` only Settings can change; `unavailable` no notifications module.\n */\nexport type PushPermissionStatus = \"unknown\" | \"undetermined\" | \"granted\" | \"provisional\" | \"denied\" | \"unavailable\";\n\nexport interface PermissionState {\n status: PushPermissionStatus;\n /** The system prompt is up. */\n requesting: boolean;\n}\n\nexport interface PermissionStore extends Store<PermissionState> {\n /** Read the status without asking (no prompt). */\n refresh(): Promise<PushPermissionStatus>;\n /** Show the system prompt (only after a tap); resolves to the new status. */\n request(): Promise<PushPermissionStatus>;\n}\n\nconst IOS_PROVISIONAL = 3;\nconst IOS_EPHEMERAL = 4;\n\n/** Expo's answer as one status. Android \"denied but can ask again\" is still askable. */\nexport function statusOf(response: PermissionStatusLike): PushPermissionStatus {\n const ios = response.ios?.status;\n if (ios === IOS_PROVISIONAL) return \"provisional\";\n if (response.granted || response.status === \"granted\" || ios === IOS_EPHEMERAL) return \"granted\";\n if (response.status === \"undetermined\" || response.canAskAgain) return \"undetermined\";\n return \"denied\";\n}\n\nexport const canPush = (status: PushPermissionStatus) => status === \"granted\" || status === \"provisional\";\n\nexport function createPermissionStore(options: {\n notifications?: NotificationsModuleLike;\n request?: PermissionRequestLike;\n /** Runs before the system prompt (Android 13 shows it only once a channel exists). */\n beforeRequest?: () => Promise<void>;\n onError?: PushOnError;\n}): PermissionStore {\n const { notifications, onError } = options;\n const store = createStore<PermissionState>({ status: notifications ? \"unknown\" : \"unavailable\", requesting: false });\n return {\n ...store,\n async refresh() {\n if (!notifications) return \"unavailable\";\n try {\n const status = statusOf(await notifications.getPermissionsAsync());\n store.setState({ status });\n return status;\n } catch (error) {\n report(onError, error, \"permission\");\n return store.getState().status;\n }\n },\n async request() {\n if (!notifications) return \"unavailable\";\n if (store.getState().requesting) return store.getState().status;\n store.setState({ requesting: true });\n try {\n await options.beforeRequest?.().catch((error) => report(onError, error, \"channels\"));\n const status = statusOf(await notifications.requestPermissionsAsync(options.request ?? DEFAULT_REQUEST));\n store.setState({ status });\n return status;\n } catch (error) {\n report(onError, error, \"permission\");\n return store.getState().status;\n } finally {\n store.setState({ requesting: false });\n }\n },\n };\n}\n\nconst DEFAULT_REQUEST: PermissionRequestLike = { ios: { allowAlert: true, allowBadge: true, allowSound: true } };\n\nexport interface PromptOptions {\n /** After \"Not now\", how long before the sheet may show again. Default 3 days. */\n cooldownMs?: number;\n /** After this many \"Not now\"s it never offers again. Default 3. */\n maxDeclines?: number;\n /** `offer()` is ignored this long after the block starts, so no screen can ask at launch. Default 10 s. */\n launchGraceMs?: number;\n}\n\nexport interface PromptState {\n visible: boolean;\n /** What `offer(reason)` said push is for here, for the sheet's copy. */\n reason: string | null;\n}\n\nexport interface PromptStore extends Store<PromptState> {\n /**\n * Show the soft prompt if it is a good moment: signed in, the system can\n * still ask, not at launch, not too soon after \"Not now\". Resolves to\n * whether it showed.\n */\n offer(reason?: string): Promise<boolean>;\n /** \"Turn on\": hides the sheet and shows the system prompt. */\n accept(): Promise<PushPermissionStatus>;\n /** \"Not now\": hides the sheet and remembers it. */\n decline(): Promise<void>;\n hide(): void;\n}\n\ninterface Declines {\n count: number;\n at: number;\n}\n\nexport function createPromptStore(options: PromptOptions & {\n permission: PermissionStore;\n storage?: PushStorageLike;\n storageKey: string;\n signedIn: () => boolean;\n /** When the block started (ms), or null before. */\n startedAt: () => number | null;\n now: () => number;\n onError?: PushOnError;\n}): PromptStore {\n const { permission, storage, storageKey, now, onError } = options;\n const cooldownMs = options.cooldownMs ?? 3 * 24 * 60 * 60_000;\n const maxDeclines = options.maxDeclines ?? 3;\n const launchGraceMs = options.launchGraceMs ?? 10_000;\n const store = createStore<PromptState>({ visible: false, reason: null });\n let memory: Declines = { count: 0, at: 0 };\n\n const readDeclines = async (): Promise<Declines> => {\n if (!storage) return memory;\n try {\n const raw = await storage.getItem(storageKey);\n const parsed = raw ? (JSON.parse(raw) as Partial<Declines>) : null;\n return { count: Number(parsed?.count) || 0, at: Number(parsed?.at) || 0 };\n } catch (error) {\n report(onError, error, \"storage\");\n return memory;\n }\n };\n\n return {\n ...store,\n async offer(reason) {\n if (store.getState().visible) return true;\n const started = options.startedAt();\n if (started === null || now() - started < launchGraceMs) return false;\n if (!options.signedIn()) return false;\n const status = permission.getState().status === \"unknown\" ? await permission.refresh() : permission.getState().status;\n if (status !== \"undetermined\") return false;\n const declines = await readDeclines();\n if (declines.count >= maxDeclines || (declines.count > 0 && now() - declines.at < cooldownMs)) return false;\n if (!options.signedIn()) return false;\n store.setState({ visible: true, reason: reason ?? null });\n return true;\n },\n async accept() {\n store.setState({ visible: false });\n return permission.request();\n },\n async decline() {\n // Only from the sheet: a dismissal that fires as it closes after \"Turn on\" isn't a \"Not now\".\n if (!store.getState().visible) return;\n store.setState({ visible: false });\n const declines = await readDeclines();\n memory = { count: declines.count + 1, at: now() };\n try {\n await storage?.setItem(storageKey, JSON.stringify(memory));\n } catch (error) {\n report(onError, error, \"storage\");\n }\n },\n hide() {\n store.setState({ visible: false, reason: null });\n },\n };\n}\n","/**\n * Where the push block keeps devices and preferences: migration 0005 of\n * @marktiderman/genesis-supabase, through the app's Supabase client and row\n * level security. `supabasePushBackend(supabase)` is the one to use; tests\n * (and an app with its own server) pass their own `PushBackend`.\n */\n\n/** A person's notification preferences, as the screens edit them. */\nexport interface NotificationPreferences {\n /** Category id → on or off. A category not listed has its default (`NotificationCategory.defaultOn`). */\n categories: Record<string, boolean>;\n quietHours: QuietHours;\n /** Hide what a push says on the lock screen: the sender sends neutral text instead. */\n hidePreviews: boolean;\n}\n\nexport interface QuietHours {\n enabled: boolean;\n /** Local time, `\"HH:MM\"` (24-hour). */\n start: string;\n /** Local time, `\"HH:MM\"`; before `start` means the quiet runs past midnight. */\n end: string;\n /** IANA time zone (`\"Europe/London\"`) the times are read in; required while enabled. */\n timeZone: string | null;\n}\n\nexport const DEFAULT_PREFERENCES: NotificationPreferences = {\n categories: {},\n quietHours: { enabled: false, start: \"22:00\", end: \"07:00\", timeZone: null },\n hidePreviews: false,\n};\n\nexport interface PushBackend {\n /** Keep this device's token against the signed-in person. */\n register(token: string, platform: string, appVersion: string | null): Promise<void>;\n /** Forget this device's token; works signed out (holding the token is the proof). */\n forget(token: string): Promise<void>;\n /** The signed-in person's preferences, or `null` before they have saved any. */\n loadPreferences(userId: string): Promise<NotificationPreferences | null>;\n savePreferences(userId: string, preferences: NotificationPreferences): Promise<void>;\n}\n\ntype Result = { data: unknown; error: { message?: string; code?: string | null } | null };\n\n/** The parts of a Supabase client the backend uses; a `SupabaseClient` fits, typed by your Database or not. */\nexport interface PushSupabaseLike {\n // Loose on purpose (as deleteMyAccount's): a client typed by an app's Database narrows `rpc`'s\n // and `from`'s arguments to its own functions and tables, which these names may not be in yet.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n rpc: (fn: any, ...rest: any[]) => PromiseLike<Result>;\n from(table: string): unknown;\n}\n\ninterface PreferencesQuery {\n select(columns: string): { eq(column: string, value: string): { maybeSingle(): PromiseLike<Result> } };\n upsert(row: Record<string, unknown>, options: { onConflict: string }): { select(columns: string): PromiseLike<Result> };\n}\n\n/** A database refusal, with its SQLSTATE; the message is the database's own, never a token. */\nexport class PushBackendError extends Error {\n constructor(\n readonly operation: string,\n readonly code: string | null,\n ) {\n super(`${operation} failed${code ? ` (${code})` : \"\"}`);\n this.name = \"PushBackendError\";\n }\n}\n\nconst COLUMNS = \"categories, quiet_hours_enabled, quiet_hours_start, quiet_hours_end, time_zone, hide_previews\";\n\n/** Postgres answers `time` as `\"22:00:00\"`. */\nfunction clock(value: unknown, fallback: string): string {\n const match = typeof value === \"string\" ? /^(\\d{2}):(\\d{2})/.exec(value) : null;\n return match ? `${match[1]}:${match[2]}` : fallback;\n}\n\nfunction fromRow(row: Record<string, unknown>): NotificationPreferences {\n const categories: Record<string, boolean> = {};\n const raw = row.categories;\n if (raw && typeof raw === \"object\" && !Array.isArray(raw)) {\n for (const [id, on] of Object.entries(raw as Record<string, unknown>)) if (typeof on === \"boolean\") categories[id] = on;\n }\n return {\n categories,\n quietHours: {\n enabled: row.quiet_hours_enabled === true,\n start: clock(row.quiet_hours_start, DEFAULT_PREFERENCES.quietHours.start),\n end: clock(row.quiet_hours_end, DEFAULT_PREFERENCES.quietHours.end),\n timeZone: typeof row.time_zone === \"string\" ? row.time_zone : null,\n },\n hidePreviews: row.hide_previews === true,\n };\n}\n\n/** Migration 0005's functions and tables, under the signed-in person's row level security. */\nexport function supabasePushBackend(client: PushSupabaseLike): PushBackend {\n const must = (operation: string, result: Result) => {\n if (result.error) throw new PushBackendError(operation, result.error.code ?? null);\n return result.data;\n };\n return {\n async register(token, platform, appVersion) {\n must(\"genesis_push_register\", await client.rpc(\"genesis_push_register\", { p_token: token, p_platform: platform, p_app_version: appVersion }));\n },\n async forget(token) {\n must(\"genesis_push_forget\", await client.rpc(\"genesis_push_forget\", { p_token: token }));\n },\n async loadPreferences(userId) {\n // Row level security already limits it to the caller; the filter says so twice.\n const data = must(\"notification_preferences\", await (client.from(\"notification_preferences\") as PreferencesQuery).select(COLUMNS).eq(\"user_id\", userId).maybeSingle());\n return data && typeof data === \"object\" ? fromRow(data as Record<string, unknown>) : null;\n },\n async savePreferences(userId, p) {\n const row = {\n user_id: userId,\n categories: p.categories,\n quiet_hours_enabled: p.quietHours.enabled,\n quiet_hours_start: p.quietHours.start,\n quiet_hours_end: p.quietHours.end,\n time_zone: p.quietHours.timeZone,\n hide_previews: p.hidePreviews,\n };\n const data = must(\"notification_preferences\", await (client.from(\"notification_preferences\") as PreferencesQuery).upsert(row, { onConflict: \"user_id\" }).select(\"user_id\"));\n // Row level security turns a write it refuses into zero rows, not an error.\n if (!Array.isArray(data) || data.length !== 1) throw new PushBackendError(\"notification_preferences\", \"no_rows\");\n },\n };\n}\n","/**\n * Quiet hours on the phone: only for showing them (\"on now, until 07:00\").\n * Whether a push waits is decided on the server (migration 0005's\n * genesis_push_status), in the person's saved time zone, so a phone with a\n * wrong clock or in another zone can't change it.\n */\nimport type { QuietHours } from \"./backend\";\n\nconst CLOCK = /^([01]\\d|2[0-3]):([0-5]\\d)$/;\n\n/** Minutes since midnight for `\"HH:MM\"`, or null. */\nexport function parseClock(value: string): number | null {\n const match = CLOCK.exec(value);\n return match ? Number(match[1]) * 60 + Number(match[2]) : null;\n}\n\n/** `\"HH:MM\"` for minutes since midnight (wrapping a day). */\nexport function formatClock(minutes: number): string {\n const m = ((Math.round(minutes) % 1440) + 1440) % 1440;\n return `${String(Math.floor(m / 60)).padStart(2, \"0\")}:${String(m % 60).padStart(2, \"0\")}`;\n}\n\n/** `\"HH:MM\"` for a `Date`'s local time (what a time picker hands back). */\nexport function clockOf(date: Date): string {\n return formatClock(date.getHours() * 60 + date.getMinutes());\n}\n\n/** Today at `\"HH:MM\"` local, for a time picker's value. */\nexport function dateAt(clock: string, today = new Date()): Date {\n const minutes = parseClock(clock) ?? 0;\n const d = new Date(today);\n d.setHours(Math.floor(minutes / 60), minutes % 60, 0, 0);\n return d;\n}\n\n/** This phone's IANA time zone, or null when the JavaScript engine can't say. */\nexport function deviceTimeZone(): string | null {\n try {\n const zone = Intl.DateTimeFormat().resolvedOptions().timeZone;\n return typeof zone === \"string\" && zone.length > 0 ? zone : null;\n } catch {\n return null;\n }\n}\n\n/** Minutes since midnight at `at` in `timeZone`, or null for a zone the engine doesn't know. */\nexport function minutesIn(timeZone: string, at: Date): number | null {\n try {\n const parts = new Intl.DateTimeFormat(\"en-US\", { timeZone, hour: \"2-digit\", minute: \"2-digit\", hourCycle: \"h23\" }).formatToParts(at);\n const hour = Number(parts.find((p) => p.type === \"hour\")?.value);\n const minute = Number(parts.find((p) => p.type === \"minute\")?.value);\n return Number.isFinite(hour) && Number.isFinite(minute) ? (hour % 24) * 60 + minute : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Are quiet hours on at `at`? The same rule as the server: the start is\n * inclusive, the end exclusive, a start after the end runs past midnight, a\n * start equal to the end is no quiet hours, and an unknown zone is never quiet.\n */\nexport function isQuietAt(quiet: QuietHours, at: Date = new Date()): boolean {\n if (!quiet.enabled || !quiet.timeZone) return false;\n const start = parseClock(quiet.start);\n const end = parseClock(quiet.end);\n if (start === null || end === null || start === end) return false;\n const now = minutesIn(quiet.timeZone, at);\n if (now === null) return false;\n return start < end ? now >= start && now < end : now >= start || now < end;\n}\n","/**\n * The signed-in person's notification preferences: categories, quiet hours\n * and privacy previews. Loaded when they sign in, saved on every change\n * (shown at once, put back if the save fails), cleared when they sign out.\n * The server reads the saved row; nothing here decides what is delivered.\n */\nimport { createStore, type Store } from \"../updates/store\";\nimport { DEFAULT_PREFERENCES, type NotificationPreferences, type PushBackend, type QuietHours } from \"./backend\";\nimport { report, type PushOnError } from \"./modules\";\nimport { parseClock } from \"./quiet-hours\";\n\n/** Android importance for a category's channel (Expo's `AndroidImportance`). */\nexport type ChannelImportance = \"min\" | \"low\" | \"default\" | \"high\" | \"max\";\n\n/** One kind of notification the app sends, which a person can turn off. */\nexport interface NotificationCategory {\n /** Lower case letters, digits, \".\", \"_\" or \"-\" (`messages`). Also its Android channel id, and the sender's `category`. */\n id: string;\n title: string;\n description?: string;\n /** On for someone who never chose. Default true; pass the same `defaultOn` to the sender. */\n defaultOn?: boolean;\n /** Android channel importance. Default `\"default\"`. */\n importance?: ChannelImportance;\n}\n\nexport type PreferencesStatus = \"idle\" | \"loading\" | \"ready\" | \"error\";\n\nexport interface PreferencesState {\n status: PreferencesStatus;\n preferences: NotificationPreferences;\n saving: boolean;\n /** The last load or save that failed (the change was put back). */\n error: Error | null;\n}\n\nexport interface PreferencesStore extends Store<PreferencesState> {\n load(userId: string): Promise<void>;\n /** Apply a change now and save it; on failure it is put back and `error` set. */\n update(change: (current: NotificationPreferences) => NotificationPreferences): Promise<boolean>;\n reset(): void;\n isOn(categoryId: string): boolean;\n}\n\nexport const CATEGORY_ID = /^[a-z0-9][a-z0-9._-]{0,63}$/;\n\n/** Checks a change before it is shown or saved, so the server never has to refuse it. */\nexport function validPreferences(p: NotificationPreferences): boolean {\n const q: QuietHours = p.quietHours;\n if (parseClock(q.start) === null || parseClock(q.end) === null) return false;\n if (q.enabled && !q.timeZone) return false;\n return Object.keys(p.categories).every((id) => CATEGORY_ID.test(id));\n}\n\nexport function createPreferencesStore(options: {\n backend: PushBackend;\n categories: readonly NotificationCategory[];\n onError?: PushOnError;\n}): PreferencesStore {\n const { backend, categories, onError } = options;\n for (const category of categories) {\n if (!CATEGORY_ID.test(category.id)) throw new Error(`createPush: category id \"${category.id}\" must be lower case letters, digits, \".\", \"_\" or \"-\"`);\n }\n const store = createStore<PreferencesState>({ status: \"idle\", preferences: DEFAULT_PREFERENCES, saving: false, error: null });\n let userId: string | null = null;\n // Each load or save belongs to one sign-in; an answer for an earlier one is dropped.\n let generation = 0;\n let saves: Promise<unknown> = Promise.resolve();\n let confirmed: NotificationPreferences = DEFAULT_PREFERENCES;\n let pending = 0;\n\n return {\n ...store,\n async load(id) {\n const mine = ++generation;\n userId = id;\n pending = 0;\n store.setState({ status: \"loading\", saving: false, error: null });\n try {\n const loaded = (await backend.loadPreferences(id)) ?? DEFAULT_PREFERENCES;\n if (mine !== generation) return;\n confirmed = loaded;\n store.setState({ status: \"ready\", preferences: loaded });\n } catch (error) {\n if (mine !== generation) return;\n report(onError, error, \"preferences\");\n store.setState({ status: \"error\", error: error instanceof Error ? error : new Error(\"Couldn't load notification settings\") });\n }\n },\n update(change) {\n const id = userId;\n const mine = generation;\n // Only on top of the server's copy: a change made while it loads (or after a failed load)\n // would save the defaults over it, turning a hidden preview back on.\n if (!id || store.getState().status !== \"ready\") return Promise.resolve(false);\n const next = change(store.getState().preferences);\n if (!validPreferences(next)) return Promise.resolve(false);\n pending++;\n store.setState({ preferences: next, saving: true, error: null });\n // Saves go one at a time, in order; each carries every change before it.\n const save = saves.then(async () => {\n if (mine !== generation) return false;\n let ok = false;\n try {\n await backend.savePreferences(id, next);\n ok = true;\n if (mine === generation) confirmed = next;\n } catch (error) {\n if (mine === generation) {\n report(onError, error, \"preferences\");\n store.setState({ error: error instanceof Error ? error : new Error(\"Couldn't save notification settings\") });\n }\n }\n if (mine !== generation) return false;\n pending--;\n // The last save settles what shows: the server's copy (a failed change is put back).\n if (pending === 0) store.setState({ preferences: confirmed, saving: false });\n return ok;\n });\n saves = save.catch(() => false);\n return save;\n },\n reset() {\n generation++;\n userId = null;\n pending = 0;\n confirmed = DEFAULT_PREFERENCES;\n store.setState({ status: \"idle\", preferences: DEFAULT_PREFERENCES, saving: false, error: null });\n },\n isOn(categoryId) {\n const chosen = store.getState().preferences.categories[categoryId];\n if (typeof chosen === \"boolean\") return chosen;\n return categories.find((c) => c.id === categoryId)?.defaultOn ?? true;\n },\n };\n}\n","/**\n * This device's Expo push token, kept against whoever is signed in.\n *\n * sync(userId) permission granted → (Android) channels → token → backend.register,\n * again when the token changes and at most hourly otherwise (last seen)\n * forget() backend.forget(token) on sign-out, an account switch or deletion;\n * a forget that fails offline is kept and retried at the next start\n *\n * The token is remembered on the phone (storage) with the user it was\n * registered for, so it can be forgotten after the session has ended. Every\n * step runs in order on one queue, so a sign-out never races a registration.\n */\nimport { createStore, type Store } from \"../updates/store\";\nimport type { PushBackend } from \"./backend\";\nimport { report, type NotificationsModuleLike, type PushOnError, type PushStorageLike } from \"./modules\";\n\nexport type RegistrationStatus = \"idle\" | \"registering\" | \"registered\" | \"unavailable\" | \"error\";\n\nexport interface RegistrationState {\n status: RegistrationStatus;\n /**\n * Why it isn't registered: `no_project_id` (the build has no EAS project id, so there is no\n * Expo push token), `no_token` (the OS gave none: a simulator without push, or no network),\n * `backend` (the server refused or couldn't be reached).\n */\n problem: \"no_project_id\" | \"no_token\" | \"backend\" | null;\n}\n\nexport interface Registration extends Store<RegistrationState> {\n sync(userId: string, options?: { force?: boolean }): Promise<void>;\n forget(): Promise<void>;\n /** Retry forgets that failed earlier (offline sign-out). */\n flush(): Promise<void>;\n /** This device's token, once known (the person's own; never shown in logs). */\n token(): string | null;\n}\n\ninterface Saved {\n token: string;\n userId: string;\n at: number;\n}\n\n/** Registered again at most this often while nothing changed (last seen, and a token another login took comes back). */\nconst REFRESH_MS = 60 * 60_000;\n\nexport function createRegistration(options: {\n notifications?: NotificationsModuleLike;\n backend: PushBackend;\n projectId?: string | null;\n platform: string;\n appVersion?: string | null;\n storage?: PushStorageLike;\n storageKeyPrefix: string;\n /** Creates the Android channels; runs before the token is asked for. */\n ensureChannels: () => Promise<void>;\n /** Is this user still the one signed in? A sync for someone who has signed out is dropped. */\n isCurrent: (userId: string) => boolean;\n now: () => number;\n onError?: PushOnError;\n}): Registration {\n const { notifications, backend, storage, storageKeyPrefix, onError, now } = options;\n const savedKey = `${storageKeyPrefix}:device`;\n const pendingKey = `${storageKeyPrefix}:forget`;\n const store = createStore<RegistrationState>({ status: \"idle\", problem: null });\n let current: string | null = null;\n let queue: Promise<unknown> = Promise.resolve();\n let warnedNoProject = false;\n\n const run = <T>(step: () => Promise<T>): Promise<T> => {\n const next = queue.then(step, step);\n queue = next.catch(() => {});\n return next;\n };\n\n const read = async <T>(key: string, fallback: T): Promise<T> => {\n if (!storage) return fallback;\n try {\n const raw = await storage.getItem(key);\n return raw ? (JSON.parse(raw) as T) : fallback;\n } catch (error) {\n report(onError, error, \"storage\");\n return fallback;\n }\n };\n const write = async (key: string, value: unknown) => {\n try {\n if (value === null) await storage?.removeItem?.(key);\n else await storage?.setItem(key, JSON.stringify(value));\n } catch (error) {\n report(onError, error, \"storage\");\n }\n };\n\n const forgetToken = async (token: string): Promise<boolean> => {\n try {\n await backend.forget(token);\n return true;\n } catch (error) {\n report(onError, error, \"forget\");\n return false;\n }\n };\n\n const queuePending = async (token: string) => {\n const pending = await read<string[]>(pendingKey, []);\n if (!pending.includes(token)) await write(pendingKey, [...pending, token].slice(-10));\n };\n\n return {\n ...store,\n token: () => current,\n sync(userId, { force = false } = {}) {\n return run(async () => {\n if (!notifications || !options.isCurrent(userId)) return;\n if (!options.projectId) {\n store.setState({ status: \"unavailable\", problem: \"no_project_id\" });\n if (!warnedNoProject) {\n warnedNoProject = true;\n // Loud once: without an EAS project id there is no Expo push token, so no push reaches this build.\n report(onError, new Error(\"push: no EAS project id (projectId), so this build gets no push token. Run `eas init` and pass Constants.expoConfig.extra.eas.projectId.\"), \"setup\");\n }\n return;\n }\n store.setState({ status: \"registering\", problem: null });\n await options.ensureChannels().catch((error) => report(onError, error, \"channels\"));\n let token: string;\n try {\n token = (await notifications.getExpoPushTokenAsync({ projectId: options.projectId })).data;\n } catch (error) {\n report(onError, error, \"register\");\n store.setState({ status: \"error\", problem: \"no_token\" });\n return;\n }\n if (typeof token !== \"string\" || token.length === 0) {\n store.setState({ status: \"error\", problem: \"no_token\" });\n return;\n }\n current = token;\n const saved = await read<Saved | null>(savedKey, null);\n // A different token kept for someone else on this phone: forget it. (The same token the server moves itself.)\n if (saved && saved.userId !== userId && saved.token !== token && !(await forgetToken(saved.token))) await queuePending(saved.token);\n if (!force && saved && saved.token === token && saved.userId === userId && now() - saved.at < REFRESH_MS) {\n store.setState({ status: \"registered\", problem: null });\n return;\n }\n if (!options.isCurrent(userId)) return;\n try {\n await backend.register(token, options.platform === \"ios\" ? \"ios\" : \"android\", options.appVersion ?? null);\n } catch (error) {\n report(onError, error, \"register\");\n store.setState({ status: \"error\", problem: \"backend\" });\n return;\n }\n // An older token this phone had (the OS rotated it) goes; the new one stays.\n if (saved && saved.token !== token && saved.userId === userId && !(await forgetToken(saved.token))) await queuePending(saved.token);\n await write(savedKey, { token, userId, at: now() } satisfies Saved);\n // A forget of this same token still waiting from an offline sign-out would undo this registration.\n const pending = await read<string[]>(pendingKey, []);\n if (pending.includes(token)) await write(pendingKey, pending.filter((t) => t !== token).length ? pending.filter((t) => t !== token) : null);\n store.setState({ status: \"registered\", problem: null });\n });\n },\n forget() {\n return run(async () => {\n const saved = await read<Saved | null>(savedKey, null);\n const token = saved?.token ?? current;\n await write(savedKey, null);\n store.setState({ status: \"idle\", problem: null });\n if (!token) return;\n if (!(await forgetToken(token))) await queuePending(token);\n });\n },\n flush() {\n return run(async () => {\n const pending = await read<string[]>(pendingKey, []);\n if (pending.length === 0) return;\n const left: string[] = [];\n const registered = (await read<Saved | null>(savedKey, null))?.token;\n for (const token of pending) {\n // Registered again since (signed back in): keep it.\n if (token === registered) continue;\n if (!(await forgetToken(token))) left.push(token);\n }\n await write(pendingKey, left.length ? left : null);\n });\n },\n };\n}\n","/**\n * Where a tapped notification goes. The sender puts an app path in\n * `data.url` (`/messages/42`); it goes through the same `normalizeLink` as\n * every deep link, so a path the app doesn't know opens `/` and an ignored\n * one goes nowhere. Without link options, only a plain app path is followed.\n */\nimport { normalizeLink, type LinkOptions } from \"../links\";\nimport type { NotificationLike, NotificationResponseLike } from \"./modules\";\n\nconst ANY_PATH: LinkOptions = { map: { \"/*\": \"/*\" } };\n\n/** The data a notification carries (`content.data`), or `{}`. */\nexport function notificationData(notification: NotificationLike): Record<string, unknown> {\n const data = notification.request?.content?.data;\n return data && typeof data === \"object\" && !Array.isArray(data) ? data : {};\n}\n\n/** The app path a tap should open, or null. */\nexport function pathForResponse(response: NotificationResponseLike, links?: LinkOptions): string | null {\n const url = notificationData(response.notification).url;\n if (typeof url !== \"string\" || url.length === 0 || url.length > 2048) return null;\n if (links) return normalizeLink(url, links);\n // No link map: an app path only (never another app's URL), with \".\" and \"..\" refused as normalizeLink does.\n if (!url.startsWith(\"/\") || url.startsWith(\"//\") || url.includes(\"\\\\\")) return null;\n const path = normalizeLink(url, ANY_PATH);\n return path === \"/\" && url.split(/[?#]/)[0] !== \"/\" ? null : path;\n}\n","/**\n * The soft pre-prompt: the default of the `pushPrompt` slot, built from\n * `@marktiderman/genesis-ui-native`. It says what push is for before the\n * system asks, so a person who isn't ready says \"Not now\" here, where the\n * app can ask again later, rather than \"Don't Allow\" there, where it can't.\n */\nimport { View } from \"react-native\";\nimport { NativeButton, NativeSheet, NativeText } from \"@marktiderman/genesis-ui-native/components\";\n\nexport interface PushPromptProps {\n /** What `offer(reason)` said push is for here (\"to hear when someone replies\"), or null. */\n reason: string | null;\n /** \"Turn on\": shows the system prompt. */\n accept: () => void;\n /** \"Not now\": asks again after the cooldown, never more than `maxDeclines` times. */\n decline: () => void;\n title?: string;\n body?: string;\n acceptLabel?: string;\n declineLabel?: string;\n}\n\n// The sheet is iOS's full-height page sheet: grow to fill it and centre the few lines in it, rather\n// than leave them at the top of an empty sheet. On Android the panel sizes to its content.\nconst PROMPT_CONTENT = { flexGrow: 1, justifyContent: \"center\", gap: 16, padding: 24 } as const;\n\nexport function PushPromptSheet({ reason, accept, decline, title, body, acceptLabel, declineLabel }: PushPromptProps) {\n return (\n <NativeSheet open onOpenChange={(open) => (open ? undefined : decline())} testID=\"genesis-push-prompt\">\n <View style={PROMPT_CONTENT} testID=\"genesis-push-prompt-content\">\n <NativeText preset=\"h3\" accessibilityRole=\"header\">\n {title ?? \"Turn on notifications?\"}\n </NativeText>\n <NativeText preset=\"body\" className=\"text-muted-foreground\" testID=\"genesis-push-prompt-body\">\n {body ?? (reason ? `Get a notification ${reason}. You can change this any time in Settings.` : \"Get a notification when something needs you. You can change this any time in Settings.\")}\n </NativeText>\n <NativeButton onPress={accept} testID=\"genesis-push-prompt-accept\">\n {acceptLabel ?? \"Turn on\"}\n </NativeButton>\n <NativeButton variant=\"ghost\" onPress={decline} testID=\"genesis-push-prompt-decline\">\n {declineLabel ?? \"Not now\"}\n </NativeButton>\n </View>\n </NativeSheet>\n );\n}\n","/**\n * `createPush(options)`: the push block. Pass the result to\n * `<GenesisNativeApp blocks={[push]}>` (removing it turns the block off), or\n * render `<PushRoot block={push}>` yourself, inside the session provider.\n *\n * It is a `defineBlock` declaration (`id: \"push\"`): it contributes a Settings\n * row for the notification settings (`useBlockSettings`, href\n * `/settings/notifications`), a boot step that reads the permission behind\n * the splash (bounded, never fails), and names migration 0005.\n *\n * PushRoot\n * ├ follows the session: registers this device's token on sign-in (only\n * │ once permission is granted), forgets it on sign-out, clears the badge\n * ├ routes a tapped notification (the one that launched the app too)\n * │ through normalizeLink; signed out, the link is held until sign-in\n * ├ decides what shows while the app is open (the foreground handler)\n * ├ your screens\n * └ pushPrompt (the soft pre-prompt, only after `usePushPrompt().offer()`)\n *\n * The block never asks for permission by itself, and never at launch.\n * Every part is a slot or a primitive, and a hook (`usePushPermission`, …).\n */\nimport { createContext, useContext, useEffect, useRef, useSyncExternalStore, type ComponentType, type ReactNode } from \"react\";\nimport { View } from \"react-native\";\nimport { renderSlot, type SlotPropsFor, type Slots } from \"@marktiderman/genesis-core/slots\";\nimport { defineBlock } from \"@marktiderman/genesis-features/blocks\";\nimport { useSession } from \"../auth\";\nimport type { NativeBlock, NativeBlockRootProps } from \"../blocks\";\nimport type { BootStep } from \"../boot\";\nimport { delay } from \"../updates/store\";\nimport type { LinkHold } from \"../held-link\";\nimport type { LinkOptions } from \"../links\";\nimport type { NotificationPreferences, PushBackend } from \"./backend\";\nimport {\n report,\n type NotificationLike,\n type NotificationResponseLike,\n type NotificationsModuleLike,\n type PermissionRequestLike,\n type PushAppStateLike,\n type PushOnError,\n type PushStorageLike,\n} from \"./modules\";\nimport {\n canPush,\n createPermissionStore,\n createPromptStore,\n type PermissionState,\n type PermissionStore,\n type PromptOptions,\n type PromptState,\n type PromptStore,\n type PushPermissionStatus,\n} from \"./permission\";\nimport { createPreferencesStore, type ChannelImportance, type NotificationCategory, type PreferencesState, type PreferencesStore } from \"./preferences\";\nimport { createRegistration, type Registration, type RegistrationState } from \"./registration\";\nimport { notificationData, pathForResponse } from \"./routing\";\nimport { PushPromptSheet, type PushPromptProps } from \"./screens\";\n\n/** An Android channel beyond the categories' own (one per category is made for you). */\nexport interface PushChannel {\n id: string;\n name: string;\n description?: string;\n importance?: ChannelImportance;\n}\n\n// A type, not an interface, so it fits the slots contract's Record constraint.\nexport type PushSlots = {\n /** The soft pre-prompt, shown after `usePushPrompt().offer()`. Default `PushPromptSheet`. */\n pushPrompt: PushPromptProps;\n};\n\nexport interface PushOptions {\n /** `import * as Notifications from \"expo-notifications\"`. Without it the block does nothing (web, tests). */\n notifications?: NotificationsModuleLike;\n /** `Platform.OS`. */\n platform: string;\n /** The EAS project id (`Constants.expoConfig?.extra?.eas?.projectId`). Without it there is no push token; the block says so once through `onError`. */\n projectId?: string | null;\n /** The installed version, kept with the device row (`Application.nativeApplicationVersion`). */\n appVersion?: string | null;\n /** Devices and preferences: `supabasePushBackend(supabase)`. */\n backend: PushBackend;\n /** The kinds of notification the app sends; each is a toggle in NotificationSettings and an Android channel. */\n categories?: readonly NotificationCategory[];\n /** More Android channels. A `default` channel is always made. */\n channels?: readonly PushChannel[];\n /** AsyncStorage: this device's token (to forget it after sign-out), the prompt's \"Not now\"s. */\n storage?: PushStorageLike;\n /** `AppState`: read the permission again on coming to the front (the person may have changed it in Settings). */\n appState?: PushAppStateLike;\n /** `Linking.openSettings`, for \"Turn on in Settings\" once the system won't ask again. */\n openSettings?: () => unknown;\n /** Where a tap goes: the app's deep-link options, so a pushed path is normalized like any link. */\n links?: LinkOptions;\n /** Open a tapped notification's path (`router.push`). Without it a tap opens nothing, and says so through `onError`. */\n onOpen?: (path: string) => void;\n /** Where a tap that arrives signed out waits for sign-in: the same `linkHold` as GenesisNativeApp's `links.hold`. */\n hold?: LinkHold;\n /**\n * The Settings row the block contributes (`useBlockSettings`), or `false`\n * for none. Default `{ title: \"Notifications\", section: \"notifications\", href: \"/settings/notifications\" }`;\n * its subtitle is the permission's status (`statusLabels`).\n */\n settingsRow?: false | { title?: string; section?: string; href?: string };\n /** The words for each permission status (the Settings row's subtitle, NotificationSettings' default). */\n statusLabels?: Partial<Record<PushPermissionStatus, string>>;\n /** Every tap and action, after routing (an action button, analytics). */\n onResponse?: (response: NotificationResponseLike) => void;\n /** Show a notification that arrives while the app is open? Default yes; `useSuppressNotifications` adds rules. */\n foreground?: (notification: NotificationLike) => boolean;\n /** The iOS permissions asked for. Default alert, badge and sound. */\n permissions?: PermissionRequestLike;\n prompt?: PromptOptions;\n /** Clear the badge whenever the app comes to the front. Default false (the server sets it). */\n clearBadgeOnForeground?: boolean;\n /** Storage key prefix. Default `\"genesis:push\"`. */\n storageKeyPrefix?: string;\n /** Every caught error, for reporting; none of them breaks the app. */\n onError?: PushOnError;\n now?: () => number;\n}\n\n/** The FeatureId of the push block. */\nexport const PUSH_BLOCK_ID = \"push\";\n\n/** The default words for each permission status. */\nexport const PUSH_STATUS_LABELS: Record<PushPermissionStatus, string> = {\n unknown: \"Checking…\",\n undetermined: \"Off\",\n granted: \"On\",\n provisional: \"Delivered quietly\",\n denied: \"Off in Settings\",\n unavailable: \"Not available on this device\",\n};\n\nexport interface PushBlock extends NativeBlock<typeof PUSH_BLOCK_ID> {\n readonly options: PushOptions;\n readonly permission: PermissionStore;\n readonly registration: Registration;\n readonly preferences: PreferencesStore;\n readonly prompt: PromptStore;\n readonly categories: readonly NotificationCategory[];\n readonly badge: { set(count: number): Promise<void>; clear(): Promise<void> };\n /** Follow this signed-in user (null when signed out). `PushRoot` calls it from the session. */\n setUser(userId: string | null): void;\n /** Hide notifications that match while the app is open (the thread on screen); returns the removal. */\n suppress(match: (data: Record<string, unknown>, notification: NotificationLike) => boolean): () => void;\n /** Make the Android channels (once; again after a failure). */\n ensureChannels(): Promise<void>;\n /** Start the foreground handler and the listeners; returns the stop. `PushRoot` calls it. */\n start(): () => void;\n /** Reads the permission behind the splash, at most a second; never fails the boot. */\n readonly bootSteps: readonly BootStep[];\n readonly Root: ComponentType<NativeBlockRootProps>;\n}\n\n/** Expo's `AndroidImportance` numbers (checked against expo-notifications 58.1). */\nconst IMPORTANCE: Record<ChannelImportance, number> = { min: 3, low: 4, default: 5, high: 6, max: 7 };\n/** `AndroidNotificationVisibility.PRIVATE`: on a secure lock screen, Android shows that there is one, not what it says. */\nconst VISIBILITY_PRIVATE = 2;\n\n/** Build the block once, at module scope, next to your Supabase client. */\nexport function createPush(options: PushOptions): PushBlock {\n const { notifications, platform, storage, onError, now = Date.now } = options;\n const prefix = options.storageKeyPrefix ?? \"genesis:push\";\n const categories = options.categories ?? [];\n let userId: string | null = null;\n let startedAt: number | null = null;\n let channelsMade: Promise<void> | null = null;\n const suppressors = new Set<(data: Record<string, unknown>, notification: NotificationLike) => boolean>();\n\n const ensureChannels = (): Promise<void> => {\n if (!notifications || platform !== \"android\") return Promise.resolve();\n channelsMade ??= (async () => {\n const all = [\n { id: \"default\", name: \"Notifications\", importance: \"default\" as ChannelImportance, description: undefined as string | undefined },\n ...categories.map((c) => ({ id: c.id, name: c.title, importance: c.importance ?? \"default\", description: c.description })),\n ...(options.channels ?? []).map((c) => ({ ...c, importance: c.importance ?? \"default\" })),\n ];\n for (const channel of all) {\n await notifications.setNotificationChannelAsync(channel.id, {\n name: channel.name,\n importance: IMPORTANCE[channel.importance],\n description: channel.description ?? null,\n lockscreenVisibility: VISIBILITY_PRIVATE,\n showBadge: true,\n });\n }\n })().catch((error) => {\n channelsMade = null;\n throw error;\n });\n return channelsMade;\n };\n\n const permission = createPermissionStore({ notifications, request: options.permissions, beforeRequest: ensureChannels, onError });\n const registration = createRegistration({\n notifications,\n backend: options.backend,\n projectId: options.projectId,\n platform,\n appVersion: options.appVersion,\n storage,\n storageKeyPrefix: prefix,\n ensureChannels,\n isCurrent: (id) => userId === id,\n now,\n onError,\n });\n const preferences = createPreferencesStore({ backend: options.backend, categories, onError });\n const prompt = createPromptStore({\n ...options.prompt,\n permission,\n storage,\n storageKey: `${prefix}:prompt`,\n signedIn: () => userId !== null,\n startedAt: () => startedAt,\n now,\n onError,\n });\n\n const badge = {\n async set(count: number) {\n try {\n await notifications?.setBadgeCountAsync(Math.max(0, Math.floor(count)));\n } catch (error) {\n report(onError, error, \"badge\");\n }\n },\n clear: () => badge.set(0),\n };\n\n // Granted later (the prompt, Settings, another screen) while signed in: register now. The\n // first read (from \"unknown\") is left to setUser, which registers after it.\n let lastStatus = permission.getState().status;\n permission.subscribe(() => {\n const status = permission.getState().status;\n if (status !== lastStatus && lastStatus !== \"unknown\" && canPush(status) && userId) void registration.sync(userId);\n lastStatus = status;\n });\n\n const row = options.settingsRow;\n const labels = { ...PUSH_STATUS_LABELS, ...options.statusLabels };\n const declaration = defineBlock<typeof PUSH_BLOCK_ID, ComponentType<never>>({\n id: PUSH_BLOCK_ID,\n platforms: [\"native\"],\n contributes: {\n settings:\n row === false\n ? []\n : [\n {\n id: \"notifications\",\n section: row?.section ?? \"notifications\",\n title: row?.title ?? \"Notifications\",\n href: row?.href ?? \"/settings/notifications\",\n testID: \"genesis-push-settings\",\n // Bound to this block, so it needs no provider above the Settings screen.\n useSubtitle: () => labels[useSyncExternalStore(permission.subscribe, permission.getState, permission.getState).status],\n },\n ],\n routes: [{ path: row === false ? \"/settings/notifications\" : (row?.href ?? \"/settings/notifications\"), description: \"Notification settings: categories, quiet hours, previews\", signedIn: true }],\n migrations: [\n { package: \"@marktiderman/genesis-supabase\", file: \"migrations/0005_genesis_push.sql\", test: \"migrations/tests/0005_genesis_push.test.sql\" },\n ],\n privacy: {\n collects: [{ type: \"device ID\", purposes: [\"app functionality\"], linked: true, tracking: false }],\n notes: [\n \"Keeps this device's push token against the signed-in person, to send them notifications; forgotten on sign-out and account deletion.\",\n \"Keeps notification preferences (categories, quiet hours and time zone, previews) per person.\",\n ],\n },\n },\n });\n const bootStep: BootStep = {\n id: \"genesis:push\",\n // Bounded and never rejects (refresh reports its own errors), so it can't fail or hold the boot.\n run: () => Promise.race([permission.refresh(), delay(1000)]).then(() => undefined),\n timeoutMs: 3000,\n };\n\n const block: PushBlock = {\n ...declaration,\n bootSteps: [bootStep],\n options,\n permission,\n registration,\n preferences,\n prompt,\n categories,\n badge,\n ensureChannels,\n setUser(next) {\n if (next === userId) return;\n const previous = userId;\n userId = next;\n if (previous !== null) {\n // Signed out or switched: this phone stops getting the last person's pushes, and shows none of their count.\n void registration.forget();\n void badge.clear();\n preferences.reset();\n prompt.hide();\n }\n if (next !== null) {\n void preferences.load(next);\n void permission.refresh().then((status) => {\n if (canPush(status) && userId === next) void registration.sync(next);\n });\n }\n },\n suppress(match) {\n suppressors.add(match);\n return () => {\n suppressors.delete(match);\n };\n },\n start() {\n startedAt = now();\n if (!notifications) return () => {};\n notifications.setNotificationHandler({\n handleNotification: async (notification) => {\n let show = true;\n try {\n const data = notificationData(notification);\n show = !userId ? false : ![...suppressors].some((match) => match(data, notification)) && (options.foreground?.(notification) ?? true);\n } catch (error) {\n report(onError, error, \"routing\");\n }\n // Nothing of a push that isn't shown, the badge included (it may be the last person's).\n return { shouldShowBanner: show, shouldShowList: show, shouldPlaySound: show, shouldSetBadge: show };\n },\n });\n void registration.flush();\n void permission.refresh();\n const tokenSubscription = notifications.addPushTokenListener(() => {\n // The OS rotated the device token: fetch the Expo token again and register it.\n if (userId) void registration.sync(userId, { force: true });\n });\n const appSubscription = options.appState?.addEventListener(\"change\", (state) => {\n if (state !== \"active\") return;\n // Back in front: a forget that failed offline goes now, and this phone's registration is\n // confirmed (it may have failed, or another login may have taken the token since).\n void registration.flush();\n void permission.refresh().then((status) => {\n if (canPush(status) && userId) void registration.sync(userId);\n });\n if (options.clearBadgeOnForeground && userId) void badge.clear();\n });\n return () => {\n startedAt = null;\n notifications.setNotificationHandler(null);\n tokenSubscription.remove();\n appSubscription?.remove();\n };\n },\n Root: function PushBlockRoot({ slots, slotProps, children }: NativeBlockRootProps) {\n return (\n <PushRoot block={block} slots={slots} slotProps={slotProps}>\n {children}\n </PushRoot>\n );\n },\n };\n return block;\n}\n\nconst PushContext = createContext<PushBlock | null>(null);\n\n/** Provides the block to the hooks, without rendering any of its parts (rung 4). */\nexport function PushProvider({ block, children }: { block: PushBlock; children?: ReactNode }) {\n return <PushContext.Provider value={block}>{children}</PushContext.Provider>;\n}\n\n/** The block from `PushProvider` / `PushRoot` / `GenesisNativeApp`. Throws outside one. */\nexport function usePush(): PushBlock {\n const block = useContext(PushContext);\n if (!block) throw new Error(\"usePush: no push block. Put `createPush(…)` in GenesisNativeApp's `blocks`, or wrap in <PushProvider>.\");\n return block;\n}\n\n/** The block, or null when push is off: for a screen that works either way. */\nexport function useOptionalPush(): PushBlock | null {\n return useContext(PushContext);\n}\n\nexport function usePushPermissionState(): PermissionState {\n const { permission } = usePush();\n return useSyncExternalStore(permission.subscribe, permission.getState, permission.getState);\n}\n\nexport function usePushRegistration(): RegistrationState {\n const { registration } = usePush();\n return useSyncExternalStore(registration.subscribe, registration.getState, registration.getState);\n}\n\nexport function useNotificationPreferences(): PreferencesState & { update: PreferencesStore[\"update\"] } {\n const { preferences } = usePush();\n const state = useSyncExternalStore(preferences.subscribe, preferences.getState, preferences.getState);\n return { ...state, update: preferences.update };\n}\n\n/** The soft prompt: `offer(\"to hear when someone replies\")` at the right moment. */\nexport function usePushPrompt(): PromptState & Pick<PromptStore, \"offer\" | \"accept\" | \"decline\"> {\n const { prompt } = usePush();\n const state = useSyncExternalStore(prompt.subscribe, prompt.getState, prompt.getState);\n return { ...state, offer: prompt.offer, accept: prompt.accept, decline: prompt.decline };\n}\n\n/** The badge: `set(unread)`, `clear()`. */\nexport function useBadge(): PushBlock[\"badge\"] {\n return usePush().badge;\n}\n\n/**\n * Hide notifications that match while this screen is open (`data` is the\n * notification's `data`): a chat screen hides pushes for its own thread.\n * Does nothing without a push block.\n */\nexport function useSuppressNotifications(match: ((data: Record<string, unknown>) => boolean) | null) {\n const block = useOptionalPush();\n const latest = useRef(match);\n latest.current = match;\n const active = match !== null;\n useEffect(() => (block && active ? block.suppress((data) => latest.current?.(data) ?? false) : undefined), [block, active]);\n}\n\nexport interface PushRootProps {\n block: PushBlock;\n /** Where a tap that arrives signed out waits for sign-in (GenesisNativeApp passes its `links.hold`). */\n hold?: LinkHold;\n /** Open a path; used when the block's own `onOpen` isn't given. */\n onOpen?: (path: string) => void;\n slots?: Slots<PushSlots>;\n slotProps?: SlotPropsFor<PushSlots>;\n children?: ReactNode;\n}\n\n/** The block's parts around your screens. Must be inside GenesisNativeApp's session (or a `SessionProvider`). */\nexport function PushRoot({ block, hold, onOpen, slots, slotProps, children }: PushRootProps) {\n const { status, userId } = useSession();\n useEffect(() => block.start(), [block]);\n useEffect(() => {\n if (status === \"loading\") return;\n block.setUser(status === \"signedIn\" ? userId : null);\n }, [block, status, userId]);\n useTapRouting(block, status, hold, onOpen);\n\n return (\n <PushProvider block={block}>\n <View style={{ flex: 1 }}>\n {children}\n <PushPromptPart slots={slots} slotProps={slotProps} />\n </View>\n </PushProvider>\n );\n}\n\nfunction PushPromptPart({ slots, slotProps }: Pick<PushRootProps, \"slots\" | \"slotProps\">) {\n const prompt = usePushPrompt();\n if (!prompt.visible) return null;\n return renderSlot(\n PushPromptSheet,\n slots?.pushPrompt,\n { reason: prompt.reason, accept: () => void prompt.accept(), decline: () => void prompt.decline() },\n slotProps?.pushPrompt,\n );\n}\n\n/**\n * Taps: the one that launched the app (read once), then each one while it\n * runs. Signed in, the path opens on the next tick (after the navigator has\n * mounted); signed out, it is held and GenesisNativeApp follows it after\n * sign-in. Each notification is followed once, however many ways it arrives.\n */\nfunction useTapRouting(block: PushBlock, status: string, hold: LinkHold | undefined, onOpen: ((path: string) => void) | undefined) {\n const auth = useRef(status);\n auth.current = status;\n const latest = useRef({ hold, onOpen });\n latest.current = { hold, onOpen };\n const waiting = useRef<string | null>(null);\n\n const follow = (path: string) => {\n const open = block.options.onOpen ?? latest.current.onOpen;\n if (auth.current === \"signedIn\") {\n if (!open) {\n report(block.options.onError, new Error(\"push: a tapped notification has nowhere to go; pass `onOpen` to createPush (router.push).\"), \"setup\");\n return;\n }\n // After this render: at a cold start the router's navigator mounts with the screens.\n setTimeout(() => {\n try {\n open(path);\n } catch (error) {\n report(block.options.onError, error, \"routing\");\n }\n }, 0);\n } else if (auth.current === \"signedOut\") {\n const hold = block.options.hold ?? latest.current.hold;\n if (hold) hold.hold(path);\n else report(block.options.onError, new Error(\"push: a notification tapped while signed out was dropped; pass `hold` (your linkHold) to createPush.\"), \"setup\");\n } else {\n waiting.current = path;\n }\n };\n\n useEffect(() => {\n if (status === \"loading\" || waiting.current === null) return;\n const path = waiting.current;\n waiting.current = null;\n follow(path);\n }, [status]);\n\n useEffect(() => {\n const notifications = block.options.notifications;\n if (!notifications) return;\n const seen = new Set<string>();\n const handle = (response: NotificationResponseLike | null) => {\n if (!response) return;\n try {\n const id = response.notification.request.identifier;\n if (seen.has(id)) return;\n seen.add(id);\n if (response.actionIdentifier === notifications.DEFAULT_ACTION_IDENTIFIER) {\n const path = pathForResponse(response, block.options.links);\n if (path) follow(path);\n }\n block.options.onResponse?.(response);\n } catch (error) {\n report(block.options.onError, error, \"routing\");\n }\n };\n try {\n handle(notifications.getLastNotificationResponse());\n notifications.clearLastNotificationResponse();\n } catch (error) {\n report(block.options.onError, error, \"routing\");\n }\n const subscription = notifications.addNotificationResponseReceivedListener(handle);\n return () => subscription.remove();\n }, [block]);\n}\n\nexport type { NotificationPreferences };\n","/**\n * `<NotificationSettings>`: the notification preferences screen, a Genesis\n * `SettingsPage` with four parts:\n *\n * permission whether this phone may show notifications; Turn on / Open Settings\n * categories a switch per category the app defined\n * quietHours a switch, from and to times, and the time zone they're read in\n * privacy show previews (off: the sender sends neutral text instead)\n *\n * Each part is a slot (`slots.quietHours = MyQuietHours` replaces it inside\n * the same section, `null` drops the section) and a hook\n * (`useQuietHours()` …) for a screen of your own. Saving is immediate; a save\n * that fails is put back and said.\n */\nimport { useEffect, useMemo, useSyncExternalStore, type ComponentType, type ReactNode } from \"react\";\nimport type { SlotPropsFor, Slots } from \"@marktiderman/genesis-core/slots\";\nimport { NativeSwitch, NativeTimePicker } from \"@marktiderman/genesis-ui-native/components\";\nimport { SettingsPage, type SettingsPageProps, type SettingsPageRow, type SettingsPageSection } from \"@marktiderman/genesis-ui-native/layouts\";\nimport { useSession } from \"../auth\";\nimport { PUSH_STATUS_LABELS, usePush, useNotificationPreferences, usePushPermissionState, usePushRegistration } from \"./block\";\nimport type { PushPermissionStatus } from \"./permission\";\nimport { clockOf, dateAt, deviceTimeZone, isQuietAt } from \"./quiet-hours\";\n\nexport interface NotificationSettingsCopy {\n permissionSection: string;\n allow: string;\n status: Record<PushPermissionStatus, string>;\n turnOn: string;\n openSettings: string;\n noProjectId: string;\n noToken: string;\n registerFailed: string;\n categoriesSection: string;\n categoriesFootnote: string;\n quietHoursSection: string;\n quietHours: string;\n quietHoursOnNow: string;\n from: string;\n to: string;\n timeZone: string;\n useDeviceTimeZone: string;\n noTimeZone: string;\n quietHoursFootnote: string;\n privacySection: string;\n showPreviews: string;\n previewsFootnote: string;\n saveFailed: string;\n loadFailed: string;\n}\n\nexport const notificationSettingsCopy: NotificationSettingsCopy = {\n permissionSection: \"Notifications\",\n allow: \"Allow notifications\",\n status: PUSH_STATUS_LABELS,\n turnOn: \"Turn on\",\n openSettings: \"Open Settings\",\n noProjectId: \"This build can't get notifications: it has no EAS project id.\",\n noToken: \"This phone didn't give the app a push token. Try again on a device with a network connection.\",\n registerFailed: \"Couldn't turn notifications on for this phone. They'll be tried again next time you open the app.\",\n categoriesSection: \"Notify me about\",\n categoriesFootnote: \"Applies to every phone you're signed in on.\",\n quietHoursSection: \"Quiet hours\",\n quietHours: \"Quiet hours\",\n quietHoursOnNow: \"On now\",\n from: \"From\",\n to: \"To\",\n timeZone: \"Time zone\",\n useDeviceTimeZone: \"Tap to use this phone's\",\n noTimeZone: \"This phone didn't say its time zone, so quiet hours can't be placed in your day.\",\n quietHoursFootnote: \"Notifications that arrive during quiet hours wait until they end. Urgent ones still come through.\",\n privacySection: \"Privacy\",\n showPreviews: \"Show previews\",\n previewsFootnote: \"When off, notifications say only that there's something new; what they say stays on the server, off your lock screen.\",\n saveFailed: \"Couldn't save that change. Check your connection and try again.\",\n loadFailed: \"Couldn't load your notification settings, so they can't be changed yet. Check your connection; they load again when you come back here.\",\n};\n\n/** The permission part's props: what `usePushPermission()` returns. */\nexport interface PermissionPartProps {\n status: PushPermissionStatus;\n requesting: boolean;\n /** Shows the system prompt (a tap is the person's intent, so no soft prompt first). */\n request: () => void;\n /** Opens the app's page in Settings, once the system won't ask again. */\n openSettings: (() => void) | null;\n /** Why this phone isn't registered, in the copy's words, or null. */\n problem: string | null;\n copy: NotificationSettingsCopy;\n}\n\nexport interface CategoryRow {\n id: string;\n title: string;\n description?: string;\n on: boolean;\n}\n\nexport interface CategoriesPartProps {\n /** The saved settings aren't loaded (yet): nothing can change, so nothing overwrites them. */\n disabled: boolean;\n categories: CategoryRow[];\n setOn: (id: string, on: boolean) => void;\n saving: boolean;\n copy: NotificationSettingsCopy;\n}\n\nexport interface QuietHoursPartProps {\n /** The saved settings aren't loaded (yet): nothing can change, so nothing overwrites them. */\n disabled: boolean;\n enabled: boolean;\n start: string;\n end: string;\n timeZone: string | null;\n /** This phone's zone, when it differs from the saved one (it travelled). */\n deviceTimeZone: string | null;\n /** In quiet hours right now (shown only; the server decides). */\n activeNow: boolean;\n setEnabled: (on: boolean) => void;\n setStart: (clock: string) => void;\n setEnd: (clock: string) => void;\n adoptDeviceTimeZone: () => void;\n saving: boolean;\n copy: NotificationSettingsCopy;\n}\n\nexport interface PrivacyPartProps {\n /** The saved settings aren't loaded (yet): nothing can change, so nothing overwrites them. */\n disabled: boolean;\n hidePreviews: boolean;\n setHidePreviews: (hide: boolean) => void;\n saving: boolean;\n copy: NotificationSettingsCopy;\n}\n\n// A type, not an interface, so it fits the slots contract's Record constraint.\nexport type NotificationSettingsSlots = {\n permission: PermissionPartProps;\n categories: CategoriesPartProps;\n quietHours: QuietHoursPartProps;\n privacy: PrivacyPartProps;\n};\n\nconst DEFAULT_COPY = notificationSettingsCopy;\n\n/** The permission part (rung 4). */\nexport function usePushPermission(copy: NotificationSettingsCopy = DEFAULT_COPY): PermissionPartProps {\n const block = usePush();\n const { status, requesting } = usePushPermissionState();\n const { problem } = usePushRegistration();\n const open = block.options.openSettings;\n return {\n status,\n requesting,\n request: () => void block.permission.request(),\n openSettings: open\n ? () => {\n Promise.resolve()\n .then(open)\n .catch((error: unknown) => block.options.onError?.(error instanceof Error ? error : new Error(\"openSettings failed\"), \"permission\"));\n }\n : null,\n problem: problem === \"no_project_id\" ? copy.noProjectId : problem === \"no_token\" ? copy.noToken : problem === \"backend\" ? copy.registerFailed : null,\n copy,\n };\n}\n\n/** The categories part (rung 4). */\nexport function useNotificationCategories(copy: NotificationSettingsCopy = DEFAULT_COPY): CategoriesPartProps {\n const block = usePush();\n const { preferences, saving, update, status } = useNotificationPreferences();\n const categories = useMemo(\n () =>\n block.categories.map((c) => ({\n id: c.id,\n title: c.title,\n description: c.description,\n on: typeof preferences.categories[c.id] === \"boolean\" ? preferences.categories[c.id]! : (c.defaultOn ?? true),\n })),\n [block.categories, preferences.categories],\n );\n return {\n categories,\n setOn: (id, on) => void update((p) => ({ ...p, categories: { ...p.categories, [id]: on } })),\n saving,\n disabled: status !== \"ready\",\n copy,\n };\n}\n\n/** The quiet-hours part (rung 4). */\nexport function useQuietHours(copy: NotificationSettingsCopy = DEFAULT_COPY): QuietHoursPartProps {\n const { preferences, saving, update, status } = useNotificationPreferences();\n const q = preferences.quietHours;\n const device = deviceTimeZone();\n // Re-read each minute only while shown; the server is what decides.\n const minute = useMinute();\n const setQuiet = (change: Partial<typeof q>) => void update((p) => ({ ...p, quietHours: { ...p.quietHours, ...change } }));\n return {\n enabled: q.enabled,\n start: q.start,\n end: q.end,\n timeZone: q.timeZone,\n deviceTimeZone: device && device !== q.timeZone ? device : null,\n activeNow: isQuietAt(q, new Date(minute)),\n // Turning quiet hours on fills in this phone's zone if none was saved.\n setEnabled: (on) => setQuiet(on ? { enabled: true, timeZone: q.timeZone ?? device } : { enabled: false }),\n setStart: (start) => setQuiet({ start }),\n setEnd: (end) => setQuiet({ end }),\n adoptDeviceTimeZone: () => (device ? setQuiet({ timeZone: device }) : undefined),\n saving,\n disabled: status !== \"ready\",\n copy,\n };\n}\n\n/** The privacy part (rung 4). */\nexport function usePrivacyPreviews(copy: NotificationSettingsCopy = DEFAULT_COPY): PrivacyPartProps {\n const { preferences, saving, update, status } = useNotificationPreferences();\n return {\n hidePreviews: preferences.hidePreviews,\n setHidePreviews: (hidePreviews) => void update((p) => ({ ...p, hidePreviews })),\n saving,\n disabled: status !== \"ready\",\n copy,\n };\n}\n\nconst minuteStore = {\n subscribe(listener: () => void) {\n const timer = setInterval(listener, 30_000);\n return () => clearInterval(timer);\n },\n get: () => Math.floor(Date.now() / 60_000) * 60_000,\n};\nfunction useMinute(): number {\n return useSyncExternalStore(minuteStore.subscribe, minuteStore.get, minuteStore.get);\n}\n\nfunction toggle(id: string, label: string, checked: boolean, onChange: (on: boolean) => void, disabled = false): ReactNode {\n return (\n <NativeSwitch\n testID={`notification-settings-${id}-switch`}\n accessibilityLabel={label}\n checked={checked}\n onCheckedChange={onChange}\n disabled={disabled}\n />\n );\n}\n\n/** The permission part's default rows. */\nexport function permissionRows(p: PermissionPartProps): SettingsPageRow[] {\n const { status, copy } = p;\n const row: SettingsPageRow = { id: \"allow\", title: copy.allow, subtitle: copy.status[status], testID: \"notification-settings-allow\" };\n if (status === \"undetermined\") {\n return [{ ...row, showChevron: true, onPress: p.requesting ? undefined : p.request, disabled: p.requesting, subtitle: `${copy.status.undetermined} · ${copy.turnOn}` }];\n }\n if (status === \"denied\" && p.openSettings) {\n return [{ ...row, showChevron: true, onPress: p.openSettings, subtitle: `${copy.status.denied} · ${copy.openSettings}` }];\n }\n return [row];\n}\n\n/** The categories part's default rows. */\nexport function categoryRows(p: CategoriesPartProps): SettingsPageRow[] {\n return p.categories.map((c) => ({\n id: `category-${c.id}`,\n title: c.title,\n subtitle: c.description,\n testID: `notification-settings-category-${c.id}`,\n trailing: toggle(`category-${c.id}`, c.title, c.on, (on) => p.setOn(c.id, on), p.disabled),\n }));\n}\n\n/** The quiet-hours part's default rows. */\nexport function quietHoursRows(p: QuietHoursPartProps): SettingsPageRow[] {\n const { copy } = p;\n const rows: SettingsPageRow[] = [\n {\n id: \"quiet-hours\",\n title: copy.quietHours,\n subtitle: p.enabled && p.activeNow ? copy.quietHoursOnNow : undefined,\n testID: \"notification-settings-quiet-hours\",\n trailing: toggle(\"quiet-hours\", copy.quietHours, p.enabled, p.setEnabled, p.disabled || (!p.enabled && !p.timeZone && !p.deviceTimeZone)),\n },\n ];\n if (!p.enabled) return rows;\n const picker = (id: string, label: string, value: string, set: (clock: string) => void) => (\n <NativeTimePicker testID={`notification-settings-${id}-time`} value={dateAt(value)} onChange={(d) => set(clockOf(d))} formatLabel={() => value} disabled={p.disabled} />\n );\n rows.push(\n { id: \"quiet-from\", title: copy.from, testID: \"notification-settings-quiet-from\", trailing: picker(\"quiet-from\", copy.from, p.start, p.setStart) },\n { id: \"quiet-to\", title: copy.to, testID: \"notification-settings-quiet-to\", trailing: picker(\"quiet-to\", copy.to, p.end, p.setEnd) },\n {\n id: \"time-zone\",\n title: copy.timeZone,\n subtitle: p.timeZone ? (p.deviceTimeZone ? `${p.timeZone} · ${copy.useDeviceTimeZone} (${p.deviceTimeZone})` : p.timeZone) : copy.noTimeZone,\n testID: \"notification-settings-time-zone\",\n ...(p.deviceTimeZone && !p.disabled ? { onPress: p.adoptDeviceTimeZone, showChevron: true } : {}),\n },\n );\n return rows;\n}\n\n/** The privacy part's default rows. */\nexport function privacyRows(p: PrivacyPartProps): SettingsPageRow[] {\n return [\n {\n id: \"previews\",\n title: p.copy.showPreviews,\n testID: \"notification-settings-previews\",\n trailing: toggle(\"previews\", p.copy.showPreviews, !p.hidePreviews, (show) => p.setHidePreviews(!show), p.disabled),\n },\n ];\n}\n\nexport interface NotificationSettingsProps {\n /** Your words: any of `notificationSettingsCopy`'s, replaced. */\n copy?: Partial<NotificationSettingsCopy>;\n /** Replace a part (rendered in its section) or drop its section (`null`). */\n slots?: Slots<NotificationSettingsSlots>;\n /** More props for a part, merged over what the screen passes. */\n slotProps?: SlotPropsFor<NotificationSettingsSlots>;\n /** Passed to SettingsPage (its own `slots` and `slotProps` reach rows and headers). */\n page?: Omit<SettingsPageProps, \"sections\" | \"children\">;\n /** Above the first section. */\n children?: ReactNode;\n testID?: string;\n}\n\nfunction section<P extends object>(\n id: string,\n title: string,\n footnote: string | undefined,\n props: P,\n rows: (props: P) => SettingsPageRow[],\n slot: ComponentType<P> | null | undefined,\n extra: Partial<P> | undefined,\n): SettingsPageSection | null {\n if (slot === null) return null;\n const merged = { ...props, ...extra } as P;\n if (slot) {\n const Part = slot;\n return { id, title, footnote, rows: [], children: <Part {...merged} /> };\n }\n return { id, title, footnote, rows: rows(merged) };\n}\n\n/** The notification preferences screen. Needs the push block (in GenesisNativeApp's `blocks`, or a `PushProvider`). */\nexport function NotificationSettings({ copy: overrides, slots = {}, slotProps = {}, page, children, testID = \"notification-settings\" }: NotificationSettingsProps) {\n const copy = useMemo(() => ({ ...DEFAULT_COPY, ...overrides, status: { ...DEFAULT_COPY.status, ...overrides?.status } }), [overrides]);\n const block = usePush();\n const permission = usePushPermission(copy);\n const categories = useNotificationCategories(copy);\n const quietHours = useQuietHours(copy);\n const privacy = usePrivacyPreviews(copy);\n const { error, status } = useNotificationPreferences();\n const { userId } = useSession();\n // A load that failed is tried again whenever the screen opens (the block also loads on sign-in).\n useEffect(() => {\n if (block.preferences.getState().status === \"error\" && userId) void block.preferences.load(userId);\n }, [block, userId]);\n\n const sections = [\n section(\"permission\", copy.permissionSection, permission.problem ?? (status === \"error\" ? copy.loadFailed : error ? copy.saveFailed : undefined), permission, permissionRows, slots.permission, slotProps.permission),\n block.categories.length > 0\n ? section(\"categories\", copy.categoriesSection, copy.categoriesFootnote, categories, categoryRows, slots.categories, slotProps.categories)\n : null,\n section(\"quiet-hours\", copy.quietHoursSection, copy.quietHoursFootnote, quietHours, quietHoursRows, slots.quietHours, slotProps.quietHours),\n section(\"privacy\", copy.privacySection, copy.previewsFootnote, privacy, privacyRows, slots.privacy, slotProps.privacy),\n ].filter((s): s is SettingsPageSection => s !== null);\n\n return (\n <SettingsPage testID={testID} {...page} sections={sections}>\n {children}\n </SettingsPage>\n );\n}\n"]}
@@ -16,11 +16,16 @@ interface AsyncStorageLike {
16
16
  /** One day in milliseconds: the default max age of the saved query cache. */
17
17
  declare const DAY_MS: number;
18
18
  /**
19
- * A QueryClient for a phone. `networkMode: "always"` runs a query or mutation
20
- * even when the device reports offline, so it fails (and shows its error or
21
- * cached data) instead of waiting forever for a network that may never come
22
- * back. `gcTime` matches the persisted max age, or restored queries would be
23
- * collected before they are used. Your `config` wins.
19
+ * A QueryClient for a phone. `networkMode: "offlineFirst"` runs a query or
20
+ * mutation once whatever the network says, then pauses its retries while the
21
+ * device is offline (`onlineManager`, which `connectQueryLifecycle` feeds from
22
+ * NetInfo), continues them when it is back, and refetches stale queries on
23
+ * reconnect. So offline, a query with saved data keeps showing it
24
+ * (`fetchStatus: "paused"`); one with nothing saved stays `pending` and paused
25
+ * until the network returns (check `isPaused`, not only `isPending`, before
26
+ * showing a spinner); and a mutation, which TanStack doesn't retry by default,
27
+ * fails at once instead of waiting. `gcTime` matches the persisted max age, or
28
+ * restored queries would be collected before they are used. Your `config` wins.
24
29
  */
25
30
  declare function createNativeQueryClient(config?: QueryClientConfig): QueryClient;
26
31
  /**
@@ -62,4 +67,4 @@ interface QueryLifecycleOptions {
62
67
  */
63
68
  declare function connectQueryLifecycle({ appState, netInfo }: QueryLifecycleOptions): () => void;
64
69
 
65
- export { type AsyncStorageLike as A, DAY_MS as D, type NetInfoLike as N, type QueryPersistence as Q, type QueryLifecycleOptions as a, type AppStateLike as b, connectQueryLifecycle as c, createNativeQueryClient as d };
70
+ export { type AsyncStorageLike as A, DAY_MS as D, type NetInfoLike as N, type QueryLifecycleOptions as Q, type AppStateLike as a, type QueryPersistence as b, connectQueryLifecycle as c, createNativeQueryClient as d };
package/dist/updates.d.ts CHANGED
@@ -1,6 +1,13 @@
1
- export { A as ApplicationLike, C as CLOCK_SKEW_MS, b as ChannelSwitchResult, c as ChannelSwitcher, d as ChannelSwitcherOptions, E as EvaluatePolicyOptions, F as ForceUpgradeProps, e as ForceUpgradeScreen, M as MaintenanceProps, f as MaintenanceScreen, P as PolicyClientLike, g as PolicyOrigin, h as PolicyState, i as PolicyStore, j as PolicyStoreOptions, R as ReleaseNote, k as ReloadGuard, S as SupabasePolicySourceOptions, l as UpdateBanner, m as UpdateBannerProps, n as UpdateCheckState, o as UpdateCheckStatus, p as UpdateChecker, q as UpdateCheckerOptions, r as UpdatePlatform, s as UpdatePolicy, t as UpdatePolicySource, u as UpdateVerdict, v as UpdatesAppStateLike, U as UpdatesBlock, w as UpdatesErrorSource, x as UpdatesModuleLike, y as UpdatesOnError, z as UpdatesOptions, B as UpdatesProvider, D as UpdatesRoot, G as UpdatesRootProps, a as UpdatesSlots, H as UpdatesStorageLike, V as VersionSignature, I as VersionSignatureInput, W as WEEK_MS, J as WhatsNewOptions, K as WhatsNewProps, L as WhatsNewSheet, N as WhatsNewState, O as WhatsNewStore, Q as createChannelSwitcher, T as createPolicyStore, X as createReloadGuard, Y as createUpdateChecker, Z as createUpdates, _ as createWhatsNewStore, $ as evaluatePolicy, a0 as notesSince, a1 as sanitizePolicy, a2 as staticPolicySource, a3 as supabasePolicySource, a4 as useBlockReload, a5 as useCanReload, a6 as useForceUpgrade, a7 as useMaintenance, a8 as useUpdateBanner, a9 as useUpdateCheck, aa as useUpdatePolicy, ab as useUpdateVerdict, ac as useUpdates, ad as useVersionSignature, ae as useWhatsNew, af as versionSignature } from './block-Dh5ny06W.js';
1
+ export { b3 as ApplicationLike, b4 as CLOCK_SKEW_MS, b5 as ChannelSwitchResult, b6 as ChannelSwitcher, b7 as ChannelSwitcherOptions, b8 as EvaluatePolicyOptions, b9 as ForceUpgradeProps, ba as ForceUpgradeScreen, bb as MaintenanceProps, bc as MaintenanceScreen, bd as PolicyClientLike, be as PolicyOrigin, bf as PolicyState, bg as PolicyStore, bh as PolicyStoreOptions, bi as ReleaseNote, bj as ReloadGuard, bk as SupabasePolicySourceOptions, bl as UPDATES_BLOCK_ID, bm as UpdateBanner, bn as UpdateBannerProps, bo as UpdateCheckState, bp as UpdateCheckStatus, bq as UpdateChecker, br as UpdateCheckerOptions, bs as UpdatePlatform, bt as UpdatePolicy, bu as UpdatePolicySource, bv as UpdateVerdict, bw as UpdatesAppStateLike, U as UpdatesBlock, bx as UpdatesErrorSource, by as UpdatesModuleLike, bz as UpdatesOnError, bA as UpdatesOptions, bB as UpdatesProvider, bC as UpdatesRoot, bD as UpdatesRootProps, bE as UpdatesSlots, bF as UpdatesStorageLike, V as VersionSignature, bG as VersionSignatureInput, bH as WEEK_MS, bI as WhatsNewOptions, bJ as WhatsNewProps, bK as WhatsNewSheet, bL as WhatsNewState, bM as WhatsNewStore, bN as createChannelSwitcher, bO as createPolicyStore, bP as createReloadGuard, bQ as createUpdateChecker, bR as createUpdates, bS as createWhatsNewStore, bT as evaluatePolicy, bU as notesSince, bV as sanitizePolicy, bW as staticPolicySource, bX as supabasePolicySource, bY as useBlockReload, bZ as useCanReload, b_ as useForceUpgrade, b$ as useMaintenance, c0 as useUpdateBanner, c1 as useUpdateCheck, c2 as useUpdatePolicy, c3 as useUpdateVerdict, c4 as useUpdates, c5 as useVersionSignature, c6 as useWhatsNew, c7 as versionSignature } from './blocks-a1YQ1Elf.js';
2
2
  import 'react';
3
3
  import '@marktiderman/genesis-core/slots';
4
+ import '@marktiderman/genesis-features/blocks';
5
+ import '@tanstack/react-query';
6
+ import '@marktiderman/genesis-design-system';
7
+ import '@marktiderman/genesis-core/provider';
8
+ import '@marktiderman/genesis-ui-native/layouts';
9
+ import '@marktiderman/genesis-ui-native/components';
10
+ import './query-DUmVAfsF.js';
4
11
 
5
12
  /**
6
13
  * Version numbers: the store version an app reports (`1.4.0`, `1.10`) and
package/dist/updates.js CHANGED
@@ -1,38 +1,14 @@
1
+ import { createStore, delay } from './chunk-XE7LC7K6.js';
2
+ import { versionSignature } from './chunk-6BT4PTGH.js';
3
+ export { versionSignature } from './chunk-6BT4PTGH.js';
1
4
  import { createContext, useContext, useEffect, useSyncExternalStore, useMemo, useState } from 'react';
2
5
  import { View } from 'react-native';
3
6
  import { renderSlot } from '@marktiderman/genesis-core/slots';
7
+ import { defineBlock } from '@marktiderman/genesis-features/blocks';
4
8
  import { SafeAreaView } from 'react-native-safe-area-context';
5
- import { NativeEmptyState, NativeButton, NativeBanner, NativeSheet, NativeText } from '@marktiderman/genesis-ui-native/components';
9
+ import { NativeEmptyState, NativeButton, useLiquidGlass, NativeGlassSurface, NativeBanner, NativeSheet, NativeSheetScrollView, NativeText } from '@marktiderman/genesis-ui-native/components';
6
10
  import { jsx, jsxs } from 'react/jsx-runtime';
7
11
 
8
- // src/updates/block.tsx
9
-
10
- // src/updates/store.ts
11
- function createStore(initial) {
12
- let state = initial;
13
- const listeners = /* @__PURE__ */ new Set();
14
- return {
15
- getState: () => state,
16
- setState(next) {
17
- const merged = { ...state, ...next };
18
- if (Object.keys(merged).every((key) => Object.is(merged[key], state[key]))) return;
19
- state = merged;
20
- for (const listener of [...listeners]) listener();
21
- },
22
- subscribe(listener) {
23
- listeners.add(listener);
24
- return () => {
25
- listeners.delete(listener);
26
- };
27
- }
28
- };
29
- }
30
- function delay(ms) {
31
- return new Promise((resolve) => {
32
- if (Number.isFinite(ms)) setTimeout(resolve, Math.max(0, ms));
33
- });
34
- }
35
-
36
12
  // src/updates/modules.ts
37
13
  function toError(value) {
38
14
  return value instanceof Error ? value : new Error(typeof value === "string" ? value : "Unknown error");
@@ -444,39 +420,6 @@ function evaluatePolicy(state, options) {
444
420
  return { kind: "ok" };
445
421
  }
446
422
 
447
- // src/updates/signature.ts
448
- var UNKNOWN = "unknown";
449
- function versionSignature({ application, updates, platform, requestedChannel = null }) {
450
- const version = application?.nativeApplicationVersion ?? null;
451
- const build = application?.nativeBuildVersion ?? null;
452
- const on = Boolean(updates?.isEnabled);
453
- const channel = on ? updates?.channel ?? null : null;
454
- const updateId = on ? updates?.updateId ?? null : null;
455
- const runtimeVersion = updates?.runtimeVersion ?? null;
456
- const launch = !on ? "off" : updates?.isEmbeddedLaunch ? "embedded" : "update";
457
- const emergency = on && updates?.isEmergencyLaunch === true;
458
- const shownChannel = requestedChannel ?? channel;
459
- const head = `${version ?? UNKNOWN} (${build ?? UNKNOWN})`;
460
- const parts = [head];
461
- if (launch === "off") {
462
- parts.push("updates off");
463
- } else {
464
- parts.push(shownChannel ?? "no channel");
465
- parts.push(launch === "embedded" ? "embedded" : updateId?.slice(0, 8) ?? UNKNOWN);
466
- }
467
- if (emergency) parts.push("emergency launch");
468
- const short = parts.join(" \xB7 ");
469
- const lines = [
470
- `Version ${head}`,
471
- `Platform ${platform}`,
472
- `Channel ${channel ?? (on ? UNKNOWN : "none")}${requestedChannel && requestedChannel !== channel ? ` (switched to ${requestedChannel})` : ""}`,
473
- `Runtime ${runtimeVersion ?? UNKNOWN}`,
474
- `Update ${launch === "off" ? "updates off" : launch === "embedded" ? "embedded" : updateId ?? UNKNOWN}`
475
- ];
476
- if (emergency) lines.push(`Emergency launch: ${updates?.emergencyLaunchReason ?? UNKNOWN}`);
477
- return { version, build, platform, channel, requestedChannel, runtimeVersion, updateId, launch, emergency, short, text: lines.join("\n") };
478
- }
479
-
480
423
  // src/updates/whats-new.ts
481
424
  function notesSince(notes, seen, version) {
482
425
  return notes.filter((note) => {
@@ -574,14 +517,15 @@ function MaintenanceScreen({ message, retry, retrying }) {
574
517
  ) });
575
518
  }
576
519
  function UpdateBanner({ reload, dismiss, canReload, blocked, reloading }) {
577
- return /* @__PURE__ */ jsx(SafeAreaView, { edges: ["top"], pointerEvents: "box-none", style: { position: "absolute", top: 0, left: 0, right: 0 }, children: /* @__PURE__ */ jsxs(View, { testID: "genesis-update-banner", className: "mx-3 mt-2 overflow-hidden rounded-lg border border-border bg-secondary", children: [
520
+ const onGlass = useLiquidGlass() !== null;
521
+ return /* @__PURE__ */ jsx(SafeAreaView, { edges: ["top"], pointerEvents: "box-none", style: { position: "absolute", top: 0, left: 0, right: 0 }, children: /* @__PURE__ */ jsx(View, { className: "mx-3 mt-2", children: /* @__PURE__ */ jsxs(NativeGlassSurface, { testID: "genesis-update-banner", fallbackClassName: "overflow-hidden rounded-lg border border-border bg-secondary", children: [
578
522
  /* @__PURE__ */ jsx(
579
523
  NativeBanner,
580
524
  {
581
525
  variant: "info",
582
526
  title: "An update is ready",
583
527
  description: blocked || !canReload ? "Finish what you're doing, then restart to use it." : "Restart to use the latest version.",
584
- className: "border-b-0",
528
+ className: onGlass ? "border-b-0 border-transparent bg-transparent" : "border-b-0",
585
529
  testID: "genesis-update-banner-message"
586
530
  }
587
531
  ),
@@ -589,10 +533,10 @@ function UpdateBanner({ reload, dismiss, canReload, blocked, reloading }) {
589
533
  /* @__PURE__ */ jsx(NativeButton, { variant: "ghost", size: "sm", onPress: dismiss, testID: "genesis-update-banner-later", children: "Later" }),
590
534
  /* @__PURE__ */ jsx(NativeButton, { size: "sm", onPress: reload, disabled: !canReload, loading: reloading, testID: "genesis-update-banner-restart", children: "Restart" })
591
535
  ] })
592
- ] }) });
536
+ ] }) }) });
593
537
  }
594
538
  function WhatsNewSheet({ notes, dismiss }) {
595
- return /* @__PURE__ */ jsx(NativeSheet, { open: true, onOpenChange: (open) => open ? void 0 : dismiss(), testID: "genesis-whats-new", children: /* @__PURE__ */ jsxs(View, { className: "gap-4 p-6", children: [
539
+ return /* @__PURE__ */ jsx(NativeSheet, { open: true, onOpenChange: (open) => open ? void 0 : dismiss(), testID: "genesis-whats-new", children: /* @__PURE__ */ jsxs(NativeSheetScrollView, { contentContainerClassName: "gap-4 p-6", children: [
596
540
  /* @__PURE__ */ jsx(NativeText, { preset: "h3", accessibilityRole: "header", children: "What's new" }),
597
541
  notes.map((note) => /* @__PURE__ */ jsxs(View, { className: "gap-1", testID: `genesis-whats-new-${note.version}`, children: [
598
542
  /* @__PURE__ */ jsx(NativeText, { preset: "label", children: note.title ?? `Version ${note.version}` }),
@@ -601,6 +545,7 @@ function WhatsNewSheet({ notes, dismiss }) {
601
545
  /* @__PURE__ */ jsx(NativeButton, { onPress: dismiss, testID: "genesis-whats-new-done", children: "Got it" })
602
546
  ] }) });
603
547
  }
548
+ var UPDATES_BLOCK_ID = "app-updates";
604
549
  function createUpdates(options) {
605
550
  const {
606
551
  platform,
@@ -661,7 +606,34 @@ function createUpdates(options) {
661
606
  });
662
607
  return loaded;
663
608
  };
609
+ const bootStep = { id: "genesis:updates", run: load, timeoutMs: policyTimeoutMs + 5e3 };
610
+ const { versionRow } = options;
611
+ const declaration = defineBlock({
612
+ id: UPDATES_BLOCK_ID,
613
+ platforms: ["native"],
614
+ contributes: {
615
+ settings: versionRow === false ? [] : [
616
+ {
617
+ id: "app-version",
618
+ section: versionRow?.section ?? "about",
619
+ title: versionRow?.title ?? "Version",
620
+ testID: "genesis-app-version",
621
+ // Bound to this block, so it needs no provider above the Settings screen.
622
+ useSubtitle: () => useVersionSignatureOf(block).short
623
+ }
624
+ ],
625
+ migrations: [
626
+ {
627
+ package: "@marktiderman/genesis-supabase",
628
+ file: "migrations/0002_genesis_app_release_policy.sql",
629
+ test: "migrations/tests/0002_genesis_app_release_policy.test.sql"
630
+ }
631
+ ],
632
+ privacy: { notes: ["Reads the installed version and update ids on the device to decide on a force upgrade; sends nothing about the person."] }
633
+ }
634
+ });
664
635
  const block = {
636
+ ...declaration,
665
637
  options,
666
638
  policy,
667
639
  checker,
@@ -669,7 +641,8 @@ function createUpdates(options) {
669
641
  whatsNew,
670
642
  channels: switcher,
671
643
  signature,
672
- bootStep: { id: "genesis:updates", run: load, timeoutMs: policyTimeoutMs + 5e3 },
644
+ bootStep,
645
+ bootSteps: [bootStep],
673
646
  start() {
674
647
  void load();
675
648
  void checker.check();
@@ -765,7 +738,9 @@ function useWhatsNew() {
765
738
  return { notes: state.notes, version: block.options.application?.nativeApplicationVersion ?? null, dismiss: () => block.whatsNew.dismiss() };
766
739
  }
767
740
  function useVersionSignature() {
768
- const block = useUpdates();
741
+ return useVersionSignatureOf(useUpdates());
742
+ }
743
+ function useVersionSignatureOf(block) {
769
744
  const [requested, setRequested] = useState(null);
770
745
  useEffect(() => {
771
746
  let alive = true;
@@ -808,6 +783,6 @@ function UpdatesParts({ slots, slotProps, children }) {
808
783
  ] });
809
784
  }
810
785
 
811
- export { CLOCK_SKEW_MS, ForceUpgradeScreen, MaintenanceScreen, UpdateBanner, UpdatesProvider, UpdatesRoot, WEEK_MS, WhatsNewSheet, compareVersions, createChannelSwitcher, createPolicyStore, createReloadGuard, createUpdateChecker, createUpdates, createWhatsNewStore, evaluatePolicy, isBelowMinimum, notesSince, parseVersion, sanitizePolicy, staticPolicySource, supabasePolicySource, useBlockReload, useCanReload, useForceUpgrade, useMaintenance, useUpdateBanner, useUpdateCheck, useUpdatePolicy, useUpdateVerdict, useUpdates, useVersionSignature, useWhatsNew, versionSignature };
786
+ export { CLOCK_SKEW_MS, ForceUpgradeScreen, MaintenanceScreen, UPDATES_BLOCK_ID, UpdateBanner, UpdatesProvider, UpdatesRoot, WEEK_MS, WhatsNewSheet, compareVersions, createChannelSwitcher, createPolicyStore, createReloadGuard, createUpdateChecker, createUpdates, createWhatsNewStore, evaluatePolicy, isBelowMinimum, notesSince, parseVersion, sanitizePolicy, staticPolicySource, supabasePolicySource, useBlockReload, useCanReload, useForceUpgrade, useMaintenance, useUpdateBanner, useUpdateCheck, useUpdatePolicy, useUpdateVerdict, useUpdates, useVersionSignature, useWhatsNew };
812
787
  //# sourceMappingURL=updates.js.map
813
788
  //# sourceMappingURL=updates.js.map