From 115ab2ac32b19bec7a384a3f61c62d29b1fa3c9e Mon Sep 17 00:00:00 2001 From: Etienne Lescot Date: Sun, 19 Jul 2026 09:09:21 +0200 Subject: [PATCH 1/2] perf(timeline): decouple playhead from ancestor re-renders so it tracks playback The timeline playhead read its position from `currentTime` React state, set from VideoEditor (a ~3300-line component) on every rAF tick of video playback and on every `seeking` event while dragging. Each tick forced a full re-render of VideoEditor + VideoPlayback + TimelineEditor before the playhead's DOM moved, so the visual position lagged behind actual video playback and felt sluggish while scrubbing during playback. - PlaybackCursor now reads the video element's currentTime directly via a `getPlaybackTimeMs` getter, in its own requestAnimationFrame loop and its own local `useState`. Only this small component re-renders per frame, independent of how long the ancestor tree's render takes. - Coalesce the `onTimeUpdate` React state commit (still used by everything else that reads `currentTime`) to at most once per animation frame via a new `createRafCoalescer` helper, so a burst of `seeking` events from a fast timeline drag doesn't force one state commit per event. Fixes #111 --- src/components/video-editor/VideoEditor.tsx | 11 +++ src/components/video-editor/VideoPlayback.tsx | 40 ++++---- .../video-editor/timeline/TimelineEditor.tsx | 47 ++++++++- .../videoPlayback/rafCoalescer.test.ts | 97 +++++++++++++++++++ .../videoPlayback/rafCoalescer.ts | 41 ++++++++ .../videoPlayback/videoEventHandlers.ts | 11 ++- 6 files changed, 225 insertions(+), 22 deletions(-) create mode 100644 src/components/video-editor/videoPlayback/rafCoalescer.test.ts create mode 100644 src/components/video-editor/videoPlayback/rafCoalescer.ts diff --git a/src/components/video-editor/VideoEditor.tsx b/src/components/video-editor/VideoEditor.tsx index b49197da4..b0a278c4c 100644 --- a/src/components/video-editor/VideoEditor.tsx +++ b/src/components/video-editor/VideoEditor.tsx @@ -1004,6 +1004,16 @@ export default function VideoEditor() { video.currentTime = time; } + // Reads the live playhead position directly off the