Something went wrong. Try again.
Bluesky app fork with some witchin' additions 💫 forked from jollywhoppers.com/witchsky.app
Something went wrong. Try again.
6.6 kB · 212 lines
TSX
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213import {useCallback, useImperativeHandle, useRef, useState} from 'react'import {useWindowDimensions, View} from 'react-native'import {msg, Trans} from '@lingui/macro'import {useLingui} from '@lingui/react'
import {BSKY_SERVICE} from '#/lib/constants'import * as persisted from '#/state/persisted'import {useSession} from '#/state/session'import {atoms as a, platform, useBreakpoints, useTheme, web} from '#/alf'import {Admonition} from '#/components/Admonition'import {Button, ButtonText} from '#/components/Button'import * as Dialog from '#/components/Dialog'import * as TextField from '#/components/forms/TextField'import {Globe_Stroke2_Corner0_Rounded as Globe} from '#/components/icons/Globe'import {InlineLinkText} from '#/components/Link'import {Text} from '#/components/Typography'import {useAnalytics} from '#/analytics'
export function ServerInputDialog({ control, onSelect,}: { control: Dialog.DialogOuterProps['control'] onSelect: (url: string) => void}) { const ax = useAnalytics() const {height} = useWindowDimensions() const formRef = useRef<DialogInnerRef>(null)
// persist these options between dialog open/close const [previousCustomAddress, setPreviousCustomAddress] = useState('')
const onClose = useCallback(() => { const result = formRef.current?.getFormState() if (result) { onSelect(result) if (result !== BSKY_SERVICE) { setPreviousCustomAddress(result) } } ax.metric('signin:hostingProviderPressed', { hostingProviderDidChange: result !== BSKY_SERVICE, }) }, [ax, onSelect])
return ( <Dialog.Outer control={control} onClose={onClose} nativeOptions={platform({ android: {minHeight: height / 2}, ios: {preventExpansion: true}, })}> <Dialog.Handle /> <DialogInner formRef={formRef} initialCustomAddress={previousCustomAddress} /> </Dialog.Outer> )}
type DialogInnerRef = {getFormState: () => string | null}
function DialogInner({ formRef, initialCustomAddress,}: { formRef: React.Ref<DialogInnerRef> 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 = customAddress.trim().toLowerCase() if (!url) { return null } if (!url.startsWith('http://') && !url.startsWith('https://')) { if (url === 'localhost' || url.startsWith('localhost:')) { url = `http://${url}` } else { url = `https://${url}` } }
if (!pdsAddressHistory.includes(url)) { const newHistory = [url, ...pdsAddressHistory.slice(0, 4)] setPdsAddressHistory(newHistory) persisted.write('pdsAddressHistory', newHistory) }
return url }, }), [customAddress, pdsAddressHistory], )
const isFirstTimeUser = accounts.length === 0
return ( <Dialog.ScrollableInner accessibilityDescribedBy="dialog-description" accessibilityLabelledBy="dialog-title" style={web({maxWidth: 500})}> <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>
{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> )}
<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]}> <Text style={[t.atoms.text_contrast_medium, a.text_sm, a.leading_snug]}> {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> </Text> </View>
<View style={gtMobile && [a.flex_row, a.justify_end]}> <Button testID="doneBtn" variant="solid" color="primary" size={platform({ native: 'large', web: 'small', })} onPress={() => control.close()} label={_(msg`Done`)}> <ButtonText> <Trans>Done</Trans> </ButtonText> </Button> </View> </View> </Dialog.ScrollableInner> )}