@mentra/miniapp 0.3.0-beta.0
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/README.md +259 -0
- package/dist/background/index.d.ts +60 -0
- package/dist/background/index.d.ts.map +1 -0
- package/dist/background/index.js +25 -0
- package/dist/background/index.js.map +1 -0
- package/dist/background/register.d.ts +38 -0
- package/dist/background/register.d.ts.map +1 -0
- package/dist/background/register.js +75 -0
- package/dist/background/register.js.map +1 -0
- package/dist/dev-reload.d.ts +21 -0
- package/dist/dev-reload.d.ts.map +1 -0
- package/dist/dev-reload.js +62 -0
- package/dist/dev-reload.js.map +1 -0
- package/dist/envelope.d.ts +23 -0
- package/dist/envelope.d.ts.map +1 -0
- package/dist/envelope.js +47 -0
- package/dist/envelope.js.map +1 -0
- package/dist/globals.d.ts +54 -0
- package/dist/globals.d.ts.map +1 -0
- package/dist/globals.js +12 -0
- package/dist/globals.js.map +1 -0
- package/dist/index.d.ts +59 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/modules/actions.d.ts +54 -0
- package/dist/modules/actions.d.ts.map +1 -0
- package/dist/modules/actions.js +122 -0
- package/dist/modules/actions.js.map +1 -0
- package/dist/modules/auth.d.ts +25 -0
- package/dist/modules/auth.d.ts.map +1 -0
- package/dist/modules/auth.js +52 -0
- package/dist/modules/auth.js.map +1 -0
- package/dist/modules/base64.d.ts +16 -0
- package/dist/modules/base64.d.ts.map +1 -0
- package/dist/modules/base64.js +92 -0
- package/dist/modules/base64.js.map +1 -0
- package/dist/modules/blob.d.ts +161 -0
- package/dist/modules/blob.d.ts.map +1 -0
- package/dist/modules/blob.js +277 -0
- package/dist/modules/blob.js.map +1 -0
- package/dist/modules/camera.d.ts +170 -0
- package/dist/modules/camera.d.ts.map +1 -0
- package/dist/modules/camera.js +116 -0
- package/dist/modules/camera.js.map +1 -0
- package/dist/modules/cloud.d.ts +34 -0
- package/dist/modules/cloud.d.ts.map +1 -0
- package/dist/modules/cloud.js +70 -0
- package/dist/modules/cloud.js.map +1 -0
- package/dist/modules/dashboard.d.ts +16 -0
- package/dist/modules/dashboard.d.ts.map +1 -0
- package/dist/modules/dashboard.js +27 -0
- package/dist/modules/dashboard.js.map +1 -0
- package/dist/modules/display.d.ts +106 -0
- package/dist/modules/display.d.ts.map +1 -0
- package/dist/modules/display.js +57 -0
- package/dist/modules/display.js.map +1 -0
- package/dist/modules/events.d.ts +160 -0
- package/dist/modules/events.d.ts.map +1 -0
- package/dist/modules/events.js +168 -0
- package/dist/modules/events.js.map +1 -0
- package/dist/modules/glasses.d.ts +28 -0
- package/dist/modules/glasses.d.ts.map +1 -0
- package/dist/modules/glasses.js +39 -0
- package/dist/modules/glasses.js.map +1 -0
- package/dist/modules/heading.d.ts +16 -0
- package/dist/modules/heading.d.ts.map +1 -0
- package/dist/modules/heading.js +20 -0
- package/dist/modules/heading.js.map +1 -0
- package/dist/modules/imu.d.ts +31 -0
- package/dist/modules/imu.d.ts.map +1 -0
- package/dist/modules/imu.js +40 -0
- package/dist/modules/imu.js.map +1 -0
- package/dist/modules/input.d.ts +34 -0
- package/dist/modules/input.d.ts.map +1 -0
- package/dist/modules/input.js +50 -0
- package/dist/modules/input.js.map +1 -0
- package/dist/modules/led.d.ts +35 -0
- package/dist/modules/led.d.ts.map +1 -0
- package/dist/modules/led.js +39 -0
- package/dist/modules/led.js.map +1 -0
- package/dist/modules/location.d.ts +27 -0
- package/dist/modules/location.d.ts.map +1 -0
- package/dist/modules/location.js +35 -0
- package/dist/modules/location.js.map +1 -0
- package/dist/modules/mic.d.ts +44 -0
- package/dist/modules/mic.d.ts.map +1 -0
- package/dist/modules/mic.js +67 -0
- package/dist/modules/mic.js.map +1 -0
- package/dist/modules/miniapps.d.ts +72 -0
- package/dist/modules/miniapps.d.ts.map +1 -0
- package/dist/modules/miniapps.js +48 -0
- package/dist/modules/miniapps.js.map +1 -0
- package/dist/modules/navigation.d.ts +326 -0
- package/dist/modules/navigation.d.ts.map +1 -0
- package/dist/modules/navigation.js +386 -0
- package/dist/modules/navigation.js.map +1 -0
- package/dist/modules/permissions.d.ts +58 -0
- package/dist/modules/permissions.d.ts.map +1 -0
- package/dist/modules/permissions.js +66 -0
- package/dist/modules/permissions.js.map +1 -0
- package/dist/modules/phone.d.ts +95 -0
- package/dist/modules/phone.d.ts.map +1 -0
- package/dist/modules/phone.js +110 -0
- package/dist/modules/phone.js.map +1 -0
- package/dist/modules/pivots/engine.d.ts +169 -0
- package/dist/modules/pivots/engine.d.ts.map +1 -0
- package/dist/modules/pivots/engine.js +779 -0
- package/dist/modules/pivots/engine.js.map +1 -0
- package/dist/modules/pivots/geometry.d.ts +84 -0
- package/dist/modules/pivots/geometry.d.ts.map +1 -0
- package/dist/modules/pivots/geometry.js +371 -0
- package/dist/modules/pivots/geometry.js.map +1 -0
- package/dist/modules/pivots/instructions.d.ts +139 -0
- package/dist/modules/pivots/instructions.d.ts.map +1 -0
- package/dist/modules/pivots/instructions.js +280 -0
- package/dist/modules/pivots/instructions.js.map +1 -0
- package/dist/modules/speaker.d.ts +169 -0
- package/dist/modules/speaker.d.ts.map +1 -0
- package/dist/modules/speaker.js +251 -0
- package/dist/modules/speaker.js.map +1 -0
- package/dist/modules/storage.d.ts +50 -0
- package/dist/modules/storage.d.ts.map +1 -0
- package/dist/modules/storage.js +99 -0
- package/dist/modules/storage.js.map +1 -0
- package/dist/modules/stream.d.ts +129 -0
- package/dist/modules/stream.d.ts.map +1 -0
- package/dist/modules/stream.js +52 -0
- package/dist/modules/stream.js.map +1 -0
- package/dist/modules/system.d.ts +45 -0
- package/dist/modules/system.d.ts.map +1 -0
- package/dist/modules/system.js +42 -0
- package/dist/modules/system.js.map +1 -0
- package/dist/modules/transcription.d.ts +75 -0
- package/dist/modules/transcription.d.ts.map +1 -0
- package/dist/modules/transcription.js +106 -0
- package/dist/modules/transcription.js.map +1 -0
- package/dist/modules/translation.d.ts +59 -0
- package/dist/modules/translation.d.ts.map +1 -0
- package/dist/modules/translation.js +119 -0
- package/dist/modules/translation.js.map +1 -0
- package/dist/modules/ui.d.ts +186 -0
- package/dist/modules/ui.d.ts.map +1 -0
- package/dist/modules/ui.js +293 -0
- package/dist/modules/ui.js.map +1 -0
- package/dist/protocol.d.ts +299 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +325 -0
- package/dist/protocol.js.map +1 -0
- package/dist/react/MentraProvider.d.ts +33 -0
- package/dist/react/MentraProvider.d.ts.map +1 -0
- package/dist/react/MentraProvider.js +15 -0
- package/dist/react/MentraProvider.js.map +1 -0
- package/dist/react/MiniappHeader.d.ts +44 -0
- package/dist/react/MiniappHeader.d.ts.map +1 -0
- package/dist/react/MiniappHeader.js +32 -0
- package/dist/react/MiniappHeader.js.map +1 -0
- package/dist/react/index.d.ts +13 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +9 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/useCapabilities.d.ts +26 -0
- package/dist/react/useCapabilities.d.ts.map +1 -0
- package/dist/react/useCapabilities.js +27 -0
- package/dist/react/useCapabilities.js.map +1 -0
- package/dist/react/useCapsuleHeaderStyle.d.ts +27 -0
- package/dist/react/useCapsuleHeaderStyle.d.ts.map +1 -0
- package/dist/react/useCapsuleHeaderStyle.js +36 -0
- package/dist/react/useCapsuleHeaderStyle.js.map +1 -0
- package/dist/react/useColorScheme.d.ts +18 -0
- package/dist/react/useColorScheme.d.ts.map +1 -0
- package/dist/react/useColorScheme.js +24 -0
- package/dist/react/useColorScheme.js.map +1 -0
- package/dist/react/useConnected.d.ts +17 -0
- package/dist/react/useConnected.d.ts.map +1 -0
- package/dist/react/useConnected.js +39 -0
- package/dist/react/useConnected.js.map +1 -0
- package/dist/react/useRpc.d.ts +29 -0
- package/dist/react/useRpc.d.ts.map +1 -0
- package/dist/react/useRpc.js +82 -0
- package/dist/react/useRpc.js.map +1 -0
- package/dist/react/useSafeArea.d.ts +21 -0
- package/dist/react/useSafeArea.d.ts.map +1 -0
- package/dist/react/useSafeArea.js +22 -0
- package/dist/react/useSafeArea.js.map +1 -0
- package/dist/session.d.ts +312 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +653 -0
- package/dist/session.js.map +1 -0
- package/dist/sub-path-types.test-d.d.ts +28 -0
- package/dist/sub-path-types.test-d.d.ts.map +1 -0
- package/dist/sub-path-types.test-d.js +37 -0
- package/dist/sub-path-types.test-d.js.map +1 -0
- package/dist/transport/auto.d.ts +35 -0
- package/dist/transport/auto.d.ts.map +1 -0
- package/dist/transport/auto.js +125 -0
- package/dist/transport/auto.js.map +1 -0
- package/dist/transport/dispatch.d.ts +43 -0
- package/dist/transport/dispatch.d.ts.map +1 -0
- package/dist/transport/dispatch.js +91 -0
- package/dist/transport/dispatch.js.map +1 -0
- package/dist/transport/local-socket.d.ts +28 -0
- package/dist/transport/local-socket.d.ts.map +1 -0
- package/dist/transport/local-socket.js +80 -0
- package/dist/transport/local-socket.js.map +1 -0
- package/dist/transport/mock.d.ts +54 -0
- package/dist/transport/mock.d.ts.map +1 -0
- package/dist/transport/mock.js +207 -0
- package/dist/transport/mock.js.map +1 -0
- package/dist/transport/postmessage.d.ts +36 -0
- package/dist/transport/postmessage.d.ts.map +1 -0
- package/dist/transport/postmessage.js +78 -0
- package/dist/transport/postmessage.js.map +1 -0
- package/dist/transport/types.d.ts +25 -0
- package/dist/transport/types.d.ts.map +1 -0
- package/dist/transport/types.js +11 -0
- package/dist/transport/types.js.map +1 -0
- package/dist/ui/index.d.ts +98 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +32 -0
- package/dist/ui/index.js.map +1 -0
- package/package.json +84 -0
- package/src/background/index.ts +152 -0
- package/src/background/register.ts +85 -0
- package/src/dev-reload.ts +60 -0
- package/src/envelope.ts +54 -0
- package/src/globals.ts +62 -0
- package/src/index.ts +171 -0
- package/src/modules/actions.ts +156 -0
- package/src/modules/auth.ts +68 -0
- package/src/modules/base64.ts +87 -0
- package/src/modules/blob.ts +341 -0
- package/src/modules/camera.ts +242 -0
- package/src/modules/cloud.ts +94 -0
- package/src/modules/dashboard.ts +31 -0
- package/src/modules/display.ts +122 -0
- package/src/modules/events.ts +291 -0
- package/src/modules/glasses.ts +44 -0
- package/src/modules/heading.ts +23 -0
- package/src/modules/imu.ts +44 -0
- package/src/modules/input.ts +71 -0
- package/src/modules/led.ts +61 -0
- package/src/modules/location.ts +39 -0
- package/src/modules/mic.ts +74 -0
- package/src/modules/miniapps.ts +90 -0
- package/src/modules/navigation.ts +670 -0
- package/src/modules/permissions.ts +84 -0
- package/src/modules/phone.ts +155 -0
- package/src/modules/pivots/engine.ts +863 -0
- package/src/modules/pivots/geometry.ts +409 -0
- package/src/modules/pivots/instructions.ts +343 -0
- package/src/modules/speaker.ts +335 -0
- package/src/modules/storage.ts +109 -0
- package/src/modules/stream.ts +163 -0
- package/src/modules/system.ts +76 -0
- package/src/modules/transcription.ts +145 -0
- package/src/modules/translation.ts +149 -0
- package/src/modules/ui.ts +498 -0
- package/src/protocol.ts +378 -0
- package/src/react/MentraProvider.tsx +50 -0
- package/src/react/MiniappHeader.tsx +122 -0
- package/src/react/index.ts +12 -0
- package/src/react/useCapabilities.ts +29 -0
- package/src/react/useCapsuleHeaderStyle.ts +54 -0
- package/src/react/useColorScheme.ts +26 -0
- package/src/react/useConnected.ts +47 -0
- package/src/react/useRpc.ts +106 -0
- package/src/react/useSafeArea.ts +40 -0
- package/src/session.ts +886 -0
- package/src/sub-path-types.test-d.ts +49 -0
- package/src/transport/auto.ts +143 -0
- package/src/transport/dispatch.ts +106 -0
- package/src/transport/local-socket.ts +93 -0
- package/src/transport/mock.ts +251 -0
- package/src/transport/postmessage.ts +95 -0
- package/src/transport/types.ts +26 -0
- package/src/ui/index.ts +122 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview CameraModule — glasses camera control and photo capture.
|
|
3
|
+
*/
|
|
4
|
+
import { MiniappRequestType } from "../protocol";
|
|
5
|
+
export class CameraModule {
|
|
6
|
+
constructor(session) {
|
|
7
|
+
this.session = session;
|
|
8
|
+
}
|
|
9
|
+
/** True iff `CAMERA` is declared in the miniapp's manifest. */
|
|
10
|
+
get hasPermission() {
|
|
11
|
+
return this.session._hasManifestPermission("CAMERA");
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Apply a session-owned camera FOV/ROI override on the glasses.
|
|
15
|
+
*
|
|
16
|
+
* Resolves after the ASG client reports that the setting was applied to camera
|
|
17
|
+
* hardware after the restart cooldown. The host restores the prior override or persistent base
|
|
18
|
+
* when this miniapp closes. Requires CAMERA permission declared in miniapp.json.
|
|
19
|
+
*/
|
|
20
|
+
async setFov(request) {
|
|
21
|
+
return this.session.sendRequest({
|
|
22
|
+
type: MiniappRequestType.CAMERA_FOV,
|
|
23
|
+
...request,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Take a photo via the glasses camera. Returns a URL to the captured image.
|
|
28
|
+
* Requires CAMERA permission declared in miniapp.json.
|
|
29
|
+
*
|
|
30
|
+
* The photo is uploaded to cloud storage; the returned URL is a short-TTL
|
|
31
|
+
* (~30 minute) signed download URL. If the glasses don't have a camera,
|
|
32
|
+
* the phone-side handler rejects with an error. Check
|
|
33
|
+
* `session.capabilities.hasCamera` before calling.
|
|
34
|
+
*/
|
|
35
|
+
async takePhoto(options = {}) {
|
|
36
|
+
return this.session.sendRequest({
|
|
37
|
+
type: MiniappRequestType.PHOTO,
|
|
38
|
+
size: options.size ?? "medium",
|
|
39
|
+
mode: options.mode ?? "photo",
|
|
40
|
+
compress: options.compress ?? "none",
|
|
41
|
+
sound: options.sound ?? true,
|
|
42
|
+
saveToGallery: options.saveToGallery ?? false,
|
|
43
|
+
exposureTimeNs: options.exposureTimeNs,
|
|
44
|
+
iso: options.iso,
|
|
45
|
+
aeExposureDivisor: options.aeExposureDivisor,
|
|
46
|
+
isoCap: options.isoCap,
|
|
47
|
+
noiseReduction: options.noiseReduction,
|
|
48
|
+
edgeEnhancement: options.edgeEnhancement,
|
|
49
|
+
mfnr: options.mfnr,
|
|
50
|
+
zsl: options.zsl,
|
|
51
|
+
ispDigitalGain: options.ispDigitalGain,
|
|
52
|
+
ispAnalogGain: options.ispAnalogGain,
|
|
53
|
+
}, options.timeoutMs != null ? { timeoutMs: options.timeoutMs } : undefined);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Pre-warm the glasses camera so the next takePhoto() is near-instant.
|
|
57
|
+
* The camera stays warm for ~durationMs (default 15s, maximum 60s); call warmUp() again to
|
|
58
|
+
* extend it. Warm with the same `size` you'll capture with — a mismatched size
|
|
59
|
+
* forces the camera to reconfigure and loses the speedup. Requires CAMERA
|
|
60
|
+
* permission in miniapp.json. Resolves once the camera reports ready. The host automatically
|
|
61
|
+
* releases this miniapp's request-owned lease when the miniapp closes.
|
|
62
|
+
*
|
|
63
|
+
* Warm-ups are serialized: only one runs at a time and none may start while a
|
|
64
|
+
* photo is being captured. If the camera is busy (a capture is in flight, or
|
|
65
|
+
* another warm-up is still opening) this rejects with `camera_busy` — retry
|
|
66
|
+
* shortly, or just call takePhoto() (it works regardless, only slower). The
|
|
67
|
+
* normal warmUp() → takePhoto() sequence never hits this.
|
|
68
|
+
*/
|
|
69
|
+
async warmUp(options = {}) {
|
|
70
|
+
await this.session.sendRequest({
|
|
71
|
+
type: MiniappRequestType.CAMERA_WARM_UP,
|
|
72
|
+
size: options.size ?? "medium",
|
|
73
|
+
mode: options.mode ?? "photo",
|
|
74
|
+
exposureTimeNs: options.exposureTimeNs,
|
|
75
|
+
durationMs: options.durationMs ?? 15000,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Start recording video on the glasses camera. Returns a `recordingId` to pass
|
|
80
|
+
* to {@link stopVideoRecording} after the glasses report that recording
|
|
81
|
+
* started. Requires CAMERA permission declared in miniapp.json. Check
|
|
82
|
+
* `session.capabilities.hasCamera` before calling.
|
|
83
|
+
*
|
|
84
|
+
* Resolution and frame rate are optional — omit them to use the device's saved
|
|
85
|
+
* button-video settings. Lowering `fps` (e.g. to 5) keeps the glasses cooler
|
|
86
|
+
* during long recordings.
|
|
87
|
+
*/
|
|
88
|
+
async startVideoRecording(options = {}) {
|
|
89
|
+
return this.session.sendRequest({
|
|
90
|
+
type: MiniappRequestType.VIDEO_RECORDING_START,
|
|
91
|
+
width: options.width,
|
|
92
|
+
height: options.height,
|
|
93
|
+
fps: options.fps,
|
|
94
|
+
sound: options.sound ?? true,
|
|
95
|
+
save: options.save ?? false,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Stop an in-progress video recording started with {@link startVideoRecording}.
|
|
100
|
+
*
|
|
101
|
+
* By default the recording stays on the glasses. Pass `uploadUrl` to have the
|
|
102
|
+
* glasses upload the finished clip to your own endpoint.
|
|
103
|
+
*
|
|
104
|
+
* @param recordingId The id returned from `startVideoRecording`.
|
|
105
|
+
* @param options Optional upload destination for the finished recording.
|
|
106
|
+
*/
|
|
107
|
+
async stopVideoRecording(recordingId, options = {}) {
|
|
108
|
+
await this.session.sendRequest({
|
|
109
|
+
type: MiniappRequestType.VIDEO_RECORDING_STOP,
|
|
110
|
+
recordingId,
|
|
111
|
+
uploadUrl: options.uploadUrl,
|
|
112
|
+
uploadAuthToken: options.uploadAuthToken,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=camera.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"camera.js","sourceRoot":"","sources":["../../src/modules/camera.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview CloudModule — local miniapp view of the phone-owned cloud client.
|
|
3
|
+
*
|
|
4
|
+
* Miniapps do not own or configure the cloud connection. The phone owns one
|
|
5
|
+
* cloud-client instance and pushes status snapshots here so miniapps can render
|
|
6
|
+
* honest UX such as online/offline captions indicators.
|
|
7
|
+
*/
|
|
8
|
+
import { MiniappSession } from "../session";
|
|
9
|
+
import type { UnsubscribeFn } from "./events";
|
|
10
|
+
export type CloudClientConnectionStatus = "connected" | "connecting" | "reconnecting" | "disconnected";
|
|
11
|
+
export type CloudClientAudioTransport = "udp" | "ws" | "offline" | "none";
|
|
12
|
+
export interface CloudClientStatus {
|
|
13
|
+
status: CloudClientConnectionStatus;
|
|
14
|
+
audioTransport: CloudClientAudioTransport;
|
|
15
|
+
}
|
|
16
|
+
export declare const CLOUD_STATUS_STREAM = "_cloud_status";
|
|
17
|
+
export declare class CloudModule {
|
|
18
|
+
private readonly session;
|
|
19
|
+
private readonly emitter;
|
|
20
|
+
private current;
|
|
21
|
+
constructor(session: MiniappSession);
|
|
22
|
+
/** Latest status snapshot pushed by the phone runtime. */
|
|
23
|
+
get status(): CloudClientStatus;
|
|
24
|
+
/** True when the phone's cloud-client runtime handshake is complete. */
|
|
25
|
+
get connected(): boolean;
|
|
26
|
+
/** Method alias for callers who prefer function-style state reads. */
|
|
27
|
+
isConnected(): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Subscribe to cloud-client status updates. The current value is delivered
|
|
30
|
+
* immediately so UI code can hydrate without waiting for the next transition.
|
|
31
|
+
*/
|
|
32
|
+
onStatusChanged(handler: (status: CloudClientStatus) => void): UnsubscribeFn;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=cloud.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloud.d.ts","sourceRoot":"","sources":["../../src/modules/cloud.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAC,cAAc,EAAC,MAAM,YAAY,CAAA;AACzC,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,UAAU,CAAA;AAE3C,MAAM,MAAM,2BAA2B,GAAG,WAAW,GAAG,YAAY,GAAG,cAAc,GAAG,cAAc,CAAA;AACtG,MAAM,MAAM,yBAAyB,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAAA;AAEzE,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,2BAA2B,CAAA;IACnC,cAAc,EAAE,yBAAyB,CAAA;CAC1C;AAMD,eAAO,MAAM,mBAAmB,kBAAkB,CAAA;AA4BlD,qBAAa,WAAW;IAIV,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyC;IACjE,OAAO,CAAC,OAAO,CAAyC;gBAE3B,OAAO,EAAE,cAAc;IAUpD,0DAA0D;IAC1D,IAAI,MAAM,IAAI,iBAAiB,CAE9B;IAED,wEAAwE;IACxE,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,sEAAsE;IACtE,WAAW,IAAI,OAAO;IAItB;;;OAGG;IACH,eAAe,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,IAAI,GAAG,aAAa;CAO7E"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview CloudModule — local miniapp view of the phone-owned cloud client.
|
|
3
|
+
*
|
|
4
|
+
* Miniapps do not own or configure the cloud connection. The phone owns one
|
|
5
|
+
* cloud-client instance and pushes status snapshots here so miniapps can render
|
|
6
|
+
* honest UX such as online/offline captions indicators.
|
|
7
|
+
*/
|
|
8
|
+
import { EventEmitter } from "eventemitter3";
|
|
9
|
+
export const CLOUD_STATUS_STREAM = "_cloud_status";
|
|
10
|
+
const DEFAULT_STATUS = {
|
|
11
|
+
status: "disconnected",
|
|
12
|
+
audioTransport: "none",
|
|
13
|
+
};
|
|
14
|
+
function normalizeCloudStatus(data) {
|
|
15
|
+
if (!data || typeof data !== "object")
|
|
16
|
+
return null;
|
|
17
|
+
const raw = data;
|
|
18
|
+
const status = raw.status;
|
|
19
|
+
const audioTransport = raw.audioTransport;
|
|
20
|
+
if (status !== "connected" && status !== "connecting" && status !== "reconnecting" && status !== "disconnected") {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
if (audioTransport !== "udp" &&
|
|
24
|
+
audioTransport !== "ws" &&
|
|
25
|
+
audioTransport !== "offline" &&
|
|
26
|
+
audioTransport !== "none") {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
return { status, audioTransport };
|
|
30
|
+
}
|
|
31
|
+
export class CloudModule {
|
|
32
|
+
constructor(session) {
|
|
33
|
+
this.session = session;
|
|
34
|
+
this.emitter = new EventEmitter();
|
|
35
|
+
this.current = { ...DEFAULT_STATUS };
|
|
36
|
+
this.session._subscribe(CLOUD_STATUS_STREAM, (data) => {
|
|
37
|
+
const next = normalizeCloudStatus(data);
|
|
38
|
+
if (!next)
|
|
39
|
+
return;
|
|
40
|
+
if (next.status === this.current.status && next.audioTransport === this.current.audioTransport)
|
|
41
|
+
return;
|
|
42
|
+
this.current = next;
|
|
43
|
+
this.emitter.emit("status", { ...this.current });
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/** Latest status snapshot pushed by the phone runtime. */
|
|
47
|
+
get status() {
|
|
48
|
+
return { ...this.current };
|
|
49
|
+
}
|
|
50
|
+
/** True when the phone's cloud-client runtime handshake is complete. */
|
|
51
|
+
get connected() {
|
|
52
|
+
return this.current.status === "connected";
|
|
53
|
+
}
|
|
54
|
+
/** Method alias for callers who prefer function-style state reads. */
|
|
55
|
+
isConnected() {
|
|
56
|
+
return this.connected;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Subscribe to cloud-client status updates. The current value is delivered
|
|
60
|
+
* immediately so UI code can hydrate without waiting for the next transition.
|
|
61
|
+
*/
|
|
62
|
+
onStatusChanged(handler) {
|
|
63
|
+
handler({ ...this.current });
|
|
64
|
+
this.emitter.on("status", handler);
|
|
65
|
+
return () => {
|
|
66
|
+
this.emitter.off("status", handler);
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=cloud.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloud.js","sourceRoot":"","sources":["../../src/modules/cloud.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAC,YAAY,EAAC,MAAM,eAAe,CAAA;AAiB1C,MAAM,CAAC,MAAM,mBAAmB,GAAG,eAAe,CAAA;AAElD,MAAM,cAAc,GAAsB;IACxC,MAAM,EAAE,cAAc;IACtB,cAAc,EAAE,MAAM;CACvB,CAAA;AAED,SAAS,oBAAoB,CAAC,IAAa;IACzC,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAA;IAClD,MAAM,GAAG,GAAG,IAA+B,CAAA;IAC3C,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAA;IACzB,MAAM,cAAc,GAAG,GAAG,CAAC,cAAc,CAAA;IAEzC,IAAI,MAAM,KAAK,WAAW,IAAI,MAAM,KAAK,YAAY,IAAI,MAAM,KAAK,cAAc,IAAI,MAAM,KAAK,cAAc,EAAE,CAAC;QAChH,OAAO,IAAI,CAAA;IACb,CAAC;IACD,IACE,cAAc,KAAK,KAAK;QACxB,cAAc,KAAK,IAAI;QACvB,cAAc,KAAK,SAAS;QAC5B,cAAc,KAAK,MAAM,EACzB,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,OAAO,EAAC,MAAM,EAAE,cAAc,EAAC,CAAA;AACjC,CAAC;AAED,MAAM,OAAO,WAAW;IAItB,YAA6B,OAAuB;QAAvB,YAAO,GAAP,OAAO,CAAgB;QAHnC,YAAO,GAAG,IAAI,YAAY,EAAsB,CAAA;QACzD,YAAO,GAAsB,EAAC,GAAG,cAAc,EAAC,CAAA;QAGtD,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,IAAI,EAAE,EAAE;YACpD,MAAM,IAAI,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAA;YACvC,IAAI,CAAC,IAAI;gBAAE,OAAM;YACjB,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,cAAc,KAAK,IAAI,CAAC,OAAO,CAAC,cAAc;gBAAE,OAAM;YACtG,IAAI,CAAC,OAAO,GAAG,IAAI,CAAA;YACnB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAC,GAAG,IAAI,CAAC,OAAO,EAAC,CAAC,CAAA;QAChD,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,0DAA0D;IAC1D,IAAI,MAAM;QACR,OAAO,EAAC,GAAG,IAAI,CAAC,OAAO,EAAC,CAAA;IAC1B,CAAC;IAED,wEAAwE;IACxE,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,WAAW,CAAA;IAC5C,CAAC;IAED,sEAAsE;IACtE,WAAW;QACT,OAAO,IAAI,CAAC,SAAS,CAAA;IACvB,CAAC;IAED;;;OAGG;IACH,eAAe,CAAC,OAA4C;QAC1D,OAAO,CAAC,EAAC,GAAG,IAAI,CAAC,OAAO,EAAC,CAAC,CAAA;QAC1B,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;QAClC,OAAO,GAAG,EAAE;YACV,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;QACrC,CAAC,CAAA;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview DashboardAPI — noop surface in v1.
|
|
3
|
+
*
|
|
4
|
+
* The cloud DashboardManager owns widget rendering in OS-ranked
|
|
5
|
+
* rotation. Keeping the API shape so miniapps compile, but calls are
|
|
6
|
+
* noop + console.warn.
|
|
7
|
+
*/
|
|
8
|
+
import { MiniappSession } from "../session";
|
|
9
|
+
export type DashboardMode = "main" | "expanded" | "always_on";
|
|
10
|
+
export declare class DashboardAPI {
|
|
11
|
+
private readonly session;
|
|
12
|
+
private warned;
|
|
13
|
+
constructor(session: MiniappSession);
|
|
14
|
+
setContent(mode: DashboardMode, content: string): void;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=dashboard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../../src/modules/dashboard.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAC,cAAc,EAAC,MAAM,YAAY,CAAA;AAEzC,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,UAAU,GAAG,WAAW,CAAA;AAE7D,qBAAa,YAAY;IAGX,OAAO,CAAC,QAAQ,CAAC,OAAO;IAFpC,OAAO,CAAC,MAAM,CAAQ;gBAEO,OAAO,EAAE,cAAc;IAEpD,UAAU,CAAC,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;CAYvD"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview DashboardAPI — noop surface in v1.
|
|
3
|
+
*
|
|
4
|
+
* The cloud DashboardManager owns widget rendering in OS-ranked
|
|
5
|
+
* rotation. Keeping the API shape so miniapps compile, but calls are
|
|
6
|
+
* noop + console.warn.
|
|
7
|
+
*/
|
|
8
|
+
import { MiniappRequestType } from "../protocol";
|
|
9
|
+
export class DashboardAPI {
|
|
10
|
+
constructor(session) {
|
|
11
|
+
this.session = session;
|
|
12
|
+
this.warned = false;
|
|
13
|
+
}
|
|
14
|
+
setContent(mode, content) {
|
|
15
|
+
if (!this.warned) {
|
|
16
|
+
console.warn("[@mentra/miniapp] dashboard.setContent() is deferred in v1.");
|
|
17
|
+
this.warned = true;
|
|
18
|
+
}
|
|
19
|
+
// Still forward so the phone can log/ignore consistently.
|
|
20
|
+
this.session.sendOneShot({
|
|
21
|
+
type: MiniappRequestType.DASHBOARD_CONTENT_UPDATE,
|
|
22
|
+
mode,
|
|
23
|
+
content,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=dashboard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../../src/modules/dashboard.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAC,kBAAkB,EAAC,MAAM,aAAa,CAAA;AAK9C,MAAM,OAAO,YAAY;IAGvB,YAA6B,OAAuB;QAAvB,YAAO,GAAP,OAAO,CAAgB;QAF5C,WAAM,GAAG,KAAK,CAAA;IAEiC,CAAC;IAExD,UAAU,CAAC,IAAmB,EAAE,OAAe;QAC7C,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,OAAO,CAAC,IAAI,CAAC,6DAA6D,CAAC,CAAA;YAC3E,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;QACpB,CAAC;QACD,0DAA0D;QAC1D,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC;YACvB,IAAI,EAAE,kBAAkB,CAAC,wBAAwB;YACjD,IAAI;YACJ,OAAO;SACR,CAAC,CAAA;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview DisplayManager — the glasses display, via `render()`.
|
|
3
|
+
*
|
|
4
|
+
* render(elements) is replace-the-frame scene rendering: each call describes
|
|
5
|
+
* everything that should be on screen, the host diffs it against the previous
|
|
6
|
+
* frame per device, and `render([])` clears. The legacy one-shot `show*`
|
|
7
|
+
* layout methods were removed once nothing first-party or known-external
|
|
8
|
+
* called them; hosts still accept the historical `miniapp_display` wire shape
|
|
9
|
+
* from bundles packed with older SDKs.
|
|
10
|
+
*/
|
|
11
|
+
import { MiniappSession } from "../session";
|
|
12
|
+
export type ViewType = "main" | "dashboard";
|
|
13
|
+
export type DisplayBreakMode = "character" | "character-no-hyphen" | "word" | "strict-word";
|
|
14
|
+
/** Pixel-space bounding box on the device's drawable canvas (see `capabilities.display`). */
|
|
15
|
+
export interface RenderBox {
|
|
16
|
+
x: number;
|
|
17
|
+
y: number;
|
|
18
|
+
w: number;
|
|
19
|
+
h: number;
|
|
20
|
+
}
|
|
21
|
+
export interface RenderTextStyle {
|
|
22
|
+
/** Border width in px (0/absent = none). */
|
|
23
|
+
border?: number;
|
|
24
|
+
/** Border corner radius in px. */
|
|
25
|
+
radius?: number;
|
|
26
|
+
/** What happens to text that doesn't fit the box after wrapping. Default "clip". */
|
|
27
|
+
overflow?: "clip" | "ellipsis";
|
|
28
|
+
/** Line-break policy for wrapping (host wraps; the box carries pre-wrapped text). */
|
|
29
|
+
breakMode?: DisplayBreakMode;
|
|
30
|
+
}
|
|
31
|
+
export interface RenderRectStyle {
|
|
32
|
+
border?: number;
|
|
33
|
+
radius?: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* One element of a rendered scene. `id` is optional but recommended for
|
|
37
|
+
* anything that updates over time: elements with a stable id update in place on
|
|
38
|
+
* the glasses (no flicker); the host matches unnamed elements by geometry.
|
|
39
|
+
*/
|
|
40
|
+
export type RenderElement = {
|
|
41
|
+
type: "text";
|
|
42
|
+
id?: string;
|
|
43
|
+
box: RenderBox;
|
|
44
|
+
text: string;
|
|
45
|
+
style?: RenderTextStyle;
|
|
46
|
+
} | {
|
|
47
|
+
type: "image";
|
|
48
|
+
id?: string;
|
|
49
|
+
box: RenderBox;
|
|
50
|
+
data: string;
|
|
51
|
+
} | {
|
|
52
|
+
type: "rect";
|
|
53
|
+
id?: string;
|
|
54
|
+
box: RenderBox;
|
|
55
|
+
style?: RenderRectStyle;
|
|
56
|
+
};
|
|
57
|
+
export interface RenderOptions {
|
|
58
|
+
view?: ViewType;
|
|
59
|
+
/** Auto-clear after this many ms (same semantics as legacy display options). */
|
|
60
|
+
durationMs?: number;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Outcome of a render request, resolved when the host's display arbitration
|
|
64
|
+
* settles it. "displayed" = accepted and sent to the device — NOT a
|
|
65
|
+
* render confirmation. "blocked" = another app owns the display (or the
|
|
66
|
+
* request failed); `reason` says why.
|
|
67
|
+
*/
|
|
68
|
+
export interface RenderResult {
|
|
69
|
+
status: "displayed" | "blocked";
|
|
70
|
+
/** True when the host adjusted the scene (clamped boxes, dropped elements, degraded for the device). */
|
|
71
|
+
degraded?: boolean;
|
|
72
|
+
/** Ids of elements the host dropped (budget/bounds/device limits) — dropped is never silent. */
|
|
73
|
+
dropped?: string[];
|
|
74
|
+
reason?: string;
|
|
75
|
+
}
|
|
76
|
+
export declare class DisplayManager {
|
|
77
|
+
private readonly session;
|
|
78
|
+
constructor(session: MiniappSession);
|
|
79
|
+
/**
|
|
80
|
+
* Render a whole scene of positioned elements — replace-the-frame.
|
|
81
|
+
*
|
|
82
|
+
* Each call describes everything that should be on screen; the host diffs it
|
|
83
|
+
* against the previous frame per device (elements with a stable `id` update
|
|
84
|
+
* in place; elements you stop sending are removed). There is no lifecycle to
|
|
85
|
+
* manage and no remove calls — `render([])` clears.
|
|
86
|
+
*
|
|
87
|
+
* Coordinates are raw pixels on the device's drawable canvas — read
|
|
88
|
+
* `session.capabilities.display` (populated on the "ready" event) for the
|
|
89
|
+
* real width/height and element budgets. Out-of-bounds boxes are clamped and
|
|
90
|
+
* over-budget elements are dropped tail-first; both are reported via the
|
|
91
|
+
* result, never silently.
|
|
92
|
+
*
|
|
93
|
+
* Awaiting is OPT-IN — a plain fire-and-forget call is fine. The returned
|
|
94
|
+
* promise never rejects.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* const result = await session.display.render([
|
|
98
|
+
* {type: "text", id: "stats", box: {x: 12, y: 9, w: 200, h: 28}, text: "863 m 11 min"},
|
|
99
|
+
* {type: "image", id: "map", box: {x: 335, y: 14, w: 150, h: 150}, data: mapPng},
|
|
100
|
+
* {type: "rect", box: {x: 0, y: 0, w: 500, h: 220}, style: {radius: 4}},
|
|
101
|
+
* ])
|
|
102
|
+
* if (result.degraded) console.warn("dropped:", result.dropped)
|
|
103
|
+
*/
|
|
104
|
+
render(elements: RenderElement[], options?: RenderOptions): Promise<RenderResult>;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=display.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"display.d.ts","sourceRoot":"","sources":["../../src/modules/display.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAC,cAAc,EAAC,MAAM,YAAY,CAAA;AAEzC,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAA;AAE3C,MAAM,MAAM,gBAAgB,GAAG,WAAW,GAAG,qBAAqB,GAAG,MAAM,GAAG,aAAa,CAAA;AAM3F,6FAA6F;AAC7F,MAAM,WAAW,SAAS;IACxB,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;CACV;AAED,MAAM,WAAW,eAAe;IAC9B,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,kCAAkC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,oFAAoF;IACpF,QAAQ,CAAC,EAAE,MAAM,GAAG,UAAU,CAAA;IAC9B,qFAAqF;IACrF,SAAS,CAAC,EAAE,gBAAgB,CAAA;CAC7B;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;;GAIG;AACH,MAAM,MAAM,aAAa,GACrB;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,eAAe,CAAA;CAAC,GAClF;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC,GAC1D;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,eAAe,CAAA;CAAC,CAAA;AAExE,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,QAAQ,CAAA;IACf,gFAAgF;IAChF,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,WAAW,GAAG,SAAS,CAAA;IAC/B,wGAAwG;IACxG,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,gGAAgG;IAChG,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,qBAAa,cAAc;IACb,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,cAAc;IAEpD;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,MAAM,CAAC,QAAQ,EAAE,aAAa,EAAE,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,YAAY,CAAC;CAgBtF"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview DisplayManager — the glasses display, via `render()`.
|
|
3
|
+
*
|
|
4
|
+
* render(elements) is replace-the-frame scene rendering: each call describes
|
|
5
|
+
* everything that should be on screen, the host diffs it against the previous
|
|
6
|
+
* frame per device, and `render([])` clears. The legacy one-shot `show*`
|
|
7
|
+
* layout methods were removed once nothing first-party or known-external
|
|
8
|
+
* called them; hosts still accept the historical `miniapp_display` wire shape
|
|
9
|
+
* from bundles packed with older SDKs.
|
|
10
|
+
*/
|
|
11
|
+
import { MiniappRequestType } from "../protocol";
|
|
12
|
+
export class DisplayManager {
|
|
13
|
+
constructor(session) {
|
|
14
|
+
this.session = session;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Render a whole scene of positioned elements — replace-the-frame.
|
|
18
|
+
*
|
|
19
|
+
* Each call describes everything that should be on screen; the host diffs it
|
|
20
|
+
* against the previous frame per device (elements with a stable `id` update
|
|
21
|
+
* in place; elements you stop sending are removed). There is no lifecycle to
|
|
22
|
+
* manage and no remove calls — `render([])` clears.
|
|
23
|
+
*
|
|
24
|
+
* Coordinates are raw pixels on the device's drawable canvas — read
|
|
25
|
+
* `session.capabilities.display` (populated on the "ready" event) for the
|
|
26
|
+
* real width/height and element budgets. Out-of-bounds boxes are clamped and
|
|
27
|
+
* over-budget elements are dropped tail-first; both are reported via the
|
|
28
|
+
* result, never silently.
|
|
29
|
+
*
|
|
30
|
+
* Awaiting is OPT-IN — a plain fire-and-forget call is fine. The returned
|
|
31
|
+
* promise never rejects.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* const result = await session.display.render([
|
|
35
|
+
* {type: "text", id: "stats", box: {x: 12, y: 9, w: 200, h: 28}, text: "863 m 11 min"},
|
|
36
|
+
* {type: "image", id: "map", box: {x: 335, y: 14, w: 150, h: 150}, data: mapPng},
|
|
37
|
+
* {type: "rect", box: {x: 0, y: 0, w: 500, h: 220}, style: {radius: 4}},
|
|
38
|
+
* ])
|
|
39
|
+
* if (result.degraded) console.warn("dropped:", result.dropped)
|
|
40
|
+
*/
|
|
41
|
+
render(elements, options = {}) {
|
|
42
|
+
return this.session
|
|
43
|
+
.sendRequest({
|
|
44
|
+
type: MiniappRequestType.RENDER,
|
|
45
|
+
view: options.view ?? "main",
|
|
46
|
+
elements,
|
|
47
|
+
durationMs: options.durationMs,
|
|
48
|
+
})
|
|
49
|
+
.catch((err) => ({
|
|
50
|
+
status: "blocked",
|
|
51
|
+
reason: typeof err === "object" && err !== null && "message" in err
|
|
52
|
+
? String(err.message)
|
|
53
|
+
: String(err),
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=display.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"display.js","sourceRoot":"","sources":["../../src/modules/display.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAC,kBAAkB,EAAC,MAAM,aAAa,CAAA;AAkE9C,MAAM,OAAO,cAAc;IACzB,YAA6B,OAAuB;QAAvB,YAAO,GAAP,OAAO,CAAgB;IAAG,CAAC;IAExD;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,MAAM,CAAC,QAAyB,EAAE,UAAyB,EAAE;QAC3D,OAAO,IAAI,CAAC,OAAO;aAChB,WAAW,CAAe;YACzB,IAAI,EAAE,kBAAkB,CAAC,MAAM;YAC/B,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,MAAM;YAC5B,QAAQ;YACR,UAAU,EAAE,OAAO,CAAC,UAAU;SAC/B,CAAC;aACD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACf,MAAM,EAAE,SAAkB;YAC1B,MAAM,EACJ,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,SAAS,IAAI,GAAG;gBACzD,CAAC,CAAC,MAAM,CAAE,GAA0B,CAAC,OAAO,CAAC;gBAC7C,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SAClB,CAAC,CAAC,CAAA;IACP,CAAC;CACF"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview EventManager — internal subscription registry + escape hatch.
|
|
3
|
+
*
|
|
4
|
+
* Most miniapp authors should NOT touch this directly. Use the typed methods
|
|
5
|
+
* on domain modules instead:
|
|
6
|
+
* - session.transcription.on(...)
|
|
7
|
+
* - session.mic.onAudioChunk(...) / onVoiceActivity(...)
|
|
8
|
+
* - session.input.onButtonPress(...)
|
|
9
|
+
* - session.imu.onHeadPosition(...)
|
|
10
|
+
* - session.location.onUpdate(...)
|
|
11
|
+
* - session.glasses.onBattery(...) / onConnection(...)
|
|
12
|
+
* - session.phone.notifications.on(...) / session.phone.onBattery(...)
|
|
13
|
+
*
|
|
14
|
+
* This module's only public method is `subscribe(rawStreamType, handler)` —
|
|
15
|
+
* a forward-compat escape hatch for new event types not yet wrapped on a
|
|
16
|
+
* domain module. Officially undocumented; the typed methods on domain
|
|
17
|
+
* modules are the canonical surface.
|
|
18
|
+
*
|
|
19
|
+
* Internally, EventManager owns:
|
|
20
|
+
* 1. The ref-count map. Outbound SUBSCRIBE is only sent when a stream's
|
|
21
|
+
* ref count transitions 0↔1, so multiple components listening for the
|
|
22
|
+
* same stream issue one wire-level subscribe.
|
|
23
|
+
* 2. Inbound event fan-out via `_forwardEvent(streamType, data)`, called
|
|
24
|
+
* by MiniappSession.handleIncoming when an EVENT envelope arrives.
|
|
25
|
+
*
|
|
26
|
+
* Domain modules call back into the session via session._subscribe(...) which
|
|
27
|
+
* in turn delegates to this class — the session is the integration point;
|
|
28
|
+
* domain modules don't see this class directly.
|
|
29
|
+
*/
|
|
30
|
+
import { MiniappSession } from "../session";
|
|
31
|
+
export type UnsubscribeFn = () => void;
|
|
32
|
+
/** @internal Host-selected delivery target for a transcription event. */
|
|
33
|
+
export type TranscriptionEventRoute = "default" | "forceLocal" | "all";
|
|
34
|
+
export interface TranscriptionData {
|
|
35
|
+
text: string;
|
|
36
|
+
isFinal: boolean;
|
|
37
|
+
language?: string;
|
|
38
|
+
}
|
|
39
|
+
export interface TranslationData {
|
|
40
|
+
text: string;
|
|
41
|
+
isFinal: boolean;
|
|
42
|
+
sourceLanguage: string;
|
|
43
|
+
targetLanguage: string;
|
|
44
|
+
/** Source-language text of the same utterance, when the provider supplies it. */
|
|
45
|
+
originalText?: string;
|
|
46
|
+
/** Stable id correlating interim + final results of one utterance. */
|
|
47
|
+
utteranceId?: string;
|
|
48
|
+
/** Speaker id when the provider reports diarization. */
|
|
49
|
+
speakerId?: string;
|
|
50
|
+
}
|
|
51
|
+
export interface ButtonPressData {
|
|
52
|
+
buttonId: string;
|
|
53
|
+
pressType: "short" | "long";
|
|
54
|
+
}
|
|
55
|
+
export interface HeadPositionData {
|
|
56
|
+
position: "up" | "down";
|
|
57
|
+
}
|
|
58
|
+
export interface AccelData {
|
|
59
|
+
/** Accelerometer axes in g (gravity-normalized). */
|
|
60
|
+
x: number;
|
|
61
|
+
y: number;
|
|
62
|
+
z: number;
|
|
63
|
+
/** Unix ms timestamp of the reading. */
|
|
64
|
+
timestamp: number;
|
|
65
|
+
}
|
|
66
|
+
export interface LocationData {
|
|
67
|
+
lat: number;
|
|
68
|
+
lng: number;
|
|
69
|
+
/** Accuracy in meters, if the platform reported it. */
|
|
70
|
+
accuracy?: number;
|
|
71
|
+
/** Unix ms timestamp of the fix. */
|
|
72
|
+
timestamp?: number;
|
|
73
|
+
/** Set when this event is a response to a single-location request. */
|
|
74
|
+
correlationId?: string;
|
|
75
|
+
}
|
|
76
|
+
export interface HeadingData {
|
|
77
|
+
/** Compass heading in degrees, 0 = north, 90 = east. */
|
|
78
|
+
degrees: number;
|
|
79
|
+
}
|
|
80
|
+
export interface BatteryData {
|
|
81
|
+
level: number;
|
|
82
|
+
charging: boolean;
|
|
83
|
+
}
|
|
84
|
+
export interface ConnectionData {
|
|
85
|
+
connected: boolean;
|
|
86
|
+
modelName?: string;
|
|
87
|
+
}
|
|
88
|
+
/** Glasses Wi-Fi state. `connected` is false on glasses without Wi-Fi or when offline. */
|
|
89
|
+
export interface WifiData {
|
|
90
|
+
connected: boolean;
|
|
91
|
+
ssid?: string;
|
|
92
|
+
localIp?: string;
|
|
93
|
+
}
|
|
94
|
+
export interface PhoneNotificationData {
|
|
95
|
+
/** Stable id from the phone's notification listener. */
|
|
96
|
+
notificationId: string;
|
|
97
|
+
/** Human app name (e.g. "Messages"). */
|
|
98
|
+
app: string;
|
|
99
|
+
title: string;
|
|
100
|
+
content: string;
|
|
101
|
+
/** Android priority string; empty on iOS. */
|
|
102
|
+
priority: string;
|
|
103
|
+
timestamp: number;
|
|
104
|
+
/** Reverse-DNS package/bundle id of the originating app. */
|
|
105
|
+
packageName: string;
|
|
106
|
+
}
|
|
107
|
+
export interface NotificationDismissedData {
|
|
108
|
+
/** Same id as the matching post event from `notifications.on(...)`. */
|
|
109
|
+
notificationId: string;
|
|
110
|
+
/** Android NotificationKey. More stable than notificationId across reposts. */
|
|
111
|
+
notificationKey?: string;
|
|
112
|
+
/** Reverse-DNS package/bundle id of the originating app. */
|
|
113
|
+
packageName?: string;
|
|
114
|
+
/** Unix ms timestamp of the dismissal. */
|
|
115
|
+
timestamp: number;
|
|
116
|
+
}
|
|
117
|
+
export interface VadData {
|
|
118
|
+
/** True while the user is speaking (voice detected), false when silent. */
|
|
119
|
+
status: boolean;
|
|
120
|
+
}
|
|
121
|
+
export interface TouchData {
|
|
122
|
+
/** The gesture: single_tap, double_tap, triple_tap, long_press, swipe_up, or swipe_down. */
|
|
123
|
+
kind: "single_tap" | "double_tap" | "triple_tap" | "long_press" | "swipe_up" | "swipe_down" | string;
|
|
124
|
+
}
|
|
125
|
+
export interface AudioChunkData {
|
|
126
|
+
/** PCM or LC3, base64-encoded. Format depends on phone's mic mode. */
|
|
127
|
+
data: string;
|
|
128
|
+
sampleRate?: number;
|
|
129
|
+
format?: string;
|
|
130
|
+
}
|
|
131
|
+
export declare class EventManager {
|
|
132
|
+
private readonly session;
|
|
133
|
+
private readonly emitter;
|
|
134
|
+
/** Stream -> ref count. Outbound SUBSCRIBE tracks active streams and routing changes. */
|
|
135
|
+
private readonly refCounts;
|
|
136
|
+
/** Transcription stream -> refs that require on-device-only processing. */
|
|
137
|
+
private readonly forceLocalRefCounts;
|
|
138
|
+
constructor(session: MiniappSession);
|
|
139
|
+
/**
|
|
140
|
+
* Generic subscribe. `stream` is the raw wire value, including any language
|
|
141
|
+
* suffix like `"transcription:en-US"`. Forward-compat escape hatch for new
|
|
142
|
+
* event types not yet wrapped on a domain module. Most authors should use
|
|
143
|
+
* typed methods on domain modules instead.
|
|
144
|
+
*
|
|
145
|
+
* Stream names beginning with `_` (e.g. `_ui` for the session.ui bus) are
|
|
146
|
+
* INTERNAL — they ride the local _forwardEvent fan-out and never appear in
|
|
147
|
+
* the outbound SUBSCRIBE list. Native already knows to deliver UI envelopes
|
|
148
|
+
* via a separate envelope `type`; the EventManager only routes them
|
|
149
|
+
* locally.
|
|
150
|
+
*/
|
|
151
|
+
subscribe(stream: string, handler: (data: unknown) => void, options?: {
|
|
152
|
+
forceLocal?: boolean;
|
|
153
|
+
}): UnsubscribeFn;
|
|
154
|
+
/** Unsubscribe every handler on every stream this EventManager owns. */
|
|
155
|
+
unsubscribeAll(): void;
|
|
156
|
+
/** @internal */
|
|
157
|
+
_forwardEvent(stream: string, data: unknown, transcriptionRoute?: TranscriptionEventRoute): void;
|
|
158
|
+
private sendSubscriptionUpdate;
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/modules/events.ts"],"names":[],"mappings":"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"}
|