diff --git a/apps/desktop/src/routes/editor/Editor.tsx b/apps/desktop/src/routes/editor/Editor.tsx index 4842726fb4..2c7865b75b 100644 --- a/apps/desktop/src/routes/editor/Editor.tsx +++ b/apps/desktop/src/routes/editor/Editor.tsx @@ -365,7 +365,12 @@ function Inner() { setEditorState("playbackTime", payload.playhead_position / FPS); }); + let skipRenderFrameForConfigUpdate = false; + const emitRenderFrame = (time: number) => { + if (skipRenderFrameForConfigUpdate) { + return; + } if (!editorState.playing) { events.renderFrameEvent.emit({ frame_number: Math.max(Math.floor(time * FPS), 0), @@ -390,33 +395,6 @@ function Inner() { return editorState.playbackTime; }); - createEffect( - on( - () => [frameNumberToRender(), previewResolutionBase()], - ([number]) => { - if (editorState.playing) return; - renderFrame(number as number); - }, - { defer: false }, - ), - ); - - createEffect( - on(isExportMode, (exportMode, prevExportMode) => { - if (prevExportMode === true && exportMode === false) { - emitRenderFrame(frameNumberToRender()); - } - }), - ); - - createEffect( - on(isCropMode, (cropMode, prevCropMode) => { - if (prevCropMode === true && cropMode === false) { - emitRenderFrame(frameNumberToRender()); - } - }), - ); - const doConfigUpdate = async (time: number) => { const config = getPreviewProjectConfig(project, editorState); const frameNumber = Math.max(Math.floor(time * FPS), 0); @@ -441,6 +419,7 @@ function Inner() { throttledConfigUpdate(time); trailingConfigUpdate(time); }; + createEffect( on( () => { @@ -451,12 +430,43 @@ function Inner() { }; }, () => { + skipRenderFrameForConfigUpdate = true; + queueMicrotask(() => { + skipRenderFrameForConfigUpdate = false; + }); updateConfigAndRender(frameNumberToRender()); }, { defer: true }, ), ); + createEffect( + on( + () => [frameNumberToRender(), previewResolutionBase()], + ([number]) => { + if (editorState.playing) return; + renderFrame(number as number); + }, + { defer: false }, + ), + ); + + createEffect( + on(isExportMode, (exportMode, prevExportMode) => { + if (prevExportMode === true && exportMode === false) { + emitRenderFrame(frameNumberToRender()); + } + }), + ); + + createEffect( + on(isCropMode, (cropMode, prevCropMode) => { + if (prevCropMode === true && cropMode === false) { + emitRenderFrame(frameNumberToRender()); + } + }), + ); + const fullscreenMode = () => { if (isExportMode()) return "export" as const; return null; diff --git a/apps/desktop/src/routes/editor/Timeline/ClipTrack.tsx b/apps/desktop/src/routes/editor/Timeline/ClipTrack.tsx index 68c13f09e1..69559a25da 100644 --- a/apps/desktop/src/routes/editor/Timeline/ClipTrack.tsx +++ b/apps/desktop/src/routes/editor/Timeline/ClipTrack.tsx @@ -4,6 +4,7 @@ import { } from "@solid-primitives/event-listener"; import { cx } from "cva"; import { + batch, type ComponentProps, createEffect, createMemo, @@ -718,14 +719,16 @@ export function ClipTrack( initialStart, }); - setProject( - "timeline", - "segments", - i(), - "start", - clampedStart, - ); - setPreviewTime(prevDuration()); + batch(() => { + setProject( + "timeline", + "segments", + i(), + "start", + clampedStart, + ); + setPreviewTime(prevDuration()); + }); } const resumeHistory = projectHistory.pause(); @@ -822,17 +825,19 @@ export function ClipTrack( seg.start + minRecordedDuration, ); - setProject( - "timeline", - "segments", - i(), - "end", - clampedEnd, - ); - setPreviewTime( - prevDuration() + - (clampedEnd - seg.start) / seg.timescale, - ); + batch(() => { + setProject( + "timeline", + "segments", + i(), + "end", + clampedEnd, + ); + setPreviewTime( + prevDuration() + + (clampedEnd - seg.start) / seg.timescale, + ); + }); } const resumeHistory = projectHistory.pause();