forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
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 = ['twitch.tv', 'www.twitch.tv']
89export type LiveNowConfig = {
90 allowedDomains: Set<string>
91}
92export function useLiveNowConfig(): LiveNowConfig {
93 const ctx = useContext(LiveNowContext)
94 const canGoLive = useCanGoLive()
95 const {currentAccount} = useSession()
96 if (!currentAccount?.did || !canGoLive) return {allowedDomains: new Set()}
97 const vip = ctx.find(live => live.did === currentAccount.did)
98 return {
99 allowedDomains: new Set(
100 DEFAULT_LIVE_ALLOWED_DOMAINS.concat(vip ? vip.domains : []),
101 ),
102 }
103}
104
105export function useCanGoLive() {
106 const gate = useGate()
107 const {hasSession} = useSession()
108 if (!hasSession) return false
109 return IS_DEV ? true : gate('live_now_beta')
110}
111
112export function useCheckEmailConfirmed() {
113 const ctx = useContext(CheckEmailConfirmedContext)
114 if (ctx === null) {
115 throw new Error(
116 'useCheckEmailConfirmed must be used within a ServiceConfigManager',
117 )
118 }
119 return ctx
120}