mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at samuel/exp-cli 239 lines 7.7 kB view raw
1import {useCallback, useImperativeHandle, useRef, useState} from 'react' 2import {View} from 'react-native' 3import {useWindowDimensions} from 'react-native' 4import {msg, Trans} from '@lingui/macro' 5import {useLingui} from '@lingui/react' 6 7import {BSKY_SERVICE} from '#/lib/constants' 8import {logEvent} from '#/lib/statsig/statsig' 9import * as persisted from '#/state/persisted' 10import {useSession} from '#/state/session' 11import {atoms as a, useBreakpoints, useTheme} from '#/alf' 12import {Admonition} from '#/components/Admonition' 13import {Button, ButtonText} from '#/components/Button' 14import * as Dialog from '#/components/Dialog' 15import * as TextField from '#/components/forms/TextField' 16import * as ToggleButton from '#/components/forms/ToggleButton' 17import {Globe_Stroke2_Corner0_Rounded as Globe} from '#/components/icons/Globe' 18import {InlineLinkText} from '#/components/Link' 19import {P, Text} from '#/components/Typography' 20 21export function ServerInputDialog({ 22 control, 23 onSelect, 24}: { 25 control: Dialog.DialogOuterProps['control'] 26 onSelect: (url: string) => void 27}) { 28 const {height} = useWindowDimensions() 29 const formRef = useRef<DialogInnerRef>(null) 30 31 // persist these options between dialog open/close 32 const [fixedOption, setFixedOption] = useState(BSKY_SERVICE) 33 const [previousCustomAddress, setPreviousCustomAddress] = useState('') 34 35 const onClose = useCallback(() => { 36 const result = formRef.current?.getFormState() 37 if (result) { 38 onSelect(result) 39 if (result !== BSKY_SERVICE) { 40 setPreviousCustomAddress(result) 41 } 42 } 43 logEvent('signin:hostingProviderPressed', { 44 hostingProviderDidChange: fixedOption !== BSKY_SERVICE, 45 }) 46 }, [onSelect, fixedOption]) 47 48 return ( 49 <Dialog.Outer 50 control={control} 51 onClose={onClose} 52 nativeOptions={{minHeight: height / 2}}> 53 <Dialog.Handle /> 54 <DialogInner 55 formRef={formRef} 56 fixedOption={fixedOption} 57 setFixedOption={setFixedOption} 58 initialCustomAddress={previousCustomAddress} 59 /> 60 </Dialog.Outer> 61 ) 62} 63 64type DialogInnerRef = {getFormState: () => string | null} 65 66function DialogInner({ 67 formRef, 68 fixedOption, 69 setFixedOption, 70 initialCustomAddress, 71}: { 72 formRef: React.Ref<DialogInnerRef> 73 fixedOption: string 74 setFixedOption: (opt: string) => void 75 initialCustomAddress: string 76}) { 77 const control = Dialog.useDialogContext() 78 const {_} = useLingui() 79 const t = useTheme() 80 const {accounts} = useSession() 81 const {gtMobile} = useBreakpoints() 82 const [customAddress, setCustomAddress] = useState(initialCustomAddress) 83 const [pdsAddressHistory, setPdsAddressHistory] = useState<string[]>( 84 persisted.get('pdsAddressHistory') || [], 85 ) 86 87 useImperativeHandle( 88 formRef, 89 () => ({ 90 getFormState: () => { 91 let url 92 if (fixedOption === 'custom') { 93 url = customAddress.trim().toLowerCase() 94 if (!url) { 95 return null 96 } 97 } else { 98 url = fixedOption 99 } 100 if (!url.startsWith('http://') && !url.startsWith('https://')) { 101 if (url === 'localhost' || url.startsWith('localhost:')) { 102 url = `http://${url}` 103 } else { 104 url = `https://${url}` 105 } 106 } 107 108 if (fixedOption === 'custom') { 109 if (!pdsAddressHistory.includes(url)) { 110 const newHistory = [url, ...pdsAddressHistory.slice(0, 4)] 111 setPdsAddressHistory(newHistory) 112 persisted.write('pdsAddressHistory', newHistory) 113 } 114 } 115 116 return url 117 }, 118 }), 119 [customAddress, fixedOption, pdsAddressHistory], 120 ) 121 122 const isFirstTimeUser = accounts.length === 0 123 124 return ( 125 <Dialog.ScrollableInner 126 accessibilityDescribedBy="dialog-description" 127 accessibilityLabelledBy="dialog-title"> 128 <View style={[a.relative, a.gap_md, a.w_full]}> 129 <Text nativeID="dialog-title" style={[a.text_2xl, a.font_bold]}> 130 <Trans>Choose your account provider</Trans> 131 </Text> 132 <ToggleButton.Group 133 label="Preferences" 134 values={[fixedOption]} 135 onChange={values => setFixedOption(values[0])}> 136 <ToggleButton.Button name={BSKY_SERVICE} label={_(msg`Bluesky`)}> 137 <ToggleButton.ButtonText>{_(msg`Bluesky`)}</ToggleButton.ButtonText> 138 </ToggleButton.Button> 139 <ToggleButton.Button 140 testID="customSelectBtn" 141 name="custom" 142 label={_(msg`Custom`)}> 143 <ToggleButton.ButtonText>{_(msg`Custom`)}</ToggleButton.ButtonText> 144 </ToggleButton.Button> 145 </ToggleButton.Group> 146 147 {fixedOption === BSKY_SERVICE && isFirstTimeUser && ( 148 <Admonition type="tip"> 149 <Trans> 150 Bluesky is an open network where you can choose your own provider. 151 If you're new here, we recommend sticking with the default Bluesky 152 Social option. 153 </Trans> 154 </Admonition> 155 )} 156 157 {fixedOption === 'custom' && ( 158 <View 159 style={[ 160 a.border, 161 t.atoms.border_contrast_low, 162 a.rounded_sm, 163 a.px_md, 164 a.py_md, 165 ]}> 166 <TextField.LabelText nativeID="address-input-label"> 167 <Trans>Server address</Trans> 168 </TextField.LabelText> 169 <TextField.Root> 170 <TextField.Icon icon={Globe} /> 171 <Dialog.Input 172 testID="customServerTextInput" 173 value={customAddress} 174 onChangeText={setCustomAddress} 175 label="my-server.com" 176 accessibilityLabelledBy="address-input-label" 177 autoCapitalize="none" 178 keyboardType="url" 179 /> 180 </TextField.Root> 181 {pdsAddressHistory.length > 0 && ( 182 <View style={[a.flex_row, a.flex_wrap, a.mt_xs]}> 183 {pdsAddressHistory.map(uri => ( 184 <Button 185 key={uri} 186 variant="ghost" 187 color="primary" 188 label={uri} 189 style={[a.px_sm, a.py_xs, a.rounded_sm, a.gap_sm]} 190 onPress={() => setCustomAddress(uri)}> 191 <ButtonText>{uri}</ButtonText> 192 </Button> 193 ))} 194 </View> 195 )} 196 </View> 197 )} 198 199 <View style={[a.py_xs]}> 200 <P 201 style={[ 202 t.atoms.text_contrast_medium, 203 a.text_sm, 204 a.leading_snug, 205 a.flex_1, 206 ]}> 207 {isFirstTimeUser ? ( 208 <Trans> 209 If you're a developer, you can host your own server. 210 </Trans> 211 ) : ( 212 <Trans> 213 Bluesky is an open network where you can choose your hosting 214 provider. If you're a developer, you can host your own server. 215 </Trans> 216 )}{' '} 217 <InlineLinkText 218 label={_(msg`Learn more about self hosting your PDS.`)} 219 to="https://atproto.com/guides/self-hosting"> 220 <Trans>Learn more.</Trans> 221 </InlineLinkText> 222 </P> 223 </View> 224 225 <View style={gtMobile && [a.flex_row, a.justify_end]}> 226 <Button 227 testID="doneBtn" 228 variant="outline" 229 color="primary" 230 size="small" 231 onPress={() => control.close()} 232 label={_(msg`Done`)}> 233 <ButtonText>{_(msg`Done`)}</ButtonText> 234 </Button> 235 </View> 236 </View> 237 </Dialog.ScrollableInner> 238 ) 239}