diff --git a/app/static/js/app.jsx b/app/static/js/app.jsx index 23a9ad0..12b71ff 100644 --- a/app/static/js/app.jsx +++ b/app/static/js/app.jsx @@ -3318,6 +3318,8 @@ const App = () => { const rulerAnchorRef = useRef(null); const isDraggingRulerRef = useRef(false); const handlePlayPauseRef = useRef(null); + const currentTimeRef = useRef(currentTime); + currentTimeRef.current = currentTime; // ── Keyboard Shortcuts ── const handleUndoRef = useRef(handleUndo); @@ -4881,18 +4883,16 @@ const App = () => { const handleWheel = e => { if (e.ctrlKey || e.metaKey) { e.preventDefault(); - const rect = timeline.getBoundingClientRect(); - const mouseXInViewport = e.clientX - rect.left; - const mouseXInCanvas = mouseXInViewport + timeline.scrollLeft; - const anchorTime = mouseXInCanvas / zoom; const zoomFactor = e.deltaY > 0 ? 0.9 : 1.1; setZoom(prevZoom => { let newZoom = prevZoom * zoomFactor; if (newZoom < minZoom) newZoom = minZoom; if (newZoom > 50000) newZoom = 50000; - const newMouseXInCanvas = anchorTime * newZoom; requestAnimationFrame(() => { - timeline.scrollLeft = newMouseXInCanvas - mouseXInViewport; + const centerTime = currentTimeRef.current; + const newCenterX = centerTime * newZoom; + const viewportWidth = timeline.clientWidth; + timeline.scrollLeft = newCenterX - viewportWidth / 2; }); return newZoom; }); @@ -4905,7 +4905,7 @@ const App = () => { passive: false }); return () => timeline.removeEventListener('wheel', handleWheel); - }, [zoom, minZoom, maxDuration, activeTab]); + }, [minZoom]); // ── Update Playhead ── const startSubTabPlayback = (st, offsetWallTime) => { diff --git a/app/static/js/app.precompiled.js b/app/static/js/app.precompiled.js index 23a9ad0..12b71ff 100644 --- a/app/static/js/app.precompiled.js +++ b/app/static/js/app.precompiled.js @@ -3318,6 +3318,8 @@ const App = () => { const rulerAnchorRef = useRef(null); const isDraggingRulerRef = useRef(false); const handlePlayPauseRef = useRef(null); + const currentTimeRef = useRef(currentTime); + currentTimeRef.current = currentTime; // ── Keyboard Shortcuts ── const handleUndoRef = useRef(handleUndo); @@ -4881,18 +4883,16 @@ const App = () => { const handleWheel = e => { if (e.ctrlKey || e.metaKey) { e.preventDefault(); - const rect = timeline.getBoundingClientRect(); - const mouseXInViewport = e.clientX - rect.left; - const mouseXInCanvas = mouseXInViewport + timeline.scrollLeft; - const anchorTime = mouseXInCanvas / zoom; const zoomFactor = e.deltaY > 0 ? 0.9 : 1.1; setZoom(prevZoom => { let newZoom = prevZoom * zoomFactor; if (newZoom < minZoom) newZoom = minZoom; if (newZoom > 50000) newZoom = 50000; - const newMouseXInCanvas = anchorTime * newZoom; requestAnimationFrame(() => { - timeline.scrollLeft = newMouseXInCanvas - mouseXInViewport; + const centerTime = currentTimeRef.current; + const newCenterX = centerTime * newZoom; + const viewportWidth = timeline.clientWidth; + timeline.scrollLeft = newCenterX - viewportWidth / 2; }); return newZoom; }); @@ -4905,7 +4905,7 @@ const App = () => { passive: false }); return () => timeline.removeEventListener('wheel', handleWheel); - }, [zoom, minZoom, maxDuration, activeTab]); + }, [minZoom]); // ── Update Playhead ── const startSubTabPlayback = (st, offsetWallTime) => { diff --git a/app/storage/sonicforge.db b/app/storage/sonicforge.db index 42eb543..dcb73ab 100644 Binary files a/app/storage/sonicforge.db and b/app/storage/sonicforge.db differ