diff --git a/app/static/js/app.jsx b/app/static/js/app.jsx index 378a166..affcd2e 100644 --- a/app/static/js/app.jsx +++ b/app/static/js/app.jsx @@ -7136,6 +7136,10 @@ const App = () => { const handleAISend = async () => { const prompt = aiPrompt.trim(); if (!prompt) { showToast('Vui lòng nhập nội dung prompt.', 'warning'); return; } + if (window.DAWCommandDispatcher) { + window.DAWCommandDispatcher.currentSelectedTrackId = selectedTrackId; + window.DAWCommandDispatcher.currentTracks = tracks; + } setAiProcessing(true); setAiActionLog(prev => [...prev, { type: 'status', text: ` ⏳ Đang gửi prompt đến AI...`, time: Date.now() }]); try { @@ -7509,8 +7513,10 @@ const App = () => { return { success: true, start: parseFloat(start.toFixed(3)), end: parseFloat(end.toFixed(3)), length: parseFloat((end - start).toFixed(3)) }; }, cutAudio: (args) => { - const tid = args.track_id || selectedTrackId; - const track = tracks.find(t => t.id === tid); + const currentTracks = window.DAWCommandDispatcher?.currentTracks || tracks; + const currentSelTrackId = window.DAWCommandDispatcher?.currentSelectedTrackId || selectedTrackId; + const tid = args.track_id || currentSelTrackId; + const track = currentTracks.find(t => t.id === String(tid)); if (!track) return { success: false, error: 'Track not found' }; if (!track.buffer) return { success: false, error: 'Track has no audio buffer' }; const barDur = 60 / parseInt(bpm || 120) * 4; @@ -7545,7 +7551,7 @@ const App = () => { } const newId = 'track_cut_' + Date.now(); const colors = ['#0f766e', '#1d4ed8', '#701a75', '#a21caf', '#b45309']; - const color = colors[tracks.length % colors.length]; + const color = colors[currentTracks.length % colors.length]; const cutName = args.new_track_name || `Cut_${track.name}`; const newTrack = { id: newId, name: cutName, buffer: slicedBuffer, @@ -7554,12 +7560,18 @@ const App = () => { clips: [{ id: 'clip_' + newId, buffer: slicedBuffer, startTime: 0, name: cutName }], serverFileId: null }; - setTracks(prev => { - const idx = prev.findIndex(t => t.id === tid); - const updated = [...prev]; - updated.splice(idx + 1, 0, newTrack); - return updated; - }); + const idx = currentTracks.findIndex(t => t.id === tid); + const nextTracks = [...currentTracks]; + if (idx !== -1) { + nextTracks.splice(idx + 1, 0, newTrack); + } else { + nextTracks.push(newTrack); + } + if (window.DAWCommandDispatcher) { + window.DAWCommandDispatcher.currentTracks = nextTracks; + window.DAWCommandDispatcher.currentSelectedTrackId = newId; + } + setTracks(nextTracks); setSelectedTrackId(newId); selectionRef.current = { start: 0, end: slicedBuffer.duration }; clearLocalSelection(); @@ -7759,8 +7771,10 @@ const App = () => { return { success: true, trackId, time }; }, fadeIn: (args) => { - const trackIdRaw = args.track_id || selectedTrackId; - const track = tracks.find(t => t.id === String(trackIdRaw) || t.id === 'track_' + trackIdRaw); + const currentTracks = window.DAWCommandDispatcher?.currentTracks || tracks; + const currentSelTrackId = window.DAWCommandDispatcher?.currentSelectedTrackId || selectedTrackId; + const trackIdRaw = args.track_id || currentSelTrackId; + const track = currentTracks.find(t => t.id === String(trackIdRaw) || t.id === 'track_' + trackIdRaw); if (!track) return { success: false, error: `Track ${trackIdRaw} not found` }; const clips = track.clips && track.clips.length > 0 ? track.clips : (track.buffer ? [{ id: 'default_' + track.id, buffer: track.buffer, startTime: track.startTime || 0, name: track.name }] : []); if (clips.length === 0) return { success: false, error: 'No clips on track' }; @@ -7794,7 +7808,7 @@ const App = () => { } } const beforeSnap = captureTrackSnapshot(track.id); - setTracks(prev => prev.map(t => { + const nextTracks = currentTracks.map(t => { if (t.id !== track.id) return t; const existingClips = t.clips && t.clips.length > 0 ? t.clips : (t.buffer ? [{ id: 'default_' + t.id, buffer: t.buffer, startTime: t.startTime || 0, name: t.name }] : []); const updatedClips = existingClips.map(c => { @@ -7805,7 +7819,11 @@ const App = () => { }); const mainBuffer = updatedClips[0]?.buffer || t.buffer; return { ...t, clips: updatedClips, buffer: mainBuffer }; - })); + }); + if (window.DAWCommandDispatcher) { + window.DAWCommandDispatcher.currentTracks = nextTracks; + } + setTracks(nextTracks); setTimeout(() => { const afterSnap = captureTrackSnapshot(track.id); pushAction('AI_FADE_IN', track.id, beforeSnap, afterSnap); @@ -7813,8 +7831,10 @@ const App = () => { return { success: true, trackId: track.id, clipId: clip.id, duration_seconds: duration }; }, fadeOut: (args) => { - const trackIdRaw = args.track_id || selectedTrackId; - const track = tracks.find(t => t.id === String(trackIdRaw) || t.id === 'track_' + trackIdRaw); + const currentTracks = window.DAWCommandDispatcher?.currentTracks || tracks; + const currentSelTrackId = window.DAWCommandDispatcher?.currentSelectedTrackId || selectedTrackId; + const trackIdRaw = args.track_id || currentSelTrackId; + const track = currentTracks.find(t => t.id === String(trackIdRaw) || t.id === 'track_' + trackIdRaw); if (!track) return { success: false, error: `Track ${trackIdRaw} not found` }; const clips = track.clips && track.clips.length > 0 ? track.clips : (track.buffer ? [{ id: 'default_' + track.id, buffer: track.buffer, startTime: track.startTime || 0, name: track.name }] : []); if (clips.length === 0) return { success: false, error: 'No clips on track' }; @@ -7849,7 +7869,7 @@ const App = () => { } } const beforeSnap = captureTrackSnapshot(track.id); - setTracks(prev => prev.map(t => { + const nextTracks = currentTracks.map(t => { if (t.id !== track.id) return t; const existingClips = t.clips && t.clips.length > 0 ? t.clips : (t.buffer ? [{ id: 'default_' + t.id, buffer: t.buffer, startTime: t.startTime || 0, name: t.name }] : []); const updatedClips = existingClips.map(c => { @@ -7860,7 +7880,11 @@ const App = () => { }); const mainBuffer = updatedClips[0]?.buffer || t.buffer; return { ...t, clips: updatedClips, buffer: mainBuffer }; - })); + }); + if (window.DAWCommandDispatcher) { + window.DAWCommandDispatcher.currentTracks = nextTracks; + } + setTracks(nextTracks); setTimeout(() => { const afterSnap = captureTrackSnapshot(track.id); pushAction('AI_FADE_OUT', track.id, beforeSnap, afterSnap); diff --git a/app/static/js/app.precompiled.js b/app/static/js/app.precompiled.js index 1b72cfa..a6b0e45 100644 --- a/app/static/js/app.precompiled.js +++ b/app/static/js/app.precompiled.js @@ -7274,6 +7274,10 @@ const App = () => { showToast('Vui lòng nhập nội dung prompt.', 'warning'); return; } + if (window.DAWCommandDispatcher) { + window.DAWCommandDispatcher.currentSelectedTrackId = selectedTrackId; + window.DAWCommandDispatcher.currentTracks = tracks; + } setAiProcessing(true); setAiActionLog(prev => [...prev, { type: 'status', @@ -7779,8 +7783,10 @@ const App = () => { }; }, cutAudio: args => { - const tid = args.track_id || selectedTrackId; - const track = tracks.find(t => t.id === tid); + const currentTracks = window.DAWCommandDispatcher?.currentTracks || tracks; + const currentSelTrackId = window.DAWCommandDispatcher?.currentSelectedTrackId || selectedTrackId; + const tid = args.track_id || currentSelTrackId; + const track = currentTracks.find(t => t.id === String(tid)); if (!track) return { success: false, error: 'Track not found' @@ -7823,7 +7829,7 @@ const App = () => { } const newId = 'track_cut_' + Date.now(); const colors = ['#0f766e', '#1d4ed8', '#701a75', '#a21caf', '#b45309']; - const color = colors[tracks.length % colors.length]; + const color = colors[currentTracks.length % colors.length]; const cutName = args.new_track_name || `Cut_${track.name}`; const newTrack = { id: newId, @@ -7845,12 +7851,18 @@ const App = () => { }], serverFileId: null }; - setTracks(prev => { - const idx = prev.findIndex(t => t.id === tid); - const updated = [...prev]; - updated.splice(idx + 1, 0, newTrack); - return updated; - }); + const idx = currentTracks.findIndex(t => t.id === tid); + const nextTracks = [...currentTracks]; + if (idx !== -1) { + nextTracks.splice(idx + 1, 0, newTrack); + } else { + nextTracks.push(newTrack); + } + if (window.DAWCommandDispatcher) { + window.DAWCommandDispatcher.currentTracks = nextTracks; + window.DAWCommandDispatcher.currentSelectedTrackId = newId; + } + setTracks(nextTracks); setSelectedTrackId(newId); selectionRef.current = { start: 0, @@ -8140,8 +8152,10 @@ const App = () => { }; }, fadeIn: args => { - const trackIdRaw = args.track_id || selectedTrackId; - const track = tracks.find(t => t.id === String(trackIdRaw) || t.id === 'track_' + trackIdRaw); + const currentTracks = window.DAWCommandDispatcher?.currentTracks || tracks; + const currentSelTrackId = window.DAWCommandDispatcher?.currentSelectedTrackId || selectedTrackId; + const trackIdRaw = args.track_id || currentSelTrackId; + const track = currentTracks.find(t => t.id === String(trackIdRaw) || t.id === 'track_' + trackIdRaw); if (!track) return { success: false, error: `Track ${trackIdRaw} not found` @@ -8189,7 +8203,7 @@ const App = () => { } } const beforeSnap = captureTrackSnapshot(track.id); - setTracks(prev => prev.map(t => { + const nextTracks = currentTracks.map(t => { if (t.id !== track.id) return t; const existingClips = t.clips && t.clips.length > 0 ? t.clips : t.buffer ? [{ id: 'default_' + t.id, @@ -8212,7 +8226,11 @@ const App = () => { clips: updatedClips, buffer: mainBuffer }; - })); + }); + if (window.DAWCommandDispatcher) { + window.DAWCommandDispatcher.currentTracks = nextTracks; + } + setTracks(nextTracks); setTimeout(() => { const afterSnap = captureTrackSnapshot(track.id); pushAction('AI_FADE_IN', track.id, beforeSnap, afterSnap); @@ -8225,8 +8243,10 @@ const App = () => { }; }, fadeOut: args => { - const trackIdRaw = args.track_id || selectedTrackId; - const track = tracks.find(t => t.id === String(trackIdRaw) || t.id === 'track_' + trackIdRaw); + const currentTracks = window.DAWCommandDispatcher?.currentTracks || tracks; + const currentSelTrackId = window.DAWCommandDispatcher?.currentSelectedTrackId || selectedTrackId; + const trackIdRaw = args.track_id || currentSelTrackId; + const track = currentTracks.find(t => t.id === String(trackIdRaw) || t.id === 'track_' + trackIdRaw); if (!track) return { success: false, error: `Track ${trackIdRaw} not found` @@ -8275,7 +8295,7 @@ const App = () => { } } const beforeSnap = captureTrackSnapshot(track.id); - setTracks(prev => prev.map(t => { + const nextTracks = currentTracks.map(t => { if (t.id !== track.id) return t; const existingClips = t.clips && t.clips.length > 0 ? t.clips : t.buffer ? [{ id: 'default_' + t.id, @@ -8298,7 +8318,11 @@ const App = () => { clips: updatedClips, buffer: mainBuffer }; - })); + }); + if (window.DAWCommandDispatcher) { + window.DAWCommandDispatcher.currentTracks = nextTracks; + } + setTracks(nextTracks); setTimeout(() => { const afterSnap = captureTrackSnapshot(track.id); pushAction('AI_FADE_OUT', track.id, beforeSnap, afterSnap); diff --git a/app/storage/sonicforge.db b/app/storage/sonicforge.db index 8ec2f7f..5a684f8 100644 Binary files a/app/storage/sonicforge.db and b/app/storage/sonicforge.db differ