@glassly/engine 0.2.9-dev.452 → 0.2.9-dev.455
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/facades/miniapps.d.ts +2 -2
- package/build/facades/miniapps.d.ts.map +1 -1
- package/build/facades/miniapps.js +2 -2
- package/build/facades/miniapps.js.map +1 -1
- package/build/generated/releaseMetadata.js +3 -3
- package/build/generated/releaseMetadata.js.map +1 -1
- package/build/index.d.ts +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -1
- package/build/index.js.map +1 -1
- package/build/services/AppRegistry.d.ts +3 -3
- package/build/services/AppRegistry.d.ts.map +1 -1
- package/build/services/AppRegistry.js +6 -6
- package/build/services/AppRegistry.js.map +1 -1
- package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
- package/build/services/LocalMiniappRuntime.js +2 -3
- package/build/services/LocalMiniappRuntime.js.map +1 -1
- package/build/services/MiniappLauncher.d.ts +2 -2
- package/build/services/MiniappLauncher.js +3 -3
- package/build/services/MiniappLauncher.js.map +1 -1
- package/build/services/pages/overlayApps.d.ts +3 -4
- package/build/services/pages/overlayApps.d.ts.map +1 -1
- package/build/services/pages/overlayApps.js +3 -4
- package/build/services/pages/overlayApps.js.map +1 -1
- package/build/stores/apps.d.ts +5 -5
- package/build/stores/apps.d.ts.map +1 -1
- package/build/stores/apps.js +9 -9
- package/build/stores/apps.js.map +1 -1
- package/build/types/applet.d.ts +4 -4
- package/build/types/applet.d.ts.map +1 -1
- package/build/types/applet.js.map +1 -1
- package/package.json +7 -7
- package/src/facades/miniapps.ts +2 -3
- package/src/generated/releaseMetadata.ts +3 -3
- package/src/index.ts +1 -1
- package/src/services/AppRegistry.ts +7 -7
- package/src/services/LocalMiniappRuntime.ts +2 -3
- package/src/services/MiniappLauncher.ts +3 -3
- package/src/services/pages/overlayApps.ts +3 -4
- package/src/stores/apps.ts +12 -12
- package/src/types/applet.ts +4 -4
|
@@ -112,10 +112,10 @@ declare class MiniappLauncher {
|
|
|
112
112
|
* dropped just because glasses are momentarily disconnected at boot — it
|
|
113
113
|
* resumes when they reconnect, same as mid-session.
|
|
114
114
|
*
|
|
115
|
-
*
|
|
115
|
+
* Always On apps (the dashboard) start whether or not they were running
|
|
116
116
|
* when the app was last killed, and get a switcher card like any other app.
|
|
117
117
|
* Both restore paths skip apps missing required OS permissions without
|
|
118
|
-
* prompting or clearing their saved running/
|
|
118
|
+
* prompting or clearing their saved running/Always On choice.
|
|
119
119
|
*/
|
|
120
120
|
autostartLocalMiniapps(): Promise<void>;
|
|
121
121
|
/**
|
|
@@ -243,10 +243,10 @@ class MiniappLauncher {
|
|
|
243
243
|
* dropped just because glasses are momentarily disconnected at boot — it
|
|
244
244
|
* resumes when they reconnect, same as mid-session.
|
|
245
245
|
*
|
|
246
|
-
*
|
|
246
|
+
* Always On apps (the dashboard) start whether or not they were running
|
|
247
247
|
* when the app was last killed, and get a switcher card like any other app.
|
|
248
248
|
* Both restore paths skip apps missing required OS permissions without
|
|
249
|
-
* prompting or clearing their saved running/
|
|
249
|
+
* prompting or clearing their saved running/Always On choice.
|
|
250
250
|
*/
|
|
251
251
|
async autostartLocalMiniapps() {
|
|
252
252
|
const apps = await appRegistry.getInstalledMiniapps();
|
|
@@ -256,7 +256,7 @@ class MiniappLauncher {
|
|
|
256
256
|
// state elsewhere and have no bundle to launch.
|
|
257
257
|
if (!app.local)
|
|
258
258
|
continue;
|
|
259
|
-
if (!app.
|
|
259
|
+
if (!app.alwaysOn && !getLocalAppRunningState(app.packageName))
|
|
260
260
|
continue;
|
|
261
261
|
if (this.isRunning(app.packageName))
|
|
262
262
|
continue;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MiniappLauncher.js","sourceRoot":"","sources":["../../src/services/MiniappLauncher.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * MiniappLauncher — headless launch/teardown of a local miniapp's background\n * JS context.\n *\n * This is the one piece of \"run a miniapp\" that used to live inside the\n * `LocalMiniappView` React component (resolve the bundle → read the manifest →\n * `spawnAndRegister`), triggered only when the Compositor mounted that\n * component on foreground. Pulling it into the runtime means:\n *\n * - `start()` can actually spawn an app even when nothing foregrounds it\n * (e.g. a system app launching another miniapp via `session.miniapps`).\n * - the action broker can wake a stopped target headlessly — no UI at all.\n * - the dev hot-reload respawn path and the WebView mount path share one\n * resolve+spawn recipe instead of three copies.\n *\n * The launcher is **headless**: no React, no RN components. The engine-owned\n * MiniappEngine hands it the {@link JSRouter} instance once during\n * engine construction. OEMs embedding the runtime drive miniapp lifecycle\n * through the engine facade and stores, not a separate launcher configure API.\n *\n * Boundary: the launcher owns the **background** context. WebView *rendering*\n * (the UI layer) stays with the host — the launcher just hands back the\n * resolved UI entry so the host can mount its `<WebView>`.\n */\n\nimport {File} from \"expo-file-system\"\n\nimport {permissions} from \"../facades/permissions\"\nimport {decideDevLaunchRoute} from \"../utils/devMiniappLaunch\"\nimport {storage} from \"../utils/storage/storage\"\nimport appRegistry, {getLocalAppRunningState, saveLocalAppRunningState} from \"./AppRegistry\"\nimport devServerBridge from \"./DevServerBridge\"\nimport localMiniappRuntime, {type InstalledMiniappManifest} from \"./LocalMiniappRuntime\"\nimport type {MiniappLaunchSource} from \"@glassly/miniapp\"\nimport type {JSRouter} from \"./JSRouter\"\n\ninterface LauncherDeps {\n /** The host-constructed router (needs the native Crust binding). */\n router: JSRouter\n}\n\n/** Hints the host may pass from a view's props to avoid re-deriving them. */\nexport interface LaunchHints {\n devUrl?: string\n version?: string\n devPort?: string\n /** Who started the app; reported to the miniapp on connect. */\n launchSource?: MiniappLaunchSource\n}\n\n/** Everything the launcher resolved for a package — bg source + UI entry. */\nexport interface ResolvedBundle {\n bgSource: string\n uiUri: string | null\n uiBaseDir: string | null\n declaredPermissions: string[]\n installedManifest?: InstalledMiniappManifest\n /** Set for dev miniapps (HTTP off the dev server); null for released. */\n devUrl: string | null\n devPort: number | null\n}\n\n/** What the host needs back to render the UI layer. */\nexport interface LaunchResult {\n uiUri: string | null\n uiBaseDir: string | null\n}\n\nclass MiniappLauncher {\n private deps: LauncherDeps | null = null\n\n /**\n * In-flight launches keyed by packageName. Both apps.ts start() and the\n * WebView mount call ensureRunning() before the first spawnAndRegister\n * resolves — without this, neither sees the package in registeredPackages()\n * yet and both spawn the same context (a clobber/double-spawn). Concurrent\n * callers share the same promise.\n */\n private readonly inFlight = new Map<string, Promise<LaunchResult>>()\n\n /** Wire the router in. Called once from MiniappEngine construction. */\n configure(deps: LauncherDeps): void {\n this.deps = deps\n }\n\n private requireRouter(): JSRouter {\n if (!this.deps) {\n throw new Error(\"MiniappLauncher not configured — ensureMiniappEngine() has not run\")\n }\n return this.deps.router\n }\n\n /** True iff the package's background JS context is currently spawned. */\n isRunning(packageName: string): boolean {\n return this.deps?.router.registeredPackages().includes(packageName) ?? false\n }\n\n /**\n * Resolve the background JS source + UI entry + declared permissions for a\n * package. Handles both dev (HTTP off the running dev server) and released\n * (file:// from the installed snapshot). Reads disk/network/storage; does\n * NOT spawn. Returns null when the bundle can't be resolved (dev server\n * unreachable, missing entry, no installed version).\n */\n async resolveBundle(packageName: string, hints?: LaunchHints): Promise<ResolvedBundle | null> {\n const devUrl = hints?.devUrl ?? this.storedDevUrl(packageName)\n\n // --- Dev: load directly off the local dev server over HTTP. ---\n if (devUrl) {\n const route = await decideDevLaunchRoute(packageName, devUrl)\n if (route.decision === \"offline\" || !route.manifest) return null\n const manifest = route.manifest\n const entry = manifest.entry as {background?: string; ui?: string} | undefined\n if (!entry?.background) return null\n\n // Use the host that actually answered — may differ from the stored IP\n // after a laptop Wi-Fi change (mDNS / Metro failover inside decideDevLaunchRoute).\n const base = route.resolvedUrl.replace(/\\/$/, \"\")\n // entry.* are bundle-root paths (dist/ stripped); the dev server serves\n // files relative to cwd, so prepend dist/.\n const bgUrl = `${base}/dist/${entry.background.replace(/^\\.?\\/+/, \"\")}`\n const uiUri = entry.ui ? `${base}/dist/${entry.ui.replace(/^\\.?\\/+/, \"\")}` : null\n\n const perms = manifest.permissions as Array<{type?: string} | string> | undefined\n const declaredPermissions = (perms ?? [])\n .map((p) => (typeof p === \"string\" ? p : p?.type))\n .filter((t): t is string => typeof t === \"string\")\n const installedManifest: InstalledMiniappManifest = {\n packageName: typeof manifest.packageName === \"string\" ? manifest.packageName : packageName,\n name: manifest.name,\n version: typeof manifest.version === \"string\" ? manifest.version : undefined,\n sdkVersion: typeof manifest.sdkVersion === \"string\" ? manifest.sdkVersion : undefined,\n minHostVersion: typeof manifest.minHostVersion === \"string\" ? manifest.minHostVersion : undefined,\n type: typeof manifest.type === \"string\" ? manifest.type : undefined,\n entry: manifest.entry as InstalledMiniappManifest[\"entry\"],\n permissions: manifest.permissions as InstalledMiniappManifest[\"permissions\"],\n hardwareRequirements: manifest.hardwareRequirements as InstalledMiniappManifest[\"hardwareRequirements\"],\n actions: manifest.actions as InstalledMiniappManifest[\"actions\"],\n }\n\n let bgSource: string\n try {\n const res = await fetch(bgUrl)\n if (!res.ok) return null\n bgSource = await res.text()\n } catch {\n return null\n }\n\n return {\n bgSource,\n uiUri,\n uiBaseDir: uiUri ? uiUri.replace(/\\/[^/]+$/, \"/\") : null,\n declaredPermissions,\n installedManifest,\n devUrl: route.resolvedUrl,\n devPort: this.resolveDevPort(hints?.devPort, packageName),\n }\n }\n\n // --- Released: resolve from the installed file:// snapshot. ---\n const version = hints?.version ?? (await appRegistry.getActiveVersion(packageName))\n if (!version) return null\n const entryPaths = appRegistry.getMiniappEntryPaths(packageName, version)\n if (!entryPaths?.background) return null\n\n const manifest = appRegistry.getMiniappManifest(packageName, version) as {\n packageName?: string\n name?: string\n version?: string\n sdkVersion?: string\n minHostVersion?: string\n type?: string\n entry?: {background?: string; ui?: string}\n permissions?: Array<{type: string; required?: boolean; description?: string}>\n hardwareRequirements?: Array<{type: string; level: string; description?: string}>\n actions?: Array<{id?: unknown; description?: unknown; parameters?: unknown; outputSchema?: unknown}>\n } | null\n const declaredPermissions = (manifest?.permissions ?? [])\n .map((p) => p.type)\n .filter((t): t is string => typeof t === \"string\")\n const installedManifest: InstalledMiniappManifest | undefined = manifest\n ? {\n packageName: manifest.packageName ?? packageName,\n name: manifest.name,\n version: manifest.version ?? version,\n sdkVersion: manifest.sdkVersion,\n minHostVersion: manifest.minHostVersion,\n type: manifest.type,\n entry: manifest.entry,\n permissions: manifest.permissions,\n hardwareRequirements: manifest.hardwareRequirements,\n actions: manifest.actions,\n }\n : undefined\n\n let bgSource: string\n try {\n bgSource = new File(entryPaths.background).textSync()\n } catch {\n return null\n }\n\n return {\n bgSource,\n uiUri: entryPaths.ui ?? null,\n uiBaseDir: entryPaths.ui ? entryPaths.ui.replace(/\\/[^/]+$/, \"/\") : null,\n declaredPermissions,\n installedManifest,\n devUrl: null,\n devPort: null,\n }\n }\n\n /**\n * Ensure a miniapp's background JS context is spawned. Idempotent — if the\n * context is already alive this is a no-op spawn-wise (it still resolves the\n * UI entry so a re-mounting host gets its `<WebView>` source back).\n *\n * Resolves once the context is SPAWNED. It does NOT block on the context's\n * CONNECT handshake — the host's WebView mount shouldn't wait on background\n * JS. Callers that need the context to be connected and ready to receive\n * messages (the action broker) follow up with\n * {@link LocalMiniappRuntime.waitForConnect}.\n */\n async ensureRunning(packageName: string, hints?: LaunchHints): Promise<LaunchResult> {\n const router = this.requireRouter()\n\n // Already spawned: best-effort resolve for the UI entry, never throw —\n // a headless caller that doesn't need UI gets {null, null} fast even if\n // the dev server has since dropped.\n if (router.registeredPackages().includes(packageName)) {\n const existing = await this.resolveBundle(packageName, hints).catch(() => null)\n return {uiUri: existing?.uiUri ?? null, uiBaseDir: existing?.uiBaseDir ?? null}\n }\n\n // Coalesce concurrent launches of the same package onto one promise.\n const pending = this.inFlight.get(packageName)\n if (pending) return pending\n\n const launch = this.spawn(packageName, hints)\n this.inFlight.set(packageName, launch)\n try {\n return await launch\n } finally {\n this.inFlight.delete(packageName)\n }\n }\n\n /** Resolve the bundle and spawn the context. Serialized via {@link inFlight}. */\n private async spawn(packageName: string, hints?: LaunchHints): Promise<LaunchResult> {\n const router = this.requireRouter()\n const resolved = await this.resolveBundle(packageName, hints)\n if (!resolved) {\n throw new Error(`MiniappLauncher: cannot resolve bundle for ${packageName}`)\n }\n\n // Re-check after the async resolve: a different path may have spawned it\n // while we were fetching/reading the bundle.\n if (!router.registeredPackages().includes(packageName)) {\n const ok = await router.spawnAndRegister(packageName, resolved.bgSource, {\n permissions: resolved.declaredPermissions,\n installedManifest: resolved.installedManifest,\n launchSource: hints?.launchSource,\n })\n if (!ok) {\n throw new Error(`MiniappLauncher: spawn failed for ${packageName}`)\n }\n\n // Dev: wire the hot-reload + log-forwarding sidecar. No-op in prod\n // (devServerBridge silently drops when no sidecar is up).\n if (resolved.devUrl && resolved.devPort != null) {\n devServerBridge.connect(packageName, resolved.devUrl, resolved.devPort)\n } else if (resolved.devUrl) {\n // Dev miniapp with no resolvable port — it still launches, but hot\n // reload + log forwarding won't connect. Surface it instead of failing\n // silently (the old inline path hard-failed with \"no dev port\").\n console.warn(`MiniappLauncher: ${packageName} has no dev port — hot reload + log forwarding disabled`)\n }\n }\n\n return {uiUri: resolved.uiUri, uiBaseDir: resolved.uiBaseDir}\n }\n\n /**\n * Re-spawn local miniapps that were running when the app was last killed.\n *\n * Miniapps run in the phone's own JS engine, so a host-process kill tears\n * down their JSContext with nothing to resurrect them. Without this they\n * would silently stay stopped on the next launch even though the user left\n * them running.\n *\n * Each local miniapp persists its running flag to disk on start/stop\n * (`saveLocalAppRunningState`, via the applet's `onStart`/`onStop`). We read\n * those flags back and re-spawn the background context headlessly (no\n * foreground, no navigation) — the spawn registers the package so the home\n * tray/switcher project it as running, exactly as a normal start would. The\n * WebView, if any, re-attaches lazily when the user opens the app.\n *\n * Idempotent and best-effort: skips already-spawned contexts, and clears the\n * persisted flag for any app whose bundle can no longer be resolved\n * (uninstalled, or dev server gone) so a dead entry doesn't retry every boot.\n * Not compatibility-gated: a previously-running background app shouldn't be\n * dropped just because glasses are momentarily disconnected at boot — it\n * resumes when they reconnect, same as mid-session.\n *\n * Persistent apps (the dashboard) start whether or not they were running\n * when the app was last killed, and get a switcher card like any other app.\n * Both restore paths skip apps missing required OS permissions without\n * prompting or clearing their saved running/persistent choice.\n */\n async autostartLocalMiniapps(): Promise<void> {\n const apps = await appRegistry.getInstalledMiniapps()\n for (const app of apps) {\n // Only phone-hosted miniapps have a JSContext to re-spawn. Offline\n // built-ins (`local:false, offline:true`) restore their native running\n // state elsewhere and have no bundle to launch.\n if (!app.local) continue\n if (!app.persistent && !getLocalAppRunningState(app.packageName)) continue\n if (this.isRunning(app.packageName)) continue\n try {\n const missing = await permissions.missingRequired(app.permissions ?? [])\n if (missing.length > 0) {\n console.info(\n `MiniappLauncher: skipping autostart for ${app.packageName} — missing required permissions: ${missing.join(\n \", \",\n )}`,\n )\n continue\n }\n } catch (e) {\n console.warn(`MiniappLauncher: skipping autostart for ${app.packageName} — permission check failed`, e)\n continue\n }\n try {\n await this.ensureRunning(app.packageName)\n } catch (e) {\n console.warn(`MiniappLauncher: autostart failed for ${app.packageName} — clearing stale running flag`, e)\n saveLocalAppRunningState(app.packageName, false)\n }\n }\n }\n\n /**\n * Ensure the context is running AND has completed its CONNECT handshake.\n * Used by the action broker, which must not deliver to a context that hasn't\n * come up yet. Throws on spawn failure or connect timeout.\n */\n async ensureConnected(packageName: string, connectTimeoutMs = 10_000, hints?: LaunchHints): Promise<void> {\n await this.ensureRunning(packageName, hints)\n await localMiniappRuntime.waitForConnect(packageName, connectTimeoutMs)\n }\n\n /** Tear down a miniapp's background JS context. */\n async stop(packageName: string): Promise<void> {\n // If a launch is in flight, let it finish first. Otherwise unregister()\n // no-ops on the not-yet-registered package and the pending spawn then\n // re-registers the context — leaving it running despite the stop.\n const pending = this.inFlight.get(packageName)\n if (pending) {\n try {\n await pending\n } catch {\n // Launch failed — nothing got registered, so nothing to tear down.\n }\n }\n await this.deps?.router.unregister(packageName)\n }\n\n // --- internals -----------------------------------------------------------\n\n private storedDevUrl(packageName: string): string | undefined {\n const r = storage.load<string>(`${packageName}_dev_url`)\n return r.is_ok() ? r.value : undefined\n }\n\n /** resolveDevPort — moved verbatim from the old LocalMiniappView helper. */\n private resolveDevPort(searchParam: string | undefined, packageName: string): number | null {\n if (searchParam) {\n const n = parseInt(searchParam, 10)\n if (Number.isFinite(n)) return n\n }\n const stored = storage.load<number>(`${packageName}_dev_port`)\n if (stored.is_ok()) return stored.value\n return null\n }\n}\n\nexport const miniappLauncher = new MiniappLauncher()\n"]}
|
|
1
|
+
{"version":3,"file":"MiniappLauncher.js","sourceRoot":"","sources":["../../src/services/MiniappLauncher.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * MiniappLauncher — headless launch/teardown of a local miniapp's background\n * JS context.\n *\n * This is the one piece of \"run a miniapp\" that used to live inside the\n * `LocalMiniappView` React component (resolve the bundle → read the manifest →\n * `spawnAndRegister`), triggered only when the Compositor mounted that\n * component on foreground. Pulling it into the runtime means:\n *\n * - `start()` can actually spawn an app even when nothing foregrounds it\n * (e.g. a system app launching another miniapp via `session.miniapps`).\n * - the action broker can wake a stopped target headlessly — no UI at all.\n * - the dev hot-reload respawn path and the WebView mount path share one\n * resolve+spawn recipe instead of three copies.\n *\n * The launcher is **headless**: no React, no RN components. The engine-owned\n * MiniappEngine hands it the {@link JSRouter} instance once during\n * engine construction. OEMs embedding the runtime drive miniapp lifecycle\n * through the engine facade and stores, not a separate launcher configure API.\n *\n * Boundary: the launcher owns the **background** context. WebView *rendering*\n * (the UI layer) stays with the host — the launcher just hands back the\n * resolved UI entry so the host can mount its `<WebView>`.\n */\n\nimport {File} from \"expo-file-system\"\n\nimport {permissions} from \"../facades/permissions\"\nimport {decideDevLaunchRoute} from \"../utils/devMiniappLaunch\"\nimport {storage} from \"../utils/storage/storage\"\nimport appRegistry, {getLocalAppRunningState, saveLocalAppRunningState} from \"./AppRegistry\"\nimport devServerBridge from \"./DevServerBridge\"\nimport localMiniappRuntime, {type InstalledMiniappManifest} from \"./LocalMiniappRuntime\"\nimport type {MiniappLaunchSource} from \"@glassly/miniapp\"\nimport type {JSRouter} from \"./JSRouter\"\n\ninterface LauncherDeps {\n /** The host-constructed router (needs the native Crust binding). */\n router: JSRouter\n}\n\n/** Hints the host may pass from a view's props to avoid re-deriving them. */\nexport interface LaunchHints {\n devUrl?: string\n version?: string\n devPort?: string\n /** Who started the app; reported to the miniapp on connect. */\n launchSource?: MiniappLaunchSource\n}\n\n/** Everything the launcher resolved for a package — bg source + UI entry. */\nexport interface ResolvedBundle {\n bgSource: string\n uiUri: string | null\n uiBaseDir: string | null\n declaredPermissions: string[]\n installedManifest?: InstalledMiniappManifest\n /** Set for dev miniapps (HTTP off the dev server); null for released. */\n devUrl: string | null\n devPort: number | null\n}\n\n/** What the host needs back to render the UI layer. */\nexport interface LaunchResult {\n uiUri: string | null\n uiBaseDir: string | null\n}\n\nclass MiniappLauncher {\n private deps: LauncherDeps | null = null\n\n /**\n * In-flight launches keyed by packageName. Both apps.ts start() and the\n * WebView mount call ensureRunning() before the first spawnAndRegister\n * resolves — without this, neither sees the package in registeredPackages()\n * yet and both spawn the same context (a clobber/double-spawn). Concurrent\n * callers share the same promise.\n */\n private readonly inFlight = new Map<string, Promise<LaunchResult>>()\n\n /** Wire the router in. Called once from MiniappEngine construction. */\n configure(deps: LauncherDeps): void {\n this.deps = deps\n }\n\n private requireRouter(): JSRouter {\n if (!this.deps) {\n throw new Error(\"MiniappLauncher not configured — ensureMiniappEngine() has not run\")\n }\n return this.deps.router\n }\n\n /** True iff the package's background JS context is currently spawned. */\n isRunning(packageName: string): boolean {\n return this.deps?.router.registeredPackages().includes(packageName) ?? false\n }\n\n /**\n * Resolve the background JS source + UI entry + declared permissions for a\n * package. Handles both dev (HTTP off the running dev server) and released\n * (file:// from the installed snapshot). Reads disk/network/storage; does\n * NOT spawn. Returns null when the bundle can't be resolved (dev server\n * unreachable, missing entry, no installed version).\n */\n async resolveBundle(packageName: string, hints?: LaunchHints): Promise<ResolvedBundle | null> {\n const devUrl = hints?.devUrl ?? this.storedDevUrl(packageName)\n\n // --- Dev: load directly off the local dev server over HTTP. ---\n if (devUrl) {\n const route = await decideDevLaunchRoute(packageName, devUrl)\n if (route.decision === \"offline\" || !route.manifest) return null\n const manifest = route.manifest\n const entry = manifest.entry as {background?: string; ui?: string} | undefined\n if (!entry?.background) return null\n\n // Use the host that actually answered — may differ from the stored IP\n // after a laptop Wi-Fi change (mDNS / Metro failover inside decideDevLaunchRoute).\n const base = route.resolvedUrl.replace(/\\/$/, \"\")\n // entry.* are bundle-root paths (dist/ stripped); the dev server serves\n // files relative to cwd, so prepend dist/.\n const bgUrl = `${base}/dist/${entry.background.replace(/^\\.?\\/+/, \"\")}`\n const uiUri = entry.ui ? `${base}/dist/${entry.ui.replace(/^\\.?\\/+/, \"\")}` : null\n\n const perms = manifest.permissions as Array<{type?: string} | string> | undefined\n const declaredPermissions = (perms ?? [])\n .map((p) => (typeof p === \"string\" ? p : p?.type))\n .filter((t): t is string => typeof t === \"string\")\n const installedManifest: InstalledMiniappManifest = {\n packageName: typeof manifest.packageName === \"string\" ? manifest.packageName : packageName,\n name: manifest.name,\n version: typeof manifest.version === \"string\" ? manifest.version : undefined,\n sdkVersion: typeof manifest.sdkVersion === \"string\" ? manifest.sdkVersion : undefined,\n minHostVersion: typeof manifest.minHostVersion === \"string\" ? manifest.minHostVersion : undefined,\n type: typeof manifest.type === \"string\" ? manifest.type : undefined,\n entry: manifest.entry as InstalledMiniappManifest[\"entry\"],\n permissions: manifest.permissions as InstalledMiniappManifest[\"permissions\"],\n hardwareRequirements: manifest.hardwareRequirements as InstalledMiniappManifest[\"hardwareRequirements\"],\n actions: manifest.actions as InstalledMiniappManifest[\"actions\"],\n }\n\n let bgSource: string\n try {\n const res = await fetch(bgUrl)\n if (!res.ok) return null\n bgSource = await res.text()\n } catch {\n return null\n }\n\n return {\n bgSource,\n uiUri,\n uiBaseDir: uiUri ? uiUri.replace(/\\/[^/]+$/, \"/\") : null,\n declaredPermissions,\n installedManifest,\n devUrl: route.resolvedUrl,\n devPort: this.resolveDevPort(hints?.devPort, packageName),\n }\n }\n\n // --- Released: resolve from the installed file:// snapshot. ---\n const version = hints?.version ?? (await appRegistry.getActiveVersion(packageName))\n if (!version) return null\n const entryPaths = appRegistry.getMiniappEntryPaths(packageName, version)\n if (!entryPaths?.background) return null\n\n const manifest = appRegistry.getMiniappManifest(packageName, version) as {\n packageName?: string\n name?: string\n version?: string\n sdkVersion?: string\n minHostVersion?: string\n type?: string\n entry?: {background?: string; ui?: string}\n permissions?: Array<{type: string; required?: boolean; description?: string}>\n hardwareRequirements?: Array<{type: string; level: string; description?: string}>\n actions?: Array<{id?: unknown; description?: unknown; parameters?: unknown; outputSchema?: unknown}>\n } | null\n const declaredPermissions = (manifest?.permissions ?? [])\n .map((p) => p.type)\n .filter((t): t is string => typeof t === \"string\")\n const installedManifest: InstalledMiniappManifest | undefined = manifest\n ? {\n packageName: manifest.packageName ?? packageName,\n name: manifest.name,\n version: manifest.version ?? version,\n sdkVersion: manifest.sdkVersion,\n minHostVersion: manifest.minHostVersion,\n type: manifest.type,\n entry: manifest.entry,\n permissions: manifest.permissions,\n hardwareRequirements: manifest.hardwareRequirements,\n actions: manifest.actions,\n }\n : undefined\n\n let bgSource: string\n try {\n bgSource = new File(entryPaths.background).textSync()\n } catch {\n return null\n }\n\n return {\n bgSource,\n uiUri: entryPaths.ui ?? null,\n uiBaseDir: entryPaths.ui ? entryPaths.ui.replace(/\\/[^/]+$/, \"/\") : null,\n declaredPermissions,\n installedManifest,\n devUrl: null,\n devPort: null,\n }\n }\n\n /**\n * Ensure a miniapp's background JS context is spawned. Idempotent — if the\n * context is already alive this is a no-op spawn-wise (it still resolves the\n * UI entry so a re-mounting host gets its `<WebView>` source back).\n *\n * Resolves once the context is SPAWNED. It does NOT block on the context's\n * CONNECT handshake — the host's WebView mount shouldn't wait on background\n * JS. Callers that need the context to be connected and ready to receive\n * messages (the action broker) follow up with\n * {@link LocalMiniappRuntime.waitForConnect}.\n */\n async ensureRunning(packageName: string, hints?: LaunchHints): Promise<LaunchResult> {\n const router = this.requireRouter()\n\n // Already spawned: best-effort resolve for the UI entry, never throw —\n // a headless caller that doesn't need UI gets {null, null} fast even if\n // the dev server has since dropped.\n if (router.registeredPackages().includes(packageName)) {\n const existing = await this.resolveBundle(packageName, hints).catch(() => null)\n return {uiUri: existing?.uiUri ?? null, uiBaseDir: existing?.uiBaseDir ?? null}\n }\n\n // Coalesce concurrent launches of the same package onto one promise.\n const pending = this.inFlight.get(packageName)\n if (pending) return pending\n\n const launch = this.spawn(packageName, hints)\n this.inFlight.set(packageName, launch)\n try {\n return await launch\n } finally {\n this.inFlight.delete(packageName)\n }\n }\n\n /** Resolve the bundle and spawn the context. Serialized via {@link inFlight}. */\n private async spawn(packageName: string, hints?: LaunchHints): Promise<LaunchResult> {\n const router = this.requireRouter()\n const resolved = await this.resolveBundle(packageName, hints)\n if (!resolved) {\n throw new Error(`MiniappLauncher: cannot resolve bundle for ${packageName}`)\n }\n\n // Re-check after the async resolve: a different path may have spawned it\n // while we were fetching/reading the bundle.\n if (!router.registeredPackages().includes(packageName)) {\n const ok = await router.spawnAndRegister(packageName, resolved.bgSource, {\n permissions: resolved.declaredPermissions,\n installedManifest: resolved.installedManifest,\n launchSource: hints?.launchSource,\n })\n if (!ok) {\n throw new Error(`MiniappLauncher: spawn failed for ${packageName}`)\n }\n\n // Dev: wire the hot-reload + log-forwarding sidecar. No-op in prod\n // (devServerBridge silently drops when no sidecar is up).\n if (resolved.devUrl && resolved.devPort != null) {\n devServerBridge.connect(packageName, resolved.devUrl, resolved.devPort)\n } else if (resolved.devUrl) {\n // Dev miniapp with no resolvable port — it still launches, but hot\n // reload + log forwarding won't connect. Surface it instead of failing\n // silently (the old inline path hard-failed with \"no dev port\").\n console.warn(`MiniappLauncher: ${packageName} has no dev port — hot reload + log forwarding disabled`)\n }\n }\n\n return {uiUri: resolved.uiUri, uiBaseDir: resolved.uiBaseDir}\n }\n\n /**\n * Re-spawn local miniapps that were running when the app was last killed.\n *\n * Miniapps run in the phone's own JS engine, so a host-process kill tears\n * down their JSContext with nothing to resurrect them. Without this they\n * would silently stay stopped on the next launch even though the user left\n * them running.\n *\n * Each local miniapp persists its running flag to disk on start/stop\n * (`saveLocalAppRunningState`, via the applet's `onStart`/`onStop`). We read\n * those flags back and re-spawn the background context headlessly (no\n * foreground, no navigation) — the spawn registers the package so the home\n * tray/switcher project it as running, exactly as a normal start would. The\n * WebView, if any, re-attaches lazily when the user opens the app.\n *\n * Idempotent and best-effort: skips already-spawned contexts, and clears the\n * persisted flag for any app whose bundle can no longer be resolved\n * (uninstalled, or dev server gone) so a dead entry doesn't retry every boot.\n * Not compatibility-gated: a previously-running background app shouldn't be\n * dropped just because glasses are momentarily disconnected at boot — it\n * resumes when they reconnect, same as mid-session.\n *\n * Always On apps (the dashboard) start whether or not they were running\n * when the app was last killed, and get a switcher card like any other app.\n * Both restore paths skip apps missing required OS permissions without\n * prompting or clearing their saved running/Always On choice.\n */\n async autostartLocalMiniapps(): Promise<void> {\n const apps = await appRegistry.getInstalledMiniapps()\n for (const app of apps) {\n // Only phone-hosted miniapps have a JSContext to re-spawn. Offline\n // built-ins (`local:false, offline:true`) restore their native running\n // state elsewhere and have no bundle to launch.\n if (!app.local) continue\n if (!app.alwaysOn && !getLocalAppRunningState(app.packageName)) continue\n if (this.isRunning(app.packageName)) continue\n try {\n const missing = await permissions.missingRequired(app.permissions ?? [])\n if (missing.length > 0) {\n console.info(\n `MiniappLauncher: skipping autostart for ${app.packageName} — missing required permissions: ${missing.join(\n \", \",\n )}`,\n )\n continue\n }\n } catch (e) {\n console.warn(`MiniappLauncher: skipping autostart for ${app.packageName} — permission check failed`, e)\n continue\n }\n try {\n await this.ensureRunning(app.packageName)\n } catch (e) {\n console.warn(`MiniappLauncher: autostart failed for ${app.packageName} — clearing stale running flag`, e)\n saveLocalAppRunningState(app.packageName, false)\n }\n }\n }\n\n /**\n * Ensure the context is running AND has completed its CONNECT handshake.\n * Used by the action broker, which must not deliver to a context that hasn't\n * come up yet. Throws on spawn failure or connect timeout.\n */\n async ensureConnected(packageName: string, connectTimeoutMs = 10_000, hints?: LaunchHints): Promise<void> {\n await this.ensureRunning(packageName, hints)\n await localMiniappRuntime.waitForConnect(packageName, connectTimeoutMs)\n }\n\n /** Tear down a miniapp's background JS context. */\n async stop(packageName: string): Promise<void> {\n // If a launch is in flight, let it finish first. Otherwise unregister()\n // no-ops on the not-yet-registered package and the pending spawn then\n // re-registers the context — leaving it running despite the stop.\n const pending = this.inFlight.get(packageName)\n if (pending) {\n try {\n await pending\n } catch {\n // Launch failed — nothing got registered, so nothing to tear down.\n }\n }\n await this.deps?.router.unregister(packageName)\n }\n\n // --- internals -----------------------------------------------------------\n\n private storedDevUrl(packageName: string): string | undefined {\n const r = storage.load<string>(`${packageName}_dev_url`)\n return r.is_ok() ? r.value : undefined\n }\n\n /** resolveDevPort — moved verbatim from the old LocalMiniappView helper. */\n private resolveDevPort(searchParam: string | undefined, packageName: string): number | null {\n if (searchParam) {\n const n = parseInt(searchParam, 10)\n if (Number.isFinite(n)) return n\n }\n const stored = storage.load<number>(`${packageName}_dev_port`)\n if (stored.is_ok()) return stored.value\n return null\n }\n}\n\nexport const miniappLauncher = new MiniappLauncher()\n"]}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The overlay apps: the connected miniapps whose manifest type is
|
|
3
|
-
* "system_dashboard" (the dashboard
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* glasses are eligible. The runtime adds an app when it connects and
|
|
3
|
+
* "system_dashboard" (the dashboard). They alone may take the overlay slot
|
|
4
|
+
* through `session.display.showView("dashboard")` and have "dashboard" in
|
|
5
|
+
* their `display.views` capability while the glasses are eligible. The runtime adds an app when it connects and
|
|
7
6
|
* removes it when it stops; the engine never knows what any of them draws.
|
|
8
7
|
* Kept free of imports so the runtime and the notification policy can both
|
|
9
8
|
* read it without a cycle.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"overlayApps.d.ts","sourceRoot":"","sources":["../../../src/services/pages/overlayApps.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"overlayApps.d.ts","sourceRoot":"","sources":["../../../src/services/pages/overlayApps.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,WAAW,CAAA;AAO9C,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED,wBAAgB,WAAW,IAAI,SAAS,MAAM,EAAE,CAE/C;AAED,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAIvD;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAI1D;AAED,sGAAsG;AACtG,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,IAAI,CAK9E;AAED,mEAAmE;AACnE,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAKpE;AAED,+GAA+G;AAC/G,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,WAAW,EAAE,CAErF;AAMD,kBAAkB;AAClB,wBAAgB,wBAAwB,IAAI,IAAI,CAG/C"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The overlay apps: the connected miniapps whose manifest type is
|
|
3
|
-
* "system_dashboard" (the dashboard
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* glasses are eligible. The runtime adds an app when it connects and
|
|
3
|
+
* "system_dashboard" (the dashboard). They alone may take the overlay slot
|
|
4
|
+
* through `session.display.showView("dashboard")` and have "dashboard" in
|
|
5
|
+
* their `display.views` capability while the glasses are eligible. The runtime adds an app when it connects and
|
|
7
6
|
* removes it when it stops; the engine never knows what any of them draws.
|
|
8
7
|
* Kept free of imports so the runtime and the notification policy can both
|
|
9
8
|
* read it without a cycle.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"overlayApps.js","sourceRoot":"","sources":["../../../src/services/pages/overlayApps.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"overlayApps.js","sourceRoot":"","sources":["../../../src/services/pages/overlayApps.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAA;AAC9B,mGAAmG;AACnG,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAA;AACjC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAc,CAAA;AAEvC,MAAM,UAAU,YAAY,CAAC,WAAmB;IAC9C,OAAO,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;AAC9B,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,CAAC,GAAG,IAAI,CAAC,CAAA;AAClB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,WAAmB;IAC/C,IAAI,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC;QAAE,OAAM;IACjC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;IACrB,IAAI,EAAE,CAAA;AACR,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,WAAmB;IAClD,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;IAC3B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC;QAAE,OAAM;IACrC,IAAI,EAAE,CAAA;AACR,CAAC;AAED,sGAAsG;AACtG,MAAM,UAAU,gBAAgB,CAAC,WAAmB,EAAE,SAAkB;IACtE,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;IACpC,IAAI,SAAS,IAAI,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC;QAAE,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;;QAC3D,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;IAChC,IAAI,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;QAAE,IAAI,EAAE,CAAA;AAC9C,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,oBAAoB;IAClC,OAAO,OAAO,CAAC,IAAI,GAAG,CAAC,CAAA;AACzB,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,QAAoB;IACtD,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IACvB,OAAO,GAAG,EAAE;QACV,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IAC5B,CAAC,CAAA;AACH,CAAC;AAED,+GAA+G;AAC/G,MAAM,UAAU,eAAe,CAAC,WAAmB,EAAE,QAAiB;IACpE,OAAO,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;AAC7E,CAAC;AAED,SAAS,IAAI;IACX,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;QAAE,QAAQ,EAAE,CAAA;AAC1D,CAAC;AAED,kBAAkB;AAClB,MAAM,UAAU,wBAAwB;IACtC,IAAI,CAAC,KAAK,EAAE,CAAA;IACZ,OAAO,CAAC,KAAK,EAAE,CAAA;AACjB,CAAC","sourcesContent":["/**\n * The overlay apps: the connected miniapps whose manifest type is\n * \"system_dashboard\" (the dashboard). They alone may take the overlay slot\n * through `session.display.showView(\"dashboard\")` and have \"dashboard\" in\n * their `display.views` capability while the glasses are eligible. The runtime adds an app when it connects and\n * removes it when it stops; the engine never knows what any of them draws.\n * Kept free of imports so the runtime and the notification policy can both\n * read it without a cycle.\n */\n\nexport type DisplayView = \"main\" | \"dashboard\"\n\nconst apps = new Set<string>()\n/** Overlay apps listening to the phone's notifications: something on the glasses presents them. */\nconst viewers = new Set<string>()\nconst listeners = new Set<() => void>()\n\nexport function isOverlayApp(packageName: string): boolean {\n return apps.has(packageName)\n}\n\nexport function overlayApps(): readonly string[] {\n return [...apps]\n}\n\nexport function addOverlayApp(packageName: string): void {\n if (apps.has(packageName)) return\n apps.add(packageName)\n emit()\n}\n\nexport function removeOverlayApp(packageName: string): void {\n viewers.delete(packageName)\n if (!apps.delete(packageName)) return\n emit()\n}\n\n/** Record whether an overlay app subscribes to phone notifications (it is a viewer while it does). */\nexport function setOverlayViewer(packageName: string, listening: boolean): void {\n const was = viewers.has(packageName)\n if (listening && apps.has(packageName)) viewers.add(packageName)\n else viewers.delete(packageName)\n if (was !== viewers.has(packageName)) emit()\n}\n\n/** An overlay app that presents phone notifications is running. */\nexport function overlayViewerRunning(): boolean {\n return viewers.size > 0\n}\n\nexport function onOverlayAppsChange(listener: () => void): () => void {\n listeners.add(listener)\n return () => {\n listeners.delete(listener)\n }\n}\n\n/** The views `packageName` may draw: main for everyone, the dashboard for overlay apps on eligible glasses. */\nexport function displayViewsFor(packageName: string, eligible: boolean): DisplayView[] {\n return apps.has(packageName) && eligible ? [\"main\", \"dashboard\"] : [\"main\"]\n}\n\nfunction emit(): void {\n for (const listener of Array.from(listeners)) listener()\n}\n\n/** Tests only. */\nexport function _resetOverlayAppsForTest(): void {\n apps.clear()\n viewers.clear()\n}\n"]}
|
package/build/stores/apps.d.ts
CHANGED
|
@@ -64,12 +64,12 @@ interface AppStatusState {
|
|
|
64
64
|
setHiddenStatus: (packageName: string, status: boolean) => void;
|
|
65
65
|
getHiddenStatus: (packageName: string) => boolean;
|
|
66
66
|
/**
|
|
67
|
-
* Mark a miniapp
|
|
68
|
-
* app switcher's
|
|
67
|
+
* Mark a miniapp Always On: it starts at launch and only stops from the
|
|
68
|
+
* app switcher's Always On pill (its card cannot be swiped away and the
|
|
69
69
|
* capsule close minimizes it). Turning it on starts the app; turning it
|
|
70
70
|
* off leaves it running. Persists the wearer's choice beside the hidden flag.
|
|
71
71
|
*/
|
|
72
|
-
|
|
72
|
+
setAlwaysOn: (packageName: string, status: boolean) => Promise<void>;
|
|
73
73
|
/** Replace the whole apps array. Hosts use this when their extra source changes. */
|
|
74
74
|
setApps: (apps: ClientApp[]) => void;
|
|
75
75
|
}
|
|
@@ -97,8 +97,8 @@ export declare const useInstall: () => (url: string, opts?: {
|
|
|
97
97
|
export declare const useUninstall: () => (packageName: string, version?: string) => AsyncResult<void, Error>;
|
|
98
98
|
/** Every running app; each one has a card in the app switcher tray. */
|
|
99
99
|
export declare const useActiveApps: () => ClientApp[];
|
|
100
|
-
/**
|
|
101
|
-
export declare const
|
|
100
|
+
/** Always On apps whose background task is running, card or no card. */
|
|
101
|
+
export declare const useRunningAlwaysOnApps: () => ClientApp[];
|
|
102
102
|
export declare const useActiveBackgroundApps: () => ClientApp[];
|
|
103
103
|
export declare const useBackgroundApps: () => {
|
|
104
104
|
active: ClientApp[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apps.d.ts","sourceRoot":"","sources":["../../src/stores/apps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAC,WAAW,EAAE,MAAM,EAAgB,MAAM,aAAa,CAAA;AAG9D,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,iBAAiB,CAAA;AAe9C,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,kBAAkB,CAAA;AAMzD,MAAM,WAAW,YAAY;IAC3B,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,+DAA+D;IAC/D,YAAY,CAAC,EAAE,mBAAmB,CAAA;CACnC;AAED,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,IAAI,CAAA;IAChD;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,IAAI,CAAA;IAC/C;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,YAAY,KAAK,IAAI,CAAA;CAChE;AAID,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAE/D;AAMD,UAAU,cAAc;IACtB,IAAI,EAAE,SAAS,EAAE,CAAA;IACjB;;;;;;OAMG;IACH,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5B,oHAAoH;IACpH,KAAK,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,YAAY,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IAChE,IAAI,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5C,aAAa,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACrD,eAAe,EAAE,MAAM,IAAI,CAAA;IAC3B,OAAO,EAAE,MAAM,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IACvC,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAC,eAAe,CAAC,EAAE,MAAM,CAAA;KAAC,KAAK,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IACrF,SAAS,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IAC9E,cAAc,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1E,eAAe,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,KAAK,IAAI,CAAA;IAC/D,eAAe,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAA;IACjD;;;;;OAKG;IACH,
|
|
1
|
+
{"version":3,"file":"apps.d.ts","sourceRoot":"","sources":["../../src/stores/apps.ts"],"names":[],"mappings":"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"}
|
package/build/stores/apps.js
CHANGED
|
@@ -16,7 +16,7 @@ import { DeviceTypes } from "../types/enums";
|
|
|
16
16
|
import { getModelCapabilities } from "../types/hardware";
|
|
17
17
|
import { HardwareCompatibility } from "../utils/hardware/hardware";
|
|
18
18
|
import { storage } from "../utils/storage/storage";
|
|
19
|
-
import appRegistry, {
|
|
19
|
+
import appRegistry, { saveAlwaysOnOverride } from "../services/AppRegistry";
|
|
20
20
|
import localDisplayManager from "../services/LocalDisplayManager";
|
|
21
21
|
import { islandNotifications } from "../services/NotificationsEmitter";
|
|
22
22
|
import sttModelManager from "../services/STTModelManager";
|
|
@@ -384,8 +384,8 @@ export const useAppStatusStore = create((set, get) => ({
|
|
|
384
384
|
},
|
|
385
385
|
stopAll: () => {
|
|
386
386
|
return Res.try_async(async () => {
|
|
387
|
-
//
|
|
388
|
-
const running = get().apps.filter((a) => a.running && !a.
|
|
387
|
+
// Always On apps stay up; they stop one at a time from the switcher.
|
|
388
|
+
const running = get().apps.filter((a) => a.running && !a.alwaysOn);
|
|
389
389
|
for (const a of running) {
|
|
390
390
|
await get().stop(a.packageName);
|
|
391
391
|
}
|
|
@@ -429,13 +429,13 @@ export const useAppStatusStore = create((set, get) => ({
|
|
|
429
429
|
hiddenStatusCache.set(packageName, value);
|
|
430
430
|
return value;
|
|
431
431
|
},
|
|
432
|
-
|
|
432
|
+
setAlwaysOn: async (packageName, status) => {
|
|
433
433
|
const app = get().apps.find((a) => a.packageName === packageName);
|
|
434
434
|
if (!app)
|
|
435
435
|
return;
|
|
436
|
-
|
|
436
|
+
saveAlwaysOnOverride(packageName, status);
|
|
437
437
|
set((s) => ({
|
|
438
|
-
apps: s.apps.map((a) => (a.packageName === packageName ? { ...a,
|
|
438
|
+
apps: s.apps.map((a) => (a.packageName === packageName ? { ...a, alwaysOn: status } : a)),
|
|
439
439
|
}));
|
|
440
440
|
if (status && !app.running)
|
|
441
441
|
await get().start(app, { skipNavigation: true });
|
|
@@ -521,10 +521,10 @@ export const useActiveApps = () => {
|
|
|
521
521
|
const apps = useApps();
|
|
522
522
|
return useMemo(() => apps.filter((app) => app.running), [apps]);
|
|
523
523
|
};
|
|
524
|
-
/**
|
|
525
|
-
export const
|
|
524
|
+
/** Always On apps whose background task is running, card or no card. */
|
|
525
|
+
export const useRunningAlwaysOnApps = () => {
|
|
526
526
|
const apps = useApps();
|
|
527
|
-
return useMemo(() => apps.filter((app) => app.
|
|
527
|
+
return useMemo(() => apps.filter((app) => app.alwaysOn && app.running), [apps]);
|
|
528
528
|
};
|
|
529
529
|
/** Apps that run without a foreground surface: background ones and the system dashboard. */
|
|
530
530
|
const isBackgroundApp = (app) => app.type === "background" || app.type === "system_dashboard";
|
package/build/stores/apps.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apps.js","sourceRoot":"","sources":["../../src/stores/apps.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Engine apps store — runtime state of installed and local applets.\n *\n * The OEM-facing API: subscribe to the running set, install/uninstall\n * miniapps, start/stop them. The store delegates install plumbing to\n * AppRegistry, and exposes hooks (`useApps`, `useStart`, `useStop`,\n * `useRefresh`, `useStopAll`) that the host UI can read.\n *\n * Source of `apps`:\n * - Local: appRegistry.getInstalledMiniapps() (always)\n */\n\nimport {useMemo} from \"react\"\nimport {AsyncResult, Result, result as Res} from \"typesafe-ts\"\nimport {create} from \"zustand\"\n\nimport type {ClientApp} from \"../types/applet\"\nimport {DeviceTypes} from \"../types/enums\"\nimport {getModelCapabilities} from \"../types/hardware\"\nimport {HardwareCompatibility, type CompatibilityResult} from \"../utils/hardware/hardware\"\nimport {storage} from \"../utils/storage/storage\"\nimport appRegistry, {savePersistentOverride} from \"../services/AppRegistry\"\nimport localDisplayManager from \"../services/LocalDisplayManager\"\nimport {islandNotifications} from \"../services/NotificationsEmitter\"\nimport sttModelManager from \"../services/STTModelManager\"\nimport {miniappLauncher} from \"../services/MiniappLauncher\"\nimport {miniappRunningRegistry} from \"../services/MiniappRunningRegistry\"\nimport {defaultHiddenStatus, isGatedByDevTools, isGatedUntilPaired, resolveHiddenStatus} from \"./appVisibility\"\nimport {SETTINGS, useSettingsStore} from \"./settings\"\nimport {PermissionFeatures, permissions} from \"../facades/permissions\"\nimport BluetoothSdk from \"@glassly/bluetooth-sdk\"\nimport type {MiniappLaunchSource} from \"@glassly/miniapp\"\n\n// ---------------------------------------------------------------------------\n// Configuration / hooks\n// ---------------------------------------------------------------------------\n\nexport interface StartOptions {\n skipNavigation?: boolean\n /** Reported to the miniapp on connect. Defaults to \"phone\". */\n launchSource?: MiniappLaunchSource\n}\n\nexport interface AppStoreHooks {\n /**\n * A start was blocked because the app is hardware-incompatible. Engine made\n * the decision (and raised the `version_incompatible` notification); the host\n * renders its branded alert here.\n */\n onIncompatibleBlocked?: (app: ClientApp) => void\n /**\n * A start was blocked because the app requires the on-device STT model\n * (declared at registration — see AppRegistry.installOfflineApp) and none is\n * installed. Engine decided via its model manager; the host renders the\n * alert / settings navigation here.\n */\n onMissingSpeechModel?: (app: ClientApp) => void\n /**\n * An open request passed the gates — fired on EVERY open, including\n * re-opening an already-running app, so the host's navigation / open\n * animation always plays.\n */\n onOpenRequested?: (app: ClientApp, opts?: StartOptions) => void\n}\n\nlet hostHooks: AppStoreHooks = {}\n\nexport function installAppStoreHooks(hooks: AppStoreHooks): void {\n hostHooks = {...hostHooks, ...hooks}\n}\n\n// ---------------------------------------------------------------------------\n// Store\n// ---------------------------------------------------------------------------\n\ninterface AppStatusState {\n apps: ClientApp[]\n /**\n * Source of truth for which app is foregrounded in the Compositor overlay.\n * The per-app `foregrounded` boolean is derived from this in `projectApps`\n * so a refresh can never drop the flag when an app is transiently missing\n * from one of the two refresh passes (local-only then merged). See\n * `projectApps` / `setForeground` / `clearForeground`.\n */\n foregroundedPackage: string | null\n refresh: () => Promise<void>\n /** Resolves true if the app actually started; false if a host gate aborted it or its JS context failed to spawn. */\n start: (app: ClientApp, opts?: StartOptions) => Promise<boolean>\n stop: (packageName: string) => Promise<void>\n setForeground: (packageName: string) => Promise<void>\n clearForeground: () => void\n stopAll: () => AsyncResult<void, Error>\n install: (url: string, opts?: {versionOverride?: string}) => AsyncResult<void, Error>\n uninstall: (packageName: string, version?: string) => AsyncResult<void, Error>\n saveScreenshot: (packageName: string, screenshot: string) => Promise<void>\n setHiddenStatus: (packageName: string, status: boolean) => void\n getHiddenStatus: (packageName: string) => boolean\n /**\n * Mark a miniapp persistent: it starts at launch and only stops from the\n * app switcher's persistent pill (its card cannot be swiped away and the\n * capsule close minimizes it). Turning it on starts the app; turning it\n * off leaves it running. Persists the wearer's choice beside the hidden flag.\n */\n setPersistent: (packageName: string, status: boolean) => Promise<void>\n /** Replace the whole apps array. Hosts use this when their extra source changes. */\n setApps: (apps: ClientApp[]) => void\n}\n\nexport const DUMMY_APPLET: ClientApp = {\n packageName: \"\",\n name: \"\",\n webviewUrl: \"\",\n logoUrl: \"\",\n type: \"standard\",\n permissions: [],\n running: false,\n loading: false,\n healthy: true,\n hardwareRequirements: [],\n offline: true,\n offlineRoute: \"\",\n local: false,\n hidden: false,\n}\n\nexport type OrderMap = Record<string, number>\nconst APP_ORDER_KEY = \"foreground_apps_order\"\n\nexport const saveAppsOrder = (orderMap: OrderMap): Result<void, Error> => {\n return storage.save(APP_ORDER_KEY, orderMap)\n}\n\nexport const getAppsOrder = (): Result<OrderMap, Error> => {\n return storage.load<OrderMap>(APP_ORDER_KEY)\n}\n\n// In-memory cache for hidden flags. `projectApps` reads getHiddenStatus once\n// per app per refresh — without a cache that was a synchronous JNI hop per\n// app per refresh on a hot UI path. Kept consistent with disk by writing\n// through in setHiddenStatus. Map of packageName → hidden boolean.\nconst hiddenStatusCache = new Map<string, boolean>()\n\nconst getRawPackageNamePriority = (pkg: string): number => {\n if (pkg.includes(\"@empty\")) {\n return 1000\n }\n return 0\n}\n\nexport const sortAppsByPackageNamePriority = (a: ClientApp, b: ClientApp): number => {\n const pa = getRawPackageNamePriority(a.packageName)\n const pb = getRawPackageNamePriority(b.packageName)\n if (pa !== pb) {\n return pa - pb\n }\n return a.name.localeCompare(b.name)\n}\n\nexport const saveLastOpenTime = (packageName: string): void => {\n storage.save(`${packageName}_last_open_time`, Date.now())\n}\n\nexport const getLastOpenTime = (packageName: string): number => {\n const res = storage.load<number>(`${packageName}_last_open_time`)\n if (res.is_ok()) return res.value\n return 0\n}\n\nexport const sortAppsByLastOpenTime = async <T extends {packageName: string}>(apps: T[]): Promise<T[]> => {\n const timestamps = apps.map((app) => ({app, time: getLastOpenTime(app.packageName)}))\n return timestamps.sort((a, b) => a.time - b.time).map((entry) => entry.app)\n}\n\nconst startStopApp = async (app: ClientApp, status: boolean): Promise<void> => {\n if (!status && app.onStop) {\n try {\n app.onStop()\n } catch (e) {\n console.warn(`ISLAND: onStop threw for ${app.packageName}`, e)\n }\n }\n if (status && app.onStart) {\n try {\n app.onStart()\n } catch (e) {\n console.warn(`ISLAND: onStart threw for ${app.packageName}`, e)\n }\n }\n}\n\n/**\n * Build the final `apps` array for the store from the installed/offline app\n * source. Pure — same inputs -> same outputs.\n */\nfunction projectApps(previousState: AppStatusState, localApps: ClientApp[]): ClientApp[] {\n // Dedupe by packageName, keep first occurrence.\n const byPackage = new Map<string, ClientApp>()\n for (const app of localApps) {\n if (!byPackage.has(app.packageName)) byPackage.set(app.packageName, app)\n }\n\n // Index previous snapshot for cheap lookups (was O(N²) via .find()).\n const previousByPackage = new Map<string, ClientApp>()\n for (const oldApp of previousState.apps) {\n previousByPackage.set(oldApp.packageName, oldApp)\n }\n\n const defaultWearable =\n (useSettingsStore.getState().getSetting(SETTINGS.default_wearable.key) as DeviceTypes | undefined) ||\n DeviceTypes.NONE\n const capabilities = getModelCapabilities(defaultWearable)\n const devToolsEnabled = useSettingsStore.getState().getSetting(SETTINGS.dev_tools.key) === true\n const hasPairedGlasses = useSettingsStore.getState().getSetting(SETTINGS.has_paired_glasses.key) === true\n\n // Single pass: dedupe → screenshot carry-over → compat → hidden, all into\n // fresh objects. The previous in-place mutation re-used object references\n // across refreshes, which broke React.memo / referential-equality\n // memoization downstream (every refresh propagated re-renders even when\n // nothing meaningful changed) AND tripped Reanimated's \"tried to modify\n // key of an object already passed to a worklet\" warning whenever the home\n // screen's animated app cards held a reference to a previous snapshot's\n // app object that we then mutated.\n //\n // Identity stability: refresh() is event-driven and fires repeatedly (and\n // twice per cycle via the local-only → merged two-pass emit). If we always\n // returned fresh objects, every poll changed the identity of EVERY app —\n // which re-rendered the Compositor (via useForegroundApp) mid-slide and made\n // the open/close animation hitch, and churned the home grid / switcher pill.\n // So we build the candidate object, then REUSE the previous reference when\n // nothing meaningful changed. Same pattern as the miniappRunningRegistry\n // projection below. A stable foreground-app reference lets the Compositor's\n // slide run uninterrupted on the UI thread.\n return Array.from(byPackage.values())\n .filter(\n (app) =>\n !isGatedByDevTools(app.packageName, devToolsEnabled) &&\n !isGatedUntilPaired(app.packageName, devToolsEnabled, hasPairedGlasses),\n )\n .map((app) => {\n const next: ClientApp = {\n ...app,\n screenshot: previousByPackage.get(app.packageName)?.screenshot ?? app.screenshot,\n compatibility: HardwareCompatibility.checkCompatibility(app.hardwareRequirements, capabilities),\n // A registry source can force an app off the primary home screen.\n // Compose that gate with the user's persisted home-screen layout instead\n // of replacing it, otherwise a default-false persisted value makes a\n // source-hidden app visible again during projection.\n hidden: resolveHiddenStatus(app.hidden, previousState.getHiddenStatus(app.packageName)),\n // Derive the foreground flag from the store's single source of truth\n // (`foregroundedPackage`), NOT from the previous snapshot. Carrying it over\n // per-app meant a refresh that momentarily omitted an app (e.g. the\n // two-pass local-only → merged emit) would reset its flag to false — which\n // raced OfflineAppHost's interceptor guard and made the hosted miniapp fall\n // through to the root router (restart). Deriving here keeps the flag stable\n // across both passes.\n foregrounded: app.packageName === previousState.foregroundedPackage,\n }\n const prev = previousByPackage.get(app.packageName)\n return prev && shallowEqualApp(prev, next) ? prev : next\n })\n}\n\n// Cheap equality check used by projectApps to preserve object identity across\n// refreshes when nothing meaningful changed. Most keys are compared by\n// reference (the source app's nested fields — permissions, hardwareRequirements,\n// parameters — are reference-stable within a refresh). The ONE exception is\n// `compatibility`, which projectApps recomputes into a fresh object every call;\n// comparing it by reference would always differ and defeat the whole point. We\n// compare it structurally instead so identity is only broken when the device's\n// actual compatibility verdict changes (e.g. glasses connect/disconnect).\nfunction shallowEqualApp(a: ClientApp, b: ClientApp): boolean {\n const aKeys = Object.keys(a) as (keyof ClientApp)[]\n const bKeys = Object.keys(b) as (keyof ClientApp)[]\n if (aKeys.length !== bKeys.length) return false\n for (const k of aKeys) {\n if (k === \"compatibility\") {\n if (!compatibilityEqual(a.compatibility, b.compatibility)) return false\n continue\n }\n if (a[k] !== b[k]) return false\n }\n return true\n}\n\nfunction compatibilityEqual(a?: CompatibilityResult, b?: CompatibilityResult): boolean {\n if (a === b) return true\n if (!a || !b) return false\n return (\n a.isCompatible === b.isCompatible &&\n a.missingRequired.length === b.missingRequired.length &&\n a.missingOptional.length === b.missingOptional.length &&\n a.warnings.length === b.warnings.length\n )\n}\n\nexport const useAppStatusStore = create<AppStatusState>((set, get) => ({\n apps: [],\n foregroundedPackage: null,\n\n refresh: async () => {\n const previousState = get()\n const localApps = await appRegistry.getInstalledMiniapps()\n set({apps: projectApps(previousState, localApps)})\n },\n\n start: async (clientApp: ClientApp, opts?: StartOptions) => {\n const state = get()\n const packageName = clientApp.packageName\n const app = state.apps.find((a) => a.packageName === packageName)\n if (!app) {\n console.error(`ISLAND: app not found for package name: ${packageName}`)\n return false\n }\n\n // Skip spawning a NEW app while another is mid-launch — concurrent spawns\n // race the foreground-only-one teardown. This is checked BEFORE the gates\n // and the onOpenRequested seam (which navigates/foregrounds) so a gated\n // launch doesn't paint a splash it can't back. Re-opening an already-running\n // app is exempt: it has nothing to spawn, so it skips this gate and is\n // allowed to re-navigate/animate below.\n // That exemption is the fix for the \"second tap during another app's launch\n // window silently does nothing\" bug.\n if (!app.running && state.apps.some((a) => a.loading)) {\n console.log(`ISLAND: skipping start ${packageName} — another app is loading`)\n return false\n }\n\n if (!app.offline && !app.local) {\n console.warn(`ISLAND: cloud-v1 app entries are no longer supported: ${packageName}`)\n return false\n }\n\n // Hardware-compatibility gate — engine decides and blocks; the host renders\n // its branded alert via onIncompatibleBlocked (and/or the structured\n // notification below). `!isCompatible` (not `=== false`) keeps the semantics\n // of the host gate this replaces: an unknown verdict blocks, not launches.\n if (!app.compatibility?.isCompatible) {\n islandNotifications.emit({\n kind: \"version_incompatible\",\n packageName,\n reason: `${app.name ?? packageName} is not compatible with the connected glasses`,\n metadata: {missingRequired: app.compatibility?.missingRequired ?? []},\n timestamp: Date.now(),\n })\n hostHooks.onIncompatibleBlocked?.(app)\n return false\n }\n\n // Missing-speech-model gate for apps registered with requiresLocalSttModel.\n // Engine decides via its own model manager; the host renders the alert and\n // any settings navigation via onMissingSpeechModel.\n if (appRegistry.requiresLocalSttModel(packageName) && !(await sttModelManager.isModelAvailable())) {\n islandNotifications.emit({\n kind: \"missing_speech_model\",\n packageName,\n reason: `${app.name ?? packageName} needs an on-device speech model before it can start`,\n timestamp: Date.now(),\n })\n hostHooks.onMissingSpeechModel?.(app)\n return false\n }\n\n // Host navigation / open-animation seam. Runs on EVERY accepted open —\n // including re-opening an already-running app — so the animation always\n // plays (BuiltInMiniappCatalog.navigateForApp: overlay apps setForeground\n // for the slide).\n hostHooks.onOpenRequested?.(app, opts)\n\n // First-activation mark (moved from the host's old beforeStart — engine\n // owns the settings store).\n useSettingsStore.getState().setSetting(SETTINGS.has_ever_activated_app.key, true)\n\n // If the tapped app is already running, this is a re-open: the nav/foreground\n // above already drove the animation, and there's nothing to spawn. Short-\n // circuit before the spawn pipeline.\n if (app.running) {\n saveLastOpenTime(packageName)\n return true\n }\n\n // The phone mic is asked for here, at first use, not during pairing: the\n // OS prompt lands over the app that needs it. The facade returns at once\n // when the answer is already known, so this only ever prompts once.\n if (declaresMicrophone(app)) await permissions.request(PermissionFeatures.MICROPHONE)\n\n // Foreground-only-one rule: stop other running standard apps.\n if (app.type === \"standard\") {\n const runningForeground = state.apps.filter(\n (a) => a.running && a.type === \"standard\" && a.packageName !== packageName,\n )\n for (const r of runningForeground) {\n await get().stop(r.packageName)\n }\n }\n\n set((s) => ({\n apps: s.apps.map((a) => (a.packageName === packageName ? {...a, running: true, loading: false} : a)),\n }))\n\n saveLastOpenTime(packageName)\n await startStopApp(app, true)\n\n // Spawn the background JS context for local miniapps. This used to be a\n // side effect of LocalMiniappView mounting on foreground; pulling it here\n // lets start() actually run the app even when nothing foregrounds it (e.g.\n // a system app launching another miniapp via session.miniapps). Idempotent\n // with the view's own ensureRunning; a no-op for native offline built-ins\n // (no JS bundle).\n if (app.local) {\n try {\n await miniappLauncher.ensureRunning(packageName, {launchSource: opts?.launchSource ?? \"phone\"})\n } catch (e) {\n // Spawn / bundle-resolve failed — revert the optimistic running flag so\n // the home list and miniapps.list() don't show a \"running\" app with no\n // JS context, and report failure to the caller (session.miniapps.start).\n console.warn(`ISLAND: launcher.ensureRunning failed for ${packageName}`, e)\n set((s) => ({\n apps: s.apps.map((a) => (a.packageName === packageName ? {...a, running: false, loading: false} : a)),\n }))\n // onStart already persisted running:true to disk (saveLocalAppRunningState)\n // before the spawn; run onStop to undo it so a refresh/reboot doesn't\n // resurrect a \"running\" app with no JS context.\n await startStopApp(app, false)\n return false\n }\n }\n\n return true\n },\n\n stop: async (packageName: string) => {\n const state = get()\n const app = state.apps.find((a) => a.packageName === packageName)\n if (!app) {\n console.error(`ISLAND: app not found for package name: ${packageName}`)\n return\n }\n\n set((s) => ({\n apps: s.apps.map((a) =>\n a.packageName === packageName ? {...a, running: false, screenshot: undefined, loading: false} : a,\n ),\n }))\n\n // if there are no apps running, call clearDisplay():\n // read fresh state via get() — `state` was captured before the set() above, so it still shows\n // this app as running and would never reach 0 when stopping the last app.\n if (get().apps.filter((a) => a.running).length === 0) {\n BluetoothSdk.clearDisplay()\n }\n await startStopApp(app, false)\n\n // Tear down the background JS context for local miniapps. No-op for native\n // offline built-ins.\n if (app.local) {\n try {\n await miniappLauncher.stop(packageName)\n } catch (e) {\n console.warn(`ISLAND: launcher.stop failed for ${packageName}`, e)\n }\n }\n },\n\n setForeground: async (packageName: string) => {\n const app = get().apps.find((a) => a.packageName === packageName)\n if (!app) {\n console.error(`ISLAND: setForeground — app not found: ${packageName}`)\n return\n }\n\n // Flip the foreground flag synchronously so the Compositor's open\n // animation starts on the same frame as the tap. We do NOT await start()\n // first — that gated the flag (and thus the animation) behind the whole\n // JSContext-spawn chain, which was the perceived launch delay. The\n // Compositor/LocalMiniappView already handle the spawn being in-flight\n // (the phase machine), so foregrounding needn't wait for it.\n saveLastOpenTime(packageName)\n set((s) => ({\n foregroundedPackage: packageName,\n apps: s.apps.map((a) => ({...a, foregrounded: a.packageName === packageName})),\n }))\n\n // Ensure the JSContext exists. start() is idempotent for an\n // already-running app and enforces the foreground-only-one rule for\n // standard apps. Fire-and-forget after the flag flip so it doesn't block\n // paint.\n // if (!app.running) {\n // get().start(app)\n // }\n },\n\n clearForeground: () => {\n set((s) => ({\n foregroundedPackage: null,\n apps: s.apps.some((a) => a.foregrounded)\n ? s.apps.map((a) => (a.foregrounded ? {...a, foregrounded: false} : a))\n : s.apps,\n }))\n },\n\n stopAll: () => {\n return Res.try_async(async () => {\n // Persistent apps stay up; they stop one at a time from the switcher.\n const running = get().apps.filter((a) => a.running && !a.persistent)\n for (const a of running) {\n await get().stop(a.packageName)\n }\n })\n },\n\n install: (url, opts) => appRegistry.installFromUrl(url, opts),\n\n uninstall: (packageName, version) => {\n return Res.try_async(async () => {\n const res = await appRegistry.uninstall(packageName, version)\n if (res.is_error()) throw res.error\n set((s) => ({apps: s.apps.filter((a) => a.packageName !== packageName)}))\n })\n },\n\n saveScreenshot: async (packageName: string, screenshot: string) => {\n storage.save(`${packageName}_screenshot`, screenshot)\n set((s) => ({\n apps: s.apps.map((a) => (a.packageName === packageName ? {...a, screenshot} : a)),\n }))\n },\n\n setHiddenStatus: (packageName: string, status: boolean) => {\n hiddenStatusCache.set(packageName, status)\n set((s) => ({\n apps: s.apps.map((a) => (a.packageName === packageName ? {...a, hidden: status} : a)),\n }))\n storage.save(`${packageName}_hidden`, status)\n if (!status) {\n const orderMap = getAppsOrder()\n if (orderMap.is_ok()) {\n delete orderMap.value[packageName]\n saveAppsOrder(orderMap.value)\n }\n }\n },\n\n getHiddenStatus: (packageName: string): boolean => {\n const cached = hiddenStatusCache.get(packageName)\n if (cached !== undefined) return cached\n const res = storage.load<boolean>(`${packageName}_hidden`)\n const value = res.is_ok() ? res.value : defaultHiddenStatus(packageName)\n hiddenStatusCache.set(packageName, value)\n return value\n },\n\n setPersistent: async (packageName: string, status: boolean) => {\n const app = get().apps.find((a) => a.packageName === packageName)\n if (!app) return\n savePersistentOverride(packageName, status)\n set((s) => ({\n apps: s.apps.map((a) => (a.packageName === packageName ? {...a, persistent: status} : a)),\n }))\n if (status && !app.running) await get().start(app, {skipNavigation: true})\n },\n\n setApps: (apps) => set({apps}),\n}))\n\n// Project miniappRunningRegistry membership into the store's `running` field\n// for local apps so the home tray and switcher reflect actual mount state\n// without waiting for the next refresh() cycle.\nminiappRunningRegistry.subscribe(() => {\n const running = new Set(miniappRunningRegistry.getAll())\n const state = useAppStatusStore.getState()\n let changed = false\n const updated = state.apps.map((app) => {\n if (!app.local) return app\n const next = running.has(app.packageName)\n if (app.running === next) return app\n changed = true\n return {...app, running: next}\n })\n if (changed) {\n useAppStatusStore.setState({apps: updated})\n }\n})\n\n// The display-manager's core (foreground) slot is DERIVED state: always the\n// currently-running standard app, no matter HOW it came to run — user tap\n// (start()), boot restore (autostartLocalMiniapps → registry projection\n// above), crash-respawn, or interop. One reconciler instead of per-path call\n// sites, so no launch/stop path can forget to claim or release the slot.\n// onCoreAppChange is idempotent, so firing on every store write is free.\nuseAppStatusStore.subscribe((state) => {\n const core = state.apps.find((a) => a.running && (a.type === \"standard\" || !a.type))\n localDisplayManager.onCoreAppChange(core?.packageName ?? null)\n})\n\n// AppRegistry change events trigger a store refresh.\nappRegistry.subscribe(() => {\n void useAppStatusStore.getState().refresh()\n})\n\n// Re-evaluate hardware compatibility when the paired/default wearable changes.\nuseSettingsStore.subscribe(\n (state) => state.getSetting(SETTINGS.default_wearable.key),\n () => {\n void useAppStatusStore.getState().refresh()\n },\n)\n\n// Developer tools toggled: dev-only apps enter or leave the projection. When\n// they leave, stop any that are running first so the running registry doesn't\n// keep a miniapp alive that no launcher surface can reach.\nuseSettingsStore.subscribe(\n (state) => state.getSetting(SETTINGS.dev_tools.key) === true,\n (enabled) => {\n void (async () => {\n if (!enabled) {\n const state = useAppStatusStore.getState()\n const hasPairedGlasses = useSettingsStore.getState().getSetting(SETTINGS.has_paired_glasses.key) === true\n for (const app of state.apps) {\n const gated =\n isGatedByDevTools(app.packageName, false) || isGatedUntilPaired(app.packageName, false, hasPairedGlasses)\n if (app.running && gated) await state.stop(app.packageName)\n }\n }\n await useAppStatusStore.getState().refresh()\n })()\n },\n)\n\n// First real pairing latched: the Store enters the projection. One-way, so\n// nothing ever leaves here.\nuseSettingsStore.subscribe(\n (state) => state.getSetting(SETTINGS.has_paired_glasses.key) === true,\n () => {\n void useAppStatusStore.getState().refresh()\n },\n)\n\n/** Declares the microphone (or everything) in its manifest. */\nconst declaresMicrophone = (app: ClientApp): boolean =>\n app.permissions.some((p) => p.type === \"MICROPHONE\" || p.type === \"ALL\")\n\n// ---------------------------------------------------------------------------\n// Public hooks\n// ---------------------------------------------------------------------------\n\nexport const useApps = () => useAppStatusStore((state) => state.apps)\nexport const useStart = () => useAppStatusStore((state) => state.start)\nexport const useStop = () => useAppStatusStore((state) => state.stop)\nexport const useSetForeground = () => useAppStatusStore((state) => state.setForeground)\nexport const useClearForeground = () => useAppStatusStore((state) => state.clearForeground)\nexport const useRefresh = () => useAppStatusStore((state) => state.refresh)\nexport const useStopAll = () => useAppStatusStore((state) => state.stopAll)\nexport const useInstall = () => useAppStatusStore((state) => state.install)\nexport const useUninstall = () => useAppStatusStore((state) => state.uninstall)\n\n/** Every running app; each one has a card in the app switcher tray. */\nexport const useActiveApps = () => {\n const apps = useApps()\n return useMemo(() => apps.filter((app) => app.running), [apps])\n}\n\n/** Persistent apps whose background task is running, card or no card. */\nexport const useRunningPersistentApps = () => {\n const apps = useApps()\n return useMemo(() => apps.filter((app) => app.persistent && app.running), [apps])\n}\n\n/** Apps that run without a foreground surface: background ones and the system dashboard. */\nconst isBackgroundApp = (app: ClientApp): boolean => app.type === \"background\" || app.type === \"system_dashboard\"\n\nexport const useActiveBackgroundApps = () => {\n const apps = useApps()\n return useMemo(() => apps.filter((app) => isBackgroundApp(app) && app.running), [apps])\n}\n\nexport const useBackgroundApps = () => {\n const apps = useApps()\n return useMemo(\n () => ({\n active: apps.filter((app) => isBackgroundApp(app) && app.running),\n inactive: apps.filter((app) => isBackgroundApp(app) && !app.running),\n }),\n [apps],\n )\n}\n\nexport const useActiveForegroundApp = () => {\n const apps = useApps()\n return useMemo(() => apps.find((app) => (app.type === \"standard\" || !app.type) && app.running) ?? null, [apps])\n}\n\n/**\n * The single app currently foregrounded in the Compositor overlay, or null.\n * Driven by setForeground/clearForeground — distinct from the \"active\n * standard app\" (running) selector above.\n */\nexport const useForegroundApp = () => {\n const apps = useApps()\n return useMemo(() => apps.find((app) => app.foregrounded) ?? null, [apps])\n}\n\nexport const useActiveBackgroundAppsCount = () => {\n const apps = useApps()\n return useMemo(() => apps.filter((app) => isBackgroundApp(app) && app.running).length, [apps])\n}\n\nexport const useLocalMiniApps = () => {\n const apps = useApps()\n return useMemo(() => apps.filter((app) => app.local), [apps])\n}\n"]}
|
|
1
|
+
{"version":3,"file":"apps.js","sourceRoot":"","sources":["../../src/stores/apps.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Engine apps store — runtime state of installed and local applets.\n *\n * The OEM-facing API: subscribe to the running set, install/uninstall\n * miniapps, start/stop them. The store delegates install plumbing to\n * AppRegistry, and exposes hooks (`useApps`, `useStart`, `useStop`,\n * `useRefresh`, `useStopAll`) that the host UI can read.\n *\n * Source of `apps`:\n * - Local: appRegistry.getInstalledMiniapps() (always)\n */\n\nimport {useMemo} from \"react\"\nimport {AsyncResult, Result, result as Res} from \"typesafe-ts\"\nimport {create} from \"zustand\"\n\nimport type {ClientApp} from \"../types/applet\"\nimport {DeviceTypes} from \"../types/enums\"\nimport {getModelCapabilities} from \"../types/hardware\"\nimport {HardwareCompatibility, type CompatibilityResult} from \"../utils/hardware/hardware\"\nimport {storage} from \"../utils/storage/storage\"\nimport appRegistry, {saveAlwaysOnOverride} from \"../services/AppRegistry\"\nimport localDisplayManager from \"../services/LocalDisplayManager\"\nimport {islandNotifications} from \"../services/NotificationsEmitter\"\nimport sttModelManager from \"../services/STTModelManager\"\nimport {miniappLauncher} from \"../services/MiniappLauncher\"\nimport {miniappRunningRegistry} from \"../services/MiniappRunningRegistry\"\nimport {defaultHiddenStatus, isGatedByDevTools, isGatedUntilPaired, resolveHiddenStatus} from \"./appVisibility\"\nimport {SETTINGS, useSettingsStore} from \"./settings\"\nimport {PermissionFeatures, permissions} from \"../facades/permissions\"\nimport BluetoothSdk from \"@glassly/bluetooth-sdk\"\nimport type {MiniappLaunchSource} from \"@glassly/miniapp\"\n\n// ---------------------------------------------------------------------------\n// Configuration / hooks\n// ---------------------------------------------------------------------------\n\nexport interface StartOptions {\n skipNavigation?: boolean\n /** Reported to the miniapp on connect. Defaults to \"phone\". */\n launchSource?: MiniappLaunchSource\n}\n\nexport interface AppStoreHooks {\n /**\n * A start was blocked because the app is hardware-incompatible. Engine made\n * the decision (and raised the `version_incompatible` notification); the host\n * renders its branded alert here.\n */\n onIncompatibleBlocked?: (app: ClientApp) => void\n /**\n * A start was blocked because the app requires the on-device STT model\n * (declared at registration — see AppRegistry.installOfflineApp) and none is\n * installed. Engine decided via its model manager; the host renders the\n * alert / settings navigation here.\n */\n onMissingSpeechModel?: (app: ClientApp) => void\n /**\n * An open request passed the gates — fired on EVERY open, including\n * re-opening an already-running app, so the host's navigation / open\n * animation always plays.\n */\n onOpenRequested?: (app: ClientApp, opts?: StartOptions) => void\n}\n\nlet hostHooks: AppStoreHooks = {}\n\nexport function installAppStoreHooks(hooks: AppStoreHooks): void {\n hostHooks = {...hostHooks, ...hooks}\n}\n\n// ---------------------------------------------------------------------------\n// Store\n// ---------------------------------------------------------------------------\n\ninterface AppStatusState {\n apps: ClientApp[]\n /**\n * Source of truth for which app is foregrounded in the Compositor overlay.\n * The per-app `foregrounded` boolean is derived from this in `projectApps`\n * so a refresh can never drop the flag when an app is transiently missing\n * from one of the two refresh passes (local-only then merged). See\n * `projectApps` / `setForeground` / `clearForeground`.\n */\n foregroundedPackage: string | null\n refresh: () => Promise<void>\n /** Resolves true if the app actually started; false if a host gate aborted it or its JS context failed to spawn. */\n start: (app: ClientApp, opts?: StartOptions) => Promise<boolean>\n stop: (packageName: string) => Promise<void>\n setForeground: (packageName: string) => Promise<void>\n clearForeground: () => void\n stopAll: () => AsyncResult<void, Error>\n install: (url: string, opts?: {versionOverride?: string}) => AsyncResult<void, Error>\n uninstall: (packageName: string, version?: string) => AsyncResult<void, Error>\n saveScreenshot: (packageName: string, screenshot: string) => Promise<void>\n setHiddenStatus: (packageName: string, status: boolean) => void\n getHiddenStatus: (packageName: string) => boolean\n /**\n * Mark a miniapp Always On: it starts at launch and only stops from the\n * app switcher's Always On pill (its card cannot be swiped away and the\n * capsule close minimizes it). Turning it on starts the app; turning it\n * off leaves it running. Persists the wearer's choice beside the hidden flag.\n */\n setAlwaysOn: (packageName: string, status: boolean) => Promise<void>\n /** Replace the whole apps array. Hosts use this when their extra source changes. */\n setApps: (apps: ClientApp[]) => void\n}\n\nexport const DUMMY_APPLET: ClientApp = {\n packageName: \"\",\n name: \"\",\n webviewUrl: \"\",\n logoUrl: \"\",\n type: \"standard\",\n permissions: [],\n running: false,\n loading: false,\n healthy: true,\n hardwareRequirements: [],\n offline: true,\n offlineRoute: \"\",\n local: false,\n hidden: false,\n}\n\nexport type OrderMap = Record<string, number>\nconst APP_ORDER_KEY = \"foreground_apps_order\"\n\nexport const saveAppsOrder = (orderMap: OrderMap): Result<void, Error> => {\n return storage.save(APP_ORDER_KEY, orderMap)\n}\n\nexport const getAppsOrder = (): Result<OrderMap, Error> => {\n return storage.load<OrderMap>(APP_ORDER_KEY)\n}\n\n// In-memory cache for hidden flags. `projectApps` reads getHiddenStatus once\n// per app per refresh — without a cache that was a synchronous JNI hop per\n// app per refresh on a hot UI path. Kept consistent with disk by writing\n// through in setHiddenStatus. Map of packageName → hidden boolean.\nconst hiddenStatusCache = new Map<string, boolean>()\n\nconst getRawPackageNamePriority = (pkg: string): number => {\n if (pkg.includes(\"@empty\")) {\n return 1000\n }\n return 0\n}\n\nexport const sortAppsByPackageNamePriority = (a: ClientApp, b: ClientApp): number => {\n const pa = getRawPackageNamePriority(a.packageName)\n const pb = getRawPackageNamePriority(b.packageName)\n if (pa !== pb) {\n return pa - pb\n }\n return a.name.localeCompare(b.name)\n}\n\nexport const saveLastOpenTime = (packageName: string): void => {\n storage.save(`${packageName}_last_open_time`, Date.now())\n}\n\nexport const getLastOpenTime = (packageName: string): number => {\n const res = storage.load<number>(`${packageName}_last_open_time`)\n if (res.is_ok()) return res.value\n return 0\n}\n\nexport const sortAppsByLastOpenTime = async <T extends {packageName: string}>(apps: T[]): Promise<T[]> => {\n const timestamps = apps.map((app) => ({app, time: getLastOpenTime(app.packageName)}))\n return timestamps.sort((a, b) => a.time - b.time).map((entry) => entry.app)\n}\n\nconst startStopApp = async (app: ClientApp, status: boolean): Promise<void> => {\n if (!status && app.onStop) {\n try {\n app.onStop()\n } catch (e) {\n console.warn(`ISLAND: onStop threw for ${app.packageName}`, e)\n }\n }\n if (status && app.onStart) {\n try {\n app.onStart()\n } catch (e) {\n console.warn(`ISLAND: onStart threw for ${app.packageName}`, e)\n }\n }\n}\n\n/**\n * Build the final `apps` array for the store from the installed/offline app\n * source. Pure — same inputs -> same outputs.\n */\nfunction projectApps(previousState: AppStatusState, localApps: ClientApp[]): ClientApp[] {\n // Dedupe by packageName, keep first occurrence.\n const byPackage = new Map<string, ClientApp>()\n for (const app of localApps) {\n if (!byPackage.has(app.packageName)) byPackage.set(app.packageName, app)\n }\n\n // Index previous snapshot for cheap lookups (was O(N²) via .find()).\n const previousByPackage = new Map<string, ClientApp>()\n for (const oldApp of previousState.apps) {\n previousByPackage.set(oldApp.packageName, oldApp)\n }\n\n const defaultWearable =\n (useSettingsStore.getState().getSetting(SETTINGS.default_wearable.key) as DeviceTypes | undefined) ||\n DeviceTypes.NONE\n const capabilities = getModelCapabilities(defaultWearable)\n const devToolsEnabled = useSettingsStore.getState().getSetting(SETTINGS.dev_tools.key) === true\n const hasPairedGlasses = useSettingsStore.getState().getSetting(SETTINGS.has_paired_glasses.key) === true\n\n // Single pass: dedupe → screenshot carry-over → compat → hidden, all into\n // fresh objects. The previous in-place mutation re-used object references\n // across refreshes, which broke React.memo / referential-equality\n // memoization downstream (every refresh propagated re-renders even when\n // nothing meaningful changed) AND tripped Reanimated's \"tried to modify\n // key of an object already passed to a worklet\" warning whenever the home\n // screen's animated app cards held a reference to a previous snapshot's\n // app object that we then mutated.\n //\n // Identity stability: refresh() is event-driven and fires repeatedly (and\n // twice per cycle via the local-only → merged two-pass emit). If we always\n // returned fresh objects, every poll changed the identity of EVERY app —\n // which re-rendered the Compositor (via useForegroundApp) mid-slide and made\n // the open/close animation hitch, and churned the home grid / switcher pill.\n // So we build the candidate object, then REUSE the previous reference when\n // nothing meaningful changed. Same pattern as the miniappRunningRegistry\n // projection below. A stable foreground-app reference lets the Compositor's\n // slide run uninterrupted on the UI thread.\n return Array.from(byPackage.values())\n .filter(\n (app) =>\n !isGatedByDevTools(app.packageName, devToolsEnabled) &&\n !isGatedUntilPaired(app.packageName, devToolsEnabled, hasPairedGlasses),\n )\n .map((app) => {\n const next: ClientApp = {\n ...app,\n screenshot: previousByPackage.get(app.packageName)?.screenshot ?? app.screenshot,\n compatibility: HardwareCompatibility.checkCompatibility(app.hardwareRequirements, capabilities),\n // A registry source can force an app off the primary home screen.\n // Compose that gate with the user's persisted home-screen layout instead\n // of replacing it, otherwise a default-false persisted value makes a\n // source-hidden app visible again during projection.\n hidden: resolveHiddenStatus(app.hidden, previousState.getHiddenStatus(app.packageName)),\n // Derive the foreground flag from the store's single source of truth\n // (`foregroundedPackage`), NOT from the previous snapshot. Carrying it over\n // per-app meant a refresh that momentarily omitted an app (e.g. the\n // two-pass local-only → merged emit) would reset its flag to false — which\n // raced OfflineAppHost's interceptor guard and made the hosted miniapp fall\n // through to the root router (restart). Deriving here keeps the flag stable\n // across both passes.\n foregrounded: app.packageName === previousState.foregroundedPackage,\n }\n const prev = previousByPackage.get(app.packageName)\n return prev && shallowEqualApp(prev, next) ? prev : next\n })\n}\n\n// Cheap equality check used by projectApps to preserve object identity across\n// refreshes when nothing meaningful changed. Most keys are compared by\n// reference (the source app's nested fields — permissions, hardwareRequirements,\n// parameters — are reference-stable within a refresh). The ONE exception is\n// `compatibility`, which projectApps recomputes into a fresh object every call;\n// comparing it by reference would always differ and defeat the whole point. We\n// compare it structurally instead so identity is only broken when the device's\n// actual compatibility verdict changes (e.g. glasses connect/disconnect).\nfunction shallowEqualApp(a: ClientApp, b: ClientApp): boolean {\n const aKeys = Object.keys(a) as (keyof ClientApp)[]\n const bKeys = Object.keys(b) as (keyof ClientApp)[]\n if (aKeys.length !== bKeys.length) return false\n for (const k of aKeys) {\n if (k === \"compatibility\") {\n if (!compatibilityEqual(a.compatibility, b.compatibility)) return false\n continue\n }\n if (a[k] !== b[k]) return false\n }\n return true\n}\n\nfunction compatibilityEqual(a?: CompatibilityResult, b?: CompatibilityResult): boolean {\n if (a === b) return true\n if (!a || !b) return false\n return (\n a.isCompatible === b.isCompatible &&\n a.missingRequired.length === b.missingRequired.length &&\n a.missingOptional.length === b.missingOptional.length &&\n a.warnings.length === b.warnings.length\n )\n}\n\nexport const useAppStatusStore = create<AppStatusState>((set, get) => ({\n apps: [],\n foregroundedPackage: null,\n\n refresh: async () => {\n const previousState = get()\n const localApps = await appRegistry.getInstalledMiniapps()\n set({apps: projectApps(previousState, localApps)})\n },\n\n start: async (clientApp: ClientApp, opts?: StartOptions) => {\n const state = get()\n const packageName = clientApp.packageName\n const app = state.apps.find((a) => a.packageName === packageName)\n if (!app) {\n console.error(`ISLAND: app not found for package name: ${packageName}`)\n return false\n }\n\n // Skip spawning a NEW app while another is mid-launch — concurrent spawns\n // race the foreground-only-one teardown. This is checked BEFORE the gates\n // and the onOpenRequested seam (which navigates/foregrounds) so a gated\n // launch doesn't paint a splash it can't back. Re-opening an already-running\n // app is exempt: it has nothing to spawn, so it skips this gate and is\n // allowed to re-navigate/animate below.\n // That exemption is the fix for the \"second tap during another app's launch\n // window silently does nothing\" bug.\n if (!app.running && state.apps.some((a) => a.loading)) {\n console.log(`ISLAND: skipping start ${packageName} — another app is loading`)\n return false\n }\n\n if (!app.offline && !app.local) {\n console.warn(`ISLAND: cloud-v1 app entries are no longer supported: ${packageName}`)\n return false\n }\n\n // Hardware-compatibility gate — engine decides and blocks; the host renders\n // its branded alert via onIncompatibleBlocked (and/or the structured\n // notification below). `!isCompatible` (not `=== false`) keeps the semantics\n // of the host gate this replaces: an unknown verdict blocks, not launches.\n if (!app.compatibility?.isCompatible) {\n islandNotifications.emit({\n kind: \"version_incompatible\",\n packageName,\n reason: `${app.name ?? packageName} is not compatible with the connected glasses`,\n metadata: {missingRequired: app.compatibility?.missingRequired ?? []},\n timestamp: Date.now(),\n })\n hostHooks.onIncompatibleBlocked?.(app)\n return false\n }\n\n // Missing-speech-model gate for apps registered with requiresLocalSttModel.\n // Engine decides via its own model manager; the host renders the alert and\n // any settings navigation via onMissingSpeechModel.\n if (appRegistry.requiresLocalSttModel(packageName) && !(await sttModelManager.isModelAvailable())) {\n islandNotifications.emit({\n kind: \"missing_speech_model\",\n packageName,\n reason: `${app.name ?? packageName} needs an on-device speech model before it can start`,\n timestamp: Date.now(),\n })\n hostHooks.onMissingSpeechModel?.(app)\n return false\n }\n\n // Host navigation / open-animation seam. Runs on EVERY accepted open —\n // including re-opening an already-running app — so the animation always\n // plays (BuiltInMiniappCatalog.navigateForApp: overlay apps setForeground\n // for the slide).\n hostHooks.onOpenRequested?.(app, opts)\n\n // First-activation mark (moved from the host's old beforeStart — engine\n // owns the settings store).\n useSettingsStore.getState().setSetting(SETTINGS.has_ever_activated_app.key, true)\n\n // If the tapped app is already running, this is a re-open: the nav/foreground\n // above already drove the animation, and there's nothing to spawn. Short-\n // circuit before the spawn pipeline.\n if (app.running) {\n saveLastOpenTime(packageName)\n return true\n }\n\n // The phone mic is asked for here, at first use, not during pairing: the\n // OS prompt lands over the app that needs it. The facade returns at once\n // when the answer is already known, so this only ever prompts once.\n if (declaresMicrophone(app)) await permissions.request(PermissionFeatures.MICROPHONE)\n\n // Foreground-only-one rule: stop other running standard apps.\n if (app.type === \"standard\") {\n const runningForeground = state.apps.filter(\n (a) => a.running && a.type === \"standard\" && a.packageName !== packageName,\n )\n for (const r of runningForeground) {\n await get().stop(r.packageName)\n }\n }\n\n set((s) => ({\n apps: s.apps.map((a) => (a.packageName === packageName ? {...a, running: true, loading: false} : a)),\n }))\n\n saveLastOpenTime(packageName)\n await startStopApp(app, true)\n\n // Spawn the background JS context for local miniapps. This used to be a\n // side effect of LocalMiniappView mounting on foreground; pulling it here\n // lets start() actually run the app even when nothing foregrounds it (e.g.\n // a system app launching another miniapp via session.miniapps). Idempotent\n // with the view's own ensureRunning; a no-op for native offline built-ins\n // (no JS bundle).\n if (app.local) {\n try {\n await miniappLauncher.ensureRunning(packageName, {launchSource: opts?.launchSource ?? \"phone\"})\n } catch (e) {\n // Spawn / bundle-resolve failed — revert the optimistic running flag so\n // the home list and miniapps.list() don't show a \"running\" app with no\n // JS context, and report failure to the caller (session.miniapps.start).\n console.warn(`ISLAND: launcher.ensureRunning failed for ${packageName}`, e)\n set((s) => ({\n apps: s.apps.map((a) => (a.packageName === packageName ? {...a, running: false, loading: false} : a)),\n }))\n // onStart already persisted running:true to disk (saveLocalAppRunningState)\n // before the spawn; run onStop to undo it so a refresh/reboot doesn't\n // resurrect a \"running\" app with no JS context.\n await startStopApp(app, false)\n return false\n }\n }\n\n return true\n },\n\n stop: async (packageName: string) => {\n const state = get()\n const app = state.apps.find((a) => a.packageName === packageName)\n if (!app) {\n console.error(`ISLAND: app not found for package name: ${packageName}`)\n return\n }\n\n set((s) => ({\n apps: s.apps.map((a) =>\n a.packageName === packageName ? {...a, running: false, screenshot: undefined, loading: false} : a,\n ),\n }))\n\n // if there are no apps running, call clearDisplay():\n // read fresh state via get() — `state` was captured before the set() above, so it still shows\n // this app as running and would never reach 0 when stopping the last app.\n if (get().apps.filter((a) => a.running).length === 0) {\n BluetoothSdk.clearDisplay()\n }\n await startStopApp(app, false)\n\n // Tear down the background JS context for local miniapps. No-op for native\n // offline built-ins.\n if (app.local) {\n try {\n await miniappLauncher.stop(packageName)\n } catch (e) {\n console.warn(`ISLAND: launcher.stop failed for ${packageName}`, e)\n }\n }\n },\n\n setForeground: async (packageName: string) => {\n const app = get().apps.find((a) => a.packageName === packageName)\n if (!app) {\n console.error(`ISLAND: setForeground — app not found: ${packageName}`)\n return\n }\n\n // Flip the foreground flag synchronously so the Compositor's open\n // animation starts on the same frame as the tap. We do NOT await start()\n // first — that gated the flag (and thus the animation) behind the whole\n // JSContext-spawn chain, which was the perceived launch delay. The\n // Compositor/LocalMiniappView already handle the spawn being in-flight\n // (the phase machine), so foregrounding needn't wait for it.\n saveLastOpenTime(packageName)\n set((s) => ({\n foregroundedPackage: packageName,\n apps: s.apps.map((a) => ({...a, foregrounded: a.packageName === packageName})),\n }))\n\n // Ensure the JSContext exists. start() is idempotent for an\n // already-running app and enforces the foreground-only-one rule for\n // standard apps. Fire-and-forget after the flag flip so it doesn't block\n // paint.\n // if (!app.running) {\n // get().start(app)\n // }\n },\n\n clearForeground: () => {\n set((s) => ({\n foregroundedPackage: null,\n apps: s.apps.some((a) => a.foregrounded)\n ? s.apps.map((a) => (a.foregrounded ? {...a, foregrounded: false} : a))\n : s.apps,\n }))\n },\n\n stopAll: () => {\n return Res.try_async(async () => {\n // Always On apps stay up; they stop one at a time from the switcher.\n const running = get().apps.filter((a) => a.running && !a.alwaysOn)\n for (const a of running) {\n await get().stop(a.packageName)\n }\n })\n },\n\n install: (url, opts) => appRegistry.installFromUrl(url, opts),\n\n uninstall: (packageName, version) => {\n return Res.try_async(async () => {\n const res = await appRegistry.uninstall(packageName, version)\n if (res.is_error()) throw res.error\n set((s) => ({apps: s.apps.filter((a) => a.packageName !== packageName)}))\n })\n },\n\n saveScreenshot: async (packageName: string, screenshot: string) => {\n storage.save(`${packageName}_screenshot`, screenshot)\n set((s) => ({\n apps: s.apps.map((a) => (a.packageName === packageName ? {...a, screenshot} : a)),\n }))\n },\n\n setHiddenStatus: (packageName: string, status: boolean) => {\n hiddenStatusCache.set(packageName, status)\n set((s) => ({\n apps: s.apps.map((a) => (a.packageName === packageName ? {...a, hidden: status} : a)),\n }))\n storage.save(`${packageName}_hidden`, status)\n if (!status) {\n const orderMap = getAppsOrder()\n if (orderMap.is_ok()) {\n delete orderMap.value[packageName]\n saveAppsOrder(orderMap.value)\n }\n }\n },\n\n getHiddenStatus: (packageName: string): boolean => {\n const cached = hiddenStatusCache.get(packageName)\n if (cached !== undefined) return cached\n const res = storage.load<boolean>(`${packageName}_hidden`)\n const value = res.is_ok() ? res.value : defaultHiddenStatus(packageName)\n hiddenStatusCache.set(packageName, value)\n return value\n },\n\n setAlwaysOn: async (packageName: string, status: boolean) => {\n const app = get().apps.find((a) => a.packageName === packageName)\n if (!app) return\n saveAlwaysOnOverride(packageName, status)\n set((s) => ({\n apps: s.apps.map((a) => (a.packageName === packageName ? {...a, alwaysOn: status} : a)),\n }))\n if (status && !app.running) await get().start(app, {skipNavigation: true})\n },\n\n setApps: (apps) => set({apps}),\n}))\n\n// Project miniappRunningRegistry membership into the store's `running` field\n// for local apps so the home tray and switcher reflect actual mount state\n// without waiting for the next refresh() cycle.\nminiappRunningRegistry.subscribe(() => {\n const running = new Set(miniappRunningRegistry.getAll())\n const state = useAppStatusStore.getState()\n let changed = false\n const updated = state.apps.map((app) => {\n if (!app.local) return app\n const next = running.has(app.packageName)\n if (app.running === next) return app\n changed = true\n return {...app, running: next}\n })\n if (changed) {\n useAppStatusStore.setState({apps: updated})\n }\n})\n\n// The display-manager's core (foreground) slot is DERIVED state: always the\n// currently-running standard app, no matter HOW it came to run — user tap\n// (start()), boot restore (autostartLocalMiniapps → registry projection\n// above), crash-respawn, or interop. One reconciler instead of per-path call\n// sites, so no launch/stop path can forget to claim or release the slot.\n// onCoreAppChange is idempotent, so firing on every store write is free.\nuseAppStatusStore.subscribe((state) => {\n const core = state.apps.find((a) => a.running && (a.type === \"standard\" || !a.type))\n localDisplayManager.onCoreAppChange(core?.packageName ?? null)\n})\n\n// AppRegistry change events trigger a store refresh.\nappRegistry.subscribe(() => {\n void useAppStatusStore.getState().refresh()\n})\n\n// Re-evaluate hardware compatibility when the paired/default wearable changes.\nuseSettingsStore.subscribe(\n (state) => state.getSetting(SETTINGS.default_wearable.key),\n () => {\n void useAppStatusStore.getState().refresh()\n },\n)\n\n// Developer tools toggled: dev-only apps enter or leave the projection. When\n// they leave, stop any that are running first so the running registry doesn't\n// keep a miniapp alive that no launcher surface can reach.\nuseSettingsStore.subscribe(\n (state) => state.getSetting(SETTINGS.dev_tools.key) === true,\n (enabled) => {\n void (async () => {\n if (!enabled) {\n const state = useAppStatusStore.getState()\n const hasPairedGlasses = useSettingsStore.getState().getSetting(SETTINGS.has_paired_glasses.key) === true\n for (const app of state.apps) {\n const gated =\n isGatedByDevTools(app.packageName, false) || isGatedUntilPaired(app.packageName, false, hasPairedGlasses)\n if (app.running && gated) await state.stop(app.packageName)\n }\n }\n await useAppStatusStore.getState().refresh()\n })()\n },\n)\n\n// First real pairing latched: the Store enters the projection. One-way, so\n// nothing ever leaves here.\nuseSettingsStore.subscribe(\n (state) => state.getSetting(SETTINGS.has_paired_glasses.key) === true,\n () => {\n void useAppStatusStore.getState().refresh()\n },\n)\n\n/** Declares the microphone (or everything) in its manifest. */\nconst declaresMicrophone = (app: ClientApp): boolean =>\n app.permissions.some((p) => p.type === \"MICROPHONE\" || p.type === \"ALL\")\n\n// ---------------------------------------------------------------------------\n// Public hooks\n// ---------------------------------------------------------------------------\n\nexport const useApps = () => useAppStatusStore((state) => state.apps)\nexport const useStart = () => useAppStatusStore((state) => state.start)\nexport const useStop = () => useAppStatusStore((state) => state.stop)\nexport const useSetForeground = () => useAppStatusStore((state) => state.setForeground)\nexport const useClearForeground = () => useAppStatusStore((state) => state.clearForeground)\nexport const useRefresh = () => useAppStatusStore((state) => state.refresh)\nexport const useStopAll = () => useAppStatusStore((state) => state.stopAll)\nexport const useInstall = () => useAppStatusStore((state) => state.install)\nexport const useUninstall = () => useAppStatusStore((state) => state.uninstall)\n\n/** Every running app; each one has a card in the app switcher tray. */\nexport const useActiveApps = () => {\n const apps = useApps()\n return useMemo(() => apps.filter((app) => app.running), [apps])\n}\n\n/** Always On apps whose background task is running, card or no card. */\nexport const useRunningAlwaysOnApps = () => {\n const apps = useApps()\n return useMemo(() => apps.filter((app) => app.alwaysOn && app.running), [apps])\n}\n\n/** Apps that run without a foreground surface: background ones and the system dashboard. */\nconst isBackgroundApp = (app: ClientApp): boolean => app.type === \"background\" || app.type === \"system_dashboard\"\n\nexport const useActiveBackgroundApps = () => {\n const apps = useApps()\n return useMemo(() => apps.filter((app) => isBackgroundApp(app) && app.running), [apps])\n}\n\nexport const useBackgroundApps = () => {\n const apps = useApps()\n return useMemo(\n () => ({\n active: apps.filter((app) => isBackgroundApp(app) && app.running),\n inactive: apps.filter((app) => isBackgroundApp(app) && !app.running),\n }),\n [apps],\n )\n}\n\nexport const useActiveForegroundApp = () => {\n const apps = useApps()\n return useMemo(() => apps.find((app) => (app.type === \"standard\" || !app.type) && app.running) ?? null, [apps])\n}\n\n/**\n * The single app currently foregrounded in the Compositor overlay, or null.\n * Driven by setForeground/clearForeground — distinct from the \"active\n * standard app\" (running) selector above.\n */\nexport const useForegroundApp = () => {\n const apps = useApps()\n return useMemo(() => apps.find((app) => app.foregrounded) ?? null, [apps])\n}\n\nexport const useActiveBackgroundAppsCount = () => {\n const apps = useApps()\n return useMemo(() => apps.filter((app) => isBackgroundApp(app) && app.running).length, [apps])\n}\n\nexport const useLocalMiniApps = () => {\n const apps = useApps()\n return useMemo(() => apps.filter((app) => app.local), [apps])\n}\n"]}
|
package/build/types/applet.d.ts
CHANGED
|
@@ -87,12 +87,12 @@ export interface ClientApp extends AppletInterface {
|
|
|
87
87
|
local: boolean;
|
|
88
88
|
hidden: boolean;
|
|
89
89
|
/**
|
|
90
|
-
*
|
|
91
|
-
* the app switcher's
|
|
92
|
-
* the capsule close minimizes it. Manifest `
|
|
90
|
+
* Always On miniapp: the host starts it at launch and it only stops from
|
|
91
|
+
* the app switcher's Always On pill; its card cannot be swiped away and
|
|
92
|
+
* the capsule close minimizes it. Manifest `alwaysOn` gives the default;
|
|
93
93
|
* the wearer's choice persists beside the hidden flag.
|
|
94
94
|
*/
|
|
95
|
-
|
|
95
|
+
alwaysOn?: boolean;
|
|
96
96
|
onStart?: () => void;
|
|
97
97
|
onStop?: () => void;
|
|
98
98
|
screenshot?: string;
|