mirror of
https://github.com/element-hq/element-web
synced 2024-11-29 12:58:53 +03:00
Merge pull request #8003 from vector-im/develop
Merge develop into experimental
This commit is contained in:
commit
373c587ef8
22 changed files with 861 additions and 179 deletions
25
CHANGELOG.md
25
CHANGELOG.md
|
@ -1,3 +1,28 @@
|
||||||
|
Changes in [0.17.8](https://github.com/vector-im/riot-web/releases/tag/v0.17.8) (2018-12-10)
|
||||||
|
============================================================================================
|
||||||
|
[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.17.8-rc.1...v0.17.8)
|
||||||
|
|
||||||
|
* No changes since rc.1
|
||||||
|
|
||||||
|
Changes in [0.17.8-rc.1](https://github.com/vector-im/riot-web/releases/tag/v0.17.8-rc.1) (2018-12-06)
|
||||||
|
======================================================================================================
|
||||||
|
[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.17.7...v0.17.8-rc.1)
|
||||||
|
|
||||||
|
* Update from Weblate.
|
||||||
|
[\#7784](https://github.com/vector-im/riot-web/pull/7784)
|
||||||
|
* Add a function to send a rageshake from the console
|
||||||
|
[\#7755](https://github.com/vector-im/riot-web/pull/7755)
|
||||||
|
* Re-apply "Run lint on travis builds and use modern node versions"
|
||||||
|
[\#7738](https://github.com/vector-im/riot-web/pull/7738)
|
||||||
|
* Revert "Run lint on travis builds and use modern node versions"
|
||||||
|
[\#7737](https://github.com/vector-im/riot-web/pull/7737)
|
||||||
|
* Run lint on travis builds and use modern node versions
|
||||||
|
[\#7490](https://github.com/vector-im/riot-web/pull/7490)
|
||||||
|
* Fix missing js-sdk logging
|
||||||
|
[\#7736](https://github.com/vector-im/riot-web/pull/7736)
|
||||||
|
* Add $accent-color-50pct as a CSS variable to the Status theme
|
||||||
|
[\#7710](https://github.com/vector-im/riot-web/pull/7710)
|
||||||
|
|
||||||
Changes in [0.17.7](https://github.com/vector-im/riot-web/releases/tag/v0.17.7) (2018-11-22)
|
Changes in [0.17.7](https://github.com/vector-im/riot-web/releases/tag/v0.17.7) (2018-11-22)
|
||||||
============================================================================================
|
============================================================================================
|
||||||
[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.17.6...v0.17.7)
|
[Full Changelog](https://github.com/vector-im/riot-web/compare/v0.17.6...v0.17.7)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Contributing code to Riot
|
Contributing code to Riot
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
Riot follows the same pattern as https://github.com/matrix-org/synapse/blob/master/CONTRIBUTING.rst.
|
Riot follows the same pattern as https://github.com/matrix-org/matrix-js-sdk/blob/master/CONTRIBUTING.rst.
|
||||||
|
|
|
@ -28,7 +28,8 @@ Note that Chrome does not allow microphone or webcam access for sites served
|
||||||
over http (except localhost), so for working VoIP you will need to serve Riot
|
over http (except localhost), so for working VoIP you will need to serve Riot
|
||||||
over https.
|
over https.
|
||||||
|
|
||||||
### Installation Steps for Debian Stretch
|
### Desktop Installation for Debian Stretch
|
||||||
|
|
||||||
1. Add the repository to your sources.list using either of the following two options:
|
1. Add the repository to your sources.list using either of the following two options:
|
||||||
- Directly to sources.list: `echo "deb https://riot.im/packages/debian/ stretch main" | sudo tee -a /etc/apt/sources.list`
|
- Directly to sources.list: `echo "deb https://riot.im/packages/debian/ stretch main" | sudo tee -a /etc/apt/sources.list`
|
||||||
- As a separate entry in sources.list.d: `echo "deb https://riot.im/packages/debian/ stretch main" | sudo tee /etc/apt/sources.list.d/riot.list`
|
- As a separate entry in sources.list.d: `echo "deb https://riot.im/packages/debian/ stretch main" | sudo tee /etc/apt/sources.list.d/riot.list`
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
"name": "riot-web",
|
"name": "riot-web",
|
||||||
"productName": "Riot",
|
"productName": "Riot",
|
||||||
"main": "src/electron-main.js",
|
"main": "src/electron-main.js",
|
||||||
"version": "0.17.7",
|
"version": "0.17.8",
|
||||||
"description": "A feature-rich client for Matrix.org",
|
"description": "A feature-rich client for Matrix.org",
|
||||||
"author": "New Vector Ltd.",
|
"author": "New Vector Ltd.",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
Copyright 2016 Aviral Dasgupta
|
Copyright 2016 Aviral Dasgupta
|
||||||
Copyright 2016 OpenMarket Ltd
|
Copyright 2016 OpenMarket Ltd
|
||||||
Copyright 2017 Michael Telatynski <7t3chguy@gmail.com>
|
Copyright 2017 Michael Telatynski <7t3chguy@gmail.com>
|
||||||
|
Copyright 2018 New Vector 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.
|
||||||
|
@ -23,16 +24,23 @@ const checkSquirrelHooks = require('./squirrelhooks');
|
||||||
if (checkSquirrelHooks()) return;
|
if (checkSquirrelHooks()) return;
|
||||||
|
|
||||||
const argv = require('minimist')(process.argv);
|
const argv = require('minimist')(process.argv);
|
||||||
const {app, ipcMain, powerSaveBlocker, BrowserWindow, Menu} = require('electron');
|
const {app, ipcMain, powerSaveBlocker, BrowserWindow, Menu, autoUpdater, protocol} = require('electron');
|
||||||
const AutoLaunch = require('auto-launch');
|
const AutoLaunch = require('auto-launch');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
const tray = require('./tray');
|
const tray = require('./tray');
|
||||||
const vectorMenu = require('./vectormenu');
|
const vectorMenu = require('./vectormenu');
|
||||||
const webContentsHandler = require('./webcontents-handler');
|
const webContentsHandler = require('./webcontents-handler');
|
||||||
const updater = require('./updater');
|
const updater = require('./updater');
|
||||||
|
const { migrateFromOldOrigin } = require('./originMigrator');
|
||||||
|
|
||||||
const windowStateKeeper = require('electron-window-state');
|
const windowStateKeeper = require('electron-window-state');
|
||||||
|
|
||||||
|
// boolean flag set whilst we are doing one-time origin migration
|
||||||
|
// We only serve the origin migration script while we're actually
|
||||||
|
// migrating to mitigate any risk of it being used maliciously.
|
||||||
|
let migratingOrigin = false;
|
||||||
|
|
||||||
if (argv['profile']) {
|
if (argv['profile']) {
|
||||||
app.setPath('userData', `${app.getPath('userData')}-${argv['profile']}`);
|
app.setPath('userData', `${app.getPath('userData')}-${argv['profile']}`);
|
||||||
}
|
}
|
||||||
|
@ -97,27 +105,75 @@ ipcMain.on('app_onAction', function(ev, payload) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
autoUpdater.on('update-downloaded', (ev, releaseNotes, releaseName, releaseDate, updateURL) => {
|
||||||
|
if (!mainWindow) return;
|
||||||
|
// forward to renderer
|
||||||
|
mainWindow.webContents.send('update-downloaded', {
|
||||||
|
releaseNotes,
|
||||||
|
releaseName,
|
||||||
|
releaseDate,
|
||||||
|
updateURL,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.on('ipcCall', async function(ev, payload) {
|
||||||
|
if (!mainWindow) return;
|
||||||
|
|
||||||
|
const args = payload.args || [];
|
||||||
|
let ret;
|
||||||
|
|
||||||
|
switch (payload.name) {
|
||||||
|
case 'getUpdateFeedUrl':
|
||||||
|
ret = autoUpdater.getFeedURL();
|
||||||
|
break;
|
||||||
|
case 'getAutoLaunchEnabled':
|
||||||
|
ret = launcher.isEnabled;
|
||||||
|
break;
|
||||||
|
case 'setAutoLaunchEnabled':
|
||||||
|
if (args[0]) {
|
||||||
|
launcher.enable();
|
||||||
|
} else {
|
||||||
|
launcher.disable();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'getAppVersion':
|
||||||
|
ret = app.getVersion();
|
||||||
|
break;
|
||||||
|
case 'focusWindow':
|
||||||
|
if (mainWindow.isMinimized()) {
|
||||||
|
mainWindow.restore();
|
||||||
|
} else if (!mainWindow.isVisible()) {
|
||||||
|
mainWindow.show();
|
||||||
|
} else {
|
||||||
|
mainWindow.focus();
|
||||||
|
}
|
||||||
|
case 'origin_migrate':
|
||||||
|
migratingOrigin = true;
|
||||||
|
await migrateFromOldOrigin();
|
||||||
|
migratingOrigin = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mainWindow.webContents.send('ipcReply', {
|
||||||
|
id: payload.id,
|
||||||
|
error: "Unknown IPC Call: " + payload.name,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mainWindow.webContents.send('ipcReply', {
|
||||||
|
id: payload.id,
|
||||||
|
reply: ret,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
app.commandLine.appendSwitch('--enable-usermedia-screen-capturing');
|
app.commandLine.appendSwitch('--enable-usermedia-screen-capturing');
|
||||||
|
|
||||||
const shouldQuit = app.makeSingleInstance((commandLine, workingDirectory) => {
|
const gotLock = app.requestSingleInstanceLock();
|
||||||
// If other instance launched with --hidden then skip showing window
|
if (!gotLock) {
|
||||||
if (commandLine.includes('--hidden')) return;
|
|
||||||
|
|
||||||
// Someone tried to run a second instance, we should focus our window.
|
|
||||||
if (mainWindow) {
|
|
||||||
if (!mainWindow.isVisible()) mainWindow.show();
|
|
||||||
if (mainWindow.isMinimized()) mainWindow.restore();
|
|
||||||
mainWindow.focus();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (shouldQuit) {
|
|
||||||
console.log('Other instance detected: exiting');
|
console.log('Other instance detected: exiting');
|
||||||
app.exit();
|
app.exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const launcher = new AutoLaunch({
|
const launcher = new AutoLaunch({
|
||||||
name: vectorConfig.brand || 'Riot',
|
name: vectorConfig.brand || 'Riot',
|
||||||
isHidden: true,
|
isHidden: true,
|
||||||
|
@ -126,39 +182,12 @@ const launcher = new AutoLaunch({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const settings = {
|
// Register the scheme the app is served from as 'standard'
|
||||||
'auto-launch': {
|
// which allows things like relative URLs and IndexedDB to
|
||||||
get: launcher.isEnabled,
|
// work.
|
||||||
set: function(bool) {
|
// Also mark it as secure (ie. accessing resources from this
|
||||||
if (bool) {
|
// protocol and HTTPS won't trigger mixed content warnings).
|
||||||
return launcher.enable();
|
protocol.registerStandardSchemes(['vector'], {secure: true});
|
||||||
} else {
|
|
||||||
return launcher.disable();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
ipcMain.on('settings_get', async function(ev) {
|
|
||||||
const data = {};
|
|
||||||
|
|
||||||
try {
|
|
||||||
await Promise.all(Object.keys(settings).map(async function (setting) {
|
|
||||||
data[setting] = await settings[setting].get();
|
|
||||||
}));
|
|
||||||
|
|
||||||
ev.sender.send('settings', data);
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.on('settings_set', function(ev, key, value) {
|
|
||||||
console.log(key, value);
|
|
||||||
if (settings[key] && settings[key].set) {
|
|
||||||
settings[key].set(value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
app.on('ready', () => {
|
app.on('ready', () => {
|
||||||
if (argv['devtools']) {
|
if (argv['devtools']) {
|
||||||
|
@ -175,6 +204,66 @@ app.on('ready', () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protocol.registerFileProtocol('vector', (request, callback) => {
|
||||||
|
if (request.method !== 'GET') {
|
||||||
|
callback({error: -322}); // METHOD_NOT_SUPPORTED from chromium/src/net/base/net_error_list.h
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const parsedUrl = new URL(request.url);
|
||||||
|
if (parsedUrl.protocol !== 'vector:') {
|
||||||
|
callback({error: -302}); // UNKNOWN_URL_SCHEME
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (parsedUrl.host !== 'vector') {
|
||||||
|
callback({error: -105}); // NAME_NOT_RESOLVED
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const target = parsedUrl.pathname.split('/');
|
||||||
|
|
||||||
|
// path starts with a '/'
|
||||||
|
if (target[0] !== '') {
|
||||||
|
callback({error: -6}); // FILE_NOT_FOUND
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target[target.length - 1] == '') {
|
||||||
|
target[target.length - 1] = 'index.html';
|
||||||
|
}
|
||||||
|
|
||||||
|
let baseDir;
|
||||||
|
// first part of the path determines where we serve from
|
||||||
|
if (migratingOrigin && target[1] === 'origin_migrator_dest') {
|
||||||
|
// the origin migrator destination page
|
||||||
|
// (only the destination script needs to come from the
|
||||||
|
// custom protocol: the source part is loaded from a
|
||||||
|
// file:// as that's the origin we're migrating from).
|
||||||
|
baseDir = __dirname + "/../../origin_migrator/dest";
|
||||||
|
} else if (target[1] === 'webapp') {
|
||||||
|
baseDir = __dirname + "/../../webapp";
|
||||||
|
} else {
|
||||||
|
callback({error: -6}); // FILE_NOT_FOUND
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normalise the base dir and the target path separately, then make sure
|
||||||
|
// the target path isn't trying to back out beyond its root
|
||||||
|
baseDir = path.normalize(baseDir);
|
||||||
|
|
||||||
|
const relTarget = path.normalize(path.join(...target.slice(2)));
|
||||||
|
if (relTarget.startsWith('..')) {
|
||||||
|
callback({error: -6}); // FILE_NOT_FOUND
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const absTarget = path.join(baseDir, relTarget);
|
||||||
|
|
||||||
|
callback({
|
||||||
|
path: absTarget,
|
||||||
|
});
|
||||||
|
}, (error) => {
|
||||||
|
if (error) console.error('Failed to register protocol')
|
||||||
|
});
|
||||||
|
|
||||||
if (vectorConfig['update_base_url']) {
|
if (vectorConfig['update_base_url']) {
|
||||||
console.log(`Starting auto update with base URL: ${vectorConfig['update_base_url']}`);
|
console.log(`Starting auto update with base URL: ${vectorConfig['update_base_url']}`);
|
||||||
|
@ -191,6 +280,7 @@ app.on('ready', () => {
|
||||||
defaultHeight: 768,
|
defaultHeight: 768,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const preloadScript = path.normalize(`${__dirname}/preload.js`);
|
||||||
mainWindow = global.mainWindow = new BrowserWindow({
|
mainWindow = global.mainWindow = new BrowserWindow({
|
||||||
icon: iconPath,
|
icon: iconPath,
|
||||||
show: false,
|
show: false,
|
||||||
|
@ -200,8 +290,20 @@ app.on('ready', () => {
|
||||||
y: mainWindowState.y,
|
y: mainWindowState.y,
|
||||||
width: mainWindowState.width,
|
width: mainWindowState.width,
|
||||||
height: mainWindowState.height,
|
height: mainWindowState.height,
|
||||||
|
webPreferences: {
|
||||||
|
preload: preloadScript,
|
||||||
|
nodeIntegration: false,
|
||||||
|
sandbox: true,
|
||||||
|
enableRemoteModule: false,
|
||||||
|
// We don't use this: it's useful for the preload script to
|
||||||
|
// share a context with the main page so we can give select
|
||||||
|
// objects to the main page. The sandbox option isolates the
|
||||||
|
// main page from the background script.
|
||||||
|
contextIsolation: false,
|
||||||
|
webgl: false,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
mainWindow.loadURL(`file://${__dirname}/../../webapp/index.html`);
|
mainWindow.loadURL('vector://vector/webapp/');
|
||||||
Menu.setApplicationMenu(vectorMenu);
|
Menu.setApplicationMenu(vectorMenu);
|
||||||
|
|
||||||
// explicitly hide because setApplicationMenu on Linux otherwise shows...
|
// explicitly hide because setApplicationMenu on Linux otherwise shows...
|
||||||
|
@ -268,6 +370,18 @@ app.on('before-quit', () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.on('second-instance', (ev, commandLine, workingDirectory) => {
|
||||||
|
// If other instance launched with --hidden then skip showing window
|
||||||
|
if (commandLine.includes('--hidden')) return;
|
||||||
|
|
||||||
|
// Someone tried to run a second instance, we should focus our window.
|
||||||
|
if (mainWindow) {
|
||||||
|
if (!mainWindow.isVisible()) mainWindow.show();
|
||||||
|
if (mainWindow.isMinimized()) mainWindow.restore();
|
||||||
|
mainWindow.focus();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Set the App User Model ID to match what the squirrel
|
// Set the App User Model ID to match what the squirrel
|
||||||
// installer uses for the shortcut icon.
|
// installer uses for the shortcut icon.
|
||||||
// This makes notifications work on windows 8.1 (and is
|
// This makes notifications work on windows 8.1 (and is
|
||||||
|
|
62
electron_app/src/originMigrator.js
Normal file
62
electron_app/src/originMigrator.js
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const { BrowserWindow, ipcMain } = require('electron');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
async function migrateFromOldOrigin() {
|
||||||
|
console.log("Attempting to migrate data between origins");
|
||||||
|
|
||||||
|
// We can use the same preload script: we just need ipcRenderer exposed
|
||||||
|
const preloadScript = path.normalize(`${__dirname}/preload.js`);
|
||||||
|
await new Promise(resolve => {
|
||||||
|
const migrateWindow = new BrowserWindow({
|
||||||
|
show: false,
|
||||||
|
webPreferences: {
|
||||||
|
preload: preloadScript,
|
||||||
|
nodeIntegration: false,
|
||||||
|
sandbox: true,
|
||||||
|
enableRemoteModule: false,
|
||||||
|
webgl: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
ipcMain.on('origin_migration_complete', (e, success, sentSummary, storedSummary) => {
|
||||||
|
if (success) {
|
||||||
|
console.log("Origin migration completed successfully!");
|
||||||
|
} else {
|
||||||
|
console.error("Origin migration failed!");
|
||||||
|
}
|
||||||
|
console.error("Data sent", sentSummary);
|
||||||
|
console.error("Data stored", storedSummary);
|
||||||
|
migrateWindow.close();
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
ipcMain.on('origin_migration_nodata', (e) => {
|
||||||
|
console.log("No session to migrate from old origin");
|
||||||
|
migrateWindow.close();
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
// Normalise the path because in the distribution, __dirname will be inside the
|
||||||
|
// electron asar.
|
||||||
|
const sourcePagePath = path.normalize(__dirname + '/../../origin_migrator/source.html');
|
||||||
|
console.log("Loading path: " + sourcePagePath);
|
||||||
|
migrateWindow.loadURL('file://' + sourcePagePath);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
migrateFromOldOrigin,
|
||||||
|
};
|
|
@ -1,8 +1,5 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016 Aviral Dasgupta
|
Copyright 2018 New Vector Ltd
|
||||||
Copyright 2016 OpenMarket 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.
|
||||||
|
@ -17,13 +14,16 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let Platform = null;
|
const { ipcRenderer, webFrame } = require('electron');
|
||||||
|
|
||||||
if (window && window.process && window.process && window.process.type === 'renderer') {
|
// expose ipcRenderer to the renderer process
|
||||||
// we're running inside electron
|
window.ipcRenderer = ipcRenderer;
|
||||||
Platform = require('./ElectronPlatform');
|
|
||||||
} else {
|
|
||||||
Platform = require('./WebPlatform');
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Platform;
|
// Allow the fetch API to load resources from this
|
||||||
|
// protocol: this is necessary to load olm.wasm.
|
||||||
|
// (Also mark it a secure although we've already
|
||||||
|
// done this in the main process).
|
||||||
|
webFrame.registerURLSchemeAsPrivileged('vector', {
|
||||||
|
secure: true,
|
||||||
|
supportFetchAPI: true,
|
||||||
|
});
|
19
origin_migrator/dest/browser-matrix.min.js
vendored
Normal file
19
origin_migrator/dest/browser-matrix.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
6
origin_migrator/dest/dest.html
Normal file
6
origin_migrator/dest/dest.html
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<script src="browser-matrix.min.js"></script>
|
||||||
|
<script src="dest.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
125
origin_migrator/dest/dest.js
Normal file
125
origin_migrator/dest/dest.js
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const SOURCE_ORIGIN = 'file://';
|
||||||
|
|
||||||
|
const IndexedDBCryptoStore = window.matrixcs.IndexedDBCryptoStore;
|
||||||
|
const cryptoStore = new IndexedDBCryptoStore(window.indexedDB, 'matrix-js-sdk:crypto');
|
||||||
|
|
||||||
|
let accountStored = 0;
|
||||||
|
let sessionsStored = 0;
|
||||||
|
let inboundGroupSessionsStored = 0;
|
||||||
|
let deviceDataStored = 0;
|
||||||
|
let roomsStored = 0;
|
||||||
|
let localStorageKeysStored = 0;
|
||||||
|
|
||||||
|
const promises = [];
|
||||||
|
|
||||||
|
async function onMessage(e) {
|
||||||
|
if (e.origin !== SOURCE_ORIGIN) return;
|
||||||
|
|
||||||
|
const data = e.data.data; // bleh, naming clash
|
||||||
|
switch (e.data.cmd) {
|
||||||
|
case 'init':
|
||||||
|
// start with clean stores before we migrate data in
|
||||||
|
window.localStorage.clear();
|
||||||
|
await cryptoStore.deleteAllData();
|
||||||
|
|
||||||
|
e.source.postMessage({
|
||||||
|
cmd: 'initOK',
|
||||||
|
}, SOURCE_ORIGIN);
|
||||||
|
break;
|
||||||
|
case 'storeAccount':
|
||||||
|
promises.push(cryptoStore.doTxn(
|
||||||
|
'readwrite', [IndexedDBCryptoStore.STORE_ACCOUNT],
|
||||||
|
(txn) => {
|
||||||
|
cryptoStore.storeAccount(txn, data);
|
||||||
|
},
|
||||||
|
).then(() => {
|
||||||
|
++accountStored;
|
||||||
|
}));
|
||||||
|
break;
|
||||||
|
case 'storeSessions':
|
||||||
|
promises.push(cryptoStore.doTxn(
|
||||||
|
'readwrite', [IndexedDBCryptoStore.STORE_SESSIONS],
|
||||||
|
(txn) => {
|
||||||
|
for (const sess of data) {
|
||||||
|
cryptoStore.storeEndToEndSession(sess.deviceKey, sess.sessionId, sess, txn);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
).then(() => {
|
||||||
|
sessionsStored += data.length;
|
||||||
|
}));
|
||||||
|
break;
|
||||||
|
case 'storeInboundGroupSessions':
|
||||||
|
promises.push(cryptoStore.doTxn(
|
||||||
|
'readwrite', [IndexedDBCryptoStore.STORE_INBOUND_GROUP_SESSIONS],
|
||||||
|
(txn) => {
|
||||||
|
for (const sess of data) {
|
||||||
|
cryptoStore.addEndToEndInboundGroupSession(
|
||||||
|
sess.senderKey, sess.sessionId, sess.sessionData, txn,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
).then(() => {
|
||||||
|
inboundGroupSessionsStored += data.length;
|
||||||
|
}));
|
||||||
|
break;
|
||||||
|
case 'storeDeviceData':
|
||||||
|
promises.push(cryptoStore.doTxn(
|
||||||
|
'readwrite', [IndexedDBCryptoStore.STORE_DEVICE_DATA],
|
||||||
|
(txn) => {
|
||||||
|
cryptoStore.storeEndToEndDeviceData(data, txn);
|
||||||
|
},
|
||||||
|
).then(() => {
|
||||||
|
++deviceDataStored;
|
||||||
|
}));
|
||||||
|
break;
|
||||||
|
case 'storeRooms':
|
||||||
|
promises.push(cryptoStore.doTxn(
|
||||||
|
'readwrite', [IndexedDBCryptoStore.STORE_ROOMS],
|
||||||
|
(txn) => {
|
||||||
|
for (const [roomId, roomInfo] of Object.entries(data)) {
|
||||||
|
cryptoStore.storeEndToEndRoom(roomId, roomInfo, txn);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
).then(() => {
|
||||||
|
++roomsStored;
|
||||||
|
}));
|
||||||
|
break;
|
||||||
|
case 'storeLocalStorage':
|
||||||
|
window.localStorage.setItem(data.key, data.val);
|
||||||
|
++localStorageKeysStored;
|
||||||
|
break;
|
||||||
|
case 'getSummary':
|
||||||
|
await Promise.all(promises);
|
||||||
|
e.source.postMessage({
|
||||||
|
cmd: 'summary',
|
||||||
|
data: {
|
||||||
|
accountStored,
|
||||||
|
sessionsStored,
|
||||||
|
inboundGroupSessionsStored,
|
||||||
|
deviceDataStored,
|
||||||
|
roomsStored,
|
||||||
|
localStorageKeysStored,
|
||||||
|
},
|
||||||
|
}, SOURCE_ORIGIN);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('message', onMessage);
|
||||||
|
|
7
origin_migrator/source.html
Normal file
7
origin_migrator/source.html
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<script src="dest/browser-matrix.min.js"></script>
|
||||||
|
<script src="source.js"></script>
|
||||||
|
<iframe name="dest" src="vector://vector/origin_migrator_dest/dest.html" onload="doMigrate()"></iframe>
|
||||||
|
</body>
|
||||||
|
</html>
|
210
origin_migrator/source.js
Normal file
210
origin_migrator/source.js
Normal file
|
@ -0,0 +1,210 @@
|
||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const TARGET_ORIGIN = 'vector://vector';
|
||||||
|
const BATCH_SIZE = 500;
|
||||||
|
let destFrame;
|
||||||
|
|
||||||
|
let initResolver = null;
|
||||||
|
let getSummaryResolver = null;
|
||||||
|
|
||||||
|
function onMessage(e) {
|
||||||
|
if (e.origin !== TARGET_ORIGIN) return;
|
||||||
|
|
||||||
|
if (e.data.cmd === 'initOK' && initResolver) {
|
||||||
|
initResolver();
|
||||||
|
initResolver = null;
|
||||||
|
} else if (e.data.cmd === 'summary' && getSummaryResolver) {
|
||||||
|
getSummaryResolver(e.data.data);
|
||||||
|
getSummaryResolver = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function initDestFrame() {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
initResolver = resolve;
|
||||||
|
destFrame.postMessage({
|
||||||
|
cmd: 'init',
|
||||||
|
}, TARGET_ORIGIN);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getSummary() {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
getSummaryResolver = resolve;
|
||||||
|
destFrame.postMessage({
|
||||||
|
cmd: 'getSummary',
|
||||||
|
}, TARGET_ORIGIN);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function doMigrate() {
|
||||||
|
let accountSent = 0;
|
||||||
|
let sessionsSent = 0;
|
||||||
|
let inboundGroupSessionsSent = 0;
|
||||||
|
let deviceDataSent = 0;
|
||||||
|
let roomsSent = 0;
|
||||||
|
let localStorageKeysSent = 0;
|
||||||
|
|
||||||
|
if (!window.ipcRenderer) {
|
||||||
|
console.error("ipcRenderer not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window.localStorage.getItem('mx_user_id') === null) {
|
||||||
|
window.ipcRenderer.send("origin_migration_nodata");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
destFrame = window.parent.frames.dest;
|
||||||
|
|
||||||
|
await initDestFrame();
|
||||||
|
|
||||||
|
const IndexedDBCryptoStore = window.matrixcs.IndexedDBCryptoStore;
|
||||||
|
|
||||||
|
const cryptoStore = new IndexedDBCryptoStore(window.indexedDB, 'matrix-js-sdk:crypto');
|
||||||
|
|
||||||
|
await cryptoStore.doTxn(
|
||||||
|
'readonly', [IndexedDBCryptoStore.STORE_ACCOUNT],
|
||||||
|
(txn) => {
|
||||||
|
cryptoStore.getAccount(txn, (account) => {
|
||||||
|
destFrame.postMessage({
|
||||||
|
cmd: 'storeAccount',
|
||||||
|
data: account,
|
||||||
|
}, TARGET_ORIGIN);
|
||||||
|
++accountSent;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
await cryptoStore.doTxn(
|
||||||
|
'readonly', [IndexedDBCryptoStore.STORE_SESSIONS],
|
||||||
|
(txn) => {
|
||||||
|
let sessBatch = [];
|
||||||
|
cryptoStore.getAllEndToEndSessions(txn, (sessInfo) => {
|
||||||
|
if (sessInfo) {
|
||||||
|
++sessionsSent;
|
||||||
|
sessBatch.push(sessInfo);
|
||||||
|
}
|
||||||
|
if (sessBatch.length >= BATCH_SIZE || sessInfo === null) {
|
||||||
|
destFrame.postMessage({
|
||||||
|
cmd: 'storeSessions',
|
||||||
|
data: sessBatch,
|
||||||
|
}, TARGET_ORIGIN);
|
||||||
|
sessBatch = [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
await cryptoStore.doTxn(
|
||||||
|
'readonly', [IndexedDBCryptoStore.STORE_INBOUND_GROUP_SESSIONS],
|
||||||
|
(txn) => {
|
||||||
|
let sessBatch = [];
|
||||||
|
cryptoStore.getAllEndToEndInboundGroupSessions(txn, (sessInfo) => {
|
||||||
|
if (sessInfo) {
|
||||||
|
++inboundGroupSessionsSent;
|
||||||
|
sessBatch.push(sessInfo);
|
||||||
|
}
|
||||||
|
if (sessBatch.length >= BATCH_SIZE || sessInfo === null) {
|
||||||
|
destFrame.postMessage({
|
||||||
|
cmd: 'storeInboundGroupSessions',
|
||||||
|
data: sessBatch,
|
||||||
|
}, TARGET_ORIGIN);
|
||||||
|
sessBatch = [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
await cryptoStore.doTxn(
|
||||||
|
'readonly', [IndexedDBCryptoStore.STORE_DEVICE_DATA],
|
||||||
|
(txn) => {
|
||||||
|
cryptoStore.getEndToEndDeviceData(txn, (deviceData) => {
|
||||||
|
destFrame.postMessage({
|
||||||
|
cmd: 'storeDeviceData',
|
||||||
|
data: deviceData,
|
||||||
|
}, TARGET_ORIGIN);
|
||||||
|
++deviceDataSent;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
await cryptoStore.doTxn(
|
||||||
|
'readonly', [IndexedDBCryptoStore.STORE_ROOMS],
|
||||||
|
(txn) => {
|
||||||
|
cryptoStore.getEndToEndRooms(txn, (rooms) => {
|
||||||
|
destFrame.postMessage({
|
||||||
|
cmd: 'storeRooms',
|
||||||
|
data: rooms,
|
||||||
|
}, TARGET_ORIGIN);
|
||||||
|
++roomsSent;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// we don't bother migrating;
|
||||||
|
// * sync data (we can just initialsync again)
|
||||||
|
// * logs
|
||||||
|
// * key requests (worst case they'll just be re-sent)
|
||||||
|
// * sessions needing backup (feature isn't available on Electron)
|
||||||
|
|
||||||
|
for (let i = 0; i < window.localStorage.length; ++i) {
|
||||||
|
const key = window.localStorage.key(i);
|
||||||
|
const val = window.localStorage.getItem(key);
|
||||||
|
|
||||||
|
destFrame.postMessage({
|
||||||
|
cmd: 'storeLocalStorage',
|
||||||
|
data: { key, val },
|
||||||
|
}, TARGET_ORIGIN);
|
||||||
|
++localStorageKeysSent;
|
||||||
|
}
|
||||||
|
|
||||||
|
const summary = await getSummary();
|
||||||
|
let success = false;
|
||||||
|
if (
|
||||||
|
summary.accountStored === accountSent &&
|
||||||
|
summary.sessionsStored === sessionsSent &&
|
||||||
|
summary.inboundGroupSessionsStored === inboundGroupSessionsSent &&
|
||||||
|
summary.deviceDataStored === deviceDataSent &&
|
||||||
|
summary.roomsStored === roomsSent &&
|
||||||
|
summary.localStorageKeysStored === localStorageKeysSent
|
||||||
|
) {
|
||||||
|
success = true;
|
||||||
|
window.localStorage.clear();
|
||||||
|
await cryptoStore.deleteAllData();
|
||||||
|
|
||||||
|
// we don't bother migrating them, but also blow away the sync & logs db,
|
||||||
|
// otherwise they'll just hang about taking up space
|
||||||
|
await new Promise(resolve => {
|
||||||
|
const req = window.indexedDB.deleteDatabase('matrix-js-sdk:riot-web-sync');
|
||||||
|
req.onsuccess = resolve;
|
||||||
|
req.onerror = resolve;
|
||||||
|
});
|
||||||
|
await new Promise(resolve => {
|
||||||
|
const req = window.indexedDB.deleteDatabase('logs');
|
||||||
|
req.onsuccess = resolve;
|
||||||
|
req.onerror = resolve;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
window.ipcRenderer.send("origin_migration_complete", success, {
|
||||||
|
accountSent, sessionsSent, inboundGroupSessionsSent,
|
||||||
|
deviceDataSent, roomsSent, localStorageKeysSent,
|
||||||
|
}, summary);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('message', onMessage);
|
11
package.json
11
package.json
|
@ -2,7 +2,7 @@
|
||||||
"name": "riot-web",
|
"name": "riot-web",
|
||||||
"productName": "Riot",
|
"productName": "Riot",
|
||||||
"main": "electron_app/src/electron-main.js",
|
"main": "electron_app/src/electron-main.js",
|
||||||
"version": "0.17.7",
|
"version": "0.17.8",
|
||||||
"description": "A feature-rich client for Matrix.org",
|
"description": "A feature-rich client for Matrix.org",
|
||||||
"author": "New Vector Ltd.",
|
"author": "New Vector Ltd.",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -70,8 +70,8 @@
|
||||||
"gemini-scrollbar": "github:matrix-org/gemini-scrollbar#b302279",
|
"gemini-scrollbar": "github:matrix-org/gemini-scrollbar#b302279",
|
||||||
"gfm.css": "^1.1.2",
|
"gfm.css": "^1.1.2",
|
||||||
"highlight.js": "^9.13.1",
|
"highlight.js": "^9.13.1",
|
||||||
"matrix-js-sdk": "0.14.1",
|
"matrix-js-sdk": "0.14.2",
|
||||||
"matrix-react-sdk": "0.14.6",
|
"matrix-react-sdk": "0.14.7",
|
||||||
"modernizr": "^3.6.0",
|
"modernizr": "^3.6.0",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^15.6.0",
|
"react": "^15.6.0",
|
||||||
|
@ -150,14 +150,15 @@
|
||||||
},
|
},
|
||||||
"build": {
|
"build": {
|
||||||
"appId": "im.riot.app",
|
"appId": "im.riot.app",
|
||||||
"electronVersion": "3.0.5",
|
"electronVersion": "3.0.10",
|
||||||
"files": [
|
"files": [
|
||||||
"node_modules/**",
|
"node_modules/**",
|
||||||
"src/**",
|
"src/**",
|
||||||
"img/**"
|
"img/**"
|
||||||
],
|
],
|
||||||
"extraResources": [
|
"extraResources": [
|
||||||
"webapp/**/*"
|
"webapp/**/*",
|
||||||
|
"origin_migrator/**/*"
|
||||||
],
|
],
|
||||||
"linux": {
|
"linux": {
|
||||||
"target": "deb",
|
"target": "deb",
|
||||||
|
|
|
@ -1 +1,39 @@
|
||||||
{}
|
{
|
||||||
|
"Riot is not supported on mobile web. Install the app?": "रायट फ़ोन पर समर्थन नहीं हैं। एप्लिकेशन इनस्टॉल करना चाहेंगे ?",
|
||||||
|
"Riot Desktop on %(platformName)s": "%(platformName)s पर रायट डेस्कटॉप",
|
||||||
|
"Unknown device": "अज्ञात यन्त्र",
|
||||||
|
"%(appName)s via %(browserName)s on %(osName)s": "%(osName)s पर %(browserName)s के माध्यम से %(appName)s",
|
||||||
|
"You need to be using HTTPS to place a screen-sharing call.": "स्क्रीन साझा की कॉल करने के लिए आपको HTTPS का उपयोग करने की आवश्यकता है।",
|
||||||
|
"Custom Server Options": "कस्टम सर्वर विकल्प",
|
||||||
|
"You can use the custom server options to sign into other Matrix servers by specifying a different Home server URL.<br/>This allows you to use Riot with an existing Matrix account on a different home server.<br/><br/>You can also set a custom identity server but you won't be able to invite users by email address, or be invited by email address yourself.": "आप एक अलग होम सर्वर यूआरएल निर्दिष्ट करके अन्य मैट्रिक्स सर्वरों में साइन इन करने के लिए कस्टम सर्वर विकल्प का उपयोग कर सकते हैं। <br/> यह आपको एक अलग होम सर्वर पर मौजूदा मैट्रिक्स खाते के साथ रायट का उपयोग करने की अनुमति देता है। <br/> <br/> आप अपना आइडेंटिटी सर्वर भी सेट कर सकते हैं लेकिन आप ईमेल पते से उपयोगकर्ताओं को आमंत्रित नहीं कर पाएंगे, या ईमेल पते से स्वयं आमंत्रित नहीं हों सकेंगे।",
|
||||||
|
"Dismiss": "खारिज",
|
||||||
|
"powered by Matrix": "मैट्रिक्स द्वारा संचालित",
|
||||||
|
"Welcome to Riot.im": "Riot.im में आपका स्वागत है",
|
||||||
|
"Decentralised, encrypted chat & collaboration powered by [matrix]": "[मैट्रिक्स] द्वारा संचालित विकेंद्रीकृत, एन्क्रिप्टेड चैट और सहयोगिता",
|
||||||
|
"Search the room directory": "रूम डायरेक्टरी को खोजें",
|
||||||
|
"Lots of rooms already exist in Matrix, linked to existing networks (Slack, IRC, Gitter etc) or independent. Check out the directory!": "मौजूदा नेटवर्क से जुड़े मैट्रिक्स में बहुत से कमरे पहले से मौजूद हैं (स्लैक, आईआरसी, गिटर इत्यादि) या स्वतंत्र। डायरेक्टरी देखें!",
|
||||||
|
"Chat with Riot Bot": "रायट बॉट के साथ चैट करें",
|
||||||
|
"Get started with some tips from Riot Bot!": "रायट बॉट से कुछ सुझावों के साथ शुरू करें!",
|
||||||
|
"General discussion about Matrix and Riot": "मैट्रिक्स और रायट के बारे में सामान्य चर्चा",
|
||||||
|
"Discussion of all things Matrix!": "मैट्रिक्स की सभी चीजों की चर्चा!",
|
||||||
|
"Riot/Web & Desktop chat": "रायट/वेब और डेस्कटॉप चैट",
|
||||||
|
"Riot/iOS & matrix-ios-sdk chat": "रायट / iOS और matrix-ios-sdk चैट",
|
||||||
|
"Riot/Android & matrix-android-sdk chat": "रायट / एंड्रॉइड और matrix-android-sdk चैट",
|
||||||
|
"Matrix technical discussions": "मैट्रिक्स तकनीकी चर्चाएं",
|
||||||
|
"Running Matrix services": "मैट्रिक्स सेवाएं चलाना",
|
||||||
|
"Community-run support for Synapse": "सामुदायिक चालित Synapse के लिए समर्थन",
|
||||||
|
"Admin support for Dendrite": "डेंडर्राइट के लिए व्यवस्थापक समर्थन",
|
||||||
|
"Announcements about Synapse releases": "Synapse रिलीज के बारे में घोषणाएं",
|
||||||
|
"Support for those using and running matrix-appservice-irc": "Matrix-appservice-irc का उपयोग और चलाने वाले लोगों के लिए समर्थन",
|
||||||
|
"Building services on Matrix": "मैट्रिक्स पर सेवाएं बनाना",
|
||||||
|
"Support for those using the Matrix spec": "मैट्रिक्स spec का उपयोग करने वालों के लिए समर्थन",
|
||||||
|
"Design and implementation of E2E in Matrix": "मैट्रिक्स में E2E के डिजाइन और कार्यान्वयन",
|
||||||
|
"Implementing VR services with Matrix": "मैट्रिक्स के साथ VR सेवाओं को लागू करना",
|
||||||
|
"Implementing VoIP services with Matrix": "मैट्रिक्स के साथ वीओआईपी सेवाओं को लागू करना",
|
||||||
|
"Discussion of the Identity Service API": "आइडेंटिटी सर्विस API की चर्चा",
|
||||||
|
"Support for those using, running and writing other bridges": "अन्य ब्रिज का उपयोग, चलाने और लिखने वालों के लिए समर्थन",
|
||||||
|
"Contributing code to Matrix and Riot": "मैट्रिक्स और रायट में कोड योगदान करना",
|
||||||
|
"Dev chat for the Riot/Web dev team": "रायट / वेब डेव टीम के लिए डेवलपर चैट",
|
||||||
|
"Dev chat for the Dendrite dev team": "डेन्ड्राइट देव टीम के लिए डेवलपर चैट",
|
||||||
|
"Co-ordination for Riot translators": "रायट अनुवादकों के लिए समन्वय"
|
||||||
|
}
|
||||||
|
|
|
@ -47,7 +47,9 @@ import * as languageHandler from 'matrix-react-sdk/lib/languageHandler';
|
||||||
import url from 'url';
|
import url from 'url';
|
||||||
|
|
||||||
import {parseQs, parseQsFromFragment} from './url_utils';
|
import {parseQs, parseQsFromFragment} from './url_utils';
|
||||||
import Platform from './platform';
|
|
||||||
|
import ElectronPlatform from './platform/ElectronPlatform';
|
||||||
|
import WebPlatform from './platform/WebPlatform';
|
||||||
|
|
||||||
import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
|
import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
|
||||||
import SettingsStore from "matrix-react-sdk/lib/settings/SettingsStore";
|
import SettingsStore from "matrix-react-sdk/lib/settings/SettingsStore";
|
||||||
|
@ -226,8 +228,23 @@ async function loadApp() {
|
||||||
const fragparts = parseQsFromFragment(window.location);
|
const fragparts = parseQsFromFragment(window.location);
|
||||||
const params = parseQs(window.location);
|
const params = parseQs(window.location);
|
||||||
|
|
||||||
// set the platform for react sdk (our Platform object automatically picks the right one)
|
// set the platform for react sdk
|
||||||
PlatformPeg.set(new Platform());
|
if (window.ipcRenderer) {
|
||||||
|
console.log("Using Electron platform");
|
||||||
|
const plaf = new ElectronPlatform();
|
||||||
|
PlatformPeg.set(plaf);
|
||||||
|
|
||||||
|
// Electron only: see if we need to do a one-time data
|
||||||
|
// migration
|
||||||
|
if (window.localStorage.getItem('mx_user_id') === null) {
|
||||||
|
console.log("Migrating session from old origin...");
|
||||||
|
await plaf.migrateFromOldOrigin();
|
||||||
|
console.log("Origin migration complete");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log("Using Web platform");
|
||||||
|
PlatformPeg.set(new WebPlatform());
|
||||||
|
}
|
||||||
|
|
||||||
// Load the config file. First try to load up a domain-specific config of the
|
// Load the config file. First try to load up a domain-specific config of the
|
||||||
// form "config.$domain.json" and if that fails, fall back to config.json.
|
// form "config.$domain.json" and if that fails, fall back to config.json.
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016 Aviral Dasgupta
|
Copyright 2016 Aviral Dasgupta
|
||||||
Copyright 2016 OpenMarket Ltd
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
Copyright 2018 New Vector 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.
|
||||||
|
@ -21,44 +22,26 @@ import VectorBasePlatform, {updateCheckStatusEnum} from './VectorBasePlatform';
|
||||||
import dis from 'matrix-react-sdk/lib/dispatcher';
|
import dis from 'matrix-react-sdk/lib/dispatcher';
|
||||||
import { _t } from 'matrix-react-sdk/lib/languageHandler';
|
import { _t } from 'matrix-react-sdk/lib/languageHandler';
|
||||||
import Promise from 'bluebird';
|
import Promise from 'bluebird';
|
||||||
import {remote, ipcRenderer, desktopCapturer} from 'electron';
|
|
||||||
import rageshake from 'matrix-react-sdk/lib/rageshake/rageshake';
|
import rageshake from 'matrix-react-sdk/lib/rageshake/rageshake';
|
||||||
|
|
||||||
remote.autoUpdater.on('update-downloaded', onUpdateDownloaded);
|
const ipcRenderer = window.ipcRenderer;
|
||||||
|
|
||||||
// try to flush the rageshake logs to indexeddb before quit.
|
|
||||||
ipcRenderer.on('before-quit', function() {
|
|
||||||
console.log('riot-desktop closing');
|
|
||||||
rageshake.flush();
|
|
||||||
});
|
|
||||||
|
|
||||||
function onUpdateDownloaded(ev: Event, releaseNotes: string, ver: string, date: Date, updateURL: string) {
|
|
||||||
dis.dispatch({
|
|
||||||
action: 'new_version',
|
|
||||||
currentVersion: remote.app.getVersion(),
|
|
||||||
newVersion: ver,
|
|
||||||
releaseNotes: releaseNotes,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function platformFriendlyName(): string {
|
function platformFriendlyName(): string {
|
||||||
console.log(window.process);
|
// used to use window.process but the same info is available here
|
||||||
switch (window.process.platform) {
|
if (navigator.userAgent.indexOf('Macintosh')) {
|
||||||
case 'darwin':
|
return 'macOS';
|
||||||
return 'macOS';
|
} else if (navigator.userAgent.indexOf('FreeBSD')) {
|
||||||
case 'freebsd':
|
return 'FreeBSD';
|
||||||
return 'FreeBSD';
|
} else if (navigator.userAgent.indexOf('OpenBSD')) {
|
||||||
case 'openbsd':
|
return 'OpenBSD';
|
||||||
return 'OpenBSD';
|
} else if (navigator.userAgent.indexOf('SunOS')) {
|
||||||
case 'sunos':
|
return 'SunOS';
|
||||||
return 'SunOS';
|
} else if (navigator.userAgent.indexOf('Windows')) {
|
||||||
case 'win32':
|
return 'Windows';
|
||||||
return 'Windows';
|
} else if (navigator.userAgent.indexOf('Linux')) {
|
||||||
default:
|
return 'Linux';
|
||||||
// Sorry, Linux users: you get lumped into here,
|
} else {
|
||||||
// but only because Linux's capitalisation is
|
return 'Unknown';
|
||||||
// normal. We do care about you.
|
|
||||||
return window.process.platform[0].toUpperCase() + window.process.platform.slice(1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,9 +68,11 @@ function getUpdateCheckStatus(status) {
|
||||||
export default class ElectronPlatform extends VectorBasePlatform {
|
export default class ElectronPlatform extends VectorBasePlatform {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
dis.register(_onAction);
|
|
||||||
this.updatable = Boolean(remote.autoUpdater.getFeedURL());
|
|
||||||
|
|
||||||
|
this._pendingIpcCalls = {};
|
||||||
|
this._nextIpcCallId = 0;
|
||||||
|
|
||||||
|
dis.register(_onAction);
|
||||||
/*
|
/*
|
||||||
IPC Call `check_updates` returns:
|
IPC Call `check_updates` returns:
|
||||||
true if there is an update available
|
true if there is an update available
|
||||||
|
@ -103,10 +88,28 @@ export default class ElectronPlatform extends VectorBasePlatform {
|
||||||
this.showUpdateCheck = false;
|
this.showUpdateCheck = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// try to flush the rageshake logs to indexeddb before quit.
|
||||||
|
ipcRenderer.on('before-quit', function() {
|
||||||
|
console.log('riot-desktop closing');
|
||||||
|
rageshake.flush();
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcRenderer.on('ipcReply', this._onIpcReply.bind(this));
|
||||||
|
ipcRenderer.on('update-downloaded', this.onUpdateDownloaded.bind(this));
|
||||||
|
|
||||||
this.startUpdateCheck = this.startUpdateCheck.bind(this);
|
this.startUpdateCheck = this.startUpdateCheck.bind(this);
|
||||||
this.stopUpdateCheck = this.stopUpdateCheck.bind(this);
|
this.stopUpdateCheck = this.stopUpdateCheck.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async onUpdateDownloaded(ev, updateInfo) {
|
||||||
|
dis.dispatch({
|
||||||
|
action: 'new_version',
|
||||||
|
currentVersion: await this.getAppVersion(),
|
||||||
|
newVersion: updateInfo,
|
||||||
|
releaseNotes: updateInfo.releaseNotes,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
getHumanReadableName(): string {
|
getHumanReadableName(): string {
|
||||||
return 'Electron Platform'; // no translation required: only used for analytics
|
return 'Electron Platform'; // no translation required: only used for analytics
|
||||||
}
|
}
|
||||||
|
@ -133,7 +136,7 @@ export default class ElectronPlatform extends VectorBasePlatform {
|
||||||
// maybe we should pass basic styling (italics, bold, underline) through from MD
|
// maybe we should pass basic styling (italics, bold, underline) through from MD
|
||||||
// we only have to strip out < and > as the spec doesn't include anything about things like &
|
// we only have to strip out < and > as the spec doesn't include anything about things like &
|
||||||
// so we shouldn't assume that all implementations will treat those properly. Very basic tag parsing is done.
|
// so we shouldn't assume that all implementations will treat those properly. Very basic tag parsing is done.
|
||||||
if (window.process.platform === 'linux') {
|
if (navigator.userAgent.indexOf('Linux')) {
|
||||||
msg = msg.replace(/</g, '<').replace(/>/g, '>');
|
msg = msg.replace(/</g, '<').replace(/>/g, '>');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,17 +150,13 @@ export default class ElectronPlatform extends VectorBasePlatform {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
notification.onclick = function() {
|
notification.onclick = () => {
|
||||||
dis.dispatch({
|
dis.dispatch({
|
||||||
action: 'view_room',
|
action: 'view_room',
|
||||||
room_id: room.roomId,
|
room_id: room.roomId,
|
||||||
});
|
});
|
||||||
global.focus();
|
global.focus();
|
||||||
const win = remote.getCurrentWindow();
|
this._ipcCall('focusWindow');
|
||||||
|
|
||||||
if (win.isMinimized()) win.restore();
|
|
||||||
else if (!win.isVisible()) win.show();
|
|
||||||
else win.focus();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return notification;
|
return notification;
|
||||||
|
@ -171,8 +170,25 @@ export default class ElectronPlatform extends VectorBasePlatform {
|
||||||
notif.close();
|
notif.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
getAppVersion(): Promise<string> {
|
async getAppVersion(): Promise<string> {
|
||||||
return Promise.resolve(remote.app.getVersion());
|
return await this._ipcCall('getAppVersion');
|
||||||
|
}
|
||||||
|
|
||||||
|
supportsAutoLaunch() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAutoLaunchEnabled() {
|
||||||
|
return await this._ipcCall('getAutoLaunchEnabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
async setAutoLaunchEnabled(enabled) {
|
||||||
|
return await this._ipcCall('setAutoLaunchEnabled', enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
async canSelfUpdate(): boolean {
|
||||||
|
const feedUrl = await this._ipcCall('getUpdateFeedUrl');
|
||||||
|
return Boolean(feedUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
startUpdateCheck() {
|
startUpdateCheck() {
|
||||||
|
@ -197,52 +213,47 @@ export default class ElectronPlatform extends VectorBasePlatform {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
isElectron(): boolean { return true; }
|
|
||||||
|
|
||||||
requestNotificationPermission(): Promise<string> {
|
requestNotificationPermission(): Promise<string> {
|
||||||
return Promise.resolve('granted');
|
return Promise.resolve('granted');
|
||||||
}
|
}
|
||||||
|
|
||||||
reload() {
|
reload() {
|
||||||
remote.getCurrentWebContents().reload();
|
// we used to remote to the main process to get it to
|
||||||
|
// reload the webcontents, but in practice this is unnecessary:
|
||||||
|
// the normal way works fine.
|
||||||
|
window.location.reload(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BEGIN copied and slightly-modified code
|
async migrateFromOldOrigin() {
|
||||||
* setupScreenSharingForIframe function from:
|
return this._ipcCall('origin_migrate');
|
||||||
* https://github.com/jitsi/jitsi-meet-electron-utils
|
}
|
||||||
* Copied directly here to avoid the need for a native electron module for
|
|
||||||
* 'just a bit of JavaScript'
|
async _ipcCall(name, ...args) {
|
||||||
* NOTE: Apache v2.0 licensed
|
const ipcCallId = ++this._nextIpcCallId;
|
||||||
*/
|
return new Promise((resolve, reject) => {
|
||||||
setupScreenSharingForIframe(iframe: Object) {
|
this._pendingIpcCalls[ipcCallId] = {resolve, reject};
|
||||||
iframe.contentWindow.JitsiMeetElectron = {
|
window.ipcRenderer.send('ipcCall', {id: ipcCallId, name, args});
|
||||||
/**
|
// Maybe add a timeout to these? Probably not necessary.
|
||||||
* Get sources available for screensharing. The callback is invoked
|
});
|
||||||
* with an array of DesktopCapturerSources.
|
}
|
||||||
*
|
|
||||||
* @param {Function} callback - The success callback.
|
_onIpcReply(ev, payload) {
|
||||||
* @param {Function} errorCallback - The callback for errors.
|
if (payload.id === undefined) {
|
||||||
* @param {Object} options - Configuration for getting sources.
|
console.warn("Ignoring IPC reply with no ID");
|
||||||
* @param {Array} options.types - Specify the desktop source types
|
return;
|
||||||
* to get, with valid sources being "window" and "screen".
|
}
|
||||||
* @param {Object} options.thumbnailSize - Specify how big the
|
|
||||||
* preview images for the sources should be. The valid keys are
|
if (this._pendingIpcCalls[payload.id] === undefined) {
|
||||||
* height and width, e.g. { height: number, width: number}. By
|
console.warn("Unknown IPC payload ID: " + payload.id);
|
||||||
* default electron will return images with height and width of
|
return;
|
||||||
* 150px.
|
}
|
||||||
*/
|
|
||||||
obtainDesktopStreams(callback, errorCallback, options = {}) {
|
const callbacks = this._pendingIpcCalls[payload.id];
|
||||||
desktopCapturer.getSources(options,
|
delete this._pendingIpcCalls[payload.id];
|
||||||
(error, sources) => {
|
if (payload.error) {
|
||||||
if (error) {
|
callbacks.reject(payload.error);
|
||||||
errorCallback(error);
|
} else {
|
||||||
return;
|
callbacks.resolve(payload.reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(sources);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
/* END of copied and slightly-modified code */
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016 Aviral Dasgupta
|
Copyright 2016 Aviral Dasgupta
|
||||||
Copyright 2016 OpenMarket Ltd
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
Copyright 2018 New Vector 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.
|
||||||
|
@ -45,7 +46,6 @@ export default class VectorBasePlatform extends BasePlatform {
|
||||||
this.favicon = new Favico({animation: 'none'});
|
this.favicon = new Favico({animation: 'none'});
|
||||||
this.showUpdateCheck = false;
|
this.showUpdateCheck = false;
|
||||||
this._updateFavicon();
|
this._updateFavicon();
|
||||||
this.updatable = true;
|
|
||||||
|
|
||||||
this.startUpdateCheck = this.startUpdateCheck.bind(this);
|
this.startUpdateCheck = this.startUpdateCheck.bind(this);
|
||||||
this.stopUpdateCheck = this.stopUpdateCheck.bind(this);
|
this.stopUpdateCheck = this.stopUpdateCheck.bind(this);
|
||||||
|
@ -88,6 +88,19 @@ export default class VectorBasePlatform extends BasePlatform {
|
||||||
this._updateFavicon();
|
this._updateFavicon();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
supportsAutoLaunch() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX: Surely this should be a setting like any other?
|
||||||
|
async getAutoLaunchEnabled() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async setAutoLaunchEnabled(enabled) {
|
||||||
|
throw new Error("Unimplemented");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Begin update polling, if applicable
|
* Begin update polling, if applicable
|
||||||
*/
|
*/
|
||||||
|
@ -97,8 +110,8 @@ export default class VectorBasePlatform extends BasePlatform {
|
||||||
/**
|
/**
|
||||||
* Whether we can call checkForUpdate on this platform build
|
* Whether we can call checkForUpdate on this platform build
|
||||||
*/
|
*/
|
||||||
canSelfUpdate(): boolean {
|
async canSelfUpdate(): boolean {
|
||||||
return this.updatable;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
startUpdateCheck() {
|
startUpdateCheck() {
|
||||||
|
@ -136,4 +149,12 @@ export default class VectorBasePlatform extends BasePlatform {
|
||||||
getDefaultDeviceDisplayName(): string {
|
getDefaultDeviceDisplayName(): string {
|
||||||
return _t("Unknown device");
|
return _t("Unknown device");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migrate account data from a previous origin
|
||||||
|
* Used only for the electron app
|
||||||
|
*/
|
||||||
|
async migrateFromOldOrigin() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,6 +142,10 @@ export default class WebPlatform extends VectorBasePlatform {
|
||||||
setInterval(this.pollForUpdate.bind(this), POKE_RATE_MS);
|
setInterval(this.pollForUpdate.bind(this), POKE_RATE_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async canSelfUpdate(): boolean {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
pollForUpdate() {
|
pollForUpdate() {
|
||||||
return this._getVersion().then((ver) => {
|
return this._getVersion().then((ver) => {
|
||||||
if (this.runningVersion === null) {
|
if (this.runningVersion === null) {
|
||||||
|
|
|
@ -26,10 +26,13 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import rageshake from "matrix-react-sdk/lib/rageshake/rageshake";
|
import rageshake from "matrix-react-sdk/lib/rageshake/rageshake";
|
||||||
|
import SdkConfig from "matrix-react-sdk/src/SdkConfig";
|
||||||
|
|
||||||
function initRageshake() {
|
function initRageshake() {
|
||||||
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.");
|
||||||
|
console.log("To fix line numbers in Chrome: " +
|
||||||
|
"Meatball menu → Settings → Blackboxing → Add /rageshake\\.js$");
|
||||||
|
|
||||||
window.addEventListener('beforeunload', (e) => {
|
window.addEventListener('beforeunload', (e) => {
|
||||||
console.log('riot-web closing');
|
console.log('riot-web closing');
|
||||||
|
@ -44,3 +47,18 @@ function initRageshake() {
|
||||||
}
|
}
|
||||||
|
|
||||||
initRageshake();
|
initRageshake();
|
||||||
|
|
||||||
|
global.mxSendRageshake = function(text, withLogs) {
|
||||||
|
if (withLogs === undefined) withLogs = true;
|
||||||
|
require(['matrix-react-sdk/lib/rageshake/submit-rageshake'], (s) => {
|
||||||
|
s(SdkConfig.get().bug_report_endpoint_url, {
|
||||||
|
userText: text,
|
||||||
|
sendLogs: withLogs,
|
||||||
|
progressCallback: console.log.bind(console),
|
||||||
|
}).then(() => {
|
||||||
|
console.log("Bug report sent!");
|
||||||
|
}, (err) => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
|
@ -17,7 +17,7 @@ limitations under the License.
|
||||||
/* joining.js: tests for the various paths when joining a room */
|
/* joining.js: tests for the various paths when joining a room */
|
||||||
|
|
||||||
import PlatformPeg from 'matrix-react-sdk/lib/PlatformPeg';
|
import PlatformPeg from 'matrix-react-sdk/lib/PlatformPeg';
|
||||||
import Platform from '../../src/vector/platform';
|
import WebPlatform from '../../src/vector/platform/WebPlatform';
|
||||||
|
|
||||||
require('skin-sdk');
|
require('skin-sdk');
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ describe('joining a room', function() {
|
||||||
localStorage.setItem("mx_access_token", ACCESS_TOKEN );
|
localStorage.setItem("mx_access_token", ACCESS_TOKEN );
|
||||||
localStorage.setItem("mx_user_id", USER_ID);
|
localStorage.setItem("mx_user_id", USER_ID);
|
||||||
|
|
||||||
PlatformPeg.set(new Platform());
|
PlatformPeg.set(new WebPlatform());
|
||||||
|
|
||||||
const mc = (
|
const mc = (
|
||||||
<MatrixChat config={{}}
|
<MatrixChat config={{}}
|
||||||
|
|
|
@ -17,7 +17,7 @@ limitations under the License.
|
||||||
/* loading.js: test the myriad paths we have for loading the application */
|
/* loading.js: test the myriad paths we have for loading the application */
|
||||||
|
|
||||||
import PlatformPeg from 'matrix-react-sdk/lib/PlatformPeg';
|
import PlatformPeg from 'matrix-react-sdk/lib/PlatformPeg';
|
||||||
import Platform from '../../src/vector/platform';
|
import WebPlatform from '../../src/vector/platform/WebPlatform';
|
||||||
|
|
||||||
import 'skin-sdk';
|
import 'skin-sdk';
|
||||||
|
|
||||||
|
@ -43,6 +43,17 @@ import {parseQs, parseQsFromFragment} from '../../src/vector/url_utils';
|
||||||
const DEFAULT_HS_URL='http://my_server';
|
const DEFAULT_HS_URL='http://my_server';
|
||||||
const DEFAULT_IS_URL='http://my_is';
|
const DEFAULT_IS_URL='http://my_is';
|
||||||
|
|
||||||
|
expect.extend({
|
||||||
|
toStartWith(prefix) {
|
||||||
|
expect.assert(
|
||||||
|
this.actual.startsWith(prefix),
|
||||||
|
'expected %s to start with %s',
|
||||||
|
this.actual, prefix,
|
||||||
|
);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
describe('loading:', function() {
|
describe('loading:', function() {
|
||||||
let parentDiv;
|
let parentDiv;
|
||||||
let httpBackend;
|
let httpBackend;
|
||||||
|
@ -140,7 +151,7 @@ describe('loading:', function() {
|
||||||
default_is_url: DEFAULT_IS_URL,
|
default_is_url: DEFAULT_IS_URL,
|
||||||
}, opts.config || {});
|
}, opts.config || {});
|
||||||
|
|
||||||
PlatformPeg.set(new Platform());
|
PlatformPeg.set(new WebPlatform());
|
||||||
|
|
||||||
const params = parseQs(windowLocation);
|
const params = parseQs(windowLocation);
|
||||||
matrixChat = ReactDOM.render(
|
matrixChat = ReactDOM.render(
|
||||||
|
@ -437,10 +448,7 @@ describe('loading:', function() {
|
||||||
}).done(done, done);
|
}).done(done, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('uses the last known homeserver to register with', function(done) {
|
it('uses the default homeserver to register with', function(done) {
|
||||||
localStorage.setItem("mx_hs_url", "https://homeserver" );
|
|
||||||
localStorage.setItem("mx_is_url", "https://idserver" );
|
|
||||||
|
|
||||||
loadApp();
|
loadApp();
|
||||||
|
|
||||||
Promise.delay(1).then(() => {
|
Promise.delay(1).then(() => {
|
||||||
|
@ -449,7 +457,7 @@ describe('loading:', function() {
|
||||||
assertAtLoadingSpinner(matrixChat);
|
assertAtLoadingSpinner(matrixChat);
|
||||||
|
|
||||||
httpBackend.when('POST', '/register').check(function(req) {
|
httpBackend.when('POST', '/register').check(function(req) {
|
||||||
expect(req.path).toMatch(new RegExp("^https://homeserver/"));
|
expect(req.path).toStartWith(DEFAULT_HS_URL);
|
||||||
expect(req.queryParams.kind).toEqual('guest');
|
expect(req.queryParams.kind).toEqual('guest');
|
||||||
}).respond(200, {
|
}).respond(200, {
|
||||||
user_id: "@guest:localhost",
|
user_id: "@guest:localhost",
|
||||||
|
@ -462,15 +470,15 @@ describe('loading:', function() {
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
return expectAndAwaitSync();
|
return expectAndAwaitSync();
|
||||||
}).then((req) => {
|
}).then((req) => {
|
||||||
expect(req.path).toMatch(new RegExp("^https://homeserver/"));
|
expect(req.path).toStartWith(DEFAULT_HS_URL);
|
||||||
|
|
||||||
// once the sync completes, we should have a home page
|
// once the sync completes, we should have a home page
|
||||||
httpBackend.verifyNoOutstandingExpectation();
|
httpBackend.verifyNoOutstandingExpectation();
|
||||||
ReactTestUtils.findRenderedComponentWithType(
|
ReactTestUtils.findRenderedComponentWithType(
|
||||||
matrixChat, sdk.getComponent('structures.HomePage'));
|
matrixChat, sdk.getComponent('structures.HomePage'));
|
||||||
expect(windowLocation.hash).toEqual("#/home");
|
expect(windowLocation.hash).toEqual("#/home");
|
||||||
expect(MatrixClientPeg.get().baseUrl).toEqual("https://homeserver");
|
expect(MatrixClientPeg.get().baseUrl).toEqual(DEFAULT_HS_URL);
|
||||||
expect(MatrixClientPeg.get().idBaseUrl).toEqual("https://idserver");
|
expect(MatrixClientPeg.get().idBaseUrl).toEqual(DEFAULT_IS_URL);
|
||||||
}).done(done, done);
|
}).done(done, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -109,11 +109,6 @@ module.exports = {
|
||||||
"matrix-js-sdk": path.resolve('./node_modules/matrix-js-sdk'),
|
"matrix-js-sdk": path.resolve('./node_modules/matrix-js-sdk'),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
externals: {
|
|
||||||
// Don't try to bundle electron: leave it as a commonjs dependency
|
|
||||||
// (the 'commonjs' here means it will output a 'require')
|
|
||||||
"electron": "commonjs electron",
|
|
||||||
},
|
|
||||||
plugins: [
|
plugins: [
|
||||||
new webpack.DefinePlugin({
|
new webpack.DefinePlugin({
|
||||||
'process.env': {
|
'process.env': {
|
||||||
|
|
Loading…
Reference in a new issue