Checkpoint: cleanup
This commit is contained in:
@@ -20,11 +20,11 @@ import {createStaticClick, InlineLinkText} from '#/components/Link'
|
||||
import {Text} from '#/components/Typography'
|
||||
|
||||
export function AgeAssuranceAccountCard({style}: ViewStyleProp & {}) {
|
||||
const {isLoaded, assurance, declaredAge} = useAgeInfo()
|
||||
const {isLoaded, mustCompleteAgeAssurance, isUnderage} = useAgeInfo()
|
||||
|
||||
if (!isLoaded) return null
|
||||
if (declaredAge && declaredAge < 18) return null
|
||||
if (!assurance.isAgeRestricted) return null
|
||||
if (isUnderage) return null
|
||||
if (!mustCompleteAgeAssurance) return null
|
||||
|
||||
return <Inner style={style} />
|
||||
}
|
||||
|
||||
@@ -15,11 +15,11 @@ export function AgeAssuranceAdmonition({
|
||||
style,
|
||||
}: ViewStyleProp & {children: React.ReactNode}) {
|
||||
const control = useDialogControl()
|
||||
const {isLoaded, isUnderage, assurance} = useAgeInfo()
|
||||
const {isLoaded, isUnderage, mustCompleteAgeAssurance} = useAgeInfo()
|
||||
|
||||
if (!isLoaded) return null
|
||||
if (isUnderage) return null
|
||||
if (!assurance.isAgeRestricted) return null
|
||||
if (!mustCompleteAgeAssurance) return null
|
||||
|
||||
return (
|
||||
<Inner style={style} control={control}>
|
||||
|
||||
@@ -12,7 +12,8 @@ import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times'
|
||||
|
||||
export function AgeAssuranceDismissableNotice({style}: ViewStyleProp & {}) {
|
||||
const {_} = useLingui()
|
||||
const {isLoaded, isUnderage, assurance} = useAgeInfo()
|
||||
const {isLoaded, isUnderage, mustCompleteAgeAssurance, assurance} =
|
||||
useAgeInfo()
|
||||
const {nux} = useNux(Nux.AgeAssuranceDismissableNotice)
|
||||
const copy = useAgeAssuranceCopy()
|
||||
const {mutate: save, variables} = useSaveNux()
|
||||
@@ -20,7 +21,7 @@ export function AgeAssuranceDismissableNotice({style}: ViewStyleProp & {}) {
|
||||
|
||||
if (!isLoaded) return null
|
||||
if (isUnderage) return null
|
||||
if (!assurance.isAgeRestricted) return null
|
||||
if (!mustCompleteAgeAssurance) return null
|
||||
if (assurance.lastInitiatedAt) return null
|
||||
if (hidden) return null
|
||||
if (nux && nux.completed) return null
|
||||
|
||||
@@ -24,7 +24,7 @@ export function AgeRestrictedScreen({
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const copy = useAgeAssuranceCopy()
|
||||
const {isLoaded, assurance} = useAgeInfo()
|
||||
const {isLoaded, mustCompleteAgeAssurance} = useAgeInfo()
|
||||
|
||||
if (!isLoaded) {
|
||||
return (
|
||||
@@ -39,7 +39,7 @@ export function AgeRestrictedScreen({
|
||||
</Layout.Screen>
|
||||
)
|
||||
}
|
||||
if (!assurance.isAgeRestricted) return children
|
||||
if (!mustCompleteAgeAssurance) return children
|
||||
|
||||
return (
|
||||
<Layout.Screen>
|
||||
|
||||
@@ -9,6 +9,7 @@ import {PUBLIC_APPVIEW_DID, PUBLIC_STAGING_APPVIEW_DID} from '#/lib/constants'
|
||||
import {logger as notyLogger} from '#/lib/notifications/util'
|
||||
import {isNative} from '#/platform/detection'
|
||||
import {useAgeAssuranceContext} from '#/state/ageAssurance'
|
||||
import {useMustCompleteAgeAssurance} from '#/state/ageAssurance/useMustCompleteAgeAssurance'
|
||||
import {type SessionAccount, useAgent, useSession} from '#/state/session'
|
||||
import BackgroundNotificationHandler from '#/../modules/expo-background-notification-handler'
|
||||
|
||||
@@ -122,7 +123,7 @@ async function getPushToken() {
|
||||
* @see https://github.com/bluesky-social/social-app/pull/4467
|
||||
*/
|
||||
export function useGetAndRegisterPushToken() {
|
||||
const {isAgeRestricted} = useAgeAssuranceContext()
|
||||
const mustCompleteAgeAssurance = useMustCompleteAgeAssurance()
|
||||
const registerPushToken = useRegisterPushToken()
|
||||
return useCallback(
|
||||
async ({
|
||||
@@ -149,13 +150,13 @@ export function useGetAndRegisterPushToken() {
|
||||
*/
|
||||
registerPushToken({
|
||||
token,
|
||||
isAgeRestricted: isAgeRestrictedOverride ?? isAgeRestricted,
|
||||
isAgeRestricted: isAgeRestrictedOverride ?? mustCompleteAgeAssurance,
|
||||
})
|
||||
}
|
||||
|
||||
return token
|
||||
},
|
||||
[registerPushToken, isAgeRestricted],
|
||||
[registerPushToken, mustCompleteAgeAssurance],
|
||||
)
|
||||
}
|
||||
|
||||
@@ -170,8 +171,8 @@ export function useNotificationsRegistration() {
|
||||
const {currentAccount} = useSession()
|
||||
const registerPushToken = useRegisterPushToken()
|
||||
const getAndRegisterPushToken = useGetAndRegisterPushToken()
|
||||
const {isLoaded: isAgeAssuranceLoaded, isAgeRestricted} =
|
||||
useAgeAssuranceContext()
|
||||
const {isLoaded: isAgeAssuranceLoaded} = useAgeAssuranceContext()
|
||||
const mustCompleteAgeAssurance = useMustCompleteAgeAssurance()
|
||||
|
||||
useEffect(() => {
|
||||
/**
|
||||
@@ -200,7 +201,7 @@ export function useNotificationsRegistration() {
|
||||
* @see https://docs.expo.dev/versions/latest/sdk/notifications/#addpushtokenlistenerlistener
|
||||
*/
|
||||
const subscription = Notifications.addPushTokenListener(async token => {
|
||||
registerPushToken({token, isAgeRestricted})
|
||||
registerPushToken({token, isAgeRestricted: mustCompleteAgeAssurance})
|
||||
notyLogger.debug(`addPushTokenListener callback`, {token})
|
||||
})
|
||||
|
||||
@@ -212,7 +213,7 @@ export function useNotificationsRegistration() {
|
||||
getAndRegisterPushToken,
|
||||
registerPushToken,
|
||||
isAgeAssuranceLoaded,
|
||||
isAgeRestricted,
|
||||
mustCompleteAgeAssurance,
|
||||
])
|
||||
}
|
||||
|
||||
|
||||
@@ -160,7 +160,7 @@ export function ModerationScreenInner({
|
||||
data: labelers,
|
||||
error: labelersError,
|
||||
} = useMyLabelersQuery()
|
||||
const {declaredAge, isUnderage, assurance: ageAssurance} = useAgeInfo()
|
||||
const {declaredAge, isUnderage, mustCompleteAgeAssurance} = useAgeInfo()
|
||||
|
||||
useFocusEffect(
|
||||
useCallback(() => {
|
||||
@@ -316,7 +316,7 @@ export function ModerationScreenInner({
|
||||
</AgeAssuranceAdmonition>
|
||||
|
||||
<View style={[a.gap_md]}>
|
||||
{declaredAge === undefined && ageAssurance.isAgeRestricted && (
|
||||
{declaredAge === undefined && (
|
||||
<>
|
||||
<Button
|
||||
label={_(msg`Confirm your birthdate`)}
|
||||
@@ -345,7 +345,7 @@ export function ModerationScreenInner({
|
||||
a.overflow_hidden,
|
||||
t.atoms.bg_contrast_25,
|
||||
]}>
|
||||
{!isUnderage && (
|
||||
{!isUnderage && !mustCompleteAgeAssurance && (
|
||||
<>
|
||||
<View
|
||||
style={[
|
||||
@@ -361,7 +361,7 @@ export function ModerationScreenInner({
|
||||
</Text>
|
||||
<Toggle.Item
|
||||
label={_(msg`Toggle to enable or disable adult content`)}
|
||||
disabled={disabledOnIOS || ageAssurance.isAgeRestricted}
|
||||
disabled={disabledOnIOS}
|
||||
name="adultContent"
|
||||
value={adultContentEnabled}
|
||||
onChange={onToggleAdultContentEnabled}>
|
||||
@@ -377,7 +377,7 @@ export function ModerationScreenInner({
|
||||
</View>
|
||||
</Toggle.Item>
|
||||
</View>
|
||||
{disabledOnIOS && !ageAssurance.isAgeRestricted && (
|
||||
{disabledOnIOS && (
|
||||
<View style={[a.pb_lg, a.px_lg]}>
|
||||
<Text>
|
||||
<Trans>
|
||||
@@ -414,7 +414,7 @@ export function ModerationScreenInner({
|
||||
</>
|
||||
)}
|
||||
<GlobalLabelPreference
|
||||
disabled={ageAssurance.isAgeRestricted}
|
||||
disabled={isUnderage || mustCompleteAgeAssurance}
|
||||
labelDefinition={LABELS.nudity}
|
||||
/>
|
||||
</View>
|
||||
|
||||
@@ -55,7 +55,7 @@ export function Provider({children}: {children: React.ReactNode}) {
|
||||
enabled: true,
|
||||
queryKey: createAgeAssuranceQueryKey(agent.session?.did ?? 'never'),
|
||||
staleTime: STALE.MINUTES.ONE,
|
||||
refetchOnWindowFocus: true,
|
||||
refetchOnWindowFocus: geolocation?.isAgeRestrictedGeo === true,
|
||||
async queryFn() {
|
||||
if (!agent.session) return null
|
||||
|
||||
@@ -68,7 +68,7 @@ export function Provider({children}: {children: React.ReactNode}) {
|
||||
// (() => ({
|
||||
// data: {
|
||||
// lastInitiatedAt: undefined,//new Date().toISOString(),
|
||||
// status: 'unknown',
|
||||
// status: 'pending',
|
||||
// } as AppBskyUnspeccedDefs.AgeAssuranceState,
|
||||
// }))(),
|
||||
// )
|
||||
|
||||
@@ -1,25 +1,44 @@
|
||||
import {useMemo} from 'react'
|
||||
|
||||
import {Logger} from '#/logger'
|
||||
import {useAgeAssuranceContext} from '#/state/ageAssurance'
|
||||
import {useMustCompleteAgeAssurance} from '#/state/ageAssurance/useMustCompleteAgeAssurance'
|
||||
import {usePreferencesQuery} from '#/state/queries/preferences'
|
||||
|
||||
const logger = Logger.create(Logger.Context.AgeAssurance)
|
||||
|
||||
type AgeInfo = {
|
||||
isLoaded: boolean
|
||||
declaredAge: number | undefined
|
||||
isUnderage: boolean
|
||||
mustCompleteAgeAssurance: boolean
|
||||
assurance: ReturnType<typeof useAgeAssuranceContext>
|
||||
}
|
||||
|
||||
/**
|
||||
* Computed age information based on age assurance status and the user's
|
||||
* declared age. Use this instead of {@link useAgeAssuranceContext} to get a
|
||||
* more user-friendly interface.
|
||||
*/
|
||||
export function useAgeInfo() {
|
||||
export function useAgeInfo(): AgeInfo {
|
||||
const mustCompleteAgeAssurance = useMustCompleteAgeAssurance()
|
||||
const ctx = useAgeAssuranceContext()
|
||||
const {isFetched: preferencesLoaded, data: preferences} =
|
||||
usePreferencesQuery()
|
||||
const declaredAge = useMemo(() => preferences?.userAge, [preferences])
|
||||
const declaredAge = preferences?.userAge
|
||||
|
||||
return useMemo(() => {
|
||||
return {
|
||||
isLoaded: ctx.isLoaded && preferencesLoaded,
|
||||
const isLoaded = ctx.isLoaded && preferencesLoaded
|
||||
const isUnderage = (declaredAge || 0) < 18
|
||||
const info: AgeInfo = {
|
||||
isLoaded,
|
||||
declaredAge,
|
||||
isUnderage: ctx.isAgeRestricted && (declaredAge || 0) < 18,
|
||||
isUnderage,
|
||||
mustCompleteAgeAssurance,
|
||||
|
||||
assurance: ctx,
|
||||
}
|
||||
}, [ctx, preferencesLoaded, declaredAge])
|
||||
logger.debug(`useAgeInfo`, info)
|
||||
return info
|
||||
}, [ctx, preferencesLoaded, declaredAge, mustCompleteAgeAssurance])
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
import {useCallback} from 'react'
|
||||
import {type ModerationPrefs} from '@atproto/api'
|
||||
|
||||
import {useAgeAssuranceContext} from '#/state/ageAssurance'
|
||||
import {AGE_RESTRICTED_MODERATION_PREFS} from '#/state/ageAssurance/const'
|
||||
|
||||
/**
|
||||
* Hook to conditionally apply age-restricted moderation preferences, if
|
||||
* needed. If not needed, the mod prefs passed to the callback will be used.
|
||||
*/
|
||||
export function useMaybeApplyAgeRestrictedModerationPrefs() {
|
||||
const state = useAgeAssuranceContext()
|
||||
return useCallback(
|
||||
(prev: ModerationPrefs) => {
|
||||
if (state.isAgeRestricted) {
|
||||
return AGE_RESTRICTED_MODERATION_PREFS
|
||||
}
|
||||
|
||||
return prev
|
||||
},
|
||||
[state],
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import {useMemo} from 'react'
|
||||
|
||||
import {useGate} from '#/lib/statsig/statsig'
|
||||
import {useAgeAssuranceContext} from '#/state/ageAssurance'
|
||||
import {useGeolocation} from '#/state/geolocation'
|
||||
|
||||
export function useMustCompleteAgeAssurance() {
|
||||
const gate = useGate()
|
||||
const {geolocation} = useGeolocation()
|
||||
const {isLoaded, status: ageAssuranceStatus} = useAgeAssuranceContext()
|
||||
return useMemo(() => {
|
||||
if (!gate('age_assurance')) return false
|
||||
if (!geolocation?.isAgeRestrictedGeo) return false
|
||||
if (!isLoaded) return false
|
||||
return ageAssuranceStatus !== 'assured'
|
||||
}, [isLoaded, gate, geolocation, ageAssuranceStatus])
|
||||
}
|
||||
@@ -10,7 +10,8 @@ import {PROD_DEFAULT_FEED} from '#/lib/constants'
|
||||
import {replaceEqualDeep} from '#/lib/functions'
|
||||
import {getAge} from '#/lib/strings/time'
|
||||
import {logger} from '#/logger'
|
||||
import {useMaybeApplyAgeRestrictedModerationPrefs} from '#/state/ageAssurance/useMaybeApplyAgeRestrictedModerationPrefs'
|
||||
import {AGE_RESTRICTED_MODERATION_PREFS} from '#/state/ageAssurance/const'
|
||||
import {useMustCompleteAgeAssurance} from '#/state/ageAssurance/useMustCompleteAgeAssurance'
|
||||
import {STALE} from '#/state/queries'
|
||||
import {
|
||||
DEFAULT_HOME_FEED_PREFS,
|
||||
@@ -33,7 +34,7 @@ export const preferencesQueryKey = [preferencesQueryKeyRoot]
|
||||
|
||||
export function usePreferencesQuery() {
|
||||
const agent = useAgent()
|
||||
const maybeOverrideModPrefs = useMaybeApplyAgeRestrictedModerationPrefs()
|
||||
const mustCompleteAgeAssurance = useMustCompleteAgeAssurance()
|
||||
|
||||
return useQuery({
|
||||
staleTime: STALE.SECONDS.FIFTEEN,
|
||||
@@ -74,10 +75,13 @@ export function usePreferencesQuery() {
|
||||
},
|
||||
select: useCallback(
|
||||
(data: UsePreferencesQueryResponse) => {
|
||||
data.moderationPrefs = maybeOverrideModPrefs(data.moderationPrefs)
|
||||
const isUnderage = (data.userAge || 0) < 18
|
||||
if (isUnderage || mustCompleteAgeAssurance) {
|
||||
data.moderationPrefs = AGE_RESTRICTED_MODERATION_PREFS
|
||||
}
|
||||
return data
|
||||
},
|
||||
[maybeOverrideModPrefs],
|
||||
[mustCompleteAgeAssurance],
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user