Async config file (#682)
* initial * only donwload config once * formatting * update sample config * sentry * refactor load state * fix build yaml * Upper case enums * change how defaults work. review fixes * abstract initialization * copyright * gitignore styleing * refactor initialization * use dafualt as fallback * internalInstance rename * review * remove acidentally added posthog file * DSN rename * update Copyright * remove olm from the initializer Co-authored-by: Timo K <timok@element.io>
This commit is contained in:
parent
806a9032e1
commit
78a313c373
10 changed files with 293 additions and 88 deletions
146
src/initializer.tsx
Normal file
146
src/initializer.tsx
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
Copyright 2022 Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { Integrations } from "@sentry/tracing";
|
||||
import i18n from "i18next";
|
||||
import { initReactI18next } from "react-i18next";
|
||||
import LanguageDetector from "i18next-browser-languagedetector";
|
||||
import Backend from "i18next-http-backend";
|
||||
import * as Sentry from "@sentry/react";
|
||||
|
||||
import { getUrlParams } from "./UrlParams";
|
||||
import { Config } from "./config/Config";
|
||||
import { DEFAULT_CONFIG } from "./config/ConfigOptions";
|
||||
|
||||
enum LoadState {
|
||||
None,
|
||||
Loading,
|
||||
Loaded,
|
||||
}
|
||||
|
||||
class DependencyLoadStates {
|
||||
// TODO: decide where olm should be initialized (see TODO comment below)
|
||||
// olm: LoadState = LoadState.None;
|
||||
config: LoadState = LoadState.None;
|
||||
sentry: LoadState = LoadState.None;
|
||||
i18n: LoadState = LoadState.None;
|
||||
|
||||
allDepsAreLoaded() {
|
||||
return !Object.values(this).some((s) => s !== LoadState.Loaded);
|
||||
}
|
||||
}
|
||||
|
||||
export class Initializer {
|
||||
private static internalInstance: Initializer;
|
||||
|
||||
public static init(): Promise<void> | null {
|
||||
if (Initializer?.internalInstance?.initPromise) {
|
||||
return null;
|
||||
}
|
||||
Initializer.internalInstance = new Initializer();
|
||||
Initializer.internalInstance.initPromise = new Promise<void>((resolve) => {
|
||||
// initStep calls itself recursivly until everything is initialized in the correct order.
|
||||
// Then the promise gets resolved.
|
||||
Initializer.internalInstance.initStep(resolve);
|
||||
});
|
||||
return Initializer.internalInstance.initPromise;
|
||||
}
|
||||
|
||||
loadStates = new DependencyLoadStates();
|
||||
|
||||
initStep(resolve: (value: void | PromiseLike<void>) => void) {
|
||||
// TODO: Olm is initialized with the client currently (see `initClient()` and `olm.ts`)
|
||||
// we need to decide if we want to init it here or keep it in initClient
|
||||
// if (this.loadStates.olm === LoadState.None) {
|
||||
// this.loadStates.olm = LoadState.Loading;
|
||||
// // TODO: https://gitlab.matrix.org/matrix-org/olm/-/issues/10
|
||||
// window.OLM_OPTIONS = {};
|
||||
// Olm.init({ locateFile: () => olmWasmPath }).then(() => {
|
||||
// this.loadStates.olm = LoadState.Loaded;
|
||||
// this.initStep(resolve);
|
||||
// });
|
||||
// }
|
||||
|
||||
// config
|
||||
if (this.loadStates.config === LoadState.None) {
|
||||
this.loadStates.config = LoadState.Loading;
|
||||
Config.init().then(() => {
|
||||
this.loadStates.config = LoadState.Loaded;
|
||||
this.initStep(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
//sentry (only initialize after the config is ready)
|
||||
if (
|
||||
this.loadStates.sentry === LoadState.None &&
|
||||
this.loadStates.config === LoadState.Loaded
|
||||
) {
|
||||
Sentry.init({
|
||||
dsn: Config.instance.config.sentry?.DSN ?? DEFAULT_CONFIG.sentry.DSN,
|
||||
environment:
|
||||
Config.instance.config.sentry.environment ??
|
||||
DEFAULT_CONFIG.sentry.environment,
|
||||
integrations: [
|
||||
new Integrations.BrowserTracing({
|
||||
routingInstrumentation:
|
||||
Sentry.reactRouterV5Instrumentation(history),
|
||||
}),
|
||||
],
|
||||
tracesSampleRate: 1.0,
|
||||
});
|
||||
this.loadStates.sentry = LoadState.Loaded;
|
||||
}
|
||||
|
||||
//i18n
|
||||
if (this.loadStates.i18n === LoadState.None) {
|
||||
const languageDetector = new LanguageDetector();
|
||||
languageDetector.addDetector({
|
||||
name: "urlFragment",
|
||||
// Look for a language code in the URL's fragment
|
||||
lookup: () => getUrlParams().lang ?? undefined,
|
||||
});
|
||||
|
||||
i18n
|
||||
.use(Backend)
|
||||
.use(languageDetector)
|
||||
.use(initReactI18next)
|
||||
.init({
|
||||
fallbackLng: "en-GB",
|
||||
defaultNS: "app",
|
||||
keySeparator: false,
|
||||
nsSeparator: false,
|
||||
pluralSeparator: "|",
|
||||
contextSeparator: "|",
|
||||
interpolation: {
|
||||
escapeValue: false, // React has built-in XSS protections
|
||||
},
|
||||
detection: {
|
||||
// No localStorage detectors or caching here, since we don't have any way
|
||||
// of letting the user manually select a language
|
||||
order: ["urlFragment", "navigator"],
|
||||
caches: [],
|
||||
},
|
||||
});
|
||||
this.loadStates.i18n = LoadState.Loaded;
|
||||
}
|
||||
|
||||
if (this.loadStates.allDepsAreLoaded()) {
|
||||
// resolve if there is no dependency that is not loaded
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
private initPromise: Promise<void>;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue