Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

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

Age assurance tweaks (#8671)

* Refetch state while in pending status

* Add success state to redirect, just have user close, nicer experience

* Stop refetching after pending

authored by

Eric Bailey and committed by
GitHub
0995e81b 6a15679f

+78 -7
+57 -6
src/components/ageAssurance/AgeAssuranceRedirectDialog.tsx
··· 14 14 import {Button, ButtonText} from '#/components/Button' 15 15 import * as Dialog from '#/components/Dialog' 16 16 import {useGlobalDialogsControlContext} from '#/components/dialogs/Context' 17 + import {CheckThick_Stroke2_Corner0_Rounded as SuccessIcon} from '#/components/icons/Check' 17 18 import {CircleInfo_Stroke2_Corner0_Rounded as ErrorIcon} from '#/components/icons/CircleInfo' 18 19 import {Loader} from '#/components/Loader' 19 20 import {Text} from '#/components/Typography' ··· 66 67 // Dialog.useAutoOpen(control.control, 3e3) 67 68 68 69 return ( 69 - <Dialog.Outer control={control.control}> 70 + <Dialog.Outer control={control.control} onClose={() => control.clear()}> 70 71 <Dialog.Handle /> 71 72 72 73 <Dialog.ScrollableInner ··· 86 87 const unmounted = useRef(false) 87 88 const control = useAgeAssuranceRedirectDialogControl() 88 89 const [error, setError] = useState(false) 90 + const [success, setSuccess] = useState(false) 89 91 const {refetch: refreshAgeAssuranceState} = useAgeAssuranceAPIContext() 90 92 91 93 useEffect(() => { ··· 125 127 // success! update state 126 128 await refreshAgeAssuranceState() 127 129 128 - control.clear() 129 - control.control.close() 130 + setSuccess(true) 130 131 131 132 logger.metric('ageAssurance:redirectDialogSuccess', {}) 132 133 }) ··· 143 144 } 144 145 }, [agent, control, refreshAgeAssuranceState]) 145 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_heavy]}> 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 + 146 196 return ( 147 197 <> 148 198 <View style={[a.align_start, a.w_full]}> ··· 175 225 </Trans> 176 226 ) : ( 177 227 <Trans> 178 - We're confirming your status with our servers. This dialog should 179 - close in a few seconds. 228 + We're confirming your age assurance status with our servers. This 229 + should only take a few seconds. 180 230 </Trans> 181 231 )} 182 232 </Text> ··· 187 237 label={_(msg`Close`)} 188 238 size="large" 189 239 variant="solid" 190 - color="secondary"> 240 + color="secondary" 241 + onPress={() => control.control.close()}> 191 242 <ButtonText> 192 243 <Trans>Close</Trans> 193 244 </ButtonText>
+21 -1
src/state/ageAssurance/index.tsx
··· 1 - import {createContext, useContext, useMemo} from 'react' 1 + import {createContext, useContext, useMemo, useState} from 'react' 2 2 import {type AppBskyUnspeccedDefs} from '@atproto/api' 3 3 import {useQuery} from '@tanstack/react-query' 4 4 ··· 46 46 const {geolocation} = useGeolocation() 47 47 const isAgeAssuranceEnabled = useIsAgeAssuranceEnabled() 48 48 const getAndRegisterPushToken = useGetAndRegisterPushToken() 49 + const [refetchWhilePending, setRefetchWhilePending] = useState(false) 49 50 50 51 const {data, isFetched, refetch} = useQuery({ 51 52 /** ··· 56 57 * However, it only needs to run if AA is enabled. 57 58 */ 58 59 enabled: isAgeAssuranceEnabled, 60 + refetchOnWindowFocus: refetchWhilePending, 59 61 queryKey: createAgeAssuranceQueryKey(agent.session?.did ?? 'never'), 60 62 async queryFn() { 61 63 if (!agent.session) return null ··· 108 110 logger.debug(`context`, ctx) 109 111 return ctx 110 112 }, [isFetched, data, isAgeAssuranceEnabled]) 113 + 114 + if ( 115 + !!ageAssuranceContext.lastInitiatedAt && 116 + ageAssuranceContext.status === 'pending' && 117 + !refetchWhilePending 118 + ) { 119 + /* 120 + * If we have a pending state, we want to refetch on window focus to ensure 121 + * that we get the latest state when the user returns to the app. 122 + */ 123 + setRefetchWhilePending(true) 124 + } else if ( 125 + !!ageAssuranceContext.lastInitiatedAt && 126 + ageAssuranceContext.status !== 'pending' && 127 + refetchWhilePending 128 + ) { 129 + setRefetchWhilePending(false) 130 + } 111 131 112 132 const ageAssuranceAPIContext = useMemo<AgeAssuranceAPIContextType>( 113 133 () => ({