Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

App load order changes to catch errors better #13095

Merged
merged 21 commits into from
Apr 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/@types/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -25,7 +25,10 @@ declare global {
};

mxSendRageshake: (text: string, withLogs?: boolean) => void;
matrixChat: ReactNode;
matrixChat: ReturnType<Renderer>;

// electron-only
ipcRenderer: any;
}

// workaround for https://github.com/microsoft/TypeScript/issues/30933
Expand Down
46 changes: 46 additions & 0 deletions src/components/structures/ErrorView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
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";

import { _t } from "matrix-react-sdk/src/languageHandler";

interface IProps {
title: string;
messages?: string[];
}

const ErrorView: React.FC<IProps> = ({title, messages}) => {
return <div className="mx_GenericErrorPage">
<div className="mx_GenericErrorPage_box">
<h1>{title}</h1>
<div>
{messages && messages.map(msg => <p key={msg}>
{ _t(msg) }
</p>)}
</div>
</div>
</div>;
};

ErrorView.propTypes = {
title: PropTypes.string.isRequired,
messages: PropTypes.arrayOf(PropTypes.string.isRequired),
};

export default ErrorView;

8 changes: 5 additions & 3 deletions src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
{
"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",
"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",
"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.",
"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.",
"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",
Expand Down
106 changes: 21 additions & 85 deletions src/vector/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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, loadOlm} from "./init";

let lastLocationHashSet = null;

Expand Down Expand Up @@ -128,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;
Expand All @@ -137,99 +135,37 @@ export async function loadApp(fragParams: {}, acceptBrowser: boolean) {
// 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);

window.addEventListener('hashchange', onHashChange);

await loadOlm();

// set the platform for react sdk
preparePlatform();
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();

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 = (
<div>
<p>
{_t(
"Your Riot configuration contains invalid JSON. Please correct the problem " +
"and reload the page.",
)}
</p>
<p>
{_t(
"The message from the parser is: %(message)s",
{message: configError.err.message || _t("Invalid JSON")},
)}
</p>
</div>
);

const GenericErrorPage = sdk.getComponent("structures.GenericErrorPage");
return <GenericErrorPage message={errorMessage} title={_t("Your Riot is misconfigured")} />;
}

const urlWithoutQuery = window.location.protocol + '//' + window.location.host + window.location.pathname;
console.log("Vector starting at " + urlWithoutQuery);
if (configError) {
return <div className="error">
Unable to load config file: please refresh the page to try again.
</div>;
} else 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 <MatrixChat
onNewScreen={onNewScreen}
makeRegistrationUrl={makeRegistrationUrl}
ConferenceHandler={VectorConferenceHandler}
config={config}
realQueryParams={params}
startingFragmentQueryParams={fragParams}
enableGuest={!config.disable_guests}
onTokenLoginCompleted={onTokenLoginCompleted}
initialScreenAfterLogin={getScreenFromLocation(window.location)}
defaultDeviceDisplayName={platform.getDefaultDeviceDisplayName()}
/>;
} catch (err) {
console.error(err);

let errorMessage = err.translatedMessage
|| _t("Unexpected error preparing the app. See console for details.");
errorMessage = <span>{errorMessage}</span>;

// Like the compatibility page, AWOOOOOGA at the user
const GenericErrorPage = sdk.getComponent("structures.GenericErrorPage");
return <GenericErrorPage message={errorMessage} title={_t("Your Riot is misconfigured")} />;
}
} 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 <CompatibilityPage onAccept={function() {
if (window.localStorage) window.localStorage.setItem('mx_accepts_unsupported_browser', true);
console.log("User accepts the compatibility risks.");
loadApp();
}} />;
}

platform.startUpdater();

// Don't bother loading the app until the config is verified
const config = await verifyServerConfig();
const MatrixChat = sdk.getComponent('structures.MatrixChat');
return <MatrixChat
onNewScreen={onNewScreen}
makeRegistrationUrl={makeRegistrationUrl}
ConferenceHandler={VectorConferenceHandler}
config={config}
realQueryParams={params}
startingFragmentQueryParams={fragParams}
enableGuest={!config.disable_guests}
onTokenLoginCompleted={onTokenLoginCompleted}
initialScreenAfterLogin={getScreenFromLocation(window.location)}
defaultDeviceDisplayName={platform.getDefaultDeviceDisplayName()}
/>;
}

async function verifyServerConfig() {
Expand Down
Loading