Bluesky app fork with some witchin' additions 馃挮
at main 210 lines 6.9 kB view raw
1import React from 'react' 2import {View} from 'react-native' 3import {msg, Trans} from '@lingui/macro' 4import {useLingui} from '@lingui/react' 5 6import {useCleanError} from '#/lib/hooks/useCleanError' 7import {isAppPassword} from '#/lib/jwt' 8import {getAge, getDateAgo} from '#/lib/strings/time' 9import {logger} from '#/logger' 10import { 11 useBirthdateMutation, 12 useIsBirthdateUpdateAllowed, 13} from '#/state/birthdate' 14import { 15 usePreferencesQuery, 16 type UsePreferencesQueryResponse, 17} from '#/state/queries/preferences' 18import {useSession} from '#/state/session' 19import {ErrorMessage} from '#/view/com/util/error/ErrorMessage' 20import {atoms as a, useTheme, web} from '#/alf' 21import {Admonition} from '#/components/Admonition' 22import {Button, ButtonIcon, ButtonText} from '#/components/Button' 23import * as Dialog from '#/components/Dialog' 24import {DateField} from '#/components/forms/DateField' 25import {SimpleInlineLinkText} from '#/components/Link' 26import {Loader} from '#/components/Loader' 27import {Span, Text} from '#/components/Typography' 28import {IS_IOS, IS_WEB} from '#/env' 29 30export function BirthDateSettingsDialog({ 31 control, 32}: { 33 control: Dialog.DialogControlProps 34}) { 35 const t = useTheme() 36 const {_} = useLingui() 37 const {isLoading, error, data: preferences} = usePreferencesQuery() 38 const isBirthdateUpdateAllowed = useIsBirthdateUpdateAllowed() 39 const {currentAccount} = useSession() 40 const isUsingAppPassword = isAppPassword(currentAccount?.accessJwt || '') 41 42 return ( 43 <Dialog.Outer control={control} nativeOptions={{preventExpansion: true}}> 44 <Dialog.Handle /> 45 {isBirthdateUpdateAllowed ? ( 46 <Dialog.ScrollableInner 47 label={_(msg`My Birthdate`)} 48 style={web({maxWidth: 400})}> 49 <View style={[a.gap_md]}> 50 <Text style={[a.text_xl, a.font_semi_bold]}> 51 <Trans>My Birthdate</Trans> 52 </Text> 53 <Text 54 style={[a.text_md, a.leading_snug, t.atoms.text_contrast_medium]}> 55 <Trans> 56 This information is private and not shared with other users. 57 </Trans> 58 </Text> 59 60 {isLoading ? ( 61 <Loader size="xl" /> 62 ) : error || !preferences ? ( 63 <ErrorMessage 64 message={ 65 error?.toString() || 66 _( 67 msg`We were unable to load your birthdate preferences. Please try again.`, 68 ) 69 } 70 style={[a.rounded_sm]} 71 /> 72 ) : isUsingAppPassword ? ( 73 <Admonition type="info"> 74 <Trans> 75 Hmm, it looks like you're logged in with an{' '} 76 <Span style={[a.italic]}>App Password</Span>. To set your 77 birthdate, you'll need to log in with your main account 78 password, or ask whomever controls this account to do so. 79 </Trans> 80 </Admonition> 81 ) : ( 82 <BirthdayInner control={control} preferences={preferences} /> 83 )} 84 </View> 85 86 <Dialog.Close /> 87 </Dialog.ScrollableInner> 88 ) : ( 89 <Dialog.ScrollableInner 90 label={_(msg`You recently changed your birthdate`)} 91 style={web({maxWidth: 400})}> 92 <View style={[a.gap_sm]}> 93 <Text 94 style={[ 95 a.text_xl, 96 a.font_semi_bold, 97 a.leading_snug, 98 {paddingRight: 32}, 99 ]}> 100 <Trans>You recently changed your birthdate</Trans> 101 </Text> 102 <Text 103 style={[a.text_md, a.leading_snug, t.atoms.text_contrast_medium]}> 104 <Trans> 105 There is a limit to how often you can change your birthdate. You 106 may need to wait a day or two before updating it again. 107 </Trans> 108 </Text> 109 </View> 110 111 <Dialog.Close /> 112 </Dialog.ScrollableInner> 113 )} 114 </Dialog.Outer> 115 ) 116} 117 118function BirthdayInner({ 119 control, 120 preferences, 121}: { 122 control: Dialog.DialogControlProps 123 preferences: UsePreferencesQueryResponse 124}) { 125 const {_} = useLingui() 126 const cleanError = useCleanError() 127 const [date, setDate] = React.useState( 128 preferences.birthDate || getDateAgo(18), 129 ) 130 const {isPending, error, mutateAsync: setBirthDate} = useBirthdateMutation() 131 const hasChanged = date !== preferences.birthDate 132 const errorMessage = React.useMemo(() => { 133 if (error) { 134 const {raw, clean} = cleanError(error) 135 return clean || raw || error.toString() 136 } 137 }, [error, cleanError]) 138 139 const age = getAge(new Date(date)) 140 const isUnder13 = age < 13 141 const isUnder18 = age >= 13 && age < 18 142 143 const onSave = React.useCallback(async () => { 144 try { 145 // skip if date is the same 146 if (hasChanged) { 147 await setBirthDate({birthDate: date}) 148 } 149 control.close() 150 } catch (e: any) { 151 logger.error(`setBirthDate failed`, {message: e.message}) 152 } 153 }, [date, setBirthDate, control, hasChanged]) 154 155 return ( 156 <View style={a.gap_lg} testID="birthDateSettingsDialog"> 157 <View style={IS_IOS && [a.w_full, a.align_center]}> 158 <DateField 159 testID="birthdayInput" 160 value={date} 161 onChangeDate={newDate => setDate(new Date(newDate))} 162 label={_(msg`Birthdate`)} 163 accessibilityHint={_(msg`Enter your birthdate`)} 164 /> 165 </View> 166 167 {isUnder18 && hasChanged && ( 168 <Admonition type="info"> 169 <Trans> 170 The birthdate you've entered means you are under 18 years old. 171 Certain content and features may be unavailable to you. 172 </Trans> 173 </Admonition> 174 )} 175 176 {isUnder13 && ( 177 <Admonition type="error"> 178 <Trans> 179 You must be at least 13 years old to use Bluesky. Read our{' '} 180 <SimpleInlineLinkText 181 to="https://bsky.social/about/support/tos" 182 label={_(msg`Terms of Service`)}> 183 Terms of Service 184 </SimpleInlineLinkText>{' '} 185 for more information. 186 </Trans> 187 </Admonition> 188 )} 189 190 {errorMessage ? ( 191 <ErrorMessage message={errorMessage} style={[a.rounded_sm]} /> 192 ) : undefined} 193 194 <View style={IS_WEB && [a.flex_row, a.justify_end]}> 195 <Button 196 label={hasChanged ? _(msg`Save birthdate`) : _(msg`Done`)} 197 size="large" 198 onPress={onSave} 199 variant="solid" 200 color="primary" 201 disabled={isUnder13}> 202 <ButtonText> 203 {hasChanged ? <Trans>Save</Trans> : <Trans>Done</Trans>} 204 </ButtonText> 205 {isPending && <ButtonIcon icon={Loader} />} 206 </Button> 207 </View> 208 </View> 209 ) 210}