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); }); }