Bluesky app fork with some witchin' additions 馃挮
0
fork

Configure Feed

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

at cope-settings-sync 230 lines 8.6 kB view raw
1import {View} from 'react-native' 2import {msg} from '@lingui/core/macro' 3import {useLingui} from '@lingui/react' 4import {Trans} from '@lingui/react/macro' 5 6import {dateDiff, useGetTimeAgo} from '#/lib/hooks/useTimeAgo' 7import {atoms as a, useBreakpoints, useTheme, type ViewStyleProp} from '#/alf' 8import {Admonition} from '#/components/Admonition' 9import {AgeAssuranceAppealDialog} from '#/components/ageAssurance/AgeAssuranceAppealDialog' 10import {AgeAssuranceBadge} from '#/components/ageAssurance/AgeAssuranceBadge' 11import {AgeAssuranceConfigUnavailableError} from '#/components/ageAssurance/AgeAssuranceErrors' 12import { 13 AgeAssuranceInitDialog, 14 useDialogControl, 15} from '#/components/ageAssurance/AgeAssuranceInitDialog' 16import {useAgeAssuranceCopy} from '#/components/ageAssurance/useAgeAssuranceCopy' 17import {Button, ButtonText} from '#/components/Button' 18import * as Dialog from '#/components/Dialog' 19import {DeviceLocationRequestDialog} from '#/components/dialogs/DeviceLocationRequestDialog' 20import {Divider} from '#/components/Divider' 21import {createStaticClick, InlineLinkText} from '#/components/Link' 22import * as Toast from '#/components/Toast' 23import {Text} from '#/components/Typography' 24import {useAgeAssurance} from '#/ageAssurance' 25import {useComputeAgeAssuranceRegionAccess} from '#/ageAssurance/useComputeAgeAssuranceRegionAccess' 26import {useAnalytics} from '#/analytics' 27import {IS_NATIVE} from '#/env' 28import {useDeviceGeolocationApi} from '#/geolocation' 29 30export function AgeAssuranceAccountCard({style}: ViewStyleProp & {}) { 31 const aa = useAgeAssurance() 32 if (aa.state.access === aa.Access.Full) return null 33 if (aa.state.error === 'config') { 34 return ( 35 <View style={style}> 36 <AgeAssuranceConfigUnavailableError /> 37 </View> 38 ) 39 } 40 return <Inner style={style} /> 41} 42 43function Inner({style}: ViewStyleProp & {}) { 44 const t = useTheme() 45 const {_, i18n} = useLingui() 46 const ax = useAnalytics() 47 const control = useDialogControl() 48 const appealControl = Dialog.useDialogControl() 49 const locationControl = Dialog.useDialogControl() 50 const getTimeAgo = useGetTimeAgo() 51 const {gtPhone} = useBreakpoints() 52 const {setDeviceGeolocation} = useDeviceGeolocationApi() 53 const computeAgeAssuranceRegionAccess = useComputeAgeAssuranceRegionAccess() 54 55 const copy = useAgeAssuranceCopy() 56 const aa = useAgeAssurance() 57 const {status, lastInitiatedAt} = aa.state 58 const isBlocked = status === aa.Status.Blocked 59 const hasInitiated = !!lastInitiatedAt 60 const hasCompletedFlow = status === aa.Status.Assured 61 const timeAgo = lastInitiatedAt 62 ? getTimeAgo(lastInitiatedAt, new Date()) 63 : null 64 const diff = lastInitiatedAt 65 ? dateDiff(lastInitiatedAt, new Date(), 'down') 66 : null 67 68 return ( 69 <> 70 <AgeAssuranceInitDialog control={control} /> 71 <AgeAssuranceAppealDialog control={appealControl} /> 72 73 <View style={style}> 74 <View 75 style={[a.p_lg, a.rounded_md, a.border, t.atoms.border_contrast_low]}> 76 <View 77 style={[ 78 a.flex_row, 79 a.justify_between, 80 a.align_center, 81 a.gap_lg, 82 a.pb_md, 83 a.z_10, 84 ]}> 85 <View style={[a.align_start]}> 86 <AgeAssuranceBadge /> 87 </View> 88 </View> 89 90 <View style={[a.pb_md, a.gap_sm]}> 91 <Text style={[a.text_sm, a.leading_snug]}>{copy.notice}</Text> 92 {hasCompletedFlow && ( 93 <Text style={[a.text_sm, a.leading_snug]}> 94 <Trans> 95 If you are 18 years of age or older and want to try again, 96 click the button below and use a different verification method 97 if one is available in your region. If you have questions or 98 concerns,{' '} 99 <InlineLinkText 100 label={_(msg`Contact our support team`)} 101 {...createStaticClick(() => { 102 appealControl.open() 103 })}> 104 our support team can help. 105 </InlineLinkText> 106 </Trans> 107 </Text> 108 )} 109 110 {IS_NATIVE && ( 111 <> 112 <Text style={[a.text_sm, a.leading_snug]}> 113 <Trans> 114 Is your location not accurate?{' '} 115 <InlineLinkText 116 label={_(msg`Confirm your location`)} 117 {...createStaticClick(() => { 118 locationControl.open() 119 })}> 120 Tap here to confirm your location. 121 </InlineLinkText>{' '} 122 </Trans> 123 </Text> 124 125 <DeviceLocationRequestDialog 126 control={locationControl} 127 onLocationAcquired={props => { 128 const access = computeAgeAssuranceRegionAccess( 129 props.geolocation, 130 ) 131 if (access !== aa.Access.Full) { 132 props.disableDialogAction() 133 props.setDialogError( 134 _( 135 msg`We're sorry, but based on your device's location, you are currently located in a region that requires age assurance.`, 136 ), 137 ) 138 } else { 139 props.closeDialog(() => { 140 // set this after close! 141 setDeviceGeolocation(props.geolocation) 142 Toast.show(_(msg`Thanks! You're all set.`), { 143 type: 'success', 144 }) 145 }) 146 } 147 }} 148 /> 149 </> 150 )} 151 </View> 152 153 {isBlocked ? ( 154 <Admonition type="warning"> 155 <Trans> 156 You are currently unable to access Bluesky's Age Assurance flow. 157 Please{' '} 158 <InlineLinkText 159 label={_(msg`Contact our moderation team`)} 160 {...createStaticClick(() => { 161 appealControl.open() 162 ax.metric('ageAssurance:appealDialogOpen', {}) 163 })}> 164 contact our moderation team 165 </InlineLinkText>{' '} 166 if you believe this is an error. 167 </Trans> 168 </Admonition> 169 ) : ( 170 <> 171 <Divider /> 172 <View 173 style={[ 174 a.pt_md, 175 gtPhone 176 ? [ 177 a.flex_row_reverse, 178 a.gap_xl, 179 a.justify_between, 180 a.align_center, 181 ] 182 : [a.gap_md], 183 ]}> 184 <Button 185 label={_(msg`Verify now`)} 186 size="small" 187 variant="solid" 188 color={hasInitiated ? 'secondary' : 'primary'} 189 onPress={() => { 190 control.open() 191 ax.metric('ageAssurance:initDialogOpen', { 192 hasInitiatedPreviously: hasInitiated, 193 }) 194 }}> 195 <ButtonText> 196 {hasInitiated ? ( 197 <Trans>Verify again</Trans> 198 ) : ( 199 <Trans>Verify now</Trans> 200 )} 201 </ButtonText> 202 </Button> 203 204 {lastInitiatedAt && timeAgo && diff ? ( 205 <Text 206 style={[a.text_sm, a.italic, t.atoms.text_contrast_medium]} 207 title={i18n.date(lastInitiatedAt, { 208 dateStyle: 'medium', 209 timeStyle: 'medium', 210 })}> 211 {diff.value === 0 ? ( 212 <Trans>Last initiated just now</Trans> 213 ) : ( 214 <Trans>Last initiated {timeAgo} ago</Trans> 215 )} 216 </Text> 217 ) : ( 218 <Text 219 style={[a.text_sm, a.italic, t.atoms.text_contrast_medium]}> 220 <Trans>Age assurance only takes a few minutes</Trans> 221 </Text> 222 )} 223 </View> 224 </> 225 )} 226 </View> 227 </View> 228 </> 229 ) 230}