diff --git a/AGENTS.md b/AGENTS.md index b323d6b..e017560 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -34,7 +34,8 @@ src/ │ ├── file-utils.js # Shared main-process file helpers: image listing/data URLs, │ │ # exists check, EXDEV-safe move/copy fallback │ ├── folder.js # select-folder, list-directories, get/set-last-folder, -│ │ # get/set-preview-on, get-home-dir, reveal-folder +│ │ # get/set-preview-on, get/set-sidebar-width, +│ │ # get-home-dir, reveal-folder │ └── files.js # list-images, read-image, rename-files, stage/restore-delete, │ # check-files-exist, move-files ├── preload/ @@ -63,6 +64,7 @@ src/ │ ├── auto-scroll.js # Drag auto-scroll helper │ └── ghost.js # Drag ghost UI helper ├── file-explorer.js # Sidebar directory tree (lazy-load, expand/collapse) + ├── 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 @@ -86,6 +88,7 @@ Defined in `src/main/ipc/`, bridged via `src/preload/index.js` as `window.api`: | `get-home-dir` | invoke | Returns `os.homedir()` | | `get-last-folder` / `set-last-folder` | invoke | Persists last opened folder in userData config.json | | `get-preview-on` / `set-preview-on` | invoke | Persists hover preview toggle state in userData config.json | +| `get-sidebar-width` / `set-sidebar-width` | invoke | Persists sidebar width in userData config.json | | `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 | diff --git a/src/main/ipc/folder.js b/src/main/ipc/folder.js index 28478a0..8d4b858 100644 --- a/src/main/ipc/folder.js +++ b/src/main/ipc/folder.js @@ -68,6 +68,17 @@ function register(mainWindow) { cfg.previewOn = on; writeConfig(cfg); }); + + ipcMain.handle('get-sidebar-width', () => { + const cfg = readConfig(); + return Number.isFinite(cfg.sidebarWidth) ? cfg.sidebarWidth : null; + }); + + ipcMain.handle('set-sidebar-width', (_e, width) => { + const cfg = readConfig(); + cfg.sidebarWidth = width; + writeConfig(cfg); + }); } -module.exports = { register }; \ No newline at end of file +module.exports = { register }; diff --git a/src/preload/index.js b/src/preload/index.js index bc47d24..f19fade 100644 --- a/src/preload/index.js +++ b/src/preload/index.js @@ -17,6 +17,8 @@ contextBridge.exposeInMainWorld('api', { revealFolder: (p) => ipcRenderer.invoke('reveal-folder', p), getPreviewOn: () => ipcRenderer.invoke('get-preview-on'), setPreviewOn: (on) => ipcRenderer.invoke('set-preview-on', on), + getSidebarWidth: () => ipcRenderer.invoke('get-sidebar-width'), + setSidebarWidth: (width) => ipcRenderer.invoke('set-sidebar-width', width), checkFilesExist: (folder, names) => ipcRenderer.invoke('check-files-exist', folder, names), moveFiles: (args) => ipcRenderer.invoke('move-files', args), stageDeleteFiles: (paths) => ipcRenderer.invoke('stage-delete-files', paths), diff --git a/src/renderer/handlers/sidebar-resize.js b/src/renderer/handlers/sidebar-resize.js new file mode 100644 index 0000000..8fd61c8 --- /dev/null +++ b/src/renderer/handlers/sidebar-resize.js @@ -0,0 +1,54 @@ +const MIN_WIDTH = 340; +const MAX_WIDTH = 500; + +let _aside = null; +let _handle = null; +let _onResizeEnd = null; + +export function init({ aside, handle, initialWidth = MIN_WIDTH, onResizeEnd }) { + _aside = aside; + _handle = handle; + _onResizeEnd = onResizeEnd; + + setWidth(initialWidth); + _handle.addEventListener('pointerdown', onPointerDown); +} + +function onPointerDown(e) { + e.preventDefault(); + _handle.setPointerCapture(e.pointerId); + document.body.classList.add('resizing-sidebar'); + + _handle.addEventListener('pointermove', onPointerMove); + _handle.addEventListener('pointerup', onPointerUp); + _handle.addEventListener('pointercancel', onPointerUp); +} + +function onPointerMove(e) { + const left = _aside.getBoundingClientRect().left; + setWidth(e.clientX - left); +} + +function onPointerUp(e) { + if (_handle.hasPointerCapture(e.pointerId)) { + _handle.releasePointerCapture(e.pointerId); + } + + document.body.classList.remove('resizing-sidebar'); + _handle.removeEventListener('pointermove', onPointerMove); + _handle.removeEventListener('pointerup', onPointerUp); + _handle.removeEventListener('pointercancel', onPointerUp); + _onResizeEnd?.(getWidth()); +} + +function setWidth(width) { + _aside.style.width = `${clampWidth(width)}px`; +} + +function getWidth() { + return Math.round(_aside.getBoundingClientRect().width); +} + +function clampWidth(width) { + return Math.max(MIN_WIDTH, Math.min(MAX_WIDTH, Number(width) || MIN_WIDTH)); +} diff --git a/src/renderer/index.html b/src/renderer/index.html index 8981ef2..5575eea 100644 --- a/src/renderer/index.html +++ b/src/renderer/index.html @@ -24,6 +24,8 @@ +
+