Skip to content

Commit

Permalink
Improved server selector during account creation and signin (#2840)
Browse files Browse the repository at this point in the history
* Replace the ServerInput modal with a new dialog based on alf that remembers your server address history and doesnt put staging and localdev in the options

* Update the server selector during account creation

* dont apply capitalization, use url keyboard

* Apply insets to dialog top

* Improve padding of dialogs on native

* Fix race condition in dialog close; also fix fire of the onClose event in dialogs

---------

Co-authored-by: Hailey <[email protected]>
  • Loading branch information
pfrazee and haileyok authored Feb 12, 2024
1 parent b91a6b4 commit ba7463c
Show file tree
Hide file tree
Showing 14 changed files with 316 additions and 267 deletions.
1 change: 1 addition & 0 deletions src/components/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export type ButtonProps = React.PropsWithChildren<
Pick<PressableProps, 'disabled' | 'onPress'> &
AccessibilityProps &
VariantProps & {
testID?: string
label: string
style?: StyleProp<ViewStyle>
}
Expand Down
54 changes: 33 additions & 21 deletions src/components/Dialog/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ export function Outer({
const sheet = React.useRef<BottomSheet>(null)
const sheetOptions = nativeOptions?.sheet || {}
const hasSnapPoints = !!sheetOptions.snapPoints
const insets = useSafeAreaInsets()

const open = React.useCallback<DialogControlProps['open']>((i = 0) => {
sheet.current?.snapToIndex(i)
}, [])

const close = React.useCallback(() => {
sheet.current?.close()
onClose?.()
}, [onClose])
}, [])

useImperativeHandle(
control.ref,
Expand All @@ -53,6 +53,15 @@ export function Outer({
[open, close],
)

const onChange = React.useCallback(
(index: number) => {
if (index === -1) {
onClose?.()
}
},
[onClose],
)

const context = React.useMemo(() => ({close}), [close])

return (
Expand All @@ -63,6 +72,7 @@ export function Outer({
keyboardBehavior="interactive"
android_keyboardInputMode="adjustResize"
keyboardBlurBehavior="restore"
topInset={insets.top}
{...sheetOptions}
ref={sheet}
index={-1}
Expand All @@ -77,7 +87,7 @@ export function Outer({
)}
handleIndicatorStyle={{backgroundColor: t.palette.primary_500}}
handleStyle={{display: 'none'}}
onClose={onClose}>
onChange={onChange}>
<Context.Provider value={context}>
<View
style={[
Expand Down Expand Up @@ -105,8 +115,8 @@ export function Inner(props: DialogInnerProps) {
<BottomSheetView
style={[
a.p_lg,
a.pt_3xl,
{
paddingTop: 40,
borderTopLeftRadius: 40,
borderTopRightRadius: 40,
paddingBottom: insets.bottom + a.pb_5xl.paddingBottom,
Expand All @@ -121,11 +131,13 @@ export function ScrollableInner(props: DialogInnerProps) {
const insets = useSafeAreaInsets()
return (
<BottomSheetScrollView
keyboardShouldPersistTaps="handled"
keyboardDismissMode="on-drag"
style={[
a.flex_1, // main diff is this
a.p_lg,
a.pt_3xl,
a.p_xl,
{
paddingTop: 40,
borderTopLeftRadius: 40,
borderTopRightRadius: 40,
},
Expand All @@ -139,21 +151,21 @@ export function ScrollableInner(props: DialogInnerProps) {
export function Handle() {
const t = useTheme()
return (
<View
style={[
a.absolute,
a.rounded_sm,
a.z_10,
{
top: a.pt_lg.paddingTop,
width: 35,
height: 4,
alignSelf: 'center',
backgroundColor: t.palette.contrast_900,
opacity: 0.5,
},
]}
/>
<View style={[a.absolute, a.w_full, a.align_center, a.z_10, {height: 40}]}>
<View
style={[
a.rounded_sm,
{
top: a.pt_lg.paddingTop,
width: 35,
height: 4,
alignSelf: 'center',
backgroundColor: t.palette.contrast_900,
opacity: 0.5,
},
]}
/>
</View>
)
}

Expand Down
6 changes: 5 additions & 1 deletion src/components/forms/TextField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -238,10 +238,14 @@ export function createInput(Component: typeof TextInput) {

export const Input = createInput(TextInput)

export function Label({children}: React.PropsWithChildren<{}>) {
export function Label({
nativeID,
children,
}: React.PropsWithChildren<{nativeID?: string}>) {
const t = useTheme()
return (
<Text
nativeID={nativeID}
style={[a.text_sm, a.font_bold, t.atoms.text_contrast_medium, a.mb_sm]}>
{children}
</Text>
Expand Down
2 changes: 1 addition & 1 deletion src/components/forms/ToggleButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import * as Toggle from '#/components/forms/Toggle'

export type ItemProps = Omit<Toggle.ItemProps, 'style' | 'role' | 'children'> &
AccessibilityProps &
React.PropsWithChildren<{}>
React.PropsWithChildren<{testID?: string}>

export type GroupProps = Omit<Toggle.GroupProps, 'style' | 'type'> & {
multiple?: boolean
Expand Down
7 changes: 0 additions & 7 deletions src/state/modals/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,6 @@ export interface EditProfileModal {
onUpdate?: () => void
}

export interface ServerInputModal {
name: 'server-input'
initialService: string
onSelect: (url: string) => void
}

export interface ModerationDetailsModal {
name: 'moderation-details'
context: 'account' | 'content'
Expand Down Expand Up @@ -222,7 +216,6 @@ export type Modal =
| AltTextImageModal
| CropImageModal
| EditImageModal
| ServerInputModal
| RepostModal
| SelfLabelModal
| ThreadgateModal
Expand Down
1 change: 1 addition & 0 deletions src/state/persisted/legacy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ export function transform(legacy: Partial<LegacySchema>): Schema {
hiddenPosts: defaults.hiddenPosts,
externalEmbeds: defaults.externalEmbeds,
lastSelectedHomeFeed: defaults.lastSelectedHomeFeed,
pdsAddressHistory: defaults.pdsAddressHistory,
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/state/persisted/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export const schema = z.object({
hiddenPosts: z.array(z.string()).optional(), // should move to server
useInAppBrowser: z.boolean().optional(),
lastSelectedHomeFeed: z.string().optional(),
pdsAddressHistory: z.array(z.string()).optional(),
})
export type Schema = z.infer<typeof schema>

Expand Down Expand Up @@ -91,4 +92,5 @@ export const defaults: Schema = {
hiddenPosts: [],
useInAppBrowser: undefined,
lastSelectedHomeFeed: undefined,
pdsAddressHistory: [],
}
102 changes: 77 additions & 25 deletions src/view/com/auth/create/Step1.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
ActivityIndicator,
Keyboard,
StyleSheet,
TouchableOpacity,
TouchableWithoutFeedback,
View,
} from 'react-native'
Expand All @@ -13,15 +14,21 @@ import {StepHeader} from './StepHeader'
import {s} from 'lib/styles'
import {usePalette} from 'lib/hooks/usePalette'
import {TextInput} from '../util/TextInput'
import {Button} from '../../util/forms/Button'
import {Policies} from './Policies'
import {ErrorMessage} from 'view/com/util/error/ErrorMessage'
import {isWeb} from 'platform/detection'
import {Trans, msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useModalControls} from '#/state/modals'
import {logger} from '#/logger'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {
FontAwesomeIcon,
FontAwesomeIconStyle,
} from '@fortawesome/react-native-fontawesome'
import {useDialogControl} from '#/components/Dialog'

import {ServerInputDialog} from '../server-input'
import {toNiceDomain} from '#/lib/strings/url-helpers'

function sanitizeDate(date: Date): Date {
if (!date || date.toString() === 'Invalid Date') {
Expand All @@ -43,16 +50,12 @@ export function Step1({
const pal = usePalette('default')
const {_} = useLingui()
const {openModal} = useModalControls()
const serverInputControl = useDialogControl()

const onPressSelectService = React.useCallback(() => {
openModal({
name: 'server-input',
initialService: uiState.serviceUrl,
onSelect: (url: string) =>
uiDispatch({type: 'set-service-url', value: url}),
})
serverInputControl.open()
Keyboard.dismiss()
}, [uiDispatch, uiState.serviceUrl, openModal])
}, [serverInputControl])

const onPressWaitlist = React.useCallback(() => {
openModal({name: 'waitlist'})
Expand All @@ -64,23 +67,72 @@ export function Step1({

return (
<View>
<StepHeader uiState={uiState} title={_(msg`Your account`)}>
<View>
<Button
testID="selectServiceButton"
type="default"
style={{
aspectRatio: 1,
justifyContent: 'center',
alignItems: 'center',
}}
accessibilityLabel={_(msg`Select service`)}
accessibilityHint={_(msg`Sets server for the Bluesky client`)}
onPress={onPressSelectService}>
<FontAwesomeIcon icon="server" size={21} color={pal.colors.text} />
</Button>
<ServerInputDialog
control={serverInputControl}
onSelect={url => uiDispatch({type: 'set-service-url', value: url})}
/>
<StepHeader uiState={uiState} title={_(msg`Your account`)} />

<View style={s.pb20}>
<Text type="md-medium" style={[pal.text, s.mb2]}>
<Trans>Hosting provider</Trans>
</Text>
<View style={[pal.border, {borderWidth: 1, borderRadius: 6}]}>
<View
style={[
pal.borderDark,
{flexDirection: 'row', alignItems: 'center'},
]}>
<FontAwesomeIcon
icon="globe"
style={[pal.textLight, {marginLeft: 14}]}
/>
<TouchableOpacity
testID="loginSelectServiceButton"
style={{
flexDirection: 'row',
flex: 1,
alignItems: 'center',
}}
onPress={onPressSelectService}
accessibilityRole="button"
accessibilityLabel={_(msg`Select service`)}
accessibilityHint={_(msg`Sets server for the Bluesky client`)}>
<Text
type="xl"
style={[
pal.text,
{
flex: 1,
paddingVertical: 10,
paddingRight: 12,
paddingLeft: 10,
},
]}>
{toNiceDomain(uiState.serviceUrl)}
</Text>
<View
style={[
pal.btn,
{
flexDirection: 'row',
alignItems: 'center',
borderRadius: 6,
paddingVertical: 6,
paddingHorizontal: 8,
marginHorizontal: 6,
},
]}>
<FontAwesomeIcon
icon="pen"
size={12}
style={pal.textLight as FontAwesomeIconStyle}
/>
</View>
</TouchableOpacity>
</View>
</View>
</StepHeader>
</View>

{!uiState.serviceDescription ? (
<ActivityIndicator />
Expand Down
22 changes: 13 additions & 9 deletions src/view/com/auth/login/ForgotPasswordForm.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, {useState, useEffect} from 'react'
import {
ActivityIndicator,
Keyboard,
TextInput,
TouchableOpacity,
View,
Expand All @@ -24,7 +25,9 @@ import {logger} from '#/logger'
import {Trans, msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {styles} from './styles'
import {useModalControls} from '#/state/modals'
import {useDialogControl} from '#/components/Dialog'

import {ServerInputDialog} from '../server-input'

type ServiceDescription = ComAtprotoServerDescribeServer.OutputSchema

Expand All @@ -51,19 +54,16 @@ export const ForgotPasswordForm = ({
const [email, setEmail] = useState<string>('')
const {screen} = useAnalytics()
const {_} = useLingui()
const {openModal} = useModalControls()
const serverInputControl = useDialogControl()

useEffect(() => {
screen('Signin:ForgotPassword')
}, [screen])

const onPressSelectService = () => {
openModal({
name: 'server-input',
initialService: serviceUrl,
onSelect: setServiceUrl,
})
}
const onPressSelectService = React.useCallback(() => {
serverInputControl.open()
Keyboard.dismiss()
}, [serverInputControl])

const onPressNext = async () => {
if (!EmailValidator.validate(email)) {
Expand Down Expand Up @@ -96,6 +96,10 @@ export const ForgotPasswordForm = ({
return (
<>
<View>
<ServerInputDialog
control={serverInputControl}
onSelect={setServiceUrl}
/>
<Text type="title-lg" style={[pal.text, styles.screenTitle]}>
<Trans>Reset password</Trans>
</Text>
Expand Down
Loading

0 comments on commit ba7463c

Please sign in to comment.