refactor(desktop): move title bar overlay logic to window-manager and add setTitleBarTheme IPC
This commit is contained in:
@@ -4,7 +4,7 @@ log.initialize({ spyRendererConsole: true });
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { pathToFileURL } from "node:url";
|
import { pathToFileURL } from "node:url";
|
||||||
import { existsSync } from "node:fs";
|
import { existsSync } from "node:fs";
|
||||||
import { app, BrowserWindow, nativeImage, nativeTheme, net, protocol } from "electron";
|
import { app, BrowserWindow, nativeImage, net, protocol } from "electron";
|
||||||
import { registerDaemonManager } from "./daemon/daemon-manager.js";
|
import { registerDaemonManager } from "./daemon/daemon-manager.js";
|
||||||
import {
|
import {
|
||||||
parseCliPassthroughArgsFromArgv,
|
parseCliPassthroughArgsFromArgv,
|
||||||
@@ -13,6 +13,8 @@ import {
|
|||||||
import { closeAllTransportSessions } from "./daemon/local-transport.js";
|
import { closeAllTransportSessions } from "./daemon/local-transport.js";
|
||||||
import {
|
import {
|
||||||
registerWindowManager,
|
registerWindowManager,
|
||||||
|
getTitleBarOverlayOptions,
|
||||||
|
resolveSystemWindowTheme,
|
||||||
setupWindowResizeEvents,
|
setupWindowResizeEvents,
|
||||||
setupDragDropPrevention,
|
setupDragDropPrevention,
|
||||||
} from "./window/window-manager.js";
|
} from "./window/window-manager.js";
|
||||||
@@ -32,17 +34,6 @@ protocol.registerSchemesAsPrivileged([
|
|||||||
{ scheme: APP_SCHEME, privileges: { standard: true, secure: true, supportFetchAPI: true } },
|
{ scheme: APP_SCHEME, privileges: { standard: true, secure: true, supportFetchAPI: true } },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// Window chrome
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
function getTitleBarOverlayColors(): Electron.TitleBarOverlayOptions {
|
|
||||||
if (nativeTheme.shouldUseDarkColors) {
|
|
||||||
return { color: "#18181c", symbolColor: "#e4e4e7", height: 48 };
|
|
||||||
}
|
|
||||||
return { color: "#ffffff", symbolColor: "#09090b", height: 48 };
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Window creation
|
// Window creation
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -107,7 +98,7 @@ async function createMainWindow(): Promise<void> {
|
|||||||
...(isMac
|
...(isMac
|
||||||
? { trafficLightPosition: { x: 16, y: 14 } }
|
? { trafficLightPosition: { x: 16, y: 14 } }
|
||||||
: {
|
: {
|
||||||
titleBarOverlay: getTitleBarOverlayColors(),
|
titleBarOverlay: getTitleBarOverlayOptions(resolveSystemWindowTheme()),
|
||||||
autoHideMenuBar: true,
|
autoHideMenuBar: true,
|
||||||
}),
|
}),
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
@@ -119,13 +110,6 @@ async function createMainWindow(): Promise<void> {
|
|||||||
|
|
||||||
setupWindowResizeEvents(mainWindow);
|
setupWindowResizeEvents(mainWindow);
|
||||||
setupDragDropPrevention(mainWindow);
|
setupDragDropPrevention(mainWindow);
|
||||||
|
|
||||||
if (!isMac) {
|
|
||||||
nativeTheme.on("updated", () => {
|
|
||||||
mainWindow.setTitleBarOverlay(getTitleBarOverlayColors());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
mainWindow.once("ready-to-show", () => {
|
mainWindow.once("ready-to-show", () => {
|
||||||
mainWindow.show();
|
mainWindow.show();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ contextBridge.exposeInMainWorld("paseoDesktop", {
|
|||||||
endMove: () => ipcRenderer.send("paseo:window:endMove"),
|
endMove: () => ipcRenderer.send("paseo:window:endMove"),
|
||||||
toggleMaximize: () => ipcRenderer.invoke("paseo:window:toggleMaximize"),
|
toggleMaximize: () => ipcRenderer.invoke("paseo:window:toggleMaximize"),
|
||||||
isFullscreen: () => ipcRenderer.invoke("paseo:window:isFullscreen"),
|
isFullscreen: () => ipcRenderer.invoke("paseo:window:isFullscreen"),
|
||||||
|
setTitleBarTheme: (theme: "light" | "dark") =>
|
||||||
|
ipcRenderer.invoke("paseo:window:setTitleBarTheme", theme),
|
||||||
onResized: (handler: EventHandler): (() => void) => {
|
onResized: (handler: EventHandler): (() => void) => {
|
||||||
const listener = (_ipcEvent: Electron.IpcRendererEvent, payload: unknown) => {
|
const listener = (_ipcEvent: Electron.IpcRendererEvent, payload: unknown) => {
|
||||||
handler(payload);
|
handler(payload);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
import { readBadgeCount } from "./window-manager";
|
import { getTitleBarOverlayOptions, readBadgeCount, readWindowTheme } from "./window-manager";
|
||||||
|
|
||||||
describe("window-manager", () => {
|
describe("window-manager", () => {
|
||||||
describe("readBadgeCount", () => {
|
describe("readBadgeCount", () => {
|
||||||
@@ -20,4 +20,35 @@ describe("window-manager", () => {
|
|||||||
expect(readBadgeCount({ count: 2 })).toBe(0);
|
expect(readBadgeCount({ count: 2 })).toBe(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("readWindowTheme", () => {
|
||||||
|
it("accepts supported title bar themes", () => {
|
||||||
|
expect(readWindowTheme("light")).toBe("light");
|
||||||
|
expect(readWindowTheme("dark")).toBe("dark");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("rejects invalid title bar themes", () => {
|
||||||
|
expect(readWindowTheme(undefined)).toBeNull();
|
||||||
|
expect(readWindowTheme("auto")).toBeNull();
|
||||||
|
expect(readWindowTheme("system")).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getTitleBarOverlayOptions", () => {
|
||||||
|
it("returns light title bar overlay colors", () => {
|
||||||
|
expect(getTitleBarOverlayOptions("light")).toEqual({
|
||||||
|
color: "#ffffff",
|
||||||
|
symbolColor: "#09090b",
|
||||||
|
height: 48,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns dark title bar overlay colors", () => {
|
||||||
|
expect(getTitleBarOverlayOptions("dark")).toEqual({
|
||||||
|
color: "#18181c",
|
||||||
|
symbolColor: "#e4e4e7",
|
||||||
|
height: 48,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { app, BrowserWindow, ipcMain } from "electron";
|
import { app, BrowserWindow, ipcMain, nativeTheme } from "electron";
|
||||||
import {
|
import {
|
||||||
createWindowMoveState,
|
createWindowMoveState,
|
||||||
readWindowMovePayload,
|
readWindowMovePayload,
|
||||||
@@ -14,6 +14,28 @@ export function readBadgeCount(input: unknown): number {
|
|||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type WindowTheme = "light" | "dark";
|
||||||
|
|
||||||
|
export function readWindowTheme(input: unknown): WindowTheme | null {
|
||||||
|
if (input === "light" || input === "dark") {
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resolveSystemWindowTheme(): WindowTheme {
|
||||||
|
return nativeTheme.shouldUseDarkColors ? "dark" : "light";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTitleBarOverlayOptions(theme: WindowTheme): Electron.TitleBarOverlayOptions {
|
||||||
|
if (theme === "dark") {
|
||||||
|
return { color: "#18181c", symbolColor: "#e4e4e7", height: 48 };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { color: "#ffffff", symbolColor: "#09090b", height: 48 };
|
||||||
|
}
|
||||||
|
|
||||||
export function registerWindowManager(): void {
|
export function registerWindowManager(): void {
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Manual window dragging (replaces flaky CSS -webkit-app-region: drag).
|
// Manual window dragging (replaces flaky CSS -webkit-app-region: drag).
|
||||||
@@ -101,6 +123,20 @@ export function registerWindowManager(): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ipcMain.handle("paseo:window:setTitleBarTheme", (event, theme?: unknown) => {
|
||||||
|
const win = BrowserWindow.fromWebContents(event.sender);
|
||||||
|
if (!win || process.platform === "darwin") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nextTheme = readWindowTheme(theme);
|
||||||
|
if (!nextTheme) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
win.setTitleBarOverlay(getTitleBarOverlayOptions(nextTheme));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setupWindowResizeEvents(win: BrowserWindow): void {
|
export function setupWindowResizeEvents(win: BrowserWindow): void {
|
||||||
|
|||||||
Reference in New Issue
Block a user