| 1 | import { ScreenScrollView as ScrollView } from "../../components/ScreenScrollView"; |
| 2 | import { useAuth, useUser } from "@clerk/expo"; |
| 3 | import { useNavigation } from "@react-navigation/native"; |
| 4 | import { Platform, View } from "react-native"; |
| 5 | import { deriveProjectGroupLabel } from "@t3tools/client-runtime/state/project-grouping"; |
| 6 | import { useSafeAreaInsets } from "react-native-safe-area-context"; |
| 7 | |
| 8 | import { useCloudAuthAvailable } from "../cloud/cloudAvailability"; |
| 9 | import { useAdaptiveWorkspaceLayout } from "../layout/AdaptiveWorkspaceLayout"; |
| 10 | import { NativeHeaderToolbar, NativeStackScreenOptions } from "../../native/StackHeader"; |
| 11 | import { useSavedRemoteConnections } from "../../state/use-remote-environment-registry"; |
| 12 | import { SettingsRow } from "./components/SettingsRow"; |
| 13 | import { SettingsSection } from "./components/SettingsSection"; |
| 14 | import { SettingsScreen } from "./components/SettingsScreen"; |
| 15 | import { |
| 16 | AndroidSettingsEnvironmentFilter, |
| 17 | SettingsEnvironmentFilterHeader, |
| 18 | } from "./components/SettingsEnvironmentFilterHeader"; |
| 19 | import { useSettingsEnvironmentFilter } from "./settings-environment-filter"; |
| 20 | |
| 21 | export function SettingsRouteScreen() { |
| 22 | const navigation = useNavigation(); |
| 23 | const { layout } = useAdaptiveWorkspaceLayout(); |
| 24 | const content = useCloudAuthAvailable() ? ( |
| 25 | <ConfiguredSettingsRouteScreen /> |
| 26 | ) : ( |
| 27 | <LocalSettingsRouteScreen /> |
| 28 | ); |
| 29 | |
| 30 | return ( |
| 31 | <> |
| 32 | {Platform.OS === "ios" ? ( |
| 33 | <NativeStackScreenOptions options={{ headerBackVisible: !layout.usesSplitView }} /> |
| 34 | ) : null} |
| 35 | {Platform.OS === "ios" && layout.usesSplitView ? ( |
| 36 | <> |
| 37 | <NativeHeaderToolbar placement="left"> |
| 38 | <NativeHeaderToolbar.Button |
| 39 | accessibilityLabel="Go back" |
| 40 | icon="chevron.left" |
| 41 | onPress={() => navigation.goBack()} |
| 42 | /> |
| 43 | </NativeHeaderToolbar> |
| 44 | </> |
| 45 | ) : null} |
| 46 | <SettingsEnvironmentFilterHeader closeSettings /> |
| 47 | {Platform.OS === "android" ? ( |
| 48 | <SettingsScreen title="Settings" trailing={<AndroidSettingsEnvironmentFilter />}> |
| 49 | {content} |
| 50 | </SettingsScreen> |
| 51 | ) : ( |
| 52 | content |
| 53 | )} |
| 54 | </> |
| 55 | ); |
| 56 | } |
| 57 | |
| 58 | function ConfiguredSettingsRouteScreen() { |
| 59 | const insets = useSafeAreaInsets(); |
| 60 | const navigation = useNavigation(); |
| 61 | const { isLoaded, isSignedIn } = useAuth({ treatPendingAsSignedOut: false }); |
| 62 | const { user } = useUser(); |
| 63 | const { savedConnectionsById } = useSavedRemoteConnections(); |
| 64 | const accountLabel = !isLoaded |
| 65 | ? "Checking" |
| 66 | : !isSignedIn |
| 67 | ? "Sign in" |
| 68 | : (user?.primaryEmailAddress?.emailAddress ?? "Signed in"); |
| 69 | |
| 70 | return ( |
| 71 | <View collapsable={false} className="flex-1 bg-sheet"> |
| 72 | <ScrollView |
| 73 | contentInsetAdjustmentBehavior="automatic" |
| 74 | showsVerticalScrollIndicator={false} |
| 75 | className="flex-1" |
| 76 | contentContainerClassName="gap-4 px-5 pt-4" |
| 77 | contentContainerStyle={{ paddingBottom: Math.max(insets.bottom, 18) + 18 }} |
| 78 | > |
| 79 | <SettingsSection title="Connections"> |
| 80 | <SettingsRow |
| 81 | icon="person.crop.circle" |
| 82 | label="T3 Account" |
| 83 | value={accountLabel} |
| 84 | disabled={!isLoaded} |
| 85 | onPress={() => navigation.navigate("SettingsSheet", { screen: "SettingsAuth" })} |
| 86 | /> |
| 87 | <SettingsRow |
| 88 | icon="desktopcomputer" |
| 89 | label="Environments" |
| 90 | value={`${Object.keys(savedConnectionsById).length}`} |
| 91 | valuePosition="trailing" |
| 92 | target="SettingsEnvironments" |
| 93 | /> |
| 94 | <SettingsRow icon="bell.badge" label="Notifications" target="SettingsNotifications" /> |
| 95 | </SettingsSection> |
| 96 | |
| 97 | <SettingsIndexSections /> |
| 98 | </ScrollView> |
| 99 | </View> |
| 100 | ); |
| 101 | } |
| 102 | |
| 103 | function LocalSettingsRouteScreen() { |
| 104 | const insets = useSafeAreaInsets(); |
| 105 | const { savedConnectionsById } = useSavedRemoteConnections(); |
| 106 | const environmentCount = Object.keys(savedConnectionsById).length; |
| 107 | |
| 108 | return ( |
| 109 | <View collapsable={false} className="flex-1 bg-sheet"> |
| 110 | <ScrollView |
| 111 | contentInsetAdjustmentBehavior="automatic" |
| 112 | showsVerticalScrollIndicator={false} |
| 113 | className="flex-1" |
| 114 | contentContainerClassName="gap-4 px-5 pt-4" |
| 115 | contentContainerStyle={{ |
| 116 | paddingBottom: Math.max(insets.bottom, 18) + 18, |
| 117 | }} |
| 118 | > |
| 119 | <SettingsSection title="Connections"> |
| 120 | <SettingsRow |
| 121 | icon="desktopcomputer" |
| 122 | label="Environments" |
| 123 | value={`${environmentCount}`} |
| 124 | valuePosition="trailing" |
| 125 | target="SettingsEnvironments" |
| 126 | /> |
| 127 | </SettingsSection> |
| 128 | |
| 129 | <SettingsIndexSections /> |
| 130 | </ScrollView> |
| 131 | </View> |
| 132 | ); |
| 133 | } |
| 134 | |
| 135 | function SettingsIndexSections() { |
| 136 | const { selectedTargets, projectGroups, selectedProjectKey } = useSettingsEnvironmentFilter(); |
| 137 | const noServerTargets = selectedTargets.length === 0; |
| 138 | const selectedProject = projectGroups.find((group) => group.key === selectedProjectKey); |
| 139 | const scopedProjectMembers = |
| 140 | selectedProject?.members |
| 141 | .map((member) => member.project) |
| 142 | .filter((project) => |
| 143 | selectedTargets.some((target) => target.environmentId === project.environmentId), |
| 144 | ) ?? []; |
| 145 | const projectLabel = |
| 146 | scopedProjectMembers.length > 0 |
| 147 | ? deriveProjectGroupLabel({ |
| 148 | representative: scopedProjectMembers[0]!, |
| 149 | members: scopedProjectMembers, |
| 150 | }) |
| 151 | : (selectedProject?.label ?? "Unavailable project"); |
| 152 | return ( |
| 153 | <> |
| 154 | <SettingsSection title="Interface"> |
| 155 | <SettingsRow icon="paintbrush" label="Appearance" target="SettingsAppearance" /> |
| 156 | {Platform.OS === "ios" ? ( |
| 157 | <> |
| 158 | <SettingsRow icon="keyboard" label="Keyboard" target="SettingsKeyboard" /> |
| 159 | <SettingsRow icon="mic" label="Microphone" target="SettingsMicrophone" /> |
| 160 | </> |
| 161 | ) : null} |
| 162 | </SettingsSection> |
| 163 | |
| 164 | <SettingsSection title="Automations"> |
| 165 | <SettingsRow icon="clock" label="Scheduled tasks" target="SettingsScheduledTasks" /> |
| 166 | </SettingsSection> |
| 167 | |
| 168 | <SettingsSection title="Projects & threads"> |
| 169 | {selectedProjectKey !== null ? ( |
| 170 | <SettingsRow |
| 171 | icon="folder" |
| 172 | label="Overview" |
| 173 | value={projectLabel} |
| 174 | target="SettingsProjectOverview" |
| 175 | /> |
| 176 | ) : null} |
| 177 | <SettingsRow icon="folder" label="Organization" target="SettingsOrganization" /> |
| 178 | <SettingsRow icon="text.bubble" label="Thread behavior" target="SettingsThreads" /> |
| 179 | <SettingsRow icon="arrow.turn.left.up" label="Follow-ups" target="SettingsFollowUp" /> |
| 180 | <SettingsRow icon="archivebox" label="Archived Threads" target="SettingsArchive" /> |
| 181 | </SettingsSection> |
| 182 | |
| 183 | <SettingsSection title="Server settings"> |
| 184 | <SettingsRow |
| 185 | icon="person.crop.circle" |
| 186 | label="Provider accounts" |
| 187 | target="SettingsProviderAccounts" |
| 188 | disabled={noServerTargets} |
| 189 | /> |
| 190 | <SettingsRow |
| 191 | icon="text.bubble" |
| 192 | label="New threads" |
| 193 | target="SettingsEnvironmentNewThreads" |
| 194 | disabled={noServerTargets} |
| 195 | /> |
| 196 | <SettingsRow |
| 197 | icon="arrow.triangle.branch" |
| 198 | label="Source control" |
| 199 | target="SettingsEnvironmentSourceControl" |
| 200 | disabled={noServerTargets} |
| 201 | /> |
| 202 | <SettingsRow |
| 203 | icon="text.alignleft" |
| 204 | label="Agent behavior" |
| 205 | target="SettingsEnvironmentAgentBehavior" |
| 206 | disabled={noServerTargets} |
| 207 | /> |
| 208 | <SettingsRow |
| 209 | icon="arrow.clockwise" |
| 210 | label="Maintenance" |
| 211 | target="SettingsEnvironmentMaintenance" |
| 212 | disabled={noServerTargets} |
| 213 | /> |
| 214 | </SettingsSection> |
| 215 | |
| 216 | <SettingsSection title="App"> |
| 217 | <SettingsRow icon="chart.bar.xaxis" label="Usage" target="SettingsUsage" /> |
| 218 | <SettingsRow icon="info.circle" label="About The Knife" target="SettingsAbout" /> |
| 219 | </SettingsSection> |
| 220 | </> |
| 221 | ); |
| 222 | } |