diff options
| author | JustZvan <justzvan@justzvan.xyz> | 2026-02-06 13:22:33 +0100 |
|---|---|---|
| committer | JustZvan <justzvan@justzvan.xyz> | 2026-02-06 13:22:33 +0100 |
| commit | 7eb8ccae48b0cc18a9dcaa9c3626a02df8e6d919 (patch) | |
| tree | 57b7dd06ac9aa7053c671d916f7183e3b4fa9410 /lib/device.tsx | |
feat: initial commit!
Diffstat (limited to 'lib/device.tsx')
| -rw-r--r-- | lib/device.tsx | 90 |
1 files changed, 90 insertions, 0 deletions
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<void>; + refreshDevices: () => Promise<void>; +}; + +const DeviceContext = createContext<DeviceContextType | null>(null); + +export function DeviceProvider({ children }: { children: ReactNode }) { + const [devices, setDevices] = useState<Device[]>([]); + const [selectedDevice, setSelectedDevice] = useState<Device | null>(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 ( + <DeviceContext.Provider + value={{ + devices, + selectedDevice, + isLoading, + selectDevice, + refreshDevices, + }} + > + {children} + </DeviceContext.Provider> + ); +} + +export function useDevice() { + const context = useContext(DeviceContext); + if (!context) { + throw new Error("useDevice must be used within a DeviceProvider"); + } + return context; +} |