From 09bbff1887c02e2bab1e35a8102bd77d5f1f4706 Mon Sep 17 00:00:00 2001 From: Sucukdeluxe Date: Sun, 23 Aug 2026 19:06:31 +0200 Subject: [PATCH] fix(window): force dark native title bar Apply Electron nativeTheme dark mode before creating the main window so the Windows title bar remains dark across local, server, and Remote Desktop profiles. Add focused regression coverage for the native theme contract. --- src/main/main.ts | 9 ++++++--- src/main/native-theme.ts | 7 +++++++ tests/native-theme.test.ts | 12 ++++++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 src/main/native-theme.ts create mode 100644 tests/native-theme.test.ts diff --git a/src/main/main.ts b/src/main/main.ts index 5af8909..07a8d89 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -1,7 +1,7 @@ import fs from "node:fs"; import path from "node:path"; import { pathToFileURL } from "node:url"; -import { app, BrowserWindow, clipboard, dialog, ipcMain, Menu, safeStorage, shell, Tray, type IpcMainEvent, type IpcMainInvokeEvent } from "electron"; +import { app, BrowserWindow, clipboard, dialog, ipcMain, Menu, nativeTheme, safeStorage, shell, Tray, type IpcMainEvent, type IpcMainInvokeEvent } from "electron"; import { AddLinksPayload, AppSettings, DebridProvider, EnableRemoteDiagnosticsInput, RendererSettingsUpdate, UpdateInstallProgress } from "../shared/types"; import { AppController } from "./app-controller"; import { IPC_CHANNELS } from "../shared/ipc"; @@ -23,8 +23,11 @@ import { applyMainWindowSecurity, createMainWindowWebPreferences, MAIN_WINDOW_EX import { assertTrustedIpcSender, type TrustedIpcOptions } from "./ipc-security"; import { validateRealDebridLoginRequest } from "../shared/preload-api"; import { migrateProductUserDataDirectory } from "./storage"; - -function validateString(value: unknown, name: string): string { +import { forceDarkNativeTheme } from "./native-theme"; + +forceDarkNativeTheme(nativeTheme); + +function validateString(value: unknown, name: string): string { if (typeof value !== "string") { throw new Error(`${name} muss ein String sein`); } diff --git a/src/main/native-theme.ts b/src/main/native-theme.ts new file mode 100644 index 0000000..ab2a982 --- /dev/null +++ b/src/main/native-theme.ts @@ -0,0 +1,7 @@ +export interface NativeThemeTarget { + themeSource: string; +} + +export function forceDarkNativeTheme(theme: NativeThemeTarget): void { + theme.themeSource = "dark"; +} diff --git a/tests/native-theme.test.ts b/tests/native-theme.test.ts new file mode 100644 index 0000000..8e5e5be --- /dev/null +++ b/tests/native-theme.test.ts @@ -0,0 +1,12 @@ +import { describe, expect, it } from "vitest"; +import { forceDarkNativeTheme } from "../src/main/native-theme"; + +describe("native window theme", () => { + it("forces the native Windows title bar to use the dark theme", () => { + const theme = { themeSource: "system" }; + + forceDarkNativeTheme(theme); + + expect(theme.themeSource).toBe("dark"); + }); +});