(options?: { isToolbarMode?: boolean })
| 44 | * behavior to maximize/restore UI. |
| 45 | */ |
| 46 | export const useWindowControls = (options?: { isToolbarMode?: boolean }) => { |
| 47 | const { t } = useI18n('errors'); |
| 48 | const isToolbarMode = options?.isToolbarMode ?? false; |
| 49 | const canUseNativeWindowControls = supportsNativeWindowControls(); |
| 50 | const { hasWorkspace, closeWorkspace } = useWorkspaceContext(); |
| 51 | |
| 52 | // Maximized state: ordinary OS window maximize/restore, not fullscreen. |
| 53 | const [isMaximized, setIsMaximized] = useState(false); |
| 54 | // OS fullscreen state: entire Desktop window fullscreen, not panel fullscreen. |
| 55 | const [isFullscreen, setIsFullscreen] = useState(false); |
| 56 | |
| 57 | // Debounce guard to prevent rapid toggles |
| 58 | const isMaximizeInProgress = useRef(false); |
| 59 | const isFullscreenInProgress = useRef(false); |
| 60 | |
| 61 | // Skip state updates during manual operations |
| 62 | const shouldSkipStateUpdate = useRef(false); |
| 63 | |
| 64 | const restoreMacOSOverlayTitlebar = useCallback(async (appWindow: any) => { |
| 65 | if (!isMacOSDesktopRuntime() || isToolbarMode) return; |
| 66 | try { |
| 67 | if (typeof appWindow.setTitleBarStyle === 'function') { |
| 68 | await appWindow.setTitleBarStyle('overlay'); |
| 69 | } |
| 70 | } catch { |
| 71 | // Ignore failures during window animation/state changes. |
| 72 | } |
| 73 | }, [isToolbarMode]); |
| 74 | |
| 75 | const updateWindowState = useCallback(async (appWindow: any, skipVisibilityCheck = false) => { |
| 76 | if (shouldSkipStateUpdate.current) { |
| 77 | return; |
| 78 | } |
| 79 | |
| 80 | try { |
| 81 | if (!skipVisibilityCheck) { |
| 82 | const isVisible = await appWindow.isVisible(); |
| 83 | if (!isVisible) { |
| 84 | return; |
| 85 | } |
| 86 | } |
| 87 | |
| 88 | const [maximized, fullscreen] = await Promise.all([ |
| 89 | appWindow.isMaximized(), |
| 90 | appWindow.isFullscreen(), |
| 91 | ]); |
| 92 | setIsMaximized(maximized); |
| 93 | setIsFullscreen(fullscreen); |
| 94 | } catch (_error) { |
| 95 | // Ignore errors to avoid noise when the window is minimized or transitioning. |
| 96 | } |
| 97 | }, []); |
| 98 | |
| 99 | // Listen for window state changes |
| 100 | useEffect(() => { |
| 101 | if (!canUseNativeWindowControls) return; |
| 102 | |
| 103 | let unlistenResized: (() => void) | undefined; |
no test coverage detected