fix: use ref-wrapped handler for delete selected items

Move delete logic into handleDeleteSelectedItemsRef to ensure
setSelectedItemIds, updateActiveTracks, showToast are always
up-to-date despite empty useEffect deps in keyboard handler.

Keyboard handler reads selectedItemIdsRef.current (live ref),
calls handleDeleteSelectedItemsRef.current(idsToDelete).
This commit is contained in:
2026-07-28 18:47:40 +07:00
parent 54c1ee9e94
commit 6c8eb79aac
+33 -29
View File
@@ -7717,6 +7717,38 @@ const App = () => {
const handleRedoRef = useRef(handleRedo); const handleRedoRef = useRef(handleRedo);
handleUndoRef.current = handleUndo; handleUndoRef.current = handleUndo;
handleRedoRef.current = handleRedo; handleRedoRef.current = handleRedo;
const handleDeleteSelectedItemsRef = useRef(() => {});
handleDeleteSelectedItemsRef.current = (idsToDelete) => {
const count = idsToDelete.size;
setSelectedItemIds(new Set());
updateActiveTracks(prev => prev.map(t => {
let changed = false;
const sections = (t.sections || []).filter(s => {
if (idsToDelete.has(s.id)) { changed = true; return false; }
return true;
});
const midiItems = (t.midiItems || []).filter(m => {
if (idsToDelete.has(m.id)) { changed = true; return false; }
return true;
});
const clips = (t.clips || []).filter(c => {
const canonical = c.id === 'default' ? 'default_' + t.id : c.id;
if (idsToDelete.has(canonical)) { changed = true; return false; }
return true;
});
if (!changed) return t;
return {
...t,
sections,
midiItems,
clips,
buffer: clips[0]?.buffer || null,
startTime: clips[0]?.startTime || 0,
name: clips[0]?.name || t.name
};
}));
showToast(count === 1 ? 'Đã xóa 1 item.' : `Đã xóa ${count} items.`, 'info');
};
const selectedClipIdRef = useRef(null); const selectedClipIdRef = useRef(null);
selectedClipIdRef.current = selectedClipId; selectedClipIdRef.current = selectedClipId;
const activeTabRef = useRef(activeTab); const activeTabRef = useRef(activeTab);
@@ -8164,35 +8196,7 @@ const App = () => {
if (selItems.size > 0) { if (selItems.size > 0) {
e.preventDefault(); e.preventDefault();
const idsToDelete = new Set(selItems); const idsToDelete = new Set(selItems);
setSelectedItemIds(new Set()); handleDeleteSelectedItemsRef.current(idsToDelete);
updateActiveTracks(prev => prev.map(t => {
let changed = false;
const sections = (t.sections || []).filter(s => {
if (idsToDelete.has(s.id)) { changed = true; return false; }
return true;
});
const midiItems = (t.midiItems || []).filter(m => {
if (idsToDelete.has(m.id)) { changed = true; return false; }
return true;
});
const clips = (t.clips || []).filter(c => {
const canonical = c.id === 'default' ? 'default_' + t.id : c.id;
if (idsToDelete.has(canonical)) { changed = true; return false; }
return true;
});
if (!changed) return t;
return {
...t,
sections,
midiItems,
clips,
buffer: clips[0]?.buffer || null,
startTime: clips[0]?.startTime || 0,
name: clips[0]?.name || t.name
};
}));
const count = idsToDelete.size;
showToast(count === 1 ? 'Đã xóa 1 item.' : `Đã xóa ${count} items.`, 'info');
return; return;
} }
const selClip = selectedClipIdRef.current; const selClip = selectedClipIdRef.current;