113 lines
3.0 KiB
TypeScript
113 lines
3.0 KiB
TypeScript
import {createContext, useContext, useMemo} from 'react'
|
|
import {QueryClient, useQuery} from '@tanstack/react-query'
|
|
|
|
import {useIsBskyTeam} from '#/lib/hooks/useIsBskyTeam'
|
|
import {
|
|
convertBskyAppUrlIfNeeded,
|
|
isBskyCustomFeedUrl,
|
|
makeRecordUri,
|
|
} from '#/lib/strings/url-helpers'
|
|
import {LIVE_EVENTS_URL} from '#/env'
|
|
import {useLiveEventPreferences} from '#/features/liveEvents/preferences'
|
|
import {type LiveEventsWorkerResponse} from '#/features/liveEvents/types'
|
|
import {useDevMode} from '#/storage/hooks/dev-mode'
|
|
|
|
const qc = new QueryClient()
|
|
const liveEventsQueryKey = ['live-events']
|
|
|
|
export const DEFAULT_LIVE_EVENTS = {
|
|
feeds: [],
|
|
}
|
|
|
|
async function fetchLiveEvents(): Promise<LiveEventsWorkerResponse | null> {
|
|
try {
|
|
const res = await fetch(`${LIVE_EVENTS_URL}/config`)
|
|
if (!res.ok) return null
|
|
const data = await res.json()
|
|
return data
|
|
} catch {
|
|
return null
|
|
}
|
|
}
|
|
|
|
const Context = createContext<LiveEventsWorkerResponse>(DEFAULT_LIVE_EVENTS)
|
|
|
|
export function Provider({children}: React.PropsWithChildren<{}>) {
|
|
const [isDevMode] = useDevMode()
|
|
const isBskyTeam = useIsBskyTeam()
|
|
const {data} = useQuery(
|
|
{
|
|
// keep this, prefectching handles initial load
|
|
staleTime: 1000 * 15,
|
|
queryKey: liveEventsQueryKey,
|
|
refetchInterval: 1000 * 60 * 5,
|
|
async queryFn() {
|
|
return fetchLiveEvents()
|
|
},
|
|
},
|
|
qc,
|
|
)
|
|
|
|
const ctx = useMemo(() => {
|
|
if (!data) return DEFAULT_LIVE_EVENTS
|
|
const feeds = data.feeds.filter(f => {
|
|
if (f.preview && !isBskyTeam) return false
|
|
return true
|
|
})
|
|
return {
|
|
...data,
|
|
// only one at a time for now, unless bsky team and dev mode
|
|
feeds: isBskyTeam && isDevMode ? feeds : feeds.slice(0, 1),
|
|
}
|
|
}, [data, isBskyTeam, isDevMode])
|
|
|
|
return <Context.Provider value={ctx}>{children}</Context.Provider>
|
|
}
|
|
|
|
export async function prefetchLiveEvents() {
|
|
const data = await fetchLiveEvents()
|
|
if (data) {
|
|
qc.setQueryData(liveEventsQueryKey, data)
|
|
}
|
|
}
|
|
|
|
export function useLiveEvents() {
|
|
const ctx = useContext(Context)
|
|
if (!ctx) {
|
|
throw new Error('useLiveEventsContext must be used within a Provider')
|
|
}
|
|
return ctx
|
|
}
|
|
|
|
export function useUserPreferencedLiveEvents() {
|
|
const events = useLiveEvents()
|
|
const {data, isLoading} = useLiveEventPreferences()
|
|
if (isLoading) return DEFAULT_LIVE_EVENTS
|
|
const {hideAllFeeds, hiddenFeedIds} = data
|
|
return {
|
|
...events,
|
|
feeds: hideAllFeeds
|
|
? []
|
|
: events.feeds.filter(f => {
|
|
const hidden = f?.id ? hiddenFeedIds.includes(f?.id || '') : false
|
|
return !hidden
|
|
}),
|
|
}
|
|
}
|
|
|
|
export function useActiveLiveEventFeedUris() {
|
|
const {feeds} = useLiveEvents()
|
|
|
|
return new Set(
|
|
feeds
|
|
// insurance
|
|
.filter(f => isBskyCustomFeedUrl(f.url))
|
|
.map(f => {
|
|
const uri = convertBskyAppUrlIfNeeded(f.url)
|
|
const [_0, did, _1, rkey] = uri.split('/').filter(Boolean)
|
|
const urip = makeRecordUri(did, 'app.bsky.feed.generator', rkey)
|
|
return urip.toString()
|
|
}),
|
|
)
|
|
}
|