diff --git a/apps/web/src/components/editor/timeline.tsx b/apps/web/src/components/editor/timeline.tsx index b627325e..117abc32 100644 --- a/apps/web/src/components/editor/timeline.tsx +++ b/apps/web/src/components/editor/timeline.tsx @@ -78,7 +78,6 @@ export function Timeline() { snappingEnabled, toggleSnapping, dragState, - justFinishedDragging, } = useTimelineStore(); const { mediaItems, addMediaItem } = useMediaStore(); const { activeProject } = useProjectStore(); @@ -92,6 +91,14 @@ export function Timeline() { const rulerRef = useRef(null); const [isInTimeline, setIsInTimeline] = useState(false); + // Track mouse down/up for distinguishing clicks from drag/resize ends + const mouseTrackingRef = useRef({ + isMouseDown: false, + downX: 0, + downY: 0, + downTime: 0, + }); + // Timeline zoom functionality const { zoomLevel, setZoomLevel, handleWheel } = useTimelineZoom({ containerRef: timelineRef, @@ -158,16 +165,69 @@ export function Timeline() { setCurrentSnapPoint(snapPoint); }, []); + // Track mouse down to distinguish real clicks from drag/resize ends + const handleTimelineMouseDown = useCallback((e: React.MouseEvent) => { + // Only track mouse down on timeline background areas (not elements) + const target = e.target as HTMLElement; + const isTimelineBackground = + !target.closest(".timeline-element") && + !playheadRef.current?.contains(target) && + !target.closest("[data-track-labels]"); + + if (isTimelineBackground) { + mouseTrackingRef.current = { + isMouseDown: true, + downX: e.clientX, + downY: e.clientY, + downTime: e.timeStamp, + }; + } + }, []); + // Timeline content click to seek handler const handleTimelineContentClick = useCallback( (e: React.MouseEvent) => { - // Don't seek if this was a selection box operation - if (isSelecting || justFinishedSelecting) { + const { isMouseDown, downX, downY, downTime } = mouseTrackingRef.current; + + // Reset mouse tracking + mouseTrackingRef.current = { + isMouseDown: false, + downX: 0, + downY: 0, + downTime: 0, + }; + + // Only process as click if we tracked a mouse down on timeline background + if (!isMouseDown) { + console.log( + JSON.stringify({ + ignoredClickWithoutMouseDown: true, + timeStamp: e.timeStamp, + }) + ); return; } - // Don't seek if we just finished dragging an element - if (justFinishedDragging) { + // Check if mouse moved significantly (indicates drag, not click) + const deltaX = Math.abs(e.clientX - downX); + const deltaY = Math.abs(e.clientY - downY); + const deltaTime = e.timeStamp - downTime; + + if (deltaX > 5 || deltaY > 5 || deltaTime > 500) { + console.log( + JSON.stringify({ + ignoredDragNotClick: true, + deltaX, + deltaY, + deltaTime, + timeStamp: e.timeStamp, + }) + ); + return; + } + + // Don't seek if this was a selection box operation + if (isSelecting || justFinishedSelecting) { return; } @@ -187,19 +247,6 @@ export function Timeline() { return; } - // MAIN FIX: Only seek on direct clicks to timeline background areas - // Check if the click is on the actual timeline background, not on any interactive elements - const target = e.target as HTMLElement; - const isTimelineBackground = - target.classList.contains("track-elements-container") || - target.closest("[data-ruler-area]") || - target.classList.contains("timeline-track-background"); - - if (!isTimelineBackground) { - clearSelectedElements(); - return; - } - // Clear selected elements when clicking empty timeline area console.log(JSON.stringify({ clearingSelectedElements: true })); clearSelectedElements(); @@ -256,7 +303,6 @@ export function Timeline() { clearSelectedElements, isSelecting, justFinishedSelecting, - justFinishedDragging, ] ); @@ -931,7 +977,10 @@ export function Timeline() {
{ + handleTimelineMouseDown(e); + handleSelectionMouseDown(e); + }} onClick={handleTimelineContentClick} ref={tracksContainerRef} > diff --git a/apps/web/src/hooks/use-timeline-element-resize.ts b/apps/web/src/hooks/use-timeline-element-resize.ts index 46765beb..f16ca8e2 100644 --- a/apps/web/src/hooks/use-timeline-element-resize.ts +++ b/apps/web/src/hooks/use-timeline-element-resize.ts @@ -186,12 +186,6 @@ export function useTimelineElementResize({ }; const handleResizeEnd = () => { - console.log( - JSON.stringify({ - resizeEnd: true, - timeStamp: Date.now(), - }) - ); setResizing(null); }; diff --git a/apps/web/src/stores/timeline-store.ts b/apps/web/src/stores/timeline-store.ts index c85f5bd2..9a2c7361 100644 --- a/apps/web/src/stores/timeline-store.ts +++ b/apps/web/src/stores/timeline-store.ts @@ -74,7 +74,6 @@ interface TimelineStore { clickOffsetTime: number; currentTime: number; }; - justFinishedDragging: boolean; setDragState: (dragState: Partial) => void; startDrag: ( elementId: string, @@ -231,8 +230,6 @@ export const useTimelineStore = create((set, get) => { // Snapping settings defaults snappingEnabled: true, - justFinishedDragging: false, - getSortedTracks: () => { const { _tracks } = get(); const tracksWithMain = ensureMainTrack(_tracks); @@ -941,12 +938,7 @@ export const useTimelineStore = create((set, get) => { clickOffsetTime: 0, currentTime: 0, }, - justFinishedDragging: true, }); - - setTimeout(() => { - set({ justFinishedDragging: false }); - }, 50); }, // Persistence methods