summaryrefslogtreecommitdiff
path: root/apps/web/src/components/editor/timeline/timeline-scroll-sync.tsx
diff options
context:
space:
mode:
authorSimon Orzel <simonorzel@gmail.com>2025-07-17 02:53:25 +0200
committerSimon Orzel <simonorzel@gmail.com>2025-07-17 02:53:25 +0200
commit1505c1b12f516c65b6a3d076f0e9623a294031d6 (patch)
tree3bf87f9358e24fcec719dd07c8975fb41f33aac4 /apps/web/src/components/editor/timeline/timeline-scroll-sync.tsx
parent98b2103286f04d67db1d57f9e3330efa5d41fdb7 (diff)
downloadopencut-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.tsx68
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;
}