Add derived flags, add back disabled adult content for users under 18

This commit is contained in:
Eric Bailey
2025-12-04 16:18:00 -06:00
parent c4aef9f668
commit 3dee9e75f9
3 changed files with 61 additions and 11 deletions
+25 -5
View File
@@ -3,6 +3,7 @@ import {createContext, useCallback, useContext, useEffect, useMemo} from 'react'
import {useGetAndRegisterPushToken} from '#/lib/notifications/notifications' import {useGetAndRegisterPushToken} from '#/lib/notifications/notifications'
import {Provider as RedirectOverlayProvider} from '#/ageAssurance/components/RedirectOverlay' import {Provider as RedirectOverlayProvider} from '#/ageAssurance/components/RedirectOverlay'
import {AgeAssuranceDataProvider} from '#/ageAssurance/data' import {AgeAssuranceDataProvider} from '#/ageAssurance/data'
import {useAgeAssuranceDataContext} from '#/ageAssurance/data'
import {logger} from '#/ageAssurance/logger' import {logger} from '#/ageAssurance/logger'
import { import {
useAgeAssuranceState, useAgeAssuranceState,
@@ -13,6 +14,7 @@ import {
type AgeAssuranceState, type AgeAssuranceState,
AgeAssuranceStatus, AgeAssuranceStatus,
} from '#/ageAssurance/types' } from '#/ageAssurance/types'
import {isUserUnderAdultAge} from '#/ageAssurance/util'
export { export {
prefetchConfig as prefetchAgeAssuranceConfig, prefetchConfig as prefetchAgeAssuranceConfig,
@@ -27,6 +29,10 @@ const AgeAssuranceStateContext = createContext<{
Access: typeof AgeAssuranceAccess Access: typeof AgeAssuranceAccess
Status: typeof AgeAssuranceStatus Status: typeof AgeAssuranceStatus
state: AgeAssuranceState state: AgeAssuranceState
flags: {
adultContentDisabled: boolean
chatDisabled: boolean
}
}>({ }>({
Access: AgeAssuranceAccess, Access: AgeAssuranceAccess,
Status: AgeAssuranceStatus, Status: AgeAssuranceStatus,
@@ -35,6 +41,10 @@ const AgeAssuranceStateContext = createContext<{
status: AgeAssuranceStatus.Unknown, status: AgeAssuranceStatus.Unknown,
access: AgeAssuranceAccess.Full, access: AgeAssuranceAccess.Full,
}, },
flags: {
adultContentDisabled: false,
chatDisabled: false,
},
}) })
/** /**
@@ -58,6 +68,7 @@ export function Provider({children}: {children: React.ReactNode}) {
function InnerProvider({children}: {children: React.ReactNode}) { function InnerProvider({children}: {children: React.ReactNode}) {
const state = useAgeAssuranceState() const state = useAgeAssuranceState()
const {data} = useAgeAssuranceDataContext()
const getAndRegisterPushToken = useGetAndRegisterPushToken() const getAndRegisterPushToken = useGetAndRegisterPushToken()
const handleAccessUpdate = useCallback( const handleAccessUpdate = useCallback(
@@ -76,14 +87,23 @@ function InnerProvider({children}: {children: React.ReactNode}) {
return ( return (
<AgeAssuranceStateContext.Provider <AgeAssuranceStateContext.Provider
value={useMemo( value={useMemo(() => {
() => ({ const chatDisabled = state.access !== AgeAssuranceAccess.Full
const isUnderage = data?.birthdate
? isUserUnderAdultAge(data.birthdate)
: true
const adultContentDisabled =
state.access !== AgeAssuranceAccess.Full || isUnderage
return {
Access: AgeAssuranceAccess, Access: AgeAssuranceAccess,
Status: AgeAssuranceStatus, Status: AgeAssuranceStatus,
state, state,
}), flags: {
[state], adultContentDisabled,
)}> chatDisabled,
},
}
}, [state, data])}>
{children} {children}
</AgeAssuranceStateContext.Provider> </AgeAssuranceStateContext.Provider>
) )
+4
View File
@@ -82,3 +82,7 @@ export function isLegacyBirthdateBug(birthDate: string) {
export function isUserUnderMinimumAge(birthDate: string) { export function isUserUnderMinimumAge(birthDate: string) {
return getAge(new Date(birthDate)) < DEFAULT_MIN_AGE return getAge(new Date(birthDate)) < DEFAULT_MIN_AGE
} }
export function isUserUnderAdultAge(birthDate: string) {
return getAge(new Date(birthDate)) < 18
}
+32 -6
View File
@@ -12,6 +12,7 @@ import {
} from '#/lib/routes/types' } from '#/lib/routes/types'
import {logger} from '#/logger' import {logger} from '#/logger'
import {isIOS} from '#/platform/detection' import {isIOS} from '#/platform/detection'
import {useIsBirthdateUpdateAllowed} from '#/state/birthdate'
import { import {
useMyLabelersQuery, useMyLabelersQuery,
usePreferencesQuery, usePreferencesQuery,
@@ -21,6 +22,7 @@ import {
import {isNonConfigurableModerationAuthority} from '#/state/session/additional-moderation-authorities' import {isNonConfigurableModerationAuthority} from '#/state/session/additional-moderation-authorities'
import {useSetMinimalShellMode} from '#/state/shell' import {useSetMinimalShellMode} from '#/state/shell'
import {atoms as a, useBreakpoints, useTheme, type ViewStyleProp} from '#/alf' import {atoms as a, useBreakpoints, useTheme, type ViewStyleProp} from '#/alf'
import {Admonition} from '#/components/Admonition'
import {AgeAssuranceAdmonition} from '#/components/ageAssurance/AgeAssuranceAdmonition' import {AgeAssuranceAdmonition} from '#/components/ageAssurance/AgeAssuranceAdmonition'
import {Button} from '#/components/Button' import {Button} from '#/components/Button'
import {useGlobalDialogsControlContext} from '#/components/dialogs/Context' import {useGlobalDialogsControlContext} from '#/components/dialogs/Context'
@@ -164,6 +166,7 @@ export function ModerationScreenInner({
error: labelersError, error: labelersError,
} = useMyLabelersQuery() } = useMyLabelersQuery()
const aa = useAgeAssurance() const aa = useAgeAssurance()
const isBirthdateUpdateAllowed = useIsBirthdateUpdateAllowed()
useFocusEffect( useFocusEffect(
useCallback(() => { useCallback(() => {
@@ -173,10 +176,17 @@ export function ModerationScreenInner({
const {mutateAsync: setAdultContentPref, variables: optimisticAdultContent} = const {mutateAsync: setAdultContentPref, variables: optimisticAdultContent} =
usePreferencesSetAdultContentMutation() usePreferencesSetAdultContentMutation()
const adultContentEnabled = !!( let adultContentEnabled = !!(
(optimisticAdultContent && optimisticAdultContent.enabled) || (optimisticAdultContent && optimisticAdultContent.enabled) ||
(!optimisticAdultContent && preferences.moderationPrefs.adultContentEnabled) (!optimisticAdultContent && preferences.moderationPrefs.adultContentEnabled)
) )
const adultContentUIDisabledOnIOS = isIOS && !adultContentEnabled
let adultContentUIDisabled = adultContentUIDisabledOnIOS
if (aa.flags.adultContentDisabled) {
adultContentEnabled = false
adultContentUIDisabled = true
}
const onToggleAdultContentEnabled = useCallback( const onToggleAdultContentEnabled = useCallback(
async (selected: boolean) => { async (selected: boolean) => {
@@ -193,10 +203,26 @@ export function ModerationScreenInner({
[setAdultContentPref], [setAdultContentPref],
) )
const disabledOnIOS = isIOS && !adultContentEnabled
return ( return (
<View style={[a.pt_2xl, a.px_lg, gtMobile && a.px_2xl]}> <View style={[a.pt_2xl, a.px_lg, gtMobile && a.px_2xl]}>
{aa.flags.adultContentDisabled && isBirthdateUpdateAllowed && (
<View style={[a.pb_2xl]}>
<Admonition type="tip" style={[a.pb_md]}>
<Trans>
Your declared age is under 18. Some settings below may be
disabled. If this was a mistake, you may edit your birthdate in
your{' '}
<InlineLinkText
to="/settings/account"
label={_(msg`Go to account settings`)}>
account settings
</InlineLinkText>
.
</Trans>
</Admonition>
</View>
)}
<Text <Text
style={[ style={[
a.text_md, a.text_md,
@@ -339,14 +365,14 @@ export function ModerationScreenInner({
a.flex_row, a.flex_row,
a.align_center, a.align_center,
a.justify_between, a.justify_between,
disabledOnIOS && {opacity: 0.5}, adultContentUIDisabled && {opacity: 0.5},
]}> ]}>
<Text style={[a.font_semi_bold, t.atoms.text_contrast_high]}> <Text style={[a.font_semi_bold, t.atoms.text_contrast_high]}>
<Trans>Enable adult content</Trans> <Trans>Enable adult content</Trans>
</Text> </Text>
<Toggle.Item <Toggle.Item
label={_(msg`Toggle to enable or disable adult content`)} label={_(msg`Toggle to enable or disable adult content`)}
disabled={disabledOnIOS} disabled={adultContentUIDisabled}
name="adultContent" name="adultContent"
value={adultContentEnabled} value={adultContentEnabled}
onChange={onToggleAdultContentEnabled}> onChange={onToggleAdultContentEnabled}>
@@ -362,7 +388,7 @@ export function ModerationScreenInner({
</View> </View>
</Toggle.Item> </Toggle.Item>
</View> </View>
{disabledOnIOS && ( {adultContentUIDisabledOnIOS && (
<View style={[a.pb_lg, a.px_lg]}> <View style={[a.pb_lg, a.px_lg]}>
<Text> <Text>
<Trans> <Trans>