mirror of
https://github.com/YuzuZensai/VRC-Circle.git
synced 2026-09-13 10:58:59 +00:00
✨ feat: Persist main window size, position, and maximization
This commit is contained in:
@@ -108,7 +108,9 @@ const handlers = {
|
||||
"debug:repoFlush": (name) => guard(async () => debug.repoFlush(name)),
|
||||
"debug:openWindow": () => guard(async () => openDebugWindow()),
|
||||
} satisfies {
|
||||
[C in IpcRequestChannel]: (...args: Parameters<IpcRequests[C]>) => Promise<ReturnType<IpcRequests[C]>>;
|
||||
[C in IpcRequestChannel]: (
|
||||
...args: Parameters<IpcRequests[C]>
|
||||
) => Promise<ReturnType<IpcRequests[C]>>;
|
||||
};
|
||||
|
||||
export function registerIpcHandlers(): void {
|
||||
@@ -121,7 +123,5 @@ function register<C extends IpcRequestChannel>(channel: C): void {
|
||||
const handler = handlers[channel] as (
|
||||
...args: Parameters<IpcRequests[C]>
|
||||
) => Promise<ReturnType<IpcRequests[C]>>;
|
||||
ipcMain.handle(channel, (_event, ...args) =>
|
||||
handler(...(args as Parameters<IpcRequests[C]>)),
|
||||
);
|
||||
ipcMain.handle(channel, (_event, ...args) => handler(...(args as Parameters<IpcRequests[C]>)));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
import { app, screen, type BrowserWindow, type Rectangle } from "electron";
|
||||
import { join } from "node:path";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { writeFileAtomicSync } from "./lib/atomicFile";
|
||||
|
||||
type Bounds = Rectangle & { maximized: boolean };
|
||||
|
||||
const path = () => join(app.getPath("userData"), "window-state.json");
|
||||
|
||||
function read(): Partial<Bounds> | null {
|
||||
try {
|
||||
return JSON.parse(readFileSync(path(), "utf8")) as Partial<Bounds>;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function onScreen(b: Rectangle): boolean {
|
||||
return screen.getAllDisplays().some((d) => {
|
||||
const w = d.workArea;
|
||||
return (
|
||||
b.x < w.x + w.width && b.x + b.width > w.x && b.y < w.y + w.height && b.y + b.height > w.y
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function restoreBounds(): { bounds?: Rectangle; maximized: boolean } {
|
||||
const saved = read();
|
||||
if (
|
||||
saved &&
|
||||
saved.width &&
|
||||
saved.height &&
|
||||
saved.x != null &&
|
||||
saved.y != null &&
|
||||
onScreen({ x: saved.x, y: saved.y, width: saved.width, height: saved.height })
|
||||
) {
|
||||
return {
|
||||
bounds: { x: saved.x, y: saved.y, width: saved.width, height: saved.height },
|
||||
maximized: saved.maximized ?? false,
|
||||
};
|
||||
}
|
||||
return { maximized: saved?.maximized ?? false };
|
||||
}
|
||||
|
||||
export function trackBounds(win: BrowserWindow): void {
|
||||
let normalBounds = win.getBounds();
|
||||
|
||||
const save = (): void => {
|
||||
if (win.isDestroyed()) return;
|
||||
writeFileAtomicSync(
|
||||
path(),
|
||||
JSON.stringify({ ...normalBounds, maximized: win.isMaximized() }, null, 2),
|
||||
);
|
||||
};
|
||||
|
||||
const remember = (): void => {
|
||||
if (!win.isMaximized() && !win.isMinimized() && !win.isFullScreen()) {
|
||||
normalBounds = win.getBounds();
|
||||
}
|
||||
};
|
||||
|
||||
win.on("resize", remember);
|
||||
win.on("move", remember);
|
||||
win.on("close", save);
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import { join, dirname } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import type { IpcEventChannel, IpcEvents } from "../shared/ipc";
|
||||
import { TRAFFIC_LIGHT_INSET } from "../shared/window";
|
||||
import { restoreBounds, trackBounds } from "./windowState";
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const isDev = !app.isPackaged;
|
||||
@@ -25,9 +26,11 @@ function load(win: BrowserWindow, hash = ""): void {
|
||||
}
|
||||
|
||||
export function createMainWindow(): BrowserWindow {
|
||||
const restored = restoreBounds();
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 1180,
|
||||
height: 760,
|
||||
...restored.bounds,
|
||||
minWidth: 940,
|
||||
minHeight: 600,
|
||||
show: false,
|
||||
@@ -43,6 +46,9 @@ export function createMainWindow(): BrowserWindow {
|
||||
},
|
||||
});
|
||||
|
||||
if (restored.maximized) mainWindow.maximize();
|
||||
trackBounds(mainWindow);
|
||||
|
||||
mainWindow.once("ready-to-show", () => mainWindow?.show());
|
||||
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
|
||||
void shell.openExternal(url);
|
||||
|
||||
Reference in New Issue
Block a user