@glassly/engine 0.3.8-dev.980 → 0.3.8-dev.982
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/generated/releaseMetadata.js +3 -3
- package/build/generated/releaseMetadata.js.map +1 -1
- package/build/services/LocalDisplayManager.d.ts +2 -0
- package/build/services/LocalDisplayManager.d.ts.map +1 -1
- package/build/services/LocalDisplayManager.js +4 -0
- package/build/services/LocalDisplayManager.js.map +1 -1
- package/build/services/LocalMiniappRuntime.d.ts +6 -0
- package/build/services/LocalMiniappRuntime.d.ts.map +1 -1
- package/build/services/LocalMiniappRuntime.js +23 -0
- package/build/services/LocalMiniappRuntime.js.map +1 -1
- package/build/services/SceneRenderer.d.ts +8 -0
- package/build/services/SceneRenderer.d.ts.map +1 -1
- package/build/services/SceneRenderer.js +28 -0
- package/build/services/SceneRenderer.js.map +1 -1
- package/build/stores/apps.js +9 -9
- package/build/stores/apps.js.map +1 -1
- package/package.json +7 -7
- package/src/generated/releaseMetadata.ts +3 -3
- package/src/services/LocalDisplayManager.ts +5 -0
- package/src/services/LocalMiniappRuntime.ts +24 -0
- package/src/services/SceneRenderer.ts +28 -0
- package/src/stores/apps.ts +11 -11
|
@@ -489,6 +489,11 @@ class LocalDisplayManager {
|
|
|
489
489
|
}
|
|
490
490
|
}
|
|
491
491
|
|
|
492
|
+
/** A frame for native to keep warm, never shown (SceneRenderer.prefetchScene). */
|
|
493
|
+
public prefetch(packageName: string, view: "main" | "dashboard", elements: SceneElementInput[]): boolean {
|
|
494
|
+
return sceneRenderer.prefetchScene(packageName, view, elements)
|
|
495
|
+
}
|
|
496
|
+
|
|
492
497
|
/**
|
|
493
498
|
* The overlay slot only; bypasses arbitration and main ownership state.
|
|
494
499
|
* Frames from an owner other than the slot's are dropped. Returns the scene
|
|
@@ -1495,6 +1495,9 @@ class LocalMiniappRuntime {
|
|
|
1495
1495
|
case MiniappRequestType.SHOW_VIEW:
|
|
1496
1496
|
this.handleShowView(packageName, payload, requestId)
|
|
1497
1497
|
break
|
|
1498
|
+
case MiniappRequestType.PREFETCH:
|
|
1499
|
+
this.handlePrefetch(packageName, payload, requestId)
|
|
1500
|
+
break
|
|
1498
1501
|
case MiniappRequestType.SETTINGS_GET:
|
|
1499
1502
|
this.handleSettingsGet(packageName, payload, requestId)
|
|
1500
1503
|
break
|
|
@@ -2651,6 +2654,27 @@ class LocalMiniappRuntime {
|
|
|
2651
2654
|
)
|
|
2652
2655
|
}
|
|
2653
2656
|
|
|
2657
|
+
/**
|
|
2658
|
+
* display.prefetch: the active dashboard hands over the frame its view would
|
|
2659
|
+
* show if opened now. Native keeps its fonts and images on the glasses while
|
|
2660
|
+
* nothing is on screen; nothing is displayed or retained here.
|
|
2661
|
+
*/
|
|
2662
|
+
private handlePrefetch(packageName: string, payload: Record<string, unknown>, requestId?: string): void {
|
|
2663
|
+
if (payload.view !== "dashboard" || !Array.isArray(payload.elements)) {
|
|
2664
|
+
this.sendResult(packageName, requestId, false, undefined, {
|
|
2665
|
+
code: MiniappErrorCode.INVALID_ARGUMENT,
|
|
2666
|
+
message: 'prefetch takes the "dashboard" view and an elements array',
|
|
2667
|
+
})
|
|
2668
|
+
return
|
|
2669
|
+
}
|
|
2670
|
+
if (!this.connectedApps.has(packageName) || !isDashboardApp(packageName) || !isOverlayApp(packageName)) {
|
|
2671
|
+
this.sendResult(packageName, requestId, true, {status: "unsupported", reason: "not the active dashboard"})
|
|
2672
|
+
return
|
|
2673
|
+
}
|
|
2674
|
+
const sent = localDisplayManager.prefetch(packageName, "dashboard", payload.elements as NonNullable<DisplayPayload["scene"]>)
|
|
2675
|
+
this.sendResult(packageName, requestId, true, sent ? {status: "queued"} : {status: "unsupported", reason: "no scene display"})
|
|
2676
|
+
}
|
|
2677
|
+
|
|
2654
2678
|
/**
|
|
2655
2679
|
* Reject the request with PERMISSION_NOT_DECLARED unless the caller's
|
|
2656
2680
|
* manifest declares `permission`. System apps pass without declaring it.
|
|
@@ -283,6 +283,34 @@ class SceneRenderer {
|
|
|
283
283
|
}
|
|
284
284
|
}
|
|
285
285
|
|
|
286
|
+
/**
|
|
287
|
+
* Hand native the frame `elements` would make for (app, view) without
|
|
288
|
+
* showing it or touching the retained scene: drivers with an on-glass asset
|
|
289
|
+
* cache upload its fonts and images while the panel is idle. Every element
|
|
290
|
+
* is "created" and the frame carries seq 0 (no presentation report). Empty
|
|
291
|
+
* elements drop it. False when there is nothing to send it to.
|
|
292
|
+
*/
|
|
293
|
+
public prefetchScene(appId: string, view: "main" | "dashboard", elements: SceneElementInput[]): boolean {
|
|
294
|
+
const caps = this.currentCapabilities()
|
|
295
|
+
if (!caps?.canPosition) return false
|
|
296
|
+
const processed = processScene(resolveAnchors(elements, caps.width, caps.height), caps, displayProcessor.getSceneProfile())
|
|
297
|
+
let synthetic = 0
|
|
298
|
+
const {elements: created} = diffScene([], processed.elements, () => `~prefetch${synthetic++}`)
|
|
299
|
+
const frame: SceneFrame = {
|
|
300
|
+
appId,
|
|
301
|
+
view,
|
|
302
|
+
sceneEpoch: 0,
|
|
303
|
+
seq: 0,
|
|
304
|
+
elements: created,
|
|
305
|
+
removed: [],
|
|
306
|
+
canvas: {width: caps.width, height: caps.height},
|
|
307
|
+
}
|
|
308
|
+
void Promise.resolve(BluetoothSdk.displayEvent({view, scene: frame, prefetch: true})).catch((err) => {
|
|
309
|
+
console.error(`${LOG_TAG}: native prefetch failed:`, err)
|
|
310
|
+
})
|
|
311
|
+
return true
|
|
312
|
+
}
|
|
313
|
+
|
|
286
314
|
/**
|
|
287
315
|
* Re-emit an app's retained scene (reconnect / arbitration restore). Replay
|
|
288
316
|
* is always create-based — the device rebuilds from scratch (spec §4).
|
package/src/stores/apps.ts
CHANGED
|
@@ -388,17 +388,6 @@ export const useAppStatusStore = create<AppStatusState>((set, get) => ({
|
|
|
388
388
|
// owns the settings store).
|
|
389
389
|
useSettingsStore.getState().setSetting(SETTINGS.has_ever_activated_app.key, true)
|
|
390
390
|
|
|
391
|
-
// If the tapped app is already running, this is a re-open: the nav/foreground
|
|
392
|
-
// above already drove the animation, and there's nothing to spawn. Short-
|
|
393
|
-
// circuit before the spawn pipeline. A promoted app keeps its context but
|
|
394
|
-
// still takes the foreground below.
|
|
395
|
-
if (app.running && !app.widgetOnly) {
|
|
396
|
-
saveLastOpenTime(packageName)
|
|
397
|
-
// The running background only knows the source of its spawn.
|
|
398
|
-
if (app.local) miniappLauncher.notifyLaunch(packageName, opts?.launchSource ?? "phone")
|
|
399
|
-
return true
|
|
400
|
-
}
|
|
401
|
-
|
|
402
391
|
// Only-one rules: one standard app in the foreground, one dashboard
|
|
403
392
|
// drawing the overlay. Starting another stops the one running. Widget-only
|
|
404
393
|
// peers hold no foreground, so they stay.
|
|
@@ -411,6 +400,17 @@ export const useAppStatusStore = create<AppStatusState>((set, get) => ({
|
|
|
411
400
|
}
|
|
412
401
|
}
|
|
413
402
|
|
|
403
|
+
// If the tapped app is already running, this is a re-open: the nav/foreground
|
|
404
|
+
// above already drove the animation, and there's nothing to spawn. Short-
|
|
405
|
+
// circuit before the spawn pipeline. A promoted app keeps its context but
|
|
406
|
+
// still takes the foreground below.
|
|
407
|
+
if (app.running && !app.widgetOnly) {
|
|
408
|
+
saveLastOpenTime(packageName)
|
|
409
|
+
// The running background only knows the source of its spawn.
|
|
410
|
+
if (app.local) miniappLauncher.notifyLaunch(packageName, opts?.launchSource ?? "phone")
|
|
411
|
+
return true
|
|
412
|
+
}
|
|
413
|
+
|
|
414
414
|
set((s) => ({
|
|
415
415
|
apps: s.apps.map((a) => (a.packageName === packageName ? {...a, running: true, loading: false} : a)),
|
|
416
416
|
}))
|