95 lines
2.9 KiB
TypeScript
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;
|
|
};
|