From 0b032d74341f988e630b2aed41c46a21b7c8d390 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 8 Apr 2020 16:08:39 +0100 Subject: [PATCH 01/21] loadOlm earlier Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/vector/app.js | 4 +--- src/vector/index.ts | 10 +++++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/vector/app.js b/src/vector/app.js index 836b2ef1..dee663a1 100644 --- a/src/vector/app.js +++ b/src/vector/app.js @@ -40,7 +40,7 @@ import SdkConfig from "matrix-react-sdk/src/SdkConfig"; import {setTheme} from "matrix-react-sdk/src/theme"; import CallHandler from 'matrix-react-sdk/src/CallHandler'; -import {loadConfig, preparePlatform, loadLanguage, loadOlm} from "./init"; +import {loadConfig, preparePlatform, loadLanguage} from "./init"; let lastLocationHashSet = null; @@ -144,8 +144,6 @@ export async function loadApp(fragParams: {}, acceptBrowser: boolean) { window.addEventListener('hashchange', onHashChange); - await loadOlm(); - // set the platform for react sdk preparePlatform(); const platform = PlatformPeg.get(); diff --git a/src/vector/index.ts b/src/vector/index.ts index d844827a..a35f40c7 100644 --- a/src/vector/index.ts +++ b/src/vector/index.ts @@ -81,13 +81,15 @@ function checkBrowserFeatures() { // try in react but fallback to an `alert` async function start() { // load init.ts async so that its code is not executed immediately and we can catch any exceptions - const {rageshakePromise, loadSkin, loadApp} = await import( + const {rageshakePromise, loadOlm, loadSkin, loadApp} = await import( /* webpackChunkName: "init" */ /* webpackPreload: true */ "./init"); await settled(rageshakePromise); // give rageshake a chance to load/fail + const loadOlmPromise = loadOlm(); + const fragparts = parseQsFromFragment(window.location); // don't try to redirect to the native apps if we're @@ -114,9 +116,11 @@ async function start() { acceptBrowser = Boolean(window.localStorage.getItem("mx_accepts_unsupported_browser")); } + // await things starting successfully + await loadOlmPromise; + // Finally, load the app. All of the other react-sdk imports are in this file which causes the skinner to - // run on the components. We use `require` here to make sure webpack doesn't optimize this into an async - // import and thus running before the skin can load. + // run on the components. await loadApp(fragparts.params, acceptBrowser); } start(); From 6222546e20698f882f46d95bf05d7a8d3e73a8da Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 8 Apr 2020 16:09:47 +0100 Subject: [PATCH 02/21] prepare platform earlier Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/vector/app.js | 2 -- src/vector/index.ts | 7 ++++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/vector/app.js b/src/vector/app.js index dee663a1..327690e6 100644 --- a/src/vector/app.js +++ b/src/vector/app.js @@ -144,8 +144,6 @@ export async function loadApp(fragParams: {}, acceptBrowser: boolean) { window.addEventListener('hashchange', onHashChange); - // set the platform for react sdk - preparePlatform(); const platform = PlatformPeg.get(); // Load the config from the platform diff --git a/src/vector/index.ts b/src/vector/index.ts index a35f40c7..737aeed8 100644 --- a/src/vector/index.ts +++ b/src/vector/index.ts @@ -21,6 +21,8 @@ limitations under the License. // Require common CSS here; this will make webpack process it into bundle.css. // Our own CSS (which is themed) is imported via separate webpack entry points // in webpack.config.js +import {preparePlatform} from "./init"; + require('gfm.css/gfm.css'); require('highlight.js/styles/github.css'); @@ -81,7 +83,7 @@ function checkBrowserFeatures() { // try in react but fallback to an `alert` async function start() { // load init.ts async so that its code is not executed immediately and we can catch any exceptions - const {rageshakePromise, loadOlm, loadSkin, loadApp} = await import( + const {rageshakePromise, preparePlatform, loadOlm, loadSkin, loadApp} = await import( /* webpackChunkName: "init" */ /* webpackPreload: true */ "./init"); @@ -109,6 +111,9 @@ async function start() { } } + // set the platform for react sdk + preparePlatform(); + await loadSkin(); let acceptBrowser = checkBrowserFeatures(); From 43357fe842dbb03ba17eda65fbe308c67573d18b Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 8 Apr 2020 16:10:44 +0100 Subject: [PATCH 03/21] reorder Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/vector/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vector/index.ts b/src/vector/index.ts index 737aeed8..5829b3f5 100644 --- a/src/vector/index.ts +++ b/src/vector/index.ts @@ -90,7 +90,6 @@ async function start() { await settled(rageshakePromise); // give rageshake a chance to load/fail - const loadOlmPromise = loadOlm(); const fragparts = parseQsFromFragment(window.location); @@ -114,6 +113,8 @@ async function start() { // set the platform for react sdk preparePlatform(); + const loadOlmPromise = loadOlm(); + await loadSkin(); let acceptBrowser = checkBrowserFeatures(); From 2c5664b76e3a4cdbf2e3c78a002303ddbbe47827 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 8 Apr 2020 16:12:36 +0100 Subject: [PATCH 04/21] move config loading into index for parallelism Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/vector/app.js | 5 +---- src/vector/index.ts | 10 +++++++--- src/vector/init.ts | 4 ++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/vector/app.js b/src/vector/app.js index 327690e6..b03f5503 100644 --- a/src/vector/app.js +++ b/src/vector/app.js @@ -128,7 +128,7 @@ function onTokenLoginCompleted() { window.location.href = formatted; } -export async function loadApp(fragParams: {}, acceptBrowser: boolean) { +export async function loadApp(fragParams: {}, acceptBrowser: boolean, configError: Error) { // XXX: the way we pass the path to the worker script from webpack via html in body's dataset is a hack // but alternatives seem to require changing the interface to passing Workers to js-sdk const vectorIndexeddbWorkerScript = document.body.dataset.vectorIndexeddbWorkerScript; @@ -146,9 +146,6 @@ export async function loadApp(fragParams: {}, acceptBrowser: boolean) { const platform = PlatformPeg.get(); - // Load the config from the platform - const configError = await loadConfig(); - // Load language after loading config.json so that settingsDefaults.language can be applied await loadLanguage(); diff --git a/src/vector/index.ts b/src/vector/index.ts index 5829b3f5..23dc0470 100644 --- a/src/vector/index.ts +++ b/src/vector/index.ts @@ -21,7 +21,7 @@ limitations under the License. // Require common CSS here; this will make webpack process it into bundle.css. // Our own CSS (which is themed) is imported via separate webpack entry points // in webpack.config.js -import {preparePlatform} from "./init"; +import {loadConfig, preparePlatform} from "./init"; require('gfm.css/gfm.css'); require('highlight.js/styles/github.css'); @@ -112,7 +112,8 @@ async function start() { // set the platform for react sdk preparePlatform(); - + // load config requires the platform to be ready + const loadConfigPromise = loadConfig(); const loadOlmPromise = loadOlm(); await loadSkin(); @@ -125,8 +126,11 @@ async function start() { // await things starting successfully await loadOlmPromise; + + const configError = await loadConfigPromise; + // Finally, load the app. All of the other react-sdk imports are in this file which causes the skinner to // run on the components. - await loadApp(fragparts.params, acceptBrowser); + await loadApp(fragparts.params, acceptBrowser, configError); } start(); diff --git a/src/vector/init.ts b/src/vector/init.ts index 8b8a62bb..04c847ff 100644 --- a/src/vector/init.ts +++ b/src/vector/init.ts @@ -138,12 +138,12 @@ export async function loadSkin() { console.log("Skin loaded!"); } -export async function loadApp(fragParams: {}, acceptBrowser: boolean) { +export async function loadApp(fragParams: {}, acceptBrowser: boolean, configError: Error) { // load app.js async so that its code is not executed immediately and we can catch any exceptions const module = await import( /* webpackChunkName: "riot-web-app" */ /* webpackPreload: true */ "./app"); - window.matrixChat = ReactDOM.render(await module.loadApp(fragParams, acceptBrowser), + window.matrixChat = ReactDOM.render(await module.loadApp(fragParams, acceptBrowser, configError), document.getElementById('matrixchat')); } From 719865c0339fad9581fa0977a5bd196297505b7f Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 8 Apr 2020 16:17:46 +0100 Subject: [PATCH 05/21] parallel load language and theme Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/vector/app.js | 10 +--------- src/vector/index.ts | 27 ++++++++++++++++++++------- src/vector/init.ts | 7 ++++++- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/src/vector/app.js b/src/vector/app.js index b03f5503..12706d90 100644 --- a/src/vector/app.js +++ b/src/vector/app.js @@ -37,10 +37,8 @@ import {parseQs, parseQsFromFragment} from './url_utils'; import {MatrixClientPeg} from 'matrix-react-sdk/src/MatrixClientPeg'; import SdkConfig from "matrix-react-sdk/src/SdkConfig"; -import {setTheme} from "matrix-react-sdk/src/theme"; import CallHandler from 'matrix-react-sdk/src/CallHandler'; -import {loadConfig, preparePlatform, loadLanguage} from "./init"; let lastLocationHashSet = null; @@ -128,7 +126,7 @@ function onTokenLoginCompleted() { window.location.href = formatted; } -export async function loadApp(fragParams: {}, acceptBrowser: boolean, configError: Error) { +export async function loadApp(fragParams: {}, acceptBrowser: boolean, configError: Error|void) { // XXX: the way we pass the path to the worker script from webpack via html in body's dataset is a hack // but alternatives seem to require changing the interface to passing Workers to js-sdk const vectorIndexeddbWorkerScript = document.body.dataset.vectorIndexeddbWorkerScript; @@ -146,14 +144,8 @@ export async function loadApp(fragParams: {}, acceptBrowser: boolean, configErro const platform = PlatformPeg.get(); - // Load language after loading config.json so that settingsDefaults.language can be applied - await loadLanguage(); - const params = parseQs(window.location); - // as quickly as we possibly can, set a default theme... - await setTheme(); - // Now that we've loaded the theme (CSS), display the config syntax error if needed. if (configError && configError.err && configError.err instanceof SyntaxError) { const errorMessage = ( diff --git a/src/vector/index.ts b/src/vector/index.ts index 23dc0470..f95cbc49 100644 --- a/src/vector/index.ts +++ b/src/vector/index.ts @@ -21,8 +21,6 @@ limitations under the License. // Require common CSS here; this will make webpack process it into bundle.css. // Our own CSS (which is themed) is imported via separate webpack entry points // in webpack.config.js -import {loadConfig, preparePlatform} from "./init"; - require('gfm.css/gfm.css'); require('highlight.js/styles/github.css'); @@ -83,7 +81,16 @@ function checkBrowserFeatures() { // try in react but fallback to an `alert` async function start() { // load init.ts async so that its code is not executed immediately and we can catch any exceptions - const {rageshakePromise, preparePlatform, loadOlm, loadSkin, loadApp} = await import( + const { + rageshakePromise, + preparePlatform, + loadOlm, + loadConfig, + loadSkin, + loadLanguage, + loadTheme, + loadApp, + } = await import( /* webpackChunkName: "init" */ /* webpackPreload: true */ "./init"); @@ -110,11 +117,11 @@ async function start() { } } + const loadOlmPromise = loadOlm(); // set the platform for react sdk preparePlatform(); // load config requires the platform to be ready const loadConfigPromise = loadConfig(); - const loadOlmPromise = loadOlm(); await loadSkin(); @@ -123,11 +130,17 @@ async function start() { acceptBrowser = Boolean(window.localStorage.getItem("mx_accepts_unsupported_browser")); } + // await config here + const configError = await loadConfigPromise; + // Load language after loading config.json so that settingsDefaults.language can be applied + const loadLanguagePromise = loadLanguage(); + // as quickly as we possibly can, set a default theme... + const loadThemePromise = loadTheme(); + // await things starting successfully await loadOlmPromise; - - - const configError = await loadConfigPromise; + await loadThemePromise; + await loadLanguagePromise; // Finally, load the app. All of the other react-sdk imports are in this file which causes the skinner to // run on the components. diff --git a/src/vector/init.ts b/src/vector/init.ts index 04c847ff..85f75181 100644 --- a/src/vector/init.ts +++ b/src/vector/init.ts @@ -28,6 +28,7 @@ import ElectronPlatform from "./platform/ElectronPlatform"; import WebPlatform from "./platform/WebPlatform"; import PlatformPeg from "matrix-react-sdk/src/PlatformPeg"; import SdkConfig from "matrix-react-sdk/src/SdkConfig"; +import {setTheme} from "matrix-react-sdk/src/theme"; import { initRageshake } from "./rageshakesetup"; @@ -138,7 +139,11 @@ export async function loadSkin() { console.log("Skin loaded!"); } -export async function loadApp(fragParams: {}, acceptBrowser: boolean, configError: Error) { +export async function loadTheme() { + setTheme(); +} + +export async function loadApp(fragParams: {}, acceptBrowser: boolean, configError: Error|void) { // load app.js async so that its code is not executed immediately and we can catch any exceptions const module = await import( /* webpackChunkName: "riot-web-app" */ From 7113fe7e31080b0efdf6132e440b9ec1569e8f37 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 8 Apr 2020 16:24:40 +0100 Subject: [PATCH 06/21] comments Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/vector/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vector/index.ts b/src/vector/index.ts index f95cbc49..cd33ab32 100644 --- a/src/vector/index.ts +++ b/src/vector/index.ts @@ -79,6 +79,8 @@ function checkBrowserFeatures() { // React depends on Map & Set which we check for using modernizr's es6collections // if modernizr fails we may not have a functional react to show the error message. // try in react but fallback to an `alert` +// We start loading stuff but don't block on it until as late as possible to allow +// the browser to use as much parallelism as it can. async function start() { // load init.ts async so that its code is not executed immediately and we can catch any exceptions const { @@ -97,7 +99,6 @@ async function start() { await settled(rageshakePromise); // give rageshake a chance to load/fail - const fragparts = parseQsFromFragment(window.location); // don't try to redirect to the native apps if we're From b3780445d317a89427133d61cc9fe9c369e12bc1 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 8 Apr 2020 16:31:58 +0100 Subject: [PATCH 07/21] fix typescript types Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/@types/global.d.ts | 7 +++++-- src/vector/{init.ts => init.tsx} | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) rename src/vector/{init.ts => init.tsx} (99%) diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts index a19e20b5..6a5adec6 100644 --- a/src/@types/global.d.ts +++ b/src/@types/global.d.ts @@ -14,8 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {ReactNode} from "react"; import "modernizr"; +import {Renderer} from "react-dom"; declare global { interface Window { @@ -25,7 +25,10 @@ declare global { }; mxSendRageshake: (text: string, withLogs?: boolean) => void; - matrixChat: ReactNode; + matrixChat: ReturnType; + + // electron-only + ipcRenderer: any; } // workaround for https://github.com/microsoft/TypeScript/issues/30933 diff --git a/src/vector/init.ts b/src/vector/init.tsx similarity index 99% rename from src/vector/init.ts rename to src/vector/init.tsx index 85f75181..d325dbae 100644 --- a/src/vector/init.ts +++ b/src/vector/init.tsx @@ -36,7 +36,7 @@ import { initRageshake } from "./rageshakesetup"; export const rageshakePromise = initRageshake(); export function preparePlatform() { - if ((window).ipcRenderer) { + if (window.ipcRenderer) { console.log("Using Electron platform"); const plaf = new ElectronPlatform(); PlatformPeg.set(plaf); From e267086a1733b344ab124a6511ce8de28ac0efba Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 8 Apr 2020 19:21:39 +0100 Subject: [PATCH 08/21] Parallelize loadSkin Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/vector/index.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/vector/index.ts b/src/vector/index.ts index cd33ab32..651b0191 100644 --- a/src/vector/index.ts +++ b/src/vector/index.ts @@ -76,6 +76,11 @@ function checkBrowserFeatures() { return featureComplete; } +let acceptBrowser = checkBrowserFeatures(); +if (!acceptBrowser && window.localStorage) { + acceptBrowser = Boolean(window.localStorage.getItem("mx_accepts_unsupported_browser")); +} + // React depends on Map & Set which we check for using modernizr's es6collections // if modernizr fails we may not have a functional react to show the error message. // try in react but fallback to an `alert` @@ -124,22 +129,17 @@ async function start() { // load config requires the platform to be ready const loadConfigPromise = loadConfig(); - await loadSkin(); - - let acceptBrowser = checkBrowserFeatures(); - if (!acceptBrowser && window.localStorage) { - acceptBrowser = Boolean(window.localStorage.getItem("mx_accepts_unsupported_browser")); - } - // await config here const configError = await loadConfigPromise; // Load language after loading config.json so that settingsDefaults.language can be applied const loadLanguagePromise = loadLanguage(); // as quickly as we possibly can, set a default theme... const loadThemePromise = loadTheme(); + const loadSkinPromise = loadSkin(); // await things starting successfully await loadOlmPromise; + await settled(loadSkinPromise); await loadThemePromise; await loadLanguagePromise; From 7633009ddb1760bdfc6e2a5f00fe602b9a44fbc5 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 8 Apr 2020 19:35:16 +0100 Subject: [PATCH 09/21] clean up loadConfig Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/vector/index.ts | 77 ++++++++++++++++++++++++++------------------- src/vector/init.tsx | 19 +++-------- 2 files changed, 49 insertions(+), 47 deletions(-) diff --git a/src/vector/index.ts b/src/vector/index.ts index 651b0191..bd5de6bf 100644 --- a/src/vector/index.ts +++ b/src/vector/index.ts @@ -102,49 +102,60 @@ async function start() { /* webpackPreload: true */ "./init"); - await settled(rageshakePromise); // give rageshake a chance to load/fail + try { + await settled(rageshakePromise); // give rageshake a chance to load/fail - const fragparts = parseQsFromFragment(window.location); + const fragparts = parseQsFromFragment(window.location); - // don't try to redirect to the native apps if we're - // verifying a 3pid (but after we've loaded the config) - // or if the user is following a deep link - // (https://github.com/vector-im/riot-web/issues/7378) - const preventRedirect = fragparts.params.client_secret || fragparts.location.length > 0; + // don't try to redirect to the native apps if we're + // verifying a 3pid (but after we've loaded the config) + // or if the user is following a deep link + // (https://github.com/vector-im/riot-web/issues/7378) + const preventRedirect = fragparts.params.client_secret || fragparts.location.length > 0; - if (!preventRedirect) { - const isIos = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream; - const isAndroid = /Android/.test(navigator.userAgent); - if (isIos || isAndroid) { - if (document.cookie.indexOf("riot_mobile_redirect_to_guide=false") === -1) { - window.location.href = "mobile_guide/"; - return; + if (!preventRedirect) { + const isIos = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream; + const isAndroid = /Android/.test(navigator.userAgent); + if (isIos || isAndroid) { + if (document.cookie.indexOf("riot_mobile_redirect_to_guide=false") === -1) { + window.location.href = "mobile_guide/"; + return; + } } } - } - const loadOlmPromise = loadOlm(); - // set the platform for react sdk - preparePlatform(); - // load config requires the platform to be ready - const loadConfigPromise = loadConfig(); + const loadOlmPromise = loadOlm(); + // set the platform for react sdk + preparePlatform(); + // load config requires the platform to be ready + const loadConfigPromise = loadConfig(); - // await config here - const configError = await loadConfigPromise; - // Load language after loading config.json so that settingsDefaults.language can be applied - const loadLanguagePromise = loadLanguage(); - // as quickly as we possibly can, set a default theme... - const loadThemePromise = loadTheme(); - const loadSkinPromise = loadSkin(); + let configError; + try { + // await config here + await loadConfigPromise; + } catch (err) { + configError = err; + } - // await things starting successfully - await loadOlmPromise; - await settled(loadSkinPromise); - await loadThemePromise; - await loadLanguagePromise; + // Load language after loading config.json so that settingsDefaults.language can be applied + const loadLanguagePromise = loadLanguage(); + // as quickly as we possibly can, set a default theme... + const loadThemePromise = loadTheme(); + const loadSkinPromise = loadSkin(); + + // await things starting successfully + await loadOlmPromise; + await settled(loadSkinPromise); + await loadThemePromise; + await loadLanguagePromise; // Finally, load the app. All of the other react-sdk imports are in this file which causes the skinner to // run on the components. await loadApp(fragparts.params, acceptBrowser, configError); } -start(); +start().catch(err => { + if (!acceptBrowser) { + alert("Incompatible browser"); + } +}); diff --git a/src/vector/init.tsx b/src/vector/init.tsx index d325dbae..47927762 100644 --- a/src/vector/init.tsx +++ b/src/vector/init.tsx @@ -47,20 +47,11 @@ export function preparePlatform() { } export async function loadConfig(): Promise { - const platform = PlatformPeg.get(); - - let configJson; - try { - configJson = await platform.getConfig(); - } catch (e) { - return e; - } finally { - // XXX: We call this twice, once here and once in MatrixChat as a prop. We call it here to ensure - // granular settings are loaded correctly and to avoid duplicating the override logic for the theme. - // - // Note: this isn't called twice for some wrappers, like the Jitsi wrapper. - SdkConfig.put(configJson || {}); - } + // XXX: We call this twice, once here and once in MatrixChat as a prop. We call it here to ensure + // granular settings are loaded correctly and to avoid duplicating the override logic for the theme. + // + // Note: this isn't called twice for some wrappers, like the Jitsi wrapper. + SdkConfig.put(PlatformPeg.get().getConfig() || {}); } export function loadOlm(): Promise { From 6a5268f09ba6182a899ad6ef2eadc652124e6e4a Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 8 Apr 2020 19:36:06 +0100 Subject: [PATCH 10/21] fix loadConfig Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/vector/init.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vector/init.tsx b/src/vector/init.tsx index 47927762..a0fe3f4d 100644 --- a/src/vector/init.tsx +++ b/src/vector/init.tsx @@ -46,12 +46,12 @@ export function preparePlatform() { } } -export async function loadConfig(): Promise { +export async function loadConfig() { // XXX: We call this twice, once here and once in MatrixChat as a prop. We call it here to ensure // granular settings are loaded correctly and to avoid duplicating the override logic for the theme. // // Note: this isn't called twice for some wrappers, like the Jitsi wrapper. - SdkConfig.put(PlatformPeg.get().getConfig() || {}); + SdkConfig.put(await PlatformPeg.get().getConfig() || {}); } export function loadOlm(): Promise { From 4954c732ee0c2600e80bc6898f6595e2662b8ab0 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 8 Apr 2020 19:47:52 +0100 Subject: [PATCH 11/21] extract config error handling out of app.js Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/ErrorView.tsx | 40 +++++++++++++++++++++++++ src/vector/app.js | 31 ++----------------- src/vector/index.ts | 38 +++++++++++++++++++---- src/vector/init.tsx | 24 +++++++++++++-- 4 files changed, 96 insertions(+), 37 deletions(-) create mode 100644 src/components/structures/ErrorView.tsx diff --git a/src/components/structures/ErrorView.tsx b/src/components/structures/ErrorView.tsx new file mode 100644 index 00000000..566a8480 --- /dev/null +++ b/src/components/structures/ErrorView.tsx @@ -0,0 +1,40 @@ +/* +Copyright 2020 New Vector Ltd + +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 * as React from "react"; +import * as PropTypes from "prop-types"; + +interface IProps { + title: React.ReactNode; + message: React.ReactNode; +} + +const ErrorView: React.FC = ({title, message}) => { + return
+
+

{ title }

+

{ message }

+
+
; +}; + +ErrorView.propTypes = { + title: PropTypes.object.isRequired, // jsx for title + message: PropTypes.object.isRequired, // jsx to display +}; + +export default ErrorView; + diff --git a/src/vector/app.js b/src/vector/app.js index 12706d90..d0acce63 100644 --- a/src/vector/app.js +++ b/src/vector/app.js @@ -126,7 +126,7 @@ function onTokenLoginCompleted() { window.location.href = formatted; } -export async function loadApp(fragParams: {}, acceptBrowser: boolean, configError: Error|void) { +export async function loadApp(fragParams: {}, acceptBrowser: boolean) { // XXX: the way we pass the path to the worker script from webpack via html in body's dataset is a hack // but alternatives seem to require changing the interface to passing Workers to js-sdk const vectorIndexeddbWorkerScript = document.body.dataset.vectorIndexeddbWorkerScript; @@ -146,36 +146,9 @@ export async function loadApp(fragParams: {}, acceptBrowser: boolean, configErro const params = parseQs(window.location); - // Now that we've loaded the theme (CSS), display the config syntax error if needed. - if (configError && configError.err && configError.err instanceof SyntaxError) { - const errorMessage = ( -
-

- {_t( - "Your Riot configuration contains invalid JSON. Please correct the problem " + - "and reload the page.", - )} -

-

- {_t( - "The message from the parser is: %(message)s", - {message: configError.err.message || _t("Invalid JSON")}, - )} -

-
- ); - - const GenericErrorPage = sdk.getComponent("structures.GenericErrorPage"); - return ; - } - const urlWithoutQuery = window.location.protocol + '//' + window.location.host + window.location.pathname; console.log("Vector starting at " + urlWithoutQuery); - if (configError) { - return
- Unable to load config file: please refresh the page to try again. -
; - } else if (acceptBrowser) { + if (acceptBrowser) { platform.startUpdater(); try { diff --git a/src/vector/index.ts b/src/vector/index.ts index bd5de6bf..27b48df8 100644 --- a/src/vector/index.ts +++ b/src/vector/index.ts @@ -97,6 +97,8 @@ async function start() { loadLanguage, loadTheme, loadApp, + showError, + _t, } = await import( /* webpackChunkName: "init" */ /* webpackPreload: true */ @@ -130,12 +132,18 @@ async function start() { // load config requires the platform to be ready const loadConfigPromise = loadConfig(); - let configError; try { // await config here await loadConfigPromise; - } catch (err) { - configError = err; + } catch (error) { + // Now that we've loaded the theme (CSS), display the config syntax error if needed. + if (error.err && error.err instanceof SyntaxError) { + return showError(_t("Your Riot is misconfigured"), [ + _t("Your Riot configuration contains invalid JSON. Please correct the problem and reload the page."), + _t("The message from the parser is: %(message)s", { message: error.err.message || _t("Invalid JSON")}), + ]); + } + return showError(_t("Unable to load config file: please refresh the page to try again.")); } // Load language after loading config.json so that settingsDefaults.language can be applied @@ -150,9 +158,27 @@ async function start() { await loadThemePromise; await loadLanguagePromise; - // Finally, load the app. All of the other react-sdk imports are in this file which causes the skinner to - // run on the components. - await loadApp(fragparts.params, acceptBrowser, configError); + if (!acceptBrowser) { + await new Promise(resolve => { + // todo + }); + } + + // Finally, load the app. All of the other react-sdk imports are in this file which causes the skinner to + // run on the components. + await loadApp(fragparts.params, acceptBrowser); + } catch (err) { + console.trace(err); + // check errors in this order: + // Browser Compatibility (skippable) + // config.json + // runtime errors + const { showError } = await import( + /* webpackChunkName: "init" */ + /* webpackPreload: true */ + "./init"); + await showError(err); + } } start().catch(err => { if (!acceptBrowser) { diff --git a/src/vector/init.tsx b/src/vector/init.tsx index a0fe3f4d..8e929351 100644 --- a/src/vector/init.tsx +++ b/src/vector/init.tsx @@ -21,6 +21,7 @@ limitations under the License. import olmWasmPath from "olm/olm.wasm"; import Olm from 'olm'; import * as ReactDOM from "react-dom"; +import * as React from "react"; import * as languageHandler from "matrix-react-sdk/src/languageHandler"; import SettingsStore from "matrix-react-sdk/src/settings/SettingsStore"; @@ -134,12 +135,31 @@ export async function loadTheme() { setTheme(); } -export async function loadApp(fragParams: {}, acceptBrowser: boolean, configError: Error|void) { +export async function loadApp(fragParams: {}, acceptBrowser: boolean) { // load app.js async so that its code is not executed immediately and we can catch any exceptions const module = await import( /* webpackChunkName: "riot-web-app" */ /* webpackPreload: true */ "./app"); - window.matrixChat = ReactDOM.render(await module.loadApp(fragParams, acceptBrowser, configError), + window.matrixChat = ReactDOM.render(await module.loadApp(fragParams, acceptBrowser), document.getElementById('matrixchat')); } + +export async function showError(title: string, messages?: string[]) { + const ErrorView = (await import( + /* webpackChunkName: "error-view" */ + /* webpackPreload: true */ + "../components/structures/ErrorView")).default; + const message =
+ {messages && messages.map(msg =>

+ {languageHandler._t( + "Your Riot configuration contains invalid JSON. Please correct the problem and reload the page.", + )} +

)} +
; + + window.matrixChat = ReactDOM.render(, + document.getElementById('matrixchat')); +} + +export const _t = languageHandler._t; From 2837c41ca421d029e0f39d8a73cdc3f0d0cc7542 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 8 Apr 2020 20:03:45 +0100 Subject: [PATCH 12/21] factor out config error handling Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/ErrorView.tsx | 20 +++++++----- src/vector/index.ts | 42 +++++++++++++++---------- src/vector/init.tsx | 10 +----- 3 files changed, 40 insertions(+), 32 deletions(-) diff --git a/src/components/structures/ErrorView.tsx b/src/components/structures/ErrorView.tsx index 566a8480..6941dbf1 100644 --- a/src/components/structures/ErrorView.tsx +++ b/src/components/structures/ErrorView.tsx @@ -17,23 +17,29 @@ limitations under the License. import * as React from "react"; import * as PropTypes from "prop-types"; +import { _t } from "matrix-react-sdk/src/languageHandler"; + interface IProps { - title: React.ReactNode; - message: React.ReactNode; + title: string; + messages?: string[]; } -const ErrorView: React.FC = ({title, message}) => { +const ErrorView: React.FC = ({title, messages}) => { return
-

{ title }

-

{ message }

+

{title}

+
+ {messages && messages.map(msg =>

+ { _t(msg) } +

)} +
; }; ErrorView.propTypes = { - title: PropTypes.object.isRequired, // jsx for title - message: PropTypes.object.isRequired, // jsx to display + title: PropTypes.string.isRequired, + messages: PropTypes.arrayOf(PropTypes.string.isRequired), }; export default ErrorView; diff --git a/src/vector/index.ts b/src/vector/index.ts index 27b48df8..0d3a8e87 100644 --- a/src/vector/index.ts +++ b/src/vector/index.ts @@ -131,6 +131,28 @@ async function start() { preparePlatform(); // load config requires the platform to be ready const loadConfigPromise = loadConfig(); + await settled(loadConfigPromise); // wait for it to settle + // keep initialising so that we can show any possible error with as many features (theme, i18n) as possible + + // Load language after loading config.json so that settingsDefaults.language can be applied + const loadLanguagePromise = loadLanguage(); + // as quickly as we possibly can, set a default theme... + const loadThemePromise = loadTheme(); + const loadSkinPromise = loadSkin(); + + // await things settling so that any errors we have to render have features like i18n running + await settled(loadSkinPromise); + await settled(loadThemePromise); + await settled(loadLanguagePromise); + + // ########################## + // error handling begins here + // ########################## + if (!acceptBrowser) { + await new Promise(resolve => { + // todo + }); + } try { // await config here @@ -146,33 +168,20 @@ async function start() { return showError(_t("Unable to load config file: please refresh the page to try again.")); } - // Load language after loading config.json so that settingsDefaults.language can be applied - const loadLanguagePromise = loadLanguage(); - // as quickly as we possibly can, set a default theme... - const loadThemePromise = loadTheme(); - const loadSkinPromise = loadSkin(); - + // ################################## + // app load critical path starts here // await things starting successfully + // ################################## await loadOlmPromise; await settled(loadSkinPromise); await loadThemePromise; await loadLanguagePromise; - if (!acceptBrowser) { - await new Promise(resolve => { - // todo - }); - } - // Finally, load the app. All of the other react-sdk imports are in this file which causes the skinner to // run on the components. await loadApp(fragparts.params, acceptBrowser); } catch (err) { console.trace(err); - // check errors in this order: - // Browser Compatibility (skippable) - // config.json - // runtime errors const { showError } = await import( /* webpackChunkName: "init" */ /* webpackPreload: true */ @@ -181,6 +190,7 @@ async function start() { } } start().catch(err => { + console.error(err); if (!acceptBrowser) { alert("Incompatible browser"); } diff --git a/src/vector/init.tsx b/src/vector/init.tsx index 8e929351..583d96a9 100644 --- a/src/vector/init.tsx +++ b/src/vector/init.tsx @@ -150,15 +150,7 @@ export async function showError(title: string, messages?: string[]) { /* webpackChunkName: "error-view" */ /* webpackPreload: true */ "../components/structures/ErrorView")).default; - const message =
- {messages && messages.map(msg =>

- {languageHandler._t( - "Your Riot configuration contains invalid JSON. Please correct the problem and reload the page.", - )} -

)} -
; - - window.matrixChat = ReactDOM.render(, + window.matrixChat = ReactDOM.render(, document.getElementById('matrixchat')); } From f6ad5bf54c97c3de61e05e58f34b09c16f131e11 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 8 Apr 2020 20:12:05 +0100 Subject: [PATCH 13/21] let settled accept multiple proms + i18n Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/i18n/strings/en_EN.json | 9 +++++---- src/vector/index.ts | 18 +++++++++--------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index b77de122..3582ca35 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1,11 +1,12 @@ { + "Unexpected error preparing the app. See console for details.": "Unexpected error preparing the app. See console for details.", + "Your Riot is misconfigured": "Your Riot is misconfigured", + "Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.", + "Invalid configuration: no default server specified.": "Invalid configuration: no default server specified.", "Your Riot configuration contains invalid JSON. Please correct the problem and reload the page.": "Your Riot configuration contains invalid JSON. Please correct the problem and reload the page.", "The message from the parser is: %(message)s": "The message from the parser is: %(message)s", "Invalid JSON": "Invalid JSON", - "Your Riot is misconfigured": "Your Riot is misconfigured", - "Unexpected error preparing the app. See console for details.": "Unexpected error preparing the app. See console for details.", - "Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.", - "Invalid configuration: no default server specified.": "Invalid configuration: no default server specified.", + "Unable to load config file: please refresh the page to try again.": "Unable to load config file: please refresh the page to try again.", "Open user settings": "Open user settings", "Riot Desktop on %(platformName)s": "Riot Desktop on %(platformName)s", "Go to your browser to complete Sign In": "Go to your browser to complete Sign In", diff --git a/src/vector/index.ts b/src/vector/index.ts index 0d3a8e87..f3c091f5 100644 --- a/src/vector/index.ts +++ b/src/vector/index.ts @@ -33,11 +33,13 @@ if ('serviceWorker' in navigator) { navigator.serviceWorker.register('sw.js'); } -async function settled(prom: Promise) { - try { - await prom; - } catch (e) { - console.error(e); +async function settled(...promises: Array>) { + for (const prom of promises) { + try { + await prom; + } catch (e) { + console.error(e); + } } } @@ -141,9 +143,7 @@ async function start() { const loadSkinPromise = loadSkin(); // await things settling so that any errors we have to render have features like i18n running - await settled(loadSkinPromise); - await settled(loadThemePromise); - await settled(loadLanguagePromise); + await settled(loadSkinPromise, loadThemePromise, loadLanguagePromise); // ########################## // error handling begins here @@ -173,7 +173,7 @@ async function start() { // await things starting successfully // ################################## await loadOlmPromise; - await settled(loadSkinPromise); + await loadSkinPromise; await loadThemePromise; await loadLanguagePromise; From cc939f9645971b288231616dc929981e67a8dce8 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 8 Apr 2020 21:41:22 +0100 Subject: [PATCH 14/21] extract browser compatibility error handling out of app.js Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/vector/app.js | 64 +++++++++++++++++++-------------------------- src/vector/index.ts | 16 +++++++++--- src/vector/init.tsx | 13 +++++++-- 3 files changed, 51 insertions(+), 42 deletions(-) diff --git a/src/vector/app.js b/src/vector/app.js index d0acce63..222a76a0 100644 --- a/src/vector/app.js +++ b/src/vector/app.js @@ -126,7 +126,7 @@ function onTokenLoginCompleted() { window.location.href = formatted; } -export async function loadApp(fragParams: {}, acceptBrowser: boolean) { +export async function loadApp(fragParams: {}) { // XXX: the way we pass the path to the worker script from webpack via html in body's dataset is a hack // but alternatives seem to require changing the interface to passing Workers to js-sdk const vectorIndexeddbWorkerScript = document.body.dataset.vectorIndexeddbWorkerScript; @@ -148,45 +148,35 @@ export async function loadApp(fragParams: {}, acceptBrowser: boolean) { const urlWithoutQuery = window.location.protocol + '//' + window.location.host + window.location.pathname; console.log("Vector starting at " + urlWithoutQuery); - if (acceptBrowser) { - platform.startUpdater(); - try { - // Don't bother loading the app until the config is verified - const config = await verifyServerConfig(); - const MatrixChat = sdk.getComponent('structures.MatrixChat'); - return ; - } catch (err) { - console.error(err); + platform.startUpdater(); - let errorMessage = err.translatedMessage - || _t("Unexpected error preparing the app. See console for details."); - errorMessage = {errorMessage}; + try { + // Don't bother loading the app until the config is verified + const config = await verifyServerConfig(); + const MatrixChat = sdk.getComponent('structures.MatrixChat'); + return ; + } catch (err) { + console.error(err); - // Like the compatibility page, AWOOOOOGA at the user - const GenericErrorPage = sdk.getComponent("structures.GenericErrorPage"); - return ; - } - } else { - console.error("Browser is missing required features."); - // take to a different landing page to AWOOOOOGA at the user - const CompatibilityPage = sdk.getComponent("structures.CompatibilityPage"); - return ; + let errorMessage = err.translatedMessage + || _t("Unexpected error preparing the app. See console for details."); + errorMessage = {errorMessage}; + + // Like the compatibility page, AWOOOOOGA at the user + const GenericErrorPage = sdk.getComponent("structures.GenericErrorPage"); + return ; } } diff --git a/src/vector/index.ts b/src/vector/index.ts index f3c091f5..1436171f 100644 --- a/src/vector/index.ts +++ b/src/vector/index.ts @@ -100,6 +100,7 @@ async function start() { loadTheme, loadApp, showError, + showIncompatibleBrowser, _t, } = await import( /* webpackChunkName: "init" */ @@ -148,9 +149,18 @@ async function start() { // ########################## // error handling begins here // ########################## + console.log("DEBUG", acceptBrowser); if (!acceptBrowser) { await new Promise(resolve => { - // todo + console.error("Browser is missing required features."); + // take to a different landing page to AWOOOOOGA at the user + showIncompatibleBrowser(() => { + if (window.localStorage) { + window.localStorage.setItem('mx_accepts_unsupported_browser', String(true)); + } + console.log("User accepts the compatibility risks."); + resolve(); + }); }); } @@ -170,7 +180,7 @@ async function start() { // ################################## // app load critical path starts here - // await things starting successfully + // assert things started successfully // ################################## await loadOlmPromise; await loadSkinPromise; @@ -179,7 +189,7 @@ async function start() { // Finally, load the app. All of the other react-sdk imports are in this file which causes the skinner to // run on the components. - await loadApp(fragparts.params, acceptBrowser); + await loadApp(fragparts.params); } catch (err) { console.trace(err); const { showError } = await import( diff --git a/src/vector/init.tsx b/src/vector/init.tsx index 583d96a9..c7c9141e 100644 --- a/src/vector/init.tsx +++ b/src/vector/init.tsx @@ -135,13 +135,13 @@ export async function loadTheme() { setTheme(); } -export async function loadApp(fragParams: {}, acceptBrowser: boolean) { +export async function loadApp(fragParams: {}) { // load app.js async so that its code is not executed immediately and we can catch any exceptions const module = await import( /* webpackChunkName: "riot-web-app" */ /* webpackPreload: true */ "./app"); - window.matrixChat = ReactDOM.render(await module.loadApp(fragParams, acceptBrowser), + window.matrixChat = ReactDOM.render(await module.loadApp(fragParams), document.getElementById('matrixchat')); } @@ -154,4 +154,13 @@ export async function showError(title: string, messages?: string[]) { document.getElementById('matrixchat')); } +export async function showIncompatibleBrowser(onAccept) { + const CompatibilityPage = (await import( + /* webpackChunkName: "compatibility-page" */ + /* webpackPreload: true */ + "matrix-react-sdk/src/components/structures/CompatibilityPage")).default; + window.matrixChat = ReactDOM.render(, + document.getElementById('matrixchat')); +} + export const _t = languageHandler._t; From 343d4ea64183c09d2f0faf49fff226706e4cd17d Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 8 Apr 2020 21:49:27 +0100 Subject: [PATCH 15/21] small tweaks Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/vector/index.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/vector/index.ts b/src/vector/index.ts index 1436171f..e018893f 100644 --- a/src/vector/index.ts +++ b/src/vector/index.ts @@ -191,17 +191,13 @@ async function start() { // run on the components. await loadApp(fragparts.params); } catch (err) { - console.trace(err); - const { showError } = await import( - /* webpackChunkName: "init" */ - /* webpackPreload: true */ - "./init"); + console.error(err); await showError(err); } } start().catch(err => { console.error(err); if (!acceptBrowser) { - alert("Incompatible browser"); + // TODO redirect to static incompatible browser page } }); From 0572d62c88a899816098ce438698370dca2f8bac Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 9 Apr 2020 10:32:04 +0100 Subject: [PATCH 16/21] extract app load error handler from app.js Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/vector/app.js | 42 +++++++++++++++--------------------------- src/vector/index.ts | 7 ++++++- 2 files changed, 21 insertions(+), 28 deletions(-) diff --git a/src/vector/app.js b/src/vector/app.js index 222a76a0..e92cdd2d 100644 --- a/src/vector/app.js +++ b/src/vector/app.js @@ -151,33 +151,21 @@ export async function loadApp(fragParams: {}) { platform.startUpdater(); - try { - // Don't bother loading the app until the config is verified - const config = await verifyServerConfig(); - const MatrixChat = sdk.getComponent('structures.MatrixChat'); - return ; - } catch (err) { - console.error(err); - - let errorMessage = err.translatedMessage - || _t("Unexpected error preparing the app. See console for details."); - errorMessage = {errorMessage}; - - // Like the compatibility page, AWOOOOOGA at the user - const GenericErrorPage = sdk.getComponent("structures.GenericErrorPage"); - return ; - } + // Don't bother loading the app until the config is verified + const config = await verifyServerConfig(); + const MatrixChat = sdk.getComponent('structures.MatrixChat'); + return ; } async function verifyServerConfig() { diff --git a/src/vector/index.ts b/src/vector/index.ts index e018893f..1c89c431 100644 --- a/src/vector/index.ts +++ b/src/vector/index.ts @@ -21,6 +21,8 @@ limitations under the License. // Require common CSS here; this will make webpack process it into bundle.css. // Our own CSS (which is themed) is imported via separate webpack entry points // in webpack.config.js +import React from "react"; + require('gfm.css/gfm.css'); require('highlight.js/styles/github.css'); @@ -192,7 +194,10 @@ async function start() { await loadApp(fragparts.params); } catch (err) { console.error(err); - await showError(err); + // Like the compatibility page, AWOOOOOGA at the user + await showError(_t("Your Riot is misconfigured"), [ + err.translatedMessage || _t("Unexpected error preparing the app. See console for details."), + ]); } } start().catch(err => { From 8c88e9f0f48262faf96b50a3cac6bdea8476b1af Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 9 Apr 2020 10:42:58 +0100 Subject: [PATCH 17/21] delint and i18n Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/i18n/strings/en_EN.json | 4 ++-- src/vector/app.js | 2 +- src/vector/index.ts | 2 -- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 3582ca35..9468bb8b 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1,12 +1,12 @@ { - "Unexpected error preparing the app. See console for details.": "Unexpected error preparing the app. See console for details.", - "Your Riot is misconfigured": "Your Riot is misconfigured", "Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.", "Invalid configuration: no default server specified.": "Invalid configuration: no default server specified.", + "Your Riot is misconfigured": "Your Riot is misconfigured", "Your Riot configuration contains invalid JSON. Please correct the problem and reload the page.": "Your Riot configuration contains invalid JSON. Please correct the problem and reload the page.", "The message from the parser is: %(message)s": "The message from the parser is: %(message)s", "Invalid JSON": "Invalid JSON", "Unable to load config file: please refresh the page to try again.": "Unable to load config file: please refresh the page to try again.", + "Unexpected error preparing the app. See console for details.": "Unexpected error preparing the app. See console for details.", "Open user settings": "Open user settings", "Riot Desktop on %(platformName)s": "Riot Desktop on %(platformName)s", "Go to your browser to complete Sign In": "Go to your browser to complete Sign In", diff --git a/src/vector/app.js b/src/vector/app.js index e92cdd2d..d446b38b 100644 --- a/src/vector/app.js +++ b/src/vector/app.js @@ -26,7 +26,7 @@ global.React = React; import * as sdk from 'matrix-react-sdk'; import PlatformPeg from 'matrix-react-sdk/src/PlatformPeg'; import * as VectorConferenceHandler from 'matrix-react-sdk/src/VectorConferenceHandler'; -import {_t, _td, newTranslatableError} from 'matrix-react-sdk/src/languageHandler'; +import {_td, newTranslatableError} from 'matrix-react-sdk/src/languageHandler'; import AutoDiscoveryUtils from 'matrix-react-sdk/src/utils/AutoDiscoveryUtils'; import {AutoDiscovery} from "matrix-js-sdk/src/autodiscovery"; import * as Lifecycle from "matrix-react-sdk/src/Lifecycle"; diff --git a/src/vector/index.ts b/src/vector/index.ts index 1c89c431..cb877320 100644 --- a/src/vector/index.ts +++ b/src/vector/index.ts @@ -21,8 +21,6 @@ limitations under the License. // Require common CSS here; this will make webpack process it into bundle.css. // Our own CSS (which is themed) is imported via separate webpack entry points // in webpack.config.js -import React from "react"; - require('gfm.css/gfm.css'); require('highlight.js/styles/github.css'); From e1bdcf2d9ed8be85ea9d8733c99cb6d23ab674c6 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 9 Apr 2020 10:49:50 +0100 Subject: [PATCH 18/21] remove debug statement Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/vector/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vector/index.ts b/src/vector/index.ts index cb877320..8753101f 100644 --- a/src/vector/index.ts +++ b/src/vector/index.ts @@ -149,7 +149,6 @@ async function start() { // ########################## // error handling begins here // ########################## - console.log("DEBUG", acceptBrowser); if (!acceptBrowser) { await new Promise(resolve => { console.error("Browser is missing required features."); From 83653b3a22c0be59a9f517474fe1c0ee9ae23cb3 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 9 Apr 2020 11:14:38 +0100 Subject: [PATCH 19/21] assert rageshake loaded successfully Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/vector/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vector/index.ts b/src/vector/index.ts index 8753101f..bf42da00 100644 --- a/src/vector/index.ts +++ b/src/vector/index.ts @@ -181,6 +181,7 @@ async function start() { // app load critical path starts here // assert things started successfully // ################################## + await rageshakePromise; await loadOlmPromise; await loadSkinPromise; await loadThemePromise; From 942ca3b525d67a74ce01a9e3138ccee2a764f892 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 9 Apr 2020 11:19:40 +0100 Subject: [PATCH 20/21] make error translatable Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/i18n/strings/en_EN.json | 1 + src/vector/app.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 9468bb8b..a7f2f40c 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1,4 +1,5 @@ { + "Missing indexeddb worker script!": "Missing indexeddb worker script!", "Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.", "Invalid configuration: no default server specified.": "Invalid configuration: no default server specified.", "Your Riot is misconfigured": "Your Riot is misconfigured", diff --git a/src/vector/app.js b/src/vector/app.js index d446b38b..930576e2 100644 --- a/src/vector/app.js +++ b/src/vector/app.js @@ -135,7 +135,7 @@ export async function loadApp(fragParams: {}) { // the bundling. The js-sdk will just fall back to accessing // indexeddb directly with no worker script, but we want to // make sure the indexeddb script is present, so fail hard. - throw new Error("Missing indexeddb worker script!"); + throw newTranslatableError(_td("Missing indexeddb worker script!")); } MatrixClientPeg.setIndexedDbWorkerScript(vectorIndexeddbWorkerScript); CallHandler.setConferenceHandler(VectorConferenceHandler); From c67dcae35e7ec5d1ebbbdbcc4fef550b07ae63b9 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 9 Apr 2020 11:25:40 +0100 Subject: [PATCH 21/21] improve comments Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/vector/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vector/index.ts b/src/vector/index.ts index bf42da00..a4f494bd 100644 --- a/src/vector/index.ts +++ b/src/vector/index.ts @@ -88,6 +88,7 @@ if (!acceptBrowser && window.localStorage) { // try in react but fallback to an `alert` // We start loading stuff but don't block on it until as late as possible to allow // the browser to use as much parallelism as it can. +// Load parallelism is based on research in https://github.com/vector-im/riot-web/issues/12253 async function start() { // load init.ts async so that its code is not executed immediately and we can catch any exceptions const {