From d74c2e055d0fcecd9f49b001a6b4396b1182dfa3 Mon Sep 17 00:00:00 2001 From: jisangs Date: Mon, 18 May 2026 09:39:19 +0900 Subject: [PATCH] =?UTF-8?q?=EC=95=B1=EC=9D=84=20=EC=A2=85=EB=A3=8C?= =?UTF-8?q?=ED=95=A0=20=EB=95=8C=20-=20=EC=A0=84=EC=B2=B4=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=20=EB=AA=A8=EB=93=9C=20=EC=83=81=ED=83=9C=20=EC=97=AC?= =?UTF-8?q?=EB=B6=80,=20=ED=99=94=EB=A9=B4=20=ED=81=AC=EA=B8=B0,=20?= =?UTF-8?q?=ED=99=94=EB=A9=B4=20=EC=9C=84=EC=B9=98=20=EC=A0=95=EB=B3=B4?= =?UTF-8?q?=EB=A5=BC=20=EC=A0=80=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 3 ++- src/main/config.js | 31 ++++++++++++++++++++++++++++ src/main/index.js | 47 +++++++++++++++++++++++++++++++++++++++--- src/main/ipc/folder.js | 24 +++++---------------- 4 files changed, 82 insertions(+), 23 deletions(-) create mode 100644 src/main/config.js diff --git a/AGENTS.md b/AGENTS.md index e017560..74218b0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -29,6 +29,7 @@ assets/ src/ ├── main/ │ ├── index.js # Main process entry point; app.setName(), BrowserWindow, registerAll() +│ ├── config.js # Shared userData/config.json read/write helpers │ └── ipc/ │ ├── index.js # registerAll(mainWindow) — delegates to folder and files modules │ ├── file-utils.js # Shared main-process file helpers: image listing/data URLs, @@ -189,4 +190,4 @@ Global shortcuts are registered in `keyboard.js`. They do not fire while any `.m **Build output:** `electron-builder` targets DMG for arm64 and x64. -**Config persistence:** `app.getPath('userData')/config.json`에 `lastFolder`, `previewOn` 저장. +**Config persistence:** `app.getPath('userData')/config.json`에 `lastFolder`, `previewOn`, `sidebarWidth`, `windowState` 저장. `windowState` includes fullscreen status and normal window bounds (`x`, `y`, `width`, `height`) and is restored on startup if the saved bounds overlap an available display. diff --git a/src/main/config.js b/src/main/config.js new file mode 100644 index 0000000..e12eab3 --- /dev/null +++ b/src/main/config.js @@ -0,0 +1,31 @@ +const { app } = require('electron'); +const path = require('path'); +const fs = require('fs'); + +const configPath = path.join(app.getPath('userData'), 'config.json'); + +function readConfig() { + try { + return JSON.parse(fs.readFileSync(configPath, 'utf8')); + } catch { + return {}; + } +} + +function writeConfig(data) { + try { + fs.writeFileSync(configPath, JSON.stringify(data, null, 2)); + } catch {} +} + +function updateConfig(updater) { + const cfg = readConfig(); + updater(cfg); + writeConfig(cfg); +} + +module.exports = { + readConfig, + updateConfig, + writeConfig, +}; diff --git a/src/main/index.js b/src/main/index.js index 0080d9d..adc98ea 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -1,15 +1,19 @@ -const { app, BrowserWindow } = require('electron'); +const { app, BrowserWindow, screen } = require('electron'); const path = require('path'); const { registerAll } = require('./ipc'); +const { readConfig, updateConfig } = require('./config'); app.setName('Photo Renamer'); let mainWindow; function createWindow() { + const windowState = getSavedWindowState(); mainWindow = new BrowserWindow({ - width: 1200, - height: 820, + x: windowState.bounds?.x, + y: windowState.bounds?.y, + width: windowState.bounds?.width || 1200, + height: windowState.bounds?.height || 820, minWidth: 900, minHeight: 600, titleBarStyle: 'hiddenInset', @@ -27,8 +31,11 @@ function createWindow() { mainWindow.once('ready-to-show', () => { mainWindow.show(); + if (windowState.isFullScreen) mainWindow.setFullScreen(true); }); + mainWindow.on('close', saveWindowState); + mainWindow.on('enter-full-screen', () => { mainWindow.webContents.send('fullscreen-change', true); }); @@ -37,6 +44,40 @@ function createWindow() { }); } +function getSavedWindowState() { + const cfg = readConfig(); + const state = cfg.windowState || {}; + const bounds = isUsableBounds(state.bounds) ? state.bounds : null; + return { + bounds, + isFullScreen: state.isFullScreen === true, + }; +} + +function isUsableBounds(bounds) { + if (!bounds) return false; + const values = [bounds.x, bounds.y, bounds.width, bounds.height]; + if (!values.every(Number.isFinite)) return false; + if (bounds.width < 900 || bounds.height < 600) return false; + return screen.getAllDisplays().some(display => rectanglesOverlap(bounds, display.workArea)); +} + +function rectanglesOverlap(a, b) { + return a.x < b.x + b.width && + a.x + a.width > b.x && + a.y < b.y + b.height && + a.y + a.height > b.y; +} + +function saveWindowState() { + if (!mainWindow) return; + const isFullScreen = mainWindow.isFullScreen(); + const bounds = isFullScreen ? mainWindow.getNormalBounds() : mainWindow.getBounds(); + updateConfig(cfg => { + cfg.windowState = { isFullScreen, bounds }; + }); +} + app.whenReady().then(() => { createWindow(); registerAll(mainWindow); diff --git a/src/main/ipc/folder.js b/src/main/ipc/folder.js index 8d4b858..a02c9a8 100644 --- a/src/main/ipc/folder.js +++ b/src/main/ipc/folder.js @@ -1,16 +1,8 @@ -const { ipcMain, dialog, app, shell } = require('electron'); +const { ipcMain, dialog, shell } = require('electron'); const path = require('path'); const fs = require('fs'); const os = require('os'); - -const configPath = path.join(app.getPath('userData'), 'config.json'); - -function readConfig() { - try { return JSON.parse(fs.readFileSync(configPath, 'utf8')); } catch { return {}; } -} -function writeConfig(data) { - try { fs.writeFileSync(configPath, JSON.stringify(data, null, 2)); } catch {} -} +const { readConfig, updateConfig } = require('../config'); function register(mainWindow) { ipcMain.handle('select-folder', async () => { @@ -33,9 +25,7 @@ function register(mainWindow) { }); ipcMain.handle('set-last-folder', (_e, folderPath) => { - const cfg = readConfig(); - cfg.lastFolder = folderPath; - writeConfig(cfg); + updateConfig(cfg => { cfg.lastFolder = folderPath; }); }); ipcMain.handle('list-directories', (_e, folderPath) => { @@ -64,9 +54,7 @@ function register(mainWindow) { }); ipcMain.handle('set-preview-on', (_e, on) => { - const cfg = readConfig(); - cfg.previewOn = on; - writeConfig(cfg); + updateConfig(cfg => { cfg.previewOn = on; }); }); ipcMain.handle('get-sidebar-width', () => { @@ -75,9 +63,7 @@ function register(mainWindow) { }); ipcMain.handle('set-sidebar-width', (_e, width) => { - const cfg = readConfig(); - cfg.sidebarWidth = width; - writeConfig(cfg); + updateConfig(cfg => { cfg.sidebarWidth = width; }); }); }