fix: đồng bộ hóa trạng thái track lựa chọn thời gian thực cho chuỗi lệnh AI

This commit is contained in:
2026-07-22 17:52:00 +07:00
parent b9c524230d
commit 6b7872c636
3 changed files with 82 additions and 34 deletions
+41 -17
View File
@@ -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);
+41 -17
View File
@@ -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);
Binary file not shown.