| 1 | import { useEffect, useState } from 'react' |
| 2 | import { Maximize, Minimize, Minus, X } from 'lucide-react' |
| 3 | import { ipc } from '@renderer/lib/ipc' |
| 4 | |
| 5 | const isMac = ipc.getPlatform() === 'darwin' |
| 6 | |
| 7 | export function WindowControls(): React.JSX.Element | null { |
| 8 | const [isFullscreen, setIsFullscreen] = useState(false) |
| 9 | |
| 10 | useEffect(() => { |
| 11 | if (isMac) return |
| 12 | const unsubscribe = ipc.onWindowControlStateChanged((state) => setIsFullscreen(state.isFullscreen)) |
| 13 | void ipc.getWindowControlState().then((state) => setIsFullscreen(state.isFullscreen)) |
| 14 | return unsubscribe |
| 15 | }, []) |
| 16 | |
| 17 | if (isMac) return null |
| 18 | |
| 19 | const handleToggleFullscreen = (): void => { |
| 20 | void ipc.toggleFullscreenWindow().then((state) => setIsFullscreen(state.isFullscreen)) |
| 21 | } |
| 22 | |
| 23 | const controls = [ |
| 24 | { label: 'Minimize', action: () => void ipc.minimizeWindow(), icon: Minus }, |
| 25 | { |
| 26 | label: isFullscreen ? '退出全屏' : '全屏', |
| 27 | action: handleToggleFullscreen, |
| 28 | icon: isFullscreen ? Minimize : Maximize |
| 29 | }, |
| 30 | { label: '关闭', action: () => void ipc.closeWindow(), icon: X, close: true } |
| 31 | ] |
| 32 | |
| 33 | return ( |
| 34 | <div className="app-no-drag ml-auto mr-2 flex shrink-0 items-center gap-1" aria-label="窗口控制"> |
| 35 | {controls.map(({ label, action, icon: Icon, close }) => ( |
| 36 | <button |
| 37 | key={label} |
| 38 | type="button" |
| 39 | onClick={action} |
| 40 | aria-label={label} |
| 41 | className={`inline-flex h-7 w-7 items-center justify-center rounded-md text-[#536044] transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[#789761] ${ |
| 42 | close |
| 43 | ? 'hover:bg-[#c8554d] hover:text-white focus-visible:ring-[#c8554d]' |
| 44 | : 'hover:bg-[#e5dcc9]' |
| 45 | }`} |
| 46 | > |
| 47 | <Icon className="h-3.5 w-3.5" strokeWidth={1.8} /> |
| 48 | </button> |
| 49 | ))} |
| 50 | </div> |
| 51 | ) |
| 52 | } |
| 53 |