diff --git a/packages/frontend/core/src/bootstrap/setup.ts b/packages/frontend/core/src/bootstrap/setup.ts index 5f192c21e264f..b589fd8816cea 100644 --- a/packages/frontend/core/src/bootstrap/setup.ts +++ b/packages/frontend/core/src/bootstrap/setup.ts @@ -60,8 +60,13 @@ export function setup() { const handleMaximized = (maximized: boolean | undefined) => { document.documentElement.dataset.maximized = String(maximized); }; + const handleFullscreen = (fullscreen: boolean | undefined) => { + document.documentElement.dataset.fullscreen = String(fullscreen); + }; apis?.ui.isMaximized().then(handleMaximized).catch(console.error); + apis?.ui.isFullScreen().then(handleFullscreen).catch(console.error); events?.ui.onMaximized(handleMaximized); + events?.ui.onFullScreen(handleFullscreen); const handleResize = debounce(() => { apis?.ui.handleWindowResize().catch(console.error); diff --git a/packages/frontend/core/src/components/app-sidebar/index.css.ts b/packages/frontend/core/src/components/app-sidebar/index.css.ts index cbfd81c9cd907..aecb8f3c9db38 100644 --- a/packages/frontend/core/src/components/app-sidebar/index.css.ts +++ b/packages/frontend/core/src/components/app-sidebar/index.css.ts @@ -45,7 +45,7 @@ export const navHeaderStyle = style({ }); globalStyle( - `html[data-maximized="false"] + `html[data-fullscreen="false"] ${navHeaderStyle}[data-is-macos-electron="true"]`, { paddingLeft: '90px', diff --git a/packages/frontend/core/src/components/pure/header/windows-app-controls.tsx b/packages/frontend/core/src/components/pure/header/windows-app-controls.tsx index b1dd042611ee6..addd0728288bb 100644 --- a/packages/frontend/core/src/components/pure/header/windows-app-controls.tsx +++ b/packages/frontend/core/src/components/pure/header/windows-app-controls.tsx @@ -2,17 +2,34 @@ import { apis, events } from '@affine/electron-api'; import { useAtomValue } from 'jotai'; import { atomWithObservable } from 'jotai/utils'; import { useCallback } from 'react'; -import { Observable } from 'rxjs'; +import { combineLatest, map, Observable } from 'rxjs'; import * as style from './style.css'; -const maximizedAtom = atomWithObservable(() => { - return new Observable(subscriber => { - subscriber.next(false); - return events?.ui.onMaximized(maximized => { - return subscriber.next(maximized); +const maximized$ = new Observable(subscriber => { + subscriber.next(false); + if (events) { + return events.ui.onMaximized(res => { + subscriber.next(res); + }); + } + return () => {}; +}); + +const fullscreen$ = new Observable(subscriber => { + subscriber.next(false); + if (events) { + return events.ui.onFullScreen(res => { + subscriber.next(res); }); - }); + } + return () => {}; +}); + +const maximizedAtom = atomWithObservable(() => { + return combineLatest([maximized$, fullscreen$]).pipe( + map(([maximized, fullscreen]) => maximized || fullscreen) + ); }); const minimizeSVG = ( diff --git a/packages/frontend/electron/src/main/main-window.ts b/packages/frontend/electron/src/main/main-window.ts index e27f1bd89c55f..ec7005d2d355b 100644 --- a/packages/frontend/electron/src/main/main-window.ts +++ b/packages/frontend/electron/src/main/main-window.ts @@ -104,9 +104,8 @@ async function createWindow(additionalArguments: string[]) { logger.info('main window is ready to show'); - if (browserWindow.isMaximized() || browserWindow.isFullScreen()) { - uiSubjects.onMaximized$.next(true); - } + uiSubjects.onMaximized$.next(browserWindow.isMaximized()); + uiSubjects.onFullScreen$.next(browserWindow.isFullScreen()); handleWebContentsResize().catch(logger.error); }); @@ -143,19 +142,24 @@ async function createWindow(additionalArguments: string[]) { browserWindow.setSize(size[0], size[1]); }); uiSubjects.onMaximized$.next(false); + uiSubjects.onFullScreen$.next(false); }); browserWindow.on('maximize', () => { uiSubjects.onMaximized$.next(true); }); + browserWindow.on('unmaximize', () => { + uiSubjects.onMaximized$.next(false); + }); + // full-screen == maximized in UI on windows browserWindow.on('enter-full-screen', () => { - uiSubjects.onMaximized$.next(true); + uiSubjects.onFullScreen$.next(true); }); - browserWindow.on('unmaximize', () => { - uiSubjects.onMaximized$.next(false); + browserWindow.on('leave-full-screen', () => { + uiSubjects.onFullScreen$.next(false); }); /** diff --git a/packages/frontend/electron/src/main/ui/events.ts b/packages/frontend/electron/src/main/ui/events.ts index 16569a4d8bc2c..556e031c642d2 100644 --- a/packages/frontend/electron/src/main/ui/events.ts +++ b/packages/frontend/electron/src/main/ui/events.ts @@ -11,4 +11,10 @@ export const uiEvents = { sub.unsubscribe(); }; }, + onFullScreen: (fn: (fullScreen: boolean) => void) => { + const sub = uiSubjects.onFullScreen$.subscribe(fn); + return () => { + sub.unsubscribe(); + }; + }, } satisfies Record; diff --git a/packages/frontend/electron/src/main/ui/handlers.ts b/packages/frontend/electron/src/main/ui/handlers.ts index f248b64402bac..248c9c6409e4d 100644 --- a/packages/frontend/electron/src/main/ui/handlers.ts +++ b/packages/frontend/electron/src/main/ui/handlers.ts @@ -20,6 +20,10 @@ export const uiHandlers = { const window = await getMainWindow(); return window?.isMaximized(); }, + isFullScreen: async () => { + const window = await getMainWindow(); + return window?.isFullScreen(); + }, handleThemeChange: async (_, theme: (typeof nativeTheme)['themeSource']) => { nativeTheme.themeSource = theme; }, diff --git a/packages/frontend/electron/src/main/ui/subject.ts b/packages/frontend/electron/src/main/ui/subject.ts index 488971bbd29a1..030db45c20e8c 100644 --- a/packages/frontend/electron/src/main/ui/subject.ts +++ b/packages/frontend/electron/src/main/ui/subject.ts @@ -2,4 +2,5 @@ import { Subject } from 'rxjs'; export const uiSubjects = { onMaximized$: new Subject(), + onFullScreen$: new Subject(), };