2026-01-23 18:53:59 +05:30
|
|
|
'use client';
|
|
|
|
|
|
2026-05-31 13:05:22 +05:30
|
|
|
import { createContext, ReactNode, useCallback, useContext, useEffect, useState } from 'react';
|
|
|
|
|
|
|
|
|
|
type BackendStatus = 'reachable' | 'unreachable';
|
2026-01-23 18:53:59 +05:30
|
|
|
|
|
|
|
|
interface AppConfig {
|
|
|
|
|
uiVersion: string;
|
|
|
|
|
apiVersion: string;
|
2026-02-20 18:21:24 +05:30
|
|
|
deploymentMode: string;
|
|
|
|
|
authProvider: string;
|
2026-05-11 17:13:01 +05:30
|
|
|
turnEnabled: boolean;
|
|
|
|
|
forceTurnRelay: boolean;
|
2026-05-31 13:05:22 +05:30
|
|
|
backendStatus: BackendStatus;
|
|
|
|
|
backendUrl: string;
|
|
|
|
|
backendMessage: string | null;
|
2026-01-23 18:53:59 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface AppConfigContextType {
|
|
|
|
|
config: AppConfig | null;
|
|
|
|
|
loading: boolean;
|
2026-05-31 13:05:22 +05:30
|
|
|
refresh: () => Promise<void>;
|
2026-01-23 18:53:59 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const defaultConfig: AppConfig = {
|
|
|
|
|
uiVersion: 'dev',
|
2026-05-31 13:05:22 +05:30
|
|
|
apiVersion: 'unavailable',
|
2026-02-20 18:21:24 +05:30
|
|
|
deploymentMode: 'oss',
|
|
|
|
|
authProvider: 'local',
|
2026-05-11 17:13:01 +05:30
|
|
|
turnEnabled: false,
|
|
|
|
|
forceTurnRelay: false,
|
2026-05-31 13:05:22 +05:30
|
|
|
backendStatus: 'unreachable',
|
|
|
|
|
backendUrl: process.env.NEXT_PUBLIC_BACKEND_URL || 'unknown',
|
|
|
|
|
backendMessage: process.env.NEXT_PUBLIC_BACKEND_URL
|
|
|
|
|
? `Unable to verify backend health at ${process.env.NEXT_PUBLIC_BACKEND_URL}.`
|
|
|
|
|
: 'Unable to verify backend health.',
|
2026-01-23 18:53:59 +05:30
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const AppConfigContext = createContext<AppConfigContextType>({
|
|
|
|
|
config: null,
|
|
|
|
|
loading: true,
|
2026-05-31 13:05:22 +05:30
|
|
|
refresh: async () => { },
|
2026-01-23 18:53:59 +05:30
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export function AppConfigProvider({ children }: { children: ReactNode }) {
|
|
|
|
|
const [config, setConfig] = useState<AppConfig | null>(null);
|
|
|
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
|
|
2026-05-31 13:05:22 +05:30
|
|
|
const loadConfig = useCallback(async () => {
|
|
|
|
|
setLoading(true);
|
|
|
|
|
try {
|
|
|
|
|
const response = await fetch('/api/config/version', { cache: 'no-store' });
|
|
|
|
|
const data = await response.json();
|
|
|
|
|
const backend = data.backend && typeof data.backend === 'object' ? data.backend : {};
|
|
|
|
|
const backendStatus: BackendStatus = backend.status === 'reachable' ? 'reachable' : 'unreachable';
|
|
|
|
|
const backendUrl = typeof backend.url === 'string' && backend.url.length > 0
|
|
|
|
|
? backend.url
|
|
|
|
|
: defaultConfig.backendUrl;
|
|
|
|
|
|
|
|
|
|
setConfig({
|
|
|
|
|
uiVersion: data.ui || 'dev',
|
|
|
|
|
apiVersion: data.api || 'unknown',
|
|
|
|
|
deploymentMode: data.deploymentMode || 'oss',
|
|
|
|
|
authProvider: data.authProvider || 'local',
|
|
|
|
|
turnEnabled: Boolean(data.turnEnabled),
|
|
|
|
|
forceTurnRelay: Boolean(data.forceTurnRelay),
|
|
|
|
|
backendStatus,
|
|
|
|
|
backendUrl,
|
|
|
|
|
backendMessage: typeof backend.message === 'string' && backend.message.length > 0
|
|
|
|
|
? backend.message
|
|
|
|
|
: backendStatus === 'reachable'
|
|
|
|
|
? null
|
|
|
|
|
: `Backend is not reachable at ${backendUrl}.`,
|
2026-01-23 18:53:59 +05:30
|
|
|
});
|
2026-05-31 13:05:22 +05:30
|
|
|
} catch {
|
|
|
|
|
setConfig(defaultConfig);
|
|
|
|
|
} finally {
|
|
|
|
|
setLoading(false);
|
|
|
|
|
}
|
2026-01-23 18:53:59 +05:30
|
|
|
}, []);
|
|
|
|
|
|
2026-05-31 13:05:22 +05:30
|
|
|
useEffect(() => {
|
|
|
|
|
loadConfig();
|
|
|
|
|
}, [loadConfig]);
|
|
|
|
|
|
2026-01-23 18:53:59 +05:30
|
|
|
return (
|
2026-05-31 13:05:22 +05:30
|
|
|
<AppConfigContext.Provider value={{ config, loading, refresh: loadConfig }}>
|
2026-01-23 18:53:59 +05:30
|
|
|
{children}
|
|
|
|
|
</AppConfigContext.Provider>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function useAppConfig() {
|
|
|
|
|
return useContext(AppConfigContext);
|
|
|
|
|
}
|