Bluesky app fork with some witchin' additions 馃挮 witchsky.app
bluesky fork client
120
fork

Configure Feed

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

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