Skip to content
Source
Sign inSign up

EnvironmentConnectionNotice.tsx

98 lines3.3 KB

1import { Button } from "../../components/ui/Button";
2import { AppActivityIndicator } from "../../components/ui/AppActivityIndicator";
3import { ConnectionTraceId } from "./ConnectionTraceId";
4import {
5 type EnvironmentConnectionPhase,
6 type EnvironmentConnectionPresentation,
7} from "@t3tools/client-runtime/connection";
8import { SymbolView } from "../../components/ui/AppSymbol";
9import { View } from "react-native";
10​
11import { AppText as Text } from "../../components/ui/AppText";
12​
13function noticeTitle(phase: EnvironmentConnectionPhase, environmentLabel: string): string {
14 switch (phase) {
15 case "offline":
16 return "You are offline";
17 case "connecting":
18 return `Connecting to ${environmentLabel}...`;
19 case "reconnecting":
20 return `Reconnecting to ${environmentLabel}...`;
21 case "unsupported":
22 return "Client not supported";
23 case "error":
24 return `${environmentLabel} is unavailable`;
25 case "available":
26 return `${environmentLabel} is disconnected`;
27 case "connected":
28 return "";
29 }
31​
32function noticeDetail(
33 phase: EnvironmentConnectionPhase,
34 resourceName: string,
35 error: string | null,
36): string {
37 if (error) {
38 return phase === "reconnecting" ? `The app will keep retrying automatically. ${error}` : error;
39 }
40​
41 switch (phase) {
42 case "offline":
43 return `Cached data remains available. The ${resourceName} will load when your connection returns.`;
44 case "connecting":
45 case "reconnecting":
46 return `The ${resourceName} will load as soon as the environment is ready.`;
47 case "unsupported":
48 return "Use compatible versions of the app and server to connect.";
49 case "available":
50 case "error":
51 return `Reconnect the environment to load the ${resourceName}.`;
52 case "connected":
53 return "";
54 }
56​
57export function EnvironmentConnectionNotice(props: {
58 readonly environmentLabel: string;
59 readonly connection: EnvironmentConnectionPresentation;
60 readonly resourceName: string;
61 readonly onRetry: () => void;
62}) {
63 const isRetrying =
64 props.connection.phase === "connecting" || props.connection.phase === "reconnecting";
65​
66 return (
67 <View className="flex-1 items-center justify-center px-8">
68 <View className="max-w-[320px] items-center gap-3">
69 {isRetrying ? (
70 <AppActivityIndicator size="small" colorClassName={"accent-icon-muted"} />
71 ) : (
72 <SymbolView
73 name={props.connection.phase === "offline" ? "wifi.slash" : "bolt.horizontal.circle"}
74 size={24}
75 tintColorClassName={"accent-icon-muted"}
76 type="monochrome"
77 />
78 )}
79​
80 <Text className="text-center text-lg font-t3-bold text-foreground">
81 {noticeTitle(props.connection.phase, props.environmentLabel)}
82 </Text>
83 <Text className="text-center text-sm leading-normal text-foreground-muted">
84 {noticeDetail(props.connection.phase, props.resourceName, props.connection.error)}
85 {props.connection.traceId ? (
86 <ConnectionTraceId traceId={props.connection.traceId} />
87 ) : null}
88 </Text>
89​
90 {props.connection.phase !== "offline" && props.connection.phase !== "unsupported" ? (
91 <View className="mt-1">
92 <Button label="Retry now" tone="secondary" onPress={props.onRetry} />
93 </View>
94 ) : null}
95 </View>
96 </View>
97 );