From 0681c6bb9ef2a72c2ab07f49add7bb366c31e22b Mon Sep 17 00:00:00 2001 From: Faisal Amir Date: Wed, 18 Jun 2025 19:58:24 +0700 Subject: [PATCH] fix: glitch toggle gpus (#5353) * fix: glitch toogle gpu * fix: Using the GPU's array index as a key for gpuLoading * enhancement: added try-finally --- web-app/src/hooks/useHardware.ts | 68 ++++++++++++++++-------- web-app/src/routes/settings/hardware.tsx | 8 +-- 2 files changed, 52 insertions(+), 24 deletions(-) diff --git a/web-app/src/hooks/useHardware.ts b/web-app/src/hooks/useHardware.ts index 7ad067cc8..16e83a7a5 100644 --- a/web-app/src/hooks/useHardware.ts +++ b/web-app/src/hooks/useHardware.ts @@ -87,8 +87,17 @@ interface HardwareStore { // Update RAM available updateRAMAvailable: (available: number) => void - // Toggle GPU activation - toggleGPUActivation: (index: number) => void + // Toggle GPU activation (async, with loading) + toggleGPUActivation: (index: number) => Promise + + // GPU loading state + gpuLoading: { [index: number]: boolean } + setGpuLoading: (index: number, loading: boolean) => void + + // Polling control + pollingPaused: boolean + pausePolling: () => void + resumePolling: () => void // Reorder GPUs reorderGPUs: (oldIndex: number, newIndex: number) => void @@ -96,8 +105,16 @@ interface HardwareStore { export const useHardware = create()( persist( - (set) => ({ + (set, get) => ({ hardwareData: defaultHardwareData, + gpuLoading: {}, + pollingPaused: false, + setGpuLoading: (index, loading) => + set((state) => ({ + gpuLoading: { ...state.gpuLoading, [state.hardwareData.gpus[index].uuid]: loading }, + })), + pausePolling: () => set({ pollingPaused: true }), + resumePolling: () => set({ pollingPaused: false }), setCPU: (cpu) => set((state) => ({ @@ -172,25 +189,34 @@ export const useHardware = create()( }, })), - toggleGPUActivation: (index) => { - set((state) => { - const newGPUs = [...state.hardwareData.gpus] - if (index >= 0 && index < newGPUs.length) { - newGPUs[index] = { - ...newGPUs[index], - activated: !newGPUs[index].activated, + toggleGPUActivation: async (index) => { + const { pausePolling, setGpuLoading, resumePolling } = get(); + pausePolling(); + setGpuLoading(index, true); + try { + await new Promise((resolve) => setTimeout(resolve, 200)); // Simulate async, replace with real API if needed + set((state) => { + const newGPUs = [...state.hardwareData.gpus]; + if (index >= 0 && index < newGPUs.length) { + newGPUs[index] = { + ...newGPUs[index], + activated: !newGPUs[index].activated, + }; } - } - setActiveGpus({ - gpus: newGPUs.filter((e) => e.activated).map((e) => parseInt(e.id)), - }) - return { - hardwareData: { - ...state.hardwareData, - gpus: newGPUs, - }, - } - }) + setActiveGpus({ + gpus: newGPUs.filter((e) => e.activated).map((e) => parseInt(e.id)), + }); + return { + hardwareData: { + ...state.hardwareData, + gpus: newGPUs, + }, + }; + }); + } finally { + setGpuLoading(index, false); + setTimeout(resumePolling, 1000); // Resume polling after 1s + } }, reorderGPUs: (oldIndex, newIndex) => diff --git a/web-app/src/routes/settings/hardware.tsx b/web-app/src/routes/settings/hardware.tsx index beab425fe..23f4eafef 100644 --- a/web-app/src/routes/settings/hardware.tsx +++ b/web-app/src/routes/settings/hardware.tsx @@ -49,7 +49,7 @@ function SortableGPUItem({ gpu, index }: { gpu: GPU; index: number }) { isDragging, } = useSortable({ id: gpu.id || index }) - const { toggleGPUActivation } = useHardware() + const { toggleGPUActivation, gpuLoading } = useHardware() const style = { transform: CSS.Transform.toString(transform), @@ -78,6 +78,7 @@ function SortableGPUItem({ gpu, index }: { gpu: GPU; index: number }) {
toggleGPUActivation(index)} />
@@ -122,6 +123,7 @@ function Hardware() { updateCPUUsage, updateRAMAvailable, reorderGPUs, + pollingPaused, } = useHardware() const { vulkanEnabled, setVulkanEnabled } = useVulkan() @@ -155,16 +157,16 @@ function Hardware() { } useEffect(() => { + if (pollingPaused) return; const intervalId = setInterval(() => { getHardwareInfo().then((data) => { - setHardwareData(data as unknown as HardwareData) updateCPUUsage(data.cpu.usage) updateRAMAvailable(data.ram.available) }) }, 5000) return () => clearInterval(intervalId) - }, [setHardwareData, updateCPUUsage, updateRAMAvailable]) + }, [setHardwareData, updateCPUUsage, updateRAMAvailable, pollingPaused]) const handleClickSystemMonitor = async () => { try {