Files
2026-02-22 14:06:01 -03:00

159 lines
4.6 KiB
TypeScript

'use client';
import { useEffect, useState } from 'react';
import { getCurrentWindow } from '@tauri-apps/api/window';
import { Minus, Square, X } from 'lucide-react';
import { cn } from '@/lib/utils';
import { useSystemHealth } from '@/hooks/use-system-health';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
export function TitleBar() {
const [isMaximized, setIsMaximized] = useState(false);
const health = useSystemHealth();
useEffect(() => {
let isMounted = true;
const checkMaximized = async () => {
try {
const appWindow = getCurrentWindow();
const maximized = await appWindow.isMaximized();
if (isMounted) {
setIsMaximized(maximized);
}
} catch (error) {
console.error('Failed to check window state:', error);
}
};
checkMaximized();
// Listener para mudanças de estado
const setupListener = async () => {
try {
const appWindow = getCurrentWindow();
const unlisten = await appWindow.onResized(async () => {
if (isMounted) {
const maximized = await appWindow.isMaximized();
setIsMaximized(maximized);
}
});
return unlisten;
} catch (error) {
console.error('Failed to setup resize listener:', error);
return null;
}
};
let unlistenFn: (() => void) | null = null;
setupListener().then(fn => {
unlistenFn = fn;
});
return () => {
isMounted = false;
if (unlistenFn) {
unlistenFn();
}
};
}, []);
const handleMinimize = async () => {
const appWindow = getCurrentWindow();
await appWindow.minimize();
};
const handleMaximize = async () => {
const appWindow = getCurrentWindow();
if (isMaximized) {
await appWindow.unmaximize();
} else {
await appWindow.maximize();
}
};
const handleClose = async () => {
const appWindow = getCurrentWindow();
await appWindow.close();
};
return (
<div
className="h-8 bg-sidebar border-b border-sidebar-border flex items-center justify-between select-none z-[9999] shrink-0 fixed top-0 left-0 right-0"
data-tauri-drag-region
style={{
pointerEvents: 'auto',
WebkitAppRegion: 'drag'
} as React.CSSProperties & { WebkitAppRegion?: string }}
>
{/* Área de arrasto com logo/título */}
<div
className="flex items-center gap-2 px-4 h-full flex-1"
data-tauri-drag-region
>
<img
src="/icon.png"
alt="OllaHub"
className="w-5 h-5 shrink-0"
draggable={false}
/>
<span className="text-sm font-medium text-sidebar-foreground">
OllaHub
</span>
{/* Indicador de saúde do sistema */}
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<div
className={cn(
"w-2 h-2 rounded-full shrink-0",
health.status === 'healthy' && "bg-green-500",
health.status === 'warning' && "bg-yellow-500",
health.status === 'critical' && "bg-red-500"
)}
/>
</TooltipTrigger>
<TooltipContent side="bottom" className="text-xs">
<p>{health.message}</p>
<p className="text-muted-foreground mt-1">
RAM: {health.ram_percent.toFixed(1)}% | CPU: {health.cpu_percent.toFixed(1)}%
</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</div>
{/* Controles de janela */}
<div className="flex items-center h-full">
<button
onClick={handleMinimize}
className="h-full w-12 flex items-center justify-center hover:bg-sidebar-accent transition-colors"
title="Minimizar"
>
<Minus className="w-4 h-4 text-sidebar-foreground" />
</button>
<button
onClick={handleMaximize}
className="h-full w-12 flex items-center justify-center hover:bg-sidebar-accent transition-colors"
title={isMaximized ? "Restaurar" : "Maximizar"}
>
<Square className={cn(
"w-3.5 h-3.5 text-sidebar-foreground",
isMaximized && "opacity-60"
)} />
</button>
<button
onClick={handleClose}
className="h-full w-12 flex items-center justify-center hover:bg-destructive transition-colors"
title="Fechar"
>
<X className="w-4 h-4 text-sidebar-foreground" />
</button>
</div>
</div>
);
}