@swiftbrowser/native 0.17.6 → 0.17.7

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 CHANGED
@@ -152,6 +152,28 @@ project `native init` writes does); `onOpenURL` here delivers it to the
152
152
  app's listeners. A URL that launched the app waits for the bundle and then
153
153
  for the first listener, so nothing is lost on a cold start.
154
154
 
155
+ ## Now playing
156
+
157
+ ```ts
158
+ navigator.mediaSession.metadata = new MediaMetadata({ title, artist, album, artwork: [{ src }] });
159
+ navigator.mediaSession.playbackState = 'playing';
160
+ navigator.mediaSession.setPositionState({ duration, position, playbackRate: 1 });
161
+ navigator.mediaSession.setActionHandler('nexttrack', () => player.advanceToNextItem());
162
+ ```
163
+
164
+ The browser's Media Session API, as an audio app writes it for the page,
165
+ works in the native app too: the runtime's `navigator.mediaSession` and
166
+ `MediaMetadata` hand what is set to the host, which puts it on the lock
167
+ screen and the system's player controls through MediaPlayer, and the
168
+ buttons there (and the media keys) run the handlers `setActionHandler`
169
+ registered: `play`, `pause`, `stop`, `nexttrack`, `previoustrack`,
170
+ `seekto` (with `seekTime`) and `seekforward` / `seekbackward` (with
171
+ `seekOffset`, 15 seconds when the system names none). Setting
172
+ `playbackState` to `playing` activates a playback audio session, which the
173
+ lock screen needs; for the audio to go on with the screen locked, the app's
174
+ Xcode target also needs the `audio` background mode (Signing &
175
+ Capabilities → Background Modes → Audio, AirPlay, and Picture in Picture).
176
+
155
177
  ## The dev loop and Fast Refresh
156
178
 
157
179
  `swiftbrowser-native dev` serves the bundle in two halves and a manifest:
package/dist/bridge.d.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  * (Native/Sources/SwiftBrowserNative/Host/HostBridge.swift). Every call is
4
4
  * synchronous; the ones that answer later do so by calling a global this
5
5
  * package defines (`__sbTimerFired`, `__sbFetchResult`, `__sbImageProbed`,
6
- * `__sbWorkerMessage`, `__sbOpenURL`).
6
+ * `__sbWorkerMessage`, `__sbOpenURL`, `__sbMediaSessionCommand`).
7
7
  */
8
8
  export interface NativeBridge {
9
9
  /** Applies a render pass's ops (a JSON array). Returns an error message, or nothing. */
@@ -35,6 +35,14 @@ export interface NativeBridge {
35
35
  locale(): string;
36
36
  /** The process's launch arguments (`-screen list` from an Xcode scheme or `simctl launch`). */
37
37
  launchArguments?(): string[];
38
+ /**
39
+ * `navigator.mediaSession` (mediaSession.ts): the whole session as JSON
40
+ * (`metadata`, `playbackState`, `position`, `commands`, as the web
41
+ * renderer's `mediaSession` request carries them), for the lock screen
42
+ * and the media keys; a command the viewer gives arrives at
43
+ * `__sbMediaSessionCommand(json)`. Hosts before 0.19 lack it.
44
+ */
45
+ mediaSession?(update: string): void;
38
46
  /**
39
47
  * Starts worker `id` from `<name>.worker.js` in `engine` (`'context'`
40
48
  * when absent; hosts before 0.16 take no engine); returns an error
@@ -1 +1 @@
1
- {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAgEA,kEAAkE;AAClE,MAAM,UAAU,eAAe;IAC7B,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,OAAO,MAAM,EAAE,eAAe,EAAE,EAAE,IAAI,EAAE,CAAC;AAC3C,CAAC;AA0BD,yFAAyF;AACzF,MAAM,UAAU,YAAY,CAAC,IAAuB,UAAU;IAC5D,OAAQ,CAA8C,CAAC,UAAU,CAAC;AACpE,CAAC"}
1
+ {"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAwEA,kEAAkE;AAClE,MAAM,UAAU,eAAe;IAC7B,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,OAAO,MAAM,EAAE,eAAe,EAAE,EAAE,IAAI,EAAE,CAAC;AAC3C,CAAC;AA0BD,yFAAyF;AACzF,MAAM,UAAU,YAAY,CAAC,IAAuB,UAAU;IAC5D,OAAQ,CAA8C,CAAC,UAAU,CAAC;AACpE,CAAC"}
package/dist/index.d.ts CHANGED
@@ -19,4 +19,5 @@ export { SimpleURL, SimpleURLSearchParams } from './url';
19
19
  export { SimpleTextEncoder, SimpleTextDecoder, base64Encode, base64Decode, utf8Encode, utf8Decode } from './encoding';
20
20
  export { createWorker, NativeWorker, encodeMessage, decodeMessage, workerName, type NativeWorkerOptions, type WorkerLike, type WorkerMessageEvent, type WorkerErrorEvent } from './worker';
21
21
  export { onOpenURL } from './openURL';
22
+ export { createMediaSession, NativeMediaMetadata, type NativeMediaSession, type MediaMetadataInit, type MediaActionDetails, type MediaActionHandler, type MediaPositionState } from './mediaSession';
22
23
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,GAAG,EAAE,KAAK,UAAU,EAAE,KAAK,OAAO,EAAE,MAAM,OAAO,CAAC;AAC3D,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,UAAU,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,KAAK,YAAY,EAAE,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AAChJ,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC9H,OAAO,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,OAAO,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACtH,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,UAAU,EAAE,KAAK,mBAAmB,EAAE,KAAK,UAAU,EAAE,KAAK,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC3L,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,GAAG,EAAE,KAAK,UAAU,EAAE,KAAK,OAAO,EAAE,MAAM,OAAO,CAAC;AAC3D,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,UAAU,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,KAAK,YAAY,EAAE,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AAChJ,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC9H,OAAO,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,OAAO,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACtH,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,UAAU,EAAE,KAAK,mBAAmB,EAAE,KAAK,UAAU,EAAE,KAAK,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC3L,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,KAAK,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/index.js CHANGED
@@ -19,4 +19,5 @@ export { SimpleURL, SimpleURLSearchParams } from './url';
19
19
  export { SimpleTextEncoder, SimpleTextDecoder, base64Encode, base64Decode, utf8Encode, utf8Decode } from './encoding';
20
20
  export { createWorker, NativeWorker, encodeMessage, decodeMessage, workerName } from './worker';
21
21
  export { onOpenURL } from './openURL';
22
+ export { createMediaSession, NativeMediaMetadata } from './mediaSession';
22
23
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,GAAG,EAAiC,MAAM,OAAO,CAAC;AAC3D,OAAO,EAAE,MAAM,EAAoB,MAAM,UAAU,CAAC;AACpD,OAAO,EAAE,cAAc,EAAuB,MAAM,WAAW,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAyF,MAAM,UAAU,CAAC;AAChJ,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC9H,OAAO,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,OAAO,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACtH,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,UAAU,EAA6F,MAAM,UAAU,CAAC;AAC3L,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,GAAG,EAAiC,MAAM,OAAO,CAAC;AAC3D,OAAO,EAAE,MAAM,EAAoB,MAAM,UAAU,CAAC;AACpD,OAAO,EAAE,cAAc,EAAuB,MAAM,WAAW,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAyF,MAAM,UAAU,CAAC;AAChJ,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC9H,OAAO,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,OAAO,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACtH,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,UAAU,EAA6F,MAAM,UAAU,CAAC;AAC3L,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAA8H,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * `navigator.mediaSession` and `MediaMetadata` for the native app: what an
3
+ * audio app tells the browser about what plays (the lock screen, the media
4
+ * keys) reaches the host's `mediaSession(update)` instead, which sets
5
+ * `MPNowPlayingInfoCenter` and `MPRemoteCommandCenter` (HostBridge.swift,
6
+ * NowPlayingBridge.swift); the commands the viewer gives come back to
7
+ * `__sbMediaSessionCommand(json)` and run the handlers `setActionHandler`
8
+ * registered, with the details the browser would give (`seekTime`,
9
+ * `seekOffset`). The update is the one the web renderer's `mediaSession`
10
+ * request carries (docs/ops-protocol.md, "Now playing"), so an app writes
11
+ * the same code for the page and the native app. In the page (the round
12
+ * trip) the page's own `navigator.mediaSession` is there already and
13
+ * nothing is installed over it.
14
+ */
15
+ import type { NativeBridge } from './bridge';
16
+ type Action = 'play' | 'pause' | 'stop' | 'nexttrack' | 'previoustrack' | 'seekto' | 'seekforward' | 'seekbackward' | 'skipad' | 'togglemicrophone' | 'togglecamera' | 'hangup';
17
+ export interface MediaImage {
18
+ src: string;
19
+ sizes?: string;
20
+ type?: string;
21
+ }
22
+ export interface MediaMetadataInit {
23
+ title?: string;
24
+ artist?: string;
25
+ album?: string;
26
+ artwork?: MediaImage[];
27
+ }
28
+ /** The browser's `MediaMetadata`. */
29
+ export declare class NativeMediaMetadata {
30
+ title: string;
31
+ artist: string;
32
+ album: string;
33
+ artwork: MediaImage[];
34
+ constructor(init?: MediaMetadataInit);
35
+ }
36
+ export interface MediaPositionState {
37
+ duration?: number;
38
+ playbackRate?: number;
39
+ position?: number;
40
+ }
41
+ export interface MediaActionDetails {
42
+ action: Action;
43
+ seekTime?: number;
44
+ seekOffset?: number;
45
+ }
46
+ export type MediaActionHandler = (details: MediaActionDetails) => void;
47
+ /** The browser's `navigator.mediaSession`, as far as audio apps use it. */
48
+ export interface NativeMediaSession {
49
+ metadata: NativeMediaMetadata | null;
50
+ playbackState: 'none' | 'playing' | 'paused';
51
+ setPositionState(state?: MediaPositionState): void;
52
+ setActionHandler(action: Action, handler: MediaActionHandler | null): void;
53
+ }
54
+ export declare function createMediaSession(native: Pick<NativeBridge, 'mediaSession'>): {
55
+ session: NativeMediaSession;
56
+ receive: (json: string) => void;
57
+ };
58
+ export {};
59
+ //# sourceMappingURL=mediaSession.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mediaSession.d.ts","sourceRoot":"","sources":["../src/mediaSession.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C,KAAK,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,WAAW,GAAG,eAAe,GAAG,QAAQ,GAAG,aAAa,GAAG,cAAc,GAAG,QAAQ,GAAG,kBAAkB,GAAG,cAAc,GAAG,QAAQ,CAAC;AAchL,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC;CACxB;AAED,qCAAqC;AACrC,qBAAa,mBAAmB;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,UAAU,EAAE,CAAC;gBAEV,IAAI,GAAE,iBAAsB;CAMzC;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC;AAEvE,2EAA2E;AAC3E,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACrC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC7C,gBAAgB,CAAC,KAAK,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACnD,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,IAAI,GAAG,IAAI,CAAC;CAC5E;AASD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,cAAc,CAAC,GAAG;IAAE,OAAO,EAAE,kBAAkB,CAAC;IAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,CA0E/I"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * `navigator.mediaSession` and `MediaMetadata` for the native app: what an
3
+ * audio app tells the browser about what plays (the lock screen, the media
4
+ * keys) reaches the host's `mediaSession(update)` instead, which sets
5
+ * `MPNowPlayingInfoCenter` and `MPRemoteCommandCenter` (HostBridge.swift,
6
+ * NowPlayingBridge.swift); the commands the viewer gives come back to
7
+ * `__sbMediaSessionCommand(json)` and run the handlers `setActionHandler`
8
+ * registered, with the details the browser would give (`seekTime`,
9
+ * `seekOffset`). The update is the one the web renderer's `mediaSession`
10
+ * request carries (docs/ops-protocol.md, "Now playing"), so an app writes
11
+ * the same code for the page and the native app. In the page (the round
12
+ * trip) the page's own `navigator.mediaSession` is there already and
13
+ * nothing is installed over it.
14
+ */
15
+ /** The protocol's command each Media Session action is; the rest get no button. */
16
+ const COMMANDS = {
17
+ play: 'play',
18
+ pause: 'pause',
19
+ stop: 'stop',
20
+ nexttrack: 'nextTrack',
21
+ previoustrack: 'previousTrack',
22
+ seekto: 'seekTo',
23
+ seekforward: 'skipForward',
24
+ seekbackward: 'skipBackward',
25
+ };
26
+ /** The browser's `MediaMetadata`. */
27
+ export class NativeMediaMetadata {
28
+ title;
29
+ artist;
30
+ album;
31
+ artwork;
32
+ constructor(init = {}) {
33
+ this.title = init.title ?? '';
34
+ this.artist = init.artist ?? '';
35
+ this.album = init.album ?? '';
36
+ this.artwork = (init.artwork ?? []).map((image) => ({ ...image }));
37
+ }
38
+ }
39
+ export function createMediaSession(native) {
40
+ let metadata = null;
41
+ let playbackState = 'none';
42
+ let position = null;
43
+ const handlers = new Map();
44
+ // The whole state each time: the host keeps what it has and changes what differs.
45
+ const sync = () => {
46
+ const commands = [...handlers.keys()].map((action) => COMMANDS[action]).filter((command) => command !== undefined);
47
+ native.mediaSession?.(JSON.stringify({
48
+ metadata: metadata === null ? null : { title: metadata.title, artist: metadata.artist, album: metadata.album, artwork: metadata.artwork[0]?.src },
49
+ playbackState,
50
+ position: position === null
51
+ ? null
52
+ : { duration: Number.isFinite(position.duration) ? position.duration : 0, position: position.position ?? 0, rate: position.playbackRate ?? 1 },
53
+ commands,
54
+ }));
55
+ };
56
+ const session = {
57
+ get metadata() {
58
+ return metadata;
59
+ },
60
+ set metadata(value) {
61
+ metadata = value === null || value === undefined ? null : value instanceof NativeMediaMetadata ? value : new NativeMediaMetadata(value);
62
+ sync();
63
+ },
64
+ get playbackState() {
65
+ return playbackState;
66
+ },
67
+ set playbackState(value) {
68
+ if (value !== 'none' && value !== 'playing' && value !== 'paused')
69
+ throw new TypeError(`${String(value)} is not a valid MediaSessionPlaybackState`);
70
+ playbackState = value;
71
+ sync();
72
+ },
73
+ setPositionState(state) {
74
+ if (state === undefined || state.duration === undefined) {
75
+ position = null;
76
+ }
77
+ else {
78
+ if (!(state.duration >= 0))
79
+ throw new TypeError('the duration must be a non-negative number');
80
+ if (state.position !== undefined && (state.position < 0 || state.position > state.duration))
81
+ throw new TypeError('the position must be within the duration');
82
+ position = { ...state };
83
+ }
84
+ sync();
85
+ },
86
+ setActionHandler(action, handler) {
87
+ if (!(action in COMMANDS) && !['skipad', 'togglemicrophone', 'togglecamera', 'hangup'].includes(action))
88
+ throw new TypeError(`${String(action)} is not a valid MediaSessionAction`);
89
+ if (handler)
90
+ handlers.set(action, handler);
91
+ else
92
+ handlers.delete(action);
93
+ sync();
94
+ },
95
+ };
96
+ const receive = (json) => {
97
+ let received;
98
+ try {
99
+ received = JSON.parse(json);
100
+ }
101
+ catch {
102
+ return;
103
+ }
104
+ const action = Object.keys(COMMANDS).find((name) => COMMANDS[name] === received.command);
105
+ if (!action)
106
+ return;
107
+ const handler = handlers.get(action);
108
+ if (!handler)
109
+ return;
110
+ const details = { action };
111
+ if (action === 'seekto' && typeof received.position === 'number')
112
+ details.seekTime = received.position;
113
+ if ((action === 'seekforward' || action === 'seekbackward') && typeof received.interval === 'number')
114
+ details.seekOffset = received.interval;
115
+ handler(details);
116
+ };
117
+ return { session, receive };
118
+ }
119
+ //# sourceMappingURL=mediaSession.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mediaSession.js","sourceRoot":"","sources":["../src/mediaSession.ts"],"names":[],"mappings":"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"}
package/dist/runtime.d.ts CHANGED
@@ -11,7 +11,8 @@
11
11
  * `atob`, `btoa`, `fetch` with `Headers`, `Request`, `Response`,
12
12
  * `AbortController` and `AbortSignal`, `URL`, `URLSearchParams`, `crypto`
13
13
  * (`getRandomValues`, `randomUUID`), `localStorage`, `structuredClone`,
14
- * `navigator`, `Image` (image.ts, on a bridge with `probeImage`) with the
14
+ * `navigator` (with `mediaSession` and `MediaMetadata` on a bridge with
15
+ * `mediaSession`, mediaSession.ts), `Image` (image.ts, on a bridge with `probeImage`) with the
15
16
  * bridge's `__sbImageProbed`, `Worker` (worker.ts) with the bridge's
16
17
  * `__sbWorkerMessage` and `__sbWorkerError`, `__sbOpenURL` (openURL.ts),
17
18
  * and the bridge's callbacks `__sbTimerFired` and `__sbFetchResult`. In a
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AAQ3D,KAAK,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAQzC,MAAM,WAAW,cAAc;IAC7B,uDAAuD;IACvD,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,GAAE,SAA8C,EAAE,OAAO,GAAE,cAAmB,GAAG,MAAM,EAAE,CAsLnJ"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AAS3D,KAAK,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAQzC,MAAM,WAAW,cAAc;IAC7B,uDAAuD;IACvD,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,GAAE,SAA8C,EAAE,OAAO,GAAE,cAAmB,GAAG,MAAM,EAAE,CA8LnJ"}
package/dist/runtime.js CHANGED
@@ -11,7 +11,8 @@
11
11
  * `atob`, `btoa`, `fetch` with `Headers`, `Request`, `Response`,
12
12
  * `AbortController` and `AbortSignal`, `URL`, `URLSearchParams`, `crypto`
13
13
  * (`getRandomValues`, `randomUUID`), `localStorage`, `structuredClone`,
14
- * `navigator`, `Image` (image.ts, on a bridge with `probeImage`) with the
14
+ * `navigator` (with `mediaSession` and `MediaMetadata` on a bridge with
15
+ * `mediaSession`, mediaSession.ts), `Image` (image.ts, on a bridge with `probeImage`) with the
15
16
  * bridge's `__sbImageProbed`, `Worker` (worker.ts) with the bridge's
16
17
  * `__sbWorkerMessage` and `__sbWorkerError`, `__sbOpenURL` (openURL.ts),
17
18
  * and the bridge's callbacks `__sbTimerFired` and `__sbFetchResult`. In a
@@ -27,6 +28,7 @@ import { createFetch } from './fetch';
27
28
  import { createImageGlobals } from './image';
28
29
  import { SimpleURL, SimpleURLSearchParams } from './url';
29
30
  import { installWorkerScope, NativeWorker } from './worker';
31
+ import { createMediaSession, NativeMediaMetadata } from './mediaSession';
30
32
  import { receiveOpenURL } from './openURL';
31
33
  /**
32
34
  * Installs the runtime on `target` (the global object) over `native`.
@@ -191,14 +193,23 @@ export function installRuntime(native, target = globalThis, options = {}) {
191
193
  };
192
194
  define('localStorage', storage);
193
195
  define('structuredClone', (value) => (value === undefined ? value : JSON.parse(JSON.stringify(value))));
194
- define('navigator', {
196
+ const navigator = {
195
197
  userAgent: 'SwiftBrowserNative',
196
198
  language: native.locale().replace('_', '-'),
197
199
  languages: [native.locale().replace('_', '-')],
198
200
  onLine: true,
199
201
  platform: 'iOS',
200
202
  hardwareConcurrency: 1,
201
- });
203
+ };
204
+ // What plays, for the lock screen and the media keys (mediaSession.ts); not in a worker.
205
+ const mediaSession = native.mediaSession && !native.workerPostMessage ? createMediaSession(native) : null;
206
+ if (mediaSession)
207
+ navigator['mediaSession'] = mediaSession.session;
208
+ define('navigator', navigator);
209
+ if (mediaSession) {
210
+ define('MediaMetadata', NativeMediaMetadata);
211
+ define('__sbMediaSessionCommand', mediaSession.receive);
212
+ }
202
213
  if (native.workerPostMessage) {
203
214
  installed.push(...installWorkerScope(native, target));
204
215
  }
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,YAAY,EAAqB,MAAM,UAAU,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC5G,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,OAAO,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAe3C;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,MAAoB,EAAE,SAAoB,UAAkC,EAAE,UAA0B,EAAE;IACvI,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,KAAc,EAAQ,EAAE;QACpD,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,SAAS;YAAE,OAAO;QACzD,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC;QACtG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvB,CAAC,CAAC;IAEF,wDAAwD;IACxD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC7C,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,MAAM,QAAQ,GAAG,CAAC,QAAiB,EAAE,KAAc,EAAE,IAAe,EAAE,OAAgB,EAAU,EAAE;QAChG,MAAM,EAAE,GAAG,SAAS,EAAE,CAAC;QACvB,MAAM,EAAE,GAAG,OAAO,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAE,QAAmC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;QAC5F,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QAChD,MAAM,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QAC9D,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC;IACF,MAAM,MAAM,GAAG,CAAC,EAAW,EAAQ,EAAE;QACnC,MAAM,GAAG,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;QACvB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC;YAAE,OAAO;QAChC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC,CAAC;IACF,MAAM,KAAK,GAAG,CAAC,EAAU,EAAQ,EAAE;QACjC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC7B,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,IAAI,CAAC,KAAK,CAAC,OAAO;YAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACtC,KAAK,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC,CAAC;IACF,MAAM,CAAC,YAAY,EAAE,CAAC,QAAiB,EAAE,KAAe,EAAE,GAAG,IAAe,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;IACzH,MAAM,CAAC,aAAa,EAAE,CAAC,QAAiB,EAAE,KAAe,EAAE,GAAG,IAAe,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IACzH,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;IAC/B,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;IAChC,MAAM,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;IAEhC,+DAA+D;IAC/D,MAAM,GAAG,GAAG,GAAW,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;IACvC,MAAM,CAAC,uBAAuB,EAAE,CAAC,QAAgC,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;IACtH,MAAM,CAAC,sBAAsB,EAAE,MAAM,CAAC,CAAC;IAEvC,MAAM,CAAC,gBAAgB,EAAE,CAAC,QAAoB,EAAE,EAAE;QAChD,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,kDAAkD;IAClD,MAAM,MAAM,GAAG,CAAC,KAAc,EAAU,EAAE;QACxC,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QAC5C,IAAI,KAAK,YAAY,KAAK;YAAE,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;QACzG,IAAI,OAAO,KAAK,KAAK,UAAU;YAAE,OAAO,aAAa,KAAK,CAAC,IAAI,IAAI,WAAW,GAAG,CAAC;QAClF,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;QACpF,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,KAAc,EAAE,EAAE,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;YACtI,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACnD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;IACH,CAAC,CAAC;IACF,MAAM,GAAG,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,GAAG,IAAe,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACrG,MAAM,aAAa,GAAG,IAAI,GAAG,EAAkB,CAAC;IAChD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,MAAM,CAAC,SAAS,EAAE;QAChB,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC;QACf,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC;QACjB,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC;QACjB,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC;QACnB,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC;QACnB,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC;QACnB,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC;QACf,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC;QACjB,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC;QACjB,cAAc,EAAE,GAAG,CAAC,KAAK,CAAC;QAC1B,QAAQ,EAAE,GAAG,EAAE,GAAE,CAAC;QAClB,MAAM,EAAE,CAAC,SAAkB,EAAE,GAAG,IAAe,EAAE,EAAE;YACjD,IAAI,CAAC,SAAS;gBAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,mBAAmB,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACjH,CAAC;QACD,KAAK,EAAE,CAAC,KAAK,GAAG,SAAS,EAAE,EAAE;YAC3B,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;YAC3C,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YACzB,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,KAAK,KAAK,KAAK,EAAE,CAAC,CAAC;QAC1C,CAAC;QACD,UAAU,EAAE,CAAC,KAAK,GAAG,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;QACvD,IAAI,EAAE,CAAC,KAAK,GAAG,SAAS,EAAE,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC;QAC5D,OAAO,EAAE,CAAC,KAAK,GAAG,SAAS,EAAE,EAAE;YAC7B,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACvC,IAAI,KAAK,KAAK,SAAS;gBAAE,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,KAAK,KAAK,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YACzF,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;QACD,OAAO,EAAE,CAAC,KAAK,GAAG,SAAS,EAAE,EAAE;YAC7B,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACvC,IAAI,KAAK,KAAK,SAAS;gBAAE,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,KAAK,KAAK,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC3F,CAAC;KACF,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,EAAE,CAAC;IAClC,MAAM,CAAC,aAAa,EAAE;QACpB,GAAG;QACH,UAAU,EAAE,MAAM;QAClB,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC;QACd,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC;QACjB,UAAU,EAAE,GAAG,EAAE,CAAC,EAAE;QACpB,gBAAgB,EAAE,GAAG,EAAE,CAAC,EAAE;QAC1B,gBAAgB,EAAE,GAAG,EAAE,CAAC,EAAE;QAC1B,UAAU,EAAE,GAAG,EAAE,GAAE,CAAC;QACpB,aAAa,EAAE,GAAG,EAAE,GAAE,CAAC;KACxB,CAAC,CAAC;IAEH,MAAM,CAAC,aAAa,EAAE,iBAAiB,CAAC,CAAC;IACzC,MAAM,CAAC,aAAa,EAAE,iBAAiB,CAAC,CAAC;IACzC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAC7B,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAE7B,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,CAAC,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,CAAC,UAAU,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,CAAC,iBAAiB,EAAE,YAAY,CAAC,eAAe,CAAC,CAAC;IACxD,MAAM,CAAC,aAAa,EAAE,YAAY,CAAC,WAAW,CAAC,CAAC;IAChD,MAAM,CAAC,iBAAiB,EAAE,YAAY,CAAC,eAAe,CAAC,CAAC;IAExD,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IACzB,MAAM,CAAC,iBAAiB,EAAE,qBAAqB,CAAC,CAAC;IAEjD,oEAAoE;IACpE,6DAA6D;IAC7D,IAAI,MAAM,CAAC,UAAU,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC;QACnD,MAAM,YAAY,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;QAChD,MAAM,CAAC,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC;QACpC,MAAM,CAAC,iBAAiB,EAAE,YAAY,CAAC,eAAe,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,CAAC,QAAQ,EAAE;QACf,eAAe,EAAE,CAA4B,KAAQ,EAAK,EAAE;YAC1D,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;YACjE,IAAI,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;YAC1G,OAAO,KAAK,CAAC;QACf,CAAC;QACD,UAAU,EAAE,GAAW,EAAE;YACvB,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC;YACnD,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;YACrC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;YACrC,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACrF,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;QAC7G,CAAC;KACF,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG;QACd,OAAO,EAAE,CAAC,GAAW,EAAiB,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACvE,OAAO,EAAE,CAAC,GAAW,EAAE,KAAa,EAAQ,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5F,UAAU,EAAE,CAAC,GAAW,EAAQ,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACpE,KAAK,EAAE,GAAS,EAAE,CAAC,MAAM,CAAC,YAAY,EAAE;QACxC,GAAG,EAAE,CAAC,KAAa,EAAiB,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,IAAI,IAAI;QAC1E,IAAI,MAAM;YACR,OAAO,MAAM,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC;QACrC,CAAC;KACF,CAAC;IACF,MAAM,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;IAEhC,MAAM,CAAC,iBAAiB,EAAE,CAAI,KAAQ,EAAK,EAAE,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAO,CAAC,CAAC,CAAC;IAExH,MAAM,CAAC,WAAW,EAAE;QAClB,SAAS,EAAE,oBAAoB;QAC/B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC;QAC3C,SAAS,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAC9C,MAAM,EAAE,IAAI;QACZ,QAAQ,EAAE,KAAK;QACf,mBAAmB,EAAE,CAAC;KACvB,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,iBAAiB,EAAE,CAAC;QAC7B,SAAS,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACxD,CAAC;SAAM,CAAC;QACN,2EAA2E;QAC3E,MAAM,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;QACtC,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;YACvB,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;YAC/B,MAAM,CAAC,mBAAmB,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;YAClD,MAAM,CAAC,iBAAiB,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,4EAA4E;AAC5E,yEAAyE;AACzE,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;AAC9B,IAAI,MAAM;IAAE,cAAc,CAAC,MAAM,CAAC,CAAC"}
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,YAAY,EAAqB,MAAM,UAAU,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC5G,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,OAAO,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAe3C;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,MAAoB,EAAE,SAAoB,UAAkC,EAAE,UAA0B,EAAE;IACvI,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,KAAc,EAAQ,EAAE;QACpD,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,SAAS;YAAE,OAAO;QACzD,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC;QACtG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvB,CAAC,CAAC;IAEF,wDAAwD;IACxD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC7C,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,MAAM,QAAQ,GAAG,CAAC,QAAiB,EAAE,KAAc,EAAE,IAAe,EAAE,OAAgB,EAAU,EAAE;QAChG,MAAM,EAAE,GAAG,SAAS,EAAE,CAAC;QACvB,MAAM,EAAE,GAAG,OAAO,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAE,QAAmC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;QAC5F,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QAChD,MAAM,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QAC9D,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC;IACF,MAAM,MAAM,GAAG,CAAC,EAAW,EAAQ,EAAE;QACnC,MAAM,GAAG,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;QACvB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC;YAAE,OAAO;QAChC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC,CAAC;IACF,MAAM,KAAK,GAAG,CAAC,EAAU,EAAQ,EAAE;QACjC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC7B,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,IAAI,CAAC,KAAK,CAAC,OAAO;YAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACtC,KAAK,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC,CAAC;IACF,MAAM,CAAC,YAAY,EAAE,CAAC,QAAiB,EAAE,KAAe,EAAE,GAAG,IAAe,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;IACzH,MAAM,CAAC,aAAa,EAAE,CAAC,QAAiB,EAAE,KAAe,EAAE,GAAG,IAAe,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IACzH,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;IAC/B,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;IAChC,MAAM,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;IAEhC,+DAA+D;IAC/D,MAAM,GAAG,GAAG,GAAW,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;IACvC,MAAM,CAAC,uBAAuB,EAAE,CAAC,QAAgC,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;IACtH,MAAM,CAAC,sBAAsB,EAAE,MAAM,CAAC,CAAC;IAEvC,MAAM,CAAC,gBAAgB,EAAE,CAAC,QAAoB,EAAE,EAAE;QAChD,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,kDAAkD;IAClD,MAAM,MAAM,GAAG,CAAC,KAAc,EAAU,EAAE;QACxC,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QAC5C,IAAI,KAAK,YAAY,KAAK;YAAE,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;QACzG,IAAI,OAAO,KAAK,KAAK,UAAU;YAAE,OAAO,aAAa,KAAK,CAAC,IAAI,IAAI,WAAW,GAAG,CAAC;QAClF,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;QACpF,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,KAAc,EAAE,EAAE,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;YACtI,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACnD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;IACH,CAAC,CAAC;IACF,MAAM,GAAG,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,GAAG,IAAe,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACrG,MAAM,aAAa,GAAG,IAAI,GAAG,EAAkB,CAAC;IAChD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,MAAM,CAAC,SAAS,EAAE;QAChB,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC;QACf,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC;QACjB,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC;QACjB,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC;QACnB,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC;QACnB,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC;QACnB,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC;QACf,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC;QACjB,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC;QACjB,cAAc,EAAE,GAAG,CAAC,KAAK,CAAC;QAC1B,QAAQ,EAAE,GAAG,EAAE,GAAE,CAAC;QAClB,MAAM,EAAE,CAAC,SAAkB,EAAE,GAAG,IAAe,EAAE,EAAE;YACjD,IAAI,CAAC,SAAS;gBAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,mBAAmB,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACjH,CAAC;QACD,KAAK,EAAE,CAAC,KAAK,GAAG,SAAS,EAAE,EAAE;YAC3B,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;YAC3C,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YACzB,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,KAAK,KAAK,KAAK,EAAE,CAAC,CAAC;QAC1C,CAAC;QACD,UAAU,EAAE,CAAC,KAAK,GAAG,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;QACvD,IAAI,EAAE,CAAC,KAAK,GAAG,SAAS,EAAE,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC;QAC5D,OAAO,EAAE,CAAC,KAAK,GAAG,SAAS,EAAE,EAAE;YAC7B,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACvC,IAAI,KAAK,KAAK,SAAS;gBAAE,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,KAAK,KAAK,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YACzF,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;QACD,OAAO,EAAE,CAAC,KAAK,GAAG,SAAS,EAAE,EAAE;YAC7B,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACvC,IAAI,KAAK,KAAK,SAAS;gBAAE,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,KAAK,KAAK,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC3F,CAAC;KACF,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,EAAE,CAAC;IAClC,MAAM,CAAC,aAAa,EAAE;QACpB,GAAG;QACH,UAAU,EAAE,MAAM;QAClB,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC;QACd,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC;QACjB,UAAU,EAAE,GAAG,EAAE,CAAC,EAAE;QACpB,gBAAgB,EAAE,GAAG,EAAE,CAAC,EAAE;QAC1B,gBAAgB,EAAE,GAAG,EAAE,CAAC,EAAE;QAC1B,UAAU,EAAE,GAAG,EAAE,GAAE,CAAC;QACpB,aAAa,EAAE,GAAG,EAAE,GAAE,CAAC;KACxB,CAAC,CAAC;IAEH,MAAM,CAAC,aAAa,EAAE,iBAAiB,CAAC,CAAC;IACzC,MAAM,CAAC,aAAa,EAAE,iBAAiB,CAAC,CAAC;IACzC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAC7B,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAE7B,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,CAAC,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,CAAC,UAAU,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,CAAC,iBAAiB,EAAE,YAAY,CAAC,eAAe,CAAC,CAAC;IACxD,MAAM,CAAC,aAAa,EAAE,YAAY,CAAC,WAAW,CAAC,CAAC;IAChD,MAAM,CAAC,iBAAiB,EAAE,YAAY,CAAC,eAAe,CAAC,CAAC;IAExD,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IACzB,MAAM,CAAC,iBAAiB,EAAE,qBAAqB,CAAC,CAAC;IAEjD,oEAAoE;IACpE,6DAA6D;IAC7D,IAAI,MAAM,CAAC,UAAU,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC;QACnD,MAAM,YAAY,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;QAChD,MAAM,CAAC,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC;QACpC,MAAM,CAAC,iBAAiB,EAAE,YAAY,CAAC,eAAe,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,CAAC,QAAQ,EAAE;QACf,eAAe,EAAE,CAA4B,KAAQ,EAAK,EAAE;YAC1D,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;YACjE,IAAI,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;YAC1G,OAAO,KAAK,CAAC;QACf,CAAC;QACD,UAAU,EAAE,GAAW,EAAE;YACvB,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC;YACnD,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;YACrC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;YACrC,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACrF,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;QAC7G,CAAC;KACF,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG;QACd,OAAO,EAAE,CAAC,GAAW,EAAiB,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACvE,OAAO,EAAE,CAAC,GAAW,EAAE,KAAa,EAAQ,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5F,UAAU,EAAE,CAAC,GAAW,EAAQ,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACpE,KAAK,EAAE,GAAS,EAAE,CAAC,MAAM,CAAC,YAAY,EAAE;QACxC,GAAG,EAAE,CAAC,KAAa,EAAiB,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,IAAI,IAAI;QAC1E,IAAI,MAAM;YACR,OAAO,MAAM,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC;QACrC,CAAC;KACF,CAAC;IACF,MAAM,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;IAEhC,MAAM,CAAC,iBAAiB,EAAE,CAAI,KAAQ,EAAK,EAAE,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAO,CAAC,CAAC,CAAC;IAExH,MAAM,SAAS,GAA4B;QACzC,SAAS,EAAE,oBAAoB;QAC/B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC;QAC3C,SAAS,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAC9C,MAAM,EAAE,IAAI;QACZ,QAAQ,EAAE,KAAK;QACf,mBAAmB,EAAE,CAAC;KACvB,CAAC;IACF,yFAAyF;IACzF,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1G,IAAI,YAAY;QAAE,SAAS,CAAC,cAAc,CAAC,GAAG,YAAY,CAAC,OAAO,CAAC;IACnE,MAAM,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IAC/B,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,CAAC,eAAe,EAAE,mBAAmB,CAAC,CAAC;QAC7C,MAAM,CAAC,yBAAyB,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;IAC1D,CAAC;IAED,IAAI,MAAM,CAAC,iBAAiB,EAAE,CAAC;QAC7B,SAAS,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACxD,CAAC;SAAM,CAAC;QACN,2EAA2E;QAC3E,MAAM,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;QACtC,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;YACvB,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;YAC/B,MAAM,CAAC,mBAAmB,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;YAClD,MAAM,CAAC,iBAAiB,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,4EAA4E;AAC5E,yEAAyE;AACzE,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;AAC9B,IAAI,MAAM;IAAE,cAAc,CAAC,MAAM,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swiftbrowser/native",
3
- "version": "0.17.6",
3
+ "version": "0.17.7",
4
4
  "type": "module",
5
5
  "description": "Run a @swiftbrowser/react app natively: the runtime a JavaScriptCore-hosted app needs (timers, console, fetch and the other web globals over the SwiftBrowser Native bridge), the `run` entry that renders into the native SwiftUI renderer, and the bundler that builds app.js for the Xcode target.",
6
6
  "repository": {
@@ -59,8 +59,8 @@
59
59
  },
60
60
  "dependencies": {
61
61
  "@babel/core": "^7.29.7",
62
- "@swiftbrowser/react": "0.17.6",
63
- "@swiftbrowser/web": "0.17.6",
62
+ "@swiftbrowser/react": "0.17.7",
63
+ "@swiftbrowser/web": "0.17.7",
64
64
  "esbuild": "^0.28.2",
65
65
  "react-refresh": "^0.17.0"
66
66
  },
package/src/bridge.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  * (Native/Sources/SwiftBrowserNative/Host/HostBridge.swift). Every call is
4
4
  * synchronous; the ones that answer later do so by calling a global this
5
5
  * package defines (`__sbTimerFired`, `__sbFetchResult`, `__sbImageProbed`,
6
- * `__sbWorkerMessage`, `__sbOpenURL`).
6
+ * `__sbWorkerMessage`, `__sbOpenURL`, `__sbMediaSessionCommand`).
7
7
  */
8
8
  export interface NativeBridge {
9
9
  /** Applies a render pass's ops (a JSON array). Returns an error message, or nothing. */
@@ -35,6 +35,14 @@ export interface NativeBridge {
35
35
  locale(): string;
36
36
  /** The process's launch arguments (`-screen list` from an Xcode scheme or `simctl launch`). */
37
37
  launchArguments?(): string[];
38
+ /**
39
+ * `navigator.mediaSession` (mediaSession.ts): the whole session as JSON
40
+ * (`metadata`, `playbackState`, `position`, `commands`, as the web
41
+ * renderer's `mediaSession` request carries them), for the lock screen
42
+ * and the media keys; a command the viewer gives arrives at
43
+ * `__sbMediaSessionCommand(json)`. Hosts before 0.19 lack it.
44
+ */
45
+ mediaSession?(update: string): void;
38
46
 
39
47
  // Workers (worker.ts): a second context on its own thread, from a bundle
40
48
  // `swiftbrowser-native build --worker <name>=<entry>` wrote next to app.js
package/src/index.ts CHANGED
@@ -20,3 +20,4 @@ export { SimpleURL, SimpleURLSearchParams } from './url';
20
20
  export { SimpleTextEncoder, SimpleTextDecoder, base64Encode, base64Decode, utf8Encode, utf8Decode } from './encoding';
21
21
  export { createWorker, NativeWorker, encodeMessage, decodeMessage, workerName, type NativeWorkerOptions, type WorkerLike, type WorkerMessageEvent, type WorkerErrorEvent } from './worker';
22
22
  export { onOpenURL } from './openURL';
23
+ export { createMediaSession, NativeMediaMetadata, type NativeMediaSession, type MediaMetadataInit, type MediaActionDetails, type MediaActionHandler, type MediaPositionState } from './mediaSession';
@@ -0,0 +1,163 @@
1
+ /**
2
+ * `navigator.mediaSession` and `MediaMetadata` for the native app: what an
3
+ * audio app tells the browser about what plays (the lock screen, the media
4
+ * keys) reaches the host's `mediaSession(update)` instead, which sets
5
+ * `MPNowPlayingInfoCenter` and `MPRemoteCommandCenter` (HostBridge.swift,
6
+ * NowPlayingBridge.swift); the commands the viewer gives come back to
7
+ * `__sbMediaSessionCommand(json)` and run the handlers `setActionHandler`
8
+ * registered, with the details the browser would give (`seekTime`,
9
+ * `seekOffset`). The update is the one the web renderer's `mediaSession`
10
+ * request carries (docs/ops-protocol.md, "Now playing"), so an app writes
11
+ * the same code for the page and the native app. In the page (the round
12
+ * trip) the page's own `navigator.mediaSession` is there already and
13
+ * nothing is installed over it.
14
+ */
15
+
16
+ import type { NativeBridge } from './bridge';
17
+
18
+ type Action = 'play' | 'pause' | 'stop' | 'nexttrack' | 'previoustrack' | 'seekto' | 'seekforward' | 'seekbackward' | 'skipad' | 'togglemicrophone' | 'togglecamera' | 'hangup';
19
+
20
+ /** The protocol's command each Media Session action is; the rest get no button. */
21
+ const COMMANDS: Partial<Record<Action, string>> = {
22
+ play: 'play',
23
+ pause: 'pause',
24
+ stop: 'stop',
25
+ nexttrack: 'nextTrack',
26
+ previoustrack: 'previousTrack',
27
+ seekto: 'seekTo',
28
+ seekforward: 'skipForward',
29
+ seekbackward: 'skipBackward',
30
+ };
31
+
32
+ export interface MediaImage {
33
+ src: string;
34
+ sizes?: string;
35
+ type?: string;
36
+ }
37
+
38
+ export interface MediaMetadataInit {
39
+ title?: string;
40
+ artist?: string;
41
+ album?: string;
42
+ artwork?: MediaImage[];
43
+ }
44
+
45
+ /** The browser's `MediaMetadata`. */
46
+ export class NativeMediaMetadata {
47
+ title: string;
48
+ artist: string;
49
+ album: string;
50
+ artwork: MediaImage[];
51
+
52
+ constructor(init: MediaMetadataInit = {}) {
53
+ this.title = init.title ?? '';
54
+ this.artist = init.artist ?? '';
55
+ this.album = init.album ?? '';
56
+ this.artwork = (init.artwork ?? []).map((image) => ({ ...image }));
57
+ }
58
+ }
59
+
60
+ export interface MediaPositionState {
61
+ duration?: number;
62
+ playbackRate?: number;
63
+ position?: number;
64
+ }
65
+
66
+ export interface MediaActionDetails {
67
+ action: Action;
68
+ seekTime?: number;
69
+ seekOffset?: number;
70
+ }
71
+
72
+ export type MediaActionHandler = (details: MediaActionDetails) => void;
73
+
74
+ /** The browser's `navigator.mediaSession`, as far as audio apps use it. */
75
+ export interface NativeMediaSession {
76
+ metadata: NativeMediaMetadata | null;
77
+ playbackState: 'none' | 'playing' | 'paused';
78
+ setPositionState(state?: MediaPositionState): void;
79
+ setActionHandler(action: Action, handler: MediaActionHandler | null): void;
80
+ }
81
+
82
+ /** A command the host received: the protocol's name, with the position of a seek or the interval of a skip. */
83
+ interface ReceivedCommand {
84
+ command: string;
85
+ position?: number;
86
+ interval?: number;
87
+ }
88
+
89
+ export function createMediaSession(native: Pick<NativeBridge, 'mediaSession'>): { session: NativeMediaSession; receive: (json: string) => void } {
90
+ let metadata: NativeMediaMetadata | null = null;
91
+ let playbackState: NativeMediaSession['playbackState'] = 'none';
92
+ let position: MediaPositionState | null = null;
93
+ const handlers = new Map<Action, MediaActionHandler>();
94
+
95
+ // The whole state each time: the host keeps what it has and changes what differs.
96
+ const sync = (): void => {
97
+ const commands = [...handlers.keys()].map((action) => COMMANDS[action]).filter((command): command is string => command !== undefined);
98
+ native.mediaSession?.(
99
+ JSON.stringify({
100
+ metadata: metadata === null ? null : { title: metadata.title, artist: metadata.artist, album: metadata.album, artwork: metadata.artwork[0]?.src },
101
+ playbackState,
102
+ position:
103
+ position === null
104
+ ? null
105
+ : { duration: Number.isFinite(position.duration) ? position.duration : 0, position: position.position ?? 0, rate: position.playbackRate ?? 1 },
106
+ commands,
107
+ }),
108
+ );
109
+ };
110
+
111
+ const session: NativeMediaSession = {
112
+ get metadata() {
113
+ return metadata;
114
+ },
115
+ set metadata(value) {
116
+ metadata = value === null || value === undefined ? null : value instanceof NativeMediaMetadata ? value : new NativeMediaMetadata(value as MediaMetadataInit);
117
+ sync();
118
+ },
119
+ get playbackState() {
120
+ return playbackState;
121
+ },
122
+ set playbackState(value) {
123
+ if (value !== 'none' && value !== 'playing' && value !== 'paused') throw new TypeError(`${String(value)} is not a valid MediaSessionPlaybackState`);
124
+ playbackState = value;
125
+ sync();
126
+ },
127
+ setPositionState(state) {
128
+ if (state === undefined || state.duration === undefined) {
129
+ position = null;
130
+ } else {
131
+ if (!(state.duration >= 0)) throw new TypeError('the duration must be a non-negative number');
132
+ if (state.position !== undefined && (state.position < 0 || state.position > state.duration)) throw new TypeError('the position must be within the duration');
133
+ position = { ...state };
134
+ }
135
+ sync();
136
+ },
137
+ setActionHandler(action, handler) {
138
+ if (!(action in COMMANDS) && !['skipad', 'togglemicrophone', 'togglecamera', 'hangup'].includes(action)) throw new TypeError(`${String(action)} is not a valid MediaSessionAction`);
139
+ if (handler) handlers.set(action, handler);
140
+ else handlers.delete(action);
141
+ sync();
142
+ },
143
+ };
144
+
145
+ const receive = (json: string): void => {
146
+ let received: ReceivedCommand;
147
+ try {
148
+ received = JSON.parse(json) as ReceivedCommand;
149
+ } catch {
150
+ return;
151
+ }
152
+ const action = (Object.keys(COMMANDS) as Action[]).find((name) => COMMANDS[name] === received.command);
153
+ if (!action) return;
154
+ const handler = handlers.get(action);
155
+ if (!handler) return;
156
+ const details: MediaActionDetails = { action };
157
+ if (action === 'seekto' && typeof received.position === 'number') details.seekTime = received.position;
158
+ if ((action === 'seekforward' || action === 'seekbackward') && typeof received.interval === 'number') details.seekOffset = received.interval;
159
+ handler(details);
160
+ };
161
+
162
+ return { session, receive };
163
+ }