diff --git a/.filesize-allowlist b/.filesize-allowlist index bffcc916b..693d19295 100644 --- a/.filesize-allowlist +++ b/.filesize-allowlist @@ -1 +1,2 @@ packages/studio/src/player/hooks/useTimelinePlayer.ts +packages/studio/src/hooks/useManifestPersistence.ts diff --git a/packages/studio/src/hooks/useManifestPersistence.ts b/packages/studio/src/hooks/useManifestPersistence.ts index 49b0450e9..187b1310f 100644 --- a/packages/studio/src/hooks/useManifestPersistence.ts +++ b/packages/studio/src/hooks/useManifestPersistence.ts @@ -77,6 +77,8 @@ export function useManifestPersistence({ options?: { forceFromDisk?: boolean; readFromDiskFirst?: boolean }, ) => Promise >(async () => {}); + const manifestBootstrappedRef = useRef(false); + const motionBootstrappedRef = useRef(false); const studioManualEditProjectRef = useRef(projectId); // Keep a ref to the latest projectId so async save callbacks always read the @@ -144,7 +146,13 @@ export function useManifestPersistence({ iframe: HTMLIFrameElement | null = previewIframeRef.current, options?: { forceFromDisk?: boolean; readFromDiskFirst?: boolean }, ) => { - const readFromDiskFirst = Boolean(options?.forceFromDisk || options?.readFromDiskFirst); + // Bootstrap from disk on first apply per session; explicit flag avoids + // re-reading disk after the user deletes all edits (async write race). + const needsBootstrap = !manifestBootstrappedRef.current; + if (needsBootstrap) manifestBootstrappedRef.current = true; + const readFromDiskFirst = Boolean( + options?.forceFromDisk || options?.readFromDiskFirst || needsBootstrap, + ); if (!readFromDiskFirst) { applyCurrentStudioManualEditsToPreview(iframe); return; @@ -210,7 +218,11 @@ export function useManifestPersistence({ iframe: HTMLIFrameElement | null = previewIframeRef.current, options?: { forceFromDisk?: boolean; readFromDiskFirst?: boolean }, ) => { - const readFromDiskFirst = Boolean(options?.forceFromDisk || options?.readFromDiskFirst); + const needsBootstrap = !motionBootstrappedRef.current; + if (needsBootstrap) motionBootstrappedRef.current = true; + const readFromDiskFirst = Boolean( + options?.forceFromDisk || options?.readFromDiskFirst || needsBootstrap, + ); if (!readFromDiskFirst) { applyCurrentStudioMotionToPreview(iframe); return; @@ -427,6 +439,7 @@ export function useManifestPersistence({ studioMotionManifestRef.current = emptyStudioMotionManifest(); studioMotionRevisionRef.current += 1; setStudioMotionRevision((revision) => revision + 1); + manifestBootstrappedRef.current = motionBootstrappedRef.current = false; }, [projectId]); // ── Listen for external file changes (HMR / SSE) ──