Bluesky app fork with some witchin' additions 馃挮
at 5ee667f307bc459ba53cdaabdad00a0ea1ee6846 87 lines 2.1 kB view raw
1import {createContext, useContext} from 'react' 2import {QueryClient, useQuery} from '@tanstack/react-query' 3 4import {APP_CONFIG_URL} from '#/env' 5 6const qc = new QueryClient() 7const appConfigQueryKey = ['app-config'] 8 9/** 10 * Matches the types defined in our `app-config` worker 11 */ 12type AppConfigResponse = { 13 liveNow: { 14 allow: string[] 15 exceptions: { 16 did: string 17 allow: string[] 18 }[] 19 } 20} 21 22export const DEFAULT_APP_CONFIG_RESPONSE: AppConfigResponse = { 23 liveNow: { 24 allow: [], 25 exceptions: [], 26 }, 27} 28 29let fetchAppConfigPromise: Promise<AppConfigResponse> | undefined 30 31async function fetchAppConfig(): Promise<AppConfigResponse | null> { 32 try { 33 if (!fetchAppConfigPromise) { 34 fetchAppConfigPromise = (async () => { 35 const r = await fetch(`${APP_CONFIG_URL}/config`) 36 if (!r.ok) throw new Error(await r.text()) 37 const data = await r.json() 38 return data 39 })() 40 } 41 return await fetchAppConfigPromise 42 } catch (e) { 43 fetchAppConfigPromise = undefined 44 throw e 45 } 46} 47 48const Context = createContext<AppConfigResponse>(DEFAULT_APP_CONFIG_RESPONSE) 49 50export function Provider({children}: React.PropsWithChildren<{}>) { 51 const {data} = useQuery<AppConfigResponse | null>( 52 { 53 staleTime: Infinity, 54 queryKey: appConfigQueryKey, 55 refetchInterval: query => { 56 // refetch regularly if fetch failed, otherwise never refetch 57 return query.state.status === 'error' ? 60e3 : Infinity 58 }, 59 async queryFn() { 60 return fetchAppConfig() 61 }, 62 }, 63 qc, 64 ) 65 return ( 66 <Context.Provider value={data ?? DEFAULT_APP_CONFIG_RESPONSE}> 67 {children} 68 </Context.Provider> 69 ) 70} 71 72export async function prefetchAppConfig() { 73 try { 74 const data = await fetchAppConfig() 75 if (data) { 76 qc.setQueryData(appConfigQueryKey, data) 77 } 78 } catch {} 79} 80 81export function useAppConfig() { 82 const ctx = useContext(Context) 83 if (!ctx) { 84 throw new Error('useAppConfig must be used within a Provider') 85 } 86 return ctx 87}