1import type { DeviceServiceState, EnvironmentId } from "@t3tools/contracts";
2import { useState } from "react";
3import { Button } from "~/components/ui/button";
4import { deviceEnvironment } from "~/state/device";
5import { useAtomCommand } from "~/state/use-atom-command";
6
7/** Shared by setup, Settings, and the Device panel so automatic updates stay visible. */
8export function DeviceHostUpdates({
9 state,
10 environmentId,
11}: {
12 state: DeviceServiceState;
13 environmentId: EnvironmentId;
14}) {
15 const retry = useAtomCommand(deviceEnvironment.list);
16 const [pending, setPending] = useState<string | null>(null);
17 if (state.hostStatus === "disabled") return null;
18 return (
19 <div className="space-y-2">
20 {state.hosts.map((host) => {
21 const status = state.hostStatuses[host.id];
22 if (!status || !["installing", "starting", "failed"].includes(status.status)) return null;
23 const failed = status.status === "failed";
24 return (
25 <div
26 key={host.id}
27 role={failed ? "alert" : "status"}
28 className="flex items-start gap-3 rounded-md border border-border/60 px-3 py-2 text-xs"
29 >
30 <div className="min-w-0 flex-1">
31 <p className="font-medium">{host.label}</p>
32 <p className="whitespace-pre-wrap break-words text-muted-foreground">
33 {status.detail ??
34 (failed
35 ? "Device support could not start."
36 : status.status === "installing"
37 ? "Installing device tools…"
38 : "Starting device tools…")}
39 </p>
40 {failed ? (
41 <p className="mt-1 text-muted-foreground">
42 Check the host connection and network access, then retry. Your device settings are
43 saved.
44 </p>
45 ) : null}
46 </div>
47 {failed && state.supportsHostRetry ? (
48 <Button
49 size="compact"
50 variant="outline"
51 disabled={pending !== null}
52 onClick={() => {
53 setPending(host.id);
54 void retry({ environmentId, input: { retryHostId: host.id } }).finally(() =>
55 setPending(null),
56 );
57 }}
58 >
59 {pending === host.id ? "Retrying…" : "Retry"}
60 </Button>
61 ) : null}
62 </div>
63 );
64 })}
65 </div>
66 );
67}