Move config to TS class
This commit is contained in:
parent
ad6bb903db
commit
eb58f77162
6 changed files with 122 additions and 103 deletions
|
|
@ -86,7 +86,7 @@ export default {
|
||||||
} else {
|
} else {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
}
|
}
|
||||||
this.$config.promise.then(this.onConfigLoaded);
|
this.$config.load().then(this.onConfigLoaded);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
windowNotificationPermission,
|
windowNotificationPermission,
|
||||||
|
|
@ -138,7 +138,7 @@ export default {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
showLoadingScreen() {
|
showLoadingScreen() {
|
||||||
return this.loading || !(this.$config.loaded);
|
return this.loading || !(this.$config.isLoaded());
|
||||||
},
|
},
|
||||||
notificationCount,
|
notificationCount,
|
||||||
currentUser() {
|
currentUser() {
|
||||||
|
|
|
||||||
|
|
@ -42,24 +42,4 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
|
||||||
availableRoomTypes() {
|
|
||||||
let types = [{ title: this.$t("room_info.room_type_default"), description: "", value: ROOM_TYPE_DEFAULT }];
|
|
||||||
if (this.$config.experimental_voice_mode) {
|
|
||||||
types.push({
|
|
||||||
title: this.$t("room_info.voice_mode"),
|
|
||||||
description: this.$t("room_info.voice_mode_info"),
|
|
||||||
value: ROOM_TYPE_VOICE_MODE,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (this.$config.experimental_file_mode) {
|
|
||||||
types.push({
|
|
||||||
title: this.$t("room_info.file_mode"),
|
|
||||||
description: this.$t("room_info.file_mode_info"),
|
|
||||||
value: ROOM_TYPE_FILE_MODE,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return types;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import i18n from './plugins/lang';
|
||||||
import router from './router'
|
import router from './router'
|
||||||
import matrix from './services/matrix.service'
|
import matrix from './services/matrix.service'
|
||||||
import navigation from './services/navigation.service'
|
import navigation from './services/navigation.service'
|
||||||
import config from './services/config.service'
|
import config from './services/config.service.ts'
|
||||||
import analytics from './services/analytics.service'
|
import analytics from './services/analytics.service'
|
||||||
import audioPlayer from './services/audio.service';
|
import audioPlayer from './services/audio.service';
|
||||||
import 'roboto-fontface/css/roboto/roboto-fontface.css'
|
import 'roboto-fontface/css/roboto/roboto-fontface.css'
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import cleaninsights from "./cleaninsights.service";
|
import cleaninsights from "./cleaninsights.service";
|
||||||
|
import { Config } from "./config.service";
|
||||||
import matomo from "./matomo.service";
|
import matomo from "./matomo.service";
|
||||||
|
|
||||||
export interface AnalyticsEngine {
|
export interface AnalyticsEngine {
|
||||||
event(category: string, action: string);
|
event(category: string, action: string): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
type AnalyticsEvent = {
|
type AnalyticsEvent = {
|
||||||
|
|
@ -11,7 +12,7 @@ type AnalyticsEvent = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
install(app) {
|
install(app: any) {
|
||||||
class AnalyticsServiceClass {
|
class AnalyticsServiceClass {
|
||||||
|
|
||||||
engines: AnalyticsEngine[];
|
engines: AnalyticsEngine[];
|
||||||
|
|
@ -23,7 +24,7 @@ export default {
|
||||||
this.cachedEvents = [];
|
this.cachedEvents = [];
|
||||||
this.initialized = false;
|
this.initialized = false;
|
||||||
|
|
||||||
app.$config.promise.then((config) => {
|
app.$config.load().then((config: Config) => {
|
||||||
var analytics = config.analytics || {};
|
var analytics = config.analytics || {};
|
||||||
if (!Array.isArray(analytics)) {
|
if (!Array.isArray(analytics)) {
|
||||||
analytics = [analytics];
|
analytics = [analytics];
|
||||||
|
|
@ -58,7 +59,7 @@ export default {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
event(category, action) {
|
event(category: string, action: string) {
|
||||||
if (!this.initialized) {
|
if (!this.initialized) {
|
||||||
this.cachedEvents.push({category, action});
|
this.cachedEvents.push({category, action});
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
import * as defaultConfig from "@/assets/config.json";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
install(app, defaultServerFromLocation, onloaded) {
|
|
||||||
var config = defaultConfig.default;
|
|
||||||
config["loaded"] = false;
|
|
||||||
const getRuntimeConfig = () => {
|
|
||||||
return fetch('./config.json?ms=' + Date.now()).then((res) => res.json()).catch(err => {
|
|
||||||
console.error("Failed to get config:", err);
|
|
||||||
return {};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
config.promise = getRuntimeConfig().then((json) => {
|
|
||||||
// Reactively use all the config values
|
|
||||||
for (const key of Object.keys(json)) {
|
|
||||||
config[key] = json[key];
|
|
||||||
}
|
|
||||||
// If default server is not set, default to current server address
|
|
||||||
if (!json.defaultBaseUrl) {
|
|
||||||
if (json.defaultServer) {
|
|
||||||
// TODO - Only to migrate old values (defaultServer was renamed defaultBaseUrl), can be removed later...
|
|
||||||
config["defaultBaseUrl"] = defaultServerFromLocation;
|
|
||||||
} else {
|
|
||||||
config["defaultBaseUrl"] = json.defaultServer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (json.useFullyQualifiedDMLinks == undefined) {
|
|
||||||
config["useFullyQualifiedDMLinks"] = true; // Default to true
|
|
||||||
}
|
|
||||||
if (json.disableMediaSharing == undefined) {
|
|
||||||
config["disableMediaSharing"] = false;
|
|
||||||
}
|
|
||||||
if (!json.maxSizeAutoDownloads) {
|
|
||||||
config["maxSizeAutoDownloads"] = 10 * 1024 * 1024;
|
|
||||||
}
|
|
||||||
if (!json.roomTypes) {
|
|
||||||
let roomTypes = ["group_chat", "channel"];
|
|
||||||
const fileDropEnabled = (json.experimental_file_mode === undefined) ? true : !!json.experimental_file_mode;
|
|
||||||
if (fileDropEnabled) {
|
|
||||||
roomTypes.push("file_drop");
|
|
||||||
}
|
|
||||||
config["roomTypes"] = roomTypes;
|
|
||||||
}
|
|
||||||
config["loaded"] = true;
|
|
||||||
|
|
||||||
document.title = config.appName || "";
|
|
||||||
|
|
||||||
// Tell callback we are done loading runtime config
|
|
||||||
if (onloaded) {
|
|
||||||
onloaded(config);
|
|
||||||
}
|
|
||||||
return config;
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
config.getMatrixDomainPartMapping = (domain) => {
|
|
||||||
console.log("Get domain endpoint mapping for", domain);
|
|
||||||
if (config.matrixDomainPartMapping && config.matrixDomainPartMapping[domain]) {
|
|
||||||
const mapping = config.matrixDomainPartMapping[domain];
|
|
||||||
if (Array.isArray(mapping)) {
|
|
||||||
return mapping[0]; //TODO - Use the first one for now, but maybe rotate somehow?
|
|
||||||
}
|
|
||||||
return mapping;
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
app.$config = config;
|
|
||||||
app.config.globalProperties.$config = config;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
114
src/services/config.service.ts
Normal file
114
src/services/config.service.ts
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
import * as defaultConfig from "@/assets/config.json";
|
||||||
|
|
||||||
|
export class Config {
|
||||||
|
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;
|
||||||
|
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"];
|
||||||
|
|
||||||
|
_loaded: boolean;
|
||||||
|
_loadPromise: Promise<Config> | undefined;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this._loaded = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
load = (): Promise<Config> => {
|
||||||
|
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.error("NO SUCH CONFIG VALUE", key);
|
||||||
|
}
|
||||||
|
(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;
|
||||||
|
},
|
||||||
|
};
|
||||||
Loading…
Add table
Add a link
Reference in a new issue