import { ActionIcon, AppShell, CopyButton, Group, Tooltip } from '@mantine/core'; import { Check, Globe, NotepadText } from 'lucide-react'; import { useEffect, useMemo, useState } from 'react'; import { STATUSBAR_HEIGHT } from '@/constants'; import type { CpuMetrics, GpuMetrics, MemoryMetrics } from '@/main/modules/monitoring'; import { useLaunchConfigStore } from '@/stores/launchConfig'; import { useNotepadStore } from '@/stores/notepad'; import { usePreferencesStore } from '@/stores/preferences'; import { getTunnelInterfaceUrl } from '@/utils/interface'; import { PerformanceBadge } from './PerformanceBadge'; export const StatusBar = () => { const [cpuMetrics, setCpuMetrics] = useState(null); const [memoryMetrics, setMemoryMetrics] = useState(null); const [gpuMetrics, setGpuMetrics] = useState(null); const [tunnelBaseUrl, setTunnelBaseUrl] = useState(null); const { systemMonitoringEnabled, frontendPreference, imageGenerationFrontendPreference } = usePreferencesStore(); const { isVisible, setVisible } = useNotepadStore(); const { isImageGenerationMode } = useLaunchConfigStore(); const tunnelUrl = useMemo(() => { if (!tunnelBaseUrl) { return null; } if (frontendPreference === 'sillytavern' || frontendPreference === 'openwebui') { return tunnelBaseUrl; } return getTunnelInterfaceUrl(tunnelBaseUrl, { frontendPreference, imageGenerationFrontendPreference, isImageGenerationMode, }); }, [tunnelBaseUrl, frontendPreference, imageGenerationFrontendPreference, isImageGenerationMode]); useEffect(() => { if (!systemMonitoringEnabled) { return undefined; } let isMounted = true; const handleCpuMetrics = (metrics: CpuMetrics) => { if (!isMounted) { return; } setCpuMetrics(metrics); }; const handleMemoryMetrics = (metrics: MemoryMetrics) => { if (!isMounted) { return; } setMemoryMetrics(metrics); }; const handleGpuMetrics = (metrics: GpuMetrics) => { if (!isMounted) { return; } setGpuMetrics(metrics); }; const cleanupCpu = window.electronAPI.monitoring.onCpuMetrics(handleCpuMetrics); const cleanupMemory = window.electronAPI.monitoring.onMemoryMetrics(handleMemoryMetrics); const cleanupGpu = window.electronAPI.monitoring.onGpuMetrics(handleGpuMetrics); const stopMonitoring = window.electronAPI.monitoring.start(); return () => { isMounted = false; cleanupCpu?.(); cleanupMemory?.(); cleanupGpu?.(); stopMonitoring?.(); }; }, [systemMonitoringEnabled]); useEffect(() => { const cleanup = window.electronAPI.kobold.onTunnelUrlChanged(setTunnelBaseUrl); return cleanup; }, []); const displayCpuMetrics = systemMonitoringEnabled ? cpuMetrics : null; const displayMemoryMetrics = systemMonitoringEnabled ? memoryMetrics : null; const displayGpuMetrics = systemMonitoringEnabled ? gpuMetrics : null; return ( setVisible(!isVisible)} > {tunnelUrl && ( {({ copied, copy }) => ( {copied ? : } )} )} {systemMonitoringEnabled ? ( <> {displayCpuMetrics && displayMemoryMetrics && ( <> )} {displayGpuMetrics?.gpus.map((gpu, index) => ( 1 ? ` ${index + 1}` : ''}`} value={`${gpu.usage}%`} tooltipLabel={`${gpu.usage}%${gpu.temperature ? ` • ${gpu.temperature}°C` : ''}`} /> 1 ? ` ${index + 1}` : ''}`} value={`${gpu.memoryUsage}%`} tooltipLabel={`${gpu.memoryUsed.toFixed(2)} GB / ${gpu.memoryTotal.toFixed(2)} GB (${gpu.memoryUsage}%)`} /> ))} ) : ( )} ); };