forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
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}