@@ -2,6 +2,7 @@ import { snapTimeToFrame } from "@/constants/timeline-constants";
22import { DEFAULT_FPS , useProjectStore } from "@/stores/project-store" ;
33import { usePlaybackStore } from "@/stores/playback-store" ;
44import { useState , useEffect , useCallback , useRef } from "react" ;
5+ import { useEdgeAutoScroll } from "@/hooks/use-edge-auto-scroll" ;
56
67interface UseTimelinePlayheadProps {
78 currentTime : number ;
@@ -31,9 +32,6 @@ export function useTimelinePlayhead({
3132 // Ruler drag detection state
3233 const [ isDraggingRuler , setIsDraggingRuler ] = useState ( false ) ;
3334 const [ hasDraggedRuler , setHasDraggedRuler ] = useState ( false ) ;
34-
35- // Auto-scroll state during dragging
36- const autoScrollRef = useRef < number | null > ( null ) ;
3735 const lastMouseXRef = useRef < number > ( 0 ) ;
3836
3937 const playheadPosition =
@@ -117,59 +115,13 @@ export function useTimelinePlayhead({
117115 [ duration , zoomLevel , seek , rulerRef ]
118116 ) ;
119117
120- // Auto-scroll function during dragging
121- const performAutoScroll = useCallback ( ( ) => {
122- const rulerViewport = rulerScrollRef . current ;
123- const tracksViewport = tracksScrollRef . current ;
124-
125- if ( ! rulerViewport || ! tracksViewport || ! isScrubbing ) return ;
126-
127- const viewportRect = rulerViewport . getBoundingClientRect ( ) ;
128- const mouseX = lastMouseXRef . current ;
129- const mouseXRelative = mouseX - viewportRect . left ;
130-
131- const edgeThreshold = 100 ; // pixels from edge to start scrolling
132- const maxScrollSpeed = 15 ; // max pixels per frame
133- const viewportWidth = rulerViewport . clientWidth ;
134-
135- // Calculate timeline content boundaries
136- const timelineContentWidth = duration * 50 * zoomLevel ; // TIMELINE_CONSTANTS.PIXELS_PER_SECOND = 50
137- const scrollMax = Math . max ( 0 , timelineContentWidth - viewportWidth ) ;
138-
139- let scrollSpeed = 0 ;
140-
141- // Check if near left edge (and can scroll left)
142- if ( mouseXRelative < edgeThreshold && rulerViewport . scrollLeft > 0 ) {
143- const edgeDistance = Math . max ( 0 , mouseXRelative ) ;
144- const intensity = 1 - edgeDistance / edgeThreshold ;
145- scrollSpeed = - maxScrollSpeed * intensity ;
146- }
147- // Check if near right edge (and can scroll right, and haven't reached timeline end)
148- else if (
149- mouseXRelative > viewportWidth - edgeThreshold &&
150- rulerViewport . scrollLeft < scrollMax
151- ) {
152- const edgeDistance = Math . max (
153- 0 ,
154- viewportWidth - edgeThreshold - mouseXRelative
155- ) ;
156- const intensity = 1 - edgeDistance / edgeThreshold ;
157- scrollSpeed = maxScrollSpeed * intensity ;
158- }
159-
160- if ( scrollSpeed !== 0 ) {
161- const newScrollLeft = Math . max (
162- 0 ,
163- Math . min ( scrollMax , rulerViewport . scrollLeft + scrollSpeed )
164- ) ;
165- rulerViewport . scrollLeft = newScrollLeft ;
166- tracksViewport . scrollLeft = newScrollLeft ;
167- }
168-
169- if ( isScrubbing ) {
170- autoScrollRef . current = requestAnimationFrame ( performAutoScroll ) ;
171- }
172- } , [ isScrubbing , rulerScrollRef , tracksScrollRef , duration , zoomLevel ] ) ;
118+ useEdgeAutoScroll ( {
119+ isActive : isScrubbing ,
120+ getMouseClientX : ( ) => lastMouseXRef . current ,
121+ rulerScrollRef,
122+ tracksScrollRef,
123+ contentWidth : duration * 50 * zoomLevel ,
124+ } ) ;
173125
174126 // Mouse move/up event handlers
175127 useEffect ( ( ) => {
@@ -188,12 +140,6 @@ export function useTimelinePlayhead({
188140 if ( scrubTime !== null ) seek ( scrubTime ) ; // finalize seek
189141 setScrubTime ( null ) ;
190142
191- // Stop auto-scrolling
192- if ( autoScrollRef . current ) {
193- cancelAnimationFrame ( autoScrollRef . current ) ;
194- autoScrollRef . current = null ;
195- }
196-
197143 // Handle ruler click vs drag
198144 if ( isDraggingRuler ) {
199145 setIsDraggingRuler ( false ) ;
@@ -208,16 +154,12 @@ export function useTimelinePlayhead({
208154 window . addEventListener ( "mousemove" , onMouseMove ) ;
209155 window . addEventListener ( "mouseup" , onMouseUp ) ;
210156
211- // Start auto-scrolling
212- autoScrollRef . current = requestAnimationFrame ( performAutoScroll ) ;
157+ // Edge auto-scroll is handled by useEdgeAutoScroll
213158
214159 return ( ) => {
215160 window . removeEventListener ( "mousemove" , onMouseMove ) ;
216161 window . removeEventListener ( "mouseup" , onMouseUp ) ;
217- if ( autoScrollRef . current ) {
218- cancelAnimationFrame ( autoScrollRef . current ) ;
219- autoScrollRef . current = null ;
220- }
162+ // nothing to cleanup for edge auto scroll
221163 } ;
222164 } , [
223165 isScrubbing ,
@@ -226,7 +168,7 @@ export function useTimelinePlayhead({
226168 handleScrub ,
227169 isDraggingRuler ,
228170 hasDraggedRuler ,
229- performAutoScroll ,
171+ // edge auto scroll hook is independent
230172 ] ) ;
231173
232174 // --- Playhead auto-scroll effect (only during playback) ---
0 commit comments