@thewhateverapp/tile-sdk 0.12.14 → 0.12.15
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VideoPlayer.d.ts","sourceRoot":"","sources":["../../../src/react/overlay/VideoPlayer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAOZ,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"VideoPlayer.d.ts","sourceRoot":"","sources":["../../../src/react/overlay/VideoPlayer.tsx"],"names":[],"mappings":"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"}
|
|
@@ -46,10 +46,12 @@ function getVideoMetadataFromEnv() {
|
|
|
46
46
|
? parseFloat(process.env.NEXT_PUBLIC_VIDEO_DURATION)
|
|
47
47
|
: null,
|
|
48
48
|
title: process.env.NEXT_PUBLIC_VIDEO_TITLE || null,
|
|
49
|
-
// Default to
|
|
50
|
-
|
|
49
|
+
// Default to false for autoplay - wait for visibility message from parent
|
|
50
|
+
// This prevents offscreen tiles from playing in TikTok-style feeds
|
|
51
|
+
autoplay: process.env.NEXT_PUBLIC_VIDEO_AUTOPLAY === 'true',
|
|
51
52
|
// Default to true for loop (most video tiles loop)
|
|
52
53
|
loop: process.env.NEXT_PUBLIC_VIDEO_LOOP !== 'false',
|
|
54
|
+
// Default to true for muted - start muted, unmute on visibility
|
|
53
55
|
muted: process.env.NEXT_PUBLIC_VIDEO_MUTED !== 'false',
|
|
54
56
|
};
|
|
55
57
|
}
|
|
@@ -109,8 +111,10 @@ export function VideoPlayer({ controls = false, children, className = '', videoC
|
|
|
109
111
|
}, []);
|
|
110
112
|
// Get values from metadata
|
|
111
113
|
const src = metadata?.videoUrl || null;
|
|
112
|
-
|
|
113
|
-
//
|
|
114
|
+
// Default to false for autoplay - videos wait for visibility message from parent
|
|
115
|
+
// This prevents offscreen tiles from playing in TikTok-style feeds
|
|
116
|
+
const autoplay = metadata?.autoplay ?? false;
|
|
117
|
+
// Default to true for muted - videos start muted until visibility says otherwise
|
|
114
118
|
const muted = metadata?.muted ?? true;
|
|
115
119
|
const poster = metadata?.thumbnail || undefined;
|
|
116
120
|
// Default to loop enabled (videos almost always loop)
|
|
@@ -343,72 +347,64 @@ export function VideoPlayer({ controls = false, children, className = '', videoC
|
|
|
343
347
|
};
|
|
344
348
|
}, [onTimeUpdate, onCuePoint, cuePoints]);
|
|
345
349
|
// Visibility handling - play/pause AND mute/unmute based on tile visibility.
|
|
346
|
-
//
|
|
347
|
-
//
|
|
348
|
-
// IMPORTANT:
|
|
349
|
-
//
|
|
350
|
+
// Videos start paused and only play when parent sends visible: true.
|
|
351
|
+
// This enables TikTok-style feeds where only the active tile plays.
|
|
352
|
+
// IMPORTANT: Videos default to autoplay=false, muted=true.
|
|
353
|
+
// Parent controls playback via visibility messages.
|
|
350
354
|
useEffect(() => {
|
|
351
355
|
const video = videoRef.current;
|
|
352
|
-
if (!video
|
|
356
|
+
if (!video)
|
|
353
357
|
return;
|
|
354
358
|
try {
|
|
355
359
|
const bridge = getTileBridge();
|
|
356
360
|
// Handle visibility changes from parent (mobile app)
|
|
357
|
-
// Now includes muted state for atomic updates (no race conditions)
|
|
358
361
|
const unsubscribe = bridge.onVisibilityChange((visibilityState) => {
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
const shouldMute = visibilityState.muted ?? !visibilityState.visible;
|
|
362
|
-
if (visibilityState.visible && !shouldMute) {
|
|
363
|
-
// Tile became visible and should be unmuted - unmute and play
|
|
364
|
-
// Unmute first so audio starts with the video
|
|
362
|
+
if (visibilityState.visible) {
|
|
363
|
+
// Tile is visible - play video, unmute audio
|
|
365
364
|
video.muted = false;
|
|
366
365
|
video.play().catch(() => {
|
|
367
|
-
// If play fails (
|
|
366
|
+
// If unmuted play fails (browser policy), retry muted
|
|
368
367
|
video.muted = true;
|
|
369
368
|
video.play().catch(() => { });
|
|
370
369
|
});
|
|
371
370
|
}
|
|
372
|
-
else if (visibilityState.visible && shouldMute) {
|
|
373
|
-
// Tile is visible but should be muted (e.g., transitioning)
|
|
374
|
-
video.muted = true;
|
|
375
|
-
video.play().catch(() => { });
|
|
376
|
-
}
|
|
377
371
|
else {
|
|
378
|
-
// Tile
|
|
372
|
+
// Tile is hidden - pause video, mute audio
|
|
379
373
|
video.muted = true;
|
|
380
374
|
video.pause();
|
|
381
375
|
}
|
|
382
376
|
});
|
|
383
|
-
// Check initial visibility state
|
|
377
|
+
// Check initial visibility state
|
|
384
378
|
const initialState = bridge.getVisibilityState();
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
// If visible and unmuted on mount, unmute so sound plays
|
|
388
|
-
// This handles the race condition where the first tile loads visible
|
|
379
|
+
if (initialState.visible) {
|
|
380
|
+
// Visible on mount - start playing
|
|
389
381
|
video.muted = false;
|
|
390
|
-
// If unmuted autoplay fails, fall back to muted
|
|
391
382
|
video.play().catch(() => {
|
|
392
383
|
video.muted = true;
|
|
393
384
|
video.play().catch(() => { });
|
|
394
385
|
});
|
|
395
386
|
}
|
|
396
387
|
else {
|
|
397
|
-
//
|
|
388
|
+
// Not visible on mount - ensure paused and muted
|
|
398
389
|
video.muted = true;
|
|
399
|
-
|
|
400
|
-
video.pause();
|
|
401
|
-
}
|
|
390
|
+
video.pause();
|
|
402
391
|
}
|
|
403
392
|
return () => {
|
|
404
393
|
unsubscribe();
|
|
405
394
|
};
|
|
406
395
|
}
|
|
407
396
|
catch {
|
|
408
|
-
// Bridge not available (
|
|
409
|
-
//
|
|
397
|
+
// Bridge not available (standalone tile, not in feed)
|
|
398
|
+
// For standalone tiles, play with audio if visible
|
|
399
|
+
if (!document.hidden) {
|
|
400
|
+
video.muted = false;
|
|
401
|
+
video.play().catch(() => {
|
|
402
|
+
video.muted = true;
|
|
403
|
+
video.play().catch(() => { });
|
|
404
|
+
});
|
|
405
|
+
}
|
|
410
406
|
}
|
|
411
|
-
}, [
|
|
407
|
+
}, []);
|
|
412
408
|
const contextValue = {
|
|
413
409
|
state,
|
|
414
410
|
controls: { play, pause, toggle, seek, setVolume, setMuted },
|