Bluesky app fork with some witchin' additions 馃挮
at linkat-integration 122 lines 3.4 kB view raw
1import {createContext, useContext, useMemo} from 'react' 2 3import {useLanguagePrefs} from '#/state/preferences/languages' 4import {useServiceConfigQuery} from '#/state/queries/service-config' 5import {useSession} from '#/state/session' 6import {useAnalytics} from '#/analytics' 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 const enabled = Boolean(config?.topicsEnabled) 56 57 // update cache 58 device.set(['trendingBetaEnabled'], enabled) 59 60 return {enabled} 61 }, [isInitialLoad, config, langPrefs.contentLanguages]) 62 63 const liveNow = useMemo<LiveNowContext>(() => config?.liveNow ?? [], [config]) 64 65 // probably true, so default to true when loading 66 // if the call fails, the query will set it to false for us 67 const checkEmailConfirmed = config?.checkEmailConfirmed ?? true 68 69 return ( 70 <TrendingContext.Provider value={trending}> 71 <LiveNowContext.Provider value={liveNow}> 72 <CheckEmailConfirmedContext.Provider value={checkEmailConfirmed}> 73 {children} 74 </CheckEmailConfirmedContext.Provider> 75 </LiveNowContext.Provider> 76 </TrendingContext.Provider> 77 ) 78} 79 80export function useTrendingConfig() { 81 return useContext(TrendingContext) 82} 83 84const DEFAULT_LIVE_ALLOWED_DOMAINS = [ 85 'twitch.tv', 86 'www.twitch.tv', 87 'stream.place', 88 'bluecast.app', 89 'www.bluecast.app', 90] 91export type LiveNowConfig = { 92 allowedDomains: Set<string> 93} 94export function useLiveNowConfig(): LiveNowConfig { 95 const ctx = useContext(LiveNowContext) 96 const canGoLive = useCanGoLive() 97 const {currentAccount} = useSession() 98 if (!currentAccount?.did || !canGoLive) return {allowedDomains: new Set()} 99 const vip = ctx.find(live => live.did === currentAccount.did) 100 return { 101 allowedDomains: new Set( 102 DEFAULT_LIVE_ALLOWED_DOMAINS.concat(vip ? vip.domains : []), 103 ), 104 } 105} 106 107export function useCanGoLive() { 108 const ax = useAnalytics() 109 const {hasSession} = useSession() 110 if (!hasSession) return false 111 return IS_DEV ? true : !ax.features.enabled(ax.features.LiveNowBetaDisable) 112} 113 114export function useCheckEmailConfirmed() { 115 const ctx = useContext(CheckEmailConfirmedContext) 116 if (ctx === null) { 117 throw new Error( 118 'useCheckEmailConfirmed must be used within a ServiceConfigManager', 119 ) 120 } 121 return ctx 122}