Add app config context
This commit is contained in:
@@ -46,3 +46,6 @@ GEOLOCATION_DEV_URL=
|
||||
|
||||
# live-events web worker URL
|
||||
LIVE_EVENTS_DEV_URL=
|
||||
|
||||
# app-config web worker URL
|
||||
APP_CONFIG_DEV_URL=
|
||||
|
||||
+39
-32
@@ -22,6 +22,10 @@ import {ThemeProvider} from '#/lib/ThemeContext'
|
||||
import I18nProvider from '#/locale/i18nProvider'
|
||||
import {logger} from '#/logger'
|
||||
import {Provider as A11yProvider} from '#/state/a11y'
|
||||
import {
|
||||
prefetchAppConfig,
|
||||
Provider as AppConfigProvider,
|
||||
} from '#/state/appConfig'
|
||||
import {Provider as MutedThreadsProvider} from '#/state/cache/thread-mutes'
|
||||
import {Provider as DialogStateProvider} from '#/state/dialogs'
|
||||
import {Provider as EmailVerificationProvider} from '#/state/email-verification'
|
||||
@@ -103,6 +107,7 @@ if (IS_ANDROID) {
|
||||
Geo.resolve()
|
||||
prefetchAgeAssuranceConfig()
|
||||
prefetchLiveEvents()
|
||||
prefetchAppConfig()
|
||||
|
||||
function InnerApp() {
|
||||
const [isReady, setIsReady] = React.useState(false)
|
||||
@@ -228,38 +233,40 @@ function App() {
|
||||
*/
|
||||
return (
|
||||
<Geo.Provider>
|
||||
<A11yProvider>
|
||||
<KeyboardControllerProvider>
|
||||
<OnboardingProvider>
|
||||
<AnalyticsContext>
|
||||
<SessionProvider>
|
||||
<PrefsStateProvider>
|
||||
<I18nProvider>
|
||||
<ShellStateProvider>
|
||||
<ModalStateProvider>
|
||||
<DialogStateProvider>
|
||||
<LightboxStateProvider>
|
||||
<PortalProvider>
|
||||
<BottomSheetProvider>
|
||||
<StarterPackProvider>
|
||||
<SafeAreaProvider
|
||||
initialMetrics={initialWindowMetrics}>
|
||||
<InnerApp />
|
||||
</SafeAreaProvider>
|
||||
</StarterPackProvider>
|
||||
</BottomSheetProvider>
|
||||
</PortalProvider>
|
||||
</LightboxStateProvider>
|
||||
</DialogStateProvider>
|
||||
</ModalStateProvider>
|
||||
</ShellStateProvider>
|
||||
</I18nProvider>
|
||||
</PrefsStateProvider>
|
||||
</SessionProvider>
|
||||
</AnalyticsContext>
|
||||
</OnboardingProvider>
|
||||
</KeyboardControllerProvider>
|
||||
</A11yProvider>
|
||||
<AppConfigProvider>
|
||||
<A11yProvider>
|
||||
<KeyboardControllerProvider>
|
||||
<OnboardingProvider>
|
||||
<AnalyticsContext>
|
||||
<SessionProvider>
|
||||
<PrefsStateProvider>
|
||||
<I18nProvider>
|
||||
<ShellStateProvider>
|
||||
<ModalStateProvider>
|
||||
<DialogStateProvider>
|
||||
<LightboxStateProvider>
|
||||
<PortalProvider>
|
||||
<BottomSheetProvider>
|
||||
<StarterPackProvider>
|
||||
<SafeAreaProvider
|
||||
initialMetrics={initialWindowMetrics}>
|
||||
<InnerApp />
|
||||
</SafeAreaProvider>
|
||||
</StarterPackProvider>
|
||||
</BottomSheetProvider>
|
||||
</PortalProvider>
|
||||
</LightboxStateProvider>
|
||||
</DialogStateProvider>
|
||||
</ModalStateProvider>
|
||||
</ShellStateProvider>
|
||||
</I18nProvider>
|
||||
</PrefsStateProvider>
|
||||
</SessionProvider>
|
||||
</AnalyticsContext>
|
||||
</OnboardingProvider>
|
||||
</KeyboardControllerProvider>
|
||||
</A11yProvider>
|
||||
</AppConfigProvider>
|
||||
</Geo.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
+32
-25
@@ -13,6 +13,10 @@ import {ThemeProvider} from '#/lib/ThemeContext'
|
||||
import I18nProvider from '#/locale/i18nProvider'
|
||||
import {logger} from '#/logger'
|
||||
import {Provider as A11yProvider} from '#/state/a11y'
|
||||
import {
|
||||
prefetchAppConfig,
|
||||
Provider as AppConfigProvider,
|
||||
} from '#/state/appConfig'
|
||||
import {Provider as MutedThreadsProvider} from '#/state/cache/thread-mutes'
|
||||
import {Provider as DialogStateProvider} from '#/state/dialogs'
|
||||
import {Provider as EmailVerificationProvider} from '#/state/email-verification'
|
||||
@@ -79,6 +83,7 @@ import {Provider as HideBottomBarBorderProvider} from './lib/hooks/useHideBottom
|
||||
Geo.resolve()
|
||||
prefetchAgeAssuranceConfig()
|
||||
prefetchLiveEvents()
|
||||
prefetchAppConfig()
|
||||
|
||||
function InnerApp() {
|
||||
const [isReady, setIsReady] = useState(false)
|
||||
@@ -202,31 +207,33 @@ function App() {
|
||||
*/
|
||||
return (
|
||||
<Geo.Provider>
|
||||
<A11yProvider>
|
||||
<OnboardingProvider>
|
||||
<AnalyticsContext>
|
||||
<SessionProvider>
|
||||
<PrefsStateProvider>
|
||||
<I18nProvider>
|
||||
<ShellStateProvider>
|
||||
<ModalStateProvider>
|
||||
<DialogStateProvider>
|
||||
<LightboxStateProvider>
|
||||
<PortalProvider>
|
||||
<StarterPackProvider>
|
||||
<InnerApp />
|
||||
</StarterPackProvider>
|
||||
</PortalProvider>
|
||||
</LightboxStateProvider>
|
||||
</DialogStateProvider>
|
||||
</ModalStateProvider>
|
||||
</ShellStateProvider>
|
||||
</I18nProvider>
|
||||
</PrefsStateProvider>
|
||||
</SessionProvider>
|
||||
</AnalyticsContext>
|
||||
</OnboardingProvider>
|
||||
</A11yProvider>
|
||||
<AppConfigProvider>
|
||||
<A11yProvider>
|
||||
<OnboardingProvider>
|
||||
<AnalyticsContext>
|
||||
<SessionProvider>
|
||||
<PrefsStateProvider>
|
||||
<I18nProvider>
|
||||
<ShellStateProvider>
|
||||
<ModalStateProvider>
|
||||
<DialogStateProvider>
|
||||
<LightboxStateProvider>
|
||||
<PortalProvider>
|
||||
<StarterPackProvider>
|
||||
<InnerApp />
|
||||
</StarterPackProvider>
|
||||
</PortalProvider>
|
||||
</LightboxStateProvider>
|
||||
</DialogStateProvider>
|
||||
</ModalStateProvider>
|
||||
</ShellStateProvider>
|
||||
</I18nProvider>
|
||||
</PrefsStateProvider>
|
||||
</SessionProvider>
|
||||
</AnalyticsContext>
|
||||
</OnboardingProvider>
|
||||
</A11yProvider>
|
||||
</AppConfigProvider>
|
||||
</Geo.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
Vendored
+10
@@ -141,3 +141,13 @@ export const LIVE_EVENTS_PROD_URL = `https://live-events.workers.bsky.app`
|
||||
export const LIVE_EVENTS_URL = IS_DEV
|
||||
? (LIVE_EVENTS_DEV_URL ?? LIVE_EVENTS_PROD_URL)
|
||||
: LIVE_EVENTS_PROD_URL
|
||||
|
||||
/**
|
||||
* URLs for the app-config web worker. Can be a
|
||||
* locally running server, see `env.example` for more.
|
||||
*/
|
||||
export const APP_CONFIG_DEV_URL = process.env.APP_CONFIG_DEV_URL
|
||||
export const APP_CONFIG_PROD_URL = `https://app-config.workers.bsky.app`
|
||||
export const APP_CONFIG_URL = IS_DEV
|
||||
? (APP_CONFIG_DEV_URL ?? APP_CONFIG_PROD_URL)
|
||||
: APP_CONFIG_PROD_URL
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
import {createContext, useContext} from 'react'
|
||||
import {QueryClient, useQuery} from '@tanstack/react-query'
|
||||
|
||||
import {APP_CONFIG_URL} from '#/env'
|
||||
|
||||
const qc = new QueryClient()
|
||||
const appConfigQueryKey = ['app-config']
|
||||
|
||||
/**
|
||||
* Matches the types defined in our `app-config` worker
|
||||
*/
|
||||
type AppConfigResponse = {
|
||||
liveNow: {
|
||||
allow: string[]
|
||||
exceptions: {
|
||||
did: string
|
||||
allow: string[]
|
||||
}[]
|
||||
}
|
||||
}
|
||||
|
||||
export const DEFAULT_APP_CONFIG_RESPONSE: AppConfigResponse = {
|
||||
liveNow: {
|
||||
allow: [],
|
||||
exceptions: [],
|
||||
},
|
||||
}
|
||||
|
||||
async function fetchAppConfig(): Promise<AppConfigResponse | null> {
|
||||
try {
|
||||
const res = await fetch(`${APP_CONFIG_URL}/config`)
|
||||
if (!res.ok) return null
|
||||
const data = await res.json()
|
||||
return data
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
const Context = createContext<AppConfigResponse>(DEFAULT_APP_CONFIG_RESPONSE)
|
||||
|
||||
export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||
const {data} = useQuery(
|
||||
{
|
||||
staleTime: Infinity,
|
||||
gcTime: Infinity,
|
||||
queryKey: appConfigQueryKey,
|
||||
async queryFn() {
|
||||
return fetchAppConfig()
|
||||
},
|
||||
},
|
||||
qc,
|
||||
)
|
||||
return (
|
||||
<Context.Provider value={data ?? DEFAULT_APP_CONFIG_RESPONSE}>
|
||||
{children}
|
||||
</Context.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export async function prefetchAppConfig() {
|
||||
const data = await fetchAppConfig()
|
||||
if (data) {
|
||||
qc.setQueryData(appConfigQueryKey, data)
|
||||
}
|
||||
}
|
||||
|
||||
export function useAppConfig() {
|
||||
const ctx = useContext(Context)
|
||||
if (!ctx) {
|
||||
throw new Error('useAppConfig must be used within a Provider')
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
Reference in New Issue
Block a user