diff --git a/web-app/src/routes/settings/hardware.tsx b/web-app/src/routes/settings/hardware.tsx index 242d92139..226455fb1 100644 --- a/web-app/src/routes/settings/hardware.tsx +++ b/web-app/src/routes/settings/hardware.tsx @@ -8,9 +8,9 @@ import { Progress } from '@/components/ui/progress' import { useTranslation } from '@/i18n/react-i18next-compat' import { useHardware } from '@/hooks/useHardware' import { useLlamacppDevices } from '@/hooks/useLlamacppDevices' -import { useEffect } from 'react' +import { useEffect, useState } from 'react' import { IconDeviceDesktopAnalytics } from '@tabler/icons-react' -import { getSystemUsage } from '@/services/hardware' +import { getHardwareInfo, getSystemUsage } from '@/services/hardware' import { WebviewWindow } from '@tauri-apps/api/webviewWindow' import { formatMegaBytes } from '@/lib/utils' import { windowKey } from '@/constants/windows' @@ -25,6 +25,7 @@ export const Route = createFileRoute(route.settings.hardware as any)({ function Hardware() { const { t } = useTranslation() + const [isLoading, setIsLoading] = useState(false) const { hardwareData, systemUsage, @@ -51,6 +52,29 @@ function Hardware() { fetchDevices() }, [fetchDevices]) + // Fetch initial hardware info and system usage + useEffect(() => { + setIsLoading(true) + Promise.all([ + getHardwareInfo() + .then((data) => { + setHardwareData(data) + }) + .catch((error) => { + console.error('Failed to get hardware info:', error) + }), + getSystemUsage() + .then((data) => { + updateSystemUsage(data) + }) + .catch((error) => { + console.error('Failed to get initial system usage:', error) + }), + ]).finally(() => { + setIsLoading(false) + }) + }, [setHardwareData, updateSystemUsage]) + const { getProviderByName } = useModelProvider() // Initialize llamacpp device activations from provider settings @@ -92,13 +116,17 @@ function Hardware() { useEffect(() => { if (pollingPaused) return const intervalId = setInterval(() => { - getSystemUsage().then((data) => { - updateSystemUsage(data) - }) + getSystemUsage() + .then((data) => { + updateSystemUsage(data) + }) + .catch((error) => { + console.error('Failed to get system usage:', error) + }) }, 5000) return () => clearInterval(intervalId) - }, [setHardwareData, updateSystemUsage, pollingPaused]) + }, [updateSystemUsage, pollingPaused]) const handleClickSystemMonitor = async () => { try { @@ -154,155 +182,164 @@ function Hardware() {
-
- {/* OS Information */} - - - {hardwareData.os_type} - - } - /> - - {hardwareData.os_name} - - } - /> - - - {/* CPU Information */} - - - {hardwareData.cpu?.name} - - } - /> - - {hardwareData.cpu?.arch} - - } - /> - - {hardwareData.cpu?.core_count} - - } - /> - {hardwareData.cpu?.extensions?.join(', ').length > 0 && ( + {isLoading ? ( +
+
+ Loading hardware information... +
+
+ ) : ( +
+ {/* OS Information */} + 6} + title={t('settings:hardware.name')} actions={ - - {hardwareData.cpu?.extensions?.join(', ')} + + {hardwareData.os_type} } /> - )} - - {systemUsage.cpu > 0 && ( - <> - - - {systemUsage.cpu?.toFixed(2)}% - - - )} -
- } - /> -
+ + {hardwareData.os_name} + + } + /> + - {/* RAM Information */} - - - {formatMegaBytes(hardwareData.total_memory)} - - } - /> - - {formatMegaBytes( - hardwareData.total_memory - systemUsage.used_memory - )} - - } - /> - - {hardwareData.total_memory > 0 && ( - <> - - - {( - toNumber( - systemUsage.used_memory / systemUsage.total_memory - ) * 100 - ).toFixed(2)} - % - - - )} -
- } - /> - - - {/* Llamacpp Devices Information */} - {!IS_MACOS && llamacpp && ( - - {llamacppDevicesLoading ? ( - } /> - ) : llamacppDevicesError ? ( + {/* CPU Information */} + + + {hardwareData.cpu?.name} + + } + /> + + {hardwareData.cpu?.arch} + + } + /> + + {hardwareData.cpu?.core_count} + + } + /> + {hardwareData.cpu?.extensions?.join(', ').length > 0 && ( 6} actions={ - - {llamacppDevicesError} + + {hardwareData.cpu?.extensions?.join(', ')} } /> - ) : llamacppDevices.length > 0 ? ( - llamacppDevices.map((device, index) => ( - - - {/*
+ )} + + {systemUsage.cpu > 0 && ( + <> + + + {systemUsage.cpu?.toFixed(2)}% + + + )} +
+ } + /> +
+ + {/* RAM Information */} + + + {formatMegaBytes(hardwareData.total_memory)} +
+ } + /> + + {formatMegaBytes( + hardwareData.total_memory - systemUsage.used_memory + )} + + } + /> + + {hardwareData.total_memory > 0 && ( + <> + + + {( + toNumber( + systemUsage.used_memory / + systemUsage.total_memory + ) * 100 + ).toFixed(2)} + % + + + )} +
+ } + /> + + + {/* Llamacpp Devices Information */} + {!IS_MACOS && llamacpp && ( + + {llamacppDevicesLoading ? ( + } /> + ) : llamacppDevicesError ? ( + + {llamacppDevicesError} + + } + /> + ) : llamacppDevices.length > 0 ? ( + llamacppDevices.map((device, index) => ( + + + {/*
ID: {device.id} @@ -311,36 +348,37 @@ function Hardware() { {formatMegaBytes(device.free)} free
*/} - { - toggleDevice(device.id) - stopAllModels() - }} - /> -
- } - /> -
- - {formatMegaBytes(device.mem)}{' '} - {t('settings:hardware.freeOf')}{' '} - {formatMegaBytes(device.free)} - + { + toggleDevice(device.id) + stopAllModels() + }} + /> +
} /> - - - )) - ) : ( - } /> - )} - - )} - +
+ + {formatMegaBytes(device.mem)}{' '} + {t('settings:hardware.freeOf')}{' '} + {formatMegaBytes(device.free)} + + } + /> +
+ + )) + ) : ( + } /> + )} + + )} + + )} diff --git a/web-app/src/routes/system-monitor.tsx b/web-app/src/routes/system-monitor.tsx index 46717f93d..f2ede3899 100644 --- a/web-app/src/routes/system-monitor.tsx +++ b/web-app/src/routes/system-monitor.tsx @@ -10,6 +10,7 @@ import { useTranslation } from '@/i18n/react-i18next-compat' import { toNumber } from '@/utils/number' import { useLlamacppDevices } from '@/hooks/useLlamacppDevices' import { useModelProvider } from '@/hooks/useModelProvider' +import { getSystemUsage } from '@/services/hardware' export const Route = createFileRoute(route.systemMonitor as any)({ component: SystemMonitor, @@ -34,6 +35,21 @@ function SystemMonitor() { fetchDevices() }, [updateSystemUsage, fetchDevices]) + // Poll system usage every 5 seconds + useEffect(() => { + const intervalId = setInterval(() => { + getSystemUsage() + .then((data) => { + updateSystemUsage(data) + }) + .catch((error) => { + console.error('Failed to get system usage:', error) + }) + }, 5000) + + return () => clearInterval(intervalId) + }, [updateSystemUsage]) + // Initialize when hardware data and llamacpp devices are available useEffect(() => { if (hardwareData.gpus.length > 0 && !isInitialized) {