리펙토링 - 수정 작업한 코드 최적화
This commit is contained in:
@@ -68,7 +68,7 @@ src/
|
||||
├── sidebar-resize.js # Pointer-drag resizing for the aside/main split; persisted 340–500px width
|
||||
├── selection.js # Rubber-band, Shift-click, Cmd+click, resetAnchor
|
||||
├── pinch-zoom.js # Ctrl+scroll to resize thumbnails (CSS --thumb-size, 150–400px)
|
||||
└── image-preview.js # Hover preview overlay with circular loading indicator
|
||||
└── image-preview.js # Hover preview overlay; immediate show/hide when enabled/disabled
|
||||
```
|
||||
|
||||
### IPC surface
|
||||
@@ -80,7 +80,7 @@ Defined in `src/main/ipc/`, bridged via `src/preload/index.js` as `window.api`:
|
||||
| `select-folder` | invoke | Opens native folder picker, returns path or null |
|
||||
| `list-images` | invoke | Reads directory, returns `{name, path, mtime}[]` filtered to image extensions, sorted by filename |
|
||||
| `read-image` | invoke | Reads file, returns base64 data URL (supports jpg/png/gif/webp/tiff/bmp/heic) |
|
||||
| `rename-files({folderPath, files, prefix, digits})` | invoke | Two-phase rename: temp names (crypto.randomUUID) first, then final names |
|
||||
| `rename-files({folderPath, files, prefix, digits, postfix})` | invoke | Two-phase rename: temp names (crypto.randomUUID) first, then final names using `prefix + padded sequence + postfix + ext` |
|
||||
| `check-files-exist(folderPath, names[])` | invoke | Returns subset of names that already exist in folderPath |
|
||||
| `move-files({targetFolder, files[]})` | invoke | Moves files; each file may have optional `newName`; handles cross-device (EXDEV) |
|
||||
| `stage-delete-files(paths[])` | invoke | Moves files to userData deleted_staging for undoable deletion; handles cross-device (EXDEV) |
|
||||
@@ -122,7 +122,7 @@ Prefer narrow utility modules (`utils/file-names.js`, `utils/dom.js`) over broad
|
||||
- `A` — 전체 선택
|
||||
- `Cmd+Z` — Undo (되돌리기)
|
||||
- `Cmd+Shift+Z` — Redo (다시하기)
|
||||
- `P` — 미리보기 on/off 토글
|
||||
- `Space` — 미리보기 on/off 토글
|
||||
- `Backspace` / `Delete` — 선택 파일 삭제 팝업
|
||||
|
||||
Global shortcuts are registered in `keyboard.js`. They do not fire while any `.modal-overlay` is open.
|
||||
@@ -164,6 +164,9 @@ Global shortcuts are registered in `keyboard.js`. They do not fire while any `.m
|
||||
|
||||
**Rename** (`rename.js`):
|
||||
- 선택된 파일만 이름 변경 (선택 없으면 전체)
|
||||
- 파일명 포맷은 `input-prefix` + 자리순번 + `input-postfix` + 확장자이다. 구분자 `_`는 자동 삽입하지 않고 입력값 자체에 포함한다.
|
||||
- `input-prefix`의 HTML 기본값은 `photo_`, `input-postfix`의 HTML 기본값은 `_`이다. 접미사를 비우면 접두사와 자리순번만으로 저장한다.
|
||||
- 상단 파일명 preview, 카드별 새 이름 라벨, rename 확인 목록은 모두 `utils/file-names.js`의 `getNameFormat()`과 `buildSequentialName()`을 사용해 같은 규칙을 공유한다.
|
||||
- 변경될 이름이 미선택 파일과 충돌하면 충돌 목록 모달 표시
|
||||
- 완료 후 history 리셋 (rename은 파일 경로가 바뀌므로 undo 대상 아님)
|
||||
|
||||
@@ -181,9 +184,9 @@ Global shortcuts are registered in `keyboard.js`. They do not fire while any `.m
|
||||
|
||||
**Thumbnail loading:** `IntersectionObserver` with `rootMargin: '400px 0px'` — lazy load as cards enter viewport. `entry.target.isConnected` 체크로 폴더 전환 중 스탈 카드 방지. Drag reorder remaps card elements via `card.dataset.filepath` to avoid re-fetching.
|
||||
|
||||
**Hover preview** (`image-preview.js`): 1초 지연 후 전체 크기 팝업. 썸네일 캐시 우선 사용. 상태는 config.json에 영속.
|
||||
**Hover preview** (`image-preview.js`): 활성화 상태에서 카드 hover 시 대기 없이 전체 크기 팝업을 표시한다. 썸네일 캐시 우선 사용. 상태는 config.json에 영속. `Space`로 preview를 켤 때 커서가 카드 위에 있으면 즉시 팝업을 표시하고, 끌 때는 열린 팝업을 즉시 닫는다.
|
||||
|
||||
**Sidebar tree** (`file-explorer.js`): Lazy-load 자식 폴더. 접근 불가 폴더는 `null` 반환 → "접근 불가" 표시. 행 클릭 시 항상 펼침, 화살표 클릭 시 토글.
|
||||
**Sidebar tree** (`file-explorer.js`): Lazy-load 자식 폴더. 접근 불가 폴더는 `null` 반환 → "접근 불가" 표시. 행 클릭 시 항상 펼침, 화살표 클릭 시 토글. 폴더 로드 후 `folder-controller.js`가 폴더명 뒤에 `_`를 붙여 `input-prefix`로 설정한다.
|
||||
|
||||
**Thumbnail size** (`pinch-zoom.js`): Ctrl+scroll changes CSS `--thumb-size` in the 150–400px range. The latest size is persisted as `thumbSize` in config.json and restored on startup without showing the size hint.
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
import { doRename } from './rename.js';
|
||||
import { handleFolderDrop } from './move.js';
|
||||
import { initModalControls } from './modal.js';
|
||||
import { clampDigits, getExtension } from './utils/file-names.js';
|
||||
import { buildSequentialName, getNameFormat } from './utils/file-names.js';
|
||||
import { initKeyboardShortcuts } from './keyboard.js';
|
||||
import { createFolderController } from './folder-controller.js';
|
||||
import { createHistoryController } from './history-controller.js';
|
||||
@@ -146,10 +146,8 @@ initKeyboardShortcuts({
|
||||
|
||||
// ── 포맷 미리보기 ─────────────────────────────────
|
||||
function updatePreview() {
|
||||
const prefix = inputPrefix.value.trim() || 'photo_';
|
||||
const digits = clampDigits(inputDigits.value);
|
||||
const postfix = inputPostfix.value.trim();
|
||||
const ext = state.files.length ? getExtension(state.files[0].name) : 'jpg';
|
||||
previewName.textContent = `${prefix}${'1'.padStart(digits, '0')}${postfix}.${ext}`;
|
||||
const format = getNameFormat(inputPrefix, inputDigits, 3, inputPostfix);
|
||||
const fileName = state.files[0]?.name || 'preview.jpg';
|
||||
previewName.textContent = buildSequentialName(fileName, 0, format);
|
||||
updateNewNameLabels();
|
||||
}
|
||||
|
||||
@@ -443,40 +443,6 @@ footer span { font-size: 11px; color: var(--muted); }
|
||||
@keyframes spin { to { transform: rotate(360deg); } }
|
||||
#loading p { color: var(--text); font-size: 14px; }
|
||||
|
||||
/* ── 카드 호버 원형 로딩바 ── */
|
||||
.card-hover-loader {
|
||||
position: absolute;
|
||||
top: calc(var(--thumb-size) / 2);
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
pointer-events: none;
|
||||
z-index: 10;
|
||||
overflow: visible;
|
||||
}
|
||||
.card-hover-loader .loader-bg {
|
||||
fill: rgba(0, 0, 0, 0.55);
|
||||
}
|
||||
.card-hover-loader .loader-track {
|
||||
fill: none;
|
||||
stroke: rgba(255, 255, 255, 0.15);
|
||||
stroke-width: 3;
|
||||
}
|
||||
.card-hover-loader .loader-progress {
|
||||
fill: none;
|
||||
stroke: var(--accent);
|
||||
stroke-width: 3;
|
||||
stroke-linecap: round;
|
||||
transform-origin: 24px 24px;
|
||||
transform: rotate(-90deg);
|
||||
animation: hover-loader-fill 1s linear forwards;
|
||||
}
|
||||
@keyframes hover-loader-fill {
|
||||
from { stroke-dashoffset: 125.66; }
|
||||
to { stroke-dashoffset: 0; }
|
||||
}
|
||||
|
||||
/* ── 호버 이미지 팝업 ── */
|
||||
.hover-preview {
|
||||
position: fixed;
|
||||
|
||||
Reference in New Issue
Block a user