fix: rearrangeMidiMelody newId not defined
newId was defined inside updateActiveTracks callback but referenced outside (line 15002 return). Moved declaration before the callback as rearrangeNewId, accessible in both the callback body and the outer return statement.
This commit is contained in:
+56
-56
@@ -2948,9 +2948,9 @@ const GraphEditorCanvas = ({
|
||||
};
|
||||
const sorted = [...nodes, newNode].sort((a, b) => a.time - b.time);
|
||||
onUpdateNodes(sorted);
|
||||
const newIdx = sorted.findIndex(n => n.time === newNode.time && (graphMode === 'pan' ? n.pan : n.db) === (graphMode === 'pan' ? newNode.pan : newNode.db));
|
||||
const rearrangeNewIdx = sorted.findIndex(n => n.time === newNode.time && (graphMode === 'pan' ? n.pan : n.db) === (graphMode === 'pan' ? newNode.pan : newNode.db));
|
||||
isDraggingNode.current = true;
|
||||
dragNodeIdx.current = newIdx;
|
||||
dragNodeIdx.current = rearrangeNewIdx;
|
||||
isCreatingNode.current = true;
|
||||
};
|
||||
const handleMouseMove = e => {
|
||||
@@ -3289,9 +3289,9 @@ const AIConfigModal = ({
|
||||
}, /*#__PURE__*/React.createElement("button", {
|
||||
onClick: e => {
|
||||
e.stopPropagation();
|
||||
const newId = 'provider_' + Date.now();
|
||||
const rearrangeNewId = 'provider_' + Date.now();
|
||||
setProviders(prev => [...prev, {
|
||||
id: newId,
|
||||
id: rearrangeNewId,
|
||||
name: 'New Provider',
|
||||
provider_type: 'openai_compatible',
|
||||
api_base_url: 'https://api.openai.com/v1',
|
||||
@@ -3300,7 +3300,7 @@ const AIConfigModal = ({
|
||||
temperature: 0.7,
|
||||
is_active: false
|
||||
}]);
|
||||
setSelectedId(newId);
|
||||
setSelectedId(rearrangeNewId);
|
||||
},
|
||||
className: "flex-1 px-2 py-1 bg-emerald-700 hover:bg-emerald-600 text-white text-xs font-bold rounded"
|
||||
}, "+ Thêm"), providers.length > 1 && /*#__PURE__*/React.createElement("button", {
|
||||
@@ -9524,9 +9524,9 @@ const App = () => {
|
||||
|
||||
// No matching track — create a new one
|
||||
const colors = ['#0f766e', '#1d4ed8', '#701a75', '#a21caf', '#b45309'];
|
||||
const newId = 'track_pasted_' + Date.now();
|
||||
const rearrangeNewId = 'track_pasted_' + Date.now();
|
||||
updateActiveTracks(prev => [...prev, {
|
||||
id: newId,
|
||||
id: rearrangeNewId,
|
||||
name: `Pasted_${name || 'track'}`,
|
||||
buffer: clipBuffer,
|
||||
startTime: pasteTime,
|
||||
@@ -9539,10 +9539,10 @@ const App = () => {
|
||||
markers: [],
|
||||
serverFileId: null
|
||||
}]);
|
||||
setSelectedTrackId(newId);
|
||||
setSelectedTrackId(rearrangeNewId);
|
||||
setCurrentTime(pasteTime);
|
||||
showToast('Đã dán track mới từ clipboard.', 'success');
|
||||
return newId;
|
||||
return rearrangeNewId;
|
||||
};
|
||||
const handlePasteTrack = () => doPaste(selectedTrackId, currentTime);
|
||||
const contextMenuPaste = () => {
|
||||
@@ -9580,10 +9580,10 @@ const App = () => {
|
||||
for (let i = 0; i < mergedData.length; i++) mergedData[i] /= maxPeak;
|
||||
}
|
||||
const colors = ['#0f766e', '#1d4ed8', '#701a75', '#a21caf', '#b45309'];
|
||||
const newId = 'track_merged_' + Date.now();
|
||||
const rearrangeNewId = 'track_merged_' + Date.now();
|
||||
const names = activeTracks.map(t => t.name).join('+').slice(0, 30);
|
||||
setTracks(prev => [...prev, {
|
||||
id: newId,
|
||||
id: rearrangeNewId,
|
||||
name: `Merged_${names}.wav`,
|
||||
buffer: merged,
|
||||
startTime: 0,
|
||||
@@ -9595,7 +9595,7 @@ const App = () => {
|
||||
markers: [],
|
||||
serverFileId: null
|
||||
}]);
|
||||
setSelectedTrackId(newId);
|
||||
setSelectedTrackId(rearrangeNewId);
|
||||
closeContextMenu();
|
||||
showToast(`Đã merge ${activeTracks.length} tracks.`, 'success');
|
||||
};
|
||||
@@ -11900,23 +11900,23 @@ const App = () => {
|
||||
if (info.type === 'section') {
|
||||
var sec = (t.sections || []).find(function(s) { return s.id === oid; });
|
||||
if (sec) {
|
||||
var newId = 'sec_dup_' + Date.now() + '_' + Math.random().toString(36).substr(2, 5);
|
||||
updatedSections.push({ ...sec, id: newId, name: sec.name + ' (Copy)' });
|
||||
newOriginals[newId] = { type: 'section', start: sec.start };
|
||||
var rearrangeNewId = 'sec_dup_' + Date.now() + '_' + Math.random().toString(36).substr(2, 5);
|
||||
updatedSections.push({ ...sec, id: rearrangeNewId, name: sec.name + ' (Copy)' });
|
||||
newOriginals[rearrangeNewId] = { type: 'section', start: sec.start };
|
||||
}
|
||||
} else if (info.type === 'midiItem') {
|
||||
var mid = (t.midiItems || []).find(function(m) { return m.id === oid; });
|
||||
if (mid) {
|
||||
var newId = 'midi_dup_' + Date.now() + '_' + Math.random().toString(36).substr(2, 5);
|
||||
updatedMidi.push({ ...mid, id: newId, name: mid.name + ' (Copy)' });
|
||||
newOriginals[newId] = { type: 'midiItem', start: mid.startTime };
|
||||
var rearrangeNewId = 'midi_dup_' + Date.now() + '_' + Math.random().toString(36).substr(2, 5);
|
||||
updatedMidi.push({ ...mid, id: rearrangeNewId, name: mid.name + ' (Copy)' });
|
||||
newOriginals[rearrangeNewId] = { type: 'midiItem', start: mid.startTime };
|
||||
}
|
||||
} else if (info.type === 'clip') {
|
||||
var clip = (t.clips || []).find(function(c) { return c.id === oid || 'default_' + t.id === oid; });
|
||||
if (clip) {
|
||||
var newId = 'clip_dup_' + Date.now() + '_' + Math.random().toString(36).substr(2, 5);
|
||||
updatedClips.push({ ...clip, id: newId, startTime: clip.startTime, name: clip.name + ' (Copy)' });
|
||||
newOriginals[newId] = { type: 'clip', start: clip.startTime };
|
||||
var rearrangeNewId = 'clip_dup_' + Date.now() + '_' + Math.random().toString(36).substr(2, 5);
|
||||
updatedClips.push({ ...clip, id: rearrangeNewId, startTime: clip.startTime, name: clip.name + ' (Copy)' });
|
||||
newOriginals[rearrangeNewId] = { type: 'clip', start: clip.startTime };
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -11929,8 +11929,8 @@ const App = () => {
|
||||
var items = itemType === 'section' ? (track.sections || []) : (track.midiItems || []);
|
||||
var item = items.find(function(it) { return it.id === itemId; });
|
||||
if (!item) return;
|
||||
var newId = itemType + '_dup_' + Date.now();
|
||||
var newItem = { ...item, id: newId, name: item.name + ' (Copy)' };
|
||||
var rearrangeNewId = itemType + '_dup_' + Date.now();
|
||||
var newItem = { ...item, id: rearrangeNewId, name: item.name + ' (Copy)' };
|
||||
updateActiveTracks(function(prev) {
|
||||
return prev.map(function(t) {
|
||||
if (t.id !== trackId) return t;
|
||||
@@ -11938,7 +11938,7 @@ const App = () => {
|
||||
return itemType === 'section' ? { ...t, sections: updated } : { ...t, midiItems: updated };
|
||||
});
|
||||
});
|
||||
setDraggedSectionItem({ trackId, itemType, itemId: newId, clickOffset, isDuplicate: false });
|
||||
setDraggedSectionItem({ trackId, itemType, itemId: rearrangeNewId, clickOffset, isDuplicate: false });
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -12589,12 +12589,12 @@ const App = () => {
|
||||
// ── Add Track ──
|
||||
const addNewTrack = () => {
|
||||
const curTracks = activeTracks;
|
||||
const newId = (curTracks.length + 1).toString();
|
||||
const rearrangeNewId = (curTracks.length + 1).toString();
|
||||
const colors = ['#0f766e', '#1d4ed8', '#701a75', '#a21caf', '#b45309'];
|
||||
const selectColor = colors[curTracks.length % colors.length];
|
||||
updateActiveTracks(prev => [...prev, {
|
||||
id: newId,
|
||||
name: `Track ${newId}`,
|
||||
id: rearrangeNewId,
|
||||
name: `Track ${rearrangeNewId}`,
|
||||
buffer: null,
|
||||
startTime: 0,
|
||||
volumeDb: 0,
|
||||
@@ -12611,9 +12611,9 @@ const App = () => {
|
||||
monitoringEnabled: true,
|
||||
inputSource: { deviceType: 'NONE', deviceId: '' }
|
||||
}]);
|
||||
showToast(`Đã thêm Track ${newId}.`, 'info');
|
||||
showToast(`Đã thêm Track ${rearrangeNewId}.`, 'info');
|
||||
setTimeout(() => lucide.createIcons(), 200);
|
||||
return newId;
|
||||
return rearrangeNewId;
|
||||
};
|
||||
|
||||
// ── Update tracks in active context (main session or section tab) ──
|
||||
@@ -12776,12 +12776,12 @@ const App = () => {
|
||||
// ── Insert Track Below Selected ──
|
||||
const insertTrackBelow = () => {
|
||||
const curTracks = activeTracks;
|
||||
const newId = `t${Date.now()}`;
|
||||
const rearrangeNewId = `t${Date.now()}`;
|
||||
const colors = ['#0f766e', '#1d4ed8', '#701a75', '#a21caf', '#b45309'];
|
||||
const selectColor = colors[(curTracks.length) % colors.length];
|
||||
const newTrack = {
|
||||
id: newId,
|
||||
name: `Track ${newId}`,
|
||||
id: rearrangeNewId,
|
||||
name: `Track ${rearrangeNewId}`,
|
||||
buffer: null,
|
||||
startTime: 0,
|
||||
volumeDb: 0,
|
||||
@@ -12802,8 +12802,8 @@ const App = () => {
|
||||
copy.splice(idx + 1, 0, newTrack);
|
||||
return copy;
|
||||
});
|
||||
setSelectedTrackId(newId);
|
||||
showToast(`Đã thêm Track ${newId}.`, 'info');
|
||||
setSelectedTrackId(rearrangeNewId);
|
||||
showToast(`Đã thêm Track ${rearrangeNewId}.`, 'info');
|
||||
setTimeout(() => lucide.createIcons(), 200);
|
||||
};
|
||||
|
||||
@@ -13761,13 +13761,13 @@ const App = () => {
|
||||
const dstData = slicedBuffer.getChannelData(c);
|
||||
dstData.set(srcData.subarray(startSample, endSample));
|
||||
}
|
||||
const newId = 'track_ai_cut_' + Date.now();
|
||||
const rearrangeNewId = 'track_ai_cut_' + Date.now();
|
||||
const colors = ['#0f766e', '#1d4ed8', '#701a75', '#a21caf', '#b45309'];
|
||||
const selectColor = colors[tracks.length % colors.length];
|
||||
const barNum = Math.floor(snapLoopStart / barDuration) + 1;
|
||||
const barsCount = Math.max(1, Math.round((snapLoopEnd - snapLoopStart) / barDuration));
|
||||
const newTrack = {
|
||||
id: newId,
|
||||
id: rearrangeNewId,
|
||||
name: `Loop_${barNum}bar_${activeTrack.name.replace('.wav', '').slice(0, 10)}_${snapLoopStart.toFixed(1)}s.wav`,
|
||||
buffer: slicedBuffer,
|
||||
channelInfo: activeTrack.channelInfo ? {
|
||||
@@ -13775,7 +13775,7 @@ const App = () => {
|
||||
} : null,
|
||||
startTime: snapLoopStart,
|
||||
clips: [{
|
||||
id: 'clip_' + newId,
|
||||
id: 'clip_' + rearrangeNewId,
|
||||
buffer: slicedBuffer,
|
||||
startTime: snapLoopStart,
|
||||
name: `Loop_${barNum}bar_${snapLoopStart.toFixed(1)}s`
|
||||
@@ -13804,7 +13804,7 @@ const App = () => {
|
||||
}
|
||||
return updated;
|
||||
});
|
||||
setSelectedTrackId(newId);
|
||||
setSelectedTrackId(rearrangeNewId);
|
||||
setAnalysisState({
|
||||
status: `AI Cut: ${detectedBPM} BPM, ${barsCount} bars loop (Zero-Crossing aligned)`,
|
||||
data: {
|
||||
@@ -14226,11 +14226,11 @@ const App = () => {
|
||||
createTrack: (args) => {
|
||||
const name = args.name || `AI_Track_${Date.now()}`;
|
||||
const type = args.type || 'audio';
|
||||
const newId = addNewTrack();
|
||||
const rearrangeNewId = addNewTrack();
|
||||
if (name && name !== `AI_Track_${Date.now()}`) {
|
||||
updateTrackName(newId, name);
|
||||
updateTrackName(rearrangeNewId, name);
|
||||
}
|
||||
return { success: true, trackId: newId, name };
|
||||
return { success: true, trackId: rearrangeNewId, name };
|
||||
},
|
||||
deleteTrack: (args) => {
|
||||
const tid = args.track_id || selectedTrackId;
|
||||
@@ -14416,15 +14416,15 @@ const App = () => {
|
||||
const dst = slicedBuffer.getChannelData(c);
|
||||
dst.set(src.subarray(startSample, endSample));
|
||||
}
|
||||
const newId = 'track_cut_' + Date.now();
|
||||
const rearrangeNewId = 'track_cut_' + Date.now();
|
||||
const colors = ['#0f766e', '#1d4ed8', '#701a75', '#a21caf', '#b45309'];
|
||||
const color = colors[currentTracks.length % colors.length];
|
||||
const cutName = args.new_track_name || `Cut_${track.name}`;
|
||||
const newTrack = {
|
||||
id: newId, name: cutName, buffer: slicedBuffer,
|
||||
id: rearrangeNewId, name: cutName, buffer: slicedBuffer,
|
||||
startTime: 0, volumeDb: 0, pan: 0,
|
||||
muted: false, solo: false, color, markers: [],
|
||||
clips: [{ id: 'clip_' + newId, buffer: slicedBuffer, startTime: 0, name: cutName }],
|
||||
clips: [{ id: 'clip_' + rearrangeNewId, buffer: slicedBuffer, startTime: 0, name: cutName }],
|
||||
serverFileId: null
|
||||
};
|
||||
const idx = currentTracks.findIndex(t => t.id === tid);
|
||||
@@ -14436,12 +14436,12 @@ const App = () => {
|
||||
}
|
||||
if (window.DAWCommandDispatcher) {
|
||||
window.DAWCommandDispatcher.currentTracks = nextTracks;
|
||||
window.DAWCommandDispatcher.currentSelectedTrackId = newId;
|
||||
window.DAWCommandDispatcher.currentSelectedTrackId = rearrangeNewId;
|
||||
window.DAWCommandDispatcher.lastCutSourceTrackId = tid;
|
||||
window.DAWCommandDispatcher.lastCutNewTrackId = newId;
|
||||
window.DAWCommandDispatcher.lastCutNewTrackId = rearrangeNewId;
|
||||
}
|
||||
setTracks(nextTracks);
|
||||
setSelectedTrackId(newId);
|
||||
setSelectedTrackId(rearrangeNewId);
|
||||
selectionRef.current = { start: 0, end: slicedBuffer.duration };
|
||||
clearLocalSelection();
|
||||
setSelectionMode('global');
|
||||
@@ -14449,7 +14449,7 @@ const App = () => {
|
||||
setSelectionEnd(slicedBuffer.duration);
|
||||
setTimeout(() => lucide.createIcons(), 200);
|
||||
return {
|
||||
success: true, trackId: newId, trackName: cutName,
|
||||
success: true, trackId: rearrangeNewId, trackName: cutName,
|
||||
cutStart: parseFloat(loopStart.toFixed(3)), cutEnd: parseFloat(loopEnd.toFixed(3)),
|
||||
duration: parseFloat(slicedBuffer.duration.toFixed(3))
|
||||
};
|
||||
@@ -14865,11 +14865,11 @@ const App = () => {
|
||||
t => t.name.toLowerCase() === aiTrack.track_name.toLowerCase()
|
||||
);
|
||||
if (!targetTrack) {
|
||||
const newId = (updatedTracks.length + 1).toString();
|
||||
const rearrangeNewId = (updatedTracks.length + 1).toString();
|
||||
const colors = ['#0f766e', '#1d4ed8', '#701a75', '#a21caf', '#b45309'];
|
||||
const selectColor = colors[updatedTracks.length % colors.length];
|
||||
targetTrack = {
|
||||
id: newId,
|
||||
id: rearrangeNewId,
|
||||
name: aiTrack.track_name,
|
||||
type: 'MIDI',
|
||||
volumeDb: 0,
|
||||
@@ -14945,15 +14945,15 @@ const App = () => {
|
||||
const totalBars = Math.max(1, Math.ceil(totalBeats / 4));
|
||||
const durationSec = totalBars * secondsPerBar;
|
||||
|
||||
const rearrangeNewId = (activeTracks.length + 1).toString();
|
||||
updateActiveTracks(prev => {
|
||||
let updatedTracks = [...prev];
|
||||
// Find source track index to insert new track right after it
|
||||
const sourceIdx = sourceTrackId ? updatedTracks.findIndex(t => t.id === sourceTrackId || t.id === 'track_' + sourceTrackId) : -1;
|
||||
const insertIdx = sourceIdx >= 0 ? sourceIdx + 1 : updatedTracks.length;
|
||||
const newId = (updatedTracks.length + 1).toString();
|
||||
const colors = ['#0f766e', '#1d4ed8', '#701a75', '#a21caf', '#b45309'];
|
||||
const newTrack = {
|
||||
id: newId,
|
||||
id: rearrangeNewId,
|
||||
name: `[AI Rearrange] ${rearrange_title || 'Variation'}`,
|
||||
type: 'MIDI',
|
||||
volumeDb: 0,
|
||||
@@ -14968,7 +14968,7 @@ const App = () => {
|
||||
midiItems: [{
|
||||
id: 'item_rearr_' + Date.now() + '_' + Math.random().toString(36).substr(2, 5),
|
||||
name: `[AI] ${rearrange_title || 'Rearranged'} - var`,
|
||||
parent_track_id: newId,
|
||||
parent_track_id: rearrangeNewId,
|
||||
startTime: currentTime,
|
||||
duration: durationSec,
|
||||
length_bars: totalBars,
|
||||
@@ -14999,7 +14999,7 @@ const App = () => {
|
||||
});
|
||||
|
||||
showToast(`✅ AI Rearrange: "${rearrange_title}" — ${rearranged_notes.length} notes`, 'success');
|
||||
return { success: true, trackId: newId, totalBars };
|
||||
return { success: true, trackId: rearrangeNewId, totalBars };
|
||||
},
|
||||
createMidiItem: (args) => {
|
||||
const trackId = args.track_id || selectedTrackId;
|
||||
@@ -15174,8 +15174,8 @@ const App = () => {
|
||||
input.onchange = async e => {
|
||||
if (e.target.files[0]) {
|
||||
addNewTrack();
|
||||
const newId = (tracks.length + 1).toString();
|
||||
setTimeout(() => loadFileOnTrack(newId, e.target.files[0]), 100);
|
||||
const rearrangeNewId = (tracks.length + 1).toString();
|
||||
setTimeout(() => loadFileOnTrack(rearrangeNewId, e.target.files[0]), 100);
|
||||
}
|
||||
};
|
||||
input.click();
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user