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
This commit is contained in:
Faisal Amir 2025-06-18 19:58:24 +07:00 committed by GitHub
parent f5971b9d03
commit 0681c6bb9e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 52 additions and 24 deletions

View File

@ -87,8 +87,17 @@ interface HardwareStore {
// Update RAM available // Update RAM available
updateRAMAvailable: (available: number) => void updateRAMAvailable: (available: number) => void
// Toggle GPU activation // Toggle GPU activation (async, with loading)
toggleGPUActivation: (index: number) => void toggleGPUActivation: (index: number) => Promise<void>
// GPU loading state
gpuLoading: { [index: number]: boolean }
setGpuLoading: (index: number, loading: boolean) => void
// Polling control
pollingPaused: boolean
pausePolling: () => void
resumePolling: () => void
// Reorder GPUs // Reorder GPUs
reorderGPUs: (oldIndex: number, newIndex: number) => void reorderGPUs: (oldIndex: number, newIndex: number) => void
@ -96,8 +105,16 @@ interface HardwareStore {
export const useHardware = create<HardwareStore>()( export const useHardware = create<HardwareStore>()(
persist( persist(
(set) => ({ (set, get) => ({
hardwareData: defaultHardwareData, 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) => setCPU: (cpu) =>
set((state) => ({ set((state) => ({
@ -172,25 +189,34 @@ export const useHardware = create<HardwareStore>()(
}, },
})), })),
toggleGPUActivation: (index) => { 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) => { set((state) => {
const newGPUs = [...state.hardwareData.gpus] const newGPUs = [...state.hardwareData.gpus];
if (index >= 0 && index < newGPUs.length) { if (index >= 0 && index < newGPUs.length) {
newGPUs[index] = { newGPUs[index] = {
...newGPUs[index], ...newGPUs[index],
activated: !newGPUs[index].activated, activated: !newGPUs[index].activated,
} };
} }
setActiveGpus({ setActiveGpus({
gpus: newGPUs.filter((e) => e.activated).map((e) => parseInt(e.id)), gpus: newGPUs.filter((e) => e.activated).map((e) => parseInt(e.id)),
}) });
return { return {
hardwareData: { hardwareData: {
...state.hardwareData, ...state.hardwareData,
gpus: newGPUs, gpus: newGPUs,
}, },
};
});
} finally {
setGpuLoading(index, false);
setTimeout(resumePolling, 1000); // Resume polling after 1s
} }
})
}, },
reorderGPUs: (oldIndex, newIndex) => reorderGPUs: (oldIndex, newIndex) =>

View File

@ -49,7 +49,7 @@ function SortableGPUItem({ gpu, index }: { gpu: GPU; index: number }) {
isDragging, isDragging,
} = useSortable({ id: gpu.id || index }) } = useSortable({ id: gpu.id || index })
const { toggleGPUActivation } = useHardware() const { toggleGPUActivation, gpuLoading } = useHardware()
const style = { const style = {
transform: CSS.Transform.toString(transform), transform: CSS.Transform.toString(transform),
@ -78,6 +78,7 @@ function SortableGPUItem({ gpu, index }: { gpu: GPU; index: number }) {
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<Switch <Switch
checked={gpu.activated} checked={gpu.activated}
disabled={!!gpuLoading[index]}
onCheckedChange={() => toggleGPUActivation(index)} onCheckedChange={() => toggleGPUActivation(index)}
/> />
</div> </div>
@ -122,6 +123,7 @@ function Hardware() {
updateCPUUsage, updateCPUUsage,
updateRAMAvailable, updateRAMAvailable,
reorderGPUs, reorderGPUs,
pollingPaused,
} = useHardware() } = useHardware()
const { vulkanEnabled, setVulkanEnabled } = useVulkan() const { vulkanEnabled, setVulkanEnabled } = useVulkan()
@ -155,16 +157,16 @@ function Hardware() {
} }
useEffect(() => { useEffect(() => {
if (pollingPaused) return;
const intervalId = setInterval(() => { const intervalId = setInterval(() => {
getHardwareInfo().then((data) => { getHardwareInfo().then((data) => {
setHardwareData(data as unknown as HardwareData)
updateCPUUsage(data.cpu.usage) updateCPUUsage(data.cpu.usage)
updateRAMAvailable(data.ram.available) updateRAMAvailable(data.ram.available)
}) })
}, 5000) }, 5000)
return () => clearInterval(intervalId) return () => clearInterval(intervalId)
}, [setHardwareData, updateCPUUsage, updateRAMAvailable]) }, [setHardwareData, updateCPUUsage, updateRAMAvailable, pollingPaused])
const handleClickSystemMonitor = async () => { const handleClickSystemMonitor = async () => {
try { try {