Compare commits

...
Sign in to create a new pull request.

6 commits

Author SHA1 Message Date
Michael Telatynski
4840aee8c8
add comment
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2018-06-06 13:19:48 +01:00
Michael Telatynski
6daedaeb40
delint and update copyright header
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2018-06-06 13:17:32 +01:00
Michael Telatynski
026a072278
move configError check earlier, as SdkConfig will cause Exception
if it has undefined pass to it

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2018-06-06 13:09:31 +01:00
Michael Telatynski
ab09d4b632
refactor to make it more generic and work for any number of conf files
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2018-06-06 13:05:05 +01:00
Michael Telatynski
8fada2731b
ignore domain config load error if base config loaded
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2018-06-06 12:43:09 +01:00
Michael Telatynski
88c2158474
use domain config json as override instead of one or the other
fixes #6843

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2018-06-06 12:40:00 +01:00

View file

@ -1,6 +1,6 @@
/* /*
Copyright 2015, 2016 OpenMarket Ltd Copyright 2015, 2016 OpenMarket Ltd
Copyright 2017 Vector Creations Ltd Copyright 2017, 2018 Vector Creations Ltd
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -27,7 +27,8 @@ require('draft-js/dist/Draft.css');
const rageshake = require("matrix-react-sdk/lib/rageshake/rageshake"); const rageshake = require("matrix-react-sdk/lib/rageshake/rageshake");
rageshake.init().then(() => { rageshake.init().then(() => {
console.log("Initialised rageshake: See https://bugs.chromium.org/p/chromium/issues/detail?id=583193 to fix line numbers on Chrome."); console.log("Initialised rageshake: See https://bugs.chromium.org/p/chromium/issues/detail?id=583193 " +
"to fix line numbers on Chrome.");
rageshake.cleanup(); rageshake.cleanup();
}, (err) => { }, (err) => {
console.error("Failed to initialise rageshake: " + err); console.error("Failed to initialise rageshake: " + err);
@ -47,14 +48,14 @@ if (process.env.NODE_ENV !== 'production') {
global.Perf = require("react-addons-perf"); global.Perf = require("react-addons-perf");
} }
var RunModernizrTests = require("./modernizr"); // this side-effects a global require("./modernizr"); // this side-effects a global
var ReactDOM = require("react-dom"); const ReactDOM = require("react-dom");
var sdk = require("matrix-react-sdk"); const sdk = require("matrix-react-sdk");
const PlatformPeg = require("matrix-react-sdk/lib/PlatformPeg"); const PlatformPeg = require("matrix-react-sdk/lib/PlatformPeg");
sdk.loadSkin(require('../component-index')); sdk.loadSkin(require('../component-index'));
var VectorConferenceHandler = require('matrix-react-sdk/lib/VectorConferenceHandler'); const VectorConferenceHandler = require('matrix-react-sdk/lib/VectorConferenceHandler');
import Promise from 'bluebird'; import Promise from 'bluebird';
var request = require('browser-request'); const request = require('browser-request');
import * as languageHandler from 'matrix-react-sdk/lib/languageHandler'; import * as languageHandler from 'matrix-react-sdk/lib/languageHandler';
// Also import _t directly so we can call it just `_t` as this is what gen-i18n.js expects // Also import _t directly so we can call it just `_t` as this is what gen-i18n.js expects
import { _t } from 'matrix-react-sdk/lib/languageHandler'; import { _t } from 'matrix-react-sdk/lib/languageHandler';
@ -65,13 +66,13 @@ import {parseQs, parseQsFromFragment} from './url_utils';
import Platform from './platform'; import Platform from './platform';
import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg'; import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
import SettingsStore, {SettingLevel} from "matrix-react-sdk/lib/settings/SettingsStore"; import SettingsStore from "matrix-react-sdk/lib/settings/SettingsStore";
import Tinter from 'matrix-react-sdk/lib/Tinter'; import Tinter from 'matrix-react-sdk/lib/Tinter';
import SdkConfig from "matrix-react-sdk/lib/SdkConfig"; import SdkConfig from "matrix-react-sdk/lib/SdkConfig";
var lastLocationHashSet = null; let lastLocationHashSet = null;
var CallHandler = require("matrix-react-sdk/lib/CallHandler"); const CallHandler = require("matrix-react-sdk/lib/CallHandler");
CallHandler.setConferenceHandler(VectorConferenceHandler); CallHandler.setConferenceHandler(VectorConferenceHandler);
MatrixClientPeg.setIndexedDbWorkerScript(window.vector_indexeddb_worker_script); MatrixClientPeg.setIndexedDbWorkerScript(window.vector_indexeddb_worker_script);
@ -81,12 +82,12 @@ function checkBrowserFeatures(featureList) {
console.error("Cannot check features - Modernizr global is missing."); console.error("Cannot check features - Modernizr global is missing.");
return false; return false;
} }
var featureComplete = true; let featureComplete = true;
for (var i = 0; i < featureList.length; i++) { for (let i = 0; i < featureList.length; i++) {
if (window.Modernizr[featureList[i]] === undefined) { if (window.Modernizr[featureList[i]] === undefined) {
console.error( console.error(
"Looked for feature '%s' but Modernizr has no results for this. " + "Looked for feature '%s' but Modernizr has no results for this. " +
"Has it been configured correctly?", featureList[i] "Has it been configured correctly?", featureList[i],
); );
return false; return false;
} }
@ -100,7 +101,7 @@ function checkBrowserFeatures(featureList) {
return featureComplete; return featureComplete;
} }
var validBrowser = checkBrowserFeatures([ let validBrowser = checkBrowserFeatures([
"displaytable", "flexbox", "es5object", "es5function", "localstorage", "displaytable", "flexbox", "es5object", "es5function", "localstorage",
"objectfit", "indexeddb", "webworkers", "objectfit", "indexeddb", "webworkers",
]); ]);
@ -112,7 +113,7 @@ function getScreenFromLocation(location) {
return { return {
screen: fragparts.location.substring(1), screen: fragparts.location.substring(1),
params: fragparts.params, params: fragparts.params,
} };
} }
// Here, we do some crude URL analysis to allow // Here, we do some crude URL analysis to allow
@ -126,7 +127,7 @@ function routeUrl(location) {
} }
function onHashChange(ev) { function onHashChange(ev) {
if (decodeURIComponent(window.location.hash) == lastLocationHashSet) { if (decodeURIComponent(window.location.hash) === lastLocationHashSet) {
// we just set this: no need to route it! // we just set this: no need to route it!
return; return;
} }
@ -135,9 +136,9 @@ function onHashChange(ev) {
// This will be called whenever the SDK changes screens, // This will be called whenever the SDK changes screens,
// so a web page can update the URL bar appropriately. // so a web page can update the URL bar appropriately.
var onNewScreen = function(screen) { const onNewScreen = function(screen) {
console.log("newscreen "+screen); console.log("newscreen "+screen);
var hash = '#/' + screen; const hash = '#/' + screen;
lastLocationHashSet = hash; lastLocationHashSet = hash;
window.location.hash = hash; window.location.hash = hash;
}; };
@ -151,7 +152,7 @@ var onNewScreen = function(screen) {
// If we're in electron, we should never pass through a file:// URL otherwise // 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. // 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. // so in that instance, hardcode to use riot.im/app for now instead.
var makeRegistrationUrl = function(params) { const makeRegistrationUrl = function(params) {
let url; let url;
if (window.location.protocol === "file:") { if (window.location.protocol === "file:") {
url = 'https://riot.im/app/#/register'; url = 'https://riot.im/app/#/register';
@ -166,7 +167,7 @@ var makeRegistrationUrl = function(params) {
const keys = Object.keys(params); const keys = Object.keys(params);
for (let i = 0; i < keys.length; ++i) { for (let i = 0; i < keys.length; ++i) {
if (i == 0) { if (i === 0) {
url += '?'; url += '?';
} else { } else {
url += '&'; url += '&';
@ -175,12 +176,12 @@ var makeRegistrationUrl = function(params) {
url += k + '=' + encodeURIComponent(params[k]); url += k + '=' + encodeURIComponent(params[k]);
} }
return url; return url;
} };
window.addEventListener('hashchange', onHashChange); window.addEventListener('hashchange', onHashChange);
function getConfig(configJsonFilename) { function getConfig(configJsonFilename) {
let deferred = Promise.defer(); const deferred = Promise.defer();
request( request(
{ method: "GET", url: configJsonFilename }, { method: "GET", url: configJsonFilename },
@ -194,7 +195,7 @@ function getConfig(configJsonFilename) {
// not fail if the file doesn't exist when loading // not fail if the file doesn't exist when loading
// from a file:// URI. // from a file:// URI.
if (response) { if (response) {
if (response.status == 404 || (response.status == 0 && body == '')) { if (response.status === 404 || (response.status === 0 && body === '')) {
deferred.resolve({}); deferred.resolve({});
} }
} }
@ -207,7 +208,7 @@ function getConfig(configJsonFilename) {
// which breaks if there's no config.json and we're // which breaks if there's no config.json and we're
// loading from the filesystem (see above). // loading from the filesystem (see above).
deferred.resolve(JSON.parse(body)); deferred.resolve(JSON.parse(body));
} },
); );
return deferred.promise; return deferred.promise;
@ -217,14 +218,41 @@ function onTokenLoginCompleted() {
// if we did a token login, we're now left with the token, hs and is // if we did a token login, we're now left with the token, hs and is
// url as query params in the url; a little nasty but let's redirect to // url as query params in the url; a little nasty but let's redirect to
// clear them. // clear them.
var parsedUrl = url.parse(window.location.href); const parsedUrl = url.parse(window.location.href);
parsedUrl.search = ""; parsedUrl.search = "";
var formatted = url.format(parsedUrl); const formatted = url.format(parsedUrl);
console.log("Redirecting to " + formatted + " to drop loginToken " + console.log(`Redirecting to ${formatted} to drop loginToken from queryparams`);
"from queryparams");
window.location.href = formatted; window.location.href = formatted;
} }
// defined in order starting with base config
const configFiles = [
'config.json',
`config.${document.domain}.json`,
];
// Loads a composite config made from applying the fields from each of the above configs in order to a common object
async function loadConfig() {
// load all configs concurrently, await on them in order each overriding the previous if exists, error only all fail
const promises = configFiles.map((configFile) => getConfig(configFile));
let configJson = undefined;
for (const promise of promises) {
try {
const config = await promise;
// 404s succeed with an empty json config, so check that there are keys
if (Object.keys(config).length > 0) {
configJson = Object.assign(configJson || {}, config);
}
} catch (e) {
// ignore error here, instead error=!configJson
// since the error content never gets used
}
}
return configJson;
}
async function loadApp() { async function loadApp() {
await loadLanguage(); await loadLanguage();
@ -234,22 +262,13 @@ async function loadApp() {
// set the platform for react sdk (our Platform object automatically picks the right one) // set the platform for react sdk (our Platform object automatically picks the right one)
PlatformPeg.set(new Platform()); PlatformPeg.set(new Platform());
// Load the config file. First try to load up a domain-specific config of the const configJson = await loadConfig();
// form "config.$domain.json" and if that fails, fall back to config.json.
let configJson; if (!configJson) {
let configError; window.matrixChat = ReactDOM.render(<div className="error">
try { Unable to load config file: please refresh the page to try again.
try { </div>, document.getElementById('matrixchat'));
configJson = await getConfig(`config.${document.domain}.json`); return;
// 404s succeed with an empty json config, so check that there are keys
if (Object.keys(configJson).length === 0) {
throw new Error(); // throw to enter the catch
}
} catch (e) {
configJson = await getConfig("config.json");
}
} catch (e) {
configError = e;
} }
// XXX: We call this twice, once here and once in MatrixChat as a prop. We call it here to ensure // XXX: We call this twice, once here and once in MatrixChat as a prop. We call it here to ensure
@ -266,21 +285,18 @@ async function loadApp() {
if (SettingsStore.getValue("theme") === 'status') { if (SettingsStore.getValue("theme") === 'status') {
window.location = "https://status.im/join-riot.html"; window.location = "https://status.im/join-riot.html";
return; return;
} } else {
else {
if (confirm(_t("Riot is not supported on mobile web. Install the app?"))) { if (confirm(_t("Riot is not supported on mobile web. Install the app?"))) {
window.location = "https://itunes.apple.com/us/app/vector.im/id1083446067"; window.location = "https://itunes.apple.com/us/app/vector.im/id1083446067";
return; return;
} }
} }
} } else if (/Android/.test(navigator.userAgent)) {
else if (/Android/.test(navigator.userAgent)) {
// FIXME: ugly status hardcoding // FIXME: ugly status hardcoding
if (SettingsStore.getValue("theme") === 'status') { if (SettingsStore.getValue("theme") === 'status') {
window.location = "https://status.im/join-riot.html"; window.location = "https://status.im/join-riot.html";
return; return;
} } else {
else {
if (confirm(_t("Riot is not supported on mobile web. Install the app?"))) { if (confirm(_t("Riot is not supported on mobile web. Install the app?"))) {
window.location = "https://play.google.com/store/apps/details?id=im.vector.alpha"; window.location = "https://play.google.com/store/apps/details?id=im.vector.alpha";
return; return;
@ -290,7 +306,6 @@ async function loadApp() {
} }
// as quickly as we possibly can, set a default theme... // as quickly as we possibly can, set a default theme...
const styleElements = Object.create(null);
let a; let a;
const theme = SettingsStore.getValue("theme"); const theme = SettingsStore.getValue("theme");
for (let i = 0; (a = document.getElementsByTagName("link")[i]); i++) { for (let i = 0; (a = document.getElementsByTagName("link")[i]); i++) {
@ -331,11 +346,7 @@ async function loadApp() {
} }
console.log("Vector starting at "+window.location); console.log("Vector starting at "+window.location);
if (configError) { if (validBrowser) {
window.matrixChat = ReactDOM.render(<div className="error">
Unable to load config file: please refresh the page to try again.
</div>, document.getElementById('matrixchat'));
} else if (validBrowser) {
const platform = PlatformPeg.get(); const platform = PlatformPeg.get();
platform.startUpdater(); platform.startUpdater();
@ -353,24 +364,26 @@ async function loadApp() {
initialScreenAfterLogin={getScreenFromLocation(window.location)} initialScreenAfterLogin={getScreenFromLocation(window.location)}
defaultDeviceDisplayName={platform.getDefaultDeviceDisplayName()} defaultDeviceDisplayName={platform.getDefaultDeviceDisplayName()}
/>, />,
document.getElementById('matrixchat') document.getElementById('matrixchat'),
); );
} else { } else {
console.error("Browser is missing required features."); console.error("Browser is missing required features.");
// take to a different landing page to AWOOOOOGA at the user // take to a different landing page to AWOOOOOGA at the user
var CompatibilityPage = sdk.getComponent("structures.CompatibilityPage"); const CompatibilityPage = sdk.getComponent("structures.CompatibilityPage");
window.matrixChat = ReactDOM.render( window.matrixChat = ReactDOM.render(
<CompatibilityPage onAccept={function() { <CompatibilityPage onAccept={acceptInvalidBrowser} />,
if (window.localStorage) window.localStorage.setItem('mx_accepts_unsupported_browser', true); document.getElementById('matrixchat'),
validBrowser = true;
console.log("User accepts the compatibility risks.");
loadApp();
}} />,
document.getElementById('matrixchat')
); );
} }
} }
function acceptInvalidBrowser() {
if (window.localStorage) window.localStorage.setItem('mx_accepts_unsupported_browser', true);
validBrowser = true;
console.log("User accepts the compatibility risks.");
loadApp();
}
async function loadLanguage() { async function loadLanguage() {
const prefLang = SettingsStore.getValue("language", null, /*excludeDefault=*/true); const prefLang = SettingsStore.getValue("language", null, /*excludeDefault=*/true);
let langs = []; let langs = [];