| 1 | import { useAuth } from "@clerk/expo"; |
| 2 | import { AuthView, type UserProfileCustomPage, UserProfileView } from "@clerk/expo/native"; |
| 3 | import { StackActions, useNavigation } from "@react-navigation/native"; |
| 4 | import { useCallback, useEffect, useLayoutEffect, useRef } from "react"; |
| 5 | import { View } from "react-native"; |
| 6 | import { useAtomSet } from "@effect/atom-react"; |
| 7 | |
| 8 | import { hasCloudPublicConfig } from "../cloud/publicConfig"; |
| 9 | import { T3ConnectProfilePage } from "../cloud/T3ConnectProfilePage"; |
| 10 | import { useCloudAuthAvailable } from "../cloud/cloudAvailability"; |
| 11 | import { updateMobilePreferencesAtom } from "../../state/preferences"; |
| 12 | |
| 13 | // Custom rows in Clerk's native profile. Mirrors the web UserButton pages. |
| 14 | const USER_PROFILE_CUSTOM_PAGES = [ |
| 15 | { |
| 16 | path: "t3-connect", |
| 17 | label: "T3 Connect", |
| 18 | icon: "globe", |
| 19 | content: <T3ConnectProfilePage />, |
| 20 | }, |
| 21 | ] satisfies UserProfileCustomPage[]; |
| 22 | |
| 23 | export function SettingsAuthRouteScreen() { |
| 24 | const navigation = useNavigation(); |
| 25 | const cloudAvailable = useCloudAuthAvailable(); |
| 26 | const savePreferences = useAtomSet(updateMobilePreferencesAtom); |
| 27 | |
| 28 | useLayoutEffect(() => { |
| 29 | if (!hasCloudPublicConfig()) { |
| 30 | navigation.dispatch(StackActions.replace("SettingsContent")); |
| 31 | } else if (!cloudAvailable) { |
| 32 | savePreferences({ connectionService: "t3-connect" }); |
| 33 | } |
| 34 | }, [cloudAvailable, navigation, savePreferences]); |
| 35 | |
| 36 | return cloudAvailable ? <ConfiguredSettingsAuthRouteScreen /> : null; |
| 37 | } |
| 38 | |
| 39 | function ConfiguredSettingsAuthRouteScreen() { |
| 40 | const { isLoaded, isSignedIn } = useAuth({ treatPendingAsSignedOut: false }); |
| 41 | const navigation = useNavigation(); |
| 42 | const handleHostBack = useCallback( |
| 43 | () => navigation.dispatch(StackActions.popTo("SettingsContent")), |
| 44 | [navigation], |
| 45 | ); |
| 46 | const hasBeenSignedIn = useRef(isSignedIn); |
| 47 | if (isSignedIn) { |
| 48 | hasBeenSignedIn.current = true; |
| 49 | } |
| 50 | |
| 51 | useEffect(() => { |
| 52 | if (hasBeenSignedIn.current && isLoaded && isSignedIn === false) { |
| 53 | navigation.dispatch(StackActions.popTo("SettingsContent")); |
| 54 | } |
| 55 | }, [isLoaded, isSignedIn, navigation]); |
| 56 | |
| 57 | return ( |
| 58 | <View collapsable={false} className="flex-1 overflow-hidden bg-sheet"> |
| 59 | {isLoaded ? ( |
| 60 | hasBeenSignedIn.current ? ( |
| 61 | <UserProfileView |
| 62 | customPages={USER_PROFILE_CUSTOM_PAGES} |
| 63 | isDismissible={false} |
| 64 | onHostBack={handleHostBack} |
| 65 | /> |
| 66 | ) : ( |
| 67 | <AuthView isDismissible={false} onHostBack={handleHostBack} /> |
| 68 | ) |
| 69 | ) : null} |
| 70 | </View> |
| 71 | ); |
| 72 | } |