fix: group drag cross-track uses live prev state for index mapping
Build trkIds from prev (updateActiveTracks callback) instead of stale activeTracksRef. Fix srcItem lookup with proper for loop.
This commit is contained in:
+40
-35
@@ -12049,17 +12049,16 @@ const App = () => {
|
||||
wrapper.scrollLeft = Math.max(0, itemPx - keepMargin);
|
||||
setCanvasRedrawCount(n => n + 1);
|
||||
}
|
||||
var allTrks = activeTracksRef.current || [];
|
||||
var targetTrackId = hoveredTrackIdRef.current || drag.trackId;
|
||||
// Build trackId->index map for relative offset computation
|
||||
var trkIndexMap = {};
|
||||
allTrks.forEach(function(tr, ti) { trkIndexMap[tr.id] = ti; });
|
||||
var baseIdx = trkIndexMap[drag.trackId] || 0;
|
||||
var targetIdx = trkIndexMap[targetTrackId];
|
||||
if (targetIdx === undefined) { targetIdx = allTrks.length - 1; if (targetIdx < 0) targetIdx = 0; }
|
||||
var crossOffset = targetIdx - baseIdx;
|
||||
// Build live currentTrackMap: where each multi-drag item currently lives
|
||||
updateActiveTracks(prev => {
|
||||
// Build trackId->index map from live prev state
|
||||
var trkIds = prev.map(function(tr) { return tr.id; });
|
||||
var baseIdx = trkIds.indexOf(drag.trackId);
|
||||
if (baseIdx < 0) baseIdx = 0;
|
||||
var targetIdx = trkIds.indexOf(targetTrackId);
|
||||
if (targetIdx < 0) targetIdx = prev.length - 1;
|
||||
if (targetIdx < 0) targetIdx = 0;
|
||||
var crossOffset = targetIdx - baseIdx;
|
||||
let movedItem = null;
|
||||
for (let track of prev) {
|
||||
const sec = (track.sections || []).find(it => it.id === drag.itemId);
|
||||
@@ -12067,7 +12066,6 @@ const App = () => {
|
||||
if (sec || mid) { movedItem = sec || mid; break; }
|
||||
}
|
||||
if (drag.multiIds) {
|
||||
// Build currentTrackMap from live state
|
||||
var currentTrackMap = {};
|
||||
Object.keys(drag.multiIds).forEach(function(mid) {
|
||||
for (var pi = 0; pi < prev.length; pi++) {
|
||||
@@ -12082,42 +12080,49 @@ const App = () => {
|
||||
});
|
||||
var dragOrigStart = drag.multiIds[drag.itemId] ? drag.multiIds[drag.itemId].start : 0;
|
||||
var delta = newStart - dragOrigStart;
|
||||
return prev.map(t => {
|
||||
var resultSections = (t.sections || []).slice();
|
||||
var resultMidis = (t.midiItems || []).slice();
|
||||
var resultClips = (t.clips || []).slice();
|
||||
return prev.map(function(t) {
|
||||
var resS = (t.sections || []).slice();
|
||||
var resM = (t.midiItems || []).slice();
|
||||
var resC = (t.clips || []).slice();
|
||||
Object.keys(drag.multiIds).forEach(function(mid) {
|
||||
var inf = drag.multiIds[mid];
|
||||
var newVal = inf.start + delta;
|
||||
var srcTid = currentTrackMap[mid];
|
||||
var srcIdx = trkIndexMap[srcTid] !== undefined ? trkIndexMap[srcTid] : baseIdx;
|
||||
var itemTargetIdx = Math.max(0, srcIdx + crossOffset);
|
||||
var itemTid = itemTargetIdx < allTrks.length ? allTrks[itemTargetIdx].id : null;
|
||||
var srcIdx = trkIds.indexOf(srcTid);
|
||||
if (srcIdx < 0) srcIdx = baseIdx;
|
||||
var itemTrgIdx = Math.max(0, srcIdx + crossOffset);
|
||||
var itemTid = itemTrgIdx < prev.length ? prev[itemTrgIdx].id : null;
|
||||
if (!itemTid) return;
|
||||
if (srcTid === t.id && t.id !== itemTid) {
|
||||
// Remove from source track (leaving for another track)
|
||||
if (inf.type === 'section') resultSections = resultSections.filter(function(s) { return s.id !== mid; });
|
||||
else if (inf.type === 'midiItem') resultMidis = resultMidis.filter(function(mx) { return mx.id !== mid; });
|
||||
else if (inf.type === 'clip') { var cid3 = 'default_' + t.id; resultClips = resultClips.filter(function(cx) { return cx.id !== mid && cx.id !== cid3; }); }
|
||||
if (inf.type === 'section') resS = resS.filter(function(s) { return s.id !== mid; });
|
||||
else if (inf.type === 'midiItem') resM = resM.filter(function(mx) { return mx.id !== mid; });
|
||||
else if (inf.type === 'clip') { var c3 = 'default_' + t.id; resC = resC.filter(function(cx) { return cx.id !== mid && cx.id !== c3; }); }
|
||||
}
|
||||
if (t.id === itemTid) {
|
||||
// This IS the item's target track — upsert
|
||||
if (inf.type === 'section') {
|
||||
resultSections = resultSections.filter(function(s) { return s.id !== mid; });
|
||||
resultSections.push({ ...(prev.flatMap(function(x) { return x.sections || []; }).find(function(s) { return s.id === mid; }) || {}), start: Math.max(0, newVal) });
|
||||
} else if (inf.type === 'midiItem') {
|
||||
resultMidis = resultMidis.filter(function(mx) { return mx.id !== mid; });
|
||||
resultMidis.push({ ...(prev.flatMap(function(x) { return x.midiItems || []; }).find(function(mx) { return mx.id === mid; }) || {}), startTime: Math.max(0, newVal) });
|
||||
} else if (inf.type === 'clip') {
|
||||
var cid4 = 'default_' + t.id;
|
||||
resultClips = resultClips.filter(function(cx) { return cx.id !== mid && cx.id !== cid4; });
|
||||
var allClips = prev.flatMap(function(x) { return x.clips || []; });
|
||||
var srcClip = allClips.find(function(cx) { return cx.id === mid || 'default_' + (srcTid || '') === mid; });
|
||||
if (srcClip) resultClips.push({ ...srcClip, startTime: Math.max(0, newVal) });
|
||||
var srcItem = null;
|
||||
for (var pi2 = 0; pi2 < prev.length; pi2++) {
|
||||
var tr2 = prev[pi2];
|
||||
if (inf.type === 'section') srcItem = (tr2.sections || []).find(function(s) { return s.id === mid; });
|
||||
else if (inf.type === 'midiItem') srcItem = (tr2.midiItems || []).find(function(mx) { return mx.id === mid; });
|
||||
else if (inf.type === 'clip') { var c2 = (tr2.clips || []).find(function(cx) { return cx.id === mid || 'default_' + tr2.id === mid; }); if (c2) srcItem = c2; }
|
||||
if (srcItem) break;
|
||||
}
|
||||
if (srcItem) {
|
||||
if (inf.type === 'section') {
|
||||
resS = resS.filter(function(s) { return s.id !== mid; });
|
||||
resS.push({ ...srcItem, start: Math.max(0, newVal) });
|
||||
} else if (inf.type === 'midiItem') {
|
||||
resM = resM.filter(function(mx) { return mx.id !== mid; });
|
||||
resM.push({ ...srcItem, startTime: Math.max(0, newVal) });
|
||||
} else if (inf.type === 'clip') {
|
||||
var c4 = 'default_' + t.id;
|
||||
resC = resC.filter(function(cx) { return cx.id !== mid && cx.id !== c4; });
|
||||
resC.push({ ...srcItem, startTime: Math.max(0, newVal) });
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return { ...t, sections: resultSections, midiItems: resultMidis, clips: resultClips };
|
||||
return { ...t, sections: resS, midiItems: resM, clips: resC };
|
||||
});
|
||||
}
|
||||
const items = drag.itemType === 'section' ? (t.sections || []) : (t.midiItems || []);
|
||||
|
||||
Reference in New Issue
Block a user