리펙토링: 디렉토리, 파일명을 Node.js 프로젝트 구성으로 적용

This commit is contained in:
2026-05-14 16:33:38 +09:00
parent 1c08290f69
commit fb5751f885
3 changed files with 48 additions and 14 deletions
+47 -13
View File
@@ -17,23 +17,57 @@ There are no tests or linting configured.
This is a macOS Electron desktop app for batch-renaming photo files. It follows strict Electron security practices: `contextIsolation: true`, `nodeIntegration: false`.
**Process boundary:** All filesystem access lives exclusively in `src/main.js` (main process). The renderer never touches `fs` directly.
**Process boundary:** All filesystem access lives exclusively in `src/main/` (main process). The renderer never touches `fs` directly.
**IPC surface** (defined in `main.js`, bridged via `preload.js` as `window.api`):
- `select-folder` → opens native folder picker, returns path
- `list-images` → reads directory, returns `{name, path, mtime, size}[]` filtered to image extensions
- `read-image` → reads file, returns base64 data URL for display
- `rename-files({folderPath, files, prefix, digits})` → two-phase rename (temp names first, then final names) to avoid collisions when new names overlap old names
- `reveal-folder` → opens folder in Finder via `shell.openPath`
### File structure
**Renderer (`src/renderer.js`):** Single-file, no framework. All state is module-level globals:
```
src/
├── main/
│ ├── index.js # Main process entry point; creates BrowserWindow, calls registerAll()
│ └── ipc/
│ ├── index.js # registerAll(mainWindow) — delegates to folder and files modules
│ ├── folder.js # select-folder, reveal-folder
│ └── files.js # list-images, read-image, rename-files
├── preload/
│ └── index.js # Bridges IPC to window.api via contextBridge (isolated context)
└── renderer/
├── index.html # App shell (dark theme, CSS variables in :root)
├── style.css # All CSS
├── renderer.js # Main renderer logic; imports state and handlers
├── state.js # Shared mutable state: files[], currentFolder, selectedIdxs, sortMode
└── handlers/
├── drag-drop.js # Card drag-and-drop reorder (single and multi-card)
├── selection.js # Rubber-band selection, Shift-click, Cmd+click
├── pinch-zoom.js # Trackpad pinch to resize thumbnails (CSS --thumb-size, 150400px)
└── hover-preview.js # Hover preview overlay
```
### IPC surface
Defined in `src/main/ipc/`, bridged via `src/preload/index.js` as `window.api`:
| Channel | Direction | Description |
|---|---|---|
| `select-folder` | invoke | Opens native folder picker, returns path or null |
| `list-images` | invoke | Reads directory, returns `{name, path, mtime, size}[]` filtered to image extensions, sorted by filename |
| `read-image` | invoke | Reads file, returns base64 data URL for display |
| `rename-files({folderPath, files, prefix, digits})` | invoke | Two-phase rename: temp names first, then final names to avoid collisions |
| `reveal-folder` | invoke | Opens folder in Finder via `shell.openPath` |
| `fullscreen-change` | push (main→renderer) | Sent on `enter-full-screen` / `leave-full-screen` window events |
### Renderer (`src/renderer/`)
Uses ES module imports (`type="module"`). No framework.
**State** (`src/renderer/state.js`):
- `files[]` — ordered array of file objects; order determines rename sequence
- `selectedIdxs``Set<number>` of selected card indices
- Thumbnail grid uses CSS `--thumb-size` custom property (150400px), adjusted via trackpad pinch (`ctrlKey + wheel`)
- Rubber-band selection: drag on empty grid area to select multiple cards; `Shift` adds to existing selection; `Cmd+click` toggles individual cards
- Drag-and-drop reorder: single card drag or multi-card drag (moves selected group); DOM reorder avoids re-fetching images by remapping existing card elements via `card.dataset.filepath`
- Thumbnails load in batches of 10 (`Promise.all`) to avoid blocking the UI
- `currentFolder` — active directory path
- `sortMode``'name'` | `'date'` | `null`
**Styling:** All CSS is inline in `src/index.html`. Dark theme with CSS variables defined in `:root`. The macOS traffic-light buttons sit in `#titlebar` which uses `-webkit-app-region: drag`.
**Thumbnail loading:** Uses `IntersectionObserver` with `rootMargin: '400px 0px'` — images load lazily as cards enter the viewport. DOM card elements are created immediately without `src`; the observer fills in `img.src` on entry. Drag-and-drop reorder remaps existing card elements via `card.dataset.filepath` to avoid re-fetching images.
**Styling:** All CSS lives in `src/renderer/index.html`. Dark theme with CSS variables defined in `:root`. The macOS traffic-light buttons sit in `#titlebar` with `-webkit-app-region: drag`.
**Build output:** `electron-builder` targets DMG for arm64 and x64. The app icon must be at `assets/icon.icns`.