diff --git a/src/vector/getconfig.js b/src/vector/getconfig.js new file mode 100644 index 0000000000..f3e7bea168 --- /dev/null +++ b/src/vector/getconfig.js @@ -0,0 +1,67 @@ +/* +Copyright 2018 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 Promise from 'bluebird'; +import request from 'browser-request'; + +export async function getVectorConfig(relativeLocation) { + if (relativeLocation === undefined) relativeLocation = ''; + if (relativeLocation !== '' && !relativeLocation.endsWith('/')) relativeLocation += '/'; + try { + const configJson = await getConfig(`${relativeLocation}config.${document.domain}.json`); + // 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 + } + return configJson; + } catch (e) { + return await getConfig(relativeLocation + "config.json"); + } +} + +function getConfig(configJsonFilename) { + let deferred = Promise.defer(); + + request( + { method: "GET", url: configJsonFilename }, + (err, response, body) => { + if (err || response.status < 200 || response.status >= 300) { + // Lack of a config isn't an error, we should + // just use the defaults. + // Also treat a blank config as no config, assuming + // the status code is 0, because we don't get 404s + // from file: URIs so this is the only way we can + // not fail if the file doesn't exist when loading + // from a file:// URI. + if (response) { + if (response.status == 404 || (response.status == 0 && body == '')) { + deferred.resolve({}); + } + } + deferred.reject({err: err, response: response}); + return; + } + + // We parse the JSON ourselves rather than use the JSON + // parameter, since this throws a parse error on empty + // which breaks if there's no config.json and we're + // loading from the filesystem (see above). + deferred.resolve(JSON.parse(body)); + } + ); + + return deferred.promise; +} diff --git a/src/vector/index.js b/src/vector/index.js index 69a4f1a1ac..cdfef36825 100644 --- a/src/vector/index.js +++ b/src/vector/index.js @@ -58,6 +58,8 @@ import rageshake from "matrix-react-sdk/lib/rageshake/rageshake"; import CallHandler from 'matrix-react-sdk/lib/CallHandler'; +import {getVectorConfig} from './getconfig'; + let lastLocationHashSet = null; function initRageshake() { @@ -238,15 +240,7 @@ async function loadApp() { let configJson; let configError; try { - try { - configJson = await getConfig(`config.${document.domain}.json`); - // 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"); - } + configJson = getVectorConfig(); } catch (e) { configError = e; } @@ -260,31 +254,13 @@ async function loadApp() { const preventRedirect = Boolean(fragparts.params.client_secret); if (!preventRedirect) { - if (/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream) { - // FIXME: ugly status hardcoding - if (SettingsStore.getValue("theme") === 'status') { - window.location = "https://status.im/join-riot.html"; + const isIos = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream; + const isAndroid = /Android/.test(navigator.userAgent); + if (isIos || isAndroid) { + if (!document.cookie.split(';').some((c) => c.startsWith('mobile_redirect_to_guide'))) { + window.location = "mobile_guide/"; return; } - else { - if (confirm(_t("Riot is not supported on mobile web. Install the app?"))) { - window.location = "https://itunes.apple.com/us/app/vector.im/id1083446067"; - return; - } - } - } - else if (/Android/.test(navigator.userAgent)) { - // FIXME: ugly status hardcoding - if (SettingsStore.getValue("theme") === 'status') { - window.location = "https://status.im/join-riot.html"; - return; - } - else { - 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"; - return; - } - } } } diff --git a/src/vector/mobile_guide/index.html b/src/vector/mobile_guide/index.html new file mode 100644 index 0000000000..433d5b7e5a --- /dev/null +++ b/src/vector/mobile_guide/index.html @@ -0,0 +1,386 @@ + + + + + + + + + + +
+
+ + + +
+

Riot.im

+

How to set up Riot on iOS & Android

+
+
+
+ +
+ +
+
+
+

Step 2: Register or Log in

+

Create a new account if you don't have one, or log in to your existing account.

+
+
+
+
+ +
+
+ + diff --git a/src/vector/mobile_guide/index.js b/src/vector/mobile_guide/index.js new file mode 100644 index 0000000000..b2d007ac53 --- /dev/null +++ b/src/vector/mobile_guide/index.js @@ -0,0 +1,23 @@ +import {getVectorConfig} from '../getconfig'; + +function onBackToRiotClick() { + document.cookie = 'mobile_redirect_to_guide=false;path=/'; + window.location.href = '../'; +} + +async function initPage() { + document.getElementById('back_to_riot_button').onclick = onBackToRiotClick; + + const config = await getVectorConfig('..'); + let hsUrl; + if (config && config['default_hs_url']) { + hsUrl = config['default_hs_url']; + } + if (hsUrl && hsUrl !== 'https://matrix.org/') { + document.getElementById('step2_container').style.display = 'block'; + document.getElementById('hs_url').innerHTML = hsUrl; + document.getElementById('step_login_header').innerHTML= 'Step 3: Register or Log in'; + } +} + +initPage(); diff --git a/webpack.config.js b/webpack.config.js index 2a116f5777..7c0aa8b488 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -13,6 +13,8 @@ module.exports = { "bundle": ["babel-polyfill", "./src/vector/index.js"], "indexeddb-worker": "./src/vector/indexeddb-worker.js", + "mobileguide": "./src/vector/mobile_guide/index.js", + // We ship olm.js as a separate lump of javascript. This makes it get // loaded via a separate