vojo/src/app/hooks/useClientConfig.ts

95 lines
2.9 KiB
TypeScript

import { createContext, useContext } from 'react';
export type HashRouterConfig = {
enabled?: boolean;
basename?: string;
};
export type PushConfig = {
vapidPublicKey: string;
gatewayUrl: string;
webAppId?: string;
fcmAppId?: string;
};
export type BotConfig = {
id?: string;
mxid?: string;
name?: string;
/** Optional operator override of the localized description. Falls back
* to i18n key `Bots.description.<id>` when absent. */
description?: string;
experience?: {
type?: string;
url?: string;
commandPrefix?: string;
/** Declarative opt-in to elevated host verbs (e.g. `vojo.add_to_chat`).
* Validated against an allowlist at load (catalog.ts `normalizeBotCaps`);
* unknown entries are dropped, absent ⇒ `[]`. config.json is a trusted,
* operator-controlled root — the widget cannot grant itself a capability. */
capabilities?: string[];
};
};
export type ChannelsConfig = {
/** Default true. When false, M4 per-thread unread machinery (badges,
* thread-aware receipt handler, drawer markAsRead) falls back to
* pre-M4 blind-DELETE semantics. `threadSupport: true` stays on
* unconditionally — drawer (M2) reads `room.getThread()` and
* ThreadEvent emitters which silently NO-OP without it. */
unreadThreading?: boolean;
};
export type ClientConfig = {
defaultHomeserver?: number;
homeserverList?: string[];
allowCustomHomeservers?: boolean;
featuredCommunities?: {
openAsDefault?: boolean;
spaces?: string[];
rooms?: string[];
servers?: string[];
};
hashRouter?: HashRouterConfig;
push?: PushConfig;
bots?: BotConfig[];
channels?: ChannelsConfig;
};
export const isUnreadThreadingEnabled = (clientConfig: ClientConfig): boolean =>
clientConfig.channels?.unreadThreading !== false;
const ClientConfigContext = createContext<ClientConfig | null>(null);
export const ClientConfigProvider = ClientConfigContext.Provider;
export function useClientConfig(): ClientConfig {
const config = useContext(ClientConfigContext);
if (!config) throw new Error('Client config are not provided!');
return config;
}
// Single source of truth for the M4 kill switch. Default true (absent
// config = enabled). Consumers should call this hook instead of reading
// `useClientConfig()` + `isUnreadThreadingEnabled(...)` separately —
// keeps the predicate in one place and lets future telemetry / runtime
// flips slot in transparently.
export function useUnreadThreadingEnabled(): boolean {
return isUnreadThreadingEnabled(useClientConfig());
}
export const clientDefaultServer = (clientConfig: ClientConfig): string =>
clientConfig.homeserverList?.[clientConfig.defaultHomeserver ?? 0] ?? 'matrix.org';
export const clientAllowedServer = (clientConfig: ClientConfig, server: string): boolean => {
const { homeserverList, allowCustomHomeservers } = clientConfig;
if (allowCustomHomeservers) return true;
return homeserverList?.includes(server) === true;
};