Merge pull request #3337 from bluesky-social/samuel/scrollable-loggedoutlayout
Move scrollview to `LoggedOutLayout` to fix scrolling on webzio/stable
commit
b27a0b8c97
|
@ -1,13 +1,6 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {
|
import {type StyleProp, View, type ViewStyle} from 'react-native'
|
||||||
ScrollView,
|
|
||||||
type StyleProp,
|
|
||||||
StyleSheet,
|
|
||||||
View,
|
|
||||||
type ViewStyle,
|
|
||||||
} from 'react-native'
|
|
||||||
|
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
|
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
|
||||||
|
@ -16,38 +9,24 @@ export function FormContainer({
|
||||||
title,
|
title,
|
||||||
children,
|
children,
|
||||||
style,
|
style,
|
||||||
contentContainerStyle,
|
|
||||||
}: {
|
}: {
|
||||||
testID?: string
|
testID?: string
|
||||||
title?: React.ReactNode
|
title?: React.ReactNode
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
style?: StyleProp<ViewStyle>
|
style?: StyleProp<ViewStyle>
|
||||||
contentContainerStyle?: StyleProp<ViewStyle>
|
|
||||||
}) {
|
}) {
|
||||||
const {gtMobile} = useBreakpoints()
|
const {gtMobile} = useBreakpoints()
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
return (
|
return (
|
||||||
<ScrollView
|
<View
|
||||||
testID={testID}
|
testID={testID}
|
||||||
style={[styles.maxHeight, contentContainerStyle]}
|
style={[a.gap_md, a.flex_1, !gtMobile && [a.px_lg, a.py_md], style]}>
|
||||||
keyboardShouldPersistTaps="handled">
|
{title && !gtMobile && (
|
||||||
<View
|
<Text style={[a.text_xl, a.font_bold, t.atoms.text_contrast_high]}>
|
||||||
style={[a.gap_md, a.flex_1, !gtMobile && [a.px_lg, a.pt_md], style]}>
|
{title}
|
||||||
{title && !gtMobile && (
|
</Text>
|
||||||
<Text style={[a.text_xl, a.font_bold, t.atoms.text_contrast_high]}>
|
)}
|
||||||
{title}
|
{children}
|
||||||
</Text>
|
</View>
|
||||||
)}
|
|
||||||
{children}
|
|
||||||
</View>
|
|
||||||
</ScrollView>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
maxHeight: {
|
|
||||||
// @ts-ignore web only -prf
|
|
||||||
maxHeight: isWeb ? '100vh' : undefined,
|
|
||||||
height: !isWeb ? '100%' : undefined,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
|
@ -164,7 +164,11 @@ export const Login = ({onPressBack}: {onPressBack: () => void}) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<KeyboardAvoidingView testID="signIn" behavior="padding" style={a.flex_1}>
|
<KeyboardAvoidingView testID="signIn" behavior="padding" style={a.flex_1}>
|
||||||
<LoggedOutLayout leadin="" title={title} description={description}>
|
<LoggedOutLayout
|
||||||
|
leadin=""
|
||||||
|
title={title}
|
||||||
|
description={description}
|
||||||
|
scrollable>
|
||||||
<LayoutAnimationConfig skipEntering skipExiting>
|
<LayoutAnimationConfig skipEntering skipExiting>
|
||||||
<ScreenTransition key={currentForm}>{content}</ScreenTransition>
|
<ScreenTransition key={currentForm}>{content}</ScreenTransition>
|
||||||
</LayoutAnimationConfig>
|
</LayoutAnimationConfig>
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {ActivityIndicator, StyleSheet, View} from 'react-native'
|
import {ActivityIndicator, View} from 'react-native'
|
||||||
import {msg} from '@lingui/macro'
|
import {msg} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import {nanoid} from 'nanoid/non-secure'
|
import {nanoid} from 'nanoid/non-secure'
|
||||||
|
|
||||||
import {createFullHandle} from '#/lib/strings/handles'
|
import {createFullHandle} from '#/lib/strings/handles'
|
||||||
import {isWeb} from '#/platform/detection'
|
|
||||||
import {ScreenTransition} from '#/screens/Login/ScreenTransition'
|
import {ScreenTransition} from '#/screens/Login/ScreenTransition'
|
||||||
import {useSignupContext, useSubmitSignup} from '#/screens/Signup/state'
|
import {useSignupContext, useSubmitSignup} from '#/screens/Signup/state'
|
||||||
import {CaptchaWebView} from '#/screens/Signup/StepCaptcha/CaptchaWebView'
|
import {CaptchaWebView} from '#/screens/Signup/StepCaptcha/CaptchaWebView'
|
||||||
|
@ -54,7 +53,14 @@ export function StepCaptcha() {
|
||||||
return (
|
return (
|
||||||
<ScreenTransition>
|
<ScreenTransition>
|
||||||
<View style={[a.gap_lg]}>
|
<View style={[a.gap_lg]}>
|
||||||
<View style={[styles.container, completed && styles.center]}>
|
<View
|
||||||
|
style={[
|
||||||
|
a.w_full,
|
||||||
|
a.pb_xl,
|
||||||
|
a.overflow_hidden,
|
||||||
|
{minHeight: 500},
|
||||||
|
completed && [a.align_center, a.justify_center],
|
||||||
|
]}>
|
||||||
{!completed ? (
|
{!completed ? (
|
||||||
<CaptchaWebView
|
<CaptchaWebView
|
||||||
url={url}
|
url={url}
|
||||||
|
@ -72,24 +78,3 @@ export function StepCaptcha() {
|
||||||
</ScreenTransition>
|
</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',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {ScrollView, View} from 'react-native'
|
import {View} from 'react-native'
|
||||||
|
import {LayoutAnimationConfig} from 'react-native-reanimated'
|
||||||
import {msg, Trans} from '@lingui/macro'
|
import {msg, Trans} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
|
@ -20,7 +21,7 @@ import {
|
||||||
import {StepCaptcha} from '#/screens/Signup/StepCaptcha'
|
import {StepCaptcha} from '#/screens/Signup/StepCaptcha'
|
||||||
import {StepHandle} from '#/screens/Signup/StepHandle'
|
import {StepHandle} from '#/screens/Signup/StepHandle'
|
||||||
import {StepInfo} from '#/screens/Signup/StepInfo'
|
import {StepInfo} from '#/screens/Signup/StepInfo'
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
|
||||||
import {Button, ButtonText} from '#/components/Button'
|
import {Button, ButtonText} from '#/components/Button'
|
||||||
import {Divider} from '#/components/Divider'
|
import {Divider} from '#/components/Divider'
|
||||||
import {InlineLink} from '#/components/Link'
|
import {InlineLink} from '#/components/Link'
|
||||||
|
@ -32,6 +33,7 @@ export function Signup({onPressBack}: {onPressBack: () => void}) {
|
||||||
const {screen} = useAnalytics()
|
const {screen} = useAnalytics()
|
||||||
const [state, dispatch] = React.useReducer(reducer, initialState)
|
const [state, dispatch] = React.useReducer(reducer, initialState)
|
||||||
const submit = useSubmitSignup({state, dispatch})
|
const submit = useSubmitSignup({state, dispatch})
|
||||||
|
const {gtMobile} = useBreakpoints()
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: serviceInfo,
|
data: serviceInfo,
|
||||||
|
@ -125,13 +127,16 @@ export function Signup({onPressBack}: {onPressBack: () => void}) {
|
||||||
<LoggedOutLayout
|
<LoggedOutLayout
|
||||||
leadin=""
|
leadin=""
|
||||||
title={_(msg`Create Account`)}
|
title={_(msg`Create Account`)}
|
||||||
description={_(msg`We're so excited to have you join us!`)}>
|
description={_(msg`We're so excited to have you join us!`)}
|
||||||
<ScrollView
|
scrollable>
|
||||||
testID="createAccount"
|
<View testID="createAccount" style={a.flex_1}>
|
||||||
keyboardShouldPersistTaps="handled"
|
<View
|
||||||
style={a.h_full}
|
style={[
|
||||||
keyboardDismissMode="on-drag">
|
a.flex_1,
|
||||||
<View style={[a.flex_1, a.px_xl, a.pt_2xl, {paddingBottom: 100}]}>
|
a.px_xl,
|
||||||
|
a.pt_2xl,
|
||||||
|
!gtMobile && {paddingBottom: 100},
|
||||||
|
]}>
|
||||||
<View style={[a.gap_sm, a.pb_3xl]}>
|
<View style={[a.gap_sm, a.pb_3xl]}>
|
||||||
<Text style={[a.font_semibold, t.atoms.text_contrast_medium]}>
|
<Text style={[a.font_semibold, t.atoms.text_contrast_medium]}>
|
||||||
<Trans>Step</Trans> {state.activeStep + 1} <Trans>of</Trans>{' '}
|
<Trans>Step</Trans> {state.activeStep + 1} <Trans>of</Trans>{' '}
|
||||||
|
@ -152,13 +157,15 @@ export function Signup({onPressBack}: {onPressBack: () => void}) {
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={[a.pb_3xl]}>
|
<View style={[a.pb_3xl]}>
|
||||||
{state.activeStep === SignupStep.INFO ? (
|
<LayoutAnimationConfig skipEntering skipExiting>
|
||||||
<StepInfo />
|
{state.activeStep === SignupStep.INFO ? (
|
||||||
) : state.activeStep === SignupStep.HANDLE ? (
|
<StepInfo />
|
||||||
<StepHandle />
|
) : state.activeStep === SignupStep.HANDLE ? (
|
||||||
) : (
|
<StepHandle />
|
||||||
<StepCaptcha />
|
) : (
|
||||||
)}
|
<StepCaptcha />
|
||||||
|
)}
|
||||||
|
</LayoutAnimationConfig>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={[a.flex_row, a.justify_between, a.pb_lg]}>
|
<View style={[a.flex_row, a.justify_between, a.pb_lg]}>
|
||||||
|
@ -208,7 +215,7 @@ export function Signup({onPressBack}: {onPressBack: () => void}) {
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</View>
|
||||||
</LoggedOutLayout>
|
</LoggedOutLayout>
|
||||||
</SignupContext.Provider>
|
</SignupContext.Provider>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,19 +1,24 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {StyleSheet, View} from 'react-native'
|
import {ScrollView, StyleSheet, View} from 'react-native'
|
||||||
import {Text} from '../text/Text'
|
|
||||||
|
import {isWeb} from '#/platform/detection'
|
||||||
|
import {useColorSchemeStyle} from 'lib/hooks/useColorSchemeStyle'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||||
import {useColorSchemeStyle} from 'lib/hooks/useColorSchemeStyle'
|
import {atoms as a} from '#/alf'
|
||||||
|
import {Text} from '../text/Text'
|
||||||
|
|
||||||
export const LoggedOutLayout = ({
|
export const LoggedOutLayout = ({
|
||||||
leadin,
|
leadin,
|
||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
children,
|
children,
|
||||||
|
scrollable,
|
||||||
}: React.PropsWithChildren<{
|
}: React.PropsWithChildren<{
|
||||||
leadin: string
|
leadin: string
|
||||||
title: string
|
title: string
|
||||||
description: string
|
description: string
|
||||||
|
scrollable?: boolean
|
||||||
}>) => {
|
}>) => {
|
||||||
const {isMobile, isTabletOrMobile} = useWebMediaQueries()
|
const {isMobile, isTabletOrMobile} = useWebMediaQueries()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
@ -25,7 +30,18 @@ export const LoggedOutLayout = ({
|
||||||
})
|
})
|
||||||
|
|
||||||
if (isMobile) {
|
if (isMobile) {
|
||||||
return <View style={{paddingTop: 10}}>{children}</View>
|
if (scrollable) {
|
||||||
|
return (
|
||||||
|
<ScrollView
|
||||||
|
style={styles.scrollview}
|
||||||
|
keyboardShouldPersistTaps="handled"
|
||||||
|
keyboardDismissMode="on-drag">
|
||||||
|
<View style={a.pt_md}>{children}</View>
|
||||||
|
</ScrollView>
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return <View style={a.pt_md}>{children}</View>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
|
@ -50,9 +66,23 @@ export const LoggedOutLayout = ({
|
||||||
{description}
|
{description}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[styles.content, contentBg]}>
|
{scrollable ? (
|
||||||
<View style={styles.contentWrapper}>{children}</View>
|
<View style={[styles.scrollableContent, contentBg]}>
|
||||||
</View>
|
<ScrollView
|
||||||
|
style={styles.scrollview}
|
||||||
|
contentContainerStyle={styles.scrollViewContentContainer}
|
||||||
|
keyboardShouldPersistTaps="handled"
|
||||||
|
keyboardDismissMode="on-drag">
|
||||||
|
<View style={[styles.contentWrapper, isWeb && a.my_auto]}>
|
||||||
|
{children}
|
||||||
|
</View>
|
||||||
|
</ScrollView>
|
||||||
|
</View>
|
||||||
|
) : (
|
||||||
|
<View style={[styles.content, contentBg]}>
|
||||||
|
<View style={styles.contentWrapper}>{children}</View>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -74,7 +104,16 @@ const styles = StyleSheet.create({
|
||||||
paddingHorizontal: 40,
|
paddingHorizontal: 40,
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
},
|
},
|
||||||
|
scrollableContent: {
|
||||||
|
flex: 2,
|
||||||
|
},
|
||||||
|
scrollview: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
scrollViewContentContainer: {
|
||||||
|
flex: 1,
|
||||||
|
paddingHorizontal: 40,
|
||||||
|
},
|
||||||
leadinText: {
|
leadinText: {
|
||||||
fontSize: 36,
|
fontSize: 36,
|
||||||
fontWeight: '800',
|
fontWeight: '800',
|
||||||
|
|
Loading…
Reference in New Issue