1import { useAtomValue } from "@effect/atom-react";
2import { Alert, View } from "react-native";
3
4import { AppText as Text } from "../../components/AppText";
5import { ListRowLayout } from "../../components/ListRowLayout";
6import { hubConnection } from "../../connection/hub";
7import { useAtomCommand } from "../../state/use-atom-command";
8import { SettingsRow } from "../settings/components/SettingsRow";
9import { SettingsSection } from "../settings/components/SettingsSection";
10
11export function SelfHostedServerSection() {
12 const hub = useAtomValue(hubConnection.stateValueAtom);
13 const refresh = useAtomCommand(hubConnection.refresh, { reportFailure: false });
14 const disconnect = useAtomCommand(hubConnection.disconnect, { reportFailure: false });
15
16 if (hub.connection === null) return null;
17
18 const connection = hub.connection;
19
20 return (
21 <View className="mb-6 gap-2">
22 <SettingsSection title="Self-hosted server">
23 <ListRowLayout
24 icon="server.rack"
25 label={connection.label}
26 description={connection.httpBaseUrl}
27 />
28 <SettingsRow
29 icon="arrow.clockwise"
30 label={hub.refreshing ? "Refreshing…" : "Refresh machines"}
31 disabled={hub.refreshing}
32 onPress={() => void refresh(undefined)}
33 />
34 <SettingsRow
35 icon="xmark.circle.fill"
36 label="Disconnect"
37 onPress={() =>
38 Alert.alert(
39 `Disconnect ${connection.label}?`,
40 "Remove this phone’s server access. Direct connections and running work stay in place.",
41 [
42 { text: "Cancel", style: "cancel" },
43 {
44 text: "Disconnect",
45 style: "destructive",
46 onPress: () => void disconnect(undefined),
47 },
48 ],
49 )
50 }
51 />
52 </SettingsSection>
53 {hub.error ? (
54 <Text accessibilityLiveRegion="polite" className="px-4 text-sm text-danger-foreground">
55 {hub.error}
56 </Text>
57 ) : null}
58 </View>
59 );
60}