feat(desktop-client): adapt title bar and drag region for Windows/Linux
Frontend CI / Frontend (push) Has been cancelled

- Add appTitleBarStyle() and appTitleBarOverlay() helpers for cross-platform title bar
- Use titleBarOverlay on Windows/Linux so system caption buttons render correctly
- Disable minimize button on login window (non-resizable, no need to minimize)
- Detect platform at renderer startup and set data-platform on <html> for CSS targeting
- DesktopShell: flip drag bar layout — full-width minus caption area on Win/Linux, traffic-light gap on macOS
- LoginView: move top-bar to Win/Linux caption area (top: 34px), mirror to left on macOS

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Xu Liang
2026-05-01 18:02:52 +08:00
parent b7e096ae37
commit 5cd5d6685b
4 changed files with 43 additions and 8 deletions
+26 -4
View File
@@ -132,6 +132,23 @@ const SETTINGS_WINDOW_SIZE: WindowSizePreset = {
resizable: true,
};
const TITLE_BAR_OVERLAY_HEIGHT = 24;
function appTitleBarStyle(): "hidden" | "hiddenInset" {
return process.platform === "darwin" ? "hiddenInset" : "hidden";
}
function appTitleBarOverlay(color: string): { color: string; symbolColor: string; height: number } | undefined {
if (process.platform === "darwin") {
return undefined;
}
return {
color,
symbolColor: nativeTheme.shouldUseDarkColors ? "#f8fafc" : "#111827",
height: TITLE_BAR_OVERLAY_HEIGHT,
};
}
function suppressNativeWindowMenu(window?: ElectronBrowserWindow): void {
if (process.platform === "darwin") {
return;
@@ -459,6 +476,7 @@ async function mountRendererWebContents(window: ElectronBrowserWindow, mode: Ren
async function createAppWindow(mode: WindowMode): Promise<ElectronBrowserWindow> {
const initial = WINDOW_SIZES[mode];
const backgroundColor = mode === "login" ? "#eaf2ff" : nativeTheme.shouldUseDarkColors ? "#15191a" : "#f0f2f5";
const window = new BrowserWindow({
width: initial.width,
height: initial.height,
@@ -467,13 +485,15 @@ async function createAppWindow(mode: WindowMode): Promise<ElectronBrowserWindow>
show: false,
title: "省心推",
icon: createDesktopHealthIcon("normal"),
titleBarStyle: "hiddenInset",
titleBarStyle: appTitleBarStyle(),
titleBarOverlay: appTitleBarOverlay(mode === "login" ? "#00000000" : backgroundColor),
trafficLightPosition: { x: 12, y: 14 },
resizable: initial.resizable,
minimizable: mode !== "login",
maximizable: initial.resizable,
fullscreenable: initial.resizable,
autoHideMenuBar: true,
backgroundColor: mode === "login" ? "#eaf2ff" : nativeTheme.shouldUseDarkColors ? "#15191a" : "#f0f2f5",
backgroundColor,
webPreferences: {
preload: preloadPath(),
sandbox: true,
@@ -536,6 +556,7 @@ async function createAppWindow(mode: WindowMode): Promise<ElectronBrowserWindow>
async function createSettingsWindow(): Promise<ElectronBrowserWindow> {
const initial = SETTINGS_WINDOW_SIZE;
const backgroundColor = nativeTheme.shouldUseDarkColors ? "#15191a" : "#f2f4f7";
const window = new BrowserWindow({
width: initial.width,
height: initial.height,
@@ -544,13 +565,14 @@ async function createSettingsWindow(): Promise<ElectronBrowserWindow> {
show: false,
title: "省心推设置",
icon: createDesktopHealthIcon("normal"),
titleBarStyle: "hiddenInset",
titleBarStyle: appTitleBarStyle(),
titleBarOverlay: appTitleBarOverlay(backgroundColor),
trafficLightPosition: { x: 14, y: 15 },
resizable: initial.resizable,
maximizable: initial.resizable,
fullscreenable: false,
autoHideMenuBar: true,
backgroundColor: nativeTheme.shouldUseDarkColors ? "#15191a" : "#f2f4f7",
backgroundColor,
webPreferences: {
preload: preloadPath(),
sandbox: true,