Compare commits

...

2 Commits

Author SHA1 Message Date
Eric Bailey f4f0a487e7 Update copy 2025-12-04 16:27:22 -06:00
Eric Bailey 3dee9e75f9 Add derived flags, add back disabled adult content for users under 18 2025-12-04 16:18:00 -06:00
4 changed files with 68 additions and 26 deletions
+25 -5
View File
@@ -3,6 +3,7 @@ import {createContext, useCallback, useContext, useEffect, useMemo} from 'react'
import {useGetAndRegisterPushToken} from '#/lib/notifications/notifications'
import {Provider as RedirectOverlayProvider} from '#/ageAssurance/components/RedirectOverlay'
import {AgeAssuranceDataProvider} from '#/ageAssurance/data'
import {useAgeAssuranceDataContext} from '#/ageAssurance/data'
import {logger} from '#/ageAssurance/logger'
import {
useAgeAssuranceState,
@@ -13,6 +14,7 @@ import {
type AgeAssuranceState,
AgeAssuranceStatus,
} from '#/ageAssurance/types'
import {isUserUnderAdultAge} from '#/ageAssurance/util'
export {
prefetchConfig as prefetchAgeAssuranceConfig,
@@ -27,6 +29,10 @@ const AgeAssuranceStateContext = createContext<{
Access: typeof AgeAssuranceAccess
Status: typeof AgeAssuranceStatus
state: AgeAssuranceState
flags: {
adultContentDisabled: boolean
chatDisabled: boolean
}
}>({
Access: AgeAssuranceAccess,
Status: AgeAssuranceStatus,
@@ -35,6 +41,10 @@ const AgeAssuranceStateContext = createContext<{
status: AgeAssuranceStatus.Unknown,
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}) {
const state = useAgeAssuranceState()
const {data} = useAgeAssuranceDataContext()
const getAndRegisterPushToken = useGetAndRegisterPushToken()
const handleAccessUpdate = useCallback(
@@ -76,14 +87,23 @@ function InnerProvider({children}: {children: React.ReactNode}) {
return (
<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,
Status: AgeAssuranceStatus,
state,
}),
[state],
)}>
flags: {
adultContentDisabled,
chatDisabled,
},
}
}, [state, data])}>
{children}
</AgeAssuranceStateContext.Provider>
)
+4
View File
@@ -82,3 +82,7 @@ export function isLegacyBirthdateBug(birthDate: string) {
export function isUserUnderMinimumAge(birthDate: string) {
return getAge(new Date(birthDate)) < DEFAULT_MIN_AGE
}
export function isUserUnderAdultAge(birthDate: string) {
return getAge(new Date(birthDate)) < 18
}
@@ -2,22 +2,14 @@ import {useMemo} from 'react'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useAgeAssurance} from '#/ageAssurance'
export function useAgeAssuranceCopy() {
const {_} = useLingui()
const aa = useAgeAssurance()
return useMemo(() => {
return {
notice:
aa.state.access === aa.Access.Safe
? _(
msg`Due to laws in your region, certain features on Bluesky are currently restricted until you're able to verify you're an adult.`,
)
: _(
msg`The laws in your location require you to verify you're an adult before accessing certain features on Bluesky, like adult content and direct messaging.`,
),
notice: _(
msg`Due to laws in your region, certain features on Bluesky are currently restricted until you're able to verify you're an adult.`,
),
banner: _(
msg`The laws in your location require you to verify you're an adult to access certain features. Tap to learn more.`,
),
@@ -25,5 +17,5 @@ export function useAgeAssuranceCopy() {
msg`Don't worry! All existing messages and settings are saved and will be available after you verify you're an adult.`,
),
}
}, [_, aa])
}, [_])
}
+35 -9
View File
@@ -12,6 +12,7 @@ import {
} from '#/lib/routes/types'
import {logger} from '#/logger'
import {isIOS} from '#/platform/detection'
import {useIsBirthdateUpdateAllowed} from '#/state/birthdate'
import {
useMyLabelersQuery,
usePreferencesQuery,
@@ -21,7 +22,9 @@ import {
import {isNonConfigurableModerationAuthority} from '#/state/session/additional-moderation-authorities'
import {useSetMinimalShellMode} from '#/state/shell'
import {atoms as a, useBreakpoints, useTheme, type ViewStyleProp} from '#/alf'
import {Admonition} from '#/components/Admonition'
import {AgeAssuranceAdmonition} from '#/components/ageAssurance/AgeAssuranceAdmonition'
import {useAgeAssuranceCopy} from '#/components/ageAssurance/useAgeAssuranceCopy'
import {Button} from '#/components/Button'
import {useGlobalDialogsControlContext} from '#/components/dialogs/Context'
import {Divider} from '#/components/Divider'
@@ -164,6 +167,8 @@ export function ModerationScreenInner({
error: labelersError,
} = useMyLabelersQuery()
const aa = useAgeAssurance()
const isBirthdateUpdateAllowed = useIsBirthdateUpdateAllowed()
const aaCopy = useAgeAssuranceCopy()
useFocusEffect(
useCallback(() => {
@@ -173,10 +178,17 @@ export function ModerationScreenInner({
const {mutateAsync: setAdultContentPref, variables: optimisticAdultContent} =
usePreferencesSetAdultContentMutation()
const adultContentEnabled = !!(
let adultContentEnabled = !!(
(optimisticAdultContent && optimisticAdultContent.enabled) ||
(!optimisticAdultContent && preferences.moderationPrefs.adultContentEnabled)
)
const adultContentUIDisabledOnIOS = isIOS && !adultContentEnabled
let adultContentUIDisabled = adultContentUIDisabledOnIOS
if (aa.flags.adultContentDisabled) {
adultContentEnabled = false
adultContentUIDisabled = true
}
const onToggleAdultContentEnabled = useCallback(
async (selected: boolean) => {
@@ -193,10 +205,26 @@ export function ModerationScreenInner({
[setAdultContentPref],
)
const disabledOnIOS = isIOS && !adultContentEnabled
return (
<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
style={[
a.text_md,
@@ -317,9 +345,7 @@ export function ModerationScreenInner({
</Text>
<AgeAssuranceAdmonition style={[a.pb_md]}>
<Trans>
You must complete age assurance in order to access content filters.
</Trans>
{aaCopy.notice}
</AgeAssuranceAdmonition>
<View style={[a.gap_md]}>
@@ -339,14 +365,14 @@ export function ModerationScreenInner({
a.flex_row,
a.align_center,
a.justify_between,
disabledOnIOS && {opacity: 0.5},
adultContentUIDisabled && {opacity: 0.5},
]}>
<Text style={[a.font_semi_bold, t.atoms.text_contrast_high]}>
<Trans>Enable adult content</Trans>
</Text>
<Toggle.Item
label={_(msg`Toggle to enable or disable adult content`)}
disabled={disabledOnIOS}
disabled={adultContentUIDisabled}
name="adultContent"
value={adultContentEnabled}
onChange={onToggleAdultContentEnabled}>
@@ -362,7 +388,7 @@ export function ModerationScreenInner({
</View>
</Toggle.Item>
</View>
{disabledOnIOS && (
{adultContentUIDisabledOnIOS && (
<View style={[a.pb_lg, a.px_lg]}>
<Text>
<Trans>