import type { CSSProperties, MouseEvent, ReactNode } from 'react' import { useEffect, useState } from 'react' import { getCurrentWindow } from '@tauri-apps/api/window' import { useDragRegion } from '../hooks/useDragRegion' import { shouldUseLinuxWindowChrome } from '../utils/platform' import { LinuxMenuButton } from './LinuxMenuButton' import { Button } from './ui/button' export const LINUX_TITLEBAR_HEIGHT = 32 const RESIZE_EDGE = 6 type ResizeDirection = | 'East' | 'North' | 'NorthEast' | 'NorthWest' | 'South' | 'SouthEast' | 'SouthWest' | 'West' const RESIZE_HANDLES: ReadonlyArray<{ cursor: CSSProperties['cursor'] direction: ResizeDirection style: CSSProperties }> = [ { direction: 'North', cursor: 'ns-resize', style: { top: 0, left: RESIZE_EDGE, right: RESIZE_EDGE, height: RESIZE_EDGE } }, { direction: 'South', cursor: 'ns-resize', style: { bottom: 0, left: RESIZE_EDGE, right: RESIZE_EDGE, height: RESIZE_EDGE } }, { direction: 'West', cursor: 'ew-resize', style: { top: RESIZE_EDGE, bottom: RESIZE_EDGE, left: 0, width: RESIZE_EDGE } }, { direction: 'East', cursor: 'ew-resize', style: { top: RESIZE_EDGE, bottom: RESIZE_EDGE, right: 0, width: RESIZE_EDGE } }, { direction: 'NorthWest', cursor: 'nwse-resize', style: { top: 0, left: 0, width: RESIZE_EDGE, height: RESIZE_EDGE } }, { direction: 'NorthEast', cursor: 'nesw-resize', style: { top: 0, right: 0, width: RESIZE_EDGE, height: RESIZE_EDGE } }, { direction: 'SouthWest', cursor: 'nesw-resize', style: { bottom: 0, left: 0, width: RESIZE_EDGE, height: RESIZE_EDGE } }, { direction: 'SouthEast', cursor: 'nwse-resize', style: { bottom: 0, right: 0, width: RESIZE_EDGE, height: RESIZE_EDGE } }, ] export function LinuxTitlebar() { const linuxChromeEnabled = shouldUseLinuxWindowChrome() const { onMouseDown } = useDragRegion() const maximized = useLinuxMaximizedState(linuxChromeEnabled) if (!linuxChromeEnabled) return null const appWindow = getCurrentWindow() return ( <>
) } function useLinuxMaximizedState(enabled: boolean): boolean { const [maximized, setMaximized] = useState(false) useEffect(() => { if (!enabled) return const appWindow = getCurrentWindow() let active = true const syncMaximizeState = () => { void appWindow.isMaximized().then((value) => { if (active) setMaximized(value) }).catch(() => {}) } syncMaximizeState() const unlistenPromise = appWindow.onResized(syncMaximizeState) return () => { active = false void unlistenPromise.then((unlisten) => unlisten()).catch(() => {}) } }, [enabled]) return maximized } function ResizeHandles() { if (!shouldUseLinuxWindowChrome()) return null const startResize = (direction: ResizeDirection) => (event: MouseEvent) => { if (event.button !== 0) return event.preventDefault() void getCurrentWindow().startResizeDragging(direction).catch(() => {}) } return ( <> {RESIZE_HANDLES.map(({ cursor, direction, style }) => (
))} ) } function TitlebarWindowControls({ appWindow, maximized, }: { appWindow: ReturnType maximized: boolean }) { return (
void appWindow.minimize().catch(() => {})}> void appWindow.toggleMaximize().catch(() => {})} > {maximized ? : } void appWindow.close().catch(() => {})} >
) } function TitlebarButton({ ariaLabel, children, close = false, onClick, }: { ariaLabel: string children: ReactNode close?: boolean onClick: () => void }) { return ( ) } function MinimizeIcon() { return ( ) } function MaximizeIcon() { return ( ) } function RestoreIcon() { return ( ) } function CloseIcon() { return ( ) }