feat: PC 화면 해상도 변경 — 설정에서 창 크기 프리셋 선택
CI / build (push) Failing after 14m21s

- 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 <noreply@anthropic.com>
This commit is contained in:
ByungCheol
2026-06-27 23:57:41 +09:00
parent f34980048b
commit e4e1be49ca
3 changed files with 58 additions and 1 deletions
+16 -1
View File
@@ -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(로그인 세션)는 캐시가 아니라 영향 없음.
+8
View File
@@ -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'),
})
+34
View File
@@ -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() {
</div>
</section>
<!-- PC(데스크톱) 전용: 해상도 -->
<section v-if="isDesktop" class="card">
<div class="row">
<div class="row-main">
<span class="row-label">화면 해상도</span>
<span class="row-sub">데스크톱 크기를 선택한 크기로 변경</span>
</div>
<select class="res-select" @change="onResolution">
<option value="">선택</option>
<option v-for="r in RESOLUTIONS" :key="r.label" :value="`${r.w}x${r.h}`">{{ r.label }}</option>
</select>
</div>
</section>
<section class="card">
<RouterLink to="/settings/account" class="row row-link">
<div class="row-main">
@@ -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;