summaryrefslogtreecommitdiff
path: root/lib/device.tsx
diff options
context:
space:
mode:
authorJustZvan <justzvan@justzvan.xyz>2026-02-06 13:22:33 +0100
committerJustZvan <justzvan@justzvan.xyz>2026-02-06 13:22:33 +0100
commit7eb8ccae48b0cc18a9dcaa9c3626a02df8e6d919 (patch)
tree57b7dd06ac9aa7053c671d916f7183e3b4fa9410 /lib/device.tsx
feat: initial commit!
Diffstat (limited to 'lib/device.tsx')
-rw-r--r--lib/device.tsx90
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;
+}