From acee68e8f52a270757bfa9c528b2c5caf6059c4c Mon Sep 17 00:00:00 2001 From: 3dtours Date: Sun, 19 Jul 2026 10:21:57 +0700 Subject: [PATCH] =?UTF-8?q?fix&feat:=20hi=E1=BB=83n=20th=E1=BB=8B=20tools?= =?UTF-8?q?=20ch=E1=BB=89nh=20s=E1=BB=ADa=20audioclip?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/templates/index.html | 56 +++++++++++++++++++++++++++++++++++++++- index.html | 56 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 110 insertions(+), 2 deletions(-) diff --git a/app/templates/index.html b/app/templates/index.html index e9abffb..1e9160b 100644 --- a/app/templates/index.html +++ b/app/templates/index.html @@ -668,7 +668,7 @@ }; // ── Sub-Tab Waveform Component (LOOP_EDITOR_2.md §1.2 & SUB_EDITOR.md) ── - const SubTabWaveform = ({ buffer, subTabId, activeTab, currentTime, selectionStart, selectionEnd, onSelectRange, onPlayheadSet, onContextMenu }) => { + const SubTabWaveform = ({ buffer, subTabId, activeTab, currentTime, selectionStart, selectionEnd, onSelectRange, onPlayheadSet, onContextMenu, activeTool }) => { const canvasRef = useRef(null); useEffect(() => { const canvas = canvasRef.current; @@ -742,6 +742,59 @@ const duration = buffer.duration; const startTime = (startX / rect.width) * duration; + // Tool-specific behavior + if (activeTool === 'grab') { + // Grab tool: move playhead on click/drag + onPlayheadSet(startTime); + + const handleMouseMove = (moveEvent) => { + const currentX = moveEvent.clientX - rect.left; + const currentTime = Math.max(0, Math.min(duration, (currentX / rect.width) * duration)); + onPlayheadSet(currentTime); + }; + + const handleMouseUp = () => { + document.removeEventListener('mousemove', handleMouseMove); + document.removeEventListener('mouseup', handleMouseUp); + }; + + document.addEventListener('mousemove', handleMouseMove); + document.addEventListener('mouseup', handleMouseUp); + return; + } + + if (activeTool === 'razor') { + // Razor tool: add a cut marker at click position + // For sub-tab, we can store cut points in the subTab state + onPlayheadSet(startTime); + showToast(`Cut point at ${formatTime(startTime)}`, 'info'); + return; + } + + if (activeTool === 'pen') { + // Pen tool: for volume automation drawing + // For now, just move playhead and show indicator + onPlayheadSet(startTime); + canvasRef.current.style.cursor = 'crosshair'; + + const handleMouseMove = (moveEvent) => { + const currentX = moveEvent.clientX - rect.left; + const currentTime = Math.max(0, Math.min(duration, (currentX / rect.width) * duration)); + onPlayheadSet(currentTime); + }; + + const handleMouseUp = () => { + document.removeEventListener('mousemove', handleMouseMove); + document.removeEventListener('mouseup', handleMouseUp); + canvasRef.current.style.cursor = 'crosshair'; + }; + + document.addEventListener('mousemove', handleMouseMove); + document.addEventListener('mouseup', handleMouseUp); + return; + } + + // Select tool (default): drag to select range onSelectRange(startTime, startTime); onPlayheadSet(startTime); @@ -4439,6 +4492,7 @@ buffer={st.buffer} subTabId={st.id} activeTab={activeTab} + activeTool={activeTool} currentTime={st.currentTime} selectionStart={st.selectionStart} selectionEnd={st.selectionEnd} diff --git a/index.html b/index.html index e9abffb..1e9160b 100644 --- a/index.html +++ b/index.html @@ -668,7 +668,7 @@ }; // ── Sub-Tab Waveform Component (LOOP_EDITOR_2.md §1.2 & SUB_EDITOR.md) ── - const SubTabWaveform = ({ buffer, subTabId, activeTab, currentTime, selectionStart, selectionEnd, onSelectRange, onPlayheadSet, onContextMenu }) => { + const SubTabWaveform = ({ buffer, subTabId, activeTab, currentTime, selectionStart, selectionEnd, onSelectRange, onPlayheadSet, onContextMenu, activeTool }) => { const canvasRef = useRef(null); useEffect(() => { const canvas = canvasRef.current; @@ -742,6 +742,59 @@ const duration = buffer.duration; const startTime = (startX / rect.width) * duration; + // Tool-specific behavior + if (activeTool === 'grab') { + // Grab tool: move playhead on click/drag + onPlayheadSet(startTime); + + const handleMouseMove = (moveEvent) => { + const currentX = moveEvent.clientX - rect.left; + const currentTime = Math.max(0, Math.min(duration, (currentX / rect.width) * duration)); + onPlayheadSet(currentTime); + }; + + const handleMouseUp = () => { + document.removeEventListener('mousemove', handleMouseMove); + document.removeEventListener('mouseup', handleMouseUp); + }; + + document.addEventListener('mousemove', handleMouseMove); + document.addEventListener('mouseup', handleMouseUp); + return; + } + + if (activeTool === 'razor') { + // Razor tool: add a cut marker at click position + // For sub-tab, we can store cut points in the subTab state + onPlayheadSet(startTime); + showToast(`Cut point at ${formatTime(startTime)}`, 'info'); + return; + } + + if (activeTool === 'pen') { + // Pen tool: for volume automation drawing + // For now, just move playhead and show indicator + onPlayheadSet(startTime); + canvasRef.current.style.cursor = 'crosshair'; + + const handleMouseMove = (moveEvent) => { + const currentX = moveEvent.clientX - rect.left; + const currentTime = Math.max(0, Math.min(duration, (currentX / rect.width) * duration)); + onPlayheadSet(currentTime); + }; + + const handleMouseUp = () => { + document.removeEventListener('mousemove', handleMouseMove); + document.removeEventListener('mouseup', handleMouseUp); + canvasRef.current.style.cursor = 'crosshair'; + }; + + document.addEventListener('mousemove', handleMouseMove); + document.addEventListener('mouseup', handleMouseUp); + return; + } + + // Select tool (default): drag to select range onSelectRange(startTime, startTime); onPlayheadSet(startTime); @@ -4439,6 +4492,7 @@ buffer={st.buffer} subTabId={st.id} activeTab={activeTab} + activeTool={activeTool} currentTime={st.currentTime} selectionStart={st.selectionStart} selectionEnd={st.selectionEnd}