diff options
author | Eric Bailey <git@esb.lol> | 2024-03-20 17:25:08 -0500 |
---|---|---|
committer | Eric Bailey <git@esb.lol> | 2024-03-20 17:25:08 -0500 |
commit | 19fab671a3b11daa73a169b99752a4d2ba9e0166 (patch) | |
tree | f173c36f32482bf2a0fd9f91f429d3eb40e79059 /src/screens/Signup | |
parent | 58588efceadb030fa83367fb71dbecfce7b828d3 (diff) | |
download | voidsky-19fab671a3b11daa73a169b99752a4d2ba9e0166.tar.zst |
Move some things around
Diffstat (limited to 'src/screens/Signup')
-rw-r--r-- | src/screens/Signup/StepCaptcha/CaptchaWebView.tsx | 87 | ||||
-rw-r--r-- | src/screens/Signup/StepCaptcha/CaptchaWebView.web.tsx | 61 | ||||
-rw-r--r-- | src/screens/Signup/StepCaptcha/index.tsx (renamed from src/screens/Signup/StepCaptcha.tsx) | 2 | ||||
-rw-r--r-- | src/screens/Signup/StepInfo/Policies.tsx | 97 | ||||
-rw-r--r-- | src/screens/Signup/StepInfo/index.tsx (renamed from src/screens/Signup/StepInfo.tsx) | 2 |
5 files changed, 247 insertions, 2 deletions
diff --git a/src/screens/Signup/StepCaptcha/CaptchaWebView.tsx b/src/screens/Signup/StepCaptcha/CaptchaWebView.tsx new file mode 100644 index 000000000..50918c4ce --- /dev/null +++ b/src/screens/Signup/StepCaptcha/CaptchaWebView.tsx @@ -0,0 +1,87 @@ +import React from 'react' +import {StyleSheet} from 'react-native' +import {WebView, WebViewNavigation} from 'react-native-webview' +import {ShouldStartLoadRequest} from 'react-native-webview/lib/WebViewTypes' + +import {SignupState} from '#/screens/Signup/state' + +const ALLOWED_HOSTS = [ + 'bsky.social', + 'bsky.app', + 'staging.bsky.app', + 'staging.bsky.dev', + 'js.hcaptcha.com', + 'newassets.hcaptcha.com', + 'api2.hcaptcha.com', +] + +export function CaptchaWebView({ + url, + stateParam, + state, + onSuccess, + onError, +}: { + url: string + stateParam: string + state?: SignupState + onSuccess: (code: string) => void + onError: () => void +}) { + const redirectHost = React.useMemo(() => { + if (!state?.serviceUrl) return 'bsky.app' + + return state?.serviceUrl && + new URL(state?.serviceUrl).host === 'staging.bsky.dev' + ? 'staging.bsky.app' + : 'bsky.app' + }, [state?.serviceUrl]) + + const wasSuccessful = React.useRef(false) + + const onShouldStartLoadWithRequest = React.useCallback( + (event: ShouldStartLoadRequest) => { + const urlp = new URL(event.url) + return ALLOWED_HOSTS.includes(urlp.host) + }, + [], + ) + + const onNavigationStateChange = React.useCallback( + (e: WebViewNavigation) => { + if (wasSuccessful.current) return + + const urlp = new URL(e.url) + if (urlp.host !== redirectHost) return + + const code = urlp.searchParams.get('code') + if (urlp.searchParams.get('state') !== stateParam || !code) { + onError() + return + } + + wasSuccessful.current = true + onSuccess(code) + }, + [redirectHost, stateParam, onSuccess, onError], + ) + + return ( + <WebView + source={{uri: url}} + javaScriptEnabled + style={styles.webview} + onShouldStartLoadWithRequest={onShouldStartLoadWithRequest} + onNavigationStateChange={onNavigationStateChange} + scrollEnabled={false} + /> + ) +} + +const styles = StyleSheet.create({ + webview: { + flex: 1, + backgroundColor: 'transparent', + borderRadius: 10, + }, +}) diff --git a/src/screens/Signup/StepCaptcha/CaptchaWebView.web.tsx b/src/screens/Signup/StepCaptcha/CaptchaWebView.web.tsx new file mode 100644 index 000000000..7791a58dd --- /dev/null +++ b/src/screens/Signup/StepCaptcha/CaptchaWebView.web.tsx @@ -0,0 +1,61 @@ +import React from 'react' +import {StyleSheet} from 'react-native' + +// @ts-ignore web only, we will always redirect to the app on web (CORS) +const REDIRECT_HOST = new URL(window.location.href).host + +export function CaptchaWebView({ + url, + stateParam, + onSuccess, + onError, +}: { + url: string + stateParam: string + onSuccess: (code: string) => void + onError: () => void +}) { + const onLoad = React.useCallback(() => { + // @ts-ignore web + const frame: HTMLIFrameElement = document.getElementById( + 'captcha-iframe', + ) as HTMLIFrameElement + + try { + // @ts-ignore web + const href = frame?.contentWindow?.location.href + if (!href) return + const urlp = new URL(href) + + // This shouldn't happen with CORS protections, but for good measure + if (urlp.host !== REDIRECT_HOST) return + + const code = urlp.searchParams.get('code') + if (urlp.searchParams.get('state') !== stateParam || !code) { + onError() + return + } + onSuccess(code) + } catch (e) { + // We don't need to handle this + } + }, [stateParam, onSuccess, onError]) + + return ( + <iframe + src={url} + style={styles.iframe} + id="captcha-iframe" + onLoad={onLoad} + /> + ) +} + +const styles = StyleSheet.create({ + iframe: { + flex: 1, + borderWidth: 0, + borderRadius: 10, + backgroundColor: 'transparent', + }, +}) diff --git a/src/screens/Signup/StepCaptcha.tsx b/src/screens/Signup/StepCaptcha/index.tsx index 14da8ee93..311c697e7 100644 --- a/src/screens/Signup/StepCaptcha.tsx +++ b/src/screens/Signup/StepCaptcha/index.tsx @@ -6,9 +6,9 @@ import {nanoid} from 'nanoid/non-secure' import {createFullHandle} from '#/lib/strings/handles' import {isWeb} from '#/platform/detection' -import {CaptchaWebView} from '#/view/com/auth/create/CaptchaWebView' 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' diff --git a/src/screens/Signup/StepInfo/Policies.tsx b/src/screens/Signup/StepInfo/Policies.tsx new file mode 100644 index 000000000..8a656203f --- /dev/null +++ b/src/screens/Signup/StepInfo/Policies.tsx @@ -0,0 +1,97 @@ +import React from 'react' +import {View} from 'react-native' +import {ComAtprotoServerDescribeServer} from '@atproto/api' +import {msg, Trans} from '@lingui/macro' +import {useLingui} from '@lingui/react' + +import {atoms as a, useTheme} from '#/alf' +import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo' +import {InlineLink} from '#/components/Link' +import {Text} from '#/components/Typography' + +export const Policies = ({ + serviceDescription, + needsGuardian, + under13, +}: { + serviceDescription: ComAtprotoServerDescribeServer.OutputSchema + needsGuardian: boolean + under13: boolean +}) => { + const t = useTheme() + const {_} = useLingui() + + if (!serviceDescription) { + return <View /> + } + + const tos = validWebLink(serviceDescription.links?.termsOfService) + const pp = validWebLink(serviceDescription.links?.privacyPolicy) + + if (!tos && !pp) { + return ( + <View style={[a.flex_row, a.align_center, a.gap_xs]}> + <CircleInfo size="md" fill={t.atoms.text_contrast_low.color} /> + + <Text style={[t.atoms.text_contrast_medium]}> + <Trans> + This service has not provided terms of service or a privacy policy. + </Trans> + </Text> + </View> + ) + } + + const els = [] + if (tos) { + els.push( + <InlineLink key="tos" to={tos}> + {_(msg`Terms of Service`)} + </InlineLink>, + ) + } + if (pp) { + els.push( + <InlineLink key="pp" to={pp}> + {_(msg`Privacy Policy`)} + </InlineLink>, + ) + } + if (els.length === 2) { + els.splice( + 1, + 0, + <Text key="and" style={[t.atoms.text_contrast_medium]}> + {' '} + and{' '} + </Text>, + ) + } + + return ( + <View style={[a.gap_sm]}> + <Text style={[a.leading_snug, t.atoms.text_contrast_medium]}> + <Trans>By creating an account you agree to the {els}.</Trans> + </Text> + + {under13 ? ( + <Text style={[a.font_bold, a.leading_snug, t.atoms.text_contrast_high]}> + You must be 13 years of age or older to sign up. + </Text> + ) : needsGuardian ? ( + <Text style={[a.font_bold, a.leading_snug, t.atoms.text_contrast_high]}> + <Trans> + If you are not yet an adult according to the laws of your country, + your parent or legal guardian must read these Terms on your behalf. + </Trans> + </Text> + ) : undefined} + </View> + ) +} + +function validWebLink(url?: string): string | undefined { + return url && (url.startsWith('http://') || url.startsWith('https://')) + ? url + : undefined +} diff --git a/src/screens/Signup/StepInfo.tsx b/src/screens/Signup/StepInfo/index.tsx index 784d9e017..136592a0b 100644 --- a/src/screens/Signup/StepInfo.tsx +++ b/src/screens/Signup/StepInfo/index.tsx @@ -4,9 +4,9 @@ import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {logger} from '#/logger' -import {Policies} from 'view/com/auth/create/Policies' import {ScreenTransition} from '#/screens/Login/ScreenTransition' import {is13, is18, useSignupContext} from '#/screens/Signup/state' +import {Policies} from '#/screens/Signup/StepInfo/Policies' import {atoms as a} from '#/alf' import * as DateField from '#/components/forms/DateField' import {FormError} from '#/components/forms/FormError' |