@thewhateverapp/tile-sdk 0.12.10 → 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,6 +59,9 @@ export declare class TileBridge {
|
|
|
59
59
|
private tokenExpiresAt;
|
|
60
60
|
private keyboardState;
|
|
61
61
|
private visibilityState;
|
|
62
|
+
private mediaOriginalMutedState;
|
|
63
|
+
private trackedAudioContexts;
|
|
64
|
+
private audioContextPatched;
|
|
62
65
|
private baselineViewportHeight;
|
|
63
66
|
private keyboardDetectionEnabled;
|
|
64
67
|
private lastReportedKeyboardState;
|
|
@@ -109,6 +112,18 @@ export declare class TileBridge {
|
|
|
109
112
|
* Now includes muted state for atomic updates to prevent race conditions
|
|
110
113
|
*/
|
|
111
114
|
private handleVisibility;
|
|
115
|
+
/**
|
|
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)
|
|
119
|
+
*/
|
|
120
|
+
private muteAllMedia;
|
|
121
|
+
/**
|
|
122
|
+
* Unmute all audio sources when tile becomes visible
|
|
123
|
+
* - Unmutes <video> and <audio> elements (restoring original state)
|
|
124
|
+
* - Resumes all registered AudioContexts
|
|
125
|
+
*/
|
|
126
|
+
private unmuteAllMedia;
|
|
112
127
|
private sendToParent;
|
|
113
128
|
/**
|
|
114
129
|
* Request to navigate to full page view
|
|
@@ -321,6 +336,27 @@ export declare class TileBridge {
|
|
|
321
336
|
* @returns Unsubscribe function
|
|
322
337
|
*/
|
|
323
338
|
onVisibilityChange(handler: (state: VisibilityState) => void): () => void;
|
|
339
|
+
/**
|
|
340
|
+
* Register an AudioContext for mandatory muting when tile goes offscreen.
|
|
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.
|
|
346
|
+
*
|
|
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
|
|
354
|
+
*/
|
|
355
|
+
registerAudioContext(ctx: AudioContext): void;
|
|
356
|
+
/**
|
|
357
|
+
* Unregister an AudioContext (e.g., when closing it)
|
|
358
|
+
*/
|
|
359
|
+
unregisterAudioContext(ctx: AudioContext): void;
|
|
324
360
|
/**
|
|
325
361
|
* Wait for ready state
|
|
326
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,sBAAsB,CAAa;IAC3C,OAAO,CAAC,wBAAwB,CAAkB;IAClD,OAAO,CAAC,yBAAyB,CAAuE;IACxG,OAAO,CAAC,qBAAqB,CAA8C;IAC3E,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAO;IAC1C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAO;IAGnC,OAAO,CAAC,YAAY,CAAkB;IACtC,OAAO,CAAC,cAAc,CAAwB;gBAElC,cAAc,GAAE,MAAkC,EAAE,MAAM,CAAC,EAAE,UAAU;IA6BnF,OAAO,CAAC,UAAU;IAoClB;;;OAGG;IACH,OAAO,CAAC,2BAA2B;IAwDnC;;OAEG;IACH,OAAO,CAAC,qBAAqB;IA0C7B;;OAEG;IACH,OAAO,CAAC,aAAa;IA+BrB;;OAEG;IACH,OAAO,CAAC,cAAc;IAgCtB;;OAEG;IACH,OAAO,CAAC,cAAc;IAuBtB,OAAO,CAAC,aAAa;IA6DrB,OAAO,CAAC,YAAY;IAgBpB,OAAO,CAAC,cAAc;IAUtB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,oBAAoB;IAoB5B;;OAEG;IACH,OAAO,CAAC,WAAW;IAuBnB;;OAEG;IACH,OAAO,CAAC,cAAc;IAmBtB;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;
|
|
1
|
+
{"version":3,"file":"TileBridge.d.ts","sourceRoot":"","sources":["../../src/bridge/TileBridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,6 +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
|
+
// Store original muted state of media elements to restore when unmuting
|
|
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;
|
|
21
26
|
// VisualViewport tracking for keyboard detection (Plan A)
|
|
22
27
|
this.baselineViewportHeight = 0;
|
|
23
28
|
this.keyboardDetectionEnabled = false;
|
|
@@ -407,11 +412,93 @@ export class TileBridge {
|
|
|
407
412
|
if (this.isDevelopment() || this.isPreview()) {
|
|
408
413
|
console.log('[TileBridge] 👁️ Received visibility state', this.visibilityState);
|
|
409
414
|
}
|
|
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();
|
|
421
|
+
}
|
|
410
422
|
// Emit if visibility OR muted state changed
|
|
411
423
|
if (wasVisible !== this.visibilityState.visible || wasMuted !== this.visibilityState.muted) {
|
|
412
424
|
this.emitEvent('visibility:update', this.visibilityState);
|
|
413
425
|
}
|
|
414
426
|
}
|
|
427
|
+
/**
|
|
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
|
+
*/
|
|
432
|
+
muteAllMedia() {
|
|
433
|
+
if (typeof document === 'undefined')
|
|
434
|
+
return;
|
|
435
|
+
// 1. Mute all HTML media elements
|
|
436
|
+
const mediaElements = document.querySelectorAll('video, audio');
|
|
437
|
+
let mutedCount = 0;
|
|
438
|
+
mediaElements.forEach((element) => {
|
|
439
|
+
const media = element;
|
|
440
|
+
// Store original muted state if not already stored
|
|
441
|
+
if (!this.mediaOriginalMutedState.has(media)) {
|
|
442
|
+
this.mediaOriginalMutedState.set(media, media.muted);
|
|
443
|
+
}
|
|
444
|
+
if (!media.muted) {
|
|
445
|
+
media.muted = true;
|
|
446
|
+
mutedCount++;
|
|
447
|
+
}
|
|
448
|
+
});
|
|
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)`);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Unmute all audio sources when tile becomes visible
|
|
465
|
+
* - Unmutes <video> and <audio> elements (restoring original state)
|
|
466
|
+
* - Resumes all registered AudioContexts
|
|
467
|
+
*/
|
|
468
|
+
unmuteAllMedia() {
|
|
469
|
+
if (typeof document === 'undefined')
|
|
470
|
+
return;
|
|
471
|
+
// 1. Unmute HTML media elements
|
|
472
|
+
const mediaElements = document.querySelectorAll('video, audio');
|
|
473
|
+
let unmutedCount = 0;
|
|
474
|
+
mediaElements.forEach((element) => {
|
|
475
|
+
const media = element;
|
|
476
|
+
// Restore original muted state (or unmute if we don't have stored state)
|
|
477
|
+
const originalMuted = this.mediaOriginalMutedState.get(media);
|
|
478
|
+
if (originalMuted === false || originalMuted === undefined) {
|
|
479
|
+
// Only unmute if it wasn't originally muted
|
|
480
|
+
if (media.muted) {
|
|
481
|
+
media.muted = false;
|
|
482
|
+
unmutedCount++;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
// Clear stored state
|
|
486
|
+
this.mediaOriginalMutedState.delete(media);
|
|
487
|
+
});
|
|
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)`);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
415
502
|
sendToParent(message) {
|
|
416
503
|
if (typeof window === 'undefined' || !window.parent)
|
|
417
504
|
return;
|
|
@@ -1121,6 +1208,41 @@ export class TileBridge {
|
|
|
1121
1208
|
onVisibilityChange(handler) {
|
|
1122
1209
|
return this.on('visibility:update', handler);
|
|
1123
1210
|
}
|
|
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.
|
|
1214
|
+
/**
|
|
1215
|
+
* Register an AudioContext for mandatory muting when tile goes offscreen.
|
|
1216
|
+
*
|
|
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.
|
|
1221
|
+
*
|
|
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
|
|
1229
|
+
*/
|
|
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
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
/**
|
|
1240
|
+
* Unregister an AudioContext (e.g., when closing it)
|
|
1241
|
+
*/
|
|
1242
|
+
unregisterAudioContext(ctx) {
|
|
1243
|
+
this.trackedAudioContexts.delete(ctx);
|
|
1244
|
+
console.log(`[TileBridge] 🎵 AudioContext unregistered (${this.trackedAudioContexts.size} remaining)`);
|
|
1245
|
+
}
|
|
1124
1246
|
/**
|
|
1125
1247
|
* Wait for ready state
|
|
1126
1248
|
*
|