fix: sub-tab ruler drag creates local selection, separate from main

- Add isDraggingSubTabRef/subTabDragStartRef for section-tab drag
- Ctrl+Click on sub-tab ruler clears sub-tab selection
- Sub-tab mousedown: set playhead + start drag
- Sub-tab mousemove/mouseup: update st.selectionStart/End locally
- Section-tab selection doesn't affect main session selection
This commit is contained in:
2026-07-27 09:14:34 +07:00
parent ef891e9e04
commit dff2c81848
2 changed files with 33 additions and 3 deletions
+29
View File
@@ -7321,6 +7321,8 @@ const App = () => {
const rulerDragStartRef = useRef(null);
const rulerAnchorRef = useRef(null);
const isDraggingRulerRef = useRef(false);
const subTabDragStartRef = useRef(null);
const isDraggingSubTabRef = useRef(false);
const handlePlayPauseRef = useRef(null);
const currentTimeRef = useRef(currentTime);
currentTimeRef.current = currentTime;
@@ -10829,9 +10831,28 @@ const App = () => {
};
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', handleMouseUp);
// Sub-tab ruler drag (section/editor tabs)
const handleSubTabMove = e => {
if (!isDraggingSubTabRef.current) return;
const wrapper = timelineWrapperRef.current;
if (!wrapper) return;
const rect = wrapper.getBoundingClientRect();
const sl = wrapper.scrollLeft;
const raw = Math.max(0, (e.clientX - rect.left + sl) / zoom);
const time = snapValueRef.current !== 'free' ? snapTime(raw, snapValueRef.current, bpmRef.current) : raw;
const anchor = subTabDragStartRef.current ?? 0;
setSubTabs(prev => prev.map(s => s.id === activeTabRef.current ? { ...s, selectionStart: Math.min(anchor, time), selectionEnd: Math.max(anchor, time) } : s));
};
const handleSubTabUp = () => {
if (isDraggingSubTabRef.current) { isDraggingSubTabRef.current = false; subTabDragStartRef.current = null; }
};
document.addEventListener('mousemove', handleSubTabMove);
document.addEventListener('mouseup', handleSubTabUp);
return () => {
document.removeEventListener('mousemove', handleMouseMove);
document.removeEventListener('mouseup', handleMouseUp);
document.removeEventListener('mousemove', handleSubTabMove);
document.removeEventListener('mouseup', handleSubTabUp);
};
}, [zoom, maxDuration]);
@@ -16445,8 +16466,16 @@ const App = () => {
const sl = wrapper.scrollLeft;
const raw = Math.max(0, (e.clientX - rect.left + sl) / zoom);
const t = snapValue !== 'free' ? snapTime(raw, snapValue, bpm) : raw;
if (e.ctrlKey) {
e.preventDefault();
e.stopPropagation();
setSubTabs(prev => prev.map(s => s.id === activeTab ? { ...s, selectionStart: null, selectionEnd: null } : s));
return;
}
if (e.shiftKey) { e.preventDefault(); e.stopPropagation(); }
handlePlayheadSet(t);
subTabDragStartRef.current = t;
isDraggingSubTabRef.current = true;
},
scrollLeft: scrollLeft,
canvasRedrawCount: canvasRedrawCount