fix(studio): seek slider respects effective timeline duration with appended blocks

The seek slider read duration from the player store, which was set from the
iframe adapter's getDuration() — only aware of the root composition's authored
data-duration. Appended sub-compositions (via Blocks panel) extend the timeline
but the slider stayed capped at the original duration.

Sync effectiveTimelineDuration (which accounts for all timeline elements) into
the player store, and prevent adapter callbacks from overwriting a larger
effective duration back down to the authored value.
This commit is contained in:
Miguel Ángel
2026-05-18 16:32:03 -04:00
parent 27efcd0f80
commit 43f0a2b2bb
3 changed files with 7 additions and 6 deletions
+4 -4
View File
@@ -84,6 +84,10 @@ export function StudioApp() {
: 0;
return Math.max(timelineDuration, maxEnd);
}, [timelineDuration, timelineElements]);
useEffect(() => {
if (effectiveTimelineDuration !== usePlayerStore.getState().duration)
usePlayerStore.getState().setDuration(effectiveTimelineDuration);
}, [effectiveTimelineDuration]);
const refreshPreviewDocumentVersion = useCallback(() => {
setPreviewDocumentVersion((v) => v + 1);
window.setTimeout(() => setPreviewDocumentVersion((v) => v + 1), 80);
@@ -235,11 +239,9 @@ export function StudioApp() {
openSourceForSelection: fileManager.openSourceForSelection,
selectSidebarTab: (tab: SidebarTab) => leftSidebarRef.current?.selectTab(tab),
});
domEditSelectionBridgeRef.current = domEditSession.domEditSelection;
clearDomSelectionRef.current = domEditSession.clearDomSelection;
handleDomEditElementDeleteRef.current = domEditSession.handleDomEditElementDelete;
useCaptionDetection({
projectId,
activeCompPath,
@@ -271,10 +273,8 @@ export function StudioApp() {
setConsoleErrors,
resetErrors: resetConsoleErrors,
} = useConsoleErrorCapture(previewIframe);
const [globalDragOver, setGlobalDragOver] = useState(false);
const dragCounterRef = useRef(0);
const { syncPreviewTimelineHotkey, syncPreviewHistoryHotkey } = appHotkeys;
const handlePreviewIframeRef = useCallback(
(iframe: HTMLIFrameElement | null) => {
@@ -99,7 +99,7 @@ export function useTimelinePlayer() {
if (
Number.isFinite(nextDuration) &&
(nextDuration ?? 0) > 0 &&
nextDuration !== state.duration
(nextDuration ?? 0) > state.duration
) {
setDuration(nextDuration ?? 0);
}
@@ -163,11 +163,12 @@ export function useTimelineSyncCallbacks({
// with the initial adapter seek on iframe load.
liveTime.notify(startTime);
const adapterDur = adapter.getDuration();
const storeDur = usePlayerStore.getState().duration;
if (
Number.isFinite(adapterDur) &&
adapterDur > 0 &&
adapterDur < 7200 &&
adapterDur !== usePlayerStore.getState().duration
adapterDur > storeDur
) {
setDuration(adapterDur);
}