diff --git a/README.md b/README.md index 53c86dec..b506948c 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ Riot is a modular webapp built with modern ES6 and uses a Node.js build system. Ensure you have the latest LTS version of Node.js installed. Using `yarn` instead of `npm` is recommended. Please see the Yarn [install -guide](https://yarnpkg.com/docs/install/) if you do not have it already. +guide](https://classic.yarnpkg.com/en/docs/install) if you do not have it already. 1. Install or update `node.js` so that your `node` is at least v10.x. 1. Install `yarn` if not present already. diff --git a/electron_app/src/electron-main.js b/electron_app/src/electron-main.js index b67992c2..62f1fb38 100644 --- a/electron_app/src/electron-main.js +++ b/electron_app/src/electron-main.js @@ -237,6 +237,16 @@ ipcMain.on('ipcCall', async function(ev, payload) { case 'getConfig': ret = vectorConfig; break; + case 'navigateBack': + if (mainWindow.webContents.canGoBack()) { + mainWindow.webContents.goBack(); + } + break; + case 'navigateForward': + if (mainWindow.webContents.canGoForward()) { + mainWindow.webContents.goForward(); + } + break; case 'startSSOFlow': recordSSOSession(args[0]); break; diff --git a/package.json b/package.json index d924ed74..45f99265 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "clean": "rimraf lib webapp electron_app/dist", "build": "yarn clean && yarn build:genfiles && yarn build:compile && yarn build:types && yarn build:bundle", "build-stats": "yarn clean && yarn build:genfiles && yarn build:compile && yarn build:types && yarn build:bundle-stats", - "build:jitsi": "curl -s https://jitsi.riot.im/libs/external_api.min.js > ./webapp/jitsi_external_api.min.js", + "build:jitsi": "scripts/build-jitsi.sh", "build:res": "node scripts/copy-res.js", "build:genfiles": "yarn reskindex && yarn build:res && yarn build:jitsi", "build:modernizr": "modernizr -c .modernizr.json -d src/vector/modernizr.js", diff --git a/scripts/build-jitsi.sh b/scripts/build-jitsi.sh new file mode 100755 index 00000000..5d4bdafe --- /dev/null +++ b/scripts/build-jitsi.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +if [[ ! -f "./webapp" ]]; then + mkdir "./webapp" +fi + +curl -s https://jitsi.riot.im/libs/external_api.min.js > ./webapp/jitsi_external_api.min.js diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index a7f2f40c..a10e48ac 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -9,6 +9,7 @@ "Unable to load config file: please refresh the page to try again.": "Unable to load config file: please refresh the page to try again.", "Unexpected error preparing the app. See console for details.": "Unexpected error preparing the app. See console for details.", "Open user settings": "Open user settings", + "Previous/next recently visited room or community": "Previous/next recently visited room or community", "Riot Desktop on %(platformName)s": "Riot Desktop on %(platformName)s", "Go to your browser to complete Sign In": "Go to your browser to complete Sign In", "Unknown device": "Unknown device", diff --git a/src/vector/index.ts b/src/vector/index.ts index a4f494bd..c8205873 100644 --- a/src/vector/index.ts +++ b/src/vector/index.ts @@ -109,7 +109,8 @@ async function start() { "./init"); try { - await settled(rageshakePromise); // give rageshake a chance to load/fail + // give rageshake a chance to load/fail, we don't actually assert rageshake loads, we allow it to fail if no IDB + await settled(rageshakePromise); const fragparts = parseQsFromFragment(window.location); @@ -182,7 +183,6 @@ async function start() { // app load critical path starts here // assert things started successfully // ################################## - await rageshakePromise; await loadOlmPromise; await loadSkinPromise; await loadThemePromise; diff --git a/src/vector/platform/ElectronPlatform.js b/src/vector/platform/ElectronPlatform.js index e60382b7..aee9ee49 100644 --- a/src/vector/platform/ElectronPlatform.js +++ b/src/vector/platform/ElectronPlatform.js @@ -219,7 +219,7 @@ export default class ElectronPlatform extends VectorBasePlatform { this.startUpdateCheck = this.startUpdateCheck.bind(this); this.stopUpdateCheck = this.stopUpdateCheck.bind(this); - // register Mac specific shortcuts + // register OS-specific shortcuts if (isMac) { registerShortcut(Categories.NAVIGATION, { keybinds: [{ @@ -228,6 +228,28 @@ export default class ElectronPlatform extends VectorBasePlatform { }], description: _td("Open user settings"), }); + + registerShortcut(Categories.NAVIGATION, { + keybinds: [{ + modifiers: [Modifiers.COMMAND], + key: Key.SQUARE_BRACKET_LEFT, + }, { + modifiers: [Modifiers.COMMAND], + key: Key.SQUARE_BRACKET_RIGHT, + }], + description: _td("Previous/next recently visited room or community"), + }); + } else { + registerShortcut(Categories.NAVIGATION, { + keybinds: [{ + modifiers: [Modifiers.ALT], + key: Key.ARROW_LEFT, + }, { + modifiers: [Modifiers.ALT], + key: Key.ARROW_RIGHT, + }], + description: _td("Previous/next recently visited room or community"), + }); } // this is the opaque token we pass to the HS which when we get it in our callback we can resolve to a profile @@ -440,4 +462,32 @@ export default class ElectronPlatform extends VectorBasePlatform { description: , }); } + + _navigateForwardBack(back: boolean) { + this._ipcCall(back ? "navigateBack" : "navigateForward"); + } + + onKeyDown(ev: KeyboardEvent): boolean { + let handled = false; + + switch (ev.key) { + case Key.SQUARE_BRACKET_LEFT: + case Key.SQUARE_BRACKET_RIGHT: + if (isMac && ev.metaKey && !ev.altKey && !ev.ctrlKey && !ev.shiftKey) { + this._navigateForwardBack(ev.key === Key.SQUARE_BRACKET_LEFT); + handled = true; + } + break; + + case Key.ARROW_LEFT: + case Key.ARROW_RIGHT: + if (!isMac && ev.altKey && !ev.metaKey && !ev.ctrlKey && !ev.shiftKey) { + this._navigateForwardBack(ev.key === Key.ARROW_LEFT); + handled = true; + } + break; + } + + return handled; + } }