Bluesky app fork with some witchin' additions 馃挮
0
fork

Configure Feed

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

at post-text-option 107 lines 3.3 kB view raw
1import {useMemo} from 'react' 2import { 3 ageAssuranceRuleIDs as ids, 4 type AppBskyAgeassuranceDefs, 5 getAgeAssuranceRegionConfig, 6 type ModerationPrefs, 7} from '@atproto/api' 8 9import {getAge} from '#/lib/strings/time' 10import {DEFAULT_LOGGED_OUT_LABEL_PREFERENCES} from '#/state/queries/preferences/moderation' 11import {useAgeAssuranceDataContext} from '#/ageAssurance/data' 12import {AgeAssuranceAccess} from '#/ageAssurance/types' 13import {type Geolocation, useGeolocation} from '#/geolocation' 14 15const DEFAULT_MIN_AGE = 13 16 17/** 18 * Get age assurance region config based on geolocation, with fallback to 19 * app defaults if no region config is found. 20 * 21 * See {@link getAgeAssuranceRegionConfig} for the generic option, which can 22 * return undefined if the geolocation does not match any AA region. 23 */ 24export function getAgeAssuranceRegionConfigWithFallback( 25 config: AppBskyAgeassuranceDefs.Config, 26 geolocation: Geolocation, 27): AppBskyAgeassuranceDefs.ConfigRegion { 28 const region = getAgeAssuranceRegionConfig(config, { 29 countryCode: geolocation.countryCode ?? '', 30 regionCode: geolocation.regionCode, 31 }) 32 33 return ( 34 region || { 35 countryCode: '*', 36 regionCode: undefined, 37 rules: [ 38 { 39 $type: ids.IfDeclaredOverAge, 40 age: DEFAULT_MIN_AGE, 41 access: AgeAssuranceAccess.Full, 42 }, 43 { 44 $type: ids.Default, 45 access: AgeAssuranceAccess.None, 46 }, 47 ], 48 } 49 ) 50} 51 52/** 53 * Hook to get the age assurance region config based on current geolocation. 54 * Does not fall-back to our app defaults. If no config is found, returns 55 * undefined, which indicates no regional age assurance rules apply. 56 */ 57export function useAgeAssuranceRegionConfig() { 58 const geolocation = useGeolocation() 59 const {config} = useAgeAssuranceDataContext() 60 return useMemo(() => { 61 if (!config) return 62 // use generic helper, we want to potentially return undefined 63 return getAgeAssuranceRegionConfig(config, { 64 countryCode: geolocation.countryCode ?? '', 65 regionCode: geolocation.regionCode, 66 }) 67 }, [config, geolocation]) 68} 69 70/** 71 * Some users may have erroneously set their birth date to the current date 72 * if one wasn't set on their account. We previously didn't do validation on 73 * the bday dialog, and it defaulted to the current date. This bug _has_ been 74 * seen in production, so we need to check for it where possible. 75 */ 76export function isLegacyBirthdateBug(birthDate: string) { 77 return ['2025', '2024', '2023'].includes((birthDate || '').slice(0, 4)) 78} 79 80/** 81 * Returns whether the user is under the minimum age required to use the app. 82 * This applies to all regions. 83 */ 84export function isUserUnderMinimumAge(birthDate: string) { 85 return getAge(new Date(birthDate)) < DEFAULT_MIN_AGE 86} 87 88export function isUserUnderAdultAge(birthDate: string) { 89 return getAge(new Date(birthDate)) < 18 90} 91 92export function getBirthdateStringFromAge(age: number) { 93 const today = new Date() 94 return new Date( 95 today.getFullYear() - age, 96 today.getMonth(), 97 today.getDate() - 1, // set to day before to ensure age is reached 98 ).toISOString() 99} 100 101export const makeAgeRestrictedModerationPrefs = ( 102 prefs: ModerationPrefs, 103): ModerationPrefs => ({ 104 ...prefs, 105 adultContentEnabled: false, 106 labels: DEFAULT_LOGGED_OUT_LABEL_PREFERENCES, 107})