about summary refs log tree commit diff
path: root/src/screens/Signup/StepCaptcha/index.tsx
diff options
context:
space:
mode:
authorEric Bailey <git@esb.lol>2024-03-20 17:25:08 -0500
committerEric Bailey <git@esb.lol>2024-03-20 17:25:08 -0500
commit19fab671a3b11daa73a169b99752a4d2ba9e0166 (patch)
treef173c36f32482bf2a0fd9f91f429d3eb40e79059 /src/screens/Signup/StepCaptcha/index.tsx
parent58588efceadb030fa83367fb71dbecfce7b828d3 (diff)
downloadvoidsky-19fab671a3b11daa73a169b99752a4d2ba9e0166.tar.zst
Move some things around
Diffstat (limited to 'src/screens/Signup/StepCaptcha/index.tsx')
-rw-r--r--src/screens/Signup/StepCaptcha/index.tsx95
1 files changed, 95 insertions, 0 deletions
diff --git a/src/screens/Signup/StepCaptcha/index.tsx b/src/screens/Signup/StepCaptcha/index.tsx
new file mode 100644
index 000000000..311c697e7
--- /dev/null
+++ b/src/screens/Signup/StepCaptcha/index.tsx
@@ -0,0 +1,95 @@
+import React from 'react'
+import {ActivityIndicator, StyleSheet, View} from 'react-native'
+import {msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+import {nanoid} from 'nanoid/non-secure'
+
+import {createFullHandle} from '#/lib/strings/handles'
+import {isWeb} from '#/platform/detection'
+import {ScreenTransition} from '#/screens/Login/ScreenTransition'
+import {useSignupContext, useSubmitSignup} from '#/screens/Signup/state'
+import {CaptchaWebView} from '#/screens/Signup/StepCaptcha/CaptchaWebView'
+import {atoms as a, useTheme} from '#/alf'
+import {FormError} from '#/components/forms/FormError'
+
+const CAPTCHA_PATH = '/gate/signup'
+
+export function StepCaptcha() {
+  const {_} = useLingui()
+  const theme = useTheme()
+  const {state, dispatch} = useSignupContext()
+  const submit = useSubmitSignup({state, dispatch})
+
+  const [completed, setCompleted] = React.useState(false)
+
+  const stateParam = React.useMemo(() => nanoid(15), [])
+  const url = React.useMemo(() => {
+    const newUrl = new URL(state.serviceUrl)
+    newUrl.pathname = CAPTCHA_PATH
+    newUrl.searchParams.set(
+      'handle',
+      createFullHandle(state.handle, state.userDomain),
+    )
+    newUrl.searchParams.set('state', stateParam)
+    newUrl.searchParams.set('colorScheme', theme.name)
+
+    return newUrl.href
+  }, [state.serviceUrl, state.handle, state.userDomain, stateParam, theme.name])
+
+  const onSuccess = React.useCallback(
+    (code: string) => {
+      setCompleted(true)
+      submit(code)
+    },
+    [submit],
+  )
+
+  const onError = React.useCallback(() => {
+    dispatch({
+      type: 'setError',
+      value: _(msg`Error receiving captcha response.`),
+    })
+  }, [_, dispatch])
+
+  return (
+    <ScreenTransition>
+      <View style={[a.gap_lg]}>
+        <View style={[styles.container, completed && styles.center]}>
+          {!completed ? (
+            <CaptchaWebView
+              url={url}
+              stateParam={stateParam}
+              state={state}
+              onSuccess={onSuccess}
+              onError={onError}
+            />
+          ) : (
+            <ActivityIndicator size="large" />
+          )}
+        </View>
+        <FormError error={state.error} />
+      </View>
+    </ScreenTransition>
+  )
+}
+
+const styles = StyleSheet.create({
+  error: {
+    borderRadius: 6,
+    marginTop: 10,
+  },
+  // @ts-expect-error: Suppressing error due to incomplete `ViewStyle` type definition in react-native-web, missing `cursor` prop as discussed in https://github.com/necolas/react-native-web/issues/832.
+  touchable: {
+    ...(isWeb && {cursor: 'pointer'}),
+  },
+  container: {
+    minHeight: 500,
+    width: '100%',
+    paddingBottom: 20,
+    overflow: 'hidden',
+  },
+  center: {
+    alignItems: 'center',
+    justifyContent: 'center',
+  },
+})