@glassly/engine 0.2.9-dev.452 → 0.2.9-dev.456
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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"applet.d.ts","sourceRoot":"","sources":["../../src/types/applet.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAA;AACpC;;GAEG;AAEH,OAAO,EAAC,mBAAmB,EAAC,MAAM,YAAY,CAAA;AAE9C,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,4BAA4B,CAAA;AAEnE;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,YAAY,GAAG,kBAAkB,CAAA;AAEvE;;GAEG;AACH,MAAM,MAAM,iBAAiB,GACzB,KAAK,GACL,YAAY,GACZ,QAAQ,GACR,UAAU,GACV,UAAU,GACV,qBAAqB,GACrB,oBAAoB,GACpB,gBAAgB,GAChB,oBAAoB,GACpB,UAAU,GACV,QAAQ,GACR,IAAI,GACJ,UAAU,CAAA;AAEd;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,iBAAiB,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,aAAa,CAAC,EAAE,SAAS,CAAA;IACzB,IAAI,EAAE,UAAU,CAAA;IAChB,WAAW,EAAE,gBAAgB,EAAE,CAAA;IAC/B,OAAO,EAAE,OAAO,CAAA;IAChB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,OAAO,EAAE,OAAO,CAAA;IAChB,oBAAoB,EAAE,mBAAmB,EAAE,CAAA;IAC3C,iDAAiD;IACjD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,uFAAuF;IACvF,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED;;;;;;;;GAQG;AACH;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,EAAE,MAAM,CAAA;IACnB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACpC,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACtC;;;OAGG;IACH,UAAU,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAA;CACjC;AAED,MAAM,WAAW,SAAU,SAAQ,eAAe;IAChD,OAAO,EAAE,OAAO,CAAA;IAChB,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,CAAC,EAAE,mBAAmB,CAAA;IACnC,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,OAAO,CAAA;IACd,MAAM,EAAE,OAAO,CAAA;IACf;;;;;OAKG;IACH,
|
|
1
|
+
{"version":3,"file":"applet.d.ts","sourceRoot":"","sources":["../../src/types/applet.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"applet.js","sourceRoot":"","sources":["../../src/types/applet.ts"],"names":[],"mappings":"","sourcesContent":["import type {ReactNode} from \"react\"\n/**\n * App and miniapp types owned by @glassly/engine.\n */\n\nimport {HardwareRequirement} from \"./hardware\"\n\nimport type {CompatibilityResult} from \"../utils/hardware/hardware\"\n\n/**\n * App execution model types\n */\nexport type AppletType = \"standard\" | \"background\" | \"system_dashboard\"\n\n/**\n * Permission types that apps can request\n */\nexport type AppPermissionType =\n | \"ALL\"\n | \"MICROPHONE\"\n | \"CAMERA\"\n | \"CALENDAR\"\n | \"LOCATION\"\n | \"BACKGROUND_LOCATION\"\n | \"READ_NOTIFICATIONS\"\n | \"DISPLAY_MIRROR\"\n | \"POST_NOTIFICATIONS\"\n | \"API_KEYS\"\n | \"MEMORY\"\n | \"AI\"\n | \"SPEAKERS\"\n\n/**\n * Permission object with type and description\n */\nexport interface AppletPermission {\n type: AppPermissionType\n description?: string\n required?: boolean\n}\n\n/**\n * Minimal app interface for client home screen display\n * Optimized for fast rendering - only essential fields\n *\n * This is the client-facing interface used by mobile apps.\n * Internal cloud services use AppI from models (more fields).\n */\nexport interface AppletInterface {\n packageName: string\n name: string\n webviewUrl: string\n logoUrl: string\n iconComponent?: ReactNode\n type: AppletType\n permissions: AppletPermission[]\n running: boolean\n /**\n * True while this app's UI WebView is mounted in the Compositor overlay.\n * At most one app is foregrounded at a time. Distinct from `running`:\n * a foregrounded app is always running, but a running app may be\n * backgrounded (JSContext alive, WebView torn down). Normalized to a\n * concrete boolean by the apps store's projectApps; literal call sites\n * may omit it.\n */\n foregrounded?: boolean\n healthy: boolean\n hardwareRequirements: HardwareRequirement[]\n /** ISO date string when the app was installed */\n installedDate?: string\n /** ISO date string when the app was last run. Undefined if never run (app is \"new\") */\n lastActiveAt?: string\n}\n\n/**\n * Runtime applet shape used by the engine apps store and OEM hosts.\n *\n * Extends AppletInterface with the host-side fields the manager / OEM tracks\n * outside the manifest: offline routing, hardware compatibility result,\n * loading/hidden/local flags, lifecycle hooks, screenshot, and the\n * dev-miniapp escape hatches (`devUrl` / `isMiniappDev`) that surface a\n * `glassly-miniapp dev` snapshot.\n */\n/**\n * A manifest-declared action a miniapp exposes for other miniapps to invoke\n * via `session.actions`. Populated from `miniapp.json`'s `actions` field.\n * Shape maps 1:1 onto an MCP tool (id→name, description, parameters→inputSchema).\n */\nexport interface DeclaredAction {\n id: string\n description: string\n /** JSON-Schema input descriptor (MCP-compatible subset). */\n parameters?: Record<string, unknown>\n /** JSON-Schema descriptor for the action's structured result. */\n outputSchema?: Record<string, unknown>\n /**\n * Who may invoke the action: \"public\" (default — any installed miniapp) or\n * \"system\" (system miniapps such as the AI assistant only).\n */\n visibility?: \"public\" | \"system\"\n}\n\nexport interface ClientApp extends AppletInterface {\n offline: boolean\n offlineRoute: string\n compatibility?: CompatibilityResult\n loading: boolean\n local: boolean\n hidden: boolean\n /**\n *
|
|
1
|
+
{"version":3,"file":"applet.js","sourceRoot":"","sources":["../../src/types/applet.ts"],"names":[],"mappings":"","sourcesContent":["import type {ReactNode} from \"react\"\n/**\n * App and miniapp types owned by @glassly/engine.\n */\n\nimport {HardwareRequirement} from \"./hardware\"\n\nimport type {CompatibilityResult} from \"../utils/hardware/hardware\"\n\n/**\n * App execution model types\n */\nexport type AppletType = \"standard\" | \"background\" | \"system_dashboard\"\n\n/**\n * Permission types that apps can request\n */\nexport type AppPermissionType =\n | \"ALL\"\n | \"MICROPHONE\"\n | \"CAMERA\"\n | \"CALENDAR\"\n | \"LOCATION\"\n | \"BACKGROUND_LOCATION\"\n | \"READ_NOTIFICATIONS\"\n | \"DISPLAY_MIRROR\"\n | \"POST_NOTIFICATIONS\"\n | \"API_KEYS\"\n | \"MEMORY\"\n | \"AI\"\n | \"SPEAKERS\"\n\n/**\n * Permission object with type and description\n */\nexport interface AppletPermission {\n type: AppPermissionType\n description?: string\n required?: boolean\n}\n\n/**\n * Minimal app interface for client home screen display\n * Optimized for fast rendering - only essential fields\n *\n * This is the client-facing interface used by mobile apps.\n * Internal cloud services use AppI from models (more fields).\n */\nexport interface AppletInterface {\n packageName: string\n name: string\n webviewUrl: string\n logoUrl: string\n iconComponent?: ReactNode\n type: AppletType\n permissions: AppletPermission[]\n running: boolean\n /**\n * True while this app's UI WebView is mounted in the Compositor overlay.\n * At most one app is foregrounded at a time. Distinct from `running`:\n * a foregrounded app is always running, but a running app may be\n * backgrounded (JSContext alive, WebView torn down). Normalized to a\n * concrete boolean by the apps store's projectApps; literal call sites\n * may omit it.\n */\n foregrounded?: boolean\n healthy: boolean\n hardwareRequirements: HardwareRequirement[]\n /** ISO date string when the app was installed */\n installedDate?: string\n /** ISO date string when the app was last run. Undefined if never run (app is \"new\") */\n lastActiveAt?: string\n}\n\n/**\n * Runtime applet shape used by the engine apps store and OEM hosts.\n *\n * Extends AppletInterface with the host-side fields the manager / OEM tracks\n * outside the manifest: offline routing, hardware compatibility result,\n * loading/hidden/local flags, lifecycle hooks, screenshot, and the\n * dev-miniapp escape hatches (`devUrl` / `isMiniappDev`) that surface a\n * `glassly-miniapp dev` snapshot.\n */\n/**\n * A manifest-declared action a miniapp exposes for other miniapps to invoke\n * via `session.actions`. Populated from `miniapp.json`'s `actions` field.\n * Shape maps 1:1 onto an MCP tool (id→name, description, parameters→inputSchema).\n */\nexport interface DeclaredAction {\n id: string\n description: string\n /** JSON-Schema input descriptor (MCP-compatible subset). */\n parameters?: Record<string, unknown>\n /** JSON-Schema descriptor for the action's structured result. */\n outputSchema?: Record<string, unknown>\n /**\n * Who may invoke the action: \"public\" (default — any installed miniapp) or\n * \"system\" (system miniapps such as the AI assistant only).\n */\n visibility?: \"public\" | \"system\"\n}\n\nexport interface ClientApp extends AppletInterface {\n offline: boolean\n offlineRoute: string\n compatibility?: CompatibilityResult\n loading: boolean\n local: boolean\n hidden: boolean\n /**\n * Always On miniapp: the host starts it at launch and it only stops from\n * the app switcher's Always On pill; its card cannot be swiped away and\n * the capsule close minimizes it. Manifest `alwaysOn` gives the default;\n * the wearer's choice persists beside the hidden flag.\n */\n alwaysOn?: boolean\n onStart?: () => void\n onStop?: () => void\n screenshot?: string\n runtimePermissions?: string[]\n declaredPermissions?: string[]\n version?: string\n /** Manifest `description`: the paragraph the store and the info page show. */\n description?: string\n /** Manifest `tagline`: one line under the name. */\n tagline?: string\n /** Manifest `tags`: lowercase store tag slugs. */\n tags?: string[]\n needsPcm?: boolean\n needsTranscript?: boolean\n devUrl?: string\n devPort?: number\n isMiniappDev?: boolean\n /** Manifest-declared actions (for session.miniapps.list + invoke gating). */\n actions?: DeclaredAction[]\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@glassly/engine",
|
|
3
|
-
"version": "0.2.9-dev.
|
|
3
|
+
"version": "0.2.9-dev.456",
|
|
4
4
|
"description": "Glassly Engine — miniapp registry, WebView bridge, and miniapp store",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"react-native": "src/index.ts",
|
|
@@ -97,17 +97,17 @@
|
|
|
97
97
|
"registry": "https://registry.npmjs.org/"
|
|
98
98
|
},
|
|
99
99
|
"dependencies": {
|
|
100
|
-
"@glassly/bluetooth-sdk": "0.2.9-dev.
|
|
101
|
-
"@glassly/cloud-client": "0.2.9-dev.
|
|
102
|
-
"@glassly/cloud-protocol": "0.2.9-dev.
|
|
103
|
-
"@glassly/crust": "0.2.9-dev.
|
|
104
|
-
"@glassly/miniapp": "0.2.9-dev.
|
|
100
|
+
"@glassly/bluetooth-sdk": "0.2.9-dev.456",
|
|
101
|
+
"@glassly/cloud-client": "0.2.9-dev.456",
|
|
102
|
+
"@glassly/cloud-protocol": "0.2.9-dev.456",
|
|
103
|
+
"@glassly/crust": "0.2.9-dev.456",
|
|
104
|
+
"@glassly/miniapp": "0.2.9-dev.456",
|
|
105
105
|
"buffer": "^6.0.3",
|
|
106
106
|
"events": "^3.3.0",
|
|
107
107
|
"react-native-marked": "8.1.1",
|
|
108
108
|
"semver": "^7.7.4",
|
|
109
109
|
"typesafe-ts": "^1.7.1",
|
|
110
|
-
"@glassly/llm-providers": "0.2.9-dev.
|
|
110
|
+
"@glassly/llm-providers": "0.2.9-dev.456"
|
|
111
111
|
},
|
|
112
112
|
"devDependencies": {
|
|
113
113
|
"@glassly/llm-providers": "workspace:*",
|
package/src/facades/miniapps.ts
CHANGED
|
@@ -59,7 +59,6 @@ export const miniapps = {
|
|
|
59
59
|
/** Hide/show a miniapp on the home surfaces. */
|
|
60
60
|
setHiddenStatus: (...args: Parameters<AppsState["setHiddenStatus"]>) =>
|
|
61
61
|
useAppStatusStore.getState().setHiddenStatus(...args),
|
|
62
|
-
/** Mark a miniapp
|
|
63
|
-
|
|
64
|
-
useAppStatusStore.getState().setPersistent(...args),
|
|
62
|
+
/** Mark a miniapp Always On (starts at launch, stops only from the switcher pill), persisted for the next boot. */
|
|
63
|
+
setAlwaysOn: (...args: Parameters<AppsState["setAlwaysOn"]>) => useAppStatusStore.getState().setAlwaysOn(...args),
|
|
65
64
|
}
|
|
@@ -12,9 +12,9 @@ export interface EngineReleaseMetadata {
|
|
|
12
12
|
export const ENGINE_RELEASE_METADATA: Readonly<EngineReleaseMetadata> = Object.freeze({
|
|
13
13
|
"schemaVersion": 1,
|
|
14
14
|
"familyBaseVersion": "0.2.9",
|
|
15
|
-
"releaseIdentity": "0.2.9-dev.
|
|
16
|
-
"releaseSetId": "glassly-0.2.9-dev.
|
|
17
|
-
"sourceCommit": "
|
|
15
|
+
"releaseIdentity": "0.2.9-dev.456",
|
|
16
|
+
"releaseSetId": "glassly-0.2.9-dev.456",
|
|
17
|
+
"sourceCommit": "86a7726078e8a81b9657f15d7c53974ac3ad1cf2",
|
|
18
18
|
"otaManifestUrl": null,
|
|
19
19
|
"otaManifestSha256": null
|
|
20
20
|
})
|
package/src/index.ts
CHANGED
|
@@ -752,7 +752,7 @@ class AppRegistry {
|
|
|
752
752
|
permissions?: Array<string | {type: string; required?: boolean; description?: string}>
|
|
753
753
|
hardwareRequirements?: Array<{type: string; level: string; description?: string}>
|
|
754
754
|
type?: string
|
|
755
|
-
|
|
755
|
+
alwaysOn?: unknown
|
|
756
756
|
description?: unknown
|
|
757
757
|
tagline?: unknown
|
|
758
758
|
tags?: unknown
|
|
@@ -798,7 +798,7 @@ class AppRegistry {
|
|
|
798
798
|
webviewUrl: "",
|
|
799
799
|
logoUrl: versionInfo.logoUrl,
|
|
800
800
|
type: appType,
|
|
801
|
-
|
|
801
|
+
alwaysOn: getAlwaysOnOverride(lmaInfo.packageName) ?? manifest?.alwaysOn === true,
|
|
802
802
|
permissions,
|
|
803
803
|
hardwareRequirements,
|
|
804
804
|
...(description ? {description} : {}),
|
|
@@ -946,14 +946,14 @@ export function getLocalAppRunningState(packageName: string): boolean {
|
|
|
946
946
|
return false
|
|
947
947
|
}
|
|
948
948
|
|
|
949
|
-
/** The wearer's
|
|
950
|
-
export function
|
|
951
|
-
const res = storage.load<boolean>(`${packageName}
|
|
949
|
+
/** The wearer's Always On choice for a miniapp, beside the `_hidden` flag; null when they never chose. */
|
|
950
|
+
export function getAlwaysOnOverride(packageName: string): boolean | null {
|
|
951
|
+
const res = storage.load<boolean>(`${packageName}_always_on`)
|
|
952
952
|
return res.is_ok() ? res.value : null
|
|
953
953
|
}
|
|
954
954
|
|
|
955
|
-
export function
|
|
956
|
-
storage.save(`${packageName}
|
|
955
|
+
export function saveAlwaysOnOverride(packageName: string, status: boolean): void {
|
|
956
|
+
storage.save(`${packageName}_always_on`, status)
|
|
957
957
|
}
|
|
958
958
|
|
|
959
959
|
export function getLocalAppScreenshot(packageName: string): string | undefined {
|
|
@@ -253,10 +253,9 @@ const SYSTEM_MINIAPP_PACKAGES = new Set([
|
|
|
253
253
|
"com.glassly.ai",
|
|
254
254
|
"com.glassly.feedback",
|
|
255
255
|
"com.glassly.miniappdev",
|
|
256
|
-
// The dashboard: the settings bridge and the miniapp list/start/stop are its side menu and settings
|
|
256
|
+
// The dashboard: the settings bridge and the miniapp list/start/stop are its side menu and settings
|
|
257
|
+
// page, and the notification app list is its notification settings' per-app filter.
|
|
257
258
|
"com.glassly.dashboard",
|
|
258
|
-
// The notifications viewer: the settings bridge and the notification app list are its settings page.
|
|
259
|
-
"com.glassly.notifications",
|
|
260
259
|
])
|
|
261
260
|
const PING_INTERVAL_MS = 5_000
|
|
262
261
|
// Min gap between "transcription limit reached" notices on the glasses. A
|
|
@@ -304,10 +304,10 @@ class MiniappLauncher {
|
|
|
304
304
|
* dropped just because glasses are momentarily disconnected at boot — it
|
|
305
305
|
* resumes when they reconnect, same as mid-session.
|
|
306
306
|
*
|
|
307
|
-
*
|
|
307
|
+
* Always On apps (the dashboard) start whether or not they were running
|
|
308
308
|
* when the app was last killed, and get a switcher card like any other app.
|
|
309
309
|
* Both restore paths skip apps missing required OS permissions without
|
|
310
|
-
* prompting or clearing their saved running/
|
|
310
|
+
* prompting or clearing their saved running/Always On choice.
|
|
311
311
|
*/
|
|
312
312
|
async autostartLocalMiniapps(): Promise<void> {
|
|
313
313
|
const apps = await appRegistry.getInstalledMiniapps()
|
|
@@ -316,7 +316,7 @@ class MiniappLauncher {
|
|
|
316
316
|
// built-ins (`local:false, offline:true`) restore their native running
|
|
317
317
|
// state elsewhere and have no bundle to launch.
|
|
318
318
|
if (!app.local) continue
|
|
319
|
-
if (!app.
|
|
319
|
+
if (!app.alwaysOn && !getLocalAppRunningState(app.packageName)) continue
|
|
320
320
|
if (this.isRunning(app.packageName)) continue
|
|
321
321
|
try {
|
|
322
322
|
const missing = await permissions.missingRequired(app.permissions ?? [])
|
|
@@ -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.
|
package/src/stores/apps.ts
CHANGED
|
@@ -19,7 +19,7 @@ import {DeviceTypes} from "../types/enums"
|
|
|
19
19
|
import {getModelCapabilities} from "../types/hardware"
|
|
20
20
|
import {HardwareCompatibility, type CompatibilityResult} from "../utils/hardware/hardware"
|
|
21
21
|
import {storage} from "../utils/storage/storage"
|
|
22
|
-
import appRegistry, {
|
|
22
|
+
import appRegistry, {saveAlwaysOnOverride} from "../services/AppRegistry"
|
|
23
23
|
import localDisplayManager from "../services/LocalDisplayManager"
|
|
24
24
|
import {islandNotifications} from "../services/NotificationsEmitter"
|
|
25
25
|
import sttModelManager from "../services/STTModelManager"
|
|
@@ -96,12 +96,12 @@ interface AppStatusState {
|
|
|
96
96
|
setHiddenStatus: (packageName: string, status: boolean) => void
|
|
97
97
|
getHiddenStatus: (packageName: string) => boolean
|
|
98
98
|
/**
|
|
99
|
-
* Mark a miniapp
|
|
100
|
-
* app switcher's
|
|
99
|
+
* Mark a miniapp Always On: it starts at launch and only stops from the
|
|
100
|
+
* app switcher's Always On pill (its card cannot be swiped away and the
|
|
101
101
|
* capsule close minimizes it). Turning it on starts the app; turning it
|
|
102
102
|
* off leaves it running. Persists the wearer's choice beside the hidden flag.
|
|
103
103
|
*/
|
|
104
|
-
|
|
104
|
+
setAlwaysOn: (packageName: string, status: boolean) => Promise<void>
|
|
105
105
|
/** Replace the whole apps array. Hosts use this when their extra source changes. */
|
|
106
106
|
setApps: (apps: ClientApp[]) => void
|
|
107
107
|
}
|
|
@@ -500,8 +500,8 @@ export const useAppStatusStore = create<AppStatusState>((set, get) => ({
|
|
|
500
500
|
|
|
501
501
|
stopAll: () => {
|
|
502
502
|
return Res.try_async(async () => {
|
|
503
|
-
//
|
|
504
|
-
const running = get().apps.filter((a) => a.running && !a.
|
|
503
|
+
// Always On apps stay up; they stop one at a time from the switcher.
|
|
504
|
+
const running = get().apps.filter((a) => a.running && !a.alwaysOn)
|
|
505
505
|
for (const a of running) {
|
|
506
506
|
await get().stop(a.packageName)
|
|
507
507
|
}
|
|
@@ -549,12 +549,12 @@ export const useAppStatusStore = create<AppStatusState>((set, get) => ({
|
|
|
549
549
|
return value
|
|
550
550
|
},
|
|
551
551
|
|
|
552
|
-
|
|
552
|
+
setAlwaysOn: async (packageName: string, status: boolean) => {
|
|
553
553
|
const app = get().apps.find((a) => a.packageName === packageName)
|
|
554
554
|
if (!app) return
|
|
555
|
-
|
|
555
|
+
saveAlwaysOnOverride(packageName, status)
|
|
556
556
|
set((s) => ({
|
|
557
|
-
apps: s.apps.map((a) => (a.packageName === packageName ? {...a,
|
|
557
|
+
apps: s.apps.map((a) => (a.packageName === packageName ? {...a, alwaysOn: status} : a)),
|
|
558
558
|
}))
|
|
559
559
|
if (status && !app.running) await get().start(app, {skipNavigation: true})
|
|
560
560
|
},
|
|
@@ -659,10 +659,10 @@ export const useActiveApps = () => {
|
|
|
659
659
|
return useMemo(() => apps.filter((app) => app.running), [apps])
|
|
660
660
|
}
|
|
661
661
|
|
|
662
|
-
/**
|
|
663
|
-
export const
|
|
662
|
+
/** Always On apps whose background task is running, card or no card. */
|
|
663
|
+
export const useRunningAlwaysOnApps = () => {
|
|
664
664
|
const apps = useApps()
|
|
665
|
-
return useMemo(() => apps.filter((app) => app.
|
|
665
|
+
return useMemo(() => apps.filter((app) => app.alwaysOn && app.running), [apps])
|
|
666
666
|
}
|
|
667
667
|
|
|
668
668
|
/** Apps that run without a foreground surface: background ones and the system dashboard. */
|
package/src/types/applet.ts
CHANGED
|
@@ -108,12 +108,12 @@ export interface ClientApp extends AppletInterface {
|
|
|
108
108
|
local: boolean
|
|
109
109
|
hidden: boolean
|
|
110
110
|
/**
|
|
111
|
-
*
|
|
112
|
-
* the app switcher's
|
|
113
|
-
* the capsule close minimizes it. Manifest `
|
|
111
|
+
* Always On miniapp: the host starts it at launch and it only stops from
|
|
112
|
+
* the app switcher's Always On pill; its card cannot be swiped away and
|
|
113
|
+
* the capsule close minimizes it. Manifest `alwaysOn` gives the default;
|
|
114
114
|
* the wearer's choice persists beside the hidden flag.
|
|
115
115
|
*/
|
|
116
|
-
|
|
116
|
+
alwaysOn?: boolean
|
|
117
117
|
onStart?: () => void
|
|
118
118
|
onStop?: () => void
|
|
119
119
|
screenshot?: string
|