diff options
author | Samuel Newman <mozzius@protonmail.com> | 2025-02-03 14:50:21 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-02-03 22:50:21 +0000 |
commit | 083a5c9667b243bf935f663386041e954d93803d (patch) | |
tree | b37fdb6da8fa59d6dd4c420f69d51426b501b247 | |
parent | 24a4ab2b0f155a385581da4855dae5b8cb63220f (diff) | |
download | voidsky-083a5c9667b243bf935f663386041e954d93803d.tar.zst |
Fix slow Hosting Provider dialog (#7594)
* avoid portal perf pitfall * add dep array
-rw-r--r-- | src/components/forms/HostingProvider.tsx | 4 | ||||
-rw-r--r-- | src/view/com/auth/server-input/index.tsx | 349 |
2 files changed, 194 insertions, 159 deletions
diff --git a/src/components/forms/HostingProvider.tsx b/src/components/forms/HostingProvider.tsx index 4732434b0..221a759d5 100644 --- a/src/components/forms/HostingProvider.tsx +++ b/src/components/forms/HostingProvider.tsx @@ -71,10 +71,10 @@ export function HostingProvider({ a.flex_row, a.align_center, a.rounded_sm, - a.px_md, + a.pl_md, a.pr_sm, a.gap_xs, - {paddingVertical: isAndroid ? 14 : 9}, + {paddingVertical: isAndroid ? 14 : 8}, ]} onPress={onPressSelectService}> {({hovered, pressed}) => { diff --git a/src/view/com/auth/server-input/index.tsx b/src/view/com/auth/server-input/index.tsx index f9a5c84bf..7c0bda45b 100644 --- a/src/view/com/auth/server-input/index.tsx +++ b/src/view/com/auth/server-input/index.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import {useCallback, useImperativeHandle, useRef, useState} from 'react' import {View} from 'react-native' import {useWindowDimensions} from 'react-native' import {msg, Trans} from '@lingui/macro' @@ -24,53 +24,22 @@ export function ServerInputDialog({ control: Dialog.DialogOuterProps['control'] onSelect: (url: string) => void }) { - const {_} = useLingui() - const t = useTheme() const {height} = useWindowDimensions() - const {gtMobile} = useBreakpoints() - const [pdsAddressHistory, setPdsAddressHistory] = React.useState<string[]>( - persisted.get('pdsAddressHistory') || [], - ) - const [fixedOption, setFixedOption] = React.useState([BSKY_SERVICE]) - const [customAddress, setCustomAddress] = React.useState('') - const {accounts} = useSession() + const formRef = useRef<DialogInnerRef>(null) - const isFirstTimeUser = accounts.length === 0 - - const onClose = React.useCallback(() => { - let url - if (fixedOption[0] === 'custom') { - url = customAddress.trim().toLowerCase() - if (!url) { - return - } - } else { - url = fixedOption[0] - } - if (!url.startsWith('http://') && !url.startsWith('https://')) { - if (url === 'localhost' || url.startsWith('localhost:')) { - url = `http://${url}` - } else { - url = `https://${url}` - } - } + // persist these options between dialog open/close + const [fixedOption, setFixedOption] = useState(BSKY_SERVICE) + const [previousCustomAddress, setPreviousCustomAddress] = useState('') - if (fixedOption[0] === 'custom') { - if (!pdsAddressHistory.includes(url)) { - const newHistory = [url, ...pdsAddressHistory.slice(0, 4)] - setPdsAddressHistory(newHistory) - persisted.write('pdsAddressHistory', newHistory) + const onClose = useCallback(() => { + const result = formRef.current?.getFormState() + if (result) { + onSelect(result) + if (result !== BSKY_SERVICE) { + setPreviousCustomAddress(result) } } - - onSelect(url) - }, [ - fixedOption, - customAddress, - onSelect, - pdsAddressHistory, - setPdsAddressHistory, - ]) + }, [onSelect]) return ( <Dialog.Outer @@ -78,123 +47,189 @@ export function ServerInputDialog({ onClose={onClose} nativeOptions={{minHeight: height / 2}}> <Dialog.Handle /> - <Dialog.ScrollableInner - accessibilityDescribedBy="dialog-description" - accessibilityLabelledBy="dialog-title"> - <View style={[a.relative, a.gap_md, a.w_full]}> - <Text nativeID="dialog-title" style={[a.text_2xl, a.font_bold]}> - <Trans>Choose your account provider</Trans> - </Text> - <ToggleButton.Group - label="Preferences" - values={fixedOption} - onChange={setFixedOption}> - <ToggleButton.Button name={BSKY_SERVICE} label={_(msg`Bluesky`)}> - <ToggleButton.ButtonText> - {_(msg`Bluesky`)} - </ToggleButton.ButtonText> - </ToggleButton.Button> - <ToggleButton.Button - testID="customSelectBtn" - name="custom" - label={_(msg`Custom`)}> - <ToggleButton.ButtonText> - {_(msg`Custom`)} - </ToggleButton.ButtonText> - </ToggleButton.Button> - </ToggleButton.Group> - - {fixedOption[0] === BSKY_SERVICE && isFirstTimeUser && ( - <Admonition type="tip"> + <DialogInner + formRef={formRef} + fixedOption={fixedOption} + setFixedOption={setFixedOption} + initialCustomAddress={previousCustomAddress} + /> + </Dialog.Outer> + ) +} + +type DialogInnerRef = {getFormState: () => string | null} + +function DialogInner({ + formRef, + fixedOption, + setFixedOption, + initialCustomAddress, +}: { + formRef: React.Ref<DialogInnerRef> + fixedOption: string + setFixedOption: (opt: string) => void + initialCustomAddress: string +}) { + const control = Dialog.useDialogContext() + const {_} = useLingui() + const t = useTheme() + const {accounts} = useSession() + const {gtMobile} = useBreakpoints() + const [customAddress, setCustomAddress] = useState(initialCustomAddress) + const [pdsAddressHistory, setPdsAddressHistory] = useState<string[]>( + persisted.get('pdsAddressHistory') || [], + ) + + useImperativeHandle( + formRef, + () => ({ + getFormState: () => { + let url + if (fixedOption === 'custom') { + url = customAddress.trim().toLowerCase() + if (!url) { + return null + } + } else { + url = fixedOption + } + if (!url.startsWith('http://') && !url.startsWith('https://')) { + if (url === 'localhost' || url.startsWith('localhost:')) { + url = `http://${url}` + } else { + url = `https://${url}` + } + } + + if (fixedOption === 'custom') { + if (!pdsAddressHistory.includes(url)) { + const newHistory = [url, ...pdsAddressHistory.slice(0, 4)] + setPdsAddressHistory(newHistory) + persisted.write('pdsAddressHistory', newHistory) + } + } + + return url + }, + }), + [customAddress, fixedOption, pdsAddressHistory], + ) + + const isFirstTimeUser = accounts.length === 0 + + return ( + <Dialog.ScrollableInner + accessibilityDescribedBy="dialog-description" + accessibilityLabelledBy="dialog-title"> + <View style={[a.relative, a.gap_md, a.w_full]}> + <Text nativeID="dialog-title" style={[a.text_2xl, a.font_bold]}> + <Trans>Choose your account provider</Trans> + </Text> + <ToggleButton.Group + label="Preferences" + values={[fixedOption]} + onChange={values => setFixedOption(values[0])}> + <ToggleButton.Button name={BSKY_SERVICE} label={_(msg`Bluesky`)}> + <ToggleButton.ButtonText>{_(msg`Bluesky`)}</ToggleButton.ButtonText> + </ToggleButton.Button> + <ToggleButton.Button + testID="customSelectBtn" + name="custom" + label={_(msg`Custom`)}> + <ToggleButton.ButtonText>{_(msg`Custom`)}</ToggleButton.ButtonText> + </ToggleButton.Button> + </ToggleButton.Group> + + {fixedOption === BSKY_SERVICE && isFirstTimeUser && ( + <Admonition type="tip"> + <Trans> + Bluesky is an open network where you can choose your own provider. + If you're new here, we recommend sticking with the default Bluesky + Social option. + </Trans> + </Admonition> + )} + + {fixedOption === 'custom' && ( + <View + style={[ + a.border, + t.atoms.border_contrast_low, + a.rounded_sm, + a.px_md, + a.py_md, + ]}> + <TextField.LabelText nativeID="address-input-label"> + <Trans>Server address</Trans> + </TextField.LabelText> + <TextField.Root> + <TextField.Icon icon={Globe} /> + <Dialog.Input + testID="customServerTextInput" + value={customAddress} + onChangeText={setCustomAddress} + label="my-server.com" + accessibilityLabelledBy="address-input-label" + autoCapitalize="none" + keyboardType="url" + /> + </TextField.Root> + {pdsAddressHistory.length > 0 && ( + <View style={[a.flex_row, a.flex_wrap, a.mt_xs]}> + {pdsAddressHistory.map(uri => ( + <Button + key={uri} + variant="ghost" + color="primary" + label={uri} + style={[a.px_sm, a.py_xs, a.rounded_sm, a.gap_sm]} + onPress={() => setCustomAddress(uri)}> + <ButtonText>{uri}</ButtonText> + </Button> + ))} + </View> + )} + </View> + )} + + <View style={[a.py_xs]}> + <P + style={[ + t.atoms.text_contrast_medium, + a.text_sm, + a.leading_snug, + a.flex_1, + ]}> + {isFirstTimeUser ? ( <Trans> - Bluesky is an open network where you can choose your own - provider. If you're new here, we recommend sticking with the - default Bluesky Social option. + If you're a developer, you can host your own server. </Trans> - </Admonition> - )} - - {fixedOption[0] === 'custom' && ( - <View - style={[ - a.border, - t.atoms.border_contrast_low, - a.rounded_sm, - a.px_md, - a.py_md, - ]}> - <TextField.LabelText nativeID="address-input-label"> - <Trans>Server address</Trans> - </TextField.LabelText> - <TextField.Root> - <TextField.Icon icon={Globe} /> - <Dialog.Input - testID="customServerTextInput" - value={customAddress} - onChangeText={setCustomAddress} - label="my-server.com" - accessibilityLabelledBy="address-input-label" - autoCapitalize="none" - keyboardType="url" - /> - </TextField.Root> - {pdsAddressHistory.length > 0 && ( - <View style={[a.flex_row, a.flex_wrap, a.mt_xs]}> - {pdsAddressHistory.map(uri => ( - <Button - key={uri} - variant="ghost" - color="primary" - label={uri} - style={[a.px_sm, a.py_xs, a.rounded_sm, a.gap_sm]} - onPress={() => setCustomAddress(uri)}> - <ButtonText>{uri}</ButtonText> - </Button> - ))} - </View> - )} - </View> - )} - - <View style={[a.py_xs]}> - <P - style={[ - t.atoms.text_contrast_medium, - a.text_sm, - a.leading_snug, - a.flex_1, - ]}> - {isFirstTimeUser ? ( - <Trans> - If you're a developer, you can host your own server. - </Trans> - ) : ( - <Trans> - Bluesky is an open network where you can choose your hosting - provider. If you're a developer, you can host your own server. - </Trans> - )}{' '} - <InlineLinkText - label={_(msg`Learn more about self hosting your PDS.`)} - to="https://atproto.com/guides/self-hosting"> - <Trans>Learn more.</Trans> - </InlineLinkText> - </P> - </View> + ) : ( + <Trans> + Bluesky is an open network where you can choose your hosting + provider. If you're a developer, you can host your own server. + </Trans> + )}{' '} + <InlineLinkText + label={_(msg`Learn more about self hosting your PDS.`)} + to="https://atproto.com/guides/self-hosting"> + <Trans>Learn more.</Trans> + </InlineLinkText> + </P> + </View> - <View style={gtMobile && [a.flex_row, a.justify_end]}> - <Button - testID="doneBtn" - variant="outline" - color="primary" - size="small" - onPress={() => control.close()} - label={_(msg`Done`)}> - <ButtonText>{_(msg`Done`)}</ButtonText> - </Button> - </View> + <View style={gtMobile && [a.flex_row, a.justify_end]}> + <Button + testID="doneBtn" + variant="outline" + color="primary" + size="small" + onPress={() => control.close()} + label={_(msg`Done`)}> + <ButtonText>{_(msg`Done`)}</ButtonText> + </Button> </View> - </Dialog.ScrollableInner> - </Dialog.Outer> + </View> + </Dialog.ScrollableInner> ) } |