101 lines
3.0 KiB
JavaScript
101 lines
3.0 KiB
JavaScript
import { state } from './state.js';
|
|
import { setStatus, showToast } from './ui.js';
|
|
import { renderGrid, showEmptyGrid } from './grid.js';
|
|
import * as history from './history.js';
|
|
|
|
export function createHistoryController({
|
|
btnRename,
|
|
btnUndo,
|
|
btnRedo,
|
|
updateSortButtons,
|
|
}) {
|
|
let busy = false;
|
|
|
|
function updateButtons() {
|
|
btnUndo.disabled = !history.canUndo();
|
|
btnRedo.disabled = !history.canRedo();
|
|
}
|
|
|
|
async function performUndo() {
|
|
if (busy || !history.canUndo()) {
|
|
if (!history.canUndo()) showToast('더 이상 되돌릴 수 없습니다');
|
|
return;
|
|
}
|
|
|
|
busy = true;
|
|
try {
|
|
const { entry, targetFiles } = history.undo();
|
|
if (entry.type === 'delete') {
|
|
const { restored, errors } = await window.api.restoreStagedFiles(entry.deletedEntries);
|
|
if (errors.length) showToast('일부 파일 복원 실패: ' + errors[0]);
|
|
applySnapshot(targetFiles, new Set(restored));
|
|
if (restored.length) setStatus(`${restored.length}개 파일 복원됨`, true);
|
|
} else {
|
|
applySnapshot(targetFiles, entry.affectedPaths);
|
|
}
|
|
} finally {
|
|
busy = false;
|
|
}
|
|
}
|
|
|
|
async function performRedo() {
|
|
if (busy || !history.canRedo()) {
|
|
if (!history.canRedo()) showToast('마지막 작업 상태입니다');
|
|
return;
|
|
}
|
|
|
|
busy = true;
|
|
try {
|
|
const nextEntry = history.peekRedo();
|
|
if (nextEntry.type === 'delete') {
|
|
const pathsToRedo = nextEntry.deletedEntries.map(e => e.originalPath);
|
|
const { staged, errors } = await window.api.stageDeleteFiles(pathsToRedo);
|
|
if (errors.length) showToast('일부 파일 삭제 실패: ' + errors[0]);
|
|
updateDeleteStagingPaths(nextEntry, staged);
|
|
const { targetFiles } = history.redo();
|
|
applySnapshot(targetFiles, null);
|
|
if (staged.length) setStatus(`${staged.length}개 파일 삭제됨`, true);
|
|
} else {
|
|
const { entry, targetFiles } = history.redo();
|
|
applySnapshot(targetFiles, entry.affectedPaths);
|
|
}
|
|
} finally {
|
|
busy = false;
|
|
}
|
|
}
|
|
|
|
function applySnapshot(targetFiles, affectedPaths = null) {
|
|
state.files.length = 0;
|
|
state.files.push(...targetFiles);
|
|
state.selectedIdxs.clear();
|
|
|
|
if (affectedPaths && affectedPaths.size > 0) {
|
|
const pathToIdx = new Map(state.files.map((f, i) => [f.path, i]));
|
|
affectedPaths.forEach(p => {
|
|
const idx = pathToIdx.get(p);
|
|
if (idx !== undefined) state.selectedIdxs.add(idx);
|
|
});
|
|
}
|
|
|
|
state.sortMode = null;
|
|
updateSortButtons();
|
|
if (!state.files.length) {
|
|
showEmptyGrid();
|
|
btnRename.disabled = true;
|
|
} else {
|
|
renderGrid();
|
|
btnRename.disabled = false;
|
|
}
|
|
updateButtons();
|
|
}
|
|
|
|
return { performUndo, performRedo, updateButtons };
|
|
}
|
|
|
|
function updateDeleteStagingPaths(entry, staged) {
|
|
const stagedByPath = new Map(staged.map(s => [s.originalPath, s.stagingPath]));
|
|
entry.deletedEntries.forEach(e => {
|
|
if (stagedByPath.has(e.originalPath)) e.stagingPath = stagedByPath.get(e.originalPath);
|
|
});
|
|
}
|