129 lines
4.8 KiB
JavaScript
129 lines
4.8 KiB
JavaScript
import { state } from './state.js';
|
|
import { showLoading, hideLoading, setStatus, showToast } from './ui.js';
|
|
import { renderGrid } from './grid.js';
|
|
import * as history from './history.js';
|
|
import { openModal, closeModal } from './modal.js';
|
|
import { renderTextList } from './utils/dom.js';
|
|
import { buildSequentialName, getNameFormat } from './utils/file-names.js';
|
|
|
|
const inputPrefix = document.getElementById('input-prefix');
|
|
const inputDigits = document.getElementById('input-digits');
|
|
const inputPostfix = document.getElementById('input-postfix');
|
|
const renameConfirmModal = document.getElementById('rename-confirm-modal');
|
|
const renameConfirmSelectedTitle = renameConfirmModal.querySelector('.rename-title-selected');
|
|
const renameConfirmAllTitle = renameConfirmModal.querySelector('.rename-title-all');
|
|
const renameConfirmMsg = document.getElementById('rename-confirm-msg');
|
|
const renameConfirmWarning = document.getElementById('rename-confirm-selection-warning');
|
|
const renameConfirmList = document.getElementById('rename-confirm-list');
|
|
const renameConfirmOkBtn = document.getElementById('rename-confirm-ok');
|
|
const renameConflictModal = document.getElementById('rename-conflict-modal');
|
|
const renameConflictList = document.getElementById('rename-conflict-list');
|
|
|
|
let _renameConfirmResolve = null;
|
|
|
|
renameConfirmOkBtn.addEventListener('click', () => {
|
|
closeRenameConfirm(true);
|
|
});
|
|
|
|
renameConfirmModal.addEventListener('modal:closed', () => {
|
|
resolveRenameConfirm(false);
|
|
});
|
|
|
|
export async function doRename() {
|
|
if (!state.files.length || !state.currentFolder) return;
|
|
const { prefix, digits, postfix } = getNameFormat(inputPrefix, inputDigits, 3, inputPostfix);
|
|
const format = { prefix, digits, postfix };
|
|
|
|
const selectedArr = [...state.selectedIdxs].sort((a, b) => a - b);
|
|
const filesToRename = selectedArr.length > 0
|
|
? selectedArr.map(i => state.files[i]).filter(Boolean)
|
|
: state.files;
|
|
|
|
if (!filesToRename.length) return;
|
|
|
|
// 선택된 파일이 있으면 변경될 이름이 미선택 파일 이름과 충돌하는지 확인
|
|
if (selectedArr.length > 0) {
|
|
const unselectedNames = new Set(
|
|
state.files.filter((_, i) => !state.selectedIdxs.has(i)).map(f => f.name)
|
|
);
|
|
const newNames = filesToRename.map((f, i) => buildSequentialName(f.name, i, format));
|
|
const conflicting = newNames.filter(n => unselectedNames.has(n));
|
|
if (conflicting.length) {
|
|
renderTextList(renameConflictList, conflicting);
|
|
openModal(renameConflictModal);
|
|
return;
|
|
}
|
|
}
|
|
|
|
const examples = filesToRename.slice(0, 3)
|
|
.map((f, i) => `${f.name} → ${buildSequentialName(f.name, i, format)}`);
|
|
const more = filesToRename.length > 3 ? `... 외 ${filesToRename.length - 3}개` : '';
|
|
|
|
const confirmed = await showRenameConfirm({
|
|
count: filesToRename.length,
|
|
examples,
|
|
more,
|
|
isPartial: selectedArr.length > 0,
|
|
});
|
|
if (!confirmed) return;
|
|
|
|
showLoading('파일 이름 변경 중...');
|
|
setStatus('이름 변경 중...', false);
|
|
|
|
try {
|
|
const result = await window.api.renameFiles({
|
|
folderPath: state.currentFolder,
|
|
files: filesToRename,
|
|
prefix,
|
|
digits,
|
|
postfix,
|
|
});
|
|
hideLoading();
|
|
if (result.errors.length) {
|
|
alert('일부 오류:\n' + result.errors.join('\n'));
|
|
} else {
|
|
showToast(`✅ ${result.renamed.length}개 파일 이름 변경 완료!`);
|
|
setStatus(`${result.renamed.length}개 파일 이름 변경 완료`, true);
|
|
}
|
|
const newList = await window.api.listImages(state.currentFolder);
|
|
state.files.length = 0;
|
|
state.files.push(...newList);
|
|
state.selectedIdxs.clear();
|
|
renderGrid();
|
|
history.reset();
|
|
history.pushReorder(state.files);
|
|
} catch (e) {
|
|
hideLoading();
|
|
alert('오류 발생: ' + e.message);
|
|
}
|
|
}
|
|
|
|
function showRenameConfirm({ count, examples, more, isPartial }) {
|
|
renameConfirmSelectedTitle.hidden = !isPartial;
|
|
renameConfirmAllTitle.hidden = isPartial;
|
|
renameConfirmMsg.textContent = `${count}개 파일을 이름 변경합니다. 계속하시겠습니까?`;
|
|
renameConfirmWarning.style.display = isPartial ? 'block' : 'none';
|
|
|
|
const items = [...examples];
|
|
if (more) items.push(more);
|
|
renderTextList(renameConfirmList, items);
|
|
|
|
openModal(renameConfirmModal);
|
|
|
|
return new Promise(resolve => {
|
|
_renameConfirmResolve = resolve;
|
|
});
|
|
}
|
|
|
|
function closeRenameConfirm(confirmed) {
|
|
resolveRenameConfirm(confirmed);
|
|
closeModal(renameConfirmModal);
|
|
}
|
|
|
|
function resolveRenameConfirm(confirmed) {
|
|
if (_renameConfirmResolve) {
|
|
_renameConfirmResolve(confirmed);
|
|
_renameConfirmResolve = null;
|
|
}
|
|
}
|