파일 삭제 기능 추가, undo / redo 기능에 적용
This commit is contained in:
+37
-10
@@ -1,35 +1,62 @@
|
||||
// History entries
|
||||
// reorder: { type:'reorder', files:[...], affectedPaths: Set|null }
|
||||
// delete: { type:'delete', files:[...] /* filesAfter */,
|
||||
// deletedEntries:[{name, originalPath, stagingPath}] /* mutable */ }
|
||||
|
||||
const MAX = 50;
|
||||
let _stack = [];
|
||||
let _cursor = -1;
|
||||
let _onUpdate = null;
|
||||
|
||||
export function setOnUpdate(fn) {
|
||||
_onUpdate = fn;
|
||||
export function setOnUpdate(fn) { _onUpdate = fn; }
|
||||
|
||||
// ── Push ─────────────────────────────────────────
|
||||
export function pushReorder(files, affectedPaths = null) {
|
||||
_truncate();
|
||||
_stack.push({
|
||||
type: 'reorder',
|
||||
files: [...files],
|
||||
affectedPaths: affectedPaths ? new Set(affectedPaths) : null,
|
||||
});
|
||||
_finalize();
|
||||
}
|
||||
|
||||
export function push(files, affectedPaths = null) {
|
||||
_stack = _stack.slice(0, _cursor + 1);
|
||||
_stack.push({ files: [...files], affectedPaths: affectedPaths ? new Set(affectedPaths) : null });
|
||||
export function pushDelete(filesAfter, deletedEntries) {
|
||||
_truncate();
|
||||
_stack.push({ type: 'delete', files: [...filesAfter], deletedEntries });
|
||||
_finalize();
|
||||
}
|
||||
|
||||
function _truncate() { _stack = _stack.slice(0, _cursor + 1); }
|
||||
function _finalize() {
|
||||
if (_stack.length > MAX) _stack.shift();
|
||||
_cursor = _stack.length - 1;
|
||||
_onUpdate?.();
|
||||
}
|
||||
|
||||
// Returns { files, affectedPaths } where affectedPaths are from the entry being undone
|
||||
// ── Undo / Redo ───────────────────────────────────
|
||||
// Returns { entry, targetFiles }
|
||||
// entry — the entry being undone/redone (for type-specific side-effects)
|
||||
// targetFiles — the files[] to restore in state
|
||||
export function undo() {
|
||||
if (!canUndo()) return null;
|
||||
const affectedPaths = _stack[_cursor].affectedPaths;
|
||||
const entry = _stack[_cursor]; // operation being undone
|
||||
--_cursor;
|
||||
_onUpdate?.();
|
||||
return { files: [..._stack[_cursor].files], affectedPaths };
|
||||
return { entry, targetFiles: [..._stack[_cursor].files] };
|
||||
}
|
||||
|
||||
// Returns { files, affectedPaths } from the entry being redone
|
||||
export function redo() {
|
||||
if (!canRedo()) return null;
|
||||
++_cursor;
|
||||
_onUpdate?.();
|
||||
return { files: [..._stack[_cursor].files], affectedPaths: _stack[_cursor].affectedPaths };
|
||||
const entry = _stack[_cursor];
|
||||
return { entry, targetFiles: [...entry.files] };
|
||||
}
|
||||
|
||||
// Peek at the next redo entry without moving cursor (for pre-processing)
|
||||
export function peekRedo() {
|
||||
return canRedo() ? _stack[_cursor + 1] : null;
|
||||
}
|
||||
|
||||
export function canUndo() { return _cursor > 0; }
|
||||
|
||||
Reference in New Issue
Block a user