diff --git a/packages/app/src/app/_layout.tsx b/packages/app/src/app/_layout.tsx index 5dcc3819b..56ec7fb3c 100644 --- a/packages/app/src/app/_layout.tsx +++ b/packages/app/src/app/_layout.tsx @@ -28,6 +28,7 @@ import { import { shouldUseDesktopDaemon } from "@/desktop/daemon/desktop-daemon"; import { StartupSplashScreen } from "@/screens/startup-splash-screen"; import { loadSettingsFromStorage } from "@/hooks/use-settings"; +import { useColorScheme } from "@/hooks/use-color-scheme"; import { SessionProvider } from "@/contexts/session-context"; import type { HostProfile } from "@/types/host-connection"; import { @@ -68,6 +69,7 @@ import { ensureOsNotificationPermission, } from "@/utils/os-notifications"; import { getDesktopHost } from "@/desktop/host"; +import { setDesktopTitleBarTheme } from "@/desktop/electron/window"; import { buildNotificationRoute } from "@/utils/notification-routing"; import { buildHostRootRoute, @@ -412,7 +414,9 @@ function ProvidersWrapper({ children }: { children: ReactNode }) { const { settings, isLoading: settingsLoading } = useAppSettings(); const storeReady = useStoreReady(); const { upsertConnectionFromOfferUrl } = useHostMutations(); + const systemColorScheme = useColorScheme(); const isLoading = settingsLoading || !storeReady; + const resolvedTheme = settings.theme === "auto" ? (systemColorScheme ?? "light") : settings.theme; // Apply theme setting on mount and when it changes useEffect(() => { @@ -425,6 +429,16 @@ function ProvidersWrapper({ children }: { children: ReactNode }) { } }, [isLoading, settings.theme]); + useEffect(() => { + if (isLoading || Platform.OS !== "web") { + return; + } + + void setDesktopTitleBarTheme(resolvedTheme).catch((error) => { + console.warn("[DesktopWindow] Failed to update title bar theme", error); + }); + }, [isLoading, resolvedTheme]); + if (isLoading) { const isDesktopManaged = !settingsLoading && shouldUseDesktopDaemon() && settings.manageBuiltInDaemon; diff --git a/packages/app/src/desktop/electron/window.ts b/packages/app/src/desktop/electron/window.ts index 3759e8c56..51873ca4a 100644 --- a/packages/app/src/desktop/electron/window.ts +++ b/packages/app/src/desktop/electron/window.ts @@ -27,3 +27,12 @@ export async function isDesktopFullscreen(): Promise { } return await win.isFullscreen(); } + +export async function setDesktopTitleBarTheme(theme: "light" | "dark"): Promise { + const win = getDesktopWindow(); + if (!win || typeof win.setTitleBarTheme !== "function") { + return; + } + + await win.setTitleBarTheme(theme); +} diff --git a/packages/app/src/desktop/host.ts b/packages/app/src/desktop/host.ts index 702904d1d..136dbfb69 100644 --- a/packages/app/src/desktop/host.ts +++ b/packages/app/src/desktop/host.ts @@ -51,6 +51,7 @@ export interface DesktopWindowBridge { endMove?: () => void; toggleMaximize?: () => Promise; isFullscreen?: () => Promise; + setTitleBarTheme?: (theme: "light" | "dark") => Promise; onResized?: ( handler: (event: TEvent) => void, ) => Promise<() => void> | (() => void);