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 tweaks, improve error pages #13329

Merged
merged 23 commits into from
Apr 30, 2020
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
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
1 change: 1 addition & 0 deletions __mocks__/cssMock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = "css-file-stub";
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@
"<rootDir>/node_modules/matrix-react-sdk/test/setupTests.js"
],
"moduleNameMapper": {
"\\.(css|scss)$": "<rootDir>/__mocks__/cssMock.js",
"\\.(gif|png|svg|ttf|woff2)$": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/imageMock.js",
"\\$webapp/i18n/languages.json": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/languages.json",
"^browser-request$": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/browser-request.js",
Expand Down
101 changes: 101 additions & 0 deletions res/css/structures/ErrorView.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
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 font-size variables manually, ideally this scss would get loaded by the theme which has all variables in context
@import "../../../node_modules/matrix-react-sdk/res/css/_font-sizes.scss";

.mx_ErrorView {
background: #c5e0f7;
background: -moz-linear-gradient(top, #c5e0f7 0%, #ffffff 100%);
background: -webkit-linear-gradient(top, #c5e0f7 0%, #ffffff 100%);
background: linear-gradient(to bottom, #c5e0f7 0%, #ffffff 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#c5e0f7', endColorstr='#ffffff',GradientType=0 );
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
width: 100%;
min-height: 100%;
height: auto;
color: #000;

.mx_ErrorView_container {
max-width: 680px;
margin: auto;
}

.mx_Button {
border: 0;
border-radius: 4px;
font-size: $font-18px;
margin-left: 4px;
margin-right: 4px;
min-width: 80px;
background-color: #03B381;
color: #fff;
cursor: pointer;
padding: 12px 22px;
word-break: break-word;
text-decoration: none;
}

.mx_Center {
justify-content: center;
}

.mx_HomePage_header {
color: #2E2F32;
display: flex;
align-items: center;
justify-content: center;
}

font-size: $font-16px;
h1 {
font-size: $font-32px;
}
h2 {
font-size: $font-24px;
color: #000;
}

.mx_HomePage_col {
display: flex;
flex-direction: row;
}

.mx_HomePage_row {
flex: 1 1 0;
display: flex;
flex-direction: row;
flex-wrap: wrap;
}

.mx_HomePage_logo {
margin: auto 20px auto 0;
}

h1, h2 {
font-weight: 600;
margin-bottom: 32px;
}

.mx_Spacer {
margin-top: 24px;
}

.mx_FooterLink {
color: #368BD6;
text-decoration: none;
}
}
2 changes: 1 addition & 1 deletion src/@types/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ limitations under the License.
*/

import "matrix-react-sdk/src/@types/global"; // load matrix-react-sdk's type extensions first
import {Renderer} from "react-dom";
import type {Renderer} from "react-dom";

declare global {
interface Window {
Expand Down
408 changes: 408 additions & 0 deletions src/async-components/structures/CompatibilityView.tsx

Large diffs are not rendered by default.

67 changes: 67 additions & 0 deletions src/async-components/structures/ErrorView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
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";

// directly import the style here as this layer does not support rethemedex at this time so no matrix-react-sdk
// scss variables will be accessible.
import "../../../res/css/structures/ErrorView.scss";

interface IProps {
// both of these should already be internationalised
title: string;
messages?: string[];
}

const ErrorView: React.FC<IProps> = ({title, messages}) => {
return <div className="mx_ErrorView">
<div className="mx_ErrorView_container">
<div className="mx_HomePage_header">
<span className="mx_HomePage_logo">
<img height="42" src="themes/riot/img/logos/riot-logo.svg" alt="Riot" />
</span>
<h1>{ _t("Failed to start") }</h1>
</div>
<div className="mx_HomePage_col">
<div className="mx_HomePage_row">
<div>
<h2 id="step1_heading">{ title }</h2>
{messages && messages.map(msg => <p key={msg}>
{ msg }
</p>)}
</div>
</div>
</div>
<div className="mx_HomePage_row mx_Center mx_Spacer">
<p className="mx_Spacer">
<a href="https://riot.im" target="_blank" className="mx_FooterLink">
Go to Riot.im
t3chguy marked this conversation as resolved.
Show resolved Hide resolved
</a>
</p>
</div>
</div>
</div>;
};

ErrorView.propTypes = {
t3chguy marked this conversation as resolved.
Show resolved Hide resolved
title: PropTypes.string.isRequired,
messages: PropTypes.arrayOf(PropTypes.string.isRequired),
};

export default ErrorView;

46 changes: 0 additions & 46 deletions src/components/structures/ErrorView.tsx

This file was deleted.

7 changes: 7 additions & 0 deletions src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@
"Custom Server Options": "Custom Server Options",
"You can use the custom server options to sign into other Matrix servers by specifying a different homeserver URL. This allows you to use Riot with an existing Matrix account on a different homeserver.": "You can use the custom server options to sign into other Matrix servers by specifying a different homeserver URL. This allows you to use Riot with an existing Matrix account on a different homeserver.",
"Dismiss": "Dismiss",
"Unsupported browser": "Unsupported browser",
"Your browser can't run Riot": "Your browser can't run Riot",
"Riot uses advanced browser features which aren't supported by your current browser.": "Riot uses advanced browser features which aren't supported by your current browser.",
"Please install <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, or <safariLink>Safari</safariLink> for the best experience.": "Please install <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, or <safariLink>Safari</safariLink> for the best experience.",
"You can continue using your current browser, but some or all features may not work and the look and feel of the application may be incorrect.": "You can continue using your current browser, but some or all features may not work and the look and feel of the application may be incorrect.",
"I understand the risks and wish to continue": "I understand the risks and wish to continue",
"Failed to start": "Failed to start",
"Welcome to Riot.im": "Welcome to Riot.im",
"Decentralised, encrypted chat &amp; collaboration powered by [matrix]": "Decentralised, encrypted chat &amp; collaboration powered by [matrix]",
"Sign In": "Sign In",
Expand Down
26 changes: 13 additions & 13 deletions src/vector/app.js → src/vector/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ limitations under the License.
*/

import React from 'react';
// add React and ReactPerf to the global namespace, to make them easier to
// access via the console
global.React = React;
// add React and ReactPerf to the global namespace, to make them easier to access via the console
// this incidentally means we can forget our React imports in JSX files without penalty.
window.React = React;

import * as sdk from 'matrix-react-sdk';
import PlatformPeg from 'matrix-react-sdk/src/PlatformPeg';
Expand All @@ -30,6 +30,7 @@ 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";
import type MatrixChatType from "matrix-react-sdk/src/components/structures/MatrixChat";

import url from 'url';

Expand All @@ -40,11 +41,11 @@ import SdkConfig from "matrix-react-sdk/src/SdkConfig";

import CallHandler from 'matrix-react-sdk/src/CallHandler';

let lastLocationHashSet = null;
let lastLocationHashSet: string = null;

// Parse the given window.location and return parameters that can be used when calling
// MatrixChat.showScreen(screen, params)
function getScreenFromLocation(location) {
function getScreenFromLocation(location: Location) {
const fragparts = parseQsFromFragment(location);
return {
screen: fragparts.location.substring(1),
Expand All @@ -54,15 +55,15 @@ function getScreenFromLocation(location) {

// Here, we do some crude URL analysis to allow
// deep-linking.
function routeUrl(location) {
function routeUrl(location: Location) {
if (!window.matrixChat) return;

console.log("Routing URL ", location.href);
const s = getScreenFromLocation(location);
window.matrixChat.showScreen(s.screen, s.params);
(window.matrixChat as MatrixChatType).showScreen(s.screen, s.params);
}

function onHashChange(ev) {
function onHashChange(ev: HashChangeEvent) {
if (decodeURIComponent(window.location.hash) === lastLocationHashSet) {
// we just set this: no need to route it!
return;
Expand All @@ -72,8 +73,8 @@ function onHashChange(ev) {

// This will be called whenever the SDK changes screens,
// so a web page can update the URL bar appropriately.
function onNewScreen(screen) {
console.log("newscreen "+screen);
function onNewScreen(screen: string) {
console.log("newscreen " + screen);
const hash = '#/' + screen;
lastLocationHashSet = hash;
window.location.hash = hash;
Expand All @@ -88,7 +89,7 @@ function onNewScreen(screen) {
// If we're in electron, we should never pass through a file:// URL otherwise
// the identity server will try to 302 the browser to it, which breaks horribly.
// so in that instance, hardcode to use riot.im/app for now instead.
function makeRegistrationUrl(params) {
function makeRegistrationUrl(params: object) {
let url;
if (window.location.protocol === "vector:") {
url = 'https://riot.im/app/#/register';
Expand Down Expand Up @@ -121,8 +122,7 @@ function onTokenLoginCompleted() {
const parsedUrl = url.parse(window.location.href);
parsedUrl.search = "";
const formatted = url.format(parsedUrl);
console.log("Redirecting to " + formatted + " to drop loginToken " +
"from queryparams");
console.log(`Redirecting to ${formatted} to drop loginToken from queryparams`);
window.location.href = formatted;
}

Expand Down
2 changes: 1 addition & 1 deletion src/vector/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
<% }
} %>
</head>
<body style="height: 100%;" data-vector-indexeddb-worker-script="<%= htmlWebpackPlugin.files.chunks['indexeddb-worker'].entry %>">
<body style="height: 100%; margin: 0;" data-vector-indexeddb-worker-script="<%= htmlWebpackPlugin.files.chunks['indexeddb-worker'].entry %>">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a bit unclear what this change is doing, but probably fine

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its fixing the margin around the ErrorView and CompatibilityView in Chrome which has a default margin for when our react-sdk css doesn't get loaded yet.

<noscript>Sorry, Riot requires JavaScript to be enabled.</noscript> <!-- TODO: Translate this? -->
<section id="matrixchat" style="height: 100%; overflow: auto;"></section>
<script src="<%= htmlWebpackPlugin.files.chunks['bundle'].entry %>"></script>
Expand Down
28 changes: 21 additions & 7 deletions src/vector/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,7 @@ function checkBrowserFeatures() {
return featureComplete;
}

let acceptBrowser = checkBrowserFeatures();
if (!acceptBrowser && window.localStorage) {
acceptBrowser = Boolean(window.localStorage.getItem("mx_accepts_unsupported_browser"));
}
const supportedBrowser = 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.
Expand Down Expand Up @@ -148,6 +145,11 @@ async function start() {
// await things settling so that any errors we have to render have features like i18n running
await settled(loadSkinPromise, loadThemePromise, loadLanguagePromise);

let acceptBrowser = supportedBrowser;
if (!acceptBrowser && window.localStorage) {
acceptBrowser = Boolean(window.localStorage.getItem("mx_accepts_unsupported_browser"));
}

// ##########################
// error handling begins here
// ##########################
Expand Down Expand Up @@ -199,9 +201,21 @@ async function start() {
]);
}
}

start().catch(err => {
console.error(err);
if (!acceptBrowser) {
// TODO redirect to static incompatible browser page
}
// show the static error in an iframe to not lose any context / console data
// with some basic styling to make the iframe full page
delete document.body.style.height;
const iframe = document.createElement("iframe");
t3chguy marked this conversation as resolved.
Show resolved Hide resolved
iframe.src = supportedBrowser ? "static/unable-to-load.html" : "static/incompatible-browser.html";
iframe.style.width = "100%";
iframe.style.height = "100%";
iframe.style.position = "absolute";
iframe.style.top = "0";
iframe.style.left = "0";
iframe.style.right = "0";
iframe.style.bottom = "0";
iframe.style.border = "0";
document.getElementById("matrixchat").appendChild(iframe);
});
Loading