1import type { EnvironmentId } from "@t3tools/contracts";
2import { useCallback } from "react";
3import { View } from "react-native";
4
5import { EmptyState } from "../../components/EmptyState";
6import { environmentCatalog } from "../../connection/catalog";
7import type { AssetUrlFailureReason } from "../../state/asset-url-state";
8import { useAtomCommand } from "../../state/use-atom-command";
9import { useEnvironmentPresentation } from "../../state/presentation";
10import { EnvironmentConnectionNotice } from "../connection/EnvironmentConnectionNotice";
11
12/**
13 * Terminal state for a preview whose signed asset URL will not arrive. A dead
14 * environment reuses the same notice the terminal and review sheets show, so the
15 * user gets one recognizable way back online.
16 */
17export function WorkspaceFilePreviewError(props: {
18 readonly environmentId: EnvironmentId | null;
19 readonly reason: AssetUrlFailureReason;
20 readonly onRetry: () => void;
21}) {
22 const { environmentId, onRetry } = props;
23 const environment = useEnvironmentPresentation(environmentId);
24 const retryEnvironment = useAtomCommand(environmentCatalog.retryNow, "environment retry");
25 const retryConnection = useCallback(() => {
26 if (environmentId !== null) void retryEnvironment(environmentId);
27 onRetry();
28 }, [environmentId, onRetry, retryEnvironment]);
29
30 if (props.reason === "disconnected") {
31 return (
32 <View className="flex-1 bg-sheet">
33 <EnvironmentConnectionNotice
34 environmentLabel={environment.presentation?.entry.target.label ?? "Environment"}
35 connection={
36 environment.presentation?.connection ?? {
37 phase: "available",
38 error: null,
39 traceId: null,
40 }
41 }
42 resourceName="preview"
43 onRetry={retryConnection}
44 />
45 </View>
46 );
47 }
48
49 return (
50 <View className="flex-1 items-center justify-center bg-sheet px-6">
51 <EmptyState
52 title="Preview unavailable"
53 detail="This file may be missing, unsupported, or unavailable on this environment."
54 actionLabel="Try again"
55 onAction={props.onRetry}
56 />
57 </View>
58 );
59}