fix(studio): add preview audio mute controls (#853)

This commit is contained in:
Miguel Ángel
2026-05-15 03:37:53 +02:00
committed by GitHub
parent 9cc09fca83
commit d1e5ac2939
11 changed files with 338 additions and 27 deletions
@@ -24,7 +24,6 @@ import {
import {
normalizePreviewViewport,
autoHealMissingCompositionIds,
unmutePreviewMedia,
buildMissingCompositionElements,
} from "../lib/timelineIframeHelpers";
import { getTimelineElementIdentity } from "../lib/timelineElementHelpers";
@@ -41,6 +40,7 @@ interface UseTimelineSyncCallbacksParams {
setTimelineReady: (v: boolean) => void;
setIsPlaying: (v: boolean) => void;
attachIframeShortcutListeners: () => void;
applyPreviewAudioState: () => void;
}
export function useTimelineSyncCallbacks({
@@ -55,6 +55,7 @@ export function useTimelineSyncCallbacks({
setTimelineReady,
setIsPlaying,
attachIframeShortcutListeners,
applyPreviewAudioState,
}: UseTimelineSyncCallbacksParams) {
// Convert a runtime timeline message (from iframe postMessage) into TimelineElements
const processTimelineMessage = useCallback(
@@ -192,6 +193,7 @@ export function useTimelineSyncCallbacks({
processTimelineMessage(manifest);
}
enrichMissingCompositions();
applyPreviewAudioState();
if (usePlayerStore.getState().elements.length === 0 && doc) {
const els = parseTimelineFromDOM(doc, adapter.getDuration());
@@ -225,13 +227,14 @@ export function useTimelineSyncCallbacks({
enrichMissingCompositions,
syncTimelineElements,
attachIframeShortcutListeners,
applyPreviewAudioState,
iframeRef,
isRefreshingRef,
pendingSeekRef,
]);
const onIframeLoad = useCallback(() => {
unmutePreviewMedia(iframeRef.current);
applyPreviewAudioState();
if (probeIntervalRef.current) clearInterval(probeIntervalRef.current);
// Fast path: adapter already available (in-place reloads, cached compositions)
@@ -270,7 +273,7 @@ export function useTimelineSyncCallbacks({
}
window.removeEventListener("message", onMessage);
}, 5000) as unknown as ReturnType<typeof setInterval>;
}, [initializeAdapter, iframeRef, probeIntervalRef]);
}, [initializeAdapter, iframeRef, probeIntervalRef, applyPreviewAudioState]);
// Stable refs so mount-effect closures always call the latest version
const processTimelineMessageRef = { current: processTimelineMessage };