diff --git a/apps/desktop/electron/main.cjs b/apps/desktop/electron/main.cjs index 23b68c342c6..483adbfffc1 100644 --- a/apps/desktop/electron/main.cjs +++ b/apps/desktop/electron/main.cjs @@ -7,6 +7,7 @@ const { dialog, ipcMain, nativeImage, + nativeTheme, safeStorage, session, shell, @@ -131,6 +132,20 @@ const APP_ICON_PATHS = [ path.join(unpackedPathFor(APP_ROOT), 'dist', 'apple-touch-icon.png') ] +function getTitleBarOverlayOptions() { + if (IS_MAC) { + return { height: TITLEBAR_HEIGHT } + } + + const useDarkColors = nativeTheme.shouldUseDarkColors + + return { + color: useDarkColors ? '#111111' : '#f7f7f7', + height: TITLEBAR_HEIGHT, + symbolColor: useDarkColors ? '#f7f7f7' : '#242424' + } +} + const MEDIA_MIME_TYPES = { '.avi': 'video/x-msvideo', '.bmp': 'image/bmp', @@ -2505,9 +2520,7 @@ function createWindow() { // to paint native min/max/close in the top-right of the renderer; on // macOS it just reserves a content inset alongside the traffic lights. titleBarStyle: 'hidden', - titleBarOverlay: IS_MAC - ? { height: TITLEBAR_HEIGHT } - : { color: '#f7f7f7', height: TITLEBAR_HEIGHT, symbolColor: '#242424' }, + titleBarOverlay: getTitleBarOverlayOptions(), trafficLightPosition: IS_MAC ? WINDOW_BUTTON_POSITION : undefined, vibrancy: IS_MAC ? 'sidebar' : undefined, icon, @@ -2529,6 +2542,12 @@ function createWindow() { } } + if (!IS_MAC) { + nativeTheme.on('updated', () => { + mainWindow?.setTitleBarOverlay?.(getTitleBarOverlayOptions()) + }) + } + mainWindow.on('will-enter-full-screen', () => sendWindowStateChanged(true)) mainWindow.on('enter-full-screen', () => sendWindowStateChanged(true)) mainWindow.on('will-leave-full-screen', () => sendWindowStateChanged(false)) diff --git a/apps/desktop/src/app/command-center/index.tsx b/apps/desktop/src/app/command-center/index.tsx index 81a2748b058..6982926c995 100644 --- a/apps/desktop/src/app/command-center/index.tsx +++ b/apps/desktop/src/app/command-center/index.tsx @@ -249,6 +249,7 @@ export function CommandCenterView({ const [usageLoading, setUsageLoading] = useState(false) const [usageError, setUsageError] = useState('') const searchRequestRef = useRef(0) + const usageRequestRef = useRef(0) const debouncedQuery = useDebouncedValue(query.trim(), 180) @@ -367,16 +368,25 @@ export function CommandCenterView({ const refreshUsage = useCallback( async (days: UsagePeriod) => { + const requestId = usageRequestRef.current + 1 + usageRequestRef.current = requestId setUsageLoading(true) setUsageError('') try { const response = await getUsageAnalytics(days) - setUsage(response) + + if (usageRequestRef.current === requestId) { + setUsage(response) + } } catch (error) { - setUsageError(error instanceof Error ? error.message : String(error)) + if (usageRequestRef.current === requestId) { + setUsageError(error instanceof Error ? error.message : String(error)) + } } finally { - setUsageLoading(false) + if (usageRequestRef.current === requestId) { + setUsageLoading(false) + } } }, [] diff --git a/apps/desktop/src/app/shell/titlebar.test.ts b/apps/desktop/src/app/shell/titlebar.test.ts index 2b961b80ea6..830eed31ca8 100644 --- a/apps/desktop/src/app/shell/titlebar.test.ts +++ b/apps/desktop/src/app/shell/titlebar.test.ts @@ -1,6 +1,11 @@ import { describe, expect, it } from 'vitest' -import { TITLEBAR_CONTROL_OFFSET_X, TITLEBAR_EDGE_INSET, titlebarControlsPosition } from './titlebar' +import { + TITLEBAR_CONTROL_OFFSET_X, + TITLEBAR_EDGE_INSET, + TITLEBAR_FALLBACK_WINDOW_BUTTON_X, + titlebarControlsPosition +} from './titlebar' describe('titlebarControlsPosition', () => { it('offsets controls from visible traffic lights', () => { @@ -13,6 +18,11 @@ describe('titlebarControlsPosition', () => { it('pins to the edge on Windows/Linux where native controls render on the right', () => { expect(titlebarControlsPosition(null).left).toBe(TITLEBAR_EDGE_INSET) - expect(titlebarControlsPosition(undefined).left).toBe(TITLEBAR_EDGE_INSET) + }) + + it('uses the macOS fallback while the initial window state is unknown', () => { + expect(titlebarControlsPosition(undefined).left).toBe( + TITLEBAR_FALLBACK_WINDOW_BUTTON_X + TITLEBAR_CONTROL_OFFSET_X + ) }) }) diff --git a/apps/desktop/src/app/shell/titlebar.ts b/apps/desktop/src/app/shell/titlebar.ts index 7c6ea3dc946..87cfb4bb495 100644 --- a/apps/desktop/src/app/shell/titlebar.ts +++ b/apps/desktop/src/app/shell/titlebar.ts @@ -6,6 +6,7 @@ export const TITLEBAR_ICON_SIZE = 12 export const TITLEBAR_CONTROL_OFFSET_X = 74 export const TITLEBAR_CONTROL_HEIGHT = 22 export const TITLEBAR_CONTROLS_TOP = (TITLEBAR_HEIGHT - TITLEBAR_CONTROL_HEIGHT) / 2 +export const TITLEBAR_FALLBACK_WINDOW_BUTTON_X = 24 // Edge inset used when no left-side native controls take up that space — // Windows/Linux (native overlay is on the right) and macOS fullscreen // (traffic lights are hidden). Matches the right-cluster's 0.75rem padding. @@ -30,9 +31,12 @@ export function titlebarControlsPosition( // - Windows/Linux: native min/max/close render on the right via titleBarOverlay. // - macOS fullscreen: traffic lights are hidden. // In both cases, pin the cluster to the edge with a small inset. - if (!windowButtonPosition || isFullscreen) { + if (windowButtonPosition === null || isFullscreen) { return { left: TITLEBAR_EDGE_INSET, top } } - return { left: windowButtonPosition.x + TITLEBAR_CONTROL_OFFSET_X, top } + return { + left: (windowButtonPosition?.x ?? TITLEBAR_FALLBACK_WINDOW_BUTTON_X) + TITLEBAR_CONTROL_OFFSET_X, + top + } }