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

Configure Feed

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

at fbd1138d97dda2df66bee13ad3ca6e83d55ebc25 124 lines 3.4 kB view raw
1import {createContext, useContext, useMemo} from 'react' 2 3import {useGate} from '#/lib/statsig/statsig' 4import {useLanguagePrefs} from '#/state/preferences/languages' 5import {useServiceConfigQuery} from '#/state/queries/service-config' 6import {useSession} from '#/state/session' 7import {IS_DEV} from '#/env' 8import {device} from '#/storage' 9 10type TrendingContext = { 11 enabled: boolean 12} 13 14type LiveNowContext = { 15 did: string 16 domains: string[] 17}[] 18 19const TrendingContext = createContext<TrendingContext>({ 20 enabled: false, 21}) 22TrendingContext.displayName = 'TrendingContext' 23 24const LiveNowContext = createContext<LiveNowContext>([]) 25LiveNowContext.displayName = 'LiveNowContext' 26 27const CheckEmailConfirmedContext = createContext<boolean | null>(null) 28 29export function Provider({children}: {children: React.ReactNode}) { 30 const langPrefs = useLanguagePrefs() 31 const {data: config, isLoading: isInitialLoad} = useServiceConfigQuery() 32 const trending = useMemo<TrendingContext>(() => { 33 if (__DEV__) { 34 return {enabled: true} 35 } 36 37 /* 38 * Only English during beta period 39 */ 40 if ( 41 !!langPrefs.contentLanguages.length && 42 !langPrefs.contentLanguages.includes('en') 43 ) { 44 return {enabled: false} 45 } 46 47 /* 48 * While loading, use cached value 49 */ 50 const cachedEnabled = device.get(['trendingBetaEnabled']) 51 if (isInitialLoad) { 52 return {enabled: Boolean(cachedEnabled)} 53 } 54 55 /* 56 * Doing an extra check here to reduce hits to statsig. If it's disabled on 57 * the server, we can exit early. 58 */ 59 const enabled = Boolean(config?.topicsEnabled) 60 61 // update cache 62 device.set(['trendingBetaEnabled'], enabled) 63 64 return {enabled} 65 }, [isInitialLoad, config, langPrefs.contentLanguages]) 66 67 const liveNow = useMemo<LiveNowContext>(() => config?.liveNow ?? [], [config]) 68 69 // probably true, so default to true when loading 70 // if the call fails, the query will set it to false for us 71 const checkEmailConfirmed = config?.checkEmailConfirmed ?? true 72 73 return ( 74 <TrendingContext.Provider value={trending}> 75 <LiveNowContext.Provider value={liveNow}> 76 <CheckEmailConfirmedContext.Provider value={checkEmailConfirmed}> 77 {children} 78 </CheckEmailConfirmedContext.Provider> 79 </LiveNowContext.Provider> 80 </TrendingContext.Provider> 81 ) 82} 83 84export function useTrendingConfig() { 85 return useContext(TrendingContext) 86} 87 88const DEFAULT_LIVE_ALLOWED_DOMAINS = [ 89 'twitch.tv', 90 'www.twitch.tv', 91 'stream.place', 92] 93export type LiveNowConfig = { 94 allowedDomains: Set<string> 95} 96export function useLiveNowConfig(): LiveNowConfig { 97 const ctx = useContext(LiveNowContext) 98 const canGoLive = useCanGoLive() 99 const {currentAccount} = useSession() 100 if (!currentAccount?.did || !canGoLive) return {allowedDomains: new Set()} 101 const vip = ctx.find(live => live.did === currentAccount.did) 102 return { 103 allowedDomains: new Set( 104 DEFAULT_LIVE_ALLOWED_DOMAINS.concat(vip ? vip.domains : []), 105 ), 106 } 107} 108 109export function useCanGoLive() { 110 const gate = useGate() 111 const {hasSession} = useSession() 112 if (!hasSession) return false 113 return IS_DEV ? true : gate('live_now_beta') 114} 115 116export function useCheckEmailConfirmed() { 117 const ctx = useContext(CheckEmailConfirmedContext) 118 if (ctx === null) { 119 throw new Error( 120 'useCheckEmailConfirmed must be used within a ServiceConfigManager', 121 ) 122 } 123 return ctx 124}