@thewhateverapp/tile-sdk 0.12.11 → 0.12.12
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.
|
@@ -59,8 +59,9 @@ export declare class TileBridge {
|
|
|
59
59
|
private tokenExpiresAt;
|
|
60
60
|
private keyboardState;
|
|
61
61
|
private visibilityState;
|
|
62
|
-
private autoMuteEnabled;
|
|
63
62
|
private mediaOriginalMutedState;
|
|
63
|
+
private trackedAudioContexts;
|
|
64
|
+
private audioContextPatched;
|
|
64
65
|
private baselineViewportHeight;
|
|
65
66
|
private keyboardDetectionEnabled;
|
|
66
67
|
private lastReportedKeyboardState;
|
|
@@ -112,12 +113,15 @@ export declare class TileBridge {
|
|
|
112
113
|
*/
|
|
113
114
|
private handleVisibility;
|
|
114
115
|
/**
|
|
115
|
-
*
|
|
116
|
-
*
|
|
116
|
+
* MANDATORY: Mute all audio sources when tile is offscreen
|
|
117
|
+
* - Mutes all <video> and <audio> elements
|
|
118
|
+
* - Suspends all registered AudioContexts (for WASM/Emscripten audio)
|
|
117
119
|
*/
|
|
118
120
|
private muteAllMedia;
|
|
119
121
|
/**
|
|
120
|
-
* Unmute all
|
|
122
|
+
* Unmute all audio sources when tile becomes visible
|
|
123
|
+
* - Unmutes <video> and <audio> elements (restoring original state)
|
|
124
|
+
* - Resumes all registered AudioContexts
|
|
121
125
|
*/
|
|
122
126
|
private unmuteAllMedia;
|
|
123
127
|
private sendToParent;
|
|
@@ -333,30 +337,26 @@ export declare class TileBridge {
|
|
|
333
337
|
*/
|
|
334
338
|
onVisibilityChange(handler: (state: VisibilityState) => void): () => void;
|
|
335
339
|
/**
|
|
336
|
-
*
|
|
337
|
-
* By default, auto-mute is ENABLED - all <video> and <audio> elements are
|
|
338
|
-
* automatically muted when the tile becomes hidden/offscreen.
|
|
340
|
+
* Register an AudioContext for mandatory muting when tile goes offscreen.
|
|
339
341
|
*
|
|
340
|
-
*
|
|
341
|
-
*
|
|
342
|
+
* PROTOCOL FOR TILES WITH CUSTOM AUDIO:
|
|
343
|
+
* Tiles using AudioContext (e.g., Emscripten/WASM games like DOOM) MUST call
|
|
344
|
+
* this method to register their AudioContext. The TileBridge will automatically
|
|
345
|
+
* suspend/resume the context when the tile goes offscreen/onscreen.
|
|
342
346
|
*
|
|
343
|
-
*
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
*
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
/**
|
|
351
|
-
* Manually mute all audio/video elements
|
|
352
|
-
* Useful for tiles that need to mute on demand
|
|
347
|
+
* Example usage in DoomManager:
|
|
348
|
+
* ```
|
|
349
|
+
* const bridge = getTileBridge();
|
|
350
|
+
* bridge.registerAudioContext(myAudioContext);
|
|
351
|
+
* ```
|
|
352
|
+
*
|
|
353
|
+
* @param ctx - The AudioContext to track for automatic suspension
|
|
353
354
|
*/
|
|
354
|
-
|
|
355
|
+
registerAudioContext(ctx: AudioContext): void;
|
|
355
356
|
/**
|
|
356
|
-
*
|
|
357
|
-
* Restores original muted state (elements that were muted before stay muted)
|
|
357
|
+
* Unregister an AudioContext (e.g., when closing it)
|
|
358
358
|
*/
|
|
359
|
-
|
|
359
|
+
unregisterAudioContext(ctx: AudioContext): void;
|
|
360
360
|
/**
|
|
361
361
|
* Wait for ready state
|
|
362
362
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TileBridge.d.ts","sourceRoot":"","sources":["../../src/bridge/TileBridge.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,iGAAiG;IACjG,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAGD,KAAK,UAAU,GAAG;IAChB,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB,CAAC;AAEF,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,gBAAgB,CAAmD;IAC3E,OAAO,CAAC,aAAa,CAAoD;IACzE,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,MAAM,CAA2B;IAGzC,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,cAAc,CAAqB;IAG3C,OAAO,CAAC,aAAa,CAAgD;IAIrE,OAAO,CAAC,eAAe,CAAoD;IAG3E,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"TileBridge.d.ts","sourceRoot":"","sources":["../../src/bridge/TileBridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,10 +18,11 @@ export class TileBridge {
|
|
|
18
18
|
// Visibility state from parent (for TikTok-style feeds)
|
|
19
19
|
// Includes muted state for atomic updates to prevent race conditions
|
|
20
20
|
this.visibilityState = { visible: true, muted: false };
|
|
21
|
-
// Automatic audio enforcement - enabled by default
|
|
22
|
-
this.autoMuteEnabled = true;
|
|
23
21
|
// Store original muted state of media elements to restore when unmuting
|
|
24
22
|
this.mediaOriginalMutedState = new WeakMap();
|
|
23
|
+
// Track all AudioContext instances for suspension (catches Emscripten/WASM audio)
|
|
24
|
+
this.trackedAudioContexts = new Set();
|
|
25
|
+
this.audioContextPatched = false;
|
|
25
26
|
// VisualViewport tracking for keyboard detection (Plan A)
|
|
26
27
|
this.baselineViewportHeight = 0;
|
|
27
28
|
this.keyboardDetectionEnabled = false;
|
|
@@ -411,14 +412,12 @@ export class TileBridge {
|
|
|
411
412
|
if (this.isDevelopment() || this.isPreview()) {
|
|
412
413
|
console.log('[TileBridge] 👁️ Received visibility state', this.visibilityState);
|
|
413
414
|
}
|
|
414
|
-
//
|
|
415
|
-
if (this.
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
this.unmuteAllMedia();
|
|
421
|
-
}
|
|
415
|
+
// MANDATORY: Enforce audio muting when offscreen - no exceptions
|
|
416
|
+
if (this.visibilityState.muted) {
|
|
417
|
+
this.muteAllMedia();
|
|
418
|
+
}
|
|
419
|
+
else if (wasMuted && !this.visibilityState.muted) {
|
|
420
|
+
this.unmuteAllMedia();
|
|
422
421
|
}
|
|
423
422
|
// Emit if visibility OR muted state changed
|
|
424
423
|
if (wasVisible !== this.visibilityState.visible || wasMuted !== this.visibilityState.muted) {
|
|
@@ -426,12 +425,14 @@ export class TileBridge {
|
|
|
426
425
|
}
|
|
427
426
|
}
|
|
428
427
|
/**
|
|
429
|
-
*
|
|
430
|
-
*
|
|
428
|
+
* MANDATORY: Mute all audio sources when tile is offscreen
|
|
429
|
+
* - Mutes all <video> and <audio> elements
|
|
430
|
+
* - Suspends all registered AudioContexts (for WASM/Emscripten audio)
|
|
431
431
|
*/
|
|
432
432
|
muteAllMedia() {
|
|
433
433
|
if (typeof document === 'undefined')
|
|
434
434
|
return;
|
|
435
|
+
// 1. Mute all HTML media elements
|
|
435
436
|
const mediaElements = document.querySelectorAll('video, audio');
|
|
436
437
|
let mutedCount = 0;
|
|
437
438
|
mediaElements.forEach((element) => {
|
|
@@ -445,16 +446,29 @@ export class TileBridge {
|
|
|
445
446
|
mutedCount++;
|
|
446
447
|
}
|
|
447
448
|
});
|
|
448
|
-
|
|
449
|
-
|
|
449
|
+
// 2. Suspend all registered AudioContexts (for tiles like DOOM with WASM audio)
|
|
450
|
+
let suspendedCount = 0;
|
|
451
|
+
this.trackedAudioContexts.forEach((ctx) => {
|
|
452
|
+
if (ctx.state === 'running') {
|
|
453
|
+
ctx.suspend().catch((err) => {
|
|
454
|
+
console.warn('[TileBridge] Failed to suspend AudioContext:', err);
|
|
455
|
+
});
|
|
456
|
+
suspendedCount++;
|
|
457
|
+
}
|
|
458
|
+
});
|
|
459
|
+
if (mutedCount > 0 || suspendedCount > 0) {
|
|
460
|
+
console.log(`[TileBridge] 🔇 MUTED: ${mutedCount} media element(s), ${suspendedCount} AudioContext(s)`);
|
|
450
461
|
}
|
|
451
462
|
}
|
|
452
463
|
/**
|
|
453
|
-
* Unmute all
|
|
464
|
+
* Unmute all audio sources when tile becomes visible
|
|
465
|
+
* - Unmutes <video> and <audio> elements (restoring original state)
|
|
466
|
+
* - Resumes all registered AudioContexts
|
|
454
467
|
*/
|
|
455
468
|
unmuteAllMedia() {
|
|
456
469
|
if (typeof document === 'undefined')
|
|
457
470
|
return;
|
|
471
|
+
// 1. Unmute HTML media elements
|
|
458
472
|
const mediaElements = document.querySelectorAll('video, audio');
|
|
459
473
|
let unmutedCount = 0;
|
|
460
474
|
mediaElements.forEach((element) => {
|
|
@@ -471,8 +485,18 @@ export class TileBridge {
|
|
|
471
485
|
// Clear stored state
|
|
472
486
|
this.mediaOriginalMutedState.delete(media);
|
|
473
487
|
});
|
|
474
|
-
|
|
475
|
-
|
|
488
|
+
// 2. Resume all registered AudioContexts
|
|
489
|
+
let resumedCount = 0;
|
|
490
|
+
this.trackedAudioContexts.forEach((ctx) => {
|
|
491
|
+
if (ctx.state === 'suspended') {
|
|
492
|
+
ctx.resume().catch((err) => {
|
|
493
|
+
console.warn('[TileBridge] Failed to resume AudioContext:', err);
|
|
494
|
+
});
|
|
495
|
+
resumedCount++;
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
if (unmutedCount > 0 || resumedCount > 0) {
|
|
499
|
+
console.log(`[TileBridge] 🔊 UNMUTED: ${unmutedCount} media element(s), ${resumedCount} AudioContext(s)`);
|
|
476
500
|
}
|
|
477
501
|
}
|
|
478
502
|
sendToParent(message) {
|
|
@@ -1184,40 +1208,40 @@ export class TileBridge {
|
|
|
1184
1208
|
onVisibilityChange(handler) {
|
|
1185
1209
|
return this.on('visibility:update', handler);
|
|
1186
1210
|
}
|
|
1187
|
-
// =============
|
|
1211
|
+
// ============= AUDIOCONTEXT REGISTRATION API =============
|
|
1212
|
+
// Tiles with custom audio (WASM/Emscripten) MUST register their AudioContexts
|
|
1213
|
+
// to be automatically suspended/resumed when the tile goes offscreen.
|
|
1188
1214
|
/**
|
|
1189
|
-
*
|
|
1190
|
-
* By default, auto-mute is ENABLED - all <video> and <audio> elements are
|
|
1191
|
-
* automatically muted when the tile becomes hidden/offscreen.
|
|
1215
|
+
* Register an AudioContext for mandatory muting when tile goes offscreen.
|
|
1192
1216
|
*
|
|
1193
|
-
*
|
|
1194
|
-
*
|
|
1217
|
+
* PROTOCOL FOR TILES WITH CUSTOM AUDIO:
|
|
1218
|
+
* Tiles using AudioContext (e.g., Emscripten/WASM games like DOOM) MUST call
|
|
1219
|
+
* this method to register their AudioContext. The TileBridge will automatically
|
|
1220
|
+
* suspend/resume the context when the tile goes offscreen/onscreen.
|
|
1195
1221
|
*
|
|
1196
|
-
*
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
* Check if automatic audio muting is enabled
|
|
1204
|
-
*/
|
|
1205
|
-
isAutoMuteEnabled() {
|
|
1206
|
-
return this.autoMuteEnabled;
|
|
1207
|
-
}
|
|
1208
|
-
/**
|
|
1209
|
-
* Manually mute all audio/video elements
|
|
1210
|
-
* Useful for tiles that need to mute on demand
|
|
1222
|
+
* Example usage in DoomManager:
|
|
1223
|
+
* ```
|
|
1224
|
+
* const bridge = getTileBridge();
|
|
1225
|
+
* bridge.registerAudioContext(myAudioContext);
|
|
1226
|
+
* ```
|
|
1227
|
+
*
|
|
1228
|
+
* @param ctx - The AudioContext to track for automatic suspension
|
|
1211
1229
|
*/
|
|
1212
|
-
|
|
1213
|
-
this.
|
|
1230
|
+
registerAudioContext(ctx) {
|
|
1231
|
+
this.trackedAudioContexts.add(ctx);
|
|
1232
|
+
console.log(`[TileBridge] 🎵 AudioContext registered (${this.trackedAudioContexts.size} total)`);
|
|
1233
|
+
// If tile is currently muted, suspend immediately
|
|
1234
|
+
if (this.visibilityState.muted && ctx.state === 'running') {
|
|
1235
|
+
console.log('[TileBridge] 🔇 New AudioContext auto-suspended (tile is muted)');
|
|
1236
|
+
ctx.suspend().catch(() => { });
|
|
1237
|
+
}
|
|
1214
1238
|
}
|
|
1215
1239
|
/**
|
|
1216
|
-
*
|
|
1217
|
-
* Restores original muted state (elements that were muted before stay muted)
|
|
1240
|
+
* Unregister an AudioContext (e.g., when closing it)
|
|
1218
1241
|
*/
|
|
1219
|
-
|
|
1220
|
-
this.
|
|
1242
|
+
unregisterAudioContext(ctx) {
|
|
1243
|
+
this.trackedAudioContexts.delete(ctx);
|
|
1244
|
+
console.log(`[TileBridge] 🎵 AudioContext unregistered (${this.trackedAudioContexts.size} remaining)`);
|
|
1221
1245
|
}
|
|
1222
1246
|
/**
|
|
1223
1247
|
* Wait for ready state
|