"use client"; import { useCallback, useEffect, useState } from "react"; import { useTranslations } from "next-intl"; import { RefreshCw } from "lucide-react"; import type { FirmwareInfo } from "@/lib/firmware"; import { formatBytes, cn } from "@/lib/utils"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { Card, CardHeader, CardTitle } from "@/components/ui/card"; import { EspWebInstall } from "@/components/esp-web-install"; function supportsWebSerial() { return typeof navigator !== "undefined" && "serial" in navigator; } export function FlasherPanel() { const t = useTranslations(); const [firmwares, setFirmwares] = useState([]); const [selectedId, setSelectedId] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [serialOk, setSerialOk] = useState(true); const load = useCallback(async () => { setLoading(true); setError(null); try { const res = await fetch("/api/firmware", { cache: "no-store" }); if (!res.ok) throw new Error(`HTTP ${res.status}`); const data = (await res.json()) as { firmwares: FirmwareInfo[] }; const list = data.firmwares ?? []; setFirmwares(list); setSelectedId((prev) => { if (prev && list.some((f) => f.id === prev)) return prev; return list[0]?.id ?? null; }); } catch (err) { setError(err instanceof Error ? err.message : String(err)); setFirmwares([]); } finally { setLoading(false); } }, []); useEffect(() => { setSerialOk(supportsWebSerial()); void load(); }, [load]); const selected = firmwares.find((f) => f.id === selectedId) ?? null; return (
{!serialOk && (

{t("browser.unsupported")}

)} {t("firmware.title")}
{loading && !firmwares.length && (

{t("firmware.scanning")}

)} {error && (

{t("firmware.error", { message: error })}

)} {!loading && !error && !firmwares.length && (

{t("firmware.empty")}

)} {firmwares.map((fw) => { const active = fw.id === selectedId; const meta = [fw.board, fw.date, fw.git ? `git ${fw.git}` : null] .filter(Boolean) .join(" · "); return ( ); })}
{selected ? ( <> {t("firmware.selectedLabel")}{" "} {selected.name} ({selected.id}) ) : ( {t("firmware.noneSelected")} )}
  1. {t("install.steps.1")}
  2. {t("install.steps.2")}
  3. {t("install.steps.3")}
  4. {t("install.steps.4")}
); }