···11+import React from 'react'
22+import {useAnalytics} from '#/lib/analytics/analytics'
33+import {useLingui} from '@lingui/react'
44+import {LoggedOutLayout} from '#/view/com/util/layouts/LoggedOutLayout'
55+import {SessionAccount, useSession} from '#/state/session'
66+import {DEFAULT_SERVICE} from '#/lib/constants'
77+import {useLoggedOutView} from '#/state/shell/logged-out'
88+import {useServiceQuery} from '#/state/queries/service'
99+import {msg} from '@lingui/macro'
1010+import {logger} from '#/logger'
1111+import {atoms as a} from '#/alf'
1212+import {KeyboardAvoidingView} from 'react-native'
1313+import {ChooseAccountForm} from './ChooseAccountForm'
1414+import {ForgotPasswordForm} from '#/view/com/auth/login/ForgotPasswordForm'
1515+import {SetNewPasswordForm} from '#/view/com/auth/login/SetNewPasswordForm'
1616+import {PasswordUpdatedForm} from '#/view/com/auth/login/PasswordUpdatedForm'
1717+import {LoginForm} from '#/view/com/auth/login/LoginForm'
1818+1919+enum Forms {
2020+ Login,
2121+ ChooseAccount,
2222+ ForgotPassword,
2323+ SetNewPassword,
2424+ PasswordUpdated,
2525+}
2626+2727+export const Login = ({onPressBack}: {onPressBack: () => void}) => {
2828+ const {_} = useLingui()
2929+3030+ const {accounts} = useSession()
3131+ const {track} = useAnalytics()
3232+ const {requestedAccountSwitchTo} = useLoggedOutView()
3333+ const requestedAccount = accounts.find(
3434+ acc => acc.did === requestedAccountSwitchTo,
3535+ )
3636+3737+ const [error, setError] = React.useState<string>('')
3838+ const [serviceUrl, setServiceUrl] = React.useState<string>(
3939+ requestedAccount?.service || DEFAULT_SERVICE,
4040+ )
4141+ const [initialHandle, setInitialHandle] = React.useState<string>(
4242+ requestedAccount?.handle || '',
4343+ )
4444+ const [currentForm, setCurrentForm] = React.useState<Forms>(
4545+ requestedAccount
4646+ ? Forms.Login
4747+ : accounts.length
4848+ ? Forms.ChooseAccount
4949+ : Forms.Login,
5050+ )
5151+5252+ const {
5353+ data: serviceDescription,
5454+ error: serviceError,
5555+ refetch: refetchService,
5656+ } = useServiceQuery(serviceUrl)
5757+5858+ const onSelectAccount = (account?: SessionAccount) => {
5959+ if (account?.service) {
6060+ setServiceUrl(account.service)
6161+ }
6262+ setInitialHandle(account?.handle || '')
6363+ setCurrentForm(Forms.Login)
6464+ }
6565+6666+ const gotoForm = (form: Forms) => () => {
6767+ setError('')
6868+ setCurrentForm(form)
6969+ }
7070+7171+ React.useEffect(() => {
7272+ if (serviceError) {
7373+ setError(
7474+ _(
7575+ msg`Unable to contact your service. Please check your Internet connection.`,
7676+ ),
7777+ )
7878+ logger.warn(`Failed to fetch service description for ${serviceUrl}`, {
7979+ error: String(serviceError),
8080+ })
8181+ } else {
8282+ setError('')
8383+ }
8484+ }, [serviceError, serviceUrl, _])
8585+8686+ const onPressRetryConnect = () => refetchService()
8787+ const onPressForgotPassword = () => {
8888+ track('Signin:PressedForgotPassword')
8989+ setCurrentForm(Forms.ForgotPassword)
9090+ }
9191+9292+ let content = null
9393+ let title = ''
9494+ let description = ''
9595+9696+ switch (currentForm) {
9797+ case Forms.Login:
9898+ title = _(msg`Sign in`)
9999+ description = _(msg`Enter your username and password`)
100100+ content = (
101101+ <LoginForm
102102+ error={error}
103103+ serviceUrl={serviceUrl}
104104+ serviceDescription={serviceDescription}
105105+ initialHandle={initialHandle}
106106+ setError={setError}
107107+ setServiceUrl={setServiceUrl}
108108+ onPressBack={onPressBack}
109109+ onPressForgotPassword={onPressForgotPassword}
110110+ onPressRetryConnect={onPressRetryConnect}
111111+ />
112112+ )
113113+ break
114114+ case Forms.ChooseAccount:
115115+ title = _(msg`Sign in`)
116116+ description = _(msg`Select from an existing account`)
117117+ content = (
118118+ <ChooseAccountForm
119119+ onSelectAccount={onSelectAccount}
120120+ onPressBack={onPressBack}
121121+ />
122122+ )
123123+ break
124124+ case Forms.ForgotPassword:
125125+ title = _(msg`Forgot Password`)
126126+ description = _(msg`Let's get your password reset!`)
127127+ content = (
128128+ <ForgotPasswordForm
129129+ error={error}
130130+ serviceUrl={serviceUrl}
131131+ serviceDescription={serviceDescription}
132132+ setError={setError}
133133+ setServiceUrl={setServiceUrl}
134134+ onPressBack={gotoForm(Forms.Login)}
135135+ onEmailSent={gotoForm(Forms.SetNewPassword)}
136136+ />
137137+ )
138138+ break
139139+ case Forms.SetNewPassword:
140140+ title = _(msg`Forgot Password`)
141141+ description = _(msg`Let's get your password reset!`)
142142+ content = (
143143+ <SetNewPasswordForm
144144+ error={error}
145145+ serviceUrl={serviceUrl}
146146+ setError={setError}
147147+ onPressBack={gotoForm(Forms.ForgotPassword)}
148148+ onPasswordSet={gotoForm(Forms.PasswordUpdated)}
149149+ />
150150+ )
151151+ break
152152+ case Forms.PasswordUpdated:
153153+ title = _(msg`Password updated`)
154154+ description = _(msg`You can now sign in with your new password.`)
155155+ content = <PasswordUpdatedForm onPressNext={gotoForm(Forms.Login)} />
156156+ break
157157+ }
158158+159159+ return (
160160+ <KeyboardAvoidingView testID="signIn" behavior="padding" style={a.flex_1}>
161161+ <LoggedOutLayout leadin="" title={title} description={description}>
162162+ {content}
163163+ </LoggedOutLayout>
164164+ </KeyboardAvoidingView>
165165+ )
166166+}
+8-8
src/view/com/auth/LoggedOut.tsx
···55import {Trans, msg} from '@lingui/macro'
66import {useNavigation} from '@react-navigation/native'
7788-import {isIOS, isNative} from 'platform/detection'
99-import {Login} from 'view/com/auth/login/Login'
1010-import {CreateAccount} from 'view/com/auth/create/CreateAccount'
1111-import {ErrorBoundary} from 'view/com/util/ErrorBoundary'
1212-import {s} from 'lib/styles'
1313-import {usePalette} from 'lib/hooks/usePalette'
1414-import {useAnalytics} from 'lib/analytics/analytics'
88+import {isIOS, isNative} from '#/platform/detection'
99+import {Login} from '#/screens/Login'
1010+import {CreateAccount} from '#/view/com/auth/create/CreateAccount'
1111+import {ErrorBoundary} from '#/view/com/util/ErrorBoundary'
1212+import {s} from '#/lib/styles'
1313+import {usePalette} from '#/lib/hooks/usePalette'
1414+import {useAnalytics} from '#/lib/analytics/analytics'
1515import {SplashScreen} from './SplashScreen'
1616import {useSetMinimalShellMode} from '#/state/shell/minimal-mode'
1717-import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
1717+import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
1818import {
1919 useLoggedOutView,
2020 useLoggedOutViewControls,