IKHSAN
ENID Baca dalam Bahasa Indonesia

homeio

Public

Forked from doctor-io/homeio

Branch
main
Latest commit
958d74616 October 2026

useUsbDrives.ts

Open raw
"use client";

import type { UsbDrive, UsbSseEvent } from "@/lib/shared/contracts/usb";
import { queryKeys } from "@/lib/shared/query-keys";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useEffect } from "react";

async function fetchUsbDrives(): Promise<UsbDrive[]> {
  const res = await fetch("/api/v1/files/usb");
  if (!res.ok) return [];
  const data = await res.json() as { drives: UsbDrive[] };
  return data.drives;
}

export function useUsbDrives() {
  const queryClient = useQueryClient();

  const { data: drives = [] } = useQuery({
    queryKey: queryKeys.usbDrives,
    queryFn: fetchUsbDrives,
    staleTime: 10_000,
    refetchInterval: 15_000,
  });

  useEffect(() => {
    const source = new EventSource("/api/v1/files/usb/stream");

    const handleEvent = () => {
      queryClient.invalidateQueries({ queryKey: queryKeys.usbDrives });
    };

    const eventTypes: UsbSseEvent["type"][] = [
      "usb.connected",
      "usb.disconnected",
      "usb.mounted",
      "usb.unmounted",
    ];
    for (const type of eventTypes) {
      source.addEventListener(type, handleEvent);
    }

    return () => {
      for (const type of eventTypes) {
        source.removeEventListener(type, handleEvent);
      }
      source.close();
    };
  }, [queryClient]);

  const mountMutation = useMutation({
    mutationFn: async (driveId: string) => {
      const res = await fetch(`/api/v1/files/usb/${driveId}/mount`, { method: "POST" });
      if (!res.ok) throw new Error("Mount failed");
    },
    onSuccess: () => queryClient.invalidateQueries({ queryKey: queryKeys.usbDrives }),
  });

  const unmountMutation = useMutation({
    mutationFn: async (driveId: string) => {
      const res = await fetch(`/api/v1/files/usb/${driveId}/unmount`, { method: "POST" });
      if (!res.ok) throw new Error("Unmount failed");
    },
    onSuccess: () => queryClient.invalidateQueries({ queryKey: queryKeys.usbDrives }),
  });

  const ejectMutation = useMutation({
    mutationFn: async (driveId: string) => {
      const res = await fetch(`/api/v1/files/usb/${driveId}/eject`, { method: "POST" });
      if (!res.ok) throw new Error("Eject failed");
    },
    onSuccess: () => queryClient.invalidateQueries({ queryKey: queryKeys.usbDrives }),
  });

  return {
    drives,
    mount: mountMutation.mutate,
    unmount: unmountMutation.mutate,
    eject: ejectMutation.mutate,
    isMounting: mountMutation.isPending,
    isUnmounting: unmountMutation.isPending,
    isEjecting: ejectMutation.isPending,
  };
}
bytes
2,561
lines
84
Type
ts
Latest commit
16 October 2026