From e4e1be49ca8c8d019b6e7c6f17985cd645134062 Mon Sep 17 00:00:00 2001 From: ByungCheol Date: Sat, 27 Jun 2026 23:57:41 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20PC=20=ED=99=94=EB=A9=B4=20=ED=95=B4?= =?UTF-8?q?=EC=83=81=EB=8F=84=20=EB=B3=80=EA=B2=BD=20=E2=80=94=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=EC=97=90=EC=84=9C=20=EC=B0=BD=20=ED=81=AC=EA=B8=B0=20?= =?UTF-8?q?=ED=94=84=EB=A6=AC=EC=85=8B=20=EC=84=A0=ED=83=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - electron/preload.cjs: contextBridge 로 window.desktop.setWindowSize 노출 - main.cjs: preload 연결 + ipcMain 'window:setSize'/'getSize' 핸들러 - SettingsView: PC(window.desktop 존재 시)에서 해상도 선택 추가 (1024×720 ~ 1920×1080), 선택 시 창 크기 변경+가운데 정렬 Co-Authored-By: Claude Opus 4.8 --- electron/main.cjs | 17 ++++++++++++++- electron/preload.cjs | 8 +++++++ src/views/settings/SettingsView.vue | 34 +++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 electron/preload.cjs diff --git a/electron/main.cjs b/electron/main.cjs index b45b068..e606362 100644 --- a/electron/main.cjs +++ b/electron/main.cjs @@ -1,7 +1,7 @@ // Slim Budget 데스크톱(Electron) 메인 프로세스. // 라이브 사이트(https://app.sblog.kr)를 직접 로드한다 → 프론트 변경이 자동 반영(재설치 불필요), // 같은 출처라 CORS 우회도 불필요. 배포된 웹 게이트가 Electron 을 감지해 안내페이지 대신 전체 앱을 띄운다. -const { app, BrowserWindow, shell, session } = require('electron') +const { app, BrowserWindow, shell, session, ipcMain } = require('electron') const fs = require('fs') const path = require('path') @@ -58,6 +58,7 @@ function createWindow() { webPreferences: { contextIsolation: true, nodeIntegration: false, + preload: path.join(__dirname, 'preload.cjs'), // 한글 IME 첫 글자 중복 입력 방지 — Chromium 맞춤법 검사기가 조합을 방해하는 Electron 알려진 버그 회피 spellcheck: false, }, @@ -91,6 +92,20 @@ function createWindow() { }) } +// 데스크톱 창 크기(해상도) 변경 — 렌더러(설정 화면)에서 호출 +ipcMain.handle('window:setSize', (e, w, h) => { + const win = BrowserWindow.fromWebContents(e.sender) + if (!win) return false + if (win.isMaximized()) win.unmaximize() + win.setSize(Math.max(360, Math.round(w)), Math.max(560, Math.round(h))) + win.center() + return true +}) +ipcMain.handle('window:getSize', (e) => { + const win = BrowserWindow.fromWebContents(e.sender) + return win ? win.getSize() : [0, 0] +}) + app.whenReady().then(async () => { // 시작 시 HTTP 캐시 비움 → 라이브 사이트의 최신 프론트를 항상 로드(옛 HTML 캐시로 인한 미반영 방지). // localStorage(로그인 세션)는 캐시가 아니라 영향 없음. diff --git a/electron/preload.cjs b/electron/preload.cjs new file mode 100644 index 0000000..ac99982 --- /dev/null +++ b/electron/preload.cjs @@ -0,0 +1,8 @@ +// 렌더러(웹)에서 안전하게 호출할 데스크톱 전용 API 노출 (contextIsolation 유지). +const { contextBridge, ipcRenderer } = require('electron') + +contextBridge.exposeInMainWorld('desktop', { + // 데스크톱 창 크기(해상도) 변경 + setWindowSize: (w, h) => ipcRenderer.invoke('window:setSize', w, h), + getWindowSize: () => ipcRenderer.invoke('window:getSize'), +}) diff --git a/src/views/settings/SettingsView.vue b/src/views/settings/SettingsView.vue index 8f356d7..ac1625e 100644 --- a/src/views/settings/SettingsView.vue +++ b/src/views/settings/SettingsView.vue @@ -15,6 +15,22 @@ const THEMES = [ const appVersion = typeof __APP_VERSION__ !== 'undefined' ? __APP_VERSION__ : '-' const clearing = ref(false) +// PC(데스크톱) 전용: 창 해상도 변경 (Electron preload 의 window.desktop 존재 시에만) +const isDesktop = typeof window !== 'undefined' && !!window.desktop +const RESOLUTIONS = [ + { label: '1024 × 720', w: 1024, h: 720 }, + { label: '1280 × 800', w: 1280, h: 800 }, + { label: '1366 × 768', w: 1366, h: 768 }, + { label: '1600 × 900', w: 1600, h: 900 }, + { label: '1920 × 1080', w: 1920, h: 1080 }, +] +function onResolution(e) { + const v = e.target.value + if (!v) return + const [w, h] = v.split('x').map(Number) + window.desktop?.setWindowSize(w, h) +} + async function clearAppData() { if (clearing.value) return const ok = await dialog.confirm( @@ -62,6 +78,20 @@ async function clearAppData() { + +
+
+
+ 화면 해상도 + 데스크톱 창 크기를 선택한 크기로 변경 +
+ +
+
+
@@ -164,6 +194,10 @@ async function clearAppData() { overflow: hidden; flex-shrink: 0; } +.res-select { + flex: none; + max-width: 150px; +} .seg-btn { padding: 0.4rem 0.7rem; border: 0;