fix: lỗi alt-click drag nhân bản

This commit is contained in:
2026-07-18 21:53:51 +07:00
parent 39d222126e
commit 1364cbc34b
+50 -11
View File
@@ -363,7 +363,7 @@
canvasRef.current.style.cursor = isOverClip ? 'cell' : 'not-allowed'; canvasRef.current.style.cursor = isOverClip ? 'cell' : 'not-allowed';
} else { } else {
// select tool // select tool
canvasRef.current.style.cursor = (isOverClip && e.altKey) ? 'grab' : 'crosshair'; canvasRef.current.style.cursor = (isOverClip && (e.altKey || e.ctrlKey)) ? 'grab' : 'crosshair';
} }
}} }}
onMouseDown={(e) => { onMouseDown={(e) => {
@@ -401,7 +401,7 @@
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
if (onClipDragStart) { if (onClipDragStart) {
onClipDragStart(track.id, clickedClip.id, time - clickedClip.startTime); onClipDragStart(track.id, clickedClip.id, time - clickedClip.startTime, e.ctrlKey);
} }
} else { } else {
onPlayheadSet(time); onPlayheadSet(time);
@@ -409,12 +409,12 @@
return; return;
} }
// Check for click drag clip (no Ctrl key required if select tool is in fallback ctrl-mode) // Check for click drag clip (Alt to move, Ctrl to duplicate)
if (clickedClip && e.ctrlKey) { if (clickedClip && (e.altKey || e.ctrlKey)) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
if (onClipDragStart) { if (onClipDragStart) {
onClipDragStart(track.id, clickedClip.id, time - clickedClip.startTime); onClipDragStart(track.id, clickedClip.id, time - clickedClip.startTime, e.ctrlKey);
} }
return; return;
} }
@@ -1710,25 +1710,64 @@
const captureTrackSnapshotRef = useRef(null); const captureTrackSnapshotRef = useRef(null);
captureTrackSnapshotRef.current = captureTrackSnapshot; captureTrackSnapshotRef.current = captureTrackSnapshot;
const handleClipDragStart = (trackId, clipId, clickOffset) => { const handleClipDragStart = (trackId, clipId, clickOffset, isDuplicate = false) => {
const track = tracks.find(t => t.id === trackId); const track = tracks.find(t => t.id === trackId);
if (!track) return; if (!track) return;
const clips = track.clips && track.clips.length > 0 ? track.clips : (track.buffer ? [{ const existingClips = track.clips && track.clips.length > 0 ? track.clips : (track.buffer ? [{
id: 'default', id: 'default_' + track.id,
buffer: track.buffer, buffer: track.buffer,
startTime: track.startTime || 0, startTime: track.startTime || 0,
name: track.name name: track.name
}] : []); }] : []);
const clip = clips.find(c => c.id === clipId); const clip = existingClips.find(c => c.id === clipId || (clipId === 'default' && c.id === 'default_' + track.id));
if (!clip) return; if (!clip) return;
const beforeSnap = captureTrackSnapshot(trackId); const beforeSnap = captureTrackSnapshot(trackId);
let targetClipId = clip.id;
if (isDuplicate) {
const cloneId = clip.id + '_copy_' + Date.now();
const clone = {
...clip,
id: cloneId,
name: clip.name + ' (Copy)'
};
setTracks(prev => prev.map(t => {
if (t.id === trackId) {
const newClips = [...existingClips, clone];
return {
...t,
clips: newClips,
buffer: newClips[0].buffer,
startTime: newClips[0].startTime,
name: newClips[0].name
};
}
return t;
}));
targetClipId = cloneId;
} else {
if (!track.clips || track.clips.length === 0) {
setTracks(prev => prev.map(t => {
if (t.id === trackId) {
return {
...t,
clips: existingClips
};
}
return t;
}));
}
}
setDraggedClip({ setDraggedClip({
trackId: trackId, trackId: trackId,
clipId: clipId, clipId: targetClipId,
clickOffset: clickOffset, clickOffset: clickOffset,
buffer: clip.buffer, buffer: clip.buffer,
name: clip.name, name: clip.name,
@@ -2789,7 +2828,7 @@
<button <button
onClick={() => { setActiveTool('select'); showToast('Công cụ chọn (Select Tool) đã kích hoạt.', 'info'); }} onClick={() => { setActiveTool('select'); showToast('Công cụ chọn (Select Tool) đã kích hoạt.', 'info'); }}
className={`p-1 rounded transition text-xs flex items-center justify-center ${activeTool === 'select' ? 'bg-cyan-950/80 text-cyan-400 border border-cyan-800/50 font-bold' : 'text-zinc-400 hover:bg-zinc-800 border border-transparent'}`} className={`p-1 rounded transition text-xs flex items-center justify-center ${activeTool === 'select' ? 'bg-cyan-950/80 text-cyan-400 border border-cyan-800/50 font-bold' : 'text-zinc-400 hover:bg-zinc-800 border border-transparent'}`}
title="Select Tool: Chọn khoảng, Đặt playhead (Giữ Ctrl kéo để di chuyển nhanh clip)" title="Select Tool: Chọn khoảng, Đặt playhead (Alt+Kéo để di chuyển clip, Ctrl+Kéo để nhân bản)"
> >
<i data-lucide="mouse-pointer" className="w-3 h-3"></i> <i data-lucide="mouse-pointer" className="w-3 h-3"></i>
</button> </button>