import {useCallback, useEffect, useState} from 'react' import {View} from 'react-native' import {useSafeAreaInsets} from 'react-native-safe-area-context' import {useLingui} from '@lingui/react/macro' import {useQueryClient} from '@tanstack/react-query' import {PressableScale} from '#/lib/custom-animations/PressableScale' import {STALE} from '#/state/queries' import {profilesQueryKey} from '#/state/queries/profile' import {useAppviewClient, useSession} from '#/state/session' import {useSetActiveLanding} from '#/state/shell/landing' import { useLoggedOutView, useLoggedOutViewControls, } from '#/state/shell/logged-out' import {useEnableMinimalShellMode} from '#/state/shell/minimal-mode' import {ErrorBoundary} from '#/view/com/util/ErrorBoundary' import {Login} from '#/screens/Login' import {JoinRequest} from '#/screens/Messages/JoinRequest' import {Signup} from '#/screens/Signup' import {LandingScreen} from '#/screens/StarterPack/StarterPackLandingScreen' import {atoms as a, native, tokens, useTheme} from '#/alf' import {Button, ButtonIcon} from '#/components/Button' import {TimesLarge_Stroke2_Corner0_Rounded as XIcon} from '#/components/icons/Times' import {useAnalytics} from '#/analytics' import {app} from '#/lexicons' import {SplashScreen} from './SplashScreen' enum ScreenState { S_LoginOrCreateAccount, S_Login, S_CreateAccount, S_StarterPack, S_GroupChatJoinRequest, } export {ScreenState as LoggedOutScreenState} function getInitialScreenState(requestedAccountSwitchTo?: string): ScreenState { switch (requestedAccountSwitchTo) { case 'new': return ScreenState.S_CreateAccount case 'starterpack': return ScreenState.S_StarterPack case 'groupchat': return ScreenState.S_GroupChatJoinRequest case undefined: return ScreenState.S_LoginOrCreateAccount default: // DID or other string = login with that account return ScreenState.S_Login } } export function LoggedOut({onDismiss}: {onDismiss?: () => void}) { const {t: l} = useLingui() const ax = useAnalytics() const t = useTheme() const insets = useSafeAreaInsets() useEnableMinimalShellMode() const {requestedAccountSwitchTo} = useLoggedOutView() const initialScreenState = getInitialScreenState(requestedAccountSwitchTo) const [screenState, setScreenState] = useState(initialScreenState) const {clearRequestedAccount} = useLoggedOutViewControls() const setActiveLanding = useSetActiveLanding() const queryClient = useQueryClient() const {accounts} = useSession() const client = useAppviewClient() useEffect(() => { const actors = accounts.map(acc => acc.did) if (actors.length === 0) return void queryClient.prefetchQuery({ queryKey: profilesQueryKey(actors), staleTime: STALE.MINUTES.FIVE, queryFn: async () => { return await client.call(app.bsky.actor.getProfiles, {actors}) }, }) }, [accounts, client, queryClient]) const onPressDismiss = useCallback(() => { if (onDismiss) { onDismiss() } clearRequestedAccount() // Clear landing context when user dismisses the modal setActiveLanding(undefined) }, [clearRequestedAccount, onDismiss, setActiveLanding]) /* * Back from the login or create-account step. Where it returns depends on how * the view was entered: * - Entered on the splash or a landing screen (Starter Pack, group chat * invite): return there, i.e. the screen the user actually saw first. * - Dropped directly onto login/create-account (e.g. tapping "Create * account" elsewhere in the app): there is no preceding screen in this * view, so dismiss it. Fall back to the splash when the view cannot be * dismissed (native with no session), since that is its natural root. */ const onPressBack = useCallback(() => { if ( initialScreenState === ScreenState.S_Login || initialScreenState === ScreenState.S_CreateAccount ) { if (onDismiss) { onPressDismiss() } else { setScreenState(ScreenState.S_LoginOrCreateAccount) } } else { setScreenState(initialScreenState) } }, [initialScreenState, onDismiss, onPressDismiss]) return ( {onDismiss && screenState === ScreenState.S_LoginOrCreateAccount ? ( ) : null} {screenState === ScreenState.S_StarterPack ? ( ) : screenState === ScreenState.S_GroupChatJoinRequest ? ( ) : screenState === ScreenState.S_LoginOrCreateAccount ? ( { setScreenState(ScreenState.S_Login) ax.metric('splash:signInPressed', {}) }} onPressCreateAccount={() => { setScreenState(ScreenState.S_CreateAccount) ax.metric('splash:createAccountPressed', {}) }} /> ) : undefined} {screenState === ScreenState.S_Login ? ( { setScreenState(ScreenState.S_CreateAccount) }} /> ) : undefined} {screenState === ScreenState.S_CreateAccount ? ( { setScreenState(ScreenState.S_Login) ax.metric('splash:signInPressed', {}) }} /> ) : undefined} ) }