@glassly/engine 0.4.0-dev.1038 → 0.4.0-dev.1041
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/engine.d.ts +1 -1
- package/build/engine.d.ts.map +1 -1
- package/build/engine.js +1 -1
- package/build/engine.js.map +1 -1
- package/build/facades/glasses.js +1 -1
- package/build/facades/glasses.js.map +1 -1
- package/build/facades/providerKeys.d.ts +1 -1
- package/build/facades/providerKeys.js +1 -1
- package/build/facades/providerKeys.js.map +1 -1
- package/build/generated/releaseMetadata.js +3 -3
- package/build/generated/releaseMetadata.js.map +1 -1
- package/build/react/useMentraLiveOta.d.ts.map +1 -1
- package/build/react/useMentraLiveOta.js.map +1 -1
- package/build/runtime/config.d.ts.map +1 -1
- package/build/runtime/config.js.map +1 -1
- package/build/services/AiTierResolution.d.ts +1 -1
- package/build/services/AiTierResolution.d.ts.map +1 -1
- package/build/services/AiTierResolution.js.map +1 -1
- package/build/services/AutomaticReportResult.d.ts.map +1 -1
- package/build/services/AutomaticReportResult.js.map +1 -1
- package/build/services/CloudClientService.d.ts +4 -4
- package/build/services/CloudClientService.d.ts.map +1 -1
- package/build/services/CloudClientService.js +6 -6
- package/build/services/CloudClientService.js.map +1 -1
- package/build/services/GestureDotsService.js +1 -1
- package/build/services/GestureDotsService.js.map +1 -1
- package/build/services/HotspotOtaTransport.d.ts.map +1 -1
- package/build/services/HotspotOtaTransport.js +0 -1
- package/build/services/HotspotOtaTransport.js.map +1 -1
- package/build/services/LocalMiniappRuntime.d.ts +5 -2
- package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
- package/build/services/LocalMiniappRuntime.js +53 -22
- package/build/services/LocalMiniappRuntime.js.map +1 -1
- package/build/services/LocalSttFallbackCoordinator.d.ts.map +1 -1
- package/build/services/LocalSttFallbackCoordinator.js.map +1 -1
- package/build/services/NativeNavigationService.d.ts.map +1 -1
- package/build/services/NativeNavigationService.js.map +1 -1
- package/build/services/NavigationHandlers.d.ts +1 -1
- package/build/services/NavigationHandlers.js +2 -2
- package/build/services/NavigationHandlers.js.map +1 -1
- package/build/services/NavigationService.d.ts +2 -2
- package/build/services/NavigationService.d.ts.map +1 -1
- package/build/services/NavigationService.js +11 -11
- package/build/services/NavigationService.js.map +1 -1
- package/build/services/PairingIdentity.d.ts.map +1 -1
- package/build/services/PairingIdentity.js.map +1 -1
- package/build/services/PhoneCalendarService.d.ts.map +1 -1
- package/build/services/PhoneCalendarService.js.map +1 -1
- package/build/services/PhoneNotificationsSync.d.ts.map +1 -1
- package/build/services/PhoneNotificationsSync.js +2 -1
- package/build/services/PhoneNotificationsSync.js.map +1 -1
- package/build/services/PhoneStreamCoordinator.d.ts.map +1 -1
- package/build/services/PhoneStreamCoordinator.js.map +1 -1
- package/build/services/ProviderKeyValidation.d.ts +1 -1
- package/build/services/ProviderKeyValidation.js +1 -1
- package/build/services/ProviderKeyValidation.js.map +1 -1
- package/build/services/STTModelManager.d.ts.map +1 -1
- package/build/services/STTModelManager.js +1 -6
- package/build/services/STTModelManager.js.map +1 -1
- package/build/services/TranscriptionRouting.d.ts +3 -0
- package/build/services/TranscriptionRouting.d.ts.map +1 -1
- package/build/services/TranscriptionRouting.js +14 -0
- package/build/services/TranscriptionRouting.js.map +1 -1
- package/build/services/UIRouter.d.ts.map +1 -1
- package/build/services/UIRouter.js.map +1 -1
- package/build/services/gestureDotGlyphs.d.ts.map +1 -1
- package/build/services/gestureDotGlyphs.js.map +1 -1
- package/build/services/manifestActions.d.ts.map +1 -1
- package/build/services/manifestActions.js.map +1 -1
- package/build/services/notificationAppPayload.d.ts +14 -0
- package/build/services/notificationAppPayload.d.ts.map +1 -0
- package/build/services/notificationAppPayload.js +15 -0
- package/build/services/notificationAppPayload.js.map +1 -0
- package/build/services/settingsBridge.d.ts.map +1 -1
- package/build/services/settingsBridge.js.map +1 -1
- package/build/stores/appVisibility.d.ts.map +1 -1
- package/build/stores/appVisibility.js.map +1 -1
- package/build/stores/gallerySync.d.ts.map +1 -1
- package/build/stores/gallerySync.js.map +1 -1
- package/build/stores/settings.js +1 -1
- package/build/stores/settings.js.map +1 -1
- package/build/utils/display/index.d.ts.map +1 -1
- package/build/utils/display/index.js +1 -2
- package/build/utils/display/index.js.map +1 -1
- package/build/utils/display/scene/svgPath.js.map +1 -1
- package/build/utils/memory/search.d.ts.map +1 -1
- package/build/utils/memory/search.js +17 -7
- package/build/utils/memory/search.js.map +1 -1
- package/package.json +7 -7
- package/src/engine.ts +1 -1
- package/src/facades/glasses.ts +1 -1
- package/src/facades/providerKeys.ts +1 -1
- package/src/generated/releaseMetadata.ts +3 -3
- package/src/react/useMentraLiveOta.ts +1 -4
- package/src/runtime/config.ts +1 -6
- package/src/services/AiTierResolution.ts +1 -1
- package/src/services/AutomaticReportResult.ts +1 -3
- package/src/services/CloudClientService.ts +7 -6
- package/src/services/GestureDotsService.ts +1 -1
- package/src/services/HotspotOtaTransport.ts +1 -5
- package/src/services/LocalMiniappRuntime.ts +65 -23
- package/src/services/LocalSttFallbackCoordinator.ts +1 -5
- package/src/services/NativeNavigationService.ts +1 -2
- package/src/services/NavigationHandlers.ts +2 -2
- package/src/services/NavigationService.ts +12 -11
- package/src/services/PairingIdentity.ts +1 -3
- package/src/services/PhoneCalendarService.ts +1 -3
- package/src/services/PhoneNotificationsSync.ts +2 -1
- package/src/services/PhoneStreamCoordinator.ts +1 -2
- package/src/services/ProviderKeyValidation.ts +1 -1
- package/src/services/STTModelManager.ts +1 -6
- package/src/services/TranscriptionRouting.ts +18 -0
- package/src/services/UIRouter.ts +3 -9
- package/src/services/gestureDotGlyphs.ts +10 -5
- package/src/services/manifestActions.ts +2 -1
- package/src/services/notificationAppPayload.ts +15 -0
- package/src/services/settingsBridge.ts +1 -2
- package/src/stores/appVisibility.ts +2 -5
- package/src/stores/gallerySync.ts +1 -7
- package/src/stores/settings.ts +1 -1
- package/src/utils/display/index.ts +1 -2
- package/src/utils/display/scene/svgPath.ts +1 -1
- package/src/utils/memory/search.ts +17 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TranscriptionRouting.js","sourceRoot":"","sources":["../../src/services/TranscriptionRouting.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TranscriptionRouting.js","sourceRoot":"","sources":["../../src/services/TranscriptionRouting.ts"],"names":[],"mappings":"AAEA,iEAAiE;AACjE,MAAM,UAAU,gCAAgC,CAC9C,MAAc,EACd,cAAsB,EACtB,YAAuC;IAEvC,MAAM,MAAM,GAAG,gBAAgB,CAAA;IAC/B,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAA;IAClF,IAAI,YAAY,CAAC,QAAQ,CAAC,IAAI,KAAK,UAAU;QAAE,OAAO,MAAM,KAAK,GAAG,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAA;IACzG,IAAI,MAAM,KAAK,GAAG,MAAM,MAAM;QAAE,OAAO,IAAI,CAAA;IAC3C,8EAA8E;IAC9E,uEAAuE;IACvE,MAAM,QAAQ,GAAG,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAA;IAChF,OAAO,QAAQ,KAAK,MAAM,IAAI,QAAQ,KAAK,EAAE,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,QAAQ,CAAA;AACvH,CAAC;AAmBD,MAAM,UAAU,4BAA4B,CAC1C,WAAwB,EACxB,SAA2D;IAE3D,IAAI,kBAAkB,GAAG,KAAK,CAAA;IAC9B,IAAI,uBAAuB,GAAG,KAAK,CAAA;IACnC,IAAI,qBAAqB,GAAG,KAAK,CAAA;IACjC,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,SAAS,CAAC,UAAU,CAAC,CAAA;QACpC,IAAI,MAAM,CAAC,KAAK;YAAE,kBAAkB,GAAG,IAAI,CAAA;QAC3C,IAAI,MAAM,CAAC,UAAU;YAAE,uBAAuB,GAAG,IAAI,CAAA;QACrD,IAAI,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,aAAa,KAAK,KAAK;YAAE,qBAAqB,GAAG,IAAI,CAAA;IAClF,CAAC;IACD,OAAO,EAAC,kBAAkB,EAAE,uBAAuB,EAAE,qBAAqB,EAAC,CAAA;AAC7E,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,0BAA0B,CACxC,MAAyB,EACzB,MAAqC,EACrC,SAAkB;IAElB,IAAI,MAAM,KAAK,OAAO;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAA;IAC9D,IAAI,SAAS;QAAE,OAAO,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAA;IAC7D,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,aAAa,KAAK,KAAK,CAAA;IAC/D,IAAI,QAAQ,IAAI,MAAM,CAAC,UAAU;QAAE,OAAO,KAAK,CAAA;IAC/C,IAAI,MAAM,CAAC,UAAU;QAAE,OAAO,YAAY,CAAA;IAC1C,OAAO,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAA;AACrC,CAAC","sourcesContent":["import type {TranscriptionSubscription} from \"@glassly/cloud-protocol\"\n\n/** Match a provider result to a logical miniapp subscription. */\nexport function matchesTranscriptionSubscription(\n stream: string,\n resolvedStream: string,\n subscription: TranscriptionSubscription,\n): boolean {\n const prefix = \"transcription:\"\n if (!stream.startsWith(prefix) || !resolvedStream.startsWith(prefix)) return false\n if (subscription.language.mode === \"specific\") return stream === `${prefix}${subscription.language.code}`\n if (stream === `${prefix}auto`) return true\n // Providers detect ISO language codes; miniapps request regional BCP-47 tags.\n // Unknown language stays auto-only until the recognizer identifies it.\n const detected = resolvedStream.slice(prefix.length).split(\"-\")[0].toLowerCase()\n return detected !== \"auto\" && detected !== \"\" && stream.slice(prefix.length).split(\"-\")[0].toLowerCase() === detected\n}\n\nexport interface TranscriptionRouteSummary {\n hasCloudSubscriber: boolean\n hasForceLocalSubscriber: boolean\n /** A default-route subscriber that takes on-device text while the primary is down. */\n hasFallbackSubscriber: boolean\n}\n\nexport interface TranscriptionSubscriberRoutes {\n cloud: boolean\n forceLocal: boolean\n /** Default-route fallback acceptance; absent means accepted. */\n localFallback?: boolean\n}\n\n/** \"fallback\" is on-device text serving the default route because the primary is down. */\nexport type TranscriptionDeliveryRoute = \"default\" | \"forceLocal\" | \"fallback\" | \"all\"\n\nexport function summarizeTranscriptionRoutes<T>(\n subscribers: Iterable<T>,\n routesFor: (subscriber: T) => TranscriptionSubscriberRoutes,\n): TranscriptionRouteSummary {\n let hasCloudSubscriber = false\n let hasForceLocalSubscriber = false\n let hasFallbackSubscriber = false\n for (const subscriber of subscribers) {\n const routes = routesFor(subscriber)\n if (routes.cloud) hasCloudSubscriber = true\n if (routes.forceLocal) hasForceLocalSubscriber = true\n if (routes.cloud && routes.localFallback !== false) hasFallbackSubscriber = true\n }\n return {hasCloudSubscriber, hasForceLocalSubscriber, hasFallbackSubscriber}\n}\n\n/**\n * Decide which subscription route(s) a transcript reaches.\n *\n * `source` is who produced the transcript: \"cloud\" is the PRIMARY provider\n * (the cloud runtime, or Soniox-direct when a user API key is set — both\n * deliver through the default route); \"local\" is on-device sherpa.\n * `primaryUp` is whether that primary path is currently believed usable\n * (cloud connectivity, or Soniox-direct session health) — when it is down,\n * local transcripts also serve default-route subscribers.\n */\nexport function transcriptionDeliveryRoute(\n source: \"cloud\" | \"local\",\n routes: TranscriptionSubscriberRoutes,\n primaryUp: boolean,\n): TranscriptionDeliveryRoute | null {\n if (source === \"cloud\") return routes.cloud ? \"default\" : null\n if (primaryUp) return routes.forceLocal ? \"forceLocal\" : null\n const fallback = routes.cloud && routes.localFallback !== false\n if (fallback && routes.forceLocal) return \"all\"\n if (routes.forceLocal) return \"forceLocal\"\n return fallback ? \"fallback\" : null\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UIRouter.d.ts","sourceRoot":"","sources":["../../src/services/UIRouter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,UAAU,UAAU;IAClB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;CAC7F;AAMD;;;;;;;;;GASG;AAEH,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuC;IAChE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;gBAE1B,KAAK,EAAE,cAAc;IAIjC;;;;;;;;;;;OAWG;IACH,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,GAAG,IAAI;IAI5D;;;;OAIG;IACH,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAMxC,kEAAkE;IAClE,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAIrC;;;;;;;;OAQG;IACH,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAKvC;;;;;;;;;;OAUG;IACH,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IA2C5D;;;;;;;;OAQG;IACH,mBAAmB,CACjB,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE;QACb,IAAI,EAAE,MAAM,CAAA;QACZ,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB,GAAG,CAAC,EAAE,MAAM,CAAA;QACZ,SAAS,CAAC,EAAE,MAAM,CAAA;KACnB,GACA,IAAI;
|
|
1
|
+
{"version":3,"file":"UIRouter.d.ts","sourceRoot":"","sources":["../../src/services/UIRouter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,UAAU,UAAU;IAClB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;CAC7F;AAMD;;;;;;;;;GASG;AAEH,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuC;IAChE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;gBAE1B,KAAK,EAAE,cAAc;IAIjC;;;;;;;;;;;OAWG;IACH,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,GAAG,IAAI;IAI5D;;;;OAIG;IACH,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAMxC,kEAAkE;IAClE,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAIrC;;;;;;;;OAQG;IACH,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAKvC;;;;;;;;;;OAUG;IACH,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IA2C5D;;;;;;;;OAQG;IACH,mBAAmB,CACjB,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE;QACb,IAAI,EAAE,MAAM,CAAA;QACZ,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB,GAAG,CAAC,EAAE,MAAM,CAAA;QACZ,SAAS,CAAC,EAAE,MAAM,CAAA;KACnB,GACA,IAAI;IAsBP;;;;OAIG;IACH,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE;QAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAC,GAAG,IAAI;IAQpG;;;;;;OAMG;IACH,OAAO,CAAC,mBAAmB;CAa5B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UIRouter.js","sourceRoot":"","sources":["../../src/services/UIRouter.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * UIRouter — bidirectional bus between a per-miniapp UI WebView\n * and its bound background JSContext.\n *\n * The flow:\n *\n * WebView (glassly.send/on) Background (session.ui.send/on)\n * │ │\n * │ window.ReactNativeWebView │\n * │ .postMessage(jsonEnvelope) │ session.sendOneShot({\n * │ │ type: \"UI_SEND\", channel, payload, seq\n * │ │ })\n * │ │\n * ▼ ▼\n * MiniappHost.onMessage JSRouter (recognises payload.type===\"UI_SEND\")\n * │ │\n * ▼ ▼\n * ──── UIRouter.routeFromWebView ──── UIRouter.routeFromBackground\n * ──► Crust.jsDispatchToJs ──► webView.injectJavaScript(\"window.__host.recv(...)\")\n * {kind:\"bridge\", raw: JSON({\n * payload:{\n * type:\"EVENT\", streamType:\"_ui\",\n * data:{type:\"UI_MESSAGE\", channel, payload, seq}\n * }})}\n *\n * The router is a singleton — one instance for the whole host process —\n * because only one WebView is allowed open at a time per spec. The\n * binding map is therefore N entries (one per \"currently has a UI\n * WebView mounted\" miniapp), but in practice it's 0 or 1.\n *\n * UI_OPEN / UI_CLOSE lifecycle envelopes are pushed by the WebView's\n * `glassly.ready()` and the host's WebView teardown handler; the router\n * forwards them to background via the same EVENT/_ui envelope shape.\n */\n\ninterface UIInjectFn {\n (jsSource: string): void\n}\n\n/**\n * Subset of the Crust native module that UIRouter touches.\n * Loose binding keeps tests free of Expo imports.\n */\nexport interface UICrustBinding {\n jsDispatchToJs(packageName: string, envelope: Record<string, unknown>): Promise<void> | void\n}\n\ninterface BoundWebView {\n inject: UIInjectFn\n}\n\n/**\n * NOTE: the WebView ↔ host heartbeat was removed when the lifecycle\n * inversion landed. The current model is **at most one WebView at a\n * time, foreground UI with an always-on background JSContext** (same\n * shape as the cloud-WebView miniapps). User navigation closes it\n * explicitly and `onContentProcessDidTerminate` catches OS-level\n * crashes, but the host may still re-announce UI_OPEN for an already\n * mounted WebView after app resume/dev respawn so the background can\n * push a fresh authoritative snapshot.\n */\n\nexport class UIRouter {\n private readonly bindings: Map<string, BoundWebView> = new Map()\n private readonly crust: UICrustBinding\n\n constructor(crust: UICrustBinding) {\n this.crust = crust\n }\n\n /**\n * Called when a UI WebView mounts. `injectFn` wraps\n * `webView.injectJavaScript` — the router calls it with prebuilt\n * `window.__host.recv(...)` strings to deliver background-side\n * frames into the WebView's glassly global.\n *\n * The router also pushes a UI_OPEN envelope to the background side\n * once the WebView signals ready (see {@link routeFromWebView}).\n * Calling bindWebView on a packageName that already has a binding\n * replaces the previous one (defensive — should not happen in\n * practice because only one WebView is open at a time).\n */\n bindWebView(packageName: string, injectFn: UIInjectFn): void {\n this.bindings.set(packageName, {inject: injectFn})\n }\n\n /**\n * Called when the WebView unmounts (user navigated away or the host\n * tore it down on heartbeat timeout). Pushes UI_CLOSE to background\n * so handlers can flush state, then drops the binding.\n */\n unbindWebView(packageName: string): void {\n if (!this.bindings.has(packageName)) return\n this.bindings.delete(packageName)\n this.deliverToBackground(packageName, {type: \"UI_CLOSE\"})\n }\n\n /** True iff a WebView is currently bound to the named package. */\n isBound(packageName: string): boolean {\n return this.bindings.has(packageName)\n }\n\n /**\n * Re-announce the already-mounted WebView to the background JSContext.\n * This covers dev background hot-reload, app resume, and thawed WebViews\n * whose injected UI_SEND frames may have been missed while the host was\n * suspended. Re-emitting UI_OPEN flips `ui.bound` back to true if needed\n * and lets background code push a fresh snapshot via session.ui.onOpen.\n *\n * No-op if no WebView is currently bound for the package.\n */\n notifyReopen(packageName: string): void {\n if (!this.bindings.has(packageName)) return\n this.deliverToBackground(packageName, {type: \"UI_OPEN\"})\n }\n\n /**\n * Forward a WebView-originated postMessage envelope to the JSContext.\n * `rawJson` is the raw string from `event.nativeEvent.data` — the\n * caller hasn't parsed it yet so the router controls the wire format\n * end-to-end.\n *\n * Recognised envelope types from the WebView shim:\n * - {type: \"ready\"} → fire UI_OPEN\n * - {type: \"msg\", seq, channel, payload} → fire UI_MESSAGE\n * - {type: \"heartbeat\", seq} → silently ack\n */\n routeFromWebView(packageName: string, rawJson: string): void {\n let env: {\n type?: string\n seq?: number\n channel?: string\n payload?: unknown\n requestId?: string\n }\n try {\n env = JSON.parse(rawJson)\n } catch {\n return\n }\n if (typeof env.type !== \"string\") return\n\n if (env.type === \"ready\") {\n this.deliverToBackground(packageName, {type: \"UI_OPEN\"})\n return\n }\n if (env.type === \"msg\" && typeof env.channel === \"string\") {\n const out: Record<string, unknown> = {\n type: \"UI_MESSAGE\",\n channel: env.channel,\n payload: env.payload,\n seq: env.seq,\n }\n if (typeof env.requestId === \"string\") out.requestId = env.requestId\n this.deliverToBackground(packageName, out)\n return\n }\n if (env.type === \"cancel\" && typeof env.requestId === \"string\") {\n this.deliverToBackground(packageName, {type: \"UI_CANCEL\", requestId: env.requestId})\n return\n }\n // NOTE: console.* logs do NOT come through this router. The\n // miniappGlobals console-tap shim posts {payload:{type:\"dev_log\"}}\n // envelopes which LocalMiniappRuntime handles and forwards to the\n // dev sidecar tagged source:\"ui\". Keeping that path one-way means\n // we don't have two console-capture pipelines competing.\n //\n // Unknown envelope — drop silently.\n }\n\n /**\n * Called by JSRouter when it sees a `__bridge.send` outbound\n * frame whose parsed payload is a UI_SEND envelope. The router\n * forwards it as a `msg` frame to the bound WebView (or drops if no\n * WebView is currently mounted).\n *\n * `uiSendPayload` is the raw `{type:\"UI_SEND\", channel, payload, seq}`\n * shape produced by `session.ui.send` on the background side.\n */\n routeFromBackground(\n packageName: string,\n uiSendPayload: {\n type: string\n channel?: string\n payload?: unknown\n seq?: number\n requestId?: string\n },\n ): void {\n const binding = this.bindings.get(packageName)\n if (!binding) return\n if (uiSendPayload.type === \"UI_CANCEL\" && typeof uiSendPayload.requestId === \"string\") {\n const cancel = {type: \"cancel\", requestId: uiSendPayload.requestId}\n const literal = JSON.stringify(cancel)\n const escaped = JSON.stringify(literal)\n binding.inject(\n `if (window.__host && window.__host.recv) window.__host.recv(JSON.parse(${escaped})); true;`,\n )\n return\n }\n const outbound: Record<string, unknown> = {\n type: \"msg\",\n seq: uiSendPayload.seq ?? 0,\n channel: uiSendPayload.channel,\n payload: uiSendPayload.payload,\n }\n if (typeof uiSendPayload.requestId === \"string\") outbound.requestId = uiSendPayload.requestId\n const literal = JSON.stringify(outbound)\n const escaped = JSON.stringify(literal)\n binding.inject(\n `if (window.__host && window.__host.recv) window.__host.recv(JSON.parse(${escaped})); true;`,\n )\n }\n\n /**\n * Send a synthetic frame to the WebView. Used for host-initiated\n * lifecycle events (`open`, `close`, `ack`). The wire shape is the\n * same as the WebView shim's recv handler expects.\n */\n pushLifecycleFrame(packageName: string, frame: {type: \"open\" | \"close\" | \"ack\"; seq?: number}): void {\n const binding = this.bindings.get(packageName)\n if (!binding) return\n const literal = JSON.stringify(frame)\n const escaped = JSON.stringify(literal)\n binding.inject(\n `if (window.__host && window.__host.recv) window.__host.recv(JSON.parse(${escaped})); true;`,\n )\n }\n\n /**\n * Wrap an EVENT envelope and push it to background via the bridge.\n * Background's UIModule listens for stream `_ui`. The `type` is the\n * wire value `miniapp_event` — must match `MiniappResponseType.EVENT`\n * exactly, otherwise the SDK's session switch falls through and the\n * `_ui` fan-out never fires (bound stays false; `ui.send` drops).\n */\n private deliverToBackground(packageName: string, data: Record<string, unknown>): void {\n const innerEnvelope = {\n payload: {\n type: \"miniapp_event\",\n streamType: \"_ui\",\n data,\n },\n }\n void this.crust.jsDispatchToJs(packageName, {\n kind: \"bridge\",\n raw: JSON.stringify(innerEnvelope),\n })\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"UIRouter.js","sourceRoot":"","sources":["../../src/services/UIRouter.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * UIRouter — bidirectional bus between a per-miniapp UI WebView\n * and its bound background JSContext.\n *\n * The flow:\n *\n * WebView (glassly.send/on) Background (session.ui.send/on)\n * │ │\n * │ window.ReactNativeWebView │\n * │ .postMessage(jsonEnvelope) │ session.sendOneShot({\n * │ │ type: \"UI_SEND\", channel, payload, seq\n * │ │ })\n * │ │\n * ▼ ▼\n * MiniappHost.onMessage JSRouter (recognises payload.type===\"UI_SEND\")\n * │ │\n * ▼ ▼\n * ──── UIRouter.routeFromWebView ──── UIRouter.routeFromBackground\n * ──► Crust.jsDispatchToJs ──► webView.injectJavaScript(\"window.__host.recv(...)\")\n * {kind:\"bridge\", raw: JSON({\n * payload:{\n * type:\"EVENT\", streamType:\"_ui\",\n * data:{type:\"UI_MESSAGE\", channel, payload, seq}\n * }})}\n *\n * The router is a singleton — one instance for the whole host process —\n * because only one WebView is allowed open at a time per spec. The\n * binding map is therefore N entries (one per \"currently has a UI\n * WebView mounted\" miniapp), but in practice it's 0 or 1.\n *\n * UI_OPEN / UI_CLOSE lifecycle envelopes are pushed by the WebView's\n * `glassly.ready()` and the host's WebView teardown handler; the router\n * forwards them to background via the same EVENT/_ui envelope shape.\n */\n\ninterface UIInjectFn {\n (jsSource: string): void\n}\n\n/**\n * Subset of the Crust native module that UIRouter touches.\n * Loose binding keeps tests free of Expo imports.\n */\nexport interface UICrustBinding {\n jsDispatchToJs(packageName: string, envelope: Record<string, unknown>): Promise<void> | void\n}\n\ninterface BoundWebView {\n inject: UIInjectFn\n}\n\n/**\n * NOTE: the WebView ↔ host heartbeat was removed when the lifecycle\n * inversion landed. The current model is **at most one WebView at a\n * time, foreground UI with an always-on background JSContext** (same\n * shape as the cloud-WebView miniapps). User navigation closes it\n * explicitly and `onContentProcessDidTerminate` catches OS-level\n * crashes, but the host may still re-announce UI_OPEN for an already\n * mounted WebView after app resume/dev respawn so the background can\n * push a fresh authoritative snapshot.\n */\n\nexport class UIRouter {\n private readonly bindings: Map<string, BoundWebView> = new Map()\n private readonly crust: UICrustBinding\n\n constructor(crust: UICrustBinding) {\n this.crust = crust\n }\n\n /**\n * Called when a UI WebView mounts. `injectFn` wraps\n * `webView.injectJavaScript` — the router calls it with prebuilt\n * `window.__host.recv(...)` strings to deliver background-side\n * frames into the WebView's glassly global.\n *\n * The router also pushes a UI_OPEN envelope to the background side\n * once the WebView signals ready (see {@link routeFromWebView}).\n * Calling bindWebView on a packageName that already has a binding\n * replaces the previous one (defensive — should not happen in\n * practice because only one WebView is open at a time).\n */\n bindWebView(packageName: string, injectFn: UIInjectFn): void {\n this.bindings.set(packageName, {inject: injectFn})\n }\n\n /**\n * Called when the WebView unmounts (user navigated away or the host\n * tore it down on heartbeat timeout). Pushes UI_CLOSE to background\n * so handlers can flush state, then drops the binding.\n */\n unbindWebView(packageName: string): void {\n if (!this.bindings.has(packageName)) return\n this.bindings.delete(packageName)\n this.deliverToBackground(packageName, {type: \"UI_CLOSE\"})\n }\n\n /** True iff a WebView is currently bound to the named package. */\n isBound(packageName: string): boolean {\n return this.bindings.has(packageName)\n }\n\n /**\n * Re-announce the already-mounted WebView to the background JSContext.\n * This covers dev background hot-reload, app resume, and thawed WebViews\n * whose injected UI_SEND frames may have been missed while the host was\n * suspended. Re-emitting UI_OPEN flips `ui.bound` back to true if needed\n * and lets background code push a fresh snapshot via session.ui.onOpen.\n *\n * No-op if no WebView is currently bound for the package.\n */\n notifyReopen(packageName: string): void {\n if (!this.bindings.has(packageName)) return\n this.deliverToBackground(packageName, {type: \"UI_OPEN\"})\n }\n\n /**\n * Forward a WebView-originated postMessage envelope to the JSContext.\n * `rawJson` is the raw string from `event.nativeEvent.data` — the\n * caller hasn't parsed it yet so the router controls the wire format\n * end-to-end.\n *\n * Recognised envelope types from the WebView shim:\n * - {type: \"ready\"} → fire UI_OPEN\n * - {type: \"msg\", seq, channel, payload} → fire UI_MESSAGE\n * - {type: \"heartbeat\", seq} → silently ack\n */\n routeFromWebView(packageName: string, rawJson: string): void {\n let env: {\n type?: string\n seq?: number\n channel?: string\n payload?: unknown\n requestId?: string\n }\n try {\n env = JSON.parse(rawJson)\n } catch {\n return\n }\n if (typeof env.type !== \"string\") return\n\n if (env.type === \"ready\") {\n this.deliverToBackground(packageName, {type: \"UI_OPEN\"})\n return\n }\n if (env.type === \"msg\" && typeof env.channel === \"string\") {\n const out: Record<string, unknown> = {\n type: \"UI_MESSAGE\",\n channel: env.channel,\n payload: env.payload,\n seq: env.seq,\n }\n if (typeof env.requestId === \"string\") out.requestId = env.requestId\n this.deliverToBackground(packageName, out)\n return\n }\n if (env.type === \"cancel\" && typeof env.requestId === \"string\") {\n this.deliverToBackground(packageName, {type: \"UI_CANCEL\", requestId: env.requestId})\n return\n }\n // NOTE: console.* logs do NOT come through this router. The\n // miniappGlobals console-tap shim posts {payload:{type:\"dev_log\"}}\n // envelopes which LocalMiniappRuntime handles and forwards to the\n // dev sidecar tagged source:\"ui\". Keeping that path one-way means\n // we don't have two console-capture pipelines competing.\n //\n // Unknown envelope — drop silently.\n }\n\n /**\n * Called by JSRouter when it sees a `__bridge.send` outbound\n * frame whose parsed payload is a UI_SEND envelope. The router\n * forwards it as a `msg` frame to the bound WebView (or drops if no\n * WebView is currently mounted).\n *\n * `uiSendPayload` is the raw `{type:\"UI_SEND\", channel, payload, seq}`\n * shape produced by `session.ui.send` on the background side.\n */\n routeFromBackground(\n packageName: string,\n uiSendPayload: {\n type: string\n channel?: string\n payload?: unknown\n seq?: number\n requestId?: string\n },\n ): void {\n const binding = this.bindings.get(packageName)\n if (!binding) return\n if (uiSendPayload.type === \"UI_CANCEL\" && typeof uiSendPayload.requestId === \"string\") {\n const cancel = {type: \"cancel\", requestId: uiSendPayload.requestId}\n const literal = JSON.stringify(cancel)\n const escaped = JSON.stringify(literal)\n binding.inject(`if (window.__host && window.__host.recv) window.__host.recv(JSON.parse(${escaped})); true;`)\n return\n }\n const outbound: Record<string, unknown> = {\n type: \"msg\",\n seq: uiSendPayload.seq ?? 0,\n channel: uiSendPayload.channel,\n payload: uiSendPayload.payload,\n }\n if (typeof uiSendPayload.requestId === \"string\") outbound.requestId = uiSendPayload.requestId\n const literal = JSON.stringify(outbound)\n const escaped = JSON.stringify(literal)\n binding.inject(`if (window.__host && window.__host.recv) window.__host.recv(JSON.parse(${escaped})); true;`)\n }\n\n /**\n * Send a synthetic frame to the WebView. Used for host-initiated\n * lifecycle events (`open`, `close`, `ack`). The wire shape is the\n * same as the WebView shim's recv handler expects.\n */\n pushLifecycleFrame(packageName: string, frame: {type: \"open\" | \"close\" | \"ack\"; seq?: number}): void {\n const binding = this.bindings.get(packageName)\n if (!binding) return\n const literal = JSON.stringify(frame)\n const escaped = JSON.stringify(literal)\n binding.inject(`if (window.__host && window.__host.recv) window.__host.recv(JSON.parse(${escaped})); true;`)\n }\n\n /**\n * Wrap an EVENT envelope and push it to background via the bridge.\n * Background's UIModule listens for stream `_ui`. The `type` is the\n * wire value `miniapp_event` — must match `MiniappResponseType.EVENT`\n * exactly, otherwise the SDK's session switch falls through and the\n * `_ui` fan-out never fires (bound stays false; `ui.send` drops).\n */\n private deliverToBackground(packageName: string, data: Record<string, unknown>): void {\n const innerEnvelope = {\n payload: {\n type: \"miniapp_event\",\n streamType: \"_ui\",\n data,\n },\n }\n void this.crust.jsDispatchToJs(packageName, {\n kind: \"bridge\",\n raw: JSON.stringify(innerEnvelope),\n })\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gestureDotGlyphs.d.ts","sourceRoot":"","sources":["../../src/services/gestureDotGlyphs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,sBAAsB,KAAK,CAAA;AAExC,MAAM,MAAM,eAAe,
|
|
1
|
+
{"version":3,"file":"gestureDotGlyphs.d.ts","sourceRoot":"","sources":["../../src/services/gestureDotGlyphs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,sBAAsB,KAAK,CAAA;AAExC,MAAM,MAAM,eAAe,GACzB,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,YAAY,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,CAAA;AAE7G,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,CAgB9D,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gestureDotGlyphs.js","sourceRoot":"","sources":["../../src/services/gestureDotGlyphs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"gestureDotGlyphs.js","sourceRoot":"","sources":["../../src/services/gestureDotGlyphs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,CAAA;AAKxC,MAAM,CAAC,MAAM,kBAAkB,GAAoC;IACjE,GAAG,EAAE,8IAA8I;IACnJ,MAAM,EACJ,kHAAkH;IACpH,IAAI,EAAE,sJAAsJ;IAC5J,UAAU,EACR,8HAA8H;IAChI,EAAE,EAAE,8IAA8I;IAClJ,IAAI,EAAE,0IAA0I;IAChJ,IAAI,EAAE,8HAA8H;IACpI,KAAK,EACH,0HAA0H;IAC5H,IAAI,EAAE,8KAA8K;IACpL,QAAQ,EACN,0KAA0K;IAC5K,KAAK,EAAE,kGAAkG;CAC1G,CAAA","sourcesContent":["/**\n * GENERATED by scripts/gen-gesture-dot-glyphs.mjs — do not edit by hand.\n * 24×24 8-bit grayscale PNGs (white on black) for the gesture-dots indicator.\n */\nexport const GESTURE_DOT_GLYPH_SIZE = 24\n\nexport type GestureDotGlyph =\n \"dot\" | \"double\" | \"ring\" | \"doubleRing\" | \"up\" | \"down\" | \"left\" | \"right\" | \"hold\" | \"holdRing\" | \"blank\"\n\nexport const GESTURE_DOT_GLYPHS: Record<GestureDotGlyph, string> = {\n dot: \"iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAALklEQVR4nM2QsQ0AAAjC/P/pmrhqZ+xIF6DqBQyWbwO3gduAmKjQuj7QL/ETEzQmMptl7Q9NBAAAAABJRU5ErkJggg==\",\n double:\n \"iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAAG0lEQVR4nGNgGD7gPxjgYkN4yOyBlcDp3GEBAB3sd4lPaQxDAAAAAElFTkSuQmCC\",\n ring: \"iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAANElEQVR4nGNgGBTgPxjgEseUgQphyCD4qDL/kSX+Y9WApoWqEjgsx+lc3B7EHSS4A3EgAAC+cEu1JTNREQAAAABJRU5ErkJggg==\",\n doubleRing:\n \"iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAAIklEQVR4nGNgGD7gPxjgYkN4yGwGmBA6SV0JHJbjdO6wAADBMlep8zl7TAAAAABJRU5ErkJggg==\",\n up: \"iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAAMElEQVR4nGNgoCv4////f1zi2GT+/4ciTHE4RhdHIlDFUUhkcTQKQx9WBw8PCVoBAIcbOcf3xeeBAAAAAElFTkSuQmCC\",\n down: \"iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAALUlEQVR4nGNgoC/4/3+4SkBFUCkkNjKJIoMg0GRgGEMGgrC4CQSwuxanR2gEAO1/Ocfgp8uvAAAAAElFTkSuQmCC\",\n left: \"iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAAI0lEQVR4nGNgoCv4j0sch8RAiTP8RwPESOAwajDI4JKgGQAAKO05x7DqJxIAAAAASUVORK5CYII=\",\n right:\n \"iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAAIElEQVR4nGNgoDf4j1NiMMn8RwOEJYizZKDEcQc7bQAAS7w5x+ro2lsAAAAASUVORK5CYII=\",\n hold: \"iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAAR0lEQVR4nGNgIAj+gwF2UUy5//+xyyDzcLGRedjMhTEwXAKl0Z0Lof7DKbgMhBpQCZzOxedBHEGCMxAJBTXhKGRAA9hFMQEANr7jHQU9fO0AAAAASUVORK5CYII=\",\n holdRing:\n \"iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAAQ0lEQVR4nGNgIAj+gwF2UUy5//+xyyDzcLGRedjMhTEwXAKlMd2IVQNMaEAlcDoXnwdxBAnOQCQU1ISjEIvjsYhiAgAo9KdZzePY3AAAAABJRU5ErkJggg==\",\n blank: \"iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAAAAADFHGIkAAAAD0lEQVR4nGNgGAWjgPoAAAJYAAGgxYwDAAAAAElFTkSuQmCC\",\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifestActions.d.ts","sourceRoot":"","sources":["../../src/services/manifestActions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,cAAc,EAAE,cAAc,EAAqB,MAAM,iBAAiB,CAAA;AAEvF,gGAAgG;AAChG,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,cAAc,EAAE,CAAA;IAC1B,aAAa,CAAC,EAAE;QAAC,YAAY,EAAE,OAAO,CAAA;KAAC,CAAA;CACxC;AAED,8EAA8E;AAC9E,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACvC;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,aAAa,EAAE,EACrB,iBAAiB,EAAE,MAAM,EACzB,cAAc,EAAE,OAAO,GACtB,aAAa,EAAE,CAkBjB;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,EAAE,CA0BvE;
|
|
1
|
+
{"version":3,"file":"manifestActions.d.ts","sourceRoot":"","sources":["../../src/services/manifestActions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,cAAc,EAAE,cAAc,EAAqB,MAAM,iBAAiB,CAAA;AAEvF,gGAAgG;AAChG,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,cAAc,EAAE,CAAA;IAC1B,aAAa,CAAC,EAAE;QAAC,YAAY,EAAE,OAAO,CAAA;KAAC,CAAA;CACxC;AAED,8EAA8E;AAC9E,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACvC;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,aAAa,EAAE,EACrB,iBAAiB,EAAE,MAAM,EACzB,cAAc,EAAE,OAAO,GACtB,aAAa,EAAE,CAkBjB;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,EAAE,CA0BvE;AAMD;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,EAAE,CA2BvE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifestActions.js","sourceRoot":"","sources":["../../src/services/manifestActions.ts"],"names":[],"mappings":"AAoBA;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAAqB,EACrB,iBAAyB,EACzB,cAAuB;IAEvB,MAAM,IAAI,GAAoB,EAAE,CAAA;IAChC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,CAAC,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,WAAW,KAAK,iBAAiB,IAAI,GAAG,CAAC,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAAE,SAAQ;QAC7G,IAAI,GAAG,CAAC,aAAa,EAAE,YAAY,KAAK,KAAK;YAAE,SAAQ;QACvD,KAAK,MAAM,MAAM,IAAI,GAAG,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;YACvC,IAAI,MAAM,CAAC,UAAU,KAAK,QAAQ,IAAI,CAAC,cAAc;gBAAE,SAAQ;YAC/D,IAAI,CAAC,IAAI,CAAC;gBACR,WAAW,EAAE,GAAG,CAAC,WAAW;gBAC5B,OAAO,EAAE,GAAG,CAAC,IAAI;gBACjB,EAAE,EAAE,MAAM,CAAC,EAAE;gBACb,WAAW,EAAE,MAAM,CAAC,WAAW;gBAC/B,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,EAAC,UAAU,EAAE,MAAM,CAAC,UAAU,EAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC7D,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,EAAC,YAAY,EAAE,MAAM,CAAC,YAAY,EAAC,CAAC,CAAC,CAAC,EAAE,CAAC;aACpE,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CAAC,GAAY;IACnD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAA;IAClC,MAAM,GAAG,GAAqB,EAAE,CAAA;IAChC,KAAK,MAAM,CAAC,IAAI,GAMd,EAAE,CAAC;QACH,IAAI,CAAC,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,WAAW,KAAK,QAAQ,EAAE,CAAC;YACvE,GAAG,CAAC,IAAI,CAAC;gBACP,EAAE,EAAE,CAAC,CAAC,EAAE;gBACR,WAAW,EAAE,CAAC,CAAC,WAAW;gBAC1B,GAAG,CAAC,CAAC,CAAC,UAAU,IAAI,OAAO,CAAC,CAAC,UAAU,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC;oBAClF,CAAC,CAAC,EAAC,UAAU,EAAE,CAAC,CAAC,UAAqC,EAAC;oBACvD,CAAC,CAAC,EAAE,CAAC;gBACP,GAAG,CAAC,CAAC,CAAC,YAAY,IAAI,OAAO,CAAC,CAAC,YAAY,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC;oBACxF,CAAC,CAAC,EAAC,YAAY,EAAE,CAAC,CAAC,YAAuC,EAAC;oBAC3D,CAAC,CAAC,EAAE,CAAC;gBACP,yEAAyE;gBACzE,GAAG,CAAC,CAAC,CAAC,UAAU,KAAK,QAAQ,IAAI,CAAC,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAC,UAAU,EAAE,CAAC,CAAC,UAAU,EAAC,CAAC,CAAC,CAAC,EAAE,CAAC;aAC9F,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,MAAM,YAAY,GAAkC,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAA;AACnF,MAAM,YAAY,GAAG,CAAC,KAAc,EAA+B,EAAE,
|
|
1
|
+
{"version":3,"file":"manifestActions.js","sourceRoot":"","sources":["../../src/services/manifestActions.ts"],"names":[],"mappings":"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","sourcesContent":["import type {DeclaredAction, DeclaredWidget, DeclaredWidgetSize} from \"../types/applet\"\n\n/** The subset of ClientApp that action-listing needs (structural, no cycle on applet types). */\nexport interface ActionListApp {\n packageName: string\n name: string\n actions?: DeclaredAction[]\n compatibility?: {isCompatible: boolean}\n}\n\n/** One row of `session.actions.list` — a flat, MCP-tool-shaped descriptor. */\nexport interface ActionListRow {\n packageName: string\n appName: string\n id: string\n description: string\n parameters?: Record<string, unknown>\n outputSchema?: Record<string, unknown>\n}\n\n/**\n * Project the installed-app set into the caller's invokable-action rows:\n * excludes the caller's own actions, incompatible apps, and placeholder\n * packages; `visibility: \"system\"` actions only surface for system callers.\n */\nexport function visibleActionRows(\n apps: ActionListApp[],\n callerPackageName: string,\n callerIsSystem: boolean,\n): ActionListRow[] {\n const rows: ActionListRow[] = []\n for (const app of apps) {\n if (!app.packageName || app.packageName === callerPackageName || app.packageName.includes(\"@empty\")) continue\n if (app.compatibility?.isCompatible === false) continue\n for (const action of app.actions ?? []) {\n if (action.visibility === \"system\" && !callerIsSystem) continue\n rows.push({\n packageName: app.packageName,\n appName: app.name,\n id: action.id,\n description: action.description,\n ...(action.parameters ? {parameters: action.parameters} : {}),\n ...(action.outputSchema ? {outputSchema: action.outputSchema} : {}),\n })\n }\n }\n return rows\n}\n\n/**\n * Normalize manifest actions defensively for installed and dev-sideloaded\n * bundles. Input and output schemas are passed through as opaque JSON Schema.\n */\nexport function normalizeManifestActions(raw: unknown): DeclaredAction[] {\n if (!Array.isArray(raw)) return []\n const out: DeclaredAction[] = []\n for (const a of raw as Array<{\n id?: unknown\n description?: unknown\n parameters?: unknown\n outputSchema?: unknown\n visibility?: unknown\n }>) {\n if (a && typeof a.id === \"string\" && typeof a.description === \"string\") {\n out.push({\n id: a.id,\n description: a.description,\n ...(a.parameters && typeof a.parameters === \"object\" && !Array.isArray(a.parameters)\n ? {parameters: a.parameters as Record<string, unknown>}\n : {}),\n ...(a.outputSchema && typeof a.outputSchema === \"object\" && !Array.isArray(a.outputSchema)\n ? {outputSchema: a.outputSchema as Record<string, unknown>}\n : {}),\n // Unknown/absent values fall back to the default (\"public\") by omission.\n ...(a.visibility === \"system\" || a.visibility === \"public\" ? {visibility: a.visibility} : {}),\n })\n }\n }\n return out\n}\n\nconst WIDGET_SIZES: readonly DeclaredWidgetSize[] = [\"XS\", \"XSM\", \"SM\", \"MD\", \"LG\"]\nconst isWidgetSize = (value: unknown): value is DeclaredWidgetSize =>\n (WIDGET_SIZES as readonly unknown[]).includes(value)\n\n/**\n * Normalize manifest widgets for installed and dev-sideloaded bundles: an\n * entry without an id, a name or a usable card size is dropped, repeats of a\n * size are folded, and a default size the widget does not offer becomes\n * its first size. Listing `EX` makes a widget expandable; it is not a card\n * size. Taps expand it until the wearer turns that off (AppRegistry applies\n * the choice).\n */\nexport function normalizeManifestWidgets(raw: unknown): DeclaredWidget[] {\n if (!Array.isArray(raw)) return []\n const out: DeclaredWidget[] = []\n const seen = new Set<string>()\n for (const w of raw as Array<{\n id?: unknown\n name?: unknown\n sizes?: unknown\n defaultSize?: unknown\n expandable?: unknown\n }>) {\n if (!w || typeof w.id !== \"string\" || !w.id || typeof w.name !== \"string\" || !w.name || seen.has(w.id)) continue\n const sizes = Array.isArray(w.sizes) ? Array.from(new Set(w.sizes.filter(isWidgetSize))) : []\n if (sizes.length === 0) continue\n seen.add(w.id)\n // `expandable: true` is how bundles from before `EX` said the same.\n const expandable = (Array.isArray(w.sizes) && w.sizes.includes(\"EX\")) || w.expandable === true\n out.push({\n id: w.id,\n name: w.name,\n sizes,\n defaultSize: isWidgetSize(w.defaultSize) && sizes.includes(w.defaultSize) ? w.defaultSize : sizes[0],\n expandable,\n expandOnTap: expandable,\n })\n }\n return out\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Keep installed-app icons from exhausting the miniapp's 32 MiB JS heap.
|
|
2
|
+
* Icons are optional; clients already render a fallback when one is absent.
|
|
3
|
+
* Bound both individual icons and their total before JSON crosses the bridge.
|
|
4
|
+
*/
|
|
5
|
+
export declare function notificationAppPayload(apps: Array<{
|
|
6
|
+
packageName: string;
|
|
7
|
+
appName: string;
|
|
8
|
+
icon: string | null;
|
|
9
|
+
}>): Array<{
|
|
10
|
+
packageName: string;
|
|
11
|
+
appName: string;
|
|
12
|
+
icon: string | null;
|
|
13
|
+
}>;
|
|
14
|
+
//# sourceMappingURL=notificationAppPayload.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notificationAppPayload.d.ts","sourceRoot":"","sources":["../../src/services/notificationAppPayload.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,KAAK,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAC,CAAC,GACvE,KAAK,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAC,CAAC,CAQpE"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Keep installed-app icons from exhausting the miniapp's 32 MiB JS heap.
|
|
2
|
+
* Icons are optional; clients already render a fallback when one is absent.
|
|
3
|
+
* Bound both individual icons and their total before JSON crosses the bridge.
|
|
4
|
+
*/
|
|
5
|
+
export function notificationAppPayload(apps) {
|
|
6
|
+
let remaining = 128 * 1024;
|
|
7
|
+
return apps.map(({ packageName, appName, icon }) => {
|
|
8
|
+
const size = icon?.length ?? 0;
|
|
9
|
+
const keep = size <= 8 * 1024 && size <= remaining;
|
|
10
|
+
if (keep)
|
|
11
|
+
remaining -= size;
|
|
12
|
+
return { packageName, appName, icon: keep ? icon : null };
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=notificationAppPayload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notificationAppPayload.js","sourceRoot":"","sources":["../../src/services/notificationAppPayload.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CACpC,IAAwE;IAExE,IAAI,SAAS,GAAG,GAAG,GAAG,IAAI,CAAA;IAC1B,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAC,WAAW,EAAE,OAAO,EAAE,IAAI,EAAC,EAAE,EAAE;QAC/C,MAAM,IAAI,GAAG,IAAI,EAAE,MAAM,IAAI,CAAC,CAAA;QAC9B,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,GAAG,IAAI,IAAI,IAAI,IAAI,SAAS,CAAA;QAClD,IAAI,IAAI;YAAE,SAAS,IAAI,IAAI,CAAA;QAC3B,OAAO,EAAC,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAC,CAAA;IACzD,CAAC,CAAC,CAAA;AACJ,CAAC","sourcesContent":["/** Keep installed-app icons from exhausting the miniapp's 32 MiB JS heap.\n * Icons are optional; clients already render a fallback when one is absent.\n * Bound both individual icons and their total before JSON crosses the bridge.\n */\nexport function notificationAppPayload(\n apps: Array<{packageName: string; appName: string; icon: string | null}>,\n): Array<{packageName: string; appName: string; icon: string | null}> {\n let remaining = 128 * 1024\n return apps.map(({packageName, appName, icon}) => {\n const size = icon?.length ?? 0\n const keep = size <= 8 * 1024 && size <= remaining\n if (keep) remaining -= size\n return {packageName, appName, icon: keep ? icon : null}\n })\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settingsBridge.d.ts","sourceRoot":"","sources":["../../src/services/settingsBridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAC,gBAAgB,EAAE,gBAAgB,EAAC,MAAM,wBAAwB,CAAA;AAK9E,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,OAAO,CAAA;AAEnD,2FAA2F;AAC3F,eAAO,MAAM,oBAAoB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAwB/E,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,sEAAuE,CAAA;AACzG,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAA;AAEvE,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,IAAI,kBAAkB,CAE3E;AAED,yFAAyF;AACzF,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI,CAG7E;AAED,wDAAwD;AACxD,wBAAgB,qBAAqB,IAAI,MAAM,EAAE,CAEhD;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,EAAE,CAIrE;AAED,MAAM,MAAM,qBAAqB,
|
|
1
|
+
{"version":3,"file":"settingsBridge.d.ts","sourceRoot":"","sources":["../../src/services/settingsBridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAC,gBAAgB,EAAE,gBAAgB,EAAC,MAAM,wBAAwB,CAAA;AAK9E,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,OAAO,CAAA;AAEnD,2FAA2F;AAC3F,eAAO,MAAM,oBAAoB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAwB/E,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,sEAAuE,CAAA;AACzG,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAA;AAEvE,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,IAAI,kBAAkB,CAE3E;AAED,yFAAyF;AACzF,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI,CAG7E;AAED,wDAAwD;AACxD,wBAAgB,qBAAqB,IAAI,MAAM,EAAE,CAEhD;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,EAAE,CAIrE;AAED,MAAM,MAAM,qBAAqB,GAC/B;IAAC,EAAE,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAC,GAAG;IAAC,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,kBAAkB,GAAG,eAAe,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,CAAA;AAEpH,0FAA0F;AAC1F,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,qBAAqB,CAY3F;AAED,wEAAwE;AACxE,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,wBAAwB;IACxB,SAAS,EAAE,OAAO,CAAA;IAClB,6BAA6B;IAC7B,OAAO,EAAE;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAC,CAAA;IAC3C,qEAAqE;IACrE,OAAO,EAAE,OAAO,CAAA;CACjB;AAED,gGAAgG;AAChG,MAAM,WAAW,WAAW;IAC1B,aAAa,EAAE,OAAO,CAAA;IACtB,gBAAgB,EAAE,MAAM,CAAA;IACxB,YAAY,EAAE,OAAO,CAAA;CACtB;AAcD;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,gBAAgB,EAAE,EAC3B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAAG,SAAS,EACtD,OAAO,EAAE,WAAW,GACnB,sBAAsB,EAAE,CAqB1B"}
|
|
@@ -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_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
|
+
{"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} | {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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"appVisibility.d.ts","sourceRoot":"","sources":["../../src/stores/appVisibility.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,eAAO,MAAM,eAAe,GAAI,KAAK;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC,KAAG,OAC/B,CAAA;AAEzC,+EAA+E;AAC/E,eAAO,MAAM,mBAAmB,GAAI,gBAAgB,OAAO,EAAE,YAAY,OAAO,KAAG,OACrD,CAAA;AAE9B;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,EAAE,WAAW,CAAC,MAAM,CAA2D,CAAA;AAEnH,+EAA+E;AAC/E,eAAO,MAAM,mBAAmB,GAAI,aAAa,MAAM,KAAG,OAAmD,CAAA;AAE7G;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAKjD,CAAA;AAEF,iEAAiE;AACjE,eAAO,MAAM,iBAAiB,GAAI,aAAa,MAAM,EAAE,iBAAiB,OAAO,KAAG,OACzB,CAAA;AAEzD;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,EAAE,WAAW,CAAC,MAAM,CAAkC,CAAA;AAE1F,uFAAuF;AACvF,eAAO,MAAM,kBAAkB,
|
|
1
|
+
{"version":3,"file":"appVisibility.d.ts","sourceRoot":"","sources":["../../src/stores/appVisibility.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,eAAO,MAAM,eAAe,GAAI,KAAK;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC,KAAG,OAC/B,CAAA;AAEzC,+EAA+E;AAC/E,eAAO,MAAM,mBAAmB,GAAI,gBAAgB,OAAO,EAAE,YAAY,OAAO,KAAG,OACrD,CAAA;AAE9B;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,EAAE,WAAW,CAAC,MAAM,CAA2D,CAAA;AAEnH,+EAA+E;AAC/E,eAAO,MAAM,mBAAmB,GAAI,aAAa,MAAM,KAAG,OAAmD,CAAA;AAE7G;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAKjD,CAAA;AAEF,iEAAiE;AACjE,eAAO,MAAM,iBAAiB,GAAI,aAAa,MAAM,EAAE,iBAAiB,OAAO,KAAG,OACzB,CAAA;AAEzD;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,EAAE,WAAW,CAAC,MAAM,CAAkC,CAAA;AAE1F,uFAAuF;AACvF,eAAO,MAAM,kBAAkB,GAAI,aAAa,MAAM,EAAE,iBAAiB,OAAO,EAAE,kBAAkB,OAAO,KAAG,OAC3B,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"appVisibility.js","sourceRoot":"","sources":["../../src/stores/appVisibility.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,GAAqC,EAAW,EAAE,CAChF,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,CAAA;AAEzC,+EAA+E;AAC/E,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,cAAuB,EAAE,UAAmB,EAAW,EAAE,CAC3F,cAAc,IAAI,UAAU,CAAA;AAE9B;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAwB,IAAI,GAAG,CAAC,CAAC,oBAAoB,EAAE,sBAAsB,CAAC,CAAC,CAAA;AAEnH,+EAA+E;AAC/E,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,WAAmB,EAAW,EAAE,CAAC,uBAAuB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;AAE7G;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAwB,IAAI,GAAG,CAAC;IAC7D,wBAAwB;IACxB,qBAAqB;IACrB,oBAAoB;IACpB,qBAAqB;CACtB,CAAC,CAAA;AAEF,iEAAiE;AACjE,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,WAAmB,EAAE,eAAwB,EAAW,EAAE,CAC1F,CAAC,eAAe,IAAI,kBAAkB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;AAEzD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAwB,IAAI,GAAG,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAA;AAE1F,uFAAuF;AACvF,MAAM,CAAC,MAAM,kBAAkB,GAAG,
|
|
1
|
+
{"version":3,"file":"appVisibility.js","sourceRoot":"","sources":["../../src/stores/appVisibility.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,GAAqC,EAAW,EAAE,CAChF,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,CAAA;AAEzC,+EAA+E;AAC/E,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,cAAuB,EAAE,UAAmB,EAAW,EAAE,CAC3F,cAAc,IAAI,UAAU,CAAA;AAE9B;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAwB,IAAI,GAAG,CAAC,CAAC,oBAAoB,EAAE,sBAAsB,CAAC,CAAC,CAAA;AAEnH,+EAA+E;AAC/E,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,WAAmB,EAAW,EAAE,CAAC,uBAAuB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;AAE7G;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAwB,IAAI,GAAG,CAAC;IAC7D,wBAAwB;IACxB,qBAAqB;IACrB,oBAAoB;IACpB,qBAAqB;CACtB,CAAC,CAAA;AAEF,iEAAiE;AACjE,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,WAAmB,EAAE,eAAwB,EAAW,EAAE,CAC1F,CAAC,eAAe,IAAI,kBAAkB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;AAEzD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAwB,IAAI,GAAG,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAA;AAE1F,uFAAuF;AACvF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,WAAmB,EAAE,eAAwB,EAAE,gBAAyB,EAAW,EAAE,CACtH,CAAC,eAAe,IAAI,CAAC,gBAAgB,IAAI,uBAAuB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA","sourcesContent":["/** Host built-in phone pages and dashboard-type miniapps: never launched from a glasses menu. */\nexport const isSystemMiniapp = (app: {offline: boolean; type: string}): boolean =>\n app.offline || app.type === \"dashboard\"\n\n/** Combine registry-enforced visibility with the user's home-screen choice. */\nexport const resolveHiddenStatus = (registryHidden: boolean, userHidden: boolean): boolean =>\n registryHidden || userHidden\n\n/**\n * Miniapps that start off the primary home screen. They stay listed under\n * \"view all apps\", where \"Add to Home\" saves an explicit choice that wins\n * over this default from then on.\n */\nexport const DEFAULT_HIDDEN_PACKAGES: ReadonlySet<string> = new Set([\"com.glassly.camera\", \"com.glassly.recorder\"])\n\n/** The home-screen visibility of an app the user has never hidden or added. */\nexport const defaultHiddenStatus = (packageName: string): boolean => DEFAULT_HIDDEN_PACKAGES.has(packageName)\n\n/**\n * Miniapps that exist only for developers: the Miniapp Developer launcher and\n * the bundled sample/test miniapps. They are projected into the app store\n * only while the `dev_tools` setting is on; off, they are absent from every\n * launcher surface (home, all apps, glasses menu, AI listing), not merely\n * hidden from the primary home screen.\n */\nexport const DEV_TOOLS_PACKAGES: ReadonlySet<string> = new Set([\n \"com.glassly.miniappdev\",\n \"com.glassly.example\",\n \"com.glassly.tetris\",\n \"com.glassly.compass\",\n])\n\n/** True when the app is dev-only and developer tools are off. */\nexport const isGatedByDevTools = (packageName: string, devToolsEnabled: boolean): boolean =>\n !devToolsEnabled && DEV_TOOLS_PACKAGES.has(packageName)\n\n/**\n * Miniapps that unlock once a real pair of glasses has been paired on this\n * phone (`has_paired_glasses`, latched by PairedGlassesLatch and never\n * cleared, so forgetting the glasses keeps them). Developer tools open them\n * early. Until either, they are absent from every launcher surface like the\n * dev-only set above.\n */\nexport const PAIRED_GLASSES_PACKAGES: ReadonlySet<string> = new Set([\"com.glassly.store\"])\n\n/** True when the app waits on a pairing that hasn't happened and dev tools are off. */\nexport const isGatedUntilPaired = (packageName: string, devToolsEnabled: boolean, hasPairedGlasses: boolean): boolean =>\n !devToolsEnabled && !hasPairedGlasses && PAIRED_GLASSES_PACKAGES.has(packageName)\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gallerySync.d.ts","sourceRoot":"","sources":["../../src/stores/gallerySync.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,CAAA;IAEtB,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,MAAM,CAAA;IAEtB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAGD,MAAM,MAAM,SAAS,
|
|
1
|
+
{"version":3,"file":"gallerySync.d.ts","sourceRoot":"","sources":["../../src/stores/gallerySync.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gallerySync.js","sourceRoot":"","sources":["../../src/stores/gallerySync.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Gallery Sync Store\n * Manages gallery sync state independently of UI lifecycle\n */\n\nimport {create} from \"zustand\"\nimport {subscribeWithSelector} from \"zustand/middleware\"\n\n// Relocated from the host @/types/asg so this store is self-contained inside\n// engine. The host barrel re-exports this (a shim), so its importers are unchanged.\nexport interface PhotoInfo {\n name: string\n url: string\n download: string\n size: number\n modified: string | number // Unix timestamp (milliseconds) - can be string or number from API\n mime_type?: string\n is_video?: boolean\n thumbnail_data?: string\n downloaded_at?: number\n // Video duration in milliseconds (from glasses sync response)\n duration?: number\n // New fields for filesystem storage\n filePath?: string\n thumbnailPath?: string\n // Glasses model that captured this media\n glassesModel?: string\n}\n\n// Sync state machine states\nexport type SyncState =\n | \"idle\"\n | \"requesting_hotspot\"\n | \"connecting_wifi\"\n | \"syncing\"\n | \"complete\"\n | \"error\"\n | \"cancelled\"\n\nexport interface HotspotInfo {\n ssid: string\n password: string\n ip: string\n}\n\nexport interface SyncQueue {\n files: PhotoInfo[]\n currentIndex: number\n startedAt: number\n hotspotInfo: HotspotInfo\n}\n\nexport interface GallerySyncInfo {\n // State machine\n syncState: SyncState\n syncStarting: boolean\n\n // Progress tracking\n currentFile: string | null\n currentFileProgress: number // 0-100\n completedFiles: number\n totalFiles: number\n failedFiles: string[]\n\n // Queue (persisted separately via localStorageService)\n queue: PhotoInfo[]\n queueIndex: number\n\n // Hotspot info\n hotspotInfo: HotspotInfo | null\n syncServiceOpenedHotspot: boolean\n\n // Gallery status from glasses\n glassesPhotoCount: number\n glassesVideoCount: number\n glassesTotalCount: number\n glassesHasContent: boolean\n\n // Error tracking\n lastError: string | null\n}\n\nexport interface GallerySyncState extends GallerySyncInfo {\n // State transitions\n setSyncState: (state: SyncState) => void\n setSyncStarting: (starting: boolean) => void\n setRequestingHotspot: () => void\n setConnectingWifi: () => void\n setSyncing: (files: PhotoInfo[]) => void\n setSyncComplete: () => void\n setSyncError: (error: string) => void\n setSyncCancelled: () => void\n\n // Progress updates\n setCurrentFile: (fileName: string | null, progress: number) => void\n onFileProgress: (fileName: string, progress: number) => void\n onFileComplete: (fileName: string) => void\n onFileFailed: (fileName: string, error?: string) => void\n onFileProcessing: (fileName: string) => void\n onFileProcessed: (fileName: string) => void\n updateFileInQueue: (fileName: string, updatedFile: PhotoInfo) => void\n removeFilesFromQueue: (fileNames: string[]) => void\n\n // Processing queue tracking\n processingFiles: Set<string>\n processedFiles: number\n\n // Hotspot management\n setHotspotInfo: (info: HotspotInfo | null) => void\n setSyncServiceOpenedHotspot: (opened: boolean) => void\n\n // Gallery status from glasses\n setGlassesGalleryStatus: (photos: number, videos: number, total: number, hasContent: boolean) => void\n clearGlassesGalleryStatus: () => void\n\n // Queue management (for resume)\n setQueue: (files: PhotoInfo[], startIndex?: number) => void\n advanceQueue: () => void\n clearQueue: () => void\n\n // Full reset\n reset: () => void\n}\n\nconst initialState: GallerySyncInfo & {processingFiles: Set<string>; processedFiles: number} = {\n syncState: \"idle\",\n syncStarting: false,\n currentFile: null,\n currentFileProgress: 0,\n completedFiles: 0,\n totalFiles: 0,\n failedFiles: [],\n queue: [],\n queueIndex: 0,\n hotspotInfo: null,\n syncServiceOpenedHotspot: false,\n glassesPhotoCount: 0,\n glassesVideoCount: 0,\n glassesTotalCount: 0,\n glassesHasContent: false,\n lastError: null,\n processingFiles: new Set<string>(),\n processedFiles: 0,\n}\n\nexport const useGallerySyncStore = create<GallerySyncState>()(\n subscribeWithSelector((set, get) => ({\n ...initialState,\n\n // State transitions\n setSyncState: (syncState: SyncState) => set({syncState}),\n setSyncStarting: (syncStarting: boolean) => set({syncStarting}),\n\n setRequestingHotspot: () =>\n set({\n syncState: \"requesting_hotspot\",\n lastError: null,\n failedFiles: [],\n }),\n\n setConnectingWifi: () =>\n set({\n syncState: \"connecting_wifi\",\n }),\n\n setSyncing: (files: PhotoInfo[]) =>\n set({\n syncState: \"syncing\",\n // C4: Strip thumbnail_data (base64) from store to prevent OOM\n queue: files.map(({thumbnail_data: _thumbnailData, ...rest}) => rest),\n queueIndex: 0,\n totalFiles: files.length,\n completedFiles: 0,\n currentFile: files.length > 0 ? files[0].name : null,\n currentFileProgress: 0,\n failedFiles: [],\n lastError: null,\n processedFiles: 0,\n processingFiles: new Set<string>(),\n }),\n\n setSyncComplete: () =>\n set({\n syncState: \"complete\",\n currentFile: null,\n currentFileProgress: 0,\n // Keep queue intact so photos remain visible after sync\n // Don't clear: queue: [], queueIndex: 0\n }),\n\n setSyncError: (error: string) =>\n set({\n syncState: \"error\",\n lastError: error,\n currentFile: null,\n currentFileProgress: 0,\n }),\n\n setSyncCancelled: () =>\n set({\n syncState: \"cancelled\",\n currentFile: null,\n currentFileProgress: 0,\n queue: [],\n queueIndex: 0,\n }),\n\n // Progress updates\n setCurrentFile: (fileName: string | null, progress: number) =>\n set({\n currentFile: fileName,\n currentFileProgress: Math.max(0, Math.min(100, progress)),\n }),\n\n onFileProgress: (fileName: string, progress: number) => {\n const state = get()\n const clampedProgress = Math.max(0, Math.min(100, progress))\n // Throttle: skip update if same file and same percentage (prevents Zustand flood)\n if (clampedProgress === state.currentFileProgress && fileName === state.currentFile) {\n return\n }\n set({\n currentFile: fileName,\n currentFileProgress: clampedProgress,\n })\n },\n\n onFileComplete: (_fileName: string) => {\n const state = get()\n const newCompletedFiles = state.completedFiles + 1\n const newQueueIndex = state.queueIndex + 1\n const nextFile = state.queue[newQueueIndex]\n\n set({\n completedFiles: newCompletedFiles,\n queueIndex: newQueueIndex,\n currentFile: nextFile?.name || null,\n currentFileProgress: 0,\n })\n },\n\n onFileFailed: (fileName: string, _error?: string) => {\n const state = get()\n const newQueueIndex = state.queueIndex + 1\n const nextFile = state.queue[newQueueIndex]\n\n set({\n failedFiles: [...state.failedFiles, fileName],\n queueIndex: newQueueIndex,\n currentFile: nextFile?.name || null,\n currentFileProgress: 0,\n })\n },\n\n onFileProcessing: (fileName: string) => {\n const state = get()\n const newSet = new Set(state.processingFiles)\n newSet.add(fileName)\n set({processingFiles: newSet})\n },\n\n onFileProcessed: (fileName: string) => {\n const state = get()\n const newSet = new Set(state.processingFiles)\n newSet.delete(fileName)\n set({processingFiles: newSet, processedFiles: state.processedFiles + 1})\n },\n\n updateFileInQueue: (fileName: string, updatedFile: PhotoInfo) => {\n const state = get()\n const updatedQueue = state.queue.map((file) => (file.name === fileName ? updatedFile : file))\n set({queue: updatedQueue})\n },\n\n removeFilesFromQueue: (fileNames: string[]) => {\n if (fileNames.length === 0) return\n\n const filesToRemove = new Set(fileNames)\n const state = get()\n const failedFilesSet = new Set(state.failedFiles)\n const filesBeforeQueueIndex = state.queue\n .slice(0, state.queueIndex)\n .filter((file) => filesToRemove.has(file.name))\n const removedBeforeQueueIndex = filesBeforeQueueIndex.length\n const removedCompletedBeforeQueueIndex = filesBeforeQueueIndex.filter(\n (file) => !failedFilesSet.has(file.name),\n ).length\n const filteredQueue = state.queue.filter((file) => !filesToRemove.has(file.name))\n const removedCount = state.queue.length - filteredQueue.length\n\n if (removedCount === 0) return\n\n const nextQueueIndex = state.queueIndex - removedBeforeQueueIndex\n const currentFileRemoved = state.currentFile !== null && filesToRemove.has(state.currentFile)\n\n set({\n queue: filteredQueue,\n totalFiles: state.totalFiles - removedCount,\n completedFiles: Math.max(0, state.completedFiles - removedCompletedBeforeQueueIndex),\n queueIndex: nextQueueIndex,\n failedFiles: state.failedFiles.filter((fileName) => !filesToRemove.has(fileName)),\n processingFiles: new Set(Array.from(state.processingFiles).filter((fileName) => !filesToRemove.has(fileName))),\n currentFile: currentFileRemoved ? filteredQueue[nextQueueIndex]?.name || null : state.currentFile,\n })\n },\n\n // Hotspot management\n setHotspotInfo: (info: HotspotInfo | null) => set({hotspotInfo: info}),\n\n setSyncServiceOpenedHotspot: (opened: boolean) => set({syncServiceOpenedHotspot: opened}),\n\n // Gallery status from glasses\n setGlassesGalleryStatus: (photos: number, videos: number, total: number, hasContent: boolean) => {\n const state = get()\n // Reset to idle if sync is in a terminal state and new content is available\n // This allows syncing again after taking new photos\n const shouldResetToIdle =\n hasContent && (state.syncState === \"complete\" || state.syncState === \"error\" || state.syncState === \"cancelled\")\n\n set({\n glassesPhotoCount: photos,\n glassesVideoCount: videos,\n glassesTotalCount: total,\n glassesHasContent: hasContent,\n ...(shouldResetToIdle ? {syncState: \"idle\" as SyncState} : {}),\n })\n },\n\n clearGlassesGalleryStatus: () =>\n set({\n glassesPhotoCount: 0,\n glassesVideoCount: 0,\n glassesTotalCount: 0,\n glassesHasContent: false,\n }),\n\n // Queue management\n setQueue: (files: PhotoInfo[], startIndex: number = 0) =>\n set({\n // C4: Strip thumbnail_data (base64) from store to prevent OOM\n queue: files.map(({thumbnail_data: _thumbnailData, ...rest}) => rest),\n queueIndex: startIndex,\n totalFiles: files.length,\n completedFiles: startIndex,\n }),\n\n advanceQueue: () => {\n const state = get()\n set({queueIndex: state.queueIndex + 1})\n },\n\n clearQueue: () =>\n set({\n queue: [],\n queueIndex: 0,\n totalFiles: 0,\n completedFiles: 0,\n }),\n\n // Full reset\n reset: () => set({...initialState, processingFiles: new Set<string>()}),\n })),\n)\n\n// Selector helpers for common subscriptions\nexport const selectSyncProgress = (state: GallerySyncState) => ({\n syncState: state.syncState,\n currentFile: state.currentFile,\n currentFileProgress: state.currentFileProgress,\n completedFiles: state.completedFiles,\n totalFiles: state.totalFiles,\n failedFiles: state.failedFiles,\n processingFiles: state.processingFiles,\n})\n\nexport const selectIssyncing = (state: GallerySyncState) =>\n state.syncState === \"syncing\" || state.syncState === \"requesting_hotspot\" || state.syncState === \"connecting_wifi\"\n\nexport const selectGlassesGalleryStatus = (state: GallerySyncState) => ({\n photos: state.glassesPhotoCount,\n videos: state.glassesVideoCount,\n total: state.glassesTotalCount,\n hasContent: state.glassesHasContent,\n})\n"]}
|
|
1
|
+
{"version":3,"file":"gallerySync.js","sourceRoot":"","sources":["../../src/stores/gallerySync.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Gallery Sync Store\n * Manages gallery sync state independently of UI lifecycle\n */\n\nimport {create} from \"zustand\"\nimport {subscribeWithSelector} from \"zustand/middleware\"\n\n// Relocated from the host @/types/asg so this store is self-contained inside\n// engine. The host barrel re-exports this (a shim), so its importers are unchanged.\nexport interface PhotoInfo {\n name: string\n url: string\n download: string\n size: number\n modified: string | number // Unix timestamp (milliseconds) - can be string or number from API\n mime_type?: string\n is_video?: boolean\n thumbnail_data?: string\n downloaded_at?: number\n // Video duration in milliseconds (from glasses sync response)\n duration?: number\n // New fields for filesystem storage\n filePath?: string\n thumbnailPath?: string\n // Glasses model that captured this media\n glassesModel?: string\n}\n\n// Sync state machine states\nexport type SyncState =\n \"idle\" | \"requesting_hotspot\" | \"connecting_wifi\" | \"syncing\" | \"complete\" | \"error\" | \"cancelled\"\n\nexport interface HotspotInfo {\n ssid: string\n password: string\n ip: string\n}\n\nexport interface SyncQueue {\n files: PhotoInfo[]\n currentIndex: number\n startedAt: number\n hotspotInfo: HotspotInfo\n}\n\nexport interface GallerySyncInfo {\n // State machine\n syncState: SyncState\n syncStarting: boolean\n\n // Progress tracking\n currentFile: string | null\n currentFileProgress: number // 0-100\n completedFiles: number\n totalFiles: number\n failedFiles: string[]\n\n // Queue (persisted separately via localStorageService)\n queue: PhotoInfo[]\n queueIndex: number\n\n // Hotspot info\n hotspotInfo: HotspotInfo | null\n syncServiceOpenedHotspot: boolean\n\n // Gallery status from glasses\n glassesPhotoCount: number\n glassesVideoCount: number\n glassesTotalCount: number\n glassesHasContent: boolean\n\n // Error tracking\n lastError: string | null\n}\n\nexport interface GallerySyncState extends GallerySyncInfo {\n // State transitions\n setSyncState: (state: SyncState) => void\n setSyncStarting: (starting: boolean) => void\n setRequestingHotspot: () => void\n setConnectingWifi: () => void\n setSyncing: (files: PhotoInfo[]) => void\n setSyncComplete: () => void\n setSyncError: (error: string) => void\n setSyncCancelled: () => void\n\n // Progress updates\n setCurrentFile: (fileName: string | null, progress: number) => void\n onFileProgress: (fileName: string, progress: number) => void\n onFileComplete: (fileName: string) => void\n onFileFailed: (fileName: string, error?: string) => void\n onFileProcessing: (fileName: string) => void\n onFileProcessed: (fileName: string) => void\n updateFileInQueue: (fileName: string, updatedFile: PhotoInfo) => void\n removeFilesFromQueue: (fileNames: string[]) => void\n\n // Processing queue tracking\n processingFiles: Set<string>\n processedFiles: number\n\n // Hotspot management\n setHotspotInfo: (info: HotspotInfo | null) => void\n setSyncServiceOpenedHotspot: (opened: boolean) => void\n\n // Gallery status from glasses\n setGlassesGalleryStatus: (photos: number, videos: number, total: number, hasContent: boolean) => void\n clearGlassesGalleryStatus: () => void\n\n // Queue management (for resume)\n setQueue: (files: PhotoInfo[], startIndex?: number) => void\n advanceQueue: () => void\n clearQueue: () => void\n\n // Full reset\n reset: () => void\n}\n\nconst initialState: GallerySyncInfo & {processingFiles: Set<string>; processedFiles: number} = {\n syncState: \"idle\",\n syncStarting: false,\n currentFile: null,\n currentFileProgress: 0,\n completedFiles: 0,\n totalFiles: 0,\n failedFiles: [],\n queue: [],\n queueIndex: 0,\n hotspotInfo: null,\n syncServiceOpenedHotspot: false,\n glassesPhotoCount: 0,\n glassesVideoCount: 0,\n glassesTotalCount: 0,\n glassesHasContent: false,\n lastError: null,\n processingFiles: new Set<string>(),\n processedFiles: 0,\n}\n\nexport const useGallerySyncStore = create<GallerySyncState>()(\n subscribeWithSelector((set, get) => ({\n ...initialState,\n\n // State transitions\n setSyncState: (syncState: SyncState) => set({syncState}),\n setSyncStarting: (syncStarting: boolean) => set({syncStarting}),\n\n setRequestingHotspot: () =>\n set({\n syncState: \"requesting_hotspot\",\n lastError: null,\n failedFiles: [],\n }),\n\n setConnectingWifi: () =>\n set({\n syncState: \"connecting_wifi\",\n }),\n\n setSyncing: (files: PhotoInfo[]) =>\n set({\n syncState: \"syncing\",\n // C4: Strip thumbnail_data (base64) from store to prevent OOM\n queue: files.map(({thumbnail_data: _thumbnailData, ...rest}) => rest),\n queueIndex: 0,\n totalFiles: files.length,\n completedFiles: 0,\n currentFile: files.length > 0 ? files[0].name : null,\n currentFileProgress: 0,\n failedFiles: [],\n lastError: null,\n processedFiles: 0,\n processingFiles: new Set<string>(),\n }),\n\n setSyncComplete: () =>\n set({\n syncState: \"complete\",\n currentFile: null,\n currentFileProgress: 0,\n // Keep queue intact so photos remain visible after sync\n // Don't clear: queue: [], queueIndex: 0\n }),\n\n setSyncError: (error: string) =>\n set({\n syncState: \"error\",\n lastError: error,\n currentFile: null,\n currentFileProgress: 0,\n }),\n\n setSyncCancelled: () =>\n set({\n syncState: \"cancelled\",\n currentFile: null,\n currentFileProgress: 0,\n queue: [],\n queueIndex: 0,\n }),\n\n // Progress updates\n setCurrentFile: (fileName: string | null, progress: number) =>\n set({\n currentFile: fileName,\n currentFileProgress: Math.max(0, Math.min(100, progress)),\n }),\n\n onFileProgress: (fileName: string, progress: number) => {\n const state = get()\n const clampedProgress = Math.max(0, Math.min(100, progress))\n // Throttle: skip update if same file and same percentage (prevents Zustand flood)\n if (clampedProgress === state.currentFileProgress && fileName === state.currentFile) {\n return\n }\n set({\n currentFile: fileName,\n currentFileProgress: clampedProgress,\n })\n },\n\n onFileComplete: (_fileName: string) => {\n const state = get()\n const newCompletedFiles = state.completedFiles + 1\n const newQueueIndex = state.queueIndex + 1\n const nextFile = state.queue[newQueueIndex]\n\n set({\n completedFiles: newCompletedFiles,\n queueIndex: newQueueIndex,\n currentFile: nextFile?.name || null,\n currentFileProgress: 0,\n })\n },\n\n onFileFailed: (fileName: string, _error?: string) => {\n const state = get()\n const newQueueIndex = state.queueIndex + 1\n const nextFile = state.queue[newQueueIndex]\n\n set({\n failedFiles: [...state.failedFiles, fileName],\n queueIndex: newQueueIndex,\n currentFile: nextFile?.name || null,\n currentFileProgress: 0,\n })\n },\n\n onFileProcessing: (fileName: string) => {\n const state = get()\n const newSet = new Set(state.processingFiles)\n newSet.add(fileName)\n set({processingFiles: newSet})\n },\n\n onFileProcessed: (fileName: string) => {\n const state = get()\n const newSet = new Set(state.processingFiles)\n newSet.delete(fileName)\n set({processingFiles: newSet, processedFiles: state.processedFiles + 1})\n },\n\n updateFileInQueue: (fileName: string, updatedFile: PhotoInfo) => {\n const state = get()\n const updatedQueue = state.queue.map((file) => (file.name === fileName ? updatedFile : file))\n set({queue: updatedQueue})\n },\n\n removeFilesFromQueue: (fileNames: string[]) => {\n if (fileNames.length === 0) return\n\n const filesToRemove = new Set(fileNames)\n const state = get()\n const failedFilesSet = new Set(state.failedFiles)\n const filesBeforeQueueIndex = state.queue\n .slice(0, state.queueIndex)\n .filter((file) => filesToRemove.has(file.name))\n const removedBeforeQueueIndex = filesBeforeQueueIndex.length\n const removedCompletedBeforeQueueIndex = filesBeforeQueueIndex.filter(\n (file) => !failedFilesSet.has(file.name),\n ).length\n const filteredQueue = state.queue.filter((file) => !filesToRemove.has(file.name))\n const removedCount = state.queue.length - filteredQueue.length\n\n if (removedCount === 0) return\n\n const nextQueueIndex = state.queueIndex - removedBeforeQueueIndex\n const currentFileRemoved = state.currentFile !== null && filesToRemove.has(state.currentFile)\n\n set({\n queue: filteredQueue,\n totalFiles: state.totalFiles - removedCount,\n completedFiles: Math.max(0, state.completedFiles - removedCompletedBeforeQueueIndex),\n queueIndex: nextQueueIndex,\n failedFiles: state.failedFiles.filter((fileName) => !filesToRemove.has(fileName)),\n processingFiles: new Set(Array.from(state.processingFiles).filter((fileName) => !filesToRemove.has(fileName))),\n currentFile: currentFileRemoved ? filteredQueue[nextQueueIndex]?.name || null : state.currentFile,\n })\n },\n\n // Hotspot management\n setHotspotInfo: (info: HotspotInfo | null) => set({hotspotInfo: info}),\n\n setSyncServiceOpenedHotspot: (opened: boolean) => set({syncServiceOpenedHotspot: opened}),\n\n // Gallery status from glasses\n setGlassesGalleryStatus: (photos: number, videos: number, total: number, hasContent: boolean) => {\n const state = get()\n // Reset to idle if sync is in a terminal state and new content is available\n // This allows syncing again after taking new photos\n const shouldResetToIdle =\n hasContent && (state.syncState === \"complete\" || state.syncState === \"error\" || state.syncState === \"cancelled\")\n\n set({\n glassesPhotoCount: photos,\n glassesVideoCount: videos,\n glassesTotalCount: total,\n glassesHasContent: hasContent,\n ...(shouldResetToIdle ? {syncState: \"idle\" as SyncState} : {}),\n })\n },\n\n clearGlassesGalleryStatus: () =>\n set({\n glassesPhotoCount: 0,\n glassesVideoCount: 0,\n glassesTotalCount: 0,\n glassesHasContent: false,\n }),\n\n // Queue management\n setQueue: (files: PhotoInfo[], startIndex: number = 0) =>\n set({\n // C4: Strip thumbnail_data (base64) from store to prevent OOM\n queue: files.map(({thumbnail_data: _thumbnailData, ...rest}) => rest),\n queueIndex: startIndex,\n totalFiles: files.length,\n completedFiles: startIndex,\n }),\n\n advanceQueue: () => {\n const state = get()\n set({queueIndex: state.queueIndex + 1})\n },\n\n clearQueue: () =>\n set({\n queue: [],\n queueIndex: 0,\n totalFiles: 0,\n completedFiles: 0,\n }),\n\n // Full reset\n reset: () => set({...initialState, processingFiles: new Set<string>()}),\n })),\n)\n\n// Selector helpers for common subscriptions\nexport const selectSyncProgress = (state: GallerySyncState) => ({\n syncState: state.syncState,\n currentFile: state.currentFile,\n currentFileProgress: state.currentFileProgress,\n completedFiles: state.completedFiles,\n totalFiles: state.totalFiles,\n failedFiles: state.failedFiles,\n processingFiles: state.processingFiles,\n})\n\nexport const selectIssyncing = (state: GallerySyncState) =>\n state.syncState === \"syncing\" || state.syncState === \"requesting_hotspot\" || state.syncState === \"connecting_wifi\"\n\nexport const selectGlassesGalleryStatus = (state: GallerySyncState) => ({\n photos: state.glassesPhotoCount,\n videos: state.glassesVideoCount,\n total: state.glassesTotalCount,\n hasContent: state.glassesHasContent,\n})\n"]}
|
package/build/stores/settings.js
CHANGED
|
@@ -290,7 +290,7 @@ export const SETTINGS = {
|
|
|
290
290
|
saveOnServer: false,
|
|
291
291
|
persist: true,
|
|
292
292
|
},
|
|
293
|
-
// User-supplied AI/voice provider keys (Settings > API Keys). Not consumed
|
|
293
|
+
// User-supplied AI/voice provider keys (Settings > Privacy > API Keys). Not consumed
|
|
294
294
|
// by the app itself — they exist so miniapps declaring the API_KEYS manifest
|
|
295
295
|
// permission can read them via session.keys.get() (see
|
|
296
296
|
// MINIAPP_READABLE_API_KEYS in LocalMiniappRuntime; mapbox is also readable
|