diff options
| author | Simon Orzel <simonorzel@gmail.com> | 2025-07-17 02:53:25 +0200 |
|---|---|---|
| committer | Simon Orzel <simonorzel@gmail.com> | 2025-07-17 02:53:25 +0200 |
| commit | 1505c1b12f516c65b6a3d076f0e9623a294031d6 (patch) | |
| tree | 3bf87f9358e24fcec719dd07c8975fb41f33aac4 /apps/web/src/components/editor/timeline/timeline-scroll-sync.tsx | |
| parent | 98b2103286f04d67db1d57f9e3330efa5d41fdb7 (diff) | |
| download | opencut-1505c1b12f516c65b6a3d076f0e9623a294031d6.tar.gz | |
feat: timeline changes
Diffstat (limited to 'apps/web/src/components/editor/timeline/timeline-scroll-sync.tsx')
| -rw-r--r-- | apps/web/src/components/editor/timeline/timeline-scroll-sync.tsx | 68 |
1 files changed, 13 insertions, 55 deletions
diff --git a/apps/web/src/components/editor/timeline/timeline-scroll-sync.tsx b/apps/web/src/components/editor/timeline/timeline-scroll-sync.tsx index 2318f977..473c6f3e 100644 --- a/apps/web/src/components/editor/timeline/timeline-scroll-sync.tsx +++ b/apps/web/src/components/editor/timeline/timeline-scroll-sync.tsx @@ -3,20 +3,16 @@ import { useEffect, useRef } from "react"; export interface TimelineScrollSyncProps { rulerScrollRef: React.RefObject<HTMLDivElement>; tracksScrollRef: React.RefObject<HTMLDivElement>; - trackLabelsScrollRef: React.RefObject<HTMLDivElement>; } export function useTimelineScrollSync({ rulerScrollRef, tracksScrollRef, - trackLabelsScrollRef, }: TimelineScrollSyncProps) { const isUpdatingRef = useRef(false); - const lastRulerSync = useRef(0); - const lastTracksSync = useRef(0); - const lastVerticalSync = useRef(0); + const lastSyncRef = useRef(0); - // --- Scroll synchronization effect --- + // --- Horizontal scroll synchronization between ruler and tracks --- useEffect(() => { const rulerViewport = rulerScrollRef.current?.querySelector( "[data-radix-scroll-area-viewport]" @@ -24,76 +20,38 @@ export function useTimelineScrollSync({ const tracksViewport = tracksScrollRef.current?.querySelector( "[data-radix-scroll-area-viewport]" ) as HTMLElement; - const trackLabelsViewport = trackLabelsScrollRef.current?.querySelector( - "[data-radix-scroll-area-viewport]" - ) as HTMLElement; if (!rulerViewport || !tracksViewport) return; - // Horizontal scroll synchronization between ruler and tracks + // Throttled scroll handlers for better performance const handleRulerScroll = () => { const now = Date.now(); - if (isUpdatingRef.current || now - lastRulerSync.current < 16) return; - lastRulerSync.current = now; + if (isUpdatingRef.current || now - lastSyncRef.current < 16) return; // 60fps throttling + lastSyncRef.current = now; + isUpdatingRef.current = true; tracksViewport.scrollLeft = rulerViewport.scrollLeft; isUpdatingRef.current = false; }; + const handleTracksScroll = () => { const now = Date.now(); - if (isUpdatingRef.current || now - lastTracksSync.current < 16) return; - lastTracksSync.current = now; + if (isUpdatingRef.current || now - lastSyncRef.current < 16) return; // 60fps throttling + lastSyncRef.current = now; + isUpdatingRef.current = true; rulerViewport.scrollLeft = tracksViewport.scrollLeft; isUpdatingRef.current = false; }; - rulerViewport.addEventListener("scroll", handleRulerScroll); - tracksViewport.addEventListener("scroll", handleTracksScroll); - - // Vertical scroll synchronization between track labels and tracks content - if (trackLabelsViewport) { - const handleTrackLabelsScroll = () => { - const now = Date.now(); - if (isUpdatingRef.current || now - lastVerticalSync.current < 16) - return; - lastVerticalSync.current = now; - isUpdatingRef.current = true; - tracksViewport.scrollTop = trackLabelsViewport.scrollTop; - isUpdatingRef.current = false; - }; - const handleTracksVerticalScroll = () => { - const now = Date.now(); - if (isUpdatingRef.current || now - lastVerticalSync.current < 16) - return; - lastVerticalSync.current = now; - isUpdatingRef.current = true; - trackLabelsViewport.scrollTop = tracksViewport.scrollTop; - isUpdatingRef.current = false; - }; - - trackLabelsViewport.addEventListener("scroll", handleTrackLabelsScroll); - tracksViewport.addEventListener("scroll", handleTracksVerticalScroll); - - return () => { - rulerViewport.removeEventListener("scroll", handleRulerScroll); - tracksViewport.removeEventListener("scroll", handleTracksScroll); - trackLabelsViewport.removeEventListener( - "scroll", - handleTrackLabelsScroll - ); - tracksViewport.removeEventListener( - "scroll", - handleTracksVerticalScroll - ); - }; - } + rulerViewport.addEventListener("scroll", handleRulerScroll, { passive: true }); + tracksViewport.addEventListener("scroll", handleTracksScroll, { passive: true }); return () => { rulerViewport.removeEventListener("scroll", handleRulerScroll); tracksViewport.removeEventListener("scroll", handleTracksScroll); }; - }, []); + }, [rulerScrollRef, tracksScrollRef]); return null; } |
