@glassly/engine 0.3.7 → 0.3.8-dev.977

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 (176) hide show
  1. package/README.md +4 -0
  2. package/build/engine.d.ts +8 -2
  3. package/build/engine.d.ts.map +1 -1
  4. package/build/engine.js +7 -4
  5. package/build/engine.js.map +1 -1
  6. package/build/facades/backup.d.ts +14 -0
  7. package/build/facades/backup.d.ts.map +1 -0
  8. package/build/facades/backup.js +22 -0
  9. package/build/facades/backup.js.map +1 -0
  10. package/build/facades/glasses.d.ts +4 -4
  11. package/build/facades/glasses.d.ts.map +1 -1
  12. package/build/facades/glasses.js +4 -4
  13. package/build/facades/glasses.js.map +1 -1
  14. package/build/generated/releaseMetadata.js +4 -4
  15. package/build/generated/releaseMetadata.js.map +1 -1
  16. package/build/index.d.ts +1 -0
  17. package/build/index.d.ts.map +1 -1
  18. package/build/index.js.map +1 -1
  19. package/build/services/AppRegistry.d.ts +2 -1
  20. package/build/services/AppRegistry.d.ts.map +1 -1
  21. package/build/services/AppRegistry.js +38 -8
  22. package/build/services/AppRegistry.js.map +1 -1
  23. package/build/services/AppStateBackup.d.ts +98 -0
  24. package/build/services/AppStateBackup.d.ts.map +1 -0
  25. package/build/services/AppStateBackup.js +224 -0
  26. package/build/services/AppStateBackup.js.map +1 -0
  27. package/build/services/BlobStore.d.ts.map +1 -1
  28. package/build/services/BlobStore.js +5 -12
  29. package/build/services/BlobStore.js.map +1 -1
  30. package/build/services/CloudClientService.d.ts +1 -0
  31. package/build/services/CloudClientService.d.ts.map +1 -1
  32. package/build/services/CloudClientService.js +34 -2
  33. package/build/services/CloudClientService.js.map +1 -1
  34. package/build/services/DisplayProcessor.d.ts +2 -0
  35. package/build/services/DisplayProcessor.d.ts.map +1 -1
  36. package/build/services/DisplayProcessor.js +15 -1
  37. package/build/services/DisplayProcessor.js.map +1 -1
  38. package/build/services/GlassesTouchInput.d.ts.map +1 -1
  39. package/build/services/GlassesTouchInput.js +4 -2
  40. package/build/services/GlassesTouchInput.js.map +1 -1
  41. package/build/services/JSCrashloopReportService.d.ts.map +1 -1
  42. package/build/services/JSCrashloopReportService.js +5 -0
  43. package/build/services/JSCrashloopReportService.js.map +1 -1
  44. package/build/services/JSRouter.d.ts +11 -3
  45. package/build/services/JSRouter.d.ts.map +1 -1
  46. package/build/services/JSRouter.js +36 -6
  47. package/build/services/JSRouter.js.map +1 -1
  48. package/build/services/LocalMiniappRuntime.d.ts +13 -0
  49. package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
  50. package/build/services/LocalMiniappRuntime.js +54 -20
  51. package/build/services/LocalMiniappRuntime.js.map +1 -1
  52. package/build/services/MiniappEngine.d.ts +9 -0
  53. package/build/services/MiniappEngine.d.ts.map +1 -1
  54. package/build/services/MiniappEngine.js +60 -27
  55. package/build/services/MiniappEngine.js.map +1 -1
  56. package/build/services/MiniappLauncher.d.ts +2 -0
  57. package/build/services/MiniappLauncher.d.ts.map +1 -1
  58. package/build/services/MiniappLauncher.js +6 -0
  59. package/build/services/MiniappLauncher.js.map +1 -1
  60. package/build/services/NavigationService.d.ts +1 -0
  61. package/build/services/NavigationService.d.ts.map +1 -1
  62. package/build/services/NavigationService.js +20 -6
  63. package/build/services/NavigationService.js.map +1 -1
  64. package/build/services/PhoneCalendarService.d.ts.map +1 -1
  65. package/build/services/PhoneCalendarService.js +8 -0
  66. package/build/services/PhoneCalendarService.js.map +1 -1
  67. package/build/services/PhoneNotificationsSync.d.ts.map +1 -1
  68. package/build/services/PhoneNotificationsSync.js +7 -3
  69. package/build/services/PhoneNotificationsSync.js.map +1 -1
  70. package/build/services/SceneRenderer.js +1 -1
  71. package/build/services/SceneRenderer.js.map +1 -1
  72. package/build/services/appStateBackupFile.d.ts +32 -0
  73. package/build/services/appStateBackupFile.d.ts.map +1 -0
  74. package/build/services/appStateBackupFile.js +135 -0
  75. package/build/services/appStateBackupFile.js.map +1 -0
  76. package/build/services/controllers.d.ts.map +1 -1
  77. package/build/services/controllers.js +11 -3
  78. package/build/services/controllers.js.map +1 -1
  79. package/build/services/effectiveCapabilities.js +3 -0
  80. package/build/services/effectiveCapabilities.js.map +1 -1
  81. package/build/services/pages/pageEligibility.d.ts.map +1 -1
  82. package/build/services/pages/pageEligibility.js +8 -1
  83. package/build/services/pages/pageEligibility.js.map +1 -1
  84. package/build/services/settingsBridge.d.ts.map +1 -1
  85. package/build/services/settingsBridge.js +1 -0
  86. package/build/services/settingsBridge.js.map +1 -1
  87. package/build/services/{appleWatch/AppleWatchLink.d.ts → watch/WatchLink.d.ts} +8 -7
  88. package/build/services/watch/WatchLink.d.ts.map +1 -0
  89. package/build/services/{appleWatch/AppleWatchLink.js → watch/WatchLink.js} +14 -15
  90. package/build/services/watch/WatchLink.js.map +1 -0
  91. package/build/stores/apps.d.ts.map +1 -1
  92. package/build/stores/apps.js +14 -2
  93. package/build/stores/apps.js.map +1 -1
  94. package/build/stores/settings.d.ts.map +1 -1
  95. package/build/stores/settings.js +53 -3
  96. package/build/stores/settings.js.map +1 -1
  97. package/build/types/capabilities/even-realities-g1.d.ts.map +1 -1
  98. package/build/types/capabilities/even-realities-g1.js +3 -0
  99. package/build/types/capabilities/even-realities-g1.js.map +1 -1
  100. package/build/types/capabilities/memomind-one.d.ts +3 -0
  101. package/build/types/capabilities/memomind-one.d.ts.map +1 -0
  102. package/build/types/capabilities/memomind-one.js +41 -0
  103. package/build/types/capabilities/memomind-one.js.map +1 -0
  104. package/build/types/enums.d.ts +6 -2
  105. package/build/types/enums.d.ts.map +1 -1
  106. package/build/types/enums.js +4 -0
  107. package/build/types/enums.js.map +1 -1
  108. package/build/types/hardware.d.ts +3 -1
  109. package/build/types/hardware.d.ts.map +1 -1
  110. package/build/types/hardware.js +3 -1
  111. package/build/types/hardware.js.map +1 -1
  112. package/build/utils/display/index.d.ts +2 -1
  113. package/build/utils/display/index.d.ts.map +1 -1
  114. package/build/utils/display/index.js +3 -2
  115. package/build/utils/display/index.js.map +1 -1
  116. package/build/utils/display/profiles/index.d.ts +2 -1
  117. package/build/utils/display/profiles/index.d.ts.map +1 -1
  118. package/build/utils/display/profiles/index.js +3 -2
  119. package/build/utils/display/profiles/index.js.map +1 -1
  120. package/build/utils/display/profiles/rayneo-io.d.ts +1 -1
  121. package/build/utils/display/profiles/rayneo-io.d.ts.map +1 -1
  122. package/build/utils/display/profiles/rayneo-io.js +1 -1
  123. package/build/utils/display/profiles/rayneo-io.js.map +1 -1
  124. package/build/utils/display/scene/index.d.ts +1 -1
  125. package/build/utils/display/scene/index.d.ts.map +1 -1
  126. package/build/utils/display/scene/index.js +1 -1
  127. package/build/utils/display/scene/index.js.map +1 -1
  128. package/build/utils/display/scene/process.d.ts +6 -0
  129. package/build/utils/display/scene/process.d.ts.map +1 -1
  130. package/build/utils/display/scene/process.js +22 -7
  131. package/build/utils/display/scene/process.js.map +1 -1
  132. package/build/utils/miniappGlobals.d.ts +13 -17
  133. package/build/utils/miniappGlobals.d.ts.map +1 -1
  134. package/build/utils/miniappGlobals.js +24 -56
  135. package/build/utils/miniappGlobals.js.map +1 -1
  136. package/package.json +7 -7
  137. package/src/engine.ts +7 -4
  138. package/src/facades/backup.ts +28 -0
  139. package/src/facades/glasses.ts +5 -5
  140. package/src/generated/releaseMetadata.ts +4 -4
  141. package/src/index.ts +1 -0
  142. package/src/services/AppRegistry.ts +36 -9
  143. package/src/services/AppStateBackup.ts +283 -0
  144. package/src/services/BlobStore.ts +5 -11
  145. package/src/services/CloudClientService.ts +35 -4
  146. package/src/services/DisplayProcessor.ts +20 -8
  147. package/src/services/GlassesTouchInput.ts +6 -2
  148. package/src/services/JSCrashloopReportService.ts +5 -0
  149. package/src/services/JSRouter.ts +37 -6
  150. package/src/services/LocalMiniappRuntime.ts +55 -20
  151. package/src/services/MiniappEngine.ts +62 -27
  152. package/src/services/MiniappLauncher.ts +7 -0
  153. package/src/services/NavigationService.ts +28 -8
  154. package/src/services/PhoneCalendarService.ts +7 -0
  155. package/src/services/PhoneNotificationsSync.ts +8 -3
  156. package/src/services/SceneRenderer.ts +1 -1
  157. package/src/services/appStateBackupFile.ts +171 -0
  158. package/src/services/controllers.ts +12 -3
  159. package/src/services/effectiveCapabilities.ts +3 -0
  160. package/src/services/pages/pageEligibility.ts +9 -1
  161. package/src/services/settingsBridge.ts +1 -0
  162. package/src/services/{appleWatch/AppleWatchLink.ts → watch/WatchLink.ts} +20 -20
  163. package/src/stores/apps.ts +13 -2
  164. package/src/stores/settings.ts +60 -7
  165. package/src/types/capabilities/even-realities-g1.ts +4 -0
  166. package/src/types/capabilities/memomind-one.ts +42 -0
  167. package/src/types/enums.ts +4 -0
  168. package/src/types/hardware.ts +14 -1
  169. package/src/utils/display/index.ts +4 -2
  170. package/src/utils/display/profiles/index.ts +9 -2
  171. package/src/utils/display/profiles/rayneo-io.ts +6 -1
  172. package/src/utils/display/scene/index.ts +1 -1
  173. package/src/utils/display/scene/process.ts +22 -7
  174. package/src/utils/miniappGlobals.ts +32 -64
  175. package/build/services/appleWatch/AppleWatchLink.d.ts.map +0 -1
  176. package/build/services/appleWatch/AppleWatchLink.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"settingsBridge.js","sourceRoot":"","sources":["../../src/services/settingsBridge.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The settings bridge's vocabulary (session.settings): which engine settings\n * a miniapp with the PLATFORM_SETTINGS permission may read or write, the\n * derived read-only keys the engine computes rather than stores, and the\n * request validation. Pure, so the runtime's handlers stay thin and this can\n * be tested without the native import surface the runtime pulls in.\n *\n * A dashboard miniapp is the usual consumer: it edits the notification,\n * glasses-menu, display-position, brightness and microphone keys the phone's\n * settings screens do, through the store, so persistence, server sync and the\n * Bluetooth sync behave as if a phone screen wrote them. A dashboard's own\n * look is not here; it keeps that in its storage.\n */\n\nimport type {ControllerStatus, PairedController} from \"@glassly/bluetooth-sdk\"\n\nimport {ControllerTypes} from \"../types/enums\"\nimport {hasInput2d, isControllerReady} from \"./controllers\"\n\nexport type SettingsBridgeAccess = \"read\" | \"write\"\n\n/** Stored settings the bridge serves, by key, with what a permitted app may do to each. */\nexport const SETTINGS_BRIDGE_KEYS: Readonly<Record<string, SettingsBridgeAccess>> = {\n // The dashboard's master switch is a phone-side debug knob.\n custom_dashboard_enabled: \"read\",\n contextual_dashboard: \"write\",\n head_up_angle: \"write\",\n // Where the glasses draw; each model's steps are its display.positionRange.\n dashboard_depth: \"write\",\n dashboard_height: \"write\",\n // Device settings the dashboard's glasses Settings page edits.\n brightness: \"write\",\n auto_brightness: \"write\",\n // Per paired model: the store resolves the indexed key.\n preferred_mic: \"write\",\n twelve_hour_time: \"write\",\n menu_apps: \"write\",\n notifications_enabled: \"write\",\n notifications_popups: \"write\",\n notifications_popup_seconds: \"write\",\n notifications_hold_during_apps: \"write\",\n notifications_ignore_while_active: \"write\",\n notifications_blocklist: \"write\",\n // Apps the glasses reported posting notifications; the engine records it.\n notification_seen_apps: \"read\",\n}\n\n/**\n * Read-only keys the engine computes: whether the wearer can see the phone,\n * whether the foreground miniapp is drawing on the glasses, and the paired\n * controllers with their battery and input. They change on their own clocks;\n * the runtime pushes them like stored keys.\n */\nexport const DERIVED_SETTINGS_KEYS = [\"phone_active\", \"foreground_app_on_screen\", \"controllers\"] as const\nexport type DerivedSettingsKey = (typeof DERIVED_SETTINGS_KEYS)[number]\n\nexport function isDerivedSettingsKey(key: string): key is DerivedSettingsKey {\n return (DERIVED_SETTINGS_KEYS as readonly string[]).includes(key)\n}\n\n/** What a permitted app may do with `key`, or null when the bridge does not serve it. */\nexport function settingsBridgeAccess(key: string): SettingsBridgeAccess | null {\n if (isDerivedSettingsKey(key)) return \"read\"\n return SETTINGS_BRIDGE_KEYS[key] ?? null\n}\n\n/** Every key the bridge serves, stored then derived. */\nexport function allSettingsBridgeKeys(): string[] {\n return [...Object.keys(SETTINGS_BRIDGE_KEYS), ...DERIVED_SETTINGS_KEYS]\n}\n\n/**\n * The keys a SETTINGS_GET asks for: everything when `requested` is absent,\n * else the known ones among the requested strings (unknown keys are left\n * out, never rejected).\n */\nexport function selectSettingsBridgeKeys(requested: unknown): string[] {\n if (requested === undefined || requested === null) return allSettingsBridgeKeys()\n if (!Array.isArray(requested)) return []\n return requested.filter((key): key is string => typeof key === \"string\" && settingsBridgeAccess(key) !== null)\n}\n\nexport type SettingsSetValidation =\n | {ok: true; key: string; value: unknown}\n | {ok: false; code: \"INVALID_ARGUMENT\" | \"NOT_PERMITTED\"; message: string}\n\n/** A SETTINGS_SET payload: a writable key and a JSON value (undefined is not a value). */\nexport function validateSettingsSet(payload: Record<string, unknown>): SettingsSetValidation {\n const key = payload.key\n if (typeof key !== \"string\" || !key) {\n return {ok: false, code: \"INVALID_ARGUMENT\", message: \"settings.set requires a key\"}\n }\n const access = settingsBridgeAccess(key)\n if (access === null) return {ok: false, code: \"INVALID_ARGUMENT\", message: `Unknown setting \"${key}\"`}\n if (access !== \"write\") return {ok: false, code: \"NOT_PERMITTED\", message: `Setting \"${key}\" is read-only`}\n if (!(\"value\" in payload) || payload.value === undefined) {\n return {ok: false, code: \"INVALID_ARGUMENT\", message: \"settings.set requires a value\"}\n }\n return {ok: true, key, value: payload.value}\n}\n\n/** One paired controller as the `controllers` derived key serves it. */\nexport interface ControllerSettingEntry {\n id: string\n model: string\n name: string\n /** Delivering input. */\n connected: boolean\n /** level -1 when unknown. */\n battery: {level: number; charging: boolean}\n /** Swipes sideways as well as up and down (the Meta Neural Band). */\n input2d: boolean\n}\n\n/** What the glasses report about the ring linked to them (G2 with the R1 routed through it). */\nexport interface RelayedRing {\n ringConnected: boolean\n ringBatteryLevel: number\n ringCharging: boolean\n}\n\n/**\n * The R1 the glasses' ring report is about: a ring routed through the G2 keeps\n * its phone link for telemetry, so prefer a linked ring, else the first one.\n */\nfunction relayedRingId(\n records: PairedController[],\n statuses: Record<string, ControllerStatus> | undefined,\n): string | undefined {\n const rings = records.filter((record) => record.model === ControllerTypes.R1)\n return (rings.find((ring) => statuses?.[ring.id]?.connected === true) ?? rings[0])?.id\n}\n\n/**\n * One entry per paired record, registry order. While the glasses report a\n * linked ring, that report is that ring's link and battery: a ring routed\n * through the G2 reports there, not to the phone.\n */\nexport function controllersSettingFrom(\n records: PairedController[],\n statuses: Record<string, ControllerStatus> | undefined,\n relayed: RelayedRing,\n): ControllerSettingEntry[] {\n const relayedId = relayed.ringConnected ? relayedRingId(records, statuses) : undefined\n return records.map((record) => {\n const status = statuses?.[record.id]\n let connected = isControllerReady(status)\n let battery = {level: status?.batteryLevel ?? -1, charging: status?.charging === true}\n if (record.id === relayedId) {\n connected = true\n if (relayed.ringBatteryLevel >= 0) {\n battery = {level: relayed.ringBatteryLevel, charging: relayed.ringCharging}\n }\n }\n return {\n id: record.id,\n model: record.model,\n name: record.name,\n connected,\n battery,\n input2d: connected && hasInput2d(record.model),\n }\n })\n}\n"]}
1
+ {"version":3,"file":"settingsBridge.js","sourceRoot":"","sources":["../../src/services/settingsBridge.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The settings bridge's vocabulary (session.settings): which engine settings\n * a miniapp with the PLATFORM_SETTINGS permission may read or write, the\n * derived read-only keys the engine computes rather than stores, and the\n * request validation. Pure, so the runtime's handlers stay thin and this can\n * be tested without the native import surface the runtime pulls in.\n *\n * A dashboard miniapp is the usual consumer: it edits the notification,\n * glasses-menu, display-position, brightness and microphone keys the phone's\n * settings screens do, through the store, so persistence, server sync and the\n * Bluetooth sync behave as if a phone screen wrote them. A dashboard's own\n * look is not here; it keeps that in its storage.\n */\n\nimport type {ControllerStatus, PairedController} from \"@glassly/bluetooth-sdk\"\n\nimport {ControllerTypes} from \"../types/enums\"\nimport {hasInput2d, isControllerReady} from \"./controllers\"\n\nexport type SettingsBridgeAccess = \"read\" | \"write\"\n\n/** Stored settings the bridge serves, by key, with what a permitted app may do to each. */\nexport const SETTINGS_BRIDGE_KEYS: Readonly<Record<string, SettingsBridgeAccess>> = {\n // The dashboard's master switch is a phone-side debug knob.\n custom_dashboard_enabled: \"read\",\n contextual_dashboard: \"write\",\n head_up_angle: \"write\",\n // Where the glasses draw; each model's steps are its display.positionRange.\n dashboard_depth: \"write\",\n dashboard_height: \"write\",\n // Device settings the dashboard's glasses Settings page edits.\n brightness: \"write\",\n auto_brightness: \"write\",\n // Per paired model: the store resolves the indexed key.\n preferred_mic: \"write\",\n twelve_hour_time: \"write\",\n menu_apps: \"write\",\n notifications_enabled: \"write\",\n notifications_popups: \"write\",\n notifications_popup_seconds: \"write\",\n notifications_batch_seconds: \"write\",\n notifications_hold_during_apps: \"write\",\n notifications_ignore_while_active: \"write\",\n notifications_blocklist: \"write\",\n // Apps the glasses reported posting notifications; the engine records it.\n notification_seen_apps: \"read\",\n}\n\n/**\n * Read-only keys the engine computes: whether the wearer can see the phone,\n * whether the foreground miniapp is drawing on the glasses, and the paired\n * controllers with their battery and input. They change on their own clocks;\n * the runtime pushes them like stored keys.\n */\nexport const DERIVED_SETTINGS_KEYS = [\"phone_active\", \"foreground_app_on_screen\", \"controllers\"] as const\nexport type DerivedSettingsKey = (typeof DERIVED_SETTINGS_KEYS)[number]\n\nexport function isDerivedSettingsKey(key: string): key is DerivedSettingsKey {\n return (DERIVED_SETTINGS_KEYS as readonly string[]).includes(key)\n}\n\n/** What a permitted app may do with `key`, or null when the bridge does not serve it. */\nexport function settingsBridgeAccess(key: string): SettingsBridgeAccess | null {\n if (isDerivedSettingsKey(key)) return \"read\"\n return SETTINGS_BRIDGE_KEYS[key] ?? null\n}\n\n/** Every key the bridge serves, stored then derived. */\nexport function allSettingsBridgeKeys(): string[] {\n return [...Object.keys(SETTINGS_BRIDGE_KEYS), ...DERIVED_SETTINGS_KEYS]\n}\n\n/**\n * The keys a SETTINGS_GET asks for: everything when `requested` is absent,\n * else the known ones among the requested strings (unknown keys are left\n * out, never rejected).\n */\nexport function selectSettingsBridgeKeys(requested: unknown): string[] {\n if (requested === undefined || requested === null) return allSettingsBridgeKeys()\n if (!Array.isArray(requested)) return []\n return requested.filter((key): key is string => typeof key === \"string\" && settingsBridgeAccess(key) !== null)\n}\n\nexport type SettingsSetValidation =\n | {ok: true; key: string; value: unknown}\n | {ok: false; code: \"INVALID_ARGUMENT\" | \"NOT_PERMITTED\"; message: string}\n\n/** A SETTINGS_SET payload: a writable key and a JSON value (undefined is not a value). */\nexport function validateSettingsSet(payload: Record<string, unknown>): SettingsSetValidation {\n const key = payload.key\n if (typeof key !== \"string\" || !key) {\n return {ok: false, code: \"INVALID_ARGUMENT\", message: \"settings.set requires a key\"}\n }\n const access = settingsBridgeAccess(key)\n if (access === null) return {ok: false, code: \"INVALID_ARGUMENT\", message: `Unknown setting \"${key}\"`}\n if (access !== \"write\") return {ok: false, code: \"NOT_PERMITTED\", message: `Setting \"${key}\" is read-only`}\n if (!(\"value\" in payload) || payload.value === undefined) {\n return {ok: false, code: \"INVALID_ARGUMENT\", message: \"settings.set requires a value\"}\n }\n return {ok: true, key, value: payload.value}\n}\n\n/** One paired controller as the `controllers` derived key serves it. */\nexport interface ControllerSettingEntry {\n id: string\n model: string\n name: string\n /** Delivering input. */\n connected: boolean\n /** level -1 when unknown. */\n battery: {level: number; charging: boolean}\n /** Swipes sideways as well as up and down (the Meta Neural Band). */\n input2d: boolean\n}\n\n/** What the glasses report about the ring linked to them (G2 with the R1 routed through it). */\nexport interface RelayedRing {\n ringConnected: boolean\n ringBatteryLevel: number\n ringCharging: boolean\n}\n\n/**\n * The R1 the glasses' ring report is about: a ring routed through the G2 keeps\n * its phone link for telemetry, so prefer a linked ring, else the first one.\n */\nfunction relayedRingId(\n records: PairedController[],\n statuses: Record<string, ControllerStatus> | undefined,\n): string | undefined {\n const rings = records.filter((record) => record.model === ControllerTypes.R1)\n return (rings.find((ring) => statuses?.[ring.id]?.connected === true) ?? rings[0])?.id\n}\n\n/**\n * One entry per paired record, registry order. While the glasses report a\n * linked ring, that report is that ring's link and battery: a ring routed\n * through the G2 reports there, not to the phone.\n */\nexport function controllersSettingFrom(\n records: PairedController[],\n statuses: Record<string, ControllerStatus> | undefined,\n relayed: RelayedRing,\n): ControllerSettingEntry[] {\n const relayedId = relayed.ringConnected ? relayedRingId(records, statuses) : undefined\n return records.map((record) => {\n const status = statuses?.[record.id]\n let connected = isControllerReady(status)\n let battery = {level: status?.batteryLevel ?? -1, charging: status?.charging === true}\n if (record.id === relayedId) {\n connected = true\n if (relayed.ringBatteryLevel >= 0) {\n battery = {level: relayed.ringBatteryLevel, charging: relayed.ringCharging}\n }\n }\n return {\n id: record.id,\n model: record.model,\n name: record.name,\n connected,\n battery,\n input2d: connected && hasInput2d(record.model),\n }\n })\n}\n"]}
@@ -1,11 +1,12 @@
1
1
  /**
2
- * The Apple Watch remote's phone half: the watch app's status context (glasses, the miniapp in
2
+ * The watch remote's phone half, for the Apple Watch (iOS, WatchConnectivity) and a Wear OS
3
+ * watch (Android, Wearable Data Layer) alike: the watch app's status (glasses, the miniapp in
3
4
  * front, launchable miniapps, whether Assist takes questions, the mirror setting), mirror frames
4
5
  * while the setting is on, and the commands the watch sends back. Native adds whether the active
5
6
  * watch is paired and keeps the newest frame for when the watch app opens. Gestures ride
6
7
  * `touch_event` like any controller's.
7
8
  */
8
- import type { AppleWatchCommandEvent } from "@glassly/bluetooth-sdk";
9
+ import type { WatchCommandEvent } from "@glassly/bluetooth-sdk";
9
10
  import type { MirrorSnapshot } from "@glassly/miniapp";
10
11
  import type { ClientApp } from "../../types";
11
12
  export declare const ASSIST_PACKAGE = "com.glassly.assistant";
@@ -28,7 +29,7 @@ export declare function launchableApps(apps: readonly ClientApp[]): {
28
29
  export declare function watchState({ glasses, apps, assist, mirror }: WatchStateInput): Record<string, unknown>;
29
30
  /** The glasses frame in the watch's drawing vocabulary; null when there is nothing to draw. */
30
31
  export declare function mirrorFrame(snapshot: MirrorSnapshot): Record<string, unknown> | null;
31
- export interface AppleWatchCommandDeps {
32
+ export interface WatchCommandDeps {
32
33
  apps: () => readonly ClientApp[];
33
34
  start: (app: ClientApp) => Promise<unknown>;
34
35
  stop: (packageName: string) => Promise<unknown>;
@@ -36,7 +37,7 @@ export interface AppleWatchCommandDeps {
36
37
  type: (stream: string, payload: unknown) => void;
37
38
  now: () => number;
38
39
  }
39
- export declare function handleAppleWatchCommand(event: AppleWatchCommandEvent, deps?: AppleWatchCommandDeps): Promise<void>;
40
- export declare function startAppleWatchLink(): void;
41
- export declare function stopAppleWatchLink(): void;
42
- //# sourceMappingURL=AppleWatchLink.d.ts.map
40
+ export declare function handleWatchCommand(event: WatchCommandEvent, deps?: WatchCommandDeps): Promise<void>;
41
+ export declare function startWatchLink(): void;
42
+ export declare function stopWatchLink(): void;
43
+ //# sourceMappingURL=WatchLink.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WatchLink.d.ts","sourceRoot":"","sources":["../../../src/services/watch/WatchLink.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,wBAAwB,CAAA;AAE7D,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAA;AAMpD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,aAAa,CAAA;AAO1C,eAAO,MAAM,cAAc,0BAA0B,CAAA;AACrD,eAAO,MAAM,aAAa,QAAQ,CAAA;AAQlC,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE;QAAC,SAAS,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAC,CAAA;IAC7D,IAAI,EAAE,SAAS,SAAS,EAAE,CAAA;IAC1B,MAAM,EAAE,OAAO,CAAA;IACf,MAAM,EAAE,OAAO,CAAA;CAChB;AAED,kFAAkF;AAClF,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,SAAS,EAAE,GAAG;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC,EAAE,CAMhG;AAED,wBAAgB,UAAU,CAAC,EAAC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAC,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAUpG;AAOD,+FAA+F;AAC/F,wBAAgB,WAAW,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CA4EpF;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,SAAS,SAAS,EAAE,CAAA;IAChC,KAAK,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IAC3C,IAAI,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IAC/C,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACxC,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;IAChD,GAAG,EAAE,MAAM,MAAM,CAAA;CAClB;AAWD,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,iBAAiB,EACxB,IAAI,GAAE,gBAA8B,GACnC,OAAO,CAAC,IAAI,CAAC,CA4Bf;AA6DD,wBAAgB,cAAc,IAAI,IAAI,CAqCrC;AAED,wBAAgB,aAAa,IAAI,IAAI,CAGpC"}
@@ -1,6 +1,5 @@
1
1
  import BluetoothSdk from "@glassly/bluetooth-sdk/internal";
2
2
  import { MiniappStreamType } from "@glassly/miniapp";
3
- import { Platform } from "react-native";
4
3
  import { useAppStatusStore } from "../../stores/apps";
5
4
  import { useGlassesStore } from "../../stores/glasses";
6
5
  import { SETTINGS, useSettingsStore } from "../../stores/settings";
@@ -11,7 +10,7 @@ import { mirrorService } from "../MirrorService";
11
10
  import { keyEventsForTextChange } from "../neuralBand/NeuralBandInput";
12
11
  export const ASSIST_PACKAGE = "com.glassly.assistant";
13
12
  export const ASSIST_ACTION = "ask";
14
- /** WatchConnectivity messages top out near 64 KB; frames past this are skipped, not truncated. */
13
+ /** WatchConnectivity messages top out near 64 KB (Data Layer messages at 100 KB); frames past this are skipped, not truncated. */
15
14
  const MAX_FRAME_BYTES = 48_000;
16
15
  const MAX_IMAGE_CHARS = 16_000;
17
16
  const MAX_APPS = 24;
@@ -129,14 +128,14 @@ const defaultDeps = {
129
128
  type: (stream, payload) => localMiniappRuntime.forwardEvent(stream, payload),
130
129
  now: () => Date.now(),
131
130
  };
132
- export async function handleAppleWatchCommand(event, deps = defaultDeps) {
131
+ export async function handleWatchCommand(event, deps = defaultDeps) {
133
132
  switch (event.command) {
134
133
  case "launch": {
135
134
  const app = launchableApps(deps.apps()).some((entry) => entry.packageName === event.packageName)
136
135
  ? deps.apps().find((entry) => entry.packageName === event.packageName)
137
136
  : undefined;
138
137
  if (!app) {
139
- console.warn(`AppleWatch: launch of unknown miniapp ${event.packageName}`);
138
+ console.warn(`Watch: launch of unknown miniapp ${event.packageName}`);
140
139
  return;
141
140
  }
142
141
  await deps.start(app);
@@ -172,7 +171,7 @@ function currentState() {
172
171
  },
173
172
  apps: useAppStatusStore.getState().apps,
174
173
  assist: localMiniappRuntime.hostActionAvailable(ASSIST_PACKAGE, ASSIST_ACTION),
175
- mirror: useSettingsStore.getState().getSetting(SETTINGS.apple_watch_mirror.key) === true,
174
+ mirror: useSettingsStore.getState().getSetting(SETTINGS.watch_mirror.key) === true,
176
175
  });
177
176
  }
178
177
  function syncMirror(enabled) {
@@ -191,7 +190,7 @@ function syncMirror(enabled) {
191
190
  let timer = null;
192
191
  const send = (snapshot) => {
193
192
  lastSentAt = Date.now();
194
- void BluetoothSdk.setWatchMirror(mirrorFrame(snapshot)).catch((err) => console.warn("AppleWatch: mirror push failed:", err));
193
+ void BluetoothSdk.setWatchMirror(mirrorFrame(snapshot)).catch((err) => console.warn("Watch: mirror push failed:", err));
195
194
  };
196
195
  const unsubscribe = mirrorService.subscribe((snapshot) => {
197
196
  const wait = lastSentAt + MIRROR_INTERVAL_MS - Date.now();
@@ -214,8 +213,8 @@ function syncMirror(enabled) {
214
213
  timer = null;
215
214
  };
216
215
  }
217
- export function startAppleWatchLink() {
218
- if (Platform.OS !== "ios" || stops.length > 0)
216
+ export function startWatchLink() {
217
+ if (stops.length > 0)
219
218
  return;
220
219
  let lastKey = "";
221
220
  let timer = null;
@@ -226,20 +225,20 @@ export function startAppleWatchLink() {
226
225
  if (key === lastKey)
227
226
  return;
228
227
  lastKey = key;
229
- void BluetoothSdk.setWatchState(state).catch((err) => console.warn("AppleWatch: state push failed:", err));
228
+ void BluetoothSdk.setWatchState(state).catch((err) => console.warn("Watch: state push failed:", err));
230
229
  };
231
230
  const schedule = () => {
232
231
  timer ??= BgTimer.setTimeout(push, STATE_DEBOUNCE_MS);
233
232
  };
234
- const mirrorEnabled = () => useSettingsStore.getState().getSetting(SETTINGS.apple_watch_mirror.key) === true;
235
- const commands = BluetoothSdk.addListener("apple_watch_command", (event) => {
236
- handleAppleWatchCommand(event).catch((err) => console.warn(`AppleWatch: ${event.command} failed:`, err));
233
+ const mirrorEnabled = () => useSettingsStore.getState().getSetting(SETTINGS.watch_mirror.key) === true;
234
+ const commands = BluetoothSdk.addListener("watch_command", (event) => {
235
+ handleWatchCommand(event).catch((err) => console.warn(`Watch: ${event.command} failed:`, err));
237
236
  });
238
237
  stops = [
239
238
  () => commands.remove(),
240
239
  useGlassesStore.subscribe(schedule),
241
240
  useAppStatusStore.subscribe(schedule),
242
- useSettingsStore.subscribe((s) => s.getSetting(SETTINGS.apple_watch_mirror.key), () => {
241
+ useSettingsStore.subscribe((s) => s.getSetting(SETTINGS.watch_mirror.key), () => {
243
242
  syncMirror(mirrorEnabled());
244
243
  schedule();
245
244
  }),
@@ -252,8 +251,8 @@ export function startAppleWatchLink() {
252
251
  syncMirror(mirrorEnabled());
253
252
  schedule();
254
253
  }
255
- export function stopAppleWatchLink() {
254
+ export function stopWatchLink() {
256
255
  stops.splice(0).forEach((stop) => stop());
257
256
  syncMirror(false);
258
257
  }
259
- //# sourceMappingURL=AppleWatchLink.js.map
258
+ //# sourceMappingURL=WatchLink.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WatchLink.js","sourceRoot":"","sources":["../../../src/services/watch/WatchLink.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The watch remote's phone half, for the Apple Watch (iOS, WatchConnectivity) and a Wear OS\n * watch (Android, Wearable Data Layer) alike: the watch app's status (glasses, the miniapp in\n * front, launchable miniapps, whether Assist takes questions, the mirror setting), mirror frames\n * while the setting is on, and the commands the watch sends back. Native adds whether the active\n * watch is paired and keeps the newest frame for when the watch app opens. Gestures ride\n * `touch_event` like any controller's.\n */\nimport type {WatchCommandEvent} from \"@glassly/bluetooth-sdk\"\nimport BluetoothSdk from \"@glassly/bluetooth-sdk/internal\"\nimport type {MirrorSnapshot} from \"@glassly/miniapp\"\nimport {MiniappStreamType} from \"@glassly/miniapp\"\n\nimport {useAppStatusStore} from \"../../stores/apps\"\nimport {useGlassesStore} from \"../../stores/glasses\"\nimport {SETTINGS, useSettingsStore} from \"../../stores/settings\"\nimport type {ClientApp} from \"../../types\"\nimport {BgTimer} from \"../../utils/timers\"\nimport {isGlassesConnected} from \"../GlassesReadiness\"\nimport localMiniappRuntime from \"../LocalMiniappRuntime\"\nimport {mirrorService} from \"../MirrorService\"\nimport {keyEventsForTextChange} from \"../neuralBand/NeuralBandInput\"\n\nexport const ASSIST_PACKAGE = \"com.glassly.assistant\"\nexport const ASSIST_ACTION = \"ask\"\n/** WatchConnectivity messages top out near 64 KB (Data Layer messages at 100 KB); frames past this are skipped, not truncated. */\nconst MAX_FRAME_BYTES = 48_000\nconst MAX_IMAGE_CHARS = 16_000\nconst MAX_APPS = 24\nconst STATE_DEBOUNCE_MS = 250\nconst MIRROR_INTERVAL_MS = 500\n\nexport interface WatchStateInput {\n glasses: {connected: boolean; model: string; battery: number}\n apps: readonly ClientApp[]\n assist: boolean\n mirror: boolean\n}\n\n/** Miniapps the watch can open: shown, compatible, and drawing on the glasses. */\nexport function launchableApps(apps: readonly ClientApp[]): {packageName: string; name: string}[] {\n return apps\n .filter((app) => app.type === \"standard\" && !app.hidden && app.compatibility?.isCompatible !== false)\n .filter((app) => app.packageName && !app.packageName.includes(\"@empty\"))\n .slice(0, MAX_APPS)\n .map((app) => ({packageName: app.packageName, name: app.name}))\n}\n\nexport function watchState({glasses, apps, assist, mirror}: WatchStateInput): Record<string, unknown> {\n const front = apps.find((app) => app.foregrounded && app.running && app.type === \"standard\")\n const state: Record<string, unknown> = {\n glasses: {connected: glasses.connected, name: glasses.model || \"Glasses\", battery: glasses.battery},\n apps: launchableApps(apps),\n assist,\n mirror,\n }\n if (front) state.app = {packageName: front.packageName, name: front.name}\n return state\n}\n\ntype WatchElement = Record<string, string | number | boolean | number[]>\n\nconst level = (color: unknown, fallback = 15) =>\n typeof color === \"number\" ? Math.max(0, Math.min(15, color)) : fallback\n\n/** The glasses frame in the watch's drawing vocabulary; null when there is nothing to draw. */\nexport function mirrorFrame(snapshot: MirrorSnapshot): Record<string, unknown> | null {\n const canvas = snapshot.canvas\n if (!canvas) return null\n const content = snapshot.content\n if (content.kind === \"bitmap\") {\n if (content.data.length > MAX_FRAME_BYTES) return null\n return {width: canvas.width, height: canvas.height, bitmap: content.data, elements: []}\n }\n if (content.kind !== \"scene\") return null\n const elements: WatchElement[] = []\n for (const element of content.elements) {\n const {x, y, w, h} = element.box\n const style = element.style ?? {}\n switch (element.type) {\n case \"text\":\n if (!element.text) break\n elements.push({\n type: \"text\",\n x,\n y,\n w,\n h,\n text: element.text,\n size: style.fontSize ?? 20,\n color: level(style.color),\n })\n break\n case \"rect\":\n elements.push({\n type: \"rect\",\n x,\n y,\n w,\n h,\n fill: style.fill === true,\n border: style.border ?? 1,\n radius: style.radius ?? 0,\n color: level(style.color),\n })\n break\n case \"circle\":\n elements.push({\n type: \"circle\",\n x,\n y,\n w,\n h,\n fill: style.fill === true,\n border: style.border ?? 1,\n color: level(style.color),\n })\n break\n case \"line\":\n case \"triangle\":\n case \"quad\": {\n const points = (element.points ?? []).flatMap((point) => [point.x, point.y])\n if (points.length < 4) break\n const closed = element.type !== \"line\"\n elements.push({\n type: \"line\",\n points,\n width: style.width ?? style.border ?? 1,\n color: level(style.color),\n closed,\n fill: closed && style.fill === true,\n })\n break\n }\n case \"image\":\n if (element.data && element.data.length <= MAX_IMAGE_CHARS)\n elements.push({type: \"image\", x, y, w, h, data: element.data})\n break\n }\n }\n const frame = {width: canvas.width, height: canvas.height, elements}\n return JSON.stringify(frame).length > MAX_FRAME_BYTES ? null : frame\n}\n\nexport interface WatchCommandDeps {\n apps: () => readonly ClientApp[]\n start: (app: ClientApp) => Promise<unknown>\n stop: (packageName: string) => Promise<unknown>\n ask: (query: string) => Promise<unknown>\n type: (stream: string, payload: unknown) => void\n now: () => number\n}\n\nconst defaultDeps: WatchCommandDeps = {\n apps: () => useAppStatusStore.getState().apps,\n start: (app) => useAppStatusStore.getState().start(app),\n stop: (packageName) => useAppStatusStore.getState().stop(packageName),\n ask: (query) => localMiniappRuntime.invokeActionFromHost(ASSIST_PACKAGE, ASSIST_ACTION, {query}),\n type: (stream, payload) => localMiniappRuntime.forwardEvent(stream, payload),\n now: () => Date.now(),\n}\n\nexport async function handleWatchCommand(\n event: WatchCommandEvent,\n deps: WatchCommandDeps = defaultDeps,\n): Promise<void> {\n switch (event.command) {\n case \"launch\": {\n const app = launchableApps(deps.apps()).some((entry) => entry.packageName === event.packageName)\n ? deps.apps().find((entry) => entry.packageName === event.packageName)\n : undefined\n if (!app) {\n console.warn(`Watch: launch of unknown miniapp ${event.packageName}`)\n return\n }\n await deps.start(app)\n return\n }\n case \"stop\": {\n const front = deps.apps().find((app) => app.foregrounded && app.running && app.type === \"standard\")\n if (front) await deps.stop(front.packageName)\n return\n }\n case \"assist\": {\n const query = event.text.trim()\n if (query) await deps.ask(query)\n return\n }\n case \"text\":\n for (const key of keyEventsForTextChange(\"\", event.text, deps.now()))\n deps.type(MiniappStreamType.KEYBOARD_EVENT, key)\n return\n }\n}\n\nlet stops: (() => void)[] = []\nlet stopMirror: (() => void) | null = null\n\nfunction currentState(): Record<string, unknown> {\n const glasses = useGlassesStore.getState()\n return watchState({\n glasses: {\n connected: isGlassesConnected(glasses.connection),\n model: glasses.deviceModel,\n battery: glasses.batteryLevel,\n },\n apps: useAppStatusStore.getState().apps,\n assist: localMiniappRuntime.hostActionAvailable(ASSIST_PACKAGE, ASSIST_ACTION),\n mirror: useSettingsStore.getState().getSetting(SETTINGS.watch_mirror.key) === true,\n })\n}\n\nfunction syncMirror(enabled: boolean): void {\n if (!enabled) {\n if (stopMirror) {\n stopMirror()\n stopMirror = null\n void BluetoothSdk.setWatchMirror(null).catch(() => {})\n }\n return\n }\n if (stopMirror) return\n let lastSentAt = 0\n let pending: MirrorSnapshot | null = null\n let timer: ReturnType<typeof BgTimer.setTimeout> | null = null\n const send = (snapshot: MirrorSnapshot) => {\n lastSentAt = Date.now()\n void BluetoothSdk.setWatchMirror(mirrorFrame(snapshot)).catch((err) =>\n console.warn(\"Watch: mirror push failed:\", err),\n )\n }\n const unsubscribe = mirrorService.subscribe((snapshot) => {\n const wait = lastSentAt + MIRROR_INTERVAL_MS - Date.now()\n if (wait <= 0 && !timer) {\n send(snapshot)\n return\n }\n pending = snapshot\n timer ??= BgTimer.setTimeout(\n () => {\n timer = null\n if (pending) send(pending)\n pending = null\n },\n Math.max(wait, 0),\n )\n })\n stopMirror = () => {\n unsubscribe()\n if (timer) BgTimer.clearTimeout(timer)\n timer = null\n }\n}\n\nexport function startWatchLink(): void {\n if (stops.length > 0) return\n let lastKey = \"\"\n let timer: ReturnType<typeof BgTimer.setTimeout> | null = null\n const push = () => {\n timer = null\n const state = currentState()\n const key = JSON.stringify(state)\n if (key === lastKey) return\n lastKey = key\n void BluetoothSdk.setWatchState(state).catch((err) => console.warn(\"Watch: state push failed:\", err))\n }\n const schedule = () => {\n timer ??= BgTimer.setTimeout(push, STATE_DEBOUNCE_MS)\n }\n const mirrorEnabled = () => useSettingsStore.getState().getSetting(SETTINGS.watch_mirror.key) === true\n const commands = BluetoothSdk.addListener(\"watch_command\", (event) => {\n handleWatchCommand(event).catch((err) => console.warn(`Watch: ${event.command} failed:`, err))\n })\n stops = [\n () => commands.remove(),\n useGlassesStore.subscribe(schedule),\n useAppStatusStore.subscribe(schedule),\n useSettingsStore.subscribe(\n (s) => s.getSetting(SETTINGS.watch_mirror.key),\n () => {\n syncMirror(mirrorEnabled())\n schedule()\n },\n ),\n () => {\n if (timer) BgTimer.clearTimeout(timer)\n timer = null\n },\n ]\n syncMirror(mirrorEnabled())\n schedule()\n}\n\nexport function stopWatchLink(): void {\n stops.splice(0).forEach((stop) => stop())\n syncMirror(false)\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"apps.d.ts","sourceRoot":"","sources":["../../src/stores/apps.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"apps.d.ts","sourceRoot":"","sources":["../../src/stores/apps.ts"],"names":[],"mappings":"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"}
@@ -124,6 +124,7 @@ function projectApps(previousState, localApps) {
124
124
  DeviceTypes.NONE;
125
125
  const capabilities = getModelCapabilities(defaultWearable);
126
126
  const devToolsEnabled = useSettingsStore.getState().getSetting(SETTINGS.dev_tools.key) === true;
127
+ const persistScreenshots = useSettingsStore.getState().getSetting(SETTINGS.persist_miniapp_screenshots.key) !== false;
127
128
  const hasPairedGlasses = useSettingsStore.getState().getSetting(SETTINGS.has_paired_glasses.key) === true;
128
129
  // Single pass: dedupe → screenshot carry-over → compat → hidden, all into
129
130
  // fresh objects. The previous in-place mutation re-used object references
@@ -149,7 +150,9 @@ function projectApps(previousState, localApps) {
149
150
  .map((app) => {
150
151
  const next = {
151
152
  ...app,
152
- screenshot: previousByPackage.get(app.packageName)?.screenshot ?? app.screenshot,
153
+ // The registry's screenshot is the one restored from disk; only an
154
+ // in-memory capture carries over when persistence is off.
155
+ screenshot: previousByPackage.get(app.packageName)?.screenshot ?? (persistScreenshots ? app.screenshot : undefined),
153
156
  compatibility: HardwareCompatibility.checkCompatibility(app.hardwareRequirements, capabilities),
154
157
  // A registry source can force an app off the primary home screen.
155
158
  // Compose that gate with the user's persisted home-screen layout instead
@@ -284,6 +287,9 @@ export const useAppStatusStore = create((set, get) => ({
284
287
  // still takes the foreground below.
285
288
  if (app.running && !app.widgetOnly) {
286
289
  saveLastOpenTime(packageName);
290
+ // The running background only knows the source of its spawn.
291
+ if (app.local)
292
+ miniappLauncher.notifyLaunch(packageName, opts?.launchSource ?? "phone");
287
293
  return true;
288
294
  }
289
295
  // Only-one rules: one standard app in the foreground, one dashboard
@@ -417,7 +423,13 @@ export const useAppStatusStore = create((set, get) => ({
417
423
  });
418
424
  },
419
425
  saveScreenshot: async (packageName, screenshot) => {
420
- storage.save(`${packageName}_screenshot`, screenshot);
426
+ const key = `${packageName}_screenshot`;
427
+ if (useSettingsStore.getState().getSetting(SETTINGS.persist_miniapp_screenshots.key) !== false) {
428
+ storage.save(key, screenshot);
429
+ }
430
+ else {
431
+ storage.remove(key);
432
+ }
421
433
  set((s) => ({
422
434
  apps: s.apps.map((a) => (a.packageName === packageName ? { ...a, screenshot } : a)),
423
435
  }));
@@ -1 +1 @@
1
- {"version":3,"file":"apps.js","sourceRoot":"","sources":["../../src/stores/apps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAC,OAAO,EAAC,MAAM,OAAO,CAAA;AAC7B,OAAO,EAAsB,MAAM,IAAI,GAAG,EAAC,MAAM,aAAa,CAAA;AAC9D,OAAO,EAAC,MAAM,EAAC,MAAM,SAAS,CAAA;AAG9B,OAAO,EAAC,WAAW,EAAC,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAC,oBAAoB,EAAC,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAAC,qBAAqB,EAA2B,MAAM,4BAA4B,CAAA;AAC1F,OAAO,EAAC,OAAO,EAAC,MAAM,0BAA0B,CAAA;AAChD,OAAO,WAAW,EAAE,EAAC,oBAAoB,EAAE,sBAAsB,EAAC,MAAM,yBAAyB,CAAA;AACjG,OAAO,mBAAmB,MAAM,iCAAiC,CAAA;AACjE,OAAO,EAAC,mBAAmB,EAAC,MAAM,kCAAkC,CAAA;AACpE,OAAO,eAAe,MAAM,6BAA6B,CAAA;AACzD,OAAO,EAAC,eAAe,EAAC,MAAM,6BAA6B,CAAA;AAC3D,OAAO,EAAC,gBAAgB,EAAE,qBAAqB,EAAC,MAAM,qCAAqC,CAAA;AAC3F,OAAO,EAAC,sBAAsB,EAAC,MAAM,oCAAoC,CAAA;AACzE,OAAO,EAAC,iBAAiB,EAAC,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EAAC,mBAAmB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,mBAAmB,EAAC,MAAM,iBAAiB,CAAA;AAC/G,OAAO,EAAC,QAAQ,EAAE,gBAAgB,EAAC,MAAM,YAAY,CAAA;AACrD,OAAO,YAAY,MAAM,wBAAwB,CAAA;AAmCjD,IAAI,SAAS,GAAkB,EAAE,CAAA;AAEjC,MAAM,UAAU,oBAAoB,CAAC,KAAoB;IACvD,SAAS,GAAG,EAAC,GAAG,SAAS,EAAE,GAAG,KAAK,EAAC,CAAA;AACtC,CAAC;AA6CD,MAAM,CAAC,MAAM,YAAY,GAAc;IACrC,WAAW,EAAE,EAAE;IACf,IAAI,EAAE,EAAE;IACR,UAAU,EAAE,EAAE;IACd,OAAO,EAAE,EAAE;IACX,IAAI,EAAE,UAAU;IAChB,WAAW,EAAE,EAAE;IACf,OAAO,EAAE,KAAK;IACd,OAAO,EAAE,KAAK;IACd,OAAO,EAAE,IAAI;IACb,oBAAoB,EAAE,EAAE;IACxB,OAAO,EAAE,IAAI;IACb,YAAY,EAAE,EAAE;IAChB,KAAK,EAAE,KAAK;IACZ,MAAM,EAAE,KAAK;CACd,CAAA;AAGD,MAAM,aAAa,GAAG,uBAAuB,CAAA;AAE7C,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,QAAkB,EAAuB,EAAE;IACvE,OAAO,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAA;AAC9C,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,GAA4B,EAAE;IACxD,OAAO,OAAO,CAAC,IAAI,CAAW,aAAa,CAAC,CAAA;AAC9C,CAAC,CAAA;AAED,6EAA6E;AAC7E,2EAA2E;AAC3E,yEAAyE;AACzE,mEAAmE;AACnE,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAmB,CAAA;AAEpD,MAAM,yBAAyB,GAAG,CAAC,GAAW,EAAU,EAAE;IACxD,IAAI,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAA;IACb,CAAC;IACD,OAAO,CAAC,CAAA;AACV,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAY,EAAE,CAAY,EAAU,EAAE;IAClF,MAAM,EAAE,GAAG,yBAAyB,CAAC,CAAC,CAAC,WAAW,CAAC,CAAA;IACnD,MAAM,EAAE,GAAG,yBAAyB,CAAC,CAAC,CAAC,WAAW,CAAC,CAAA;IACnD,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACd,OAAO,EAAE,GAAG,EAAE,CAAA;IAChB,CAAC;IACD,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;AACrC,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,WAAmB,EAAQ,EAAE;IAC5D,OAAO,CAAC,IAAI,CAAC,GAAG,WAAW,iBAAiB,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;AAC3D,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,WAAmB,EAAU,EAAE;IAC7D,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAS,GAAG,WAAW,iBAAiB,CAAC,CAAA;IACjE,IAAI,GAAG,CAAC,KAAK,EAAE;QAAE,OAAO,GAAG,CAAC,KAAK,CAAA;IACjC,OAAO,CAAC,CAAA;AACV,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,sBAAsB,GAAG,KAAK,EAAmC,IAAS,EAAgB,EAAE;IACvG,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAC,GAAG,EAAE,IAAI,EAAE,eAAe,CAAC,GAAG,CAAC,WAAW,CAAC,EAAC,CAAC,CAAC,CAAA;IACrF,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;AAC7E,CAAC,CAAA;AAED,MAAM,YAAY,GAAG,KAAK,EAAE,GAAc,EAAE,MAAe,EAAiB,EAAE;IAC5E,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;QAC1B,IAAI,CAAC;YACH,GAAG,CAAC,MAAM,EAAE,CAAA;QACd,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,CAAC,IAAI,CAAC,4BAA4B,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAA;QAChE,CAAC;IACH,CAAC;IACD,IAAI,MAAM,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;QAC1B,IAAI,CAAC;YACH,GAAG,CAAC,OAAO,EAAE,CAAA;QACf,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,CAAC,IAAI,CAAC,6BAA6B,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAA;QACjE,CAAC;IACH,CAAC;AACH,CAAC,CAAA;AAED;;;GAGG;AACH,SAAS,WAAW,CAAC,aAA6B,EAAE,SAAsB;IACxE,gDAAgD;IAChD,MAAM,SAAS,GAAG,IAAI,GAAG,EAAqB,CAAA;IAC9C,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;QAC5B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC;YAAE,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC,CAAA;IAC1E,CAAC;IAED,qEAAqE;IACrE,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAqB,CAAA;IACtD,KAAK,MAAM,MAAM,IAAI,aAAa,CAAC,IAAI,EAAE,CAAC;QACxC,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;IACnD,CAAC;IAED,MAAM,eAAe,GAClB,gBAAgB,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,gBAAgB,CAAC,GAAG,CAA6B;QAClG,WAAW,CAAC,IAAI,CAAA;IAClB,MAAM,YAAY,GAAG,oBAAoB,CAAC,eAAe,CAAC,CAAA;IAC1D,MAAM,eAAe,GAAG,gBAAgB,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,IAAI,CAAA;IAC/F,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,kBAAkB,CAAC,GAAG,CAAC,KAAK,IAAI,CAAA;IAEzG,0EAA0E;IAC1E,0EAA0E;IAC1E,kEAAkE;IAClE,wEAAwE;IACxE,wEAAwE;IACxE,0EAA0E;IAC1E,wEAAwE;IACxE,mCAAmC;IACnC,EAAE;IACF,0EAA0E;IAC1E,2EAA2E;IAC3E,yEAAyE;IACzE,6EAA6E;IAC7E,6EAA6E;IAC7E,2EAA2E;IAC3E,yEAAyE;IACzE,4EAA4E;IAC5E,4CAA4C;IAC5C,OAAO,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;SAClC,MAAM,CACL,CAAC,GAAG,EAAE,EAAE,CACN,CAAC,iBAAiB,CAAC,GAAG,CAAC,WAAW,EAAE,eAAe,CAAC;QACpD,CAAC,kBAAkB,CAAC,GAAG,CAAC,WAAW,EAAE,eAAe,EAAE,gBAAgB,CAAC,CAC1E;SACA,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACX,MAAM,IAAI,GAAc;YACtB,GAAG,GAAG;YACN,UAAU,EAAE,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,UAAU,IAAI,GAAG,CAAC,UAAU;YAChF,aAAa,EAAE,qBAAqB,CAAC,kBAAkB,CAAC,GAAG,CAAC,oBAAoB,EAAE,YAAY,CAAC;YAC/F,kEAAkE;YAClE,yEAAyE;YACzE,qEAAqE;YACrE,qDAAqD;YACrD,MAAM,EAAE,mBAAmB,CAAC,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,eAAe,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACvF,qEAAqE;YACrE,4EAA4E;YAC5E,oEAAoE;YACpE,2EAA2E;YAC3E,4EAA4E;YAC5E,4EAA4E;YAC5E,sBAAsB;YACtB,YAAY,EAAE,GAAG,CAAC,WAAW,KAAK,aAAa,CAAC,mBAAmB;YACnE,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,IAAI,gBAAgB,EAAE;YACtD,UAAU,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,IAAI,iBAAiB,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC;SAC1F,CAAA;QACD,MAAM,IAAI,GAAG,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QACnD,OAAO,IAAI,IAAI,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA;IAC1D,CAAC,CAAC,CAAA;AACN,CAAC;AAED,8EAA8E;AAC9E,uEAAuE;AACvE,iFAAiF;AACjF,4EAA4E;AAC5E,gFAAgF;AAChF,+EAA+E;AAC/E,+EAA+E;AAC/E,0EAA0E;AAC1E,SAAS,eAAe,CAAC,CAAY,EAAE,CAAY;IACjD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAwB,CAAA;IACnD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAwB,CAAA;IACnD,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM;QAAE,OAAO,KAAK,CAAA;IAC/C,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,KAAK,eAAe,EAAE,CAAC;YAC1B,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,aAAa,CAAC;gBAAE,OAAO,KAAK,CAAA;YACvE,SAAQ;QACV,CAAC;QACD,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAAE,OAAO,KAAK,CAAA;IACjC,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,SAAS,kBAAkB,CAAC,CAAuB,EAAE,CAAuB;IAC1E,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACxB,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;QAAE,OAAO,KAAK,CAAA;IAC1B,OAAO,CACL,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,YAAY;QACjC,CAAC,CAAC,eAAe,CAAC,MAAM,KAAK,CAAC,CAAC,eAAe,CAAC,MAAM;QACrD,CAAC,CAAC,eAAe,CAAC,MAAM,KAAK,CAAC,CAAC,eAAe,CAAC,MAAM;QACrD,CAAC,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CACxC,CAAA;AACH,CAAC;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAiB,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;IACrE,IAAI,EAAE,EAAE;IACR,mBAAmB,EAAE,IAAI;IAEzB,OAAO,EAAE,KAAK,IAAI,EAAE;QAClB,MAAM,aAAa,GAAG,GAAG,EAAE,CAAA;QAC3B,MAAM,SAAS,GAAG,MAAM,WAAW,CAAC,oBAAoB,EAAE,CAAA;QAC1D,GAAG,CAAC,EAAC,IAAI,EAAE,WAAW,CAAC,aAAa,EAAE,SAAS,CAAC,EAAC,CAAC,CAAA;IACpD,CAAC;IAED,KAAK,EAAE,KAAK,EAAE,SAAoB,EAAE,IAAmB,EAAE,EAAE;QACzD,MAAM,KAAK,GAAG,GAAG,EAAE,CAAA;QACnB,MAAM,WAAW,GAAG,SAAS,CAAC,WAAW,CAAA;QACzC,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,WAAW,CAAC,CAAA;QACjE,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,OAAO,CAAC,KAAK,CAAC,2CAA2C,WAAW,EAAE,CAAC,CAAA;YACvE,OAAO,KAAK,CAAA;QACd,CAAC;QAED,0EAA0E;QAC1E,0EAA0E;QAC1E,wEAAwE;QACxE,6EAA6E;QAC7E,uEAAuE;QACvE,wCAAwC;QACxC,4EAA4E;QAC5E,qCAAqC;QACrC,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;YACtD,OAAO,CAAC,GAAG,CAAC,0BAA0B,WAAW,2BAA2B,CAAC,CAAA;YAC7E,OAAO,KAAK,CAAA;QACd,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;YAC/B,OAAO,CAAC,IAAI,CAAC,yDAAyD,WAAW,EAAE,CAAC,CAAA;YACpF,OAAO,KAAK,CAAA;QACd,CAAC;QAED,4EAA4E;QAC5E,qEAAqE;QACrE,6EAA6E;QAC7E,2EAA2E;QAC3E,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,YAAY,EAAE,CAAC;YACrC,mBAAmB,CAAC,IAAI,CAAC;gBACvB,IAAI,EAAE,sBAAsB;gBAC5B,WAAW;gBACX,MAAM,EAAE,GAAG,GAAG,CAAC,IAAI,IAAI,WAAW,+CAA+C;gBACjF,QAAQ,EAAE,EAAC,eAAe,EAAE,GAAG,CAAC,aAAa,EAAE,eAAe,IAAI,EAAE,EAAC;gBACrE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;aACtB,CAAC,CAAA;YACF,SAAS,CAAC,qBAAqB,EAAE,CAAC,GAAG,CAAC,CAAA;YACtC,OAAO,KAAK,CAAA;QACd,CAAC;QAED,4EAA4E;QAC5E,2EAA2E;QAC3E,oDAAoD;QACpD,IAAI,WAAW,CAAC,qBAAqB,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,MAAM,eAAe,CAAC,gBAAgB,EAAE,CAAC,EAAE,CAAC;YAClG,mBAAmB,CAAC,IAAI,CAAC;gBACvB,IAAI,EAAE,sBAAsB;gBAC5B,WAAW;gBACX,MAAM,EAAE,GAAG,GAAG,CAAC,IAAI,IAAI,WAAW,sDAAsD;gBACxF,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;aACtB,CAAC,CAAA;YACF,SAAS,CAAC,oBAAoB,EAAE,CAAC,GAAG,CAAC,CAAA;YACrC,OAAO,KAAK,CAAA;QACd,CAAC;QAED,uEAAuE;QACvE,wEAAwE;QACxE,aAAa;QACb,IAAI,GAAG,CAAC,UAAU;YAAE,iBAAiB,CAAC,aAAa,CAAC,WAAW,EAAE,KAAK,CAAC,CAAA;QAEvE,uEAAuE;QACvE,wEAAwE;QACxE,0EAA0E;QAC1E,kBAAkB;QAClB,SAAS,CAAC,eAAe,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;QAEtC,wEAAwE;QACxE,4BAA4B;QAC5B,gBAAgB,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,sBAAsB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;QAEjF,8EAA8E;QAC9E,0EAA0E;QAC1E,0EAA0E;QAC1E,oCAAoC;QACpC,IAAI,GAAG,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC;YACnC,gBAAgB,CAAC,WAAW,CAAC,CAAA;YAC7B,OAAO,IAAI,CAAA;QACb,CAAC;QAED,oEAAoE;QACpE,2EAA2E;QAC3E,0CAA0C;QAC1C,IAAI,GAAG,CAAC,IAAI,KAAK,UAAU,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YACxD,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CACpC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,WAAW,KAAK,WAAW,CAC1F,CAAA;YACD,KAAK,MAAM,CAAC,IAAI,YAAY,EAAE,CAAC;gBAC7B,MAAM,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAA;YACjC,CAAC;QACH,CAAC;QAED,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACV,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,KAAK,WAAW,CAAC,CAAC,CAAC,EAAC,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SACrG,CAAC,CAAC,CAAA;QAEH,gBAAgB,CAAC,WAAW,CAAC,CAAA;QAC7B,MAAM,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;QAE7B,wEAAwE;QACxE,0EAA0E;QAC1E,2EAA2E;QAC3E,2EAA2E;QAC3E,0EAA0E;QAC1E,kBAAkB;QAClB,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;YACd,IAAI,CAAC;gBACH,MAAM,eAAe,CAAC,aAAa,CAAC,WAAW,EAAE,EAAC,YAAY,EAAE,IAAI,EAAE,YAAY,IAAI,OAAO,EAAC,CAAC,CAAA;YACjG,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,wEAAwE;gBACxE,uEAAuE;gBACvE,yEAAyE;gBACzE,OAAO,CAAC,IAAI,CAAC,6CAA6C,WAAW,EAAE,EAAE,CAAC,CAAC,CAAA;gBAC3E,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACV,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,KAAK,WAAW,CAAC,CAAC,CAAC,EAAC,GAAG,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;iBACtG,CAAC,CAAC,CAAA;gBACH,+DAA+D;gBAC/D,MAAM,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;gBAC9B,OAAO,KAAK,CAAA;YACd,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAA;IACb,CAAC;IAED,IAAI,EAAE,KAAK,EAAE,WAAmB,EAAE,EAAE;QAClC,MAAM,KAAK,GAAG,GAAG,EAAE,CAAA;QACnB,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,WAAW,CAAC,CAAA;QACjE,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,OAAO,CAAC,KAAK,CAAC,2CAA2C,WAAW,EAAE,CAAC,CAAA;YACvE,OAAM;QACR,CAAC;QAED,uEAAuE;QACvE,wEAAwE;QACxE,IAAI,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,IAAI,iBAAiB,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YACxE,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC;gBACpB,iBAAiB,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,CAAA;gBAClD,mBAAmB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAA;gBAC1C,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACV,mBAAmB,EAAE,CAAC,CAAC,mBAAmB,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,mBAAmB;oBACzF,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACrB,CAAC,CAAC,WAAW,KAAK,WAAW,CAAC,CAAC,CAAC,EAAC,GAAG,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAC,CAAC,CAAC,CAAC,CAAC,CACvG;iBACF,CAAC,CAAC,CAAA;YACL,CAAC;YACD,OAAM;QACR,CAAC;QAED,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACV,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACrB,CAAC,CAAC,WAAW,KAAK,WAAW,CAAC,CAAC,CAAC,EAAC,GAAG,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAC,CAAC,CAAC,CAAC,CAAC,CAClG;SACF,CAAC,CAAC,CAAA;QAEH,qDAAqD;QACrD,8FAA8F;QAC9F,0EAA0E;QAC1E,IAAI,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrD,YAAY,CAAC,YAAY,EAAE,CAAA;QAC7B,CAAC;QACD,MAAM,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QAE9B,2EAA2E;QAC3E,qBAAqB;QACrB,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;YACd,IAAI,CAAC;gBACH,MAAM,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;YACzC,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,OAAO,CAAC,IAAI,CAAC,oCAAoC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAA;YACpE,CAAC;QACH,CAAC;IACH,CAAC;IAED,aAAa,EAAE,KAAK,EAAE,WAAmB,EAAE,EAAE;QAC3C,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,WAAW,CAAC,CAAA;QACjE,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,OAAO,CAAC,KAAK,CAAC,0CAA0C,WAAW,EAAE,CAAC,CAAA;YACtE,OAAM;QACR,CAAC;QAED,kEAAkE;QAClE,yEAAyE;QACzE,wEAAwE;QACxE,mEAAmE;QACnE,uEAAuE;QACvE,6DAA6D;QAC7D,gBAAgB,CAAC,WAAW,CAAC,CAAA;QAC7B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACV,mBAAmB,EAAE,WAAW;YAChC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAC,GAAG,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,WAAW,KAAK,WAAW,EAAC,CAAC,CAAC;SAC/E,CAAC,CAAC,CAAA;QAEH,yEAAyE;QACzE,2EAA2E;QAC3E,0EAA0E;QAC1E,IAAI,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,UAAU;YAAE,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAC,cAAc,EAAE,IAAI,EAAC,CAAC,CAAA;IAClF,CAAC;IAED,eAAe,EAAE,GAAG,EAAE;QACpB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACV,mBAAmB,EAAE,IAAI;YACzB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC;gBACtC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAC,GAAG,CAAC,EAAE,YAAY,EAAE,KAAK,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACvE,CAAC,CAAC,CAAC,CAAC,IAAI;SACX,CAAC,CAAC,CAAA;IACL,CAAC;IAED,OAAO,EAAE,GAAG,EAAE;QACZ,OAAO,GAAG,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE;YAC9B,qEAAqE;YACrE,oEAAoE;YACpE,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAA;YACnF,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;gBACxB,MAAM,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAA;YACjC,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,OAAO,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,cAAc,CAAC,GAAG,EAAE,IAAI,CAAC;IAE7D,SAAS,EAAE,CAAC,WAAW,EAAE,OAAO,EAAE,EAAE;QAClC,OAAO,GAAG,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE;YAC9B,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,SAAS,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;YAC7D,IAAI,GAAG,CAAC,QAAQ,EAAE;gBAAE,MAAM,GAAG,CAAC,KAAK,CAAA;YACnC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,WAAW,CAAC,EAAC,CAAC,CAAC,CAAA;QAC3E,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,cAAc,EAAE,KAAK,EAAE,WAAmB,EAAE,UAAkB,EAAE,EAAE;QAChE,OAAO,CAAC,IAAI,CAAC,GAAG,WAAW,aAAa,EAAE,UAAU,CAAC,CAAA;QACrD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACV,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,KAAK,WAAW,CAAC,CAAC,CAAC,EAAC,GAAG,CAAC,EAAE,UAAU,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SAClF,CAAC,CAAC,CAAA;IACL,CAAC;IAED,eAAe,EAAE,CAAC,WAAmB,EAAE,MAAe,EAAE,EAAE;QACxD,iBAAiB,CAAC,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;QAC1C,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACV,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,KAAK,WAAW,CAAC,CAAC,CAAC,EAAC,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;SACtF,CAAC,CAAC,CAAA;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,WAAW,SAAS,EAAE,MAAM,CAAC,CAAA;QAC7C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAA;YAC/B,IAAI,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC;gBACrB,OAAO,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC,CAAA;gBAClC,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;YAC/B,CAAC;QACH,CAAC;IACH,CAAC;IAED,eAAe,EAAE,CAAC,WAAmB,EAAW,EAAE;QAChD,MAAM,MAAM,GAAG,iBAAiB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QACjD,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,MAAM,CAAA;QACvC,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAU,GAAG,WAAW,SAAS,CAAC,CAAA;QAC1D,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAA;QACxE,iBAAiB,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,CAAA;QACzC,OAAO,KAAK,CAAA;IACd,CAAC;IAED,WAAW,EAAE,KAAK,EAAE,WAAmB,EAAE,MAAe,EAAE,EAAE;QAC1D,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,WAAW,CAAC,CAAA;QACjE,IAAI,CAAC,GAAG;YAAE,OAAM;QAChB,4EAA4E;QAC5E,MAAM,OAAO,GACX,MAAM,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW;YAChC,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,WAAW,KAAK,WAAW,CAAC;YACjG,CAAC,CAAC,EAAE,CAAA;QACR,oBAAoB,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;QACzC,KAAK,MAAM,KAAK,IAAI,OAAO;YAAE,oBAAoB,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,CAAA;QAC3E,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACV,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBACrB,IAAI,CAAC,CAAC,WAAW,KAAK,WAAW;oBAAE,OAAO,EAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAC,CAAA;gBAClE,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;oBAAE,OAAO,EAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAC,CAAA;gBACvD,OAAO,CAAC,CAAA;YACV,CAAC,CAAC;SACH,CAAC,CAAC,CAAA;QACH,IAAI,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO;YAAE,MAAM,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAC,cAAc,EAAE,IAAI,EAAC,CAAC,CAAA;IAC5E,CAAC;IAED,eAAe,EAAE,CAAC,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,EAAE;QACtD,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,WAAW,CAAC,CAAA;QACjE,MAAM,MAAM,GAAG,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAA;QAC3D,IAAI,CAAC,MAAM,EAAE,UAAU;YAAE,OAAO,KAAK,CAAA;QACrC,IAAI,MAAM,CAAC,WAAW,KAAK,WAAW;YAAE,OAAO,WAAW,CAAA;QAC1D,sBAAsB,CAAC,WAAW,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAA;QAC1D,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACV,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACrB,CAAC,CAAC,WAAW,KAAK,WAAW;gBAC3B,CAAC,CAAC,EAAC,GAAG,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAC,GAAG,CAAC,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAC;gBACvF,CAAC,CAAC,CAAC,CACN;SACF,CAAC,CAAC,CAAA;QACH,OAAO,WAAW,CAAA;IACpB,CAAC;IAED,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,EAAC,IAAI,EAAC,CAAC;CAC/B,CAAC,CAAC,CAAA;AAEH,6EAA6E;AAC7E,+EAA+E;AAC/E,4EAA4E;AAC5E,mBAAmB;AACnB,SAAS,wBAAwB;IAC/B,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,sBAAsB,CAAC,MAAM,EAAE,CAAC,CAAA;IACxD,MAAM,SAAS,GAAG,gBAAgB,EAAE,CAAA;IACpC,MAAM,KAAK,GAAG,iBAAiB,CAAC,QAAQ,EAAE,CAAA;IAC1C,IAAI,OAAO,GAAG,KAAK,CAAA;IACnB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACrC,IAAI,CAAC,GAAG,CAAC,KAAK;YAAE,OAAO,GAAG,CAAA;QAC1B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QACzC,MAAM,MAAM,GAAG,IAAI,IAAI,SAAS,CAAA;QAChC,MAAM,UAAU,GAAG,IAAI,IAAI,iBAAiB,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QAC1E,IAAI,GAAG,CAAC,OAAO,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,KAAK,CAAC,KAAK,MAAM,IAAI,CAAC,GAAG,CAAC,UAAU,IAAI,KAAK,CAAC,KAAK,UAAU;YAAE,OAAO,GAAG,CAAA;QACpH,OAAO,GAAG,IAAI,CAAA;QACd,OAAO,EAAC,GAAG,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAC,CAAA;IACpD,CAAC,CAAC,CAAA;IACF,IAAI,OAAO,EAAE,CAAC;QACZ,iBAAiB,CAAC,QAAQ,CAAC,EAAC,IAAI,EAAE,OAAO,EAAC,CAAC,CAAA;IAC7C,CAAC;AACH,CAAC;AACD,sBAAsB,CAAC,SAAS,CAAC,wBAAwB,CAAC,CAAA;AAC1D,iBAAiB,CAAC,SAAS,CAAC,wBAAwB,CAAC,CAAA;AACrD,qBAAqB,CAAC,wBAAwB,CAAC,CAAA;AAE/C,4EAA4E;AAC5E,0EAA0E;AAC1E,wEAAwE;AACxE,6EAA6E;AAC7E,yEAAyE;AACzE,yEAAyE;AACzE,iBAAiB,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE;IACpC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;IACrG,mBAAmB,CAAC,eAAe,CAAC,IAAI,EAAE,WAAW,IAAI,IAAI,CAAC,CAAA;AAChE,CAAC,CAAC,CAAA;AAEF,qDAAqD;AACrD,WAAW,CAAC,SAAS,CAAC,GAAG,EAAE;IACzB,KAAK,iBAAiB,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,CAAA;AAC7C,CAAC,CAAC,CAAA;AAEF,+EAA+E;AAC/E,gBAAgB,CAAC,SAAS,CACxB,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAC1D,GAAG,EAAE;IACH,KAAK,iBAAiB,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,CAAA;AAC7C,CAAC,CACF,CAAA;AAED,6EAA6E;AAC7E,8EAA8E;AAC9E,2DAA2D;AAC3D,gBAAgB,CAAC,SAAS,CACxB,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,IAAI,EAC5D,CAAC,OAAO,EAAE,EAAE;IACV,KAAK,CAAC,KAAK,IAAI,EAAE;QACf,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,KAAK,GAAG,iBAAiB,CAAC,QAAQ,EAAE,CAAA;YAC1C,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,kBAAkB,CAAC,GAAG,CAAC,KAAK,IAAI,CAAA;YACzG,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;gBAC7B,MAAM,KAAK,GACT,iBAAiB,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,kBAAkB,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,EAAE,gBAAgB,CAAC,CAAA;gBAC3G,IAAI,GAAG,CAAC,OAAO,IAAI,KAAK;oBAAE,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;YAC7D,CAAC;QACH,CAAC;QACD,MAAM,iBAAiB,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,CAAA;IAC9C,CAAC,CAAC,EAAE,CAAA;AACN,CAAC,CACF,CAAA;AAED,2EAA2E;AAC3E,4BAA4B;AAC5B,gBAAgB,CAAC,SAAS,CACxB,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,kBAAkB,CAAC,GAAG,CAAC,KAAK,IAAI,EACrE,GAAG,EAAE;IACH,KAAK,iBAAiB,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,CAAA;AAC7C,CAAC,CACF,CAAA;AAED,8EAA8E;AAC9E,eAAe;AACf,8EAA8E;AAE9E,MAAM,CAAC,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,iBAAiB,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;AACrE,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAG,EAAE,CAAC,iBAAiB,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;AACvE,MAAM,CAAC,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,iBAAiB,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;AACrE,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,EAAE,CAAC,iBAAiB,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAA;AACvF,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,EAAE,CAAC,iBAAiB,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,eAAe,CAAC,CAAA;AAC3F,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,EAAE,CAAC,iBAAiB,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;AAC3E,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,EAAE,CAAC,iBAAiB,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;AAC3E,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,EAAE,CAAC,iBAAiB,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;AAC3E,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,EAAE,CAAC,iBAAiB,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;AAE/E,0FAA0F;AAC1F,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,EAAE;IAChC,MAAM,IAAI,GAAG,OAAO,EAAE,CAAA;IACtB,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;AACpF,CAAC,CAAA;AAED,mGAAmG;AACnG,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,EAAE;IAChC,MAAM,IAAI,GAAG,OAAO,EAAE,CAAA;IACtB,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;AACnF,CAAC,CAAA;AAED,wEAAwE;AACxE,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,EAAE;IACzC,MAAM,IAAI,GAAG,OAAO,EAAE,CAAA;IACtB,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;AACjF,CAAC,CAAA;AAED,kFAAkF;AAClF,MAAM,eAAe,GAAG,CAAC,GAAc,EAAW,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,YAAY,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,CAAA;AAE1G,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,EAAE;IAC1C,MAAM,IAAI,GAAG,OAAO,EAAE,CAAA;IACtB,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;AACzF,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,EAAE;IACpC,MAAM,IAAI,GAAG,OAAO,EAAE,CAAA;IACtB,OAAO,OAAO,CACZ,GAAG,EAAE,CAAC,CAAC;QACL,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC;QACjE,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;KACrE,CAAC,EACF,CAAC,IAAI,CAAC,CACP,CAAA;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,EAAE;IACzC,MAAM,IAAI,GAAG,OAAO,EAAE,CAAA;IACtB,OAAO,OAAO,CACZ,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,IAAI,EAC1G,CAAC,IAAI,CAAC,CACP,CAAA;AACH,CAAC,CAAA;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,EAAE;IACnC,MAAM,IAAI,GAAG,OAAO,EAAE,CAAA;IACtB,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;AAC5E,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,4BAA4B,GAAG,GAAG,EAAE;IAC/C,MAAM,IAAI,GAAG,OAAO,EAAE,CAAA;IACtB,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;AAChG,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,EAAE;IACnC,MAAM,IAAI,GAAG,OAAO,EAAE,CAAA;IACtB,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;AAC/D,CAAC,CAAA","sourcesContent":["/**\n * Engine apps store — runtime state of installed and local applets.\n *\n * The OEM-facing API: subscribe to the running set, install/uninstall\n * miniapps, start/stop them. The store delegates install plumbing to\n * AppRegistry, and exposes hooks (`useApps`, `useStart`, `useStop`,\n * `useRefresh`, `useStopAll`) that the host UI can read.\n *\n * Source of `apps`:\n * - Local: appRegistry.getInstalledMiniapps() (always)\n */\n\nimport {useMemo} from \"react\"\nimport {AsyncResult, Result, result as Res} from \"typesafe-ts\"\nimport {create} from \"zustand\"\n\nimport type {ClientApp} from \"../types/applet\"\nimport {DeviceTypes} from \"../types/enums\"\nimport {getModelCapabilities} from \"../types/hardware\"\nimport {HardwareCompatibility, type CompatibilityResult} from \"../utils/hardware/hardware\"\nimport {storage} from \"../utils/storage/storage\"\nimport appRegistry, {saveAlwaysOnOverride, saveWidgetExpandChoice} from \"../services/AppRegistry\"\nimport localDisplayManager from \"../services/LocalDisplayManager\"\nimport {islandNotifications} from \"../services/NotificationsEmitter\"\nimport sttModelManager from \"../services/STTModelManager\"\nimport {miniappLauncher} from \"../services/MiniappLauncher\"\nimport {isMiniappsPaused, onMiniappsPauseChange} from \"../services/MiniappPauseCoordinator\"\nimport {miniappRunningRegistry} from \"../services/MiniappRunningRegistry\"\nimport {miniappWidgetMode} from \"../services/MiniappWidgetMode\"\nimport {defaultHiddenStatus, isGatedByDevTools, isGatedUntilPaired, resolveHiddenStatus} from \"./appVisibility\"\nimport {SETTINGS, useSettingsStore} from \"./settings\"\nimport BluetoothSdk from \"@glassly/bluetooth-sdk\"\nimport type {MiniappLaunchSource} from \"@glassly/miniapp\"\n\n// ---------------------------------------------------------------------------\n// Configuration / hooks\n// ---------------------------------------------------------------------------\n\nexport interface StartOptions {\n skipNavigation?: boolean\n /** Reported to the miniapp on connect. Defaults to \"phone\". */\n launchSource?: MiniappLaunchSource\n}\n\nexport interface AppStoreHooks {\n /**\n * A start was blocked because the app is hardware-incompatible. Engine made\n * the decision (and raised the `version_incompatible` notification); the host\n * renders its branded alert here.\n */\n onIncompatibleBlocked?: (app: ClientApp) => void\n /**\n * A start was blocked because the app requires the on-device STT model\n * (declared at registration — see AppRegistry.installOfflineApp) and none is\n * installed. Engine decided via its model manager; the host renders the\n * alert / settings navigation here.\n */\n onMissingSpeechModel?: (app: ClientApp) => void\n /**\n * An open request passed the gates — fired on EVERY open, including\n * re-opening an already-running app, so the host's navigation / open\n * animation always plays.\n */\n onOpenRequested?: (app: ClientApp, opts?: StartOptions) => void\n}\n\nlet hostHooks: AppStoreHooks = {}\n\nexport function installAppStoreHooks(hooks: AppStoreHooks): void {\n hostHooks = {...hostHooks, ...hooks}\n}\n\n// ---------------------------------------------------------------------------\n// Store\n// ---------------------------------------------------------------------------\n\ninterface AppStatusState {\n apps: ClientApp[]\n /**\n * Source of truth for which app is foregrounded in the Compositor overlay.\n * The per-app `foregrounded` boolean is derived from this in `projectApps`\n * so a refresh can never drop the flag when an app is transiently missing\n * from one of the two refresh passes (local-only then merged). See\n * `projectApps` / `setForeground` / `clearForeground`.\n */\n foregroundedPackage: string | null\n refresh: () => Promise<void>\n /** Resolves true if the app actually started; false if a host gate aborted it or its JS context failed to spawn. */\n start: (app: ClientApp, opts?: StartOptions) => Promise<boolean>\n stop: (packageName: string) => Promise<void>\n setForeground: (packageName: string) => Promise<void>\n clearForeground: () => void\n stopAll: () => AsyncResult<void, Error>\n install: (url: string, opts?: {versionOverride?: string}) => AsyncResult<void, Error>\n uninstall: (packageName: string, version?: string) => AsyncResult<void, Error>\n saveScreenshot: (packageName: string, screenshot: string) => Promise<void>\n setHiddenStatus: (packageName: string, status: boolean) => void\n getHiddenStatus: (packageName: string) => boolean\n /**\n * Mark a miniapp Always On: it starts at launch and only stops from the\n * app switcher's Always On pill (its card cannot be swiped away and the\n * capsule close minimizes it). Turning it on starts the app; turning it\n * off leaves it running. Persists the wearer's choice beside the hidden flag.\n */\n setAlwaysOn: (packageName: string, status: boolean) => Promise<void>\n /**\n * Whether a tap on one of the miniapp's dashboard widgets expands it to the\n * full screen. Only widgets that list `EX` expand; false for the rest.\n * Persists the choice and answers the setting now in force.\n */\n setWidgetExpand: (packageName: string, widgetId: string, expandOnTap: boolean) => boolean\n /** Replace the whole apps array. Hosts use this when their extra source changes. */\n setApps: (apps: ClientApp[]) => void\n}\n\nexport const DUMMY_APPLET: ClientApp = {\n packageName: \"\",\n name: \"\",\n webviewUrl: \"\",\n logoUrl: \"\",\n type: \"standard\",\n permissions: [],\n running: false,\n loading: false,\n healthy: true,\n hardwareRequirements: [],\n offline: true,\n offlineRoute: \"\",\n local: false,\n hidden: false,\n}\n\nexport type OrderMap = Record<string, number>\nconst APP_ORDER_KEY = \"foreground_apps_order\"\n\nexport const saveAppsOrder = (orderMap: OrderMap): Result<void, Error> => {\n return storage.save(APP_ORDER_KEY, orderMap)\n}\n\nexport const getAppsOrder = (): Result<OrderMap, Error> => {\n return storage.load<OrderMap>(APP_ORDER_KEY)\n}\n\n// In-memory cache for hidden flags. `projectApps` reads getHiddenStatus once\n// per app per refresh — without a cache that was a synchronous JNI hop per\n// app per refresh on a hot UI path. Kept consistent with disk by writing\n// through in setHiddenStatus. Map of packageName → hidden boolean.\nconst hiddenStatusCache = new Map<string, boolean>()\n\nconst getRawPackageNamePriority = (pkg: string): number => {\n if (pkg.includes(\"@empty\")) {\n return 1000\n }\n return 0\n}\n\nexport const sortAppsByPackageNamePriority = (a: ClientApp, b: ClientApp): number => {\n const pa = getRawPackageNamePriority(a.packageName)\n const pb = getRawPackageNamePriority(b.packageName)\n if (pa !== pb) {\n return pa - pb\n }\n return a.name.localeCompare(b.name)\n}\n\nexport const saveLastOpenTime = (packageName: string): void => {\n storage.save(`${packageName}_last_open_time`, Date.now())\n}\n\nexport const getLastOpenTime = (packageName: string): number => {\n const res = storage.load<number>(`${packageName}_last_open_time`)\n if (res.is_ok()) return res.value\n return 0\n}\n\nexport const sortAppsByLastOpenTime = async <T extends {packageName: string}>(apps: T[]): Promise<T[]> => {\n const timestamps = apps.map((app) => ({app, time: getLastOpenTime(app.packageName)}))\n return timestamps.sort((a, b) => a.time - b.time).map((entry) => entry.app)\n}\n\nconst startStopApp = async (app: ClientApp, status: boolean): Promise<void> => {\n if (!status && app.onStop) {\n try {\n app.onStop()\n } catch (e) {\n console.warn(`ISLAND: onStop threw for ${app.packageName}`, e)\n }\n }\n if (status && app.onStart) {\n try {\n app.onStart()\n } catch (e) {\n console.warn(`ISLAND: onStart threw for ${app.packageName}`, e)\n }\n }\n}\n\n/**\n * Build the final `apps` array for the store from the installed/offline app\n * source. Pure — same inputs -> same outputs.\n */\nfunction projectApps(previousState: AppStatusState, localApps: ClientApp[]): ClientApp[] {\n // Dedupe by packageName, keep first occurrence.\n const byPackage = new Map<string, ClientApp>()\n for (const app of localApps) {\n if (!byPackage.has(app.packageName)) byPackage.set(app.packageName, app)\n }\n\n // Index previous snapshot for cheap lookups (was O(N²) via .find()).\n const previousByPackage = new Map<string, ClientApp>()\n for (const oldApp of previousState.apps) {\n previousByPackage.set(oldApp.packageName, oldApp)\n }\n\n const defaultWearable =\n (useSettingsStore.getState().getSetting(SETTINGS.default_wearable.key) as DeviceTypes | undefined) ||\n DeviceTypes.NONE\n const capabilities = getModelCapabilities(defaultWearable)\n const devToolsEnabled = useSettingsStore.getState().getSetting(SETTINGS.dev_tools.key) === true\n const hasPairedGlasses = useSettingsStore.getState().getSetting(SETTINGS.has_paired_glasses.key) === true\n\n // Single pass: dedupe → screenshot carry-over → compat → hidden, all into\n // fresh objects. The previous in-place mutation re-used object references\n // across refreshes, which broke React.memo / referential-equality\n // memoization downstream (every refresh propagated re-renders even when\n // nothing meaningful changed) AND tripped Reanimated's \"tried to modify\n // key of an object already passed to a worklet\" warning whenever the home\n // screen's animated app cards held a reference to a previous snapshot's\n // app object that we then mutated.\n //\n // Identity stability: refresh() is event-driven and fires repeatedly (and\n // twice per cycle via the local-only → merged two-pass emit). If we always\n // returned fresh objects, every poll changed the identity of EVERY app —\n // which re-rendered the Compositor (via useForegroundApp) mid-slide and made\n // the open/close animation hitch, and churned the home grid / switcher pill.\n // So we build the candidate object, then REUSE the previous reference when\n // nothing meaningful changed. Same pattern as the miniappRunningRegistry\n // projection below. A stable foreground-app reference lets the Compositor's\n // slide run uninterrupted on the UI thread.\n return Array.from(byPackage.values())\n .filter(\n (app) =>\n !isGatedByDevTools(app.packageName, devToolsEnabled) &&\n !isGatedUntilPaired(app.packageName, devToolsEnabled, hasPairedGlasses),\n )\n .map((app) => {\n const next: ClientApp = {\n ...app,\n screenshot: previousByPackage.get(app.packageName)?.screenshot ?? app.screenshot,\n compatibility: HardwareCompatibility.checkCompatibility(app.hardwareRequirements, capabilities),\n // A registry source can force an app off the primary home screen.\n // Compose that gate with the user's persisted home-screen layout instead\n // of replacing it, otherwise a default-false persisted value makes a\n // source-hidden app visible again during projection.\n hidden: resolveHiddenStatus(app.hidden, previousState.getHiddenStatus(app.packageName)),\n // Derive the foreground flag from the store's single source of truth\n // (`foregroundedPackage`), NOT from the previous snapshot. Carrying it over\n // per-app meant a refresh that momentarily omitted an app (e.g. the\n // two-pass local-only → merged emit) would reset its flag to false — which\n // raced OfflineAppHost's interceptor guard and made the hosted miniapp fall\n // through to the root router (restart). Deriving here keeps the flag stable\n // across both passes.\n foregrounded: app.packageName === previousState.foregroundedPackage,\n paused: app.local && app.running && isMiniappsPaused(),\n widgetOnly: !!app.local && app.running && miniappWidgetMode.isWidgetOnly(app.packageName),\n }\n const prev = previousByPackage.get(app.packageName)\n return prev && shallowEqualApp(prev, next) ? prev : next\n })\n}\n\n// Cheap equality check used by projectApps to preserve object identity across\n// refreshes when nothing meaningful changed. Most keys are compared by\n// reference (the source app's nested fields — permissions, hardwareRequirements,\n// parameters — are reference-stable within a refresh). The ONE exception is\n// `compatibility`, which projectApps recomputes into a fresh object every call;\n// comparing it by reference would always differ and defeat the whole point. We\n// compare it structurally instead so identity is only broken when the device's\n// actual compatibility verdict changes (e.g. glasses connect/disconnect).\nfunction shallowEqualApp(a: ClientApp, b: ClientApp): boolean {\n const aKeys = Object.keys(a) as (keyof ClientApp)[]\n const bKeys = Object.keys(b) as (keyof ClientApp)[]\n if (aKeys.length !== bKeys.length) return false\n for (const k of aKeys) {\n if (k === \"compatibility\") {\n if (!compatibilityEqual(a.compatibility, b.compatibility)) return false\n continue\n }\n if (a[k] !== b[k]) return false\n }\n return true\n}\n\nfunction compatibilityEqual(a?: CompatibilityResult, b?: CompatibilityResult): boolean {\n if (a === b) return true\n if (!a || !b) return false\n return (\n a.isCompatible === b.isCompatible &&\n a.missingRequired.length === b.missingRequired.length &&\n a.missingOptional.length === b.missingOptional.length &&\n a.warnings.length === b.warnings.length\n )\n}\n\nexport const useAppStatusStore = create<AppStatusState>((set, get) => ({\n apps: [],\n foregroundedPackage: null,\n\n refresh: async () => {\n const previousState = get()\n const localApps = await appRegistry.getInstalledMiniapps()\n set({apps: projectApps(previousState, localApps)})\n },\n\n start: async (clientApp: ClientApp, opts?: StartOptions) => {\n const state = get()\n const packageName = clientApp.packageName\n const app = state.apps.find((a) => a.packageName === packageName)\n if (!app) {\n console.error(`ISLAND: app not found for package name: ${packageName}`)\n return false\n }\n\n // Skip spawning a NEW app while another is mid-launch — concurrent spawns\n // race the foreground-only-one teardown. This is checked BEFORE the gates\n // and the onOpenRequested seam (which navigates/foregrounds) so a gated\n // launch doesn't paint a splash it can't back. Re-opening an already-running\n // app is exempt: it has nothing to spawn, so it skips this gate and is\n // allowed to re-navigate/animate below.\n // That exemption is the fix for the \"second tap during another app's launch\n // window silently does nothing\" bug.\n if (!app.running && state.apps.some((a) => a.loading)) {\n console.log(`ISLAND: skipping start ${packageName} — another app is loading`)\n return false\n }\n\n if (!app.offline && !app.local) {\n console.warn(`ISLAND: cloud-v1 app entries are no longer supported: ${packageName}`)\n return false\n }\n\n // Hardware-compatibility gate — engine decides and blocks; the host renders\n // its branded alert via onIncompatibleBlocked (and/or the structured\n // notification below). `!isCompatible` (not `=== false`) keeps the semantics\n // of the host gate this replaces: an unknown verdict blocks, not launches.\n if (!app.compatibility?.isCompatible) {\n islandNotifications.emit({\n kind: \"version_incompatible\",\n packageName,\n reason: `${app.name ?? packageName} is not compatible with the connected glasses`,\n metadata: {missingRequired: app.compatibility?.missingRequired ?? []},\n timestamp: Date.now(),\n })\n hostHooks.onIncompatibleBlocked?.(app)\n return false\n }\n\n // Missing-speech-model gate for apps registered with requiresLocalSttModel.\n // Engine decides via its own model manager; the host renders the alert and\n // any settings navigation via onMissingSpeechModel.\n if (appRegistry.requiresLocalSttModel(packageName) && !(await sttModelManager.isModelAvailable())) {\n islandNotifications.emit({\n kind: \"missing_speech_model\",\n packageName,\n reason: `${app.name ?? packageName} needs an on-device speech model before it can start`,\n timestamp: Date.now(),\n })\n hostHooks.onMissingSpeechModel?.(app)\n return false\n }\n\n // An app running only for its widget is promoted before the host hook:\n // the hook may foreground it, and setForeground sends a widget-only app\n // back here.\n if (app.widgetOnly) miniappWidgetMode.setWidgetOnly(packageName, false)\n\n // Host navigation / open-animation seam. Runs on EVERY accepted open —\n // including re-opening an already-running app — so the animation always\n // plays (BuiltInMiniappCatalog.navigateForApp: overlay apps setForeground\n // for the slide).\n hostHooks.onOpenRequested?.(app, opts)\n\n // First-activation mark (moved from the host's old beforeStart — engine\n // owns the settings store).\n useSettingsStore.getState().setSetting(SETTINGS.has_ever_activated_app.key, true)\n\n // If the tapped app is already running, this is a re-open: the nav/foreground\n // above already drove the animation, and there's nothing to spawn. Short-\n // circuit before the spawn pipeline. A promoted app keeps its context but\n // still takes the foreground below.\n if (app.running && !app.widgetOnly) {\n saveLastOpenTime(packageName)\n return true\n }\n\n // Only-one rules: one standard app in the foreground, one dashboard\n // drawing the overlay. Starting another stops the one running. Widget-only\n // peers hold no foreground, so they stay.\n if (app.type === \"standard\" || app.type === \"dashboard\") {\n const runningPeers = state.apps.filter(\n (a) => a.running && !a.widgetOnly && a.type === app.type && a.packageName !== packageName,\n )\n for (const r of runningPeers) {\n await get().stop(r.packageName)\n }\n }\n\n set((s) => ({\n apps: s.apps.map((a) => (a.packageName === packageName ? {...a, running: true, loading: false} : a)),\n }))\n\n saveLastOpenTime(packageName)\n await startStopApp(app, true)\n\n // Spawn the background JS context for local miniapps. This used to be a\n // side effect of LocalMiniappView mounting on foreground; pulling it here\n // lets start() actually run the app even when nothing foregrounds it (e.g.\n // a system app launching another miniapp via session.miniapps). Idempotent\n // with the view's own ensureRunning; a no-op for native offline built-ins\n // (no JS bundle).\n if (app.local) {\n try {\n await miniappLauncher.ensureRunning(packageName, {launchSource: opts?.launchSource ?? \"phone\"})\n } catch (e) {\n // Spawn / bundle-resolve failed — revert the optimistic running flag so\n // the home list and miniapps.list() don't show a \"running\" app with no\n // JS context, and report failure to the caller (session.miniapps.start).\n console.warn(`ISLAND: launcher.ensureRunning failed for ${packageName}`, e)\n set((s) => ({\n apps: s.apps.map((a) => (a.packageName === packageName ? {...a, running: false, loading: false} : a)),\n }))\n // onStart already ran before the spawn; run onStop to undo it.\n await startStopApp(app, false)\n return false\n }\n }\n\n return true\n },\n\n stop: async (packageName: string) => {\n const state = get()\n const app = state.apps.find((a) => a.packageName === packageName)\n if (!app) {\n console.error(`ISLAND: app not found for package name: ${packageName}`)\n return\n }\n\n // A placed widget provider is the dashboard's to keep: closing it from\n // the tray takes its card and its frame, and it runs on in widget mode.\n if (app.local && app.running && miniappWidgetMode.isPlaced(packageName)) {\n if (!app.widgetOnly) {\n miniappWidgetMode.setWidgetOnly(packageName, true)\n localDisplayManager.onUnmount(packageName)\n set((s) => ({\n foregroundedPackage: s.foregroundedPackage === packageName ? null : s.foregroundedPackage,\n apps: s.apps.map((a) =>\n a.packageName === packageName ? {...a, screenshot: undefined, foregrounded: false, loading: false} : a,\n ),\n }))\n }\n return\n }\n\n set((s) => ({\n apps: s.apps.map((a) =>\n a.packageName === packageName ? {...a, running: false, screenshot: undefined, loading: false} : a,\n ),\n }))\n\n // if there are no apps running, call clearDisplay():\n // read fresh state via get() — `state` was captured before the set() above, so it still shows\n // this app as running and would never reach 0 when stopping the last app.\n if (get().apps.filter((a) => a.running).length === 0) {\n BluetoothSdk.clearDisplay()\n }\n await startStopApp(app, false)\n\n // Tear down the background JS context for local miniapps. No-op for native\n // offline built-ins.\n if (app.local) {\n try {\n await miniappLauncher.stop(packageName)\n } catch (e) {\n console.warn(`ISLAND: launcher.stop failed for ${packageName}`, e)\n }\n }\n },\n\n setForeground: async (packageName: string) => {\n const app = get().apps.find((a) => a.packageName === packageName)\n if (!app) {\n console.error(`ISLAND: setForeground — app not found: ${packageName}`)\n return\n }\n\n // Flip the foreground flag synchronously so the Compositor's open\n // animation starts on the same frame as the tap. We do NOT await start()\n // first — that gated the flag (and thus the animation) behind the whole\n // JSContext-spawn chain, which was the perceived launch delay. The\n // Compositor/LocalMiniappView already handle the spawn being in-flight\n // (the phase machine), so foregrounding needn't wait for it.\n saveLastOpenTime(packageName)\n set((s) => ({\n foregroundedPackage: packageName,\n apps: s.apps.map((a) => ({...a, foregrounded: a.packageName === packageName})),\n }))\n\n // The wearer is in this app now: one running only for its widget becomes\n // a normal run. start() promotes it, stops the standard peer and keeps the\n // context. Fire-and-forget after the flag flip so it doesn't block paint.\n if (app.running && app.widgetOnly) void get().start(app, {skipNavigation: true})\n },\n\n clearForeground: () => {\n set((s) => ({\n foregroundedPackage: null,\n apps: s.apps.some((a) => a.foregrounded)\n ? s.apps.map((a) => (a.foregrounded ? {...a, foregrounded: false} : a))\n : s.apps,\n }))\n },\n\n stopAll: () => {\n return Res.try_async(async () => {\n // Always On apps stay up; they stop one at a time from the switcher.\n // Widget-only apps have no card to close; they are the dashboard's.\n const running = get().apps.filter((a) => a.running && !a.alwaysOn && !a.widgetOnly)\n for (const a of running) {\n await get().stop(a.packageName)\n }\n })\n },\n\n install: (url, opts) => appRegistry.installFromUrl(url, opts),\n\n uninstall: (packageName, version) => {\n return Res.try_async(async () => {\n const res = await appRegistry.uninstall(packageName, version)\n if (res.is_error()) throw res.error\n set((s) => ({apps: s.apps.filter((a) => a.packageName !== packageName)}))\n })\n },\n\n saveScreenshot: async (packageName: string, screenshot: string) => {\n storage.save(`${packageName}_screenshot`, screenshot)\n set((s) => ({\n apps: s.apps.map((a) => (a.packageName === packageName ? {...a, screenshot} : a)),\n }))\n },\n\n setHiddenStatus: (packageName: string, status: boolean) => {\n hiddenStatusCache.set(packageName, status)\n set((s) => ({\n apps: s.apps.map((a) => (a.packageName === packageName ? {...a, hidden: status} : a)),\n }))\n storage.save(`${packageName}_hidden`, status)\n if (!status) {\n const orderMap = getAppsOrder()\n if (orderMap.is_ok()) {\n delete orderMap.value[packageName]\n saveAppsOrder(orderMap.value)\n }\n }\n },\n\n getHiddenStatus: (packageName: string): boolean => {\n const cached = hiddenStatusCache.get(packageName)\n if (cached !== undefined) return cached\n const res = storage.load<boolean>(`${packageName}_hidden`)\n const value = res.is_ok() ? res.value : defaultHiddenStatus(packageName)\n hiddenStatusCache.set(packageName, value)\n return value\n },\n\n setAlwaysOn: async (packageName: string, status: boolean) => {\n const app = get().apps.find((a) => a.packageName === packageName)\n if (!app) return\n // One dashboard is Always On at a time: marking this one clears the others.\n const cleared =\n status && app.type === \"dashboard\"\n ? get().apps.filter((a) => a.type === \"dashboard\" && a.alwaysOn && a.packageName !== packageName)\n : []\n saveAlwaysOnOverride(packageName, status)\n for (const other of cleared) saveAlwaysOnOverride(other.packageName, false)\n set((s) => ({\n apps: s.apps.map((a) => {\n if (a.packageName === packageName) return {...a, alwaysOn: status}\n if (cleared.includes(a)) return {...a, alwaysOn: false}\n return a\n }),\n }))\n if (status && !app.running) await get().start(app, {skipNavigation: true})\n },\n\n setWidgetExpand: (packageName, widgetId, expandOnTap) => {\n const app = get().apps.find((a) => a.packageName === packageName)\n const widget = app?.widgets?.find((w) => w.id === widgetId)\n if (!widget?.expandable) return false\n if (widget.expandOnTap === expandOnTap) return expandOnTap\n saveWidgetExpandChoice(packageName, widgetId, expandOnTap)\n set((s) => ({\n apps: s.apps.map((a) =>\n a.packageName === packageName\n ? {...a, widgets: a.widgets?.map((w) => (w.id === widgetId ? {...w, expandOnTap} : w))}\n : a,\n ),\n }))\n return expandOnTap\n },\n\n setApps: (apps) => set({apps}),\n}))\n\n// Project miniappRunningRegistry membership into the store's `running` field\n// (and the pause coordinator's state into `paused`) for local apps so the home\n// tray and switcher reflect actual mount state without waiting for the next\n// refresh() cycle.\nfunction projectLocalRunningState(): void {\n const running = new Set(miniappRunningRegistry.getAll())\n const pausedNow = isMiniappsPaused()\n const state = useAppStatusStore.getState()\n let changed = false\n const updated = state.apps.map((app) => {\n if (!app.local) return app\n const next = running.has(app.packageName)\n const paused = next && pausedNow\n const widgetOnly = next && miniappWidgetMode.isWidgetOnly(app.packageName)\n if (app.running === next && (app.paused ?? false) === paused && (app.widgetOnly ?? false) === widgetOnly) return app\n changed = true\n return {...app, running: next, paused, widgetOnly}\n })\n if (changed) {\n useAppStatusStore.setState({apps: updated})\n }\n}\nminiappRunningRegistry.subscribe(projectLocalRunningState)\nminiappWidgetMode.subscribe(projectLocalRunningState)\nonMiniappsPauseChange(projectLocalRunningState)\n\n// The display-manager's core (foreground) slot is DERIVED state: always the\n// currently-running standard app, no matter HOW it came to run — user tap\n// (start()), boot restore (autostartLocalMiniapps → registry projection\n// above), crash-respawn, or interop. One reconciler instead of per-path call\n// sites, so no launch/stop path can forget to claim or release the slot.\n// onCoreAppChange is idempotent, so firing on every store write is free.\nuseAppStatusStore.subscribe((state) => {\n const core = state.apps.find((a) => a.running && !a.widgetOnly && (a.type === \"standard\" || !a.type))\n localDisplayManager.onCoreAppChange(core?.packageName ?? null)\n})\n\n// AppRegistry change events trigger a store refresh.\nappRegistry.subscribe(() => {\n void useAppStatusStore.getState().refresh()\n})\n\n// Re-evaluate hardware compatibility when the paired/default wearable changes.\nuseSettingsStore.subscribe(\n (state) => state.getSetting(SETTINGS.default_wearable.key),\n () => {\n void useAppStatusStore.getState().refresh()\n },\n)\n\n// Developer tools toggled: dev-only apps enter or leave the projection. When\n// they leave, stop any that are running first so the running registry doesn't\n// keep a miniapp alive that no launcher surface can reach.\nuseSettingsStore.subscribe(\n (state) => state.getSetting(SETTINGS.dev_tools.key) === true,\n (enabled) => {\n void (async () => {\n if (!enabled) {\n const state = useAppStatusStore.getState()\n const hasPairedGlasses = useSettingsStore.getState().getSetting(SETTINGS.has_paired_glasses.key) === true\n for (const app of state.apps) {\n const gated =\n isGatedByDevTools(app.packageName, false) || isGatedUntilPaired(app.packageName, false, hasPairedGlasses)\n if (app.running && gated) await state.stop(app.packageName)\n }\n }\n await useAppStatusStore.getState().refresh()\n })()\n },\n)\n\n// First real pairing latched: the Store enters the projection. One-way, so\n// nothing ever leaves here.\nuseSettingsStore.subscribe(\n (state) => state.getSetting(SETTINGS.has_paired_glasses.key) === true,\n () => {\n void useAppStatusStore.getState().refresh()\n },\n)\n\n// ---------------------------------------------------------------------------\n// Public hooks\n// ---------------------------------------------------------------------------\n\nexport const useApps = () => useAppStatusStore((state) => state.apps)\nexport const useStart = () => useAppStatusStore((state) => state.start)\nexport const useStop = () => useAppStatusStore((state) => state.stop)\nexport const useSetForeground = () => useAppStatusStore((state) => state.setForeground)\nexport const useClearForeground = () => useAppStatusStore((state) => state.clearForeground)\nexport const useRefresh = () => useAppStatusStore((state) => state.refresh)\nexport const useStopAll = () => useAppStatusStore((state) => state.stopAll)\nexport const useInstall = () => useAppStatusStore((state) => state.install)\nexport const useUninstall = () => useAppStatusStore((state) => state.uninstall)\n\n/** Every running app with a card in the app switcher tray: widget-only apps have none. */\nexport const useActiveApps = () => {\n const apps = useApps()\n return useMemo(() => apps.filter((app) => app.running && !app.widgetOnly), [apps])\n}\n\n/** Apps running only for a widget the dashboard placed; the switcher's Widgets pill lists them. */\nexport const useWidgetApps = () => {\n const apps = useApps()\n return useMemo(() => apps.filter((app) => app.running && app.widgetOnly), [apps])\n}\n\n/** Always On apps whose background task is running, card or no card. */\nexport const useRunningAlwaysOnApps = () => {\n const apps = useApps()\n return useMemo(() => apps.filter((app) => app.alwaysOn && app.running), [apps])\n}\n\n/** Apps that run without a foreground surface: background ones and dashboards. */\nconst isBackgroundApp = (app: ClientApp): boolean => app.type === \"background\" || app.type === \"dashboard\"\n\nexport const useActiveBackgroundApps = () => {\n const apps = useApps()\n return useMemo(() => apps.filter((app) => isBackgroundApp(app) && app.running), [apps])\n}\n\nexport const useBackgroundApps = () => {\n const apps = useApps()\n return useMemo(\n () => ({\n active: apps.filter((app) => isBackgroundApp(app) && app.running),\n inactive: apps.filter((app) => isBackgroundApp(app) && !app.running),\n }),\n [apps],\n )\n}\n\nexport const useActiveForegroundApp = () => {\n const apps = useApps()\n return useMemo(\n () => apps.find((app) => (app.type === \"standard\" || !app.type) && app.running && !app.widgetOnly) ?? null,\n [apps],\n )\n}\n\n/**\n * The single app currently foregrounded in the Compositor overlay, or null.\n * Driven by setForeground/clearForeground — distinct from the \"active\n * standard app\" (running) selector above.\n */\nexport const useForegroundApp = () => {\n const apps = useApps()\n return useMemo(() => apps.find((app) => app.foregrounded) ?? null, [apps])\n}\n\nexport const useActiveBackgroundAppsCount = () => {\n const apps = useApps()\n return useMemo(() => apps.filter((app) => isBackgroundApp(app) && app.running).length, [apps])\n}\n\nexport const useLocalMiniApps = () => {\n const apps = useApps()\n return useMemo(() => apps.filter((app) => app.local), [apps])\n}\n"]}
1
+ {"version":3,"file":"apps.js","sourceRoot":"","sources":["../../src/stores/apps.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Engine apps store — runtime state of installed and local applets.\n *\n * The OEM-facing API: subscribe to the running set, install/uninstall\n * miniapps, start/stop them. The store delegates install plumbing to\n * AppRegistry, and exposes hooks (`useApps`, `useStart`, `useStop`,\n * `useRefresh`, `useStopAll`) that the host UI can read.\n *\n * Source of `apps`:\n * - Local: appRegistry.getInstalledMiniapps() (always)\n */\n\nimport {useMemo} from \"react\"\nimport {AsyncResult, Result, result as Res} from \"typesafe-ts\"\nimport {create} from \"zustand\"\n\nimport type {ClientApp} from \"../types/applet\"\nimport {DeviceTypes} from \"../types/enums\"\nimport {getModelCapabilities} from \"../types/hardware\"\nimport {HardwareCompatibility, type CompatibilityResult} from \"../utils/hardware/hardware\"\nimport {storage} from \"../utils/storage/storage\"\nimport appRegistry, {saveAlwaysOnOverride, saveWidgetExpandChoice} from \"../services/AppRegistry\"\nimport localDisplayManager from \"../services/LocalDisplayManager\"\nimport {islandNotifications} from \"../services/NotificationsEmitter\"\nimport sttModelManager from \"../services/STTModelManager\"\nimport {miniappLauncher} from \"../services/MiniappLauncher\"\nimport {isMiniappsPaused, onMiniappsPauseChange} from \"../services/MiniappPauseCoordinator\"\nimport {miniappRunningRegistry} from \"../services/MiniappRunningRegistry\"\nimport {miniappWidgetMode} from \"../services/MiniappWidgetMode\"\nimport {defaultHiddenStatus, isGatedByDevTools, isGatedUntilPaired, resolveHiddenStatus} from \"./appVisibility\"\nimport {SETTINGS, useSettingsStore} from \"./settings\"\nimport BluetoothSdk from \"@glassly/bluetooth-sdk\"\nimport type {MiniappLaunchSource} from \"@glassly/miniapp\"\n\n// ---------------------------------------------------------------------------\n// Configuration / hooks\n// ---------------------------------------------------------------------------\n\nexport interface StartOptions {\n skipNavigation?: boolean\n /** Reported to the miniapp on connect. Defaults to \"phone\". */\n launchSource?: MiniappLaunchSource\n}\n\nexport interface AppStoreHooks {\n /**\n * A start was blocked because the app is hardware-incompatible. Engine made\n * the decision (and raised the `version_incompatible` notification); the host\n * renders its branded alert here.\n */\n onIncompatibleBlocked?: (app: ClientApp) => void\n /**\n * A start was blocked because the app requires the on-device STT model\n * (declared at registration — see AppRegistry.installOfflineApp) and none is\n * installed. Engine decided via its model manager; the host renders the\n * alert / settings navigation here.\n */\n onMissingSpeechModel?: (app: ClientApp) => void\n /**\n * An open request passed the gates — fired on EVERY open, including\n * re-opening an already-running app, so the host's navigation / open\n * animation always plays.\n */\n onOpenRequested?: (app: ClientApp, opts?: StartOptions) => void\n}\n\nlet hostHooks: AppStoreHooks = {}\n\nexport function installAppStoreHooks(hooks: AppStoreHooks): void {\n hostHooks = {...hostHooks, ...hooks}\n}\n\n// ---------------------------------------------------------------------------\n// Store\n// ---------------------------------------------------------------------------\n\ninterface AppStatusState {\n apps: ClientApp[]\n /**\n * Source of truth for which app is foregrounded in the Compositor overlay.\n * The per-app `foregrounded` boolean is derived from this in `projectApps`\n * so a refresh can never drop the flag when an app is transiently missing\n * from one of the two refresh passes (local-only then merged). See\n * `projectApps` / `setForeground` / `clearForeground`.\n */\n foregroundedPackage: string | null\n refresh: () => Promise<void>\n /** Resolves true if the app actually started; false if a host gate aborted it or its JS context failed to spawn. */\n start: (app: ClientApp, opts?: StartOptions) => Promise<boolean>\n stop: (packageName: string) => Promise<void>\n setForeground: (packageName: string) => Promise<void>\n clearForeground: () => void\n stopAll: () => AsyncResult<void, Error>\n install: (url: string, opts?: {versionOverride?: string}) => AsyncResult<void, Error>\n uninstall: (packageName: string, version?: string) => AsyncResult<void, Error>\n saveScreenshot: (packageName: string, screenshot: string) => Promise<void>\n setHiddenStatus: (packageName: string, status: boolean) => void\n getHiddenStatus: (packageName: string) => boolean\n /**\n * Mark a miniapp Always On: it starts at launch and only stops from the\n * app switcher's Always On pill (its card cannot be swiped away and the\n * capsule close minimizes it). Turning it on starts the app; turning it\n * off leaves it running. Persists the wearer's choice beside the hidden flag.\n */\n setAlwaysOn: (packageName: string, status: boolean) => Promise<void>\n /**\n * Whether a tap on one of the miniapp's dashboard widgets expands it to the\n * full screen. Only widgets that list `EX` expand; false for the rest.\n * Persists the choice and answers the setting now in force.\n */\n setWidgetExpand: (packageName: string, widgetId: string, expandOnTap: boolean) => boolean\n /** Replace the whole apps array. Hosts use this when their extra source changes. */\n setApps: (apps: ClientApp[]) => void\n}\n\nexport const DUMMY_APPLET: ClientApp = {\n packageName: \"\",\n name: \"\",\n webviewUrl: \"\",\n logoUrl: \"\",\n type: \"standard\",\n permissions: [],\n running: false,\n loading: false,\n healthy: true,\n hardwareRequirements: [],\n offline: true,\n offlineRoute: \"\",\n local: false,\n hidden: false,\n}\n\nexport type OrderMap = Record<string, number>\nconst APP_ORDER_KEY = \"foreground_apps_order\"\n\nexport const saveAppsOrder = (orderMap: OrderMap): Result<void, Error> => {\n return storage.save(APP_ORDER_KEY, orderMap)\n}\n\nexport const getAppsOrder = (): Result<OrderMap, Error> => {\n return storage.load<OrderMap>(APP_ORDER_KEY)\n}\n\n// In-memory cache for hidden flags. `projectApps` reads getHiddenStatus once\n// per app per refresh — without a cache that was a synchronous JNI hop per\n// app per refresh on a hot UI path. Kept consistent with disk by writing\n// through in setHiddenStatus. Map of packageName → hidden boolean.\nconst hiddenStatusCache = new Map<string, boolean>()\n\nconst getRawPackageNamePriority = (pkg: string): number => {\n if (pkg.includes(\"@empty\")) {\n return 1000\n }\n return 0\n}\n\nexport const sortAppsByPackageNamePriority = (a: ClientApp, b: ClientApp): number => {\n const pa = getRawPackageNamePriority(a.packageName)\n const pb = getRawPackageNamePriority(b.packageName)\n if (pa !== pb) {\n return pa - pb\n }\n return a.name.localeCompare(b.name)\n}\n\nexport const saveLastOpenTime = (packageName: string): void => {\n storage.save(`${packageName}_last_open_time`, Date.now())\n}\n\nexport const getLastOpenTime = (packageName: string): number => {\n const res = storage.load<number>(`${packageName}_last_open_time`)\n if (res.is_ok()) return res.value\n return 0\n}\n\nexport const sortAppsByLastOpenTime = async <T extends {packageName: string}>(apps: T[]): Promise<T[]> => {\n const timestamps = apps.map((app) => ({app, time: getLastOpenTime(app.packageName)}))\n return timestamps.sort((a, b) => a.time - b.time).map((entry) => entry.app)\n}\n\nconst startStopApp = async (app: ClientApp, status: boolean): Promise<void> => {\n if (!status && app.onStop) {\n try {\n app.onStop()\n } catch (e) {\n console.warn(`ISLAND: onStop threw for ${app.packageName}`, e)\n }\n }\n if (status && app.onStart) {\n try {\n app.onStart()\n } catch (e) {\n console.warn(`ISLAND: onStart threw for ${app.packageName}`, e)\n }\n }\n}\n\n/**\n * Build the final `apps` array for the store from the installed/offline app\n * source. Pure — same inputs -> same outputs.\n */\nfunction projectApps(previousState: AppStatusState, localApps: ClientApp[]): ClientApp[] {\n // Dedupe by packageName, keep first occurrence.\n const byPackage = new Map<string, ClientApp>()\n for (const app of localApps) {\n if (!byPackage.has(app.packageName)) byPackage.set(app.packageName, app)\n }\n\n // Index previous snapshot for cheap lookups (was O(N²) via .find()).\n const previousByPackage = new Map<string, ClientApp>()\n for (const oldApp of previousState.apps) {\n previousByPackage.set(oldApp.packageName, oldApp)\n }\n\n const defaultWearable =\n (useSettingsStore.getState().getSetting(SETTINGS.default_wearable.key) as DeviceTypes | undefined) ||\n DeviceTypes.NONE\n const capabilities = getModelCapabilities(defaultWearable)\n const devToolsEnabled = useSettingsStore.getState().getSetting(SETTINGS.dev_tools.key) === true\n const persistScreenshots = useSettingsStore.getState().getSetting(SETTINGS.persist_miniapp_screenshots.key) !== false\n const hasPairedGlasses = useSettingsStore.getState().getSetting(SETTINGS.has_paired_glasses.key) === true\n\n // Single pass: dedupe → screenshot carry-over → compat → hidden, all into\n // fresh objects. The previous in-place mutation re-used object references\n // across refreshes, which broke React.memo / referential-equality\n // memoization downstream (every refresh propagated re-renders even when\n // nothing meaningful changed) AND tripped Reanimated's \"tried to modify\n // key of an object already passed to a worklet\" warning whenever the home\n // screen's animated app cards held a reference to a previous snapshot's\n // app object that we then mutated.\n //\n // Identity stability: refresh() is event-driven and fires repeatedly (and\n // twice per cycle via the local-only → merged two-pass emit). If we always\n // returned fresh objects, every poll changed the identity of EVERY app —\n // which re-rendered the Compositor (via useForegroundApp) mid-slide and made\n // the open/close animation hitch, and churned the home grid / switcher pill.\n // So we build the candidate object, then REUSE the previous reference when\n // nothing meaningful changed. Same pattern as the miniappRunningRegistry\n // projection below. A stable foreground-app reference lets the Compositor's\n // slide run uninterrupted on the UI thread.\n return Array.from(byPackage.values())\n .filter(\n (app) =>\n !isGatedByDevTools(app.packageName, devToolsEnabled) &&\n !isGatedUntilPaired(app.packageName, devToolsEnabled, hasPairedGlasses),\n )\n .map((app) => {\n const next: ClientApp = {\n ...app,\n // The registry's screenshot is the one restored from disk; only an\n // in-memory capture carries over when persistence is off.\n screenshot:\n previousByPackage.get(app.packageName)?.screenshot ?? (persistScreenshots ? app.screenshot : undefined),\n compatibility: HardwareCompatibility.checkCompatibility(app.hardwareRequirements, capabilities),\n // A registry source can force an app off the primary home screen.\n // Compose that gate with the user's persisted home-screen layout instead\n // of replacing it, otherwise a default-false persisted value makes a\n // source-hidden app visible again during projection.\n hidden: resolveHiddenStatus(app.hidden, previousState.getHiddenStatus(app.packageName)),\n // Derive the foreground flag from the store's single source of truth\n // (`foregroundedPackage`), NOT from the previous snapshot. Carrying it over\n // per-app meant a refresh that momentarily omitted an app (e.g. the\n // two-pass local-only → merged emit) would reset its flag to false — which\n // raced OfflineAppHost's interceptor guard and made the hosted miniapp fall\n // through to the root router (restart). Deriving here keeps the flag stable\n // across both passes.\n foregrounded: app.packageName === previousState.foregroundedPackage,\n paused: app.local && app.running && isMiniappsPaused(),\n widgetOnly: !!app.local && app.running && miniappWidgetMode.isWidgetOnly(app.packageName),\n }\n const prev = previousByPackage.get(app.packageName)\n return prev && shallowEqualApp(prev, next) ? prev : next\n })\n}\n\n// Cheap equality check used by projectApps to preserve object identity across\n// refreshes when nothing meaningful changed. Most keys are compared by\n// reference (the source app's nested fields — permissions, hardwareRequirements,\n// parameters — are reference-stable within a refresh). The ONE exception is\n// `compatibility`, which projectApps recomputes into a fresh object every call;\n// comparing it by reference would always differ and defeat the whole point. We\n// compare it structurally instead so identity is only broken when the device's\n// actual compatibility verdict changes (e.g. glasses connect/disconnect).\nfunction shallowEqualApp(a: ClientApp, b: ClientApp): boolean {\n const aKeys = Object.keys(a) as (keyof ClientApp)[]\n const bKeys = Object.keys(b) as (keyof ClientApp)[]\n if (aKeys.length !== bKeys.length) return false\n for (const k of aKeys) {\n if (k === \"compatibility\") {\n if (!compatibilityEqual(a.compatibility, b.compatibility)) return false\n continue\n }\n if (a[k] !== b[k]) return false\n }\n return true\n}\n\nfunction compatibilityEqual(a?: CompatibilityResult, b?: CompatibilityResult): boolean {\n if (a === b) return true\n if (!a || !b) return false\n return (\n a.isCompatible === b.isCompatible &&\n a.missingRequired.length === b.missingRequired.length &&\n a.missingOptional.length === b.missingOptional.length &&\n a.warnings.length === b.warnings.length\n )\n}\n\nexport const useAppStatusStore = create<AppStatusState>((set, get) => ({\n apps: [],\n foregroundedPackage: null,\n\n refresh: async () => {\n const previousState = get()\n const localApps = await appRegistry.getInstalledMiniapps()\n set({apps: projectApps(previousState, localApps)})\n },\n\n start: async (clientApp: ClientApp, opts?: StartOptions) => {\n const state = get()\n const packageName = clientApp.packageName\n const app = state.apps.find((a) => a.packageName === packageName)\n if (!app) {\n console.error(`ISLAND: app not found for package name: ${packageName}`)\n return false\n }\n\n // Skip spawning a NEW app while another is mid-launch — concurrent spawns\n // race the foreground-only-one teardown. This is checked BEFORE the gates\n // and the onOpenRequested seam (which navigates/foregrounds) so a gated\n // launch doesn't paint a splash it can't back. Re-opening an already-running\n // app is exempt: it has nothing to spawn, so it skips this gate and is\n // allowed to re-navigate/animate below.\n // That exemption is the fix for the \"second tap during another app's launch\n // window silently does nothing\" bug.\n if (!app.running && state.apps.some((a) => a.loading)) {\n console.log(`ISLAND: skipping start ${packageName} — another app is loading`)\n return false\n }\n\n if (!app.offline && !app.local) {\n console.warn(`ISLAND: cloud-v1 app entries are no longer supported: ${packageName}`)\n return false\n }\n\n // Hardware-compatibility gate — engine decides and blocks; the host renders\n // its branded alert via onIncompatibleBlocked (and/or the structured\n // notification below). `!isCompatible` (not `=== false`) keeps the semantics\n // of the host gate this replaces: an unknown verdict blocks, not launches.\n if (!app.compatibility?.isCompatible) {\n islandNotifications.emit({\n kind: \"version_incompatible\",\n packageName,\n reason: `${app.name ?? packageName} is not compatible with the connected glasses`,\n metadata: {missingRequired: app.compatibility?.missingRequired ?? []},\n timestamp: Date.now(),\n })\n hostHooks.onIncompatibleBlocked?.(app)\n return false\n }\n\n // Missing-speech-model gate for apps registered with requiresLocalSttModel.\n // Engine decides via its own model manager; the host renders the alert and\n // any settings navigation via onMissingSpeechModel.\n if (appRegistry.requiresLocalSttModel(packageName) && !(await sttModelManager.isModelAvailable())) {\n islandNotifications.emit({\n kind: \"missing_speech_model\",\n packageName,\n reason: `${app.name ?? packageName} needs an on-device speech model before it can start`,\n timestamp: Date.now(),\n })\n hostHooks.onMissingSpeechModel?.(app)\n return false\n }\n\n // An app running only for its widget is promoted before the host hook:\n // the hook may foreground it, and setForeground sends a widget-only app\n // back here.\n if (app.widgetOnly) miniappWidgetMode.setWidgetOnly(packageName, false)\n\n // Host navigation / open-animation seam. Runs on EVERY accepted open —\n // including re-opening an already-running app — so the animation always\n // plays (BuiltInMiniappCatalog.navigateForApp: overlay apps setForeground\n // for the slide).\n hostHooks.onOpenRequested?.(app, opts)\n\n // First-activation mark (moved from the host's old beforeStart — engine\n // owns the settings store).\n useSettingsStore.getState().setSetting(SETTINGS.has_ever_activated_app.key, true)\n\n // If the tapped app is already running, this is a re-open: the nav/foreground\n // above already drove the animation, and there's nothing to spawn. Short-\n // circuit before the spawn pipeline. A promoted app keeps its context but\n // still takes the foreground below.\n if (app.running && !app.widgetOnly) {\n saveLastOpenTime(packageName)\n // The running background only knows the source of its spawn.\n if (app.local) miniappLauncher.notifyLaunch(packageName, opts?.launchSource ?? \"phone\")\n return true\n }\n\n // Only-one rules: one standard app in the foreground, one dashboard\n // drawing the overlay. Starting another stops the one running. Widget-only\n // peers hold no foreground, so they stay.\n if (app.type === \"standard\" || app.type === \"dashboard\") {\n const runningPeers = state.apps.filter(\n (a) => a.running && !a.widgetOnly && a.type === app.type && a.packageName !== packageName,\n )\n for (const r of runningPeers) {\n await get().stop(r.packageName)\n }\n }\n\n set((s) => ({\n apps: s.apps.map((a) => (a.packageName === packageName ? {...a, running: true, loading: false} : a)),\n }))\n\n saveLastOpenTime(packageName)\n await startStopApp(app, true)\n\n // Spawn the background JS context for local miniapps. This used to be a\n // side effect of LocalMiniappView mounting on foreground; pulling it here\n // lets start() actually run the app even when nothing foregrounds it (e.g.\n // a system app launching another miniapp via session.miniapps). Idempotent\n // with the view's own ensureRunning; a no-op for native offline built-ins\n // (no JS bundle).\n if (app.local) {\n try {\n await miniappLauncher.ensureRunning(packageName, {launchSource: opts?.launchSource ?? \"phone\"})\n } catch (e) {\n // Spawn / bundle-resolve failed — revert the optimistic running flag so\n // the home list and miniapps.list() don't show a \"running\" app with no\n // JS context, and report failure to the caller (session.miniapps.start).\n console.warn(`ISLAND: launcher.ensureRunning failed for ${packageName}`, e)\n set((s) => ({\n apps: s.apps.map((a) => (a.packageName === packageName ? {...a, running: false, loading: false} : a)),\n }))\n // onStart already ran before the spawn; run onStop to undo it.\n await startStopApp(app, false)\n return false\n }\n }\n\n return true\n },\n\n stop: async (packageName: string) => {\n const state = get()\n const app = state.apps.find((a) => a.packageName === packageName)\n if (!app) {\n console.error(`ISLAND: app not found for package name: ${packageName}`)\n return\n }\n\n // A placed widget provider is the dashboard's to keep: closing it from\n // the tray takes its card and its frame, and it runs on in widget mode.\n if (app.local && app.running && miniappWidgetMode.isPlaced(packageName)) {\n if (!app.widgetOnly) {\n miniappWidgetMode.setWidgetOnly(packageName, true)\n localDisplayManager.onUnmount(packageName)\n set((s) => ({\n foregroundedPackage: s.foregroundedPackage === packageName ? null : s.foregroundedPackage,\n apps: s.apps.map((a) =>\n a.packageName === packageName ? {...a, screenshot: undefined, foregrounded: false, loading: false} : a,\n ),\n }))\n }\n return\n }\n\n set((s) => ({\n apps: s.apps.map((a) =>\n a.packageName === packageName ? {...a, running: false, screenshot: undefined, loading: false} : a,\n ),\n }))\n\n // if there are no apps running, call clearDisplay():\n // read fresh state via get() — `state` was captured before the set() above, so it still shows\n // this app as running and would never reach 0 when stopping the last app.\n if (get().apps.filter((a) => a.running).length === 0) {\n BluetoothSdk.clearDisplay()\n }\n await startStopApp(app, false)\n\n // Tear down the background JS context for local miniapps. No-op for native\n // offline built-ins.\n if (app.local) {\n try {\n await miniappLauncher.stop(packageName)\n } catch (e) {\n console.warn(`ISLAND: launcher.stop failed for ${packageName}`, e)\n }\n }\n },\n\n setForeground: async (packageName: string) => {\n const app = get().apps.find((a) => a.packageName === packageName)\n if (!app) {\n console.error(`ISLAND: setForeground — app not found: ${packageName}`)\n return\n }\n\n // Flip the foreground flag synchronously so the Compositor's open\n // animation starts on the same frame as the tap. We do NOT await start()\n // first — that gated the flag (and thus the animation) behind the whole\n // JSContext-spawn chain, which was the perceived launch delay. The\n // Compositor/LocalMiniappView already handle the spawn being in-flight\n // (the phase machine), so foregrounding needn't wait for it.\n saveLastOpenTime(packageName)\n set((s) => ({\n foregroundedPackage: packageName,\n apps: s.apps.map((a) => ({...a, foregrounded: a.packageName === packageName})),\n }))\n\n // The wearer is in this app now: one running only for its widget becomes\n // a normal run. start() promotes it, stops the standard peer and keeps the\n // context. Fire-and-forget after the flag flip so it doesn't block paint.\n if (app.running && app.widgetOnly) void get().start(app, {skipNavigation: true})\n },\n\n clearForeground: () => {\n set((s) => ({\n foregroundedPackage: null,\n apps: s.apps.some((a) => a.foregrounded)\n ? s.apps.map((a) => (a.foregrounded ? {...a, foregrounded: false} : a))\n : s.apps,\n }))\n },\n\n stopAll: () => {\n return Res.try_async(async () => {\n // Always On apps stay up; they stop one at a time from the switcher.\n // Widget-only apps have no card to close; they are the dashboard's.\n const running = get().apps.filter((a) => a.running && !a.alwaysOn && !a.widgetOnly)\n for (const a of running) {\n await get().stop(a.packageName)\n }\n })\n },\n\n install: (url, opts) => appRegistry.installFromUrl(url, opts),\n\n uninstall: (packageName, version) => {\n return Res.try_async(async () => {\n const res = await appRegistry.uninstall(packageName, version)\n if (res.is_error()) throw res.error\n set((s) => ({apps: s.apps.filter((a) => a.packageName !== packageName)}))\n })\n },\n\n saveScreenshot: async (packageName: string, screenshot: string) => {\n const key = `${packageName}_screenshot`\n if (useSettingsStore.getState().getSetting(SETTINGS.persist_miniapp_screenshots.key) !== false) {\n storage.save(key, screenshot)\n } else {\n storage.remove(key)\n }\n set((s) => ({\n apps: s.apps.map((a) => (a.packageName === packageName ? {...a, screenshot} : a)),\n }))\n },\n\n setHiddenStatus: (packageName: string, status: boolean) => {\n hiddenStatusCache.set(packageName, status)\n set((s) => ({\n apps: s.apps.map((a) => (a.packageName === packageName ? {...a, hidden: status} : a)),\n }))\n storage.save(`${packageName}_hidden`, status)\n if (!status) {\n const orderMap = getAppsOrder()\n if (orderMap.is_ok()) {\n delete orderMap.value[packageName]\n saveAppsOrder(orderMap.value)\n }\n }\n },\n\n getHiddenStatus: (packageName: string): boolean => {\n const cached = hiddenStatusCache.get(packageName)\n if (cached !== undefined) return cached\n const res = storage.load<boolean>(`${packageName}_hidden`)\n const value = res.is_ok() ? res.value : defaultHiddenStatus(packageName)\n hiddenStatusCache.set(packageName, value)\n return value\n },\n\n setAlwaysOn: async (packageName: string, status: boolean) => {\n const app = get().apps.find((a) => a.packageName === packageName)\n if (!app) return\n // One dashboard is Always On at a time: marking this one clears the others.\n const cleared =\n status && app.type === \"dashboard\"\n ? get().apps.filter((a) => a.type === \"dashboard\" && a.alwaysOn && a.packageName !== packageName)\n : []\n saveAlwaysOnOverride(packageName, status)\n for (const other of cleared) saveAlwaysOnOverride(other.packageName, false)\n set((s) => ({\n apps: s.apps.map((a) => {\n if (a.packageName === packageName) return {...a, alwaysOn: status}\n if (cleared.includes(a)) return {...a, alwaysOn: false}\n return a\n }),\n }))\n if (status && !app.running) await get().start(app, {skipNavigation: true})\n },\n\n setWidgetExpand: (packageName, widgetId, expandOnTap) => {\n const app = get().apps.find((a) => a.packageName === packageName)\n const widget = app?.widgets?.find((w) => w.id === widgetId)\n if (!widget?.expandable) return false\n if (widget.expandOnTap === expandOnTap) return expandOnTap\n saveWidgetExpandChoice(packageName, widgetId, expandOnTap)\n set((s) => ({\n apps: s.apps.map((a) =>\n a.packageName === packageName\n ? {...a, widgets: a.widgets?.map((w) => (w.id === widgetId ? {...w, expandOnTap} : w))}\n : a,\n ),\n }))\n return expandOnTap\n },\n\n setApps: (apps) => set({apps}),\n}))\n\n// Project miniappRunningRegistry membership into the store's `running` field\n// (and the pause coordinator's state into `paused`) for local apps so the home\n// tray and switcher reflect actual mount state without waiting for the next\n// refresh() cycle.\nfunction projectLocalRunningState(): void {\n const running = new Set(miniappRunningRegistry.getAll())\n const pausedNow = isMiniappsPaused()\n const state = useAppStatusStore.getState()\n let changed = false\n const updated = state.apps.map((app) => {\n if (!app.local) return app\n const next = running.has(app.packageName)\n const paused = next && pausedNow\n const widgetOnly = next && miniappWidgetMode.isWidgetOnly(app.packageName)\n if (app.running === next && (app.paused ?? false) === paused && (app.widgetOnly ?? false) === widgetOnly) return app\n changed = true\n return {...app, running: next, paused, widgetOnly}\n })\n if (changed) {\n useAppStatusStore.setState({apps: updated})\n }\n}\nminiappRunningRegistry.subscribe(projectLocalRunningState)\nminiappWidgetMode.subscribe(projectLocalRunningState)\nonMiniappsPauseChange(projectLocalRunningState)\n\n// The display-manager's core (foreground) slot is DERIVED state: always the\n// currently-running standard app, no matter HOW it came to run — user tap\n// (start()), boot restore (autostartLocalMiniapps → registry projection\n// above), crash-respawn, or interop. One reconciler instead of per-path call\n// sites, so no launch/stop path can forget to claim or release the slot.\n// onCoreAppChange is idempotent, so firing on every store write is free.\nuseAppStatusStore.subscribe((state) => {\n const core = state.apps.find((a) => a.running && !a.widgetOnly && (a.type === \"standard\" || !a.type))\n localDisplayManager.onCoreAppChange(core?.packageName ?? null)\n})\n\n// AppRegistry change events trigger a store refresh.\nappRegistry.subscribe(() => {\n void useAppStatusStore.getState().refresh()\n})\n\n// Re-evaluate hardware compatibility when the paired/default wearable changes.\nuseSettingsStore.subscribe(\n (state) => state.getSetting(SETTINGS.default_wearable.key),\n () => {\n void useAppStatusStore.getState().refresh()\n },\n)\n\n// Developer tools toggled: dev-only apps enter or leave the projection. When\n// they leave, stop any that are running first so the running registry doesn't\n// keep a miniapp alive that no launcher surface can reach.\nuseSettingsStore.subscribe(\n (state) => state.getSetting(SETTINGS.dev_tools.key) === true,\n (enabled) => {\n void (async () => {\n if (!enabled) {\n const state = useAppStatusStore.getState()\n const hasPairedGlasses = useSettingsStore.getState().getSetting(SETTINGS.has_paired_glasses.key) === true\n for (const app of state.apps) {\n const gated =\n isGatedByDevTools(app.packageName, false) || isGatedUntilPaired(app.packageName, false, hasPairedGlasses)\n if (app.running && gated) await state.stop(app.packageName)\n }\n }\n await useAppStatusStore.getState().refresh()\n })()\n },\n)\n\n// First real pairing latched: the Store enters the projection. One-way, so\n// nothing ever leaves here.\nuseSettingsStore.subscribe(\n (state) => state.getSetting(SETTINGS.has_paired_glasses.key) === true,\n () => {\n void useAppStatusStore.getState().refresh()\n },\n)\n\n// ---------------------------------------------------------------------------\n// Public hooks\n// ---------------------------------------------------------------------------\n\nexport const useApps = () => useAppStatusStore((state) => state.apps)\nexport const useStart = () => useAppStatusStore((state) => state.start)\nexport const useStop = () => useAppStatusStore((state) => state.stop)\nexport const useSetForeground = () => useAppStatusStore((state) => state.setForeground)\nexport const useClearForeground = () => useAppStatusStore((state) => state.clearForeground)\nexport const useRefresh = () => useAppStatusStore((state) => state.refresh)\nexport const useStopAll = () => useAppStatusStore((state) => state.stopAll)\nexport const useInstall = () => useAppStatusStore((state) => state.install)\nexport const useUninstall = () => useAppStatusStore((state) => state.uninstall)\n\n/** Every running app with a card in the app switcher tray: widget-only apps have none. */\nexport const useActiveApps = () => {\n const apps = useApps()\n return useMemo(() => apps.filter((app) => app.running && !app.widgetOnly), [apps])\n}\n\n/** Apps running only for a widget the dashboard placed; the switcher's Widgets pill lists them. */\nexport const useWidgetApps = () => {\n const apps = useApps()\n return useMemo(() => apps.filter((app) => app.running && app.widgetOnly), [apps])\n}\n\n/** Always On apps whose background task is running, card or no card. */\nexport const useRunningAlwaysOnApps = () => {\n const apps = useApps()\n return useMemo(() => apps.filter((app) => app.alwaysOn && app.running), [apps])\n}\n\n/** Apps that run without a foreground surface: background ones and dashboards. */\nconst isBackgroundApp = (app: ClientApp): boolean => app.type === \"background\" || app.type === \"dashboard\"\n\nexport const useActiveBackgroundApps = () => {\n const apps = useApps()\n return useMemo(() => apps.filter((app) => isBackgroundApp(app) && app.running), [apps])\n}\n\nexport const useBackgroundApps = () => {\n const apps = useApps()\n return useMemo(\n () => ({\n active: apps.filter((app) => isBackgroundApp(app) && app.running),\n inactive: apps.filter((app) => isBackgroundApp(app) && !app.running),\n }),\n [apps],\n )\n}\n\nexport const useActiveForegroundApp = () => {\n const apps = useApps()\n return useMemo(\n () => apps.find((app) => (app.type === \"standard\" || !app.type) && app.running && !app.widgetOnly) ?? null,\n [apps],\n )\n}\n\n/**\n * The single app currently foregrounded in the Compositor overlay, or null.\n * Driven by setForeground/clearForeground — distinct from the \"active\n * standard app\" (running) selector above.\n */\nexport const useForegroundApp = () => {\n const apps = useApps()\n return useMemo(() => apps.find((app) => app.foregrounded) ?? null, [apps])\n}\n\nexport const useActiveBackgroundAppsCount = () => {\n const apps = useApps()\n return useMemo(() => apps.filter((app) => isBackgroundApp(app) && app.running).length, [apps])\n}\n\nexport const useLocalMiniApps = () => {\n const apps = useApps()\n return useMemo(() => apps.filter((app) => app.local), [apps])\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/stores/settings.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,WAAW,EAAwB,MAAM,aAAa,CAAA;AAS9D,OAAO,EAAC,wBAAwB,EAAE,gCAAgC,EAAC,MAAM,wBAAwB,CAAA;AAEjG,MAAM,WAAW,OAAO;IACtB,GAAG,EAAE,MAAM,CAAA;IACX,YAAY,EAAE,MAAM,GAAG,CAAA;IACvB,QAAQ,EAAE,OAAO,CAAA;IACjB,YAAY,EAAE,OAAO,CAAA;IAGrB,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;IAEjC,QAAQ,CAAC,EAAE,MAAM,GAAG,CAAA;IAEpB,OAAO,EAAE,OAAO,CAAA;IAQhB,mBAAmB,CAAC,EAAE,IAAI,CAAA;IAC1B;;;;;;;;;;;;;;;OAeG;IACH,qBAAqB,CAAC,EAAE,IAAI,CAAA;CAC7B;AAKD,eAAO,MAAM,uBAAuB,IAAI,CAAA;AAExC,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CA+lCnC,CAAA;AAEV,eAAO,MAAM,eAAe,EAAE,MAAM,EAAuD,CAAA;AAI3F,eAAO,MAAM,sBAAsB,EAAE,MAAM,EA2D1C,CAAA;AAeD,eAAO,MAAM,qBAAqB,EAAE,MAAM,EAEV,CAAA;AAIhC,MAAM,WAAW,aAAa;IAE5B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAE7B,aAAa,EAAE,OAAO,CAAA;IAEtB,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,YAAY,CAAC,EAAE,OAAO,KAAK,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IACzF,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IAC3E,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,GAAG,CAAA;IAEhC,eAAe,EAAE,MAAM,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IAE/C,oBAAoB,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC/C,uBAAuB,EAAE,MAAM,IAAI,CAAA;CACpC;AAoBD,eAAO,MAAM,gBAAgB;;;;;;;;EAsW5B,CAAA;AAED,eAAO,MAAM,UAAU,GAAI,CAAC,GAAG,GAAG,EAAE,KAAK,MAAM,KAAG,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAI3F,CAAA"}
1
+ {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/stores/settings.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,WAAW,EAAwB,MAAM,aAAa,CAAA;AAS9D,OAAO,EAAC,wBAAwB,EAAE,gCAAgC,EAAC,MAAM,wBAAwB,CAAA;AAEjG,MAAM,WAAW,OAAO;IACtB,GAAG,EAAE,MAAM,CAAA;IACX,YAAY,EAAE,MAAM,GAAG,CAAA;IACvB,QAAQ,EAAE,OAAO,CAAA;IACjB,YAAY,EAAE,OAAO,CAAA;IAGrB,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAA;IAEjC,QAAQ,CAAC,EAAE,MAAM,GAAG,CAAA;IAEpB,OAAO,EAAE,OAAO,CAAA;IAQhB,mBAAmB,CAAC,EAAE,IAAI,CAAA;IAC1B;;;;;;;;;;;;;;;OAeG;IACH,qBAAqB,CAAC,EAAE,IAAI,CAAA;CAC7B;AAKD,eAAO,MAAM,uBAAuB,IAAI,CAAA;AAExC,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAgoCnC,CAAA;AAEV,eAAO,MAAM,eAAe,EAAE,MAAM,EAAuD,CAAA;AAI3F,eAAO,MAAM,sBAAsB,EAAE,MAAM,EA4D1C,CAAA;AAeD,eAAO,MAAM,qBAAqB,EAAE,MAAM,EAEV,CAAA;AAIhC,MAAM,WAAW,aAAa;IAE5B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAE7B,aAAa,EAAE,OAAO,CAAA;IAEtB,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,YAAY,CAAC,EAAE,OAAO,KAAK,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IACzF,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IAC3E,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,GAAG,CAAA;IAEhC,eAAe,EAAE,MAAM,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IAE/C,oBAAoB,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC/C,uBAAuB,EAAE,MAAM,IAAI,CAAA;CACpC;AAuBD,eAAO,MAAM,gBAAgB;;;;;;;;EAsX5B,CAAA;AAED,eAAO,MAAM,UAAU,GAAI,CAAC,GAAG,GAAG,EAAE,KAAK,MAAM,KAAG,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAI3F,CAAA"}