From 38a9da26bfceb520c7672733fbb406c76876c85b Mon Sep 17 00:00:00 2001 From: Stephen Zhou <38493346+hyoban@users.noreply.github.com> Date: Mon, 17 Mar 2025 09:37:25 +0800 Subject: [PATCH] fix(mobile): show validate message, support for small screen (#3130) * show validate message * support small screen --- .../src/components/common/SubmitButton.tsx | 7 +- apps/mobile/src/modules/login/email.tsx | 85 +++++++------------ apps/mobile/src/modules/login/index.tsx | 63 +++++++++----- .../src/screens/(modal)/forget-password.tsx | 2 +- apps/mobile/src/screens/(modal)/sign-up.tsx | 22 ++++- 5 files changed, 97 insertions(+), 82 deletions(-) diff --git a/apps/mobile/src/components/common/SubmitButton.tsx b/apps/mobile/src/components/common/SubmitButton.tsx index 96837c819..4340b3cae 100644 --- a/apps/mobile/src/components/common/SubmitButton.tsx +++ b/apps/mobile/src/components/common/SubmitButton.tsx @@ -20,14 +20,15 @@ export function SubmitButton({ title, ...props }: PressableProps & { isLoading?: boolean; title: string }) { + const disabled = props.disabled || isLoading const disableColor = useColor("gray6") const disabledTextColor = useColor("gray2") const disabledValue = useSharedValue(1) useEffect(() => { cancelAnimation(disabledValue) - disabledValue.value = withTiming(props.disabled ? 1 : 0) - }, [props.disabled]) + disabledValue.value = withTiming(disabled ? 1 : 0) + }, [disabled]) const buttonStyle = useAnimatedStyle(() => ({ backgroundColor: interpolateColor(disabledValue.value, [1, 0], [disableColor, accentColor]), @@ -40,7 +41,7 @@ export function SubmitButton({ return ( diff --git a/apps/mobile/src/modules/login/email.tsx b/apps/mobile/src/modules/login/email.tsx index 823eff1d2..7994baa69 100644 --- a/apps/mobile/src/modules/login/email.tsx +++ b/apps/mobile/src/modules/login/email.tsx @@ -1,17 +1,13 @@ -import { zodResolver } from "@hookform/resolvers/zod" import { useMutation } from "@tanstack/react-query" import { router } from "expo-router" -import type { Control } from "react-hook-form" -import { useController, useForm } from "react-hook-form" -import type { TextInputProps } from "react-native" -import { Text, TouchableOpacity, View } from "react-native" +import { useCallback, useRef } from "react" +import { Alert, Text, TouchableOpacity, View } from "react-native" import { KeyboardController } from "react-native-keyboard-controller" import { z } from "zod" import { SubmitButton } from "@/src/components/common/SubmitButton" import { PlainTextField } from "@/src/components/ui/form/TextField" import { signIn } from "@/src/lib/auth" -import { toast } from "@/src/lib/toast" import { getTokenHeaders } from "@/src/lib/token" import { accentColor } from "@/src/theme/colors" @@ -23,11 +19,18 @@ const formSchema = z.object({ type FormValue = z.infer async function onSubmit(values: FormValue) { + const result = formSchema.safeParse(values) + if (!result.success) { + const issue = result.error.issues[0] + Alert.alert("Invalid email or password", issue?.message) + return + } + await signIn .email( { - email: values.email, - password: values.password, + email: result.data.email, + password: result.data.password, }, { headers: await getTokenHeaders(), @@ -43,62 +46,39 @@ async function onSubmit(values: FormValue) { } }) .catch((error) => { - toast.error(error.message) + Alert.alert(error.message) }) } -function Input({ - control, - name, - ...rest -}: TextInputProps & { - control: Control - name: keyof FormValue -}) { - const { field } = useController({ - control, - name, - }) - return ( - - ) -} - export function EmailLogin() { - const { control, handleSubmit, formState } = useForm({ - resolver: zodResolver(formSchema), - defaultValues: { - email: "", - password: "", - }, - }) + const emailValueRef = useRef("") + const passwordValueRef = useRef("") const submitMutation = useMutation({ mutationFn: onSubmit, }) - const login = handleSubmit((values) => { - submitMutation.mutate(values) - }) + const onLogin = useCallback(() => { + submitMutation.mutate({ + email: emailValueRef.current, + password: passwordValueRef.current, + }) + }, [submitMutation]) return ( - { + emailValueRef.current = text + }} + selectionColor={accentColor} hitSlop={20} autoCapitalize="none" autoCorrect={false} keyboardType="email-address" autoComplete="email" - control={control} - name="email" placeholder="Email" className="text-text flex-1" returnKeyType="next" @@ -109,28 +89,27 @@ export function EmailLogin() { - { + passwordValueRef.current = text + }} + selectionColor={accentColor} hitSlop={20} autoCapitalize="none" autoCorrect={false} autoComplete="current-password" - control={control} - name="password" placeholder="Password" className="text-text flex-1" secureTextEntry returnKeyType="go" - onSubmitEditing={() => { - login() - }} + onSubmitEditing={onLogin} /> diff --git a/apps/mobile/src/modules/login/index.tsx b/apps/mobile/src/modules/login/index.tsx index 60cc7bd91..64a10f54a 100644 --- a/apps/mobile/src/modules/login/index.tsx +++ b/apps/mobile/src/modules/login/index.tsx @@ -6,36 +6,55 @@ import Animated, { useAnimatedStyle, useSharedValue } from "react-native-reanima import * as ContextMenu from "zeego/context-menu" import { Logo } from "@/src/components/ui/logo" +import { useScaleHeight } from "@/src/lib/responsive" import { TermsMarkdown } from "@/src/screens/(headless)/terms" import { EmailLogin } from "./email" import { SocialLogin } from "./social" export function Login() { + const logoSize = useScaleHeight()(80) + const gapSize = useScaleHeight()(28) + const fontSize = useScaleHeight()(28) + const lineHeight = useScaleHeight()(32) + return ( - - { - KeyboardController.dismiss() - }} - accessible={false} - > - - - - Sign in to Follow - - + + + { + KeyboardController.dismiss() + }} + accessible={false} + > + + + + Sign in to Follow + + + + + + + + + or + + + - - - - - - or - - - diff --git a/apps/mobile/src/screens/(modal)/forget-password.tsx b/apps/mobile/src/screens/(modal)/forget-password.tsx index c0b61426b..75b080685 100644 --- a/apps/mobile/src/screens/(modal)/forget-password.tsx +++ b/apps/mobile/src/screens/(modal)/forget-password.tsx @@ -46,7 +46,7 @@ export default function ForgetPassword() { - Forgot password? + Forgot password? Enter your email address that you use with your account to continue. diff --git a/apps/mobile/src/screens/(modal)/sign-up.tsx b/apps/mobile/src/screens/(modal)/sign-up.tsx index 3fc183b1c..de49768d1 100644 --- a/apps/mobile/src/screens/(modal)/sign-up.tsx +++ b/apps/mobile/src/screens/(modal)/sign-up.tsx @@ -12,6 +12,7 @@ import { SubmitButton } from "@/src/components/common/SubmitButton" import { PlainTextField } from "@/src/components/ui/form/TextField" import { Logo } from "@/src/components/ui/logo" import { signUp } from "@/src/lib/auth" +import { useScaleHeight } from "@/src/lib/responsive" import { toast } from "@/src/lib/toast" import { getTokenHeaders } from "@/src/lib/token" import { accentColor } from "@/src/theme/colors" @@ -157,6 +158,10 @@ function EmailSignUp() { } export default function SignUpModal() { + const logoSize = useScaleHeight()(80) + const gapSize = useScaleHeight()(28) + const fontSize = useScaleHeight()(28) + const lineHeight = useScaleHeight()(32) return ( - - - + + + Sign up to Follow