From 271f0583f48013c439296c4e9fe513b11c3a39cb Mon Sep 17 00:00:00 2001 From: 3dtours Date: Mon, 20 Jul 2026 16:25:46 +0700 Subject: [PATCH] fix: time selection show handles --- app/storage/sonicforge.db | Bin 45056 -> 45056 bytes app/templates/index.html | 106 +++++++++++++++++++++----------------- 2 files changed, 60 insertions(+), 46 deletions(-) diff --git a/app/storage/sonicforge.db b/app/storage/sonicforge.db index 8555087dd46ec80b86ee5dfe33c11a7535eb2bc4..0c44863f0c0eed579c1b81d68a3128a3a5c5eb0d 100644 GIT binary patch delta 1142 zcmb_bO>5LZ7~W*Xx`kz1D-@}eB?<~|)|n)mkBZn*D->D;yL%{7*2(0ZHa1@**+MPL zwjk(1Q0c)xAr!m*fc^o&tDbridg-ZWaS|*d9?U@oGCcD>?~~_wnb|!ScaO!lQ^Lf% zYxBay$EVTs4VxJn5X5BFBDSnqnjzbiGFbslB^ILCL1_PM+8=D6?7sTEHz|yEChzW5 zCohdusAFLS1k0qwOj%QzF54DXWuv7zjPiwaN*vz}^3QA%1}TB>QQOi@(JF%W>IBSv+_qL?{#8)IfuM@7g~z(j^-v0QiV+xzX4D;JLr z>%-b|ku>7Xa;K2@L-gTJyNIH2Hg;RM&=G|q6S-BI&8)5#5iV@CS}K*q>T;=eP+cC5 zkIhwAUv$Mvw{!pHYDFAL!H>E{ycOZ>e;G_oxsEg=<+4#6J_DLc4JjZ#@KavDI^Zyk z3EfPjnI}6^&c?qf^CV8gFsRRy2;!u^6oygLk5o=bQeJAinGkA78{n>Qq|yvl%!afT zdOaT=*m)%)LB9LF6u1>eyaaf6=!H2LWQcMUb3@k=Gjtuex=-Rw{zL9*jgukXg7~59 z!6H`(dY;EyHb@YFw-_+4vvUr4gVK=PWF>_dcp;5@T;3x#cwBy^z3_P9k<{-ueg##e z#^8Jy?Q95j#E<@0v_FzzM+3+FJK4Q|M9b3lvl;a4HnH=8^o8&IB|Tp&o3Hl|2211o jx&Qb&nq8~fQK@!XI~tCoPqn68?h1vklQ=wmbGiN#a^zc{ delta 519 zcma)&y-EW?6oq$IK{gP^*rZTG3L%1w&g|^W?xID+Ry%`@h4ZslQX~<7*fPlz7>VK& z*eSv6lh|6N&^A>XJJ&qHHWv;DKE87YGj}j^N1Mod+&V_y$K`cxJF+~6g!{z!03Rd3CUjWA)t1+g|^B;ec-Mf1pX5Qm8} zIYKMjX?K^WdE4u@4fJlVlD*rzd)w~Cn#DYnp%psh0TV&aQ$_( { + const TempoTrackLane = ({ bpm, zoom, timelineWidth, onPlayheadSet, snapValue, onRulerMouseDown }) => { const canvasRef = useRef(null); useEffect(() => { @@ -705,7 +722,15 @@ const rect = canvasRef.current.getBoundingClientRect(); const x = e.clientX - rect.left + scrollLeft; const time = Math.max(0, x / zoom); - onPlayheadSet(time, e.shiftKey); + if (e.shiftKey) { + // Shift+click on tempo track: extend global selection from currentTime to clicked position + if (onRulerMouseDown) onRulerMouseDown({ ...e, shiftKey: true }); + else onPlayheadSet(time); + } else { + // Click on tempo track: set playhead and start global selection point + if (onRulerMouseDown) onRulerMouseDown(e); + else onPlayheadSet(time); + } e.stopPropagation(); }} /> @@ -4519,35 +4544,9 @@ document.addEventListener('mouseup', handleMouseUp); }; - // ── Playhead set with seek+play & shift+click selection ── + // ── Playhead set with seek+play ── const handlePlayheadSet = (time, shiftKey) => { - if (shiftKey) { - // Shift+click: extend selection from currentTime to clicked position - const selStart = Math.min(currentTime, time); - const selEnd = Math.max(currentTime, time); - setSelectionStart(selStart); - setSelectionEnd(selEnd); - setSelectionMode('global'); - clearLocalSelection(); - if (isLoopingSelection) { - // If looping, restart loop from new selection start - stopAllPlayback(); - setCurrentTime(selStart); - if (isPlaying) { - setTimeout(() => { - startOffsetTimeRef.current = selStart; - startAudioTimeRef.current = getAudioContext().currentTime; - startTrackPlayback(selStart); - setIsPlaying(true); - }, 50); - } - } else if (isPlaying) { - // Continue playing, just update the playhead visually - setCurrentTime(time); - } else { - setCurrentTime(time); - } - } else if (isPlaying) { + if (isPlaying) { // Click during playback: seek to position and continue playing setCurrentTime(time); stopAllPlayback(); @@ -4582,12 +4581,18 @@ setSelectionMode('global'); rulerDragStartRef.current = time; isDraggingRulerRef.current = true; - setSelectionStart(time); - setSelectionEnd(time); - handlePlayheadSet(time, e.shiftKey); + if (e.shiftKey) { + // Shift+click on ruler: extend global selection from currentTime to clicked position + setSelectionStart(Math.min(currentTime, time)); + setSelectionEnd(Math.max(currentTime, time)); + } else { + setSelectionStart(time); + setSelectionEnd(time); + } + handlePlayheadSet(time); }; - // Global Ruler mousemove is tracked via document listener set up in useEffect + // Global Ruler mousemove is tracked via document listener set up in useEffect useEffect(() => { const handleMouseMove = (e) => { if (!isDraggingRulerRef.current) return; @@ -6912,10 +6917,17 @@ })} + {/* Global selection overlay for main session */} + {selectionMode === 'global' && selLeft !== null && selRight !== null && selRight > selLeft && ( +
+
+
+ )}
+ onPlayheadSet={handlePlayheadSet} snapValue={snapValue} onRulerMouseDown={handleRulerMouseDown} />
@@ -6941,9 +6953,11 @@ onSplitTrackAtTime={handleSplitTrackAtTime} onEditClipInSubTab={handleEditClipInSubTab} snapValue={snapValue} bpm={bpm} - selectionMode={selectionMode} - localSelectionTrackId={localSelectionTrackId} - localSelLeft={localSelectionStart !== null && localSelectionEnd !== null ? Math.min(localSelectionStart, localSelectionEnd) : null} + selectionMode={selectionMode} + localSelectionTrackId={localSelectionTrackId} + localSelectionStart={localSelectionStart} + currentTime={currentTime} + localSelLeft={localSelectionStart !== null && localSelectionEnd !== null ? Math.min(localSelectionStart, localSelectionEnd) : null} localSelRight={localSelectionStart !== null && localSelectionEnd !== null ? Math.max(localSelectionStart, localSelectionEnd) : null} /> {track.buffer && (
@@ -6965,10 +6979,10 @@
-
handleHandleDragStart(e, 'left')}>
-
handleHandleDragStart(e, 'right')}>
+
handleHandleDragStart(e, 'left')}>
+
handleHandleDragStart(e, 'right')}>
)}