From 9f5289a1017856c303d7fefe28327b30eac3a909 Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Wed, 13 Mar 2024 23:34:01 +0000 Subject: [PATCH] alf the login form --- src/components/forms/TextField.tsx | 8 +- src/components/icons/Lock.tsx | 5 + src/components/icons/Pencil.tsx | 5 + src/screens/Login/ChooseAccountForm.tsx | 95 ++++---- .../login => screens/Login}/LoginForm.tsx | 204 +++++++++--------- src/screens/Login/index.tsx | 4 +- src/view/com/auth/server-input/index.tsx | 2 +- 7 files changed, 169 insertions(+), 154 deletions(-) create mode 100644 src/components/icons/Lock.tsx create mode 100644 src/components/icons/Pencil.tsx rename src/{view/com/auth/login => screens/Login}/LoginForm.tsx (61%) diff --git a/src/components/forms/TextField.tsx b/src/components/forms/TextField.tsx index b37f4bfa..3cffe5b2 100644 --- a/src/components/forms/TextField.tsx +++ b/src/components/forms/TextField.tsx @@ -14,6 +14,7 @@ import {useTheme, atoms as a, web, android} from '#/alf' import {Text} from '#/components/Typography' import {useInteractionState} from '#/components/hooks/useInteractionState' import {Props as SVGIconProps} from '#/components/icons/common' +import {mergeRefs} from '#/lib/merge-refs' const Context = React.createContext<{ inputRef: React.RefObject | null @@ -128,6 +129,7 @@ export type InputProps = Omit & { value: string onChangeText: (value: string) => void isInvalid?: boolean + inputRef?: React.RefObject } export function createInput(Component: typeof TextInput) { @@ -137,6 +139,7 @@ export function createInput(Component: typeof TextInput) { value, onChangeText, isInvalid, + inputRef, ...rest }: InputProps) { const t = useTheme() @@ -161,19 +164,22 @@ export function createInput(Component: typeof TextInput) { ) } + const refs = mergeRefs([ctx.inputRef, inputRef!].filter(Boolean)) + return ( <> { screen('Choose Account') @@ -133,50 +134,54 @@ export const ChooseAccountForm = ({ return ( - - Sign in as... - - - {accounts.map(account => ( - - ))} - onSelectAccount(undefined)} - accessibilityRole="button" - accessibilityLabel={_(msg`Login to account that is not listed`)} - accessibilityHint=""> - - - Other account - - - - - - - - + + + Sign in as... + + + {accounts.map(account => ( + + ))} + onSelectAccount(undefined)} + accessibilityRole="button" + accessibilityLabel={_(msg`Login to account that is not listed`)} + accessibilityHint=""> + + + Other account + + + + + + + + + ) diff --git a/src/view/com/auth/login/LoginForm.tsx b/src/screens/Login/LoginForm.tsx similarity index 61% rename from src/view/com/auth/login/LoginForm.tsx rename to src/screens/Login/LoginForm.tsx index fdba9f20..8ac4fa35 100644 --- a/src/view/com/auth/login/LoginForm.tsx +++ b/src/screens/Login/LoginForm.tsx @@ -6,28 +6,31 @@ import { TouchableOpacity, View, } from 'react-native' -import { - FontAwesomeIcon, - FontAwesomeIconStyle, -} from '@fortawesome/react-native-fontawesome' import {ComAtprotoServerDescribeServer} from '@atproto/api' +import {Trans, msg} from '@lingui/macro' + import {useAnalytics} from 'lib/analytics/analytics' -import {Text} from '../../util/text/Text' import {s} from 'lib/styles' import {createFullHandle} from 'lib/strings/handles' import {toNiceDomain} from 'lib/strings/url-helpers' import {isNetworkError} from 'lib/strings/errors' -import {usePalette} from 'lib/hooks/usePalette' -import {useTheme} from 'lib/ThemeContext' import {useSessionApi} from '#/state/session' import {cleanError} from 'lib/strings/errors' import {logger} from '#/logger' -import {Trans, msg} from '@lingui/macro' -import {styles} from './styles' +import {styles} from '../../view/com/auth/login/styles' import {useLingui} from '@lingui/react' import {useDialogControl} from '#/components/Dialog' - -import {ServerInputDialog} from '../server-input' +import {ServerInputDialog} from '../../view/com/auth/server-input' +import {Button} from '#/components/Button' +import {isAndroid} from '#/platform/detection' +import {atoms as a, useBreakpoints, useTheme} from '#/alf' +import {Text} from '#/components/Typography' +import * as TextField from '#/components/forms/TextField' +import {At_Stroke2_Corner0_Rounded as At} from '#/components/icons/At' +import {Lock_Stroke2_Corner0_Rounded as Lock} from '#/components/icons/Lock' +import {Globe_Stroke2_Corner0_Rounded as Globe} from '#/components/icons/Globe' +import {Pencil_Stroke2_Corner0_Rounded as Pencil} from '#/components/icons/Pencil' +import {Warning_Stroke2_Corner0_Rounded as Warning} from '#/components/icons/Warning' type ServiceDescription = ComAtprotoServerDescribeServer.OutputSchema @@ -40,7 +43,6 @@ export const LoginForm = ({ setServiceUrl, onPressRetryConnect, onPressBack, - onPressForgotPassword, }: { error: string serviceUrl: string @@ -53,8 +55,7 @@ export const LoginForm = ({ onPressForgotPassword: () => void }) => { const {track} = useAnalytics() - const pal = usePalette('default') - const theme = useTheme() + const t = useTheme() const [isProcessing, setIsProcessing] = useState(false) const [identifier, setIdentifier] = useState(initialHandle) const [password, setPassword] = useState('') @@ -62,6 +63,7 @@ export const LoginForm = ({ const {_} = useLingui() const {login} = useSessionApi() const serverInputControl = useDialogControl() + const {gtMobile} = useBreakpoints() const onPressSelectService = () => { serverInputControl.open() @@ -127,55 +129,54 @@ export const LoginForm = ({ const isReady = !!serviceDescription && !!identifier && !!password return ( - + - - Sign into - - - - - - - {toNiceDomain(serviceUrl)} - - - - - - + + + Hosting provider + + + + {toNiceDomain(serviceUrl)} + + + + - - Account - - - - - + + Account + + + + setIdentifier((str || '').toLowerCase().trim()) } editable={!isProcessing} - accessibilityLabel={_(msg`Username or email address`)} accessibilityHint={_( msg`Input the username or email address you used at signup`, )} /> - - - - + + + + + - Forgot - - + */} + {error ? ( - - - - - + + + {error} ) : undefined} - - - - Back - - + + {!serviceDescription && error ? ( - - - Retry - - + label={_(msg`Retry`)} + accessibilityHint={_(msg`Retries login`)} + variant="solid" + color="secondary" + size="small" + onPress={onPressRetryConnect}> + {_(msg`Retry`)} + ) : !serviceDescription ? ( <> - + Connecting... ) : isProcessing ? ( ) : isReady ? ( - - - Next - - + ) : undefined} diff --git a/src/screens/Login/index.tsx b/src/screens/Login/index.tsx index f2cfde55..3bd2df60 100644 --- a/src/screens/Login/index.tsx +++ b/src/screens/Login/index.tsx @@ -1,4 +1,5 @@ import React from 'react' +import {KeyboardAvoidingView} from 'react-native' import {useAnalytics} from '#/lib/analytics/analytics' import {useLingui} from '@lingui/react' import {LoggedOutLayout} from '#/view/com/util/layouts/LoggedOutLayout' @@ -9,12 +10,11 @@ import {useServiceQuery} from '#/state/queries/service' import {msg} from '@lingui/macro' import {logger} from '#/logger' import {atoms as a} from '#/alf' -import {KeyboardAvoidingView} from 'react-native' import {ChooseAccountForm} from './ChooseAccountForm' import {ForgotPasswordForm} from '#/view/com/auth/login/ForgotPasswordForm' import {SetNewPasswordForm} from '#/view/com/auth/login/SetNewPasswordForm' import {PasswordUpdatedForm} from '#/view/com/auth/login/PasswordUpdatedForm' -import {LoginForm} from '#/view/com/auth/login/LoginForm' +import {LoginForm} from '#/screens/Login/LoginForm' enum Forms { Login, diff --git a/src/view/com/auth/server-input/index.tsx b/src/view/com/auth/server-input/index.tsx index 32b5a314..81f4bdf9 100644 --- a/src/view/com/auth/server-input/index.tsx +++ b/src/view/com/auth/server-input/index.tsx @@ -67,7 +67,7 @@ export function ServerInputDialog({ return (