- App.vue: 비로그인 시 사이드바 숨김·단일 컬럼 그리드 → 콘텐츠가 창 중앙 정렬 (프론트 변경이라 데스크톱은 재설치 없이 자동 반영) - electron/main.cjs: 기본 창 1024x720 + 마지막 크기/위치/최대화 상태 저장·복원 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+32
-2
@@ -2,9 +2,32 @@
|
|||||||
// 라이브 사이트(https://app.sblog.kr)를 직접 로드한다 → 프론트 변경이 자동 반영(재설치 불필요),
|
// 라이브 사이트(https://app.sblog.kr)를 직접 로드한다 → 프론트 변경이 자동 반영(재설치 불필요),
|
||||||
// 같은 출처라 CORS 우회도 불필요. 배포된 웹 게이트가 Electron 을 감지해 안내페이지 대신 전체 앱을 띄운다.
|
// 같은 출처라 CORS 우회도 불필요. 배포된 웹 게이트가 Electron 을 감지해 안내페이지 대신 전체 앱을 띄운다.
|
||||||
const { app, BrowserWindow, shell } = require('electron')
|
const { app, BrowserWindow, shell } = require('electron')
|
||||||
|
const fs = require('fs')
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
const APP_URL = 'https://app.sblog.kr'
|
const APP_URL = 'https://app.sblog.kr'
|
||||||
|
|
||||||
|
// 창 크기/위치를 userData 에 저장해 다음 실행 때 복원 (기본 해상도 고정 대신 사용자가 맞춘 크기 유지)
|
||||||
|
function stateFile() {
|
||||||
|
return path.join(app.getPath('userData'), 'window-state.json')
|
||||||
|
}
|
||||||
|
function loadState() {
|
||||||
|
try {
|
||||||
|
return JSON.parse(fs.readFileSync(stateFile(), 'utf-8'))
|
||||||
|
} catch {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function saveState(win) {
|
||||||
|
try {
|
||||||
|
if (win.isMinimized()) return
|
||||||
|
const b = win.getBounds()
|
||||||
|
fs.writeFileSync(stateFile(), JSON.stringify({ ...b, maximized: win.isMaximized() }))
|
||||||
|
} catch {
|
||||||
|
/* 저장 실패 무시 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 오프라인/로드 실패 시 안내 화면 (다시 시도 버튼)
|
// 오프라인/로드 실패 시 안내 화면 (다시 시도 버튼)
|
||||||
function offlineHtml() {
|
function offlineHtml() {
|
||||||
const html = `<!doctype html><html><head><meta charset="utf-8"><title>Slim Budget</title>
|
const html = `<!doctype html><html><head><meta charset="utf-8"><title>Slim Budget</title>
|
||||||
@@ -19,9 +42,12 @@ font-size:15px;font-weight:600;cursor:pointer}</style></head>
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createWindow() {
|
function createWindow() {
|
||||||
|
const s = loadState()
|
||||||
const win = new BrowserWindow({
|
const win = new BrowserWindow({
|
||||||
width: 1200,
|
width: s?.width || 1024,
|
||||||
height: 820,
|
height: s?.height || 720,
|
||||||
|
x: s?.x,
|
||||||
|
y: s?.y,
|
||||||
minWidth: 360,
|
minWidth: 360,
|
||||||
minHeight: 560,
|
minHeight: 560,
|
||||||
backgroundColor: '#1a1a1a',
|
backgroundColor: '#1a1a1a',
|
||||||
@@ -31,11 +57,15 @@ function createWindow() {
|
|||||||
nodeIntegration: false,
|
nodeIntegration: false,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
if (s?.maximized) win.maximize()
|
||||||
|
|
||||||
// 기본 메뉴바 제거(앱 자체 내비게이션 사용)
|
// 기본 메뉴바 제거(앱 자체 내비게이션 사용)
|
||||||
win.removeMenu()
|
win.removeMenu()
|
||||||
win.loadURL(APP_URL)
|
win.loadURL(APP_URL)
|
||||||
|
|
||||||
|
// 닫을 때 창 크기/위치 저장 → 다음 실행에 복원
|
||||||
|
win.on('close', () => saveState(win))
|
||||||
|
|
||||||
// 메인 프레임 로드 실패(오프라인 등) 시 안내 화면. -3(aborted, 리다이렉트 등)은 무시.
|
// 메인 프레임 로드 실패(오프라인 등) 시 안내 화면. -3(aborted, 리다이렉트 등)은 무시.
|
||||||
win.webContents.on('did-fail-load', (event, errorCode, errorDescription, validatedURL, isMainFrame) => {
|
win.webContents.on('did-fail-load', (event, errorCode, errorDescription, validatedURL, isMainFrame) => {
|
||||||
if (isMainFrame && errorCode !== -3) win.loadURL(offlineHtml())
|
if (isMainFrame && errorCode !== -3) win.loadURL(offlineHtml())
|
||||||
|
|||||||
+15
-3
@@ -42,10 +42,13 @@ watch(() => route.fullPath, () => ui.closeSidebar())
|
|||||||
|
|
||||||
<!-- 앱(Capacitor): 전체 기능 -->
|
<!-- 앱(Capacitor): 전체 기능 -->
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div class="layout" :class="{ 'sidebar-open': ui.sidebarOpen }">
|
<div class="layout" :class="{ 'sidebar-open': ui.sidebarOpen, 'no-sidebar': !auth.isAuthenticated }">
|
||||||
<AppHeader class="layout-top" />
|
<AppHeader class="layout-top" />
|
||||||
<AppSidebar class="layout-left" />
|
<!-- 로그인 전에는 메뉴가 없어 사이드바를 숨김(빈 칸 제거·중앙 정렬) -->
|
||||||
<div class="sidebar-backdrop" @click="ui.closeSidebar()"></div>
|
<template v-if="auth.isAuthenticated">
|
||||||
|
<AppSidebar class="layout-left" />
|
||||||
|
<div class="sidebar-backdrop" @click="ui.closeSidebar()"></div>
|
||||||
|
</template>
|
||||||
<main class="layout-body">
|
<main class="layout-body">
|
||||||
<RouterView />
|
<RouterView />
|
||||||
</main>
|
</main>
|
||||||
@@ -89,6 +92,15 @@ watch(() => route.fullPath, () => ui.closeSidebar())
|
|||||||
grid-area: bottom;
|
grid-area: bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 로그인 전: 사이드바 없이 단일 컬럼 — 콘텐츠가 창 중앙에 오도록 */
|
||||||
|
.layout.no-sidebar {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
grid-template-areas:
|
||||||
|
'top'
|
||||||
|
'body'
|
||||||
|
'bottom';
|
||||||
|
}
|
||||||
|
|
||||||
.sidebar-backdrop {
|
.sidebar-backdrop {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user