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 remove-hackfix 253 lines 7.0 kB view raw
1import {useEffect, useRef, useState} from 'react' 2import {View} from 'react-native' 3import {msg, Trans} from '@lingui/macro' 4import {useLingui} from '@lingui/react' 5 6import {retry} from '#/lib/async/retry' 7import {wait} from '#/lib/async/wait' 8import {isNative} from '#/platform/detection' 9import {useAgeAssuranceAPIContext} from '#/state/ageAssurance' 10import {logger} from '#/state/ageAssurance/util' 11import {useAgent} from '#/state/session' 12import {atoms as a, useTheme, web} from '#/alf' 13import {AgeAssuranceBadge} from '#/components/ageAssurance/AgeAssuranceBadge' 14import {Button, ButtonText} from '#/components/Button' 15import * as Dialog from '#/components/Dialog' 16import {useGlobalDialogsControlContext} from '#/components/dialogs/Context' 17import {CheckThick_Stroke2_Corner0_Rounded as SuccessIcon} from '#/components/icons/Check' 18import {CircleInfo_Stroke2_Corner0_Rounded as ErrorIcon} from '#/components/icons/CircleInfo' 19import {Loader} from '#/components/Loader' 20import {Text} from '#/components/Typography' 21 22export type AgeAssuranceRedirectDialogState = { 23 result: 'success' | 'unknown' 24 actorDid: string 25} 26 27/** 28 * Validate and parse the query parameters returned from the age assurance 29 * redirect. If not valid, returns `undefined` and the dialog will not open. 30 */ 31export function parseAgeAssuranceRedirectDialogState( 32 state: { 33 result?: string 34 actorDid?: string 35 } = {}, 36): AgeAssuranceRedirectDialogState | undefined { 37 let result: AgeAssuranceRedirectDialogState['result'] = 'unknown' 38 const actorDid = state.actorDid 39 40 switch (state.result) { 41 case 'success': 42 result = 'success' 43 break 44 case 'unknown': 45 default: 46 result = 'unknown' 47 break 48 } 49 50 if (result && actorDid) { 51 return { 52 result, 53 actorDid, 54 } 55 } 56} 57 58export function useAgeAssuranceRedirectDialogControl() { 59 return useGlobalDialogsControlContext().ageAssuranceRedirectDialogControl 60} 61 62export function AgeAssuranceRedirectDialog() { 63 const {_} = useLingui() 64 const control = useAgeAssuranceRedirectDialogControl() 65 66 // TODO for testing 67 // Dialog.useAutoOpen(control.control, 3e3) 68 69 return ( 70 <Dialog.Outer control={control.control} onClose={() => control.clear()}> 71 <Dialog.Handle /> 72 73 <Dialog.ScrollableInner 74 label={_(msg`Verifying your age assurance status`)} 75 style={[web({maxWidth: 400})]}> 76 <Inner optimisticState={control.value} /> 77 </Dialog.ScrollableInner> 78 </Dialog.Outer> 79 ) 80} 81 82export function Inner({}: {optimisticState?: AgeAssuranceRedirectDialogState}) { 83 const t = useTheme() 84 const {_} = useLingui() 85 const agent = useAgent() 86 const polling = useRef(false) 87 const unmounted = useRef(false) 88 const control = useAgeAssuranceRedirectDialogControl() 89 const [error, setError] = useState(false) 90 const [success, setSuccess] = useState(false) 91 const {refetch: refreshAgeAssuranceState} = useAgeAssuranceAPIContext() 92 93 useEffect(() => { 94 if (polling.current) return 95 96 polling.current = true 97 98 logger.metric('ageAssurance:redirectDialogOpen', {}) 99 100 wait( 101 3e3, 102 retry( 103 5, 104 () => true, 105 async () => { 106 if (!agent.session) return 107 if (unmounted.current) return 108 109 const {data} = await agent.app.bsky.unspecced.getAgeAssuranceState() 110 111 if (data.status !== 'assured') { 112 throw new Error( 113 `Polling for age assurance state did not receive assured status`, 114 ) 115 } 116 117 return data 118 }, 119 1e3, 120 ), 121 ) 122 .then(async data => { 123 if (!data) return 124 if (!agent.session) return 125 if (unmounted.current) return 126 127 // success! update state 128 await refreshAgeAssuranceState() 129 130 setSuccess(true) 131 132 logger.metric('ageAssurance:redirectDialogSuccess', {}) 133 }) 134 .catch(() => { 135 if (unmounted.current) return 136 setError(true) 137 // try a refetch anyway 138 refreshAgeAssuranceState() 139 logger.metric('ageAssurance:redirectDialogFail', {}) 140 }) 141 142 return () => { 143 unmounted.current = true 144 } 145 }, [agent, control, refreshAgeAssuranceState]) 146 147 if (success) { 148 return ( 149 <> 150 <View style={[a.align_start, a.w_full]}> 151 <AgeAssuranceBadge /> 152 153 <View 154 style={[ 155 a.flex_row, 156 a.justify_between, 157 a.align_center, 158 a.gap_sm, 159 a.pt_lg, 160 a.pb_md, 161 ]}> 162 <SuccessIcon size="sm" fill={t.palette.positive_600} /> 163 <Text style={[a.text_xl, a.font_bold]}> 164 <Trans>Success</Trans> 165 </Text> 166 </View> 167 168 <Text style={[a.text_md, a.leading_snug]}> 169 <Trans> 170 We've confirmed your age assurance status. You can now close this 171 dialog. 172 </Trans> 173 </Text> 174 175 {isNative && ( 176 <View style={[a.w_full, a.pt_lg]}> 177 <Button 178 label={_(msg`Close`)} 179 size="large" 180 variant="solid" 181 color="secondary" 182 onPress={() => control.control.close()}> 183 <ButtonText> 184 <Trans>Close</Trans> 185 </ButtonText> 186 </Button> 187 </View> 188 )} 189 </View> 190 191 <Dialog.Close /> 192 </> 193 ) 194 } 195 196 return ( 197 <> 198 <View style={[a.align_start, a.w_full]}> 199 <AgeAssuranceBadge /> 200 201 <View 202 style={[ 203 a.flex_row, 204 a.justify_between, 205 a.align_center, 206 a.gap_sm, 207 a.pt_lg, 208 a.pb_md, 209 ]}> 210 {error && <ErrorIcon size="md" fill={t.palette.negative_500} />} 211 212 <Text style={[a.text_xl, a.font_bold]}> 213 {error ? <Trans>Connection issue</Trans> : <Trans>Verifying</Trans>} 214 </Text> 215 216 {!error && <Loader size="md" />} 217 </View> 218 219 <Text style={[a.text_md, a.leading_snug]}> 220 {error ? ( 221 <Trans> 222 We were unable to receive the verification due to a connection 223 issue. It may arrive later. If it does, your account will update 224 automatically. 225 </Trans> 226 ) : ( 227 <Trans> 228 We're confirming your age assurance status with our servers. This 229 should only take a few seconds. 230 </Trans> 231 )} 232 </Text> 233 234 {error && isNative && ( 235 <View style={[a.w_full, a.pt_lg]}> 236 <Button 237 label={_(msg`Close`)} 238 size="large" 239 variant="solid" 240 color="secondary" 241 onPress={() => control.control.close()}> 242 <ButtonText> 243 <Trans>Close</Trans> 244 </ButtonText> 245 </Button> 246 </View> 247 )} 248 </View> 249 250 {error && <Dialog.Close />} 251 </> 252 ) 253}