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:
2026-07-28 20:58:44 +07:00
parent fc81f19b1c
commit 393dd7190f
2 changed files with 66 additions and 66 deletions
+56 -56
View File
@@ -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();