about summary refs log tree commit diff
path: root/src/screens/Signup
diff options
context:
space:
mode:
authordan <dan.abramov@gmail.com>2024-08-22 22:43:23 +0100
committerGitHub <noreply@github.com>2024-08-22 22:43:23 +0100
commit27bb3832683275be0c778a38c526bfd55cebee59 (patch)
tree02b0e1a9c802b0f75ac33d3e00daa95203e322cc /src/screens/Signup
parentdf5bf28e614150bda5d58b22b7db308f71f70e07 (diff)
downloadvoidsky-27bb3832683275be0c778a38c526bfd55cebee59.tar.zst
Submit fix (#4978)
* Fix submit logic

* Fix type

* Align submit task creation 1:1 with callsites

* blegh. `useThrottledValue`

* make `useThrottledValue`'s time required

---------

Co-authored-by: Hailey <me@haileyok.com>
Diffstat (limited to 'src/screens/Signup')
-rw-r--r--src/screens/Signup/StepCaptcha/index.tsx11
-rw-r--r--src/screens/Signup/StepHandle.tsx11
-rw-r--r--src/screens/Signup/index.tsx11
-rw-r--r--src/screens/Signup/state.ts43
4 files changed, 45 insertions, 31 deletions
diff --git a/src/screens/Signup/StepCaptcha/index.tsx b/src/screens/Signup/StepCaptcha/index.tsx
index bf3576490..e233d31dd 100644
--- a/src/screens/Signup/StepCaptcha/index.tsx
+++ b/src/screens/Signup/StepCaptcha/index.tsx
@@ -8,7 +8,7 @@ import {createFullHandle} from '#/lib/strings/handles'
 import {logger} from '#/logger'
 import {logEvent} from 'lib/statsig/statsig'
 import {ScreenTransition} from '#/screens/Login/ScreenTransition'
-import {useSignupContext, useSubmitSignup} from '#/screens/Signup/state'
+import {useSignupContext} from '#/screens/Signup/state'
 import {CaptchaWebView} from '#/screens/Signup/StepCaptcha/CaptchaWebView'
 import {atoms as a, useTheme} from '#/alf'
 import {FormError} from '#/components/forms/FormError'
@@ -20,7 +20,6 @@ export function StepCaptcha() {
   const {_} = useLingui()
   const theme = useTheme()
   const {state, dispatch} = useSignupContext()
-  const submit = useSubmitSignup({state, dispatch})
 
   const [completed, setCompleted] = React.useState(false)
 
@@ -42,9 +41,13 @@ export function StepCaptcha() {
     (code: string) => {
       setCompleted(true)
       logEvent('signup:captchaSuccess', {})
-      submit(code)
+      const submitTask = {code, mutableProcessed: false}
+      dispatch({
+        type: 'submit',
+        task: submitTask,
+      })
     },
-    [submit],
+    [dispatch],
   )
 
   const onError = React.useCallback(
diff --git a/src/screens/Signup/StepHandle.tsx b/src/screens/Signup/StepHandle.tsx
index b443e822a..4e63efd2e 100644
--- a/src/screens/Signup/StepHandle.tsx
+++ b/src/screens/Signup/StepHandle.tsx
@@ -7,9 +7,10 @@ import {logEvent} from '#/lib/statsig/statsig'
 import {createFullHandle, validateHandle} from '#/lib/strings/handles'
 import {useAgent} from '#/state/session'
 import {ScreenTransition} from '#/screens/Login/ScreenTransition'
-import {useSignupContext, useSubmitSignup} from '#/screens/Signup/state'
+import {useSignupContext} from '#/screens/Signup/state'
 import {atoms as a, useTheme} from '#/alf'
 import * as TextField from '#/components/forms/TextField'
+import {useThrottledValue} from '#/components/hooks/useThrottledValue'
 import {At_Stroke2_Corner0_Rounded as At} from '#/components/icons/At'
 import {Check_Stroke2_Corner0_Rounded as Check} from '#/components/icons/Check'
 import {TimesLarge_Stroke2_Corner0_Rounded as Times} from '#/components/icons/Times'
@@ -20,10 +21,10 @@ export function StepHandle() {
   const {_} = useLingui()
   const t = useTheme()
   const {state, dispatch} = useSignupContext()
-  const submit = useSubmitSignup({state, dispatch})
   const agent = useAgent()
   const handleValueRef = useRef<string>(state.handle)
   const [draftValue, setDraftValue] = React.useState(state.handle)
+  const isLoading = useThrottledValue(state.isLoading, 500)
 
   const onNextPress = React.useCallback(async () => {
     const handle = handleValueRef.current.trim()
@@ -64,7 +65,8 @@ export function StepHandle() {
     })
     // phoneVerificationRequired is actually whether a captcha is required
     if (!state.serviceDescription?.phoneVerificationRequired) {
-      submit()
+      const submitTask = {code: undefined, mutableProcessed: false}
+      dispatch({type: 'submit', task: submitTask})
       return
     }
     dispatch({type: 'next'})
@@ -74,7 +76,6 @@ export function StepHandle() {
     state.activeStep,
     state.serviceDescription?.phoneVerificationRequired,
     state.userDomain,
-    submit,
     agent,
   ])
 
@@ -175,7 +176,7 @@ export function StepHandle() {
         )}
       </View>
       <BackNextButtons
-        isLoading={state.isLoading}
+        isLoading={isLoading}
         isNextDisabled={!validCheck.overall}
         onBackPress={onBackPress}
         onNextPress={onNextPress}
diff --git a/src/screens/Signup/index.tsx b/src/screens/Signup/index.tsx
index 189760460..0e1a2e61f 100644
--- a/src/screens/Signup/index.tsx
+++ b/src/screens/Signup/index.tsx
@@ -16,6 +16,7 @@ import {
   reducer,
   SignupContext,
   SignupStep,
+  useSubmitSignup,
 } from '#/screens/Signup/state'
 import {StepCaptcha} from '#/screens/Signup/StepCaptcha'
 import {StepHandle} from '#/screens/Signup/StepHandle'
@@ -33,6 +34,7 @@ export function Signup({onPressBack}: {onPressBack: () => void}) {
   const {screen} = useAnalytics()
   const [state, dispatch] = React.useReducer(reducer, initialState)
   const {gtMobile} = useBreakpoints()
+  const submit = useSubmitSignup()
 
   const activeStarterPack = useActiveStarterPack()
   const {
@@ -81,6 +83,15 @@ export function Signup({onPressBack}: {onPressBack: () => void}) {
     }
   }, [_, serviceInfo, isError])
 
+  React.useEffect(() => {
+    if (state.pendingSubmit) {
+      if (!state.pendingSubmit.mutableProcessed) {
+        state.pendingSubmit.mutableProcessed = true
+        submit(state, dispatch)
+      }
+    }
+  }, [state, dispatch, submit])
+
   return (
     <SignupContext.Provider value={{state, dispatch}}>
       <LoggedOutLayout
diff --git a/src/screens/Signup/state.ts b/src/screens/Signup/state.ts
index 826cbf1d3..0ee266564 100644
--- a/src/screens/Signup/state.ts
+++ b/src/screens/Signup/state.ts
@@ -26,6 +26,11 @@ export enum SignupStep {
   CAPTCHA,
 }
 
+type SubmitTask = {
+  code: string | undefined
+  mutableProcessed: boolean // OK to mutate assuming it's never read in render.
+}
+
 export type SignupState = {
   hasPrev: boolean
   activeStep: SignupStep
@@ -41,6 +46,8 @@ export type SignupState = {
 
   error: string
   isLoading: boolean
+
+  pendingSubmit: null | SubmitTask
 }
 
 export type SignupAction =
@@ -58,6 +65,7 @@ export type SignupAction =
   | {type: 'setVerificationCode'; value: string}
   | {type: 'setError'; value: string}
   | {type: 'setIsLoading'; value: boolean}
+  | {type: 'submit'; task: SubmitTask}
 
 export const initialState: SignupState = {
   hasPrev: false,
@@ -74,6 +82,8 @@ export const initialState: SignupState = {
 
   error: '',
   isLoading: false,
+
+  pendingSubmit: null,
 }
 
 export function is13(date: Date) {
@@ -149,6 +159,10 @@ export function reducer(s: SignupState, a: SignupAction): SignupState {
       next.error = a.value
       break
     }
+    case 'submit': {
+      next.pendingSubmit = a.task
+      break
+    }
   }
 
   next.hasPrev = next.activeStep !== SignupStep.INFO
@@ -169,19 +183,17 @@ interface IContext {
 export const SignupContext = React.createContext<IContext>({} as IContext)
 export const useSignupContext = () => React.useContext(SignupContext)
 
-export function useSubmitSignup({
-  state,
-  dispatch,
-}: {
-  state: SignupState
-  dispatch: (action: SignupAction) => void
-}) {
+export function useSubmitSignup() {
   const {_} = useLingui()
   const {createAccount} = useSessionApi()
   const onboardingDispatch = useOnboardingDispatch()
 
   return useCallback(
-    async (verificationCode?: string) => {
+    async (
+      state: SignupState,
+      dispatch: (action: SignupAction) => void,
+      verificationCode?: string,
+    ) => {
       if (!state.email) {
         dispatch({type: 'setStep', value: SignupStep.INFO})
         return dispatch({
@@ -270,19 +282,6 @@ export function useSubmitSignup({
         dispatch({type: 'setIsLoading', value: false})
       }
     },
-    [
-      state.email,
-      state.password,
-      state.handle,
-      state.serviceDescription?.phoneVerificationRequired,
-      state.serviceUrl,
-      state.userDomain,
-      state.inviteCode,
-      state.dateOfBirth,
-      dispatch,
-      _,
-      onboardingDispatch,
-      createAccount,
-    ],
+    [_, onboardingDispatch, createAccount],
   )
 }