fix: time selection show handles
This commit is contained in:
Binary file not shown.
+53
-39
@@ -200,6 +200,8 @@
|
||||
markers,
|
||||
selectionMode,
|
||||
localSelectionTrackId,
|
||||
localSelectionStart,
|
||||
currentTime,
|
||||
localSelLeft,
|
||||
localSelRight,
|
||||
onTrackLaneMouseDown,
|
||||
@@ -294,7 +296,7 @@
|
||||
// 1. Draw Clip Layer Background & Border
|
||||
ctx.fillStyle = isClipSelected ? (track.color ? track.color + '44' : 'rgba(6, 182, 212, 0.30)') : (track.color ? track.color + '22' : 'rgba(6, 182, 212, 0.12)');
|
||||
ctx.strokeStyle = isClipSelected ? '#fbbf24' : (track.color || '#06b6d4');
|
||||
ctx.lineWidth = isClipSelected ? 3 : 1.5;
|
||||
ctx.lineWidth = isClipSelected ? 1 : 1.5;
|
||||
|
||||
const clipTop = 8;
|
||||
const clipHeight = height - 16;
|
||||
@@ -379,7 +381,7 @@
|
||||
ctx.fillStyle = 'rgba(245, 158, 11, 0.15)';
|
||||
ctx.fillRect(hlLeft, 0, hlWidth, height);
|
||||
ctx.strokeStyle = '#f59e0b';
|
||||
ctx.lineWidth = 1.5;
|
||||
ctx.lineWidth = 1;
|
||||
ctx.strokeRect(hlLeft, 0, hlWidth, height);
|
||||
}
|
||||
|
||||
@@ -537,7 +539,7 @@
|
||||
onClipDragStart(track.id, clickedClip.id, time - clickedClip.startTime, e.ctrlKey);
|
||||
}
|
||||
} else {
|
||||
onPlayheadSet(time, e.shiftKey);
|
||||
onPlayheadSet(time);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -564,7 +566,22 @@
|
||||
return;
|
||||
}
|
||||
|
||||
onPlayheadSet(time, e.shiftKey);
|
||||
if (e.shiftKey) {
|
||||
// Shift+click on track: extend LOCAL selection from current start to clicked position
|
||||
const prevStart = localSelectionStart !== null ? localSelectionStart : currentTime;
|
||||
const selS = Math.min(prevStart, time);
|
||||
const selE = Math.max(prevStart, time);
|
||||
setSelectionMode('local');
|
||||
setLocalSelectionTrackId(track.id);
|
||||
setLocalSelectionStart(selS);
|
||||
setLocalSelectionEnd(selE);
|
||||
setSelectionStart(selS);
|
||||
setSelectionEnd(selE);
|
||||
setCurrentTime(time);
|
||||
e.stopPropagation();
|
||||
return;
|
||||
}
|
||||
onPlayheadSet(time);
|
||||
if (onTrackLaneMouseDown) {
|
||||
onTrackLaneMouseDown(track.id, time, e);
|
||||
}
|
||||
@@ -609,7 +626,7 @@
|
||||
);
|
||||
};
|
||||
|
||||
const TempoTrackLane = ({ bpm, zoom, timelineWidth, onPlayheadSet, snapValue }) => {
|
||||
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) {
|
||||
// Click during playback: seek to position and continue playing
|
||||
setCurrentTime(time);
|
||||
stopAllPlayback();
|
||||
@@ -4582,9 +4581,15 @@
|
||||
setSelectionMode('global');
|
||||
rulerDragStartRef.current = time;
|
||||
isDraggingRulerRef.current = true;
|
||||
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, e.shiftKey);
|
||||
}
|
||||
handlePlayheadSet(time);
|
||||
};
|
||||
|
||||
// Global Ruler mousemove is tracked via document listener set up in useEffect
|
||||
@@ -6912,10 +6917,17 @@
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
{/* Global selection overlay for main session */}
|
||||
{selectionMode === 'global' && selLeft !== null && selRight !== null && selRight > selLeft && (
|
||||
<div className="absolute inset-0 pointer-events-none z-20"
|
||||
style={{ left: `${selLeft * zoom}px`, width: `${(selRight - selLeft) * zoom}px`, top: '40px' }}>
|
||||
<div className="w-full h-full bg-amber-500/10" style={{ borderLeft: '1px solid #f59e0b', borderRight: '1px solid #f59e0b' }}></div>
|
||||
</div>
|
||||
)}
|
||||
<div className="sticky top-10 z-35 flex h-[40px] border-b border-purple-500/30 bg-[#1a1a2e] shrink-0">
|
||||
<div className="flex-1 relative h-full overflow-hidden bg-[#1a1a2e]">
|
||||
<TempoTrackLane bpm={parseInt(bpm) || 120} zoom={zoom} timelineWidth={timelineWidth}
|
||||
onPlayheadSet={handlePlayheadSet} snapValue={snapValue} />
|
||||
onPlayheadSet={handlePlayheadSet} snapValue={snapValue} onRulerMouseDown={handleRulerMouseDown} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1 flex flex-col divide-y divide-[#141414] relative bg-[#111111] min-h-full">
|
||||
@@ -6943,6 +6955,8 @@
|
||||
snapValue={snapValue} bpm={bpm}
|
||||
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 @@
|
||||
<div className="absolute top-0 bottom-0 border-l border-r border-amber-500 bg-amber-500/10 z-20 selection-interactive-box cursor-grab active:cursor-grabbing"
|
||||
style={{ left: `${selLeft * zoom}px`, width: `${(selRight - selLeft) * zoom}px` }}
|
||||
onMouseDown={handleSelectionBodyDragStart}>
|
||||
<div className="absolute -left-1.5 top-0 bottom-0 w-3 bg-amber-500 hover:bg-amber-400 cursor-ew-resize flex items-center justify-center z-30"
|
||||
onMouseDown={e => handleHandleDragStart(e, 'left')}><div className="w-[1.5px] h-4 bg-zinc-950/70 rounded"></div></div>
|
||||
<div className="absolute -right-1.5 top-0 bottom-0 w-3 bg-amber-500 hover:bg-amber-400 cursor-ew-resize flex items-center justify-center z-30"
|
||||
onMouseDown={e => handleHandleDragStart(e, 'right')}><div className="w-[1.5px] h-4 bg-zinc-950/70 rounded"></div></div>
|
||||
<div className="absolute -left-[1px] top-0 bottom-0 w-[1px] bg-amber-500 hover:bg-amber-400 cursor-ew-resize z-30"
|
||||
onMouseDown={e => handleHandleDragStart(e, 'left')}></div>
|
||||
<div className="absolute -right-[1px] top-0 bottom-0 w-[1px] bg-amber-500 hover:bg-amber-400 cursor-ew-resize z-30"
|
||||
onMouseDown={e => handleHandleDragStart(e, 'right')}></div>
|
||||
</div>
|
||||
)}
|
||||
<div className="absolute top-0 bottom-0 w-[2px] bg-[#ef4444] z-20 pointer-events-none" style={{ left: `${playheadLeftPos}px` }}>
|
||||
|
||||
Reference in New Issue
Block a user