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 currentAccountAllowedHosts: Set<string>
93 defaultAllowedHosts: Set<string>
94 allowedHostsExceptionsByDid: Map<string, Set<string>>
95}
96export function useLiveNowConfig(): LiveNowConfig {
97 const ctx = useContext(LiveNowContext)
98 const canGoLive = useCanGoLive()
99 const {currentAccount} = useSession()
100 return useMemo(() => {
101 const defaultAllowedHosts = new Set(DEFAULT_LIVE_ALLOWED_DOMAINS)
102 const allowedHostsExceptionsByDid = new Map<string, Set<string>>()
103 for (const live of ctx) {
104 allowedHostsExceptionsByDid.set(
105 live.did,
106 new Set(DEFAULT_LIVE_ALLOWED_DOMAINS.concat(live.domains)),
107 )
108 }
109 if (!currentAccount?.did || !canGoLive)
110 return {
111 currentAccountAllowedHosts: new Set(),
112 defaultAllowedHosts,
113 allowedHostsExceptionsByDid,
114 }
115 const vip = ctx.find(live => live.did === currentAccount.did)
116 return {
117 currentAccountAllowedHosts: new Set(
118 DEFAULT_LIVE_ALLOWED_DOMAINS.concat(vip ? vip.domains : []),
119 ),
120 defaultAllowedHosts,
121 allowedHostsExceptionsByDid,
122 }
123 }, [ctx, currentAccount, canGoLive])
124}
125
126export function useCanGoLive() {
127 const ax = useAnalytics()
128 const {hasSession} = useSession()
129 if (!hasSession) return false
130 return IS_DEV ? true : !ax.features.enabled(ax.features.LiveNowBetaDisable)
131}
132
133export function useCheckEmailConfirmed() {
134 const ctx = useContext(CheckEmailConfirmedContext)
135 if (ctx === null) {
136 throw new Error(
137 'useCheckEmailConfirmed must be used within a ServiceConfigManager',
138 )
139 }
140 return ctx
141}