import * as defaultConfig from "@/assets/config.json"; export class Config { // Configuration file entries // appName: string = ""; appNames: { [key: string]: string } = {}; languageSupportEmail: string = ""; productLink: string = ""; defaultBaseUrl: string = ""; matrixDomainPartMapping: { [key: string]: string | string[] } = {}; useFullyQualifiedDMLinks: boolean = true; defaultMatrixDomainPart: string = ""; identityServer?: string; registrationToken?: string; userIdPrefix?: string; accentColor?: string; logo?: string; analytics: { type?: string; enabled: boolean; config?: any }[] = []; experimental_voice_mode: boolean = true; experimental_file_mode: boolean = true; experimental_read_only_room: boolean = true; experimental_public_room: boolean = true; show_status_messages: "always" | "never" | "moderators" = "never"; hide_add_room_on_home: boolean = false; mirrors?: string[]; maxSizeAutoDownloads: number = 10 * 1024 * 1024; disableMediaSharing: boolean = false; chat_backgrounds: { all?: string[]; direct?: string[]; public?: string[]; private?: string[] } = {}; shortCodeStickers?: { packs: { name: string; stickers: string[] }[] }; roomTypes: ("group_chat" | "channel" | "file_drop")[] = ["group_chat", "channel", "file_drop"]; // Class implementation // _loaded: boolean; _loadPromise: Promise | undefined; constructor() { this._loaded = false; } load = (): Promise => { if (this._loadPromise) return this._loadPromise; this._loadPromise = fetch("./config.json?ms=" + Date.now()) .then((res) => res.json()) .catch((err) => { console.error("Failed to get config:", err); return {}; }) .then((json: { [key: string]: any }) => { this.fromJson(json); this._loaded = true; return this; }); return this._loadPromise; }; isLoaded = () => { return this._loaded; }; fromJson = (json: { [key: string]: any }) => { for (const key of Object.keys(json)) { if (!Object.hasOwn(this, key)) { console.warn("Invalid config value", key); } else { (this as any)[key] = json[key]; } } }; /** * If there is an explicit mapping for this MX domain in the config file, return the endpoint URL that it maps to. * @param {*} domain * @returns */ getMatrixDomainPartMapping = (domain: string) => { console.log("Get domain endpoint mapping for", domain); if (this.matrixDomainPartMapping && this.matrixDomainPartMapping[domain]) { const mapping = this.matrixDomainPartMapping[domain]; if (Array.isArray(mapping)) { return mapping[0]; //TODO - Use the first one for now, but maybe rotate somehow? } return mapping; } return undefined; }; } export default { install(app: any, defaultServerFromLocation: string, onloaded: (config: Config) => void) { var config = new Config(); config.defaultBaseUrl = defaultServerFromLocation; config.fromJson(defaultConfig.default); config.load().then((config: Config) => { document.title = config.appName; // Tell callback we are done loading runtime config if (onloaded) { onloaded(config); } return config; }); // Proxy the object for debugging const handler = { get(target: any, prop: string, receiver: any) { if (!Object.hasOwn(target, prop)) { console.error("CONFIG - Invalid property", prop); } return Reflect.get(target, prop, receiver); }, }; const configProxy = new Proxy(config, handler); app.$config = configProxy; app.config.globalProperties.$config = configProxy; }, };