From 9c8ef4240c02f347a9b8d2d2473c9435eb262518 Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 3 Sep 2018 20:38:30 +0100 Subject: [PATCH] Instructions for installing mobile apps Replace the native js dialog with a page telling you how to download the apps and how to set your HS URL. --- src/vector/getconfig.js | 67 +++++ src/vector/index.js | 40 +-- src/vector/mobile_guide/index.html | 386 +++++++++++++++++++++++++++++ src/vector/mobile_guide/index.js | 19 ++ webpack.config.js | 7 + 5 files changed, 487 insertions(+), 32 deletions(-) create mode 100644 src/vector/getconfig.js create mode 100644 src/vector/mobile_guide/index.html create mode 100644 src/vector/mobile_guide/index.js diff --git a/src/vector/getconfig.js b/src/vector/getconfig.js new file mode 100644 index 000000000..f3e7bea16 --- /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 69a4f1a1a..cdfef3682 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 000000000..9b6f49cd3 --- /dev/null +++ b/src/vector/mobile_guide/index.html @@ -0,0 +1,386 @@ + + + + + + + + + + +
+ + +
+
+
+

Step 2: Use a custom server

+ + Use custom server options (advanced). + + + + + + + + + + + + + + + + +

Launch the app, and enable Use custom server options (advanced).

+

In the Home Server field, enter:

+

+

Note: You shouldn't need to modify the Identity Server field, which by default is set to https://vector.im.

+
+
+
+
+
+
+

Step 3: 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 000000000..8fa4f172c --- /dev/null +++ b/src/vector/mobile_guide/index.js @@ -0,0 +1,19 @@ +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 = 'https://matrix.org/'; + if (config && config['default_hs_url']) { + hsUrl = config['default_hs_url']; + } + document.getElementById('hs_url').innerHTML = hsUrl; +} + +initPage(); diff --git a/webpack.config.js b/webpack.config.js index 2a116f577..7c0aa8b48 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