From 7eb8ccae48b0cc18a9dcaa9c3626a02df8e6d919 Mon Sep 17 00:00:00 2001 From: JustZvan Date: Fri, 6 Feb 2026 13:22:33 +0100 Subject: feat: initial commit! --- lib/device.tsx | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 lib/device.tsx (limited to 'lib/device.tsx') diff --git a/lib/device.tsx b/lib/device.tsx new file mode 100644 index 0000000..e0ec600 --- /dev/null +++ b/lib/device.tsx @@ -0,0 +1,90 @@ +import { + createContext, + ReactNode, + useCallback, + useContext, + useEffect, + useState, +} from "react"; +import { apiClient, getDevices } from "../api"; +import { Device } from "../api/types"; +import { useAuth } from "./auth"; + +type DeviceContextType = { + devices: Device[]; + selectedDevice: Device | null; + isLoading: boolean; + selectDevice: (device: Device) => Promise; + refreshDevices: () => Promise; +}; + +const DeviceContext = createContext(null); + +export function DeviceProvider({ children }: { children: ReactNode }) { + const [devices, setDevices] = useState([]); + const [selectedDevice, setSelectedDevice] = useState(null); + const [isLoading, setIsLoading] = useState(true); + const { isAuthenticated } = useAuth(); + + const refreshDevices = useCallback(async () => { + if (!isAuthenticated) { + setIsLoading(false); + return; + } + + setIsLoading(true); + try { + const fetchedDevices = await getDevices(); + setDevices(fetchedDevices); + + // If no device is selected, try to restore from storage or select first device + if (!selectedDevice && fetchedDevices.length > 0) { + const savedDeviceId = apiClient.getSelectedDeviceId(); + const savedDevice = fetchedDevices.find((d) => d.id === savedDeviceId); + + if (savedDevice) { + setSelectedDevice(savedDevice); + } else { + // Select first device by default + setSelectedDevice(fetchedDevices[0]!); + await apiClient.setSelectedDevice(fetchedDevices[0]!.id); + } + } + } catch (e) { + console.error("Failed to refresh devices", e); + } finally { + setIsLoading(false); + } + }, [selectedDevice, isAuthenticated]); + + useEffect(() => { + refreshDevices(); + }, [refreshDevices]); + + const selectDevice = useCallback(async (device: Device) => { + setSelectedDevice(device); + await apiClient.setSelectedDevice(device.id); + }, []); + + return ( + + {children} + + ); +} + +export function useDevice() { + const context = useContext(DeviceContext); + if (!context) { + throw new Error("useDevice must be used within a DeviceProvider"); + } + return context; +} -- cgit v1.2.3