Merge remote-tracking branch 'origin/develop' into jryans/review-policy

pull/12730/head
J. Ryan Stinnett 2020-03-26 11:34:29 +00:00
commit da249cbc40
33 changed files with 440 additions and 103 deletions

1
.gitignore vendored
View File

@ -21,3 +21,4 @@ electron/pub
/config.local*.json
/src/component-index.js
/.tmp
/webpack-stats.json

View File

@ -25,6 +25,9 @@
"test/svg/asimg",
"test/svg/filters",
"test/url/parser",
"test/url/urlsearchparams",
"test/cors",
"test/iframe/sandbox",
"test/json",

View File

@ -1,3 +1,32 @@
Changes in [1.5.13](https://github.com/vector-im/riot-web/releases/tag/v1.5.13) (2020-03-17)
============================================================================================
[Full Changelog](https://github.com/vector-im/riot-web/compare/v1.5.13-rc.1...v1.5.13)
* Upgrade to JS SDK 5.1.1 and React SDK 2.2.3
Changes in [1.5.13-rc.1](https://github.com/vector-im/riot-web/releases/tag/v1.5.13-rc.1) (2020-03-11)
======================================================================================================
[Full Changelog](https://github.com/vector-im/riot-web/compare/v1.5.12...v1.5.13-rc.1)
* Update from Weblate
[\#12688](https://github.com/vector-im/riot-web/pull/12688)
* Fix Docker image version for develop builds
[\#12670](https://github.com/vector-im/riot-web/pull/12670)
* docker: optimize custom sdk builds
[\#12612](https://github.com/vector-im/riot-web/pull/12612)
* riot-desktop open SSO in browser so user doesn't have to auth twice
[\#12590](https://github.com/vector-im/riot-web/pull/12590)
* Fix SSO flows for electron 8.0.2 by re-breaking will-navigate
[\#12585](https://github.com/vector-im/riot-web/pull/12585)
* index.html: Place noscript on top of the page
[\#12563](https://github.com/vector-im/riot-web/pull/12563)
* Remove will-navigate comment after Electron fix
[\#12561](https://github.com/vector-im/riot-web/pull/12561)
* Update loading test for JS SDK IDB change
[\#12552](https://github.com/vector-im/riot-web/pull/12552)
* Upgrade deps
[\#12528](https://github.com/vector-im/riot-web/pull/12528)
Changes in [1.5.12](https://github.com/vector-im/riot-web/releases/tag/v1.5.12) (2020-03-04)
============================================================================================
[Full Changelog](https://github.com/vector-im/riot-web/compare/v1.5.11...v1.5.12)

View File

@ -22,7 +22,6 @@
"https://scalar-staging.vector.im/api",
"https://scalar-staging.riot.im/scalar/api"
],
"integrations_jitsi_widget_url": "https://scalar.vector.im/api/widgets/jitsi.html",
"bug_report_endpoint_url": "https://riot.im/bugreports/submit",
"defaultCountryCode": "GB",
"showLabsSettings": false,
@ -52,5 +51,9 @@
},
"settingDefaults": {
"breadcrumbs": true
},
"jitsi": {
"preferredDomain": "jitsi.riot.im",
"externalApiUrl": "https://jitsi.riot.im/libs/external_api.min.js"
}
}

View File

@ -84,6 +84,13 @@ For a good example, see https://riot.im/develop/config.json.
By default, this is "https://matrix.to" to generate matrix.to (spec) permalinks.
Set this to your Riot instance URL if you run an unfederated server (eg:
"https://riot.example.org").
1. `jitsi`: Used to change the default conference options.
1. `preferredDomain`: The domain name of the preferred Jitsi instance. Defaults
to `jitsi.riot.im`. This is used whenever a user clicks on the voice/video
call buttons - integration managers may use a different domain.
1. `externalApiUrl`: The URL to the Jitsi Meet API script. This is required
for showing any Jitsi widgets, no matter the source. Defaults to
`https://jitsi.riot.im/libs/external_api.min.js`.
Note that `index.html` also has an og:image meta tag that is set to an image
hosted on riot.im. This is the image used if links to your copy of Riot

View File

@ -1,15 +0,0 @@
# Keyboard Shortcuts
The modifier is <kbd>Ctrl</kbd> on Windows & Linux and <kbd></kbd> on Mac.
- <kbd>Ctrl</kbd>/<kbd></kbd>+<kbd>m</kbd> - toggle markdown
- <kbd>Ctrl</kbd>/<kbd></kbd>+<kbd>d</kbd> - toggle mic mute
- <kbd>Ctrl</kbd>/<kbd></kbd>+<kbd>e</kbd> - toggle video on/off
- <kbd>Ctrl</kbd>/<kbd></kbd>+<kbd>k</kbd> - jump to named room
- <kbd></kbd>/<kbd></kbd> - navigate old messages to edit when the composer is in focus
- <kbd></kbd>/<kbd></kbd> - next/prev room when focus in room list
- <kbd>Alt</kbd>+<kbd></kbd>/<kbd></kbd> - resend previous messages when the composer is in focus
- <kbd>PageUp</kbd>/<kbd>PageDown</kbd> - scroll timeline up/down
- <kbd>Ctrl</kbd>/<kbd></kbd>+<kbd>Home</kbd>/<kbd>End</kbd> - jump to
start/end of the composer when focused, otherwise jump to timeline start/end
- <kbd>Ctrl</kbd>/<kbd></kbd>+<kbd>`</kbd> - toggle the top left menu

View File

@ -2,7 +2,7 @@
"name": "riot-web",
"productName": "Riot",
"main": "src/electron-main.js",
"version": "1.5.12",
"version": "1.5.13",
"description": "A feature-rich client for Matrix.org",
"author": "New Vector Ltd.",
"dependencies": {

View File

@ -40,6 +40,11 @@ const template = [
{ role: 'zoomin', accelerator: 'CommandOrControl+=' },
{ role: 'zoomout' },
{ type: 'separator' },
{
label: 'Preferences',
accelerator: 'Command+,', // Mac-only accelerator
click() { global.mainWindow.webContents.send('preferences'); },
},
{ role: 'togglefullscreen' },
{ role: 'toggledevtools' },
],

View File

@ -500,9 +500,9 @@ minimist@0.0.8:
integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
minimist@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
version "1.2.2"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.2.tgz#b00a00230a1108c48c169e69a291aafda3aacd63"
integrity sha512-rIqbOrKb8GJmx/5bc2M0QchhUouMXSpd1RTclXsB41JdL+VtnojfaJR+h7F9k18/4kHUsBFgk80Uk+q569vjPA==
mkdirp@0.5.1, mkdirp@^0.5.1:
version "0.5.1"

View File

@ -2,7 +2,7 @@
"name": "riot-web",
"productName": "Riot",
"main": "electron_app/src/electron-main.js",
"version": "1.5.12",
"version": "1.5.13",
"description": "A feature-rich client for Matrix.org",
"author": "New Vector Ltd.",
"repository": {
@ -37,11 +37,13 @@
"reskindex:watch-react": "node scripts/yarn-sub.js matrix-react-sdk reskindex:watch",
"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:res": "node scripts/copy-res.js",
"build:genfiles": "yarn reskindex && yarn build:res",
"build:modernizr": "modernizr -c .modernizr.json -d src/vector/modernizr.js",
"build:compile": "babel -d lib --verbose --extensions \".ts,.js,.tsx\" src",
"build:bundle": "cross-env NODE_ENV=production webpack -p --progress --bail --mode production",
"build:bundle-stats": "cross-env NODE_ENV=production webpack -p --progress --bail --mode production --json > webpack-stats.json",
"build:electron": "yarn build && yarn install:electron && electron-builder -wml --ia32 --x64",
"build:electron:linux": "yarn build && electron-builder -l --x64",
"build:electron:macos": "yarn build && electron-builder -m --x64",
@ -63,7 +65,6 @@
"dependencies": {
"browser-request": "^0.3.3",
"favico.js": "^0.3.10",
"gemini-scrollbar": "github:matrix-org/gemini-scrollbar#91e1e566",
"gfm.css": "^1.1.2",
"highlight.js": "^9.13.1",
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop",
@ -153,7 +154,7 @@
},
"build": {
"appId": "im.riot.app",
"electronVersion": "7.1.12",
"electronVersion": "7.1.14",
"files": [
"node_modules/**",
"src/**"

View File

@ -11,7 +11,7 @@ DIST_VERSION=$TAG
# a few SHAs rather than a version.
# Docker Hub doesn't always check out the tag and sometimes checks out the branch, so we should look
# for an appropriately tagged branch as well (heads/v1.2.3).
if [[ $BRANCH != 'HEAD' && $BRANCH != 'heads/v*' ]]
if [[ $BRANCH != HEAD && ! $BRANCH =~ heads/v.+ ]]
then
REACT_SHA=$(cd node_modules/matrix-react-sdk; git rev-parse --short=12 HEAD)
JSSDK_SHA=$(cd node_modules/matrix-js-sdk; git rev-parse --short=12 HEAD)

View File

@ -133,9 +133,9 @@ def on_receive_buildkite_poke():
for artifact in artifacts_array:
if re.match(r"dist/.*.tar.gz", artifact['path']):
artifact_to_deploy = artifact
if artifact_to_deploy is None:
print("No suitable artifacts found")
return jsonify({})
if artifact_to_deploy is None:
print("No suitable artifacts found")
return jsonify({})
# double paranoia check: make sure the artifact is on the right org too
if required_api_prefix is not None and not artifact_to_deploy['url'].startswith(required_api_prefix):

View File

@ -21,5 +21,7 @@
"Your Riot is misconfigured": "Riot не е конфигуриран правилно",
"Your Riot configuration contains invalid JSON. Please correct the problem and reload the page.": "Riot конфигурацията ви съдържа невалиден JSON. Коригирайте проблема и презаредете страницата.",
"The message from the parser is: %(message)s": "Грешката от парсъра е: %(message)s",
"Invalid JSON": "Невалиден JSON"
"Invalid JSON": "Невалиден JSON",
"Open user settings": "Отвори потребителските настройки",
"Go to your browser to complete Sign In": "Отидете в браузъра за да завършите влизането"
}

View File

@ -21,5 +21,6 @@
"Need help?": "Angen cymorth?",
"Chat with Riot Bot": "Sgwrsio gyda Riot Bot",
"Explore rooms": "Archwilio Ystafelloedd",
"Room Directory": "Cyfeiriadur Ystafelloedd"
"Room Directory": "Cyfeiriadur Ystafelloedd",
"Go to your browser to complete Sign In": "Ewch i'ch porwr i gwblhau Mewngofnodi"
}

View File

@ -22,5 +22,6 @@
"Your Riot configuration contains invalid JSON. Please correct the problem and reload the page.": "Deine Riot Konfiguration enthält ungültiges JSON. Bitte korrigiere das Problem und lade die Seite neu.",
"The message from the parser is: %(message)s": "Die Nachricht des Parsers ist: %(message)s",
"Invalid JSON": "Ungültiges JSON",
"Go to your browser to complete Sign In": "Gehe zu deinem Browser, um die Anmeldung abzuschließen"
"Go to your browser to complete Sign In": "Gehe zu deinem Browser, um die Anmeldung abzuschließen",
"Open user settings": "Öffne Nutzer-Einstellungen"
}

View File

@ -6,6 +6,7 @@
"Unexpected error preparing the app. See console for details.": "Unexpected error preparing the app. See console for details.",
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.",
"Invalid configuration: no default server specified.": "Invalid configuration: no default server specified.",
"Open user settings": "Open user settings",
"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",

View File

@ -22,5 +22,6 @@
"Your Riot configuration contains invalid JSON. Please correct the problem and reload the page.": "Zure Riot konfigurazioak baliogabeko JSON kodea du. Zuzendu arazoa eta kargatu orria berriro.",
"The message from the parser is: %(message)s": "Prozesatzailearen mezua hau da: %(message)s",
"Invalid JSON": "JSON baliogabea",
"Go to your browser to complete Sign In": "Joan zure nabigatzailera izena ematen bukatzeko"
"Go to your browser to complete Sign In": "Joan zure nabigatzailera izena ematen bukatzeko",
"Open user settings": "Ireki erabiltzailearen ezarpenak"
}

View File

@ -22,5 +22,6 @@
"Your Riot configuration contains invalid JSON. Please correct the problem and reload the page.": "Votre configuration de Riot contient du JSON non valide. Corrigez ce problème et rechargez la page.",
"The message from the parser is: %(message)s": "Le message de lanalyseur est : %(message)s",
"Invalid JSON": "JSON non valide",
"Go to your browser to complete Sign In": "Utilisez votre navigateur pour terminer la connexion"
"Go to your browser to complete Sign In": "Utilisez votre navigateur pour terminer la connexion",
"Open user settings": "Ouvrir les paramètres utilisateur"
}

22
src/i18n/strings/oc.json Normal file
View File

@ -0,0 +1,22 @@
{
"Your Riot configuration contains invalid JSON. Please correct the problem and reload the page.": "Vòstra configuracion Riot conten de JSON invalid. Mercés de corregir lo problèma e dactualizar la pagina.",
"The message from the parser is: %(message)s": "Lo messatge de lanalisaire es: %(message)s",
"Invalid JSON": "Invalid JSON",
"Your Riot is misconfigured": "Vòstre Riot es mal configurat",
"Unexpected error preparing the app. See console for details.": "Error inesperada en preparant laplicacion. Vejatz la consòla pels detalhs.",
"Riot Desktop on %(platformName)s": "Riot Desktop sus %(platformName)s",
"Go to your browser to complete Sign In": "Anatz al navegador per acabar la connexion",
"Unknown device": "Periferic desconegut",
"%(appName)s via %(browserName)s on %(osName)s": "%(appName)s via %(browserName)s sus %(osName)s",
"powered by Matrix": "propulsat per Matrix",
"Custom Server Options": "Opcions de servidor personalizat",
"Dismiss": "Refusar",
"Welcome to Riot.im": "La benvenguda a Riot.im",
"Decentralised, encrypted chat &amp; collaboration powered by [matrix]": "Messatjariá chifrada, descentralizada e collaborativa propulsada per [matrix]",
"Sign In": "Se connectar",
"Create Account": "Crear un compte",
"Need help?": "Besonh dajuda?",
"Chat with Riot Bot": "Charrar amb lo robòt Riot",
"Explore rooms": "Percórrer las salas",
"Room Directory": "Annuari de las sala"
}

View File

@ -1,25 +1,26 @@
{
"Custom Server Options": "Opções para Servidor Personalizado",
"Custom Server Options": "Opções do Servidor Personalizado",
"Dismiss": "Descartar",
"powered by Matrix": "rodando a partir do Matrix",
"powered by Matrix": "powered by Matrix",
"%(appName)s via %(browserName)s on %(osName)s": "%(appName)s via %(browserName)s em %(osName)s",
"Riot Desktop on %(platformName)s": "Riot para computadores desktop em %(platformName)s",
"Riot Desktop on %(platformName)s": "Riot Desktop em %(platformName)s",
"Unknown device": "Dispositivo desconhecido",
"You need to be using HTTPS to place a screen-sharing call.": "Necessita de estar a usar HTTPS para poder iniciar uma chamada com partilha de ecrã.",
"Welcome to Riot.im": "Bem-vindo ao Riot.im",
"Decentralised, encrypted chat &amp; collaboration powered by [matrix]": "Chat descentralizado, encriptado &amp; colaborativo alimentado por [matrix]",
"Decentralised, encrypted chat &amp; collaboration powered by [matrix]": "Chat descentralizado, encriptado &amp; colaborativo powered by [matrix]",
"Chat with Riot Bot": "Falar com o Bot do Riot",
"Your Riot configuration contains invalid JSON. Please correct the problem and reload the page.": "A sua configuração do RIOT contém JSON inválido. Por favor corriga o erro e recarregue a página.",
"The message from the parser is: %(message)s": "A mensagem do analisador é: %(message)s",
"Your Riot configuration contains invalid JSON. Please correct the problem and reload the page.": "A sua configuração do Riot contém JSON inválido. Por favor corrija o erro e recarregue a página.",
"The message from the parser is: %(message)s": "A mensagem do parser é: %(message)s",
"Invalid JSON": "JSON inválido",
"Your Riot is misconfigured": "A sua configuração do RIOT está incorrecta.",
"Your Riot is misconfigured": "Existe um erro na configuração do Riot",
"Unexpected error preparing the app. See console for details.": "Erro inesperado na preparação da aplicação. Veja a consola para mais detalhes.",
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Configuração inválida: só pode especificar uma das default_server_config, default_server_name,\nor default_hs_url.",
"Invalid configuration: no default server specified.": "Configuração inválida: não existe especificação de servidor padrão.",
"You can use the custom server options to sign into other Matrix servers by specifying a different homeserver URL. This allows you to use Riot with an existing Matrix account on a different homeserver.": "Pode usar as opções de custom server, para iniciar sessão noutros servidores Matrix.org, especificando o URL do homeserver diferente. Isto autoriza-lo-á a usar RIOT com a sua conta Matrix num servidor diferente",
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Configuração inválida: só pode especificar uma das default_server_config, default_server_name, ou default_hs_url.",
"Invalid configuration: no default server specified.": "Configuração inválida: servidor padrão não especificado.",
"You can use the custom server options to sign into other Matrix servers by specifying a different homeserver URL. This allows you to use Riot with an existing Matrix account on a different homeserver.": "Pode usar as opções de servidor personalizado, para iniciar sessão noutros servidores Matrix, especificando o URL do homeserver diferente. Isto autoriza-lo-á a usar Riot com a sua conta Matrix num servidor diferente.",
"Sign In": "Iniciar sessão",
"Create Account": "Criar conta",
"Need help?": "Ajuda?",
"Explore rooms": "Explorar rooms",
"Room Directory": "Diretório de rooms"
"Room Directory": "Diretório de rooms",
"Go to your browser to complete Sign In": "Abra o seu navegador para completar o inicio de sessão"
}

View File

@ -22,5 +22,6 @@
"Your Riot configuration contains invalid JSON. Please correct the problem and reload the page.": "Formësimi juaj i Riot-it përmban JSON. Ju lutemi, ndreqeni problemin dhe ringarkoni faqen.",
"The message from the parser is: %(message)s": "Mesazhi prej procesit është: %(message)s",
"Invalid JSON": "JSON i pavlefshëm",
"Go to your browser to complete Sign In": "Që të plotësoni Hyrjen, kaloni te shfletuesi juaj"
"Go to your browser to complete Sign In": "Që të plotësoni Hyrjen, kaloni te shfletuesi juaj",
"Open user settings": "Hapni rregullime përdoruesi"
}

View File

@ -21,5 +21,6 @@
"Unexpected error preparing the app. See console for details.": "Uygulamayı hazırlarken beklenmeyen hata oluştu. Lütfen detaylar için konsola bakınız.",
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Geçersiz yapılandırma: default_server_config, default_server_name, yada default_hs_url den sadece birisi seçilebilir.",
"Invalid configuration: no default server specified.": "Geçersiz yapılandırma: varsayılan sunucu seçilmemiş.",
"The message from the parser is: %(message)s": "Ayrıştırıcıdan gelen mesaj: %(message)s"
"The message from the parser is: %(message)s": "Ayrıştırıcıdan gelen mesaj: %(message)s",
"Go to your browser to complete Sign In": "Oturum açmayı tamamlamak için tarayıcınıza gidin"
}

View File

@ -22,5 +22,6 @@
"Your Riot configuration contains invalid JSON. Please correct the problem and reload the page.": "您的 Riot 包含無效的 JSON。請修正問題並重新整理頁面。",
"The message from the parser is: %(message)s": "從解析器而來的訊息為:%(message)s",
"Invalid JSON": "無效的 JSON",
"Go to your browser to complete Sign In": "到您的瀏覽器完成登入"
"Go to your browser to complete Sign In": "到您的瀏覽器完成登入",
"Open user settings": "開啟使用者設定"
}

View File

@ -39,9 +39,6 @@ import url from 'url';
import {parseQs, parseQsFromFragment} from './url_utils';
import ElectronPlatform from './platform/ElectronPlatform';
import WebPlatform from './platform/WebPlatform';
import {MatrixClientPeg} from 'matrix-react-sdk/src/MatrixClientPeg';
import SettingsStore from "matrix-react-sdk/src/settings/SettingsStore";
import SdkConfig from "matrix-react-sdk/src/SdkConfig";
@ -50,6 +47,7 @@ import {setTheme} from "matrix-react-sdk/src/theme";
import Olm from 'olm';
import CallHandler from 'matrix-react-sdk/src/CallHandler';
import {loadConfig, preparePlatform} from "./initial-load";
let lastLocationHashSet = null;
@ -191,35 +189,11 @@ export async function loadApp() {
await loadOlm();
// set the platform for react sdk
if (window.ipcRenderer) {
console.log("Using Electron platform");
const plaf = new ElectronPlatform();
PlatformPeg.set(plaf);
} else {
console.log("Using Web platform");
PlatformPeg.set(new WebPlatform());
}
preparePlatform();
const platform = PlatformPeg.get();
let configJson;
let configError;
let configSyntaxError = false;
try {
configJson = await platform.getConfig();
} catch (e) {
configError = e;
if (e && e.err && e.err instanceof SyntaxError) {
console.error("SyntaxError loading config:", e);
configSyntaxError = true;
configJson = {}; // to prevent errors between here and loading CSS for the error box
}
}
// XXX: We call this twice, once here and once in MatrixChat as a prop. We call it here to ensure
// granular settings are loaded correctly and to avoid duplicating the override logic for the theme.
SdkConfig.put(configJson);
// Load the config from the platform
const configInfo = await loadConfig();
// Load language after loading config.json so that settingsDefaults.language can be applied
await loadLanguage();
@ -248,7 +222,7 @@ export async function loadApp() {
await setTheme();
// Now that we've loaded the theme (CSS), display the config syntax error if needed.
if (configSyntaxError) {
if (configInfo.configSyntaxError) {
const errorMessage = (
<div>
<p>
@ -260,7 +234,7 @@ export async function loadApp() {
<p>
{_t(
"The message from the parser is: %(message)s",
{message: configError.err.message || _t("Invalid JSON")},
{message: configInfo.configError.err.message || _t("Invalid JSON")},
)}
</p>
</div>
@ -280,7 +254,7 @@ export async function loadApp() {
const urlWithoutQuery = window.location.protocol + '//' + window.location.host + window.location.pathname;
console.log("Vector starting at " + urlWithoutQuery);
if (configError) {
if (configInfo.configError) {
window.matrixChat = ReactDOM.render(<div className="error">
Unable to load config file: please refresh the page to try again.
</div>, document.getElementById('matrixchat'));
@ -298,7 +272,7 @@ export async function loadApp() {
config={newConfig}
realQueryParams={params}
startingFragmentQueryParams={fragparts.params}
enableGuest={!configJson.disable_guests}
enableGuest={!SdkConfig.get().disable_guests}
onTokenLoginCompleted={onTokenLoginCompleted}
initialScreenAfterLogin={getScreenFromLocation(window.location)}
defaultDeviceDisplayName={platform.getDefaultDeviceDisplayName()}

View File

@ -21,7 +21,6 @@ limitations under the License.
// Require common CSS here; this will make webpack process it into bundle.css.
// Our own CSS (which is themed) is imported via separate webpack entry points
// in webpack.config.js
require('gemini-scrollbar/gemini-scrollbar.css');
require('gfm.css/gfm.css');
require('highlight.js/styles/github.css');

View File

@ -0,0 +1,58 @@
/*
Copyright 2020 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 ElectronPlatform from './platform/ElectronPlatform';
import WebPlatform from './platform/WebPlatform';
import PlatformPeg from 'matrix-react-sdk/src/PlatformPeg';
import SdkConfig from "matrix-react-sdk/src/SdkConfig";
export function preparePlatform() {
if ((<any>window).ipcRenderer) {
console.log("Using Electron platform");
const plaf = new ElectronPlatform();
PlatformPeg.set(plaf);
} else {
console.log("Using Web platform");
PlatformPeg.set(new WebPlatform());
}
}
export async function loadConfig(): Promise<{configError?: Error, configSyntaxError: boolean}> {
const platform = PlatformPeg.get();
let configJson;
let configError;
let configSyntaxError = false;
try {
configJson = await platform.getConfig();
} catch (e) {
configError = e;
if (e && e.err && e.err instanceof SyntaxError) {
console.error("SyntaxError loading config:", e);
configSyntaxError = true;
configJson = {}; // to prevent errors between here and loading CSS for the error box
}
}
// XXX: We call this twice, once here and once in MatrixChat as a prop. We call it here to ensure
// granular settings are loaded correctly and to avoid duplicating the override logic for the theme.
//
// Note: this isn't called twice for some wrappers, like the Jitsi wrapper.
SdkConfig.put(configJson);
return {configError, configSyntaxError};
}

View File

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Jitsi Widget</title>
</head>
<body>
<div id="jitsiContainer"><!-- the js will put the conference here --></div>
<div id="joinButtonContainer">
<div class="joinConferenceFloating">
<div class="joinConferencePrompt">
<!-- TODO: i18n -->
<h2>Jitsi Video Conference</h2>
<button type="button" id="joinButton">Join Conference</button>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,75 @@
/*
Copyright 2020 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.
*/
// TODO: Match the user's theme: https://github.com/vector-im/riot-web/issues/12794
@font-face {
font-family: 'Nunito';
font-style: normal;
font-weight: 400;
src: url('~matrix-react-sdk/res/fonts/Nunito/Nunito-Regular.ttf') format('truetype');
}
body {
font-family: Nunito, Arial, Helvetica, sans-serif;
background-color: #181b21;
color: #edf3ff;
}
body, html {
padding: 0;
margin: 0;
}
#jitsiContainer {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
#joinButtonContainer {
display: table;
position: absolute;
height: 100%;
width: 100%;
}
.joinConferenceFloating {
display: table-cell;
vertical-align: middle;
}
.joinConferencePrompt {
margin-left: auto;
margin-right: auto;
width: 90%;
text-align: center;
}
#joinButton {
// A mix of AccessibleButton styles
cursor: pointer;
padding: 7px 18px;
text-align: center;
border-radius: 4px;
display: inline-block;
font-size: 14px;
color: #ffffff;
background-color: #03b381;
border: 0;
}

123
src/vector/jitsi/index.ts Normal file
View File

@ -0,0 +1,123 @@
/*
Copyright 2020 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.
*/
// We have to trick webpack into loading our CSS for us.
require("./index.scss");
import * as qs from 'querystring';
import { Capability, WidgetApi } from "matrix-react-sdk/src/widgets/WidgetApi";
// Dev note: we use raw JS without many dependencies to reduce bundle size.
// We do not need all of React to render a Jitsi conference.
declare var JitsiMeetExternalAPI: any;
let inConference = false;
// Jitsi params
let jitsiDomain: string;
let conferenceId: string;
let displayName: string;
let avatarUrl: string;
let userId: string;
let widgetApi: WidgetApi;
(async function () {
try {
// The widget's options are encoded into the fragment to avoid leaking info to the server. The widget
// spec on the other hand requires the widgetId and parentUrl to show up in the regular query string.
const widgetQuery = qs.parse(window.location.hash.substring(1));
const query = Object.assign({}, qs.parse(window.location.search.substring(1)), widgetQuery);
const qsParam = (name: string, optional = false): string => {
if (!optional && (!query[name] || typeof (query[name]) !== 'string')) {
throw new Error(`Expected singular ${name} in query string`);
}
return <string>query[name];
};
// Set this up as early as possible because Riot will be hitting it almost immediately.
widgetApi = new WidgetApi(qsParam('parentUrl'), qsParam('widgetId'), [
Capability.AlwaysOnScreen,
Capability.GetRiotWebConfig,
]);
widgetApi.expectingExplicitReady = true;
// Populate the Jitsi params now
jitsiDomain = qsParam('conferenceDomain');
conferenceId = qsParam('conferenceId');
displayName = qsParam('displayName', true);
avatarUrl = qsParam('avatarUrl', true); // http not mxc
userId = qsParam('userId');
await widgetApi.waitReady();
await widgetApi.setAlwaysOnScreen(false); // start off as detachable from the screen
const riotConfig = await widgetApi.getRiotConfig();
// Get the Jitsi Meet API loaded up as fast as possible, but ensure that the widget's postMessage
// receiver (WidgetApi) is up and running first.
const scriptTag = document.createElement("script");
scriptTag.src = riotConfig['jitsi']['externalApiUrl'];
document.body.appendChild(scriptTag);
// TODO: register widgetApi listeners for PTT controls (https://github.com/vector-im/riot-web/issues/12795)
document.getElementById("joinButton").onclick = () => joinConference();
} catch (e) {
console.error("Error setting up Jitsi widget", e);
document.getElementById("jitsiContainer").innerText = "Failed to load Jitsi widget";
switchVisibleContainers();
}
})();
function switchVisibleContainers() {
inConference = !inConference;
document.getElementById("jitsiContainer").style.visibility = inConference ? 'unset' : 'hidden';
document.getElementById("joinButtonContainer").style.visibility = inConference ? 'hidden' : 'unset';
}
function joinConference() { // event handler bound in HTML
switchVisibleContainers();
// noinspection JSIgnoredPromiseFromCall
widgetApi.setAlwaysOnScreen(true); // ignored promise because we don't care if it works
const meetApi = new JitsiMeetExternalAPI(jitsiDomain, {
width: "100%",
height: "100%",
parentNode: document.querySelector("#jitsiContainer"),
roomName: conferenceId,
interfaceConfigOverwrite: {
SHOW_JITSI_WATERMARK: false,
SHOW_WATERMARK_FOR_GUESTS: false,
MAIN_TOOLBAR_BUTTONS: [],
VIDEO_LAYOUT_FIT: "height",
},
});
if (displayName) meetApi.executeCommand("displayName", displayName);
if (avatarUrl) meetApi.executeCommand("avatarUrl", avatarUrl);
if (userId) meetApi.executeCommand("email", userId);
meetApi.on("readyToClose", () => {
switchVisibleContainers();
// noinspection JSIgnoredPromiseFromCall
widgetApi.setAlwaysOnScreen(false); // ignored promise because we don't care if it works
document.getElementById("jitsiContainer").innerHTML = "";
});
}

File diff suppressed because one or more lines are too long

View File

@ -23,15 +23,29 @@ limitations under the License.
import VectorBasePlatform, {updateCheckStatusEnum} from './VectorBasePlatform';
import BaseEventIndexManager from 'matrix-react-sdk/src/indexing/BaseEventIndexManager';
import dis from 'matrix-react-sdk/src/dispatcher';
import { _t } from 'matrix-react-sdk/src/languageHandler';
import { _t, _td } from 'matrix-react-sdk/src/languageHandler';
import * as rageshake from 'matrix-react-sdk/src/rageshake/rageshake';
import {MatrixClient} from "matrix-js-sdk";
import Modal from "matrix-react-sdk/src/Modal";
import InfoDialog from "matrix-react-sdk/src/components/views/dialogs/InfoDialog";
import Spinner from "matrix-react-sdk/src/components/views/elements/Spinner";
import {Categories, Modifiers, registerShortcut} from "matrix-react-sdk/src/accessibility/KeyboardShortcuts";
import {Key} from "matrix-react-sdk/src/Keyboard";
import React from "react";
const ipcRenderer = window.ipcRenderer;
const isMac = navigator.platform.toUpperCase().includes('MAC');
// register Mac specific shortcuts
if (isMac) {
registerShortcut(Categories.NAVIGATION, {
keybinds: [{
modifiers: [Modifiers.COMMAND],
key: Key.COMMA,
}],
description: _td("Open user settings"),
});
}
function platformFriendlyName(): string {
// used to use window.process but the same info is available here
@ -122,6 +136,10 @@ class SeshatIndexManager extends BaseEventIndexManager {
return this._ipcCall('addEventToIndex', ev, profile);
}
async deleteEvent(eventId: string): Promise<boolean> {
return this._ipcCall('deleteEvent', eventId);
}
async isEventIndexEmpty(): Promise<boolean> {
return this._ipcCall('isEventIndexEmpty');
}
@ -204,6 +222,10 @@ export default class ElectronPlatform extends VectorBasePlatform {
ipcRenderer.on('ipcReply', this._onIpcReply.bind(this));
ipcRenderer.on('update-downloaded', this.onUpdateDownloaded.bind(this));
ipcRenderer.on('preferences', () => {
dis.dispatch({ action: 'view_user_settings' });
});
this.startUpdateCheck = this.startUpdateCheck.bind(this);
this.stopUpdateCheck = this.stopUpdateCheck.bind(this);
}
@ -297,7 +319,7 @@ export default class ElectronPlatform extends VectorBasePlatform {
supportsAutoHideMenuBar(): boolean {
// This is irelevant on Mac as Menu bars don't live in the app window
return !navigator.platform.toUpperCase().includes('MAC');
return !isMac;
}
async getAutoHideMenuBarEnabled(): boolean {
@ -310,7 +332,7 @@ export default class ElectronPlatform extends VectorBasePlatform {
supportsMinimizeToTray(): boolean {
// Things other than Mac support tray icons
return !navigator.platform.toUpperCase().includes('MAC');
return !isMac;
}
async getMinimizeToTrayEnabled(): boolean {

View File

@ -34,6 +34,7 @@ module.exports = (env, argv) => {
"bundle": "./src/vector/index.js",
"indexeddb-worker": "./src/vector/indexeddb-worker.js",
"mobileguide": "./src/vector/mobile_guide/index.js",
"jitsi": "./src/vector/jitsi/index.ts",
"usercontent": "./node_modules/matrix-react-sdk/src/usercontent/index.js",
// CSS themes
@ -92,6 +93,9 @@ module.exports = (env, argv) => {
// same goes for js-sdk - we don't need two copies.
"matrix-js-sdk": path.resolve(__dirname, 'node_modules/matrix-js-sdk'),
// and prop-types and sanitize-html
"prop-types": path.resolve(__dirname, 'node_modules/prop-types'),
"sanitize-html": path.resolve(__dirname, 'node_modules/sanitize-html'),
// Define a variable so the i18n stuff can load
"$webapp": path.resolve(__dirname, 'webapp'),
@ -303,13 +307,21 @@ module.exports = (env, argv) => {
// HtmlWebpackPlugin will screw up our formatting like the names
// of the themes and which chunks we actually care about.
inject: false,
excludeChunks: ['mobileguide', 'usercontent'],
excludeChunks: ['mobileguide', 'usercontent', 'jitsi'],
minify: argv.mode === 'production',
vars: {
og_image_url: og_image_url,
},
}),
// This is the jitsi widget wrapper (embedded, so isolated stack)
new HtmlWebpackPlugin({
template: './src/vector/jitsi/index.html',
filename: 'jitsi.html',
minify: argv.mode === 'production',
chunks: ['jitsi'],
}),
// This is the mobile guide's entry point (separate for faster mobile loading)
new HtmlWebpackPlugin({
template: './src/vector/mobile_guide/index.html',

View File

@ -5031,10 +5031,6 @@ gauge@~2.7.3:
strip-ansi "^3.0.1"
wide-align "^1.1.0"
"gemini-scrollbar@github:matrix-org/gemini-scrollbar#91e1e566", gemini-scrollbar@matrix-org/gemini-scrollbar#91e1e566:
version "1.4.3"
resolved "https://codeload.github.com/matrix-org/gemini-scrollbar/tar.gz/91e1e566fa33324188f278801baf4a79f9f554ab"
gensync@^1.0.0-beta.1:
version "1.0.0-beta.1"
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269"
@ -7455,8 +7451,8 @@ mathml-tag-names@^2.1.1:
integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==
"matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop":
version "5.1.0"
resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/86304fd037ac43a493000fa42f393eaafc0480ac"
version "5.1.1"
resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/b2e154377a4268441a3b27b183dd7f7018187035"
dependencies:
"@babel/runtime" "^7.8.3"
another-json "^0.2.0"
@ -7477,8 +7473,8 @@ matrix-mock-request@^1.2.3:
expect "^1.20.2"
"matrix-react-sdk@github:matrix-org/matrix-react-sdk#develop":
version "2.2.1"
resolved "https://codeload.github.com/matrix-org/matrix-react-sdk/tar.gz/53fabf61d6647dfedf62352f6aa35ac55fa49203"
version "2.2.3"
resolved "https://codeload.github.com/matrix-org/matrix-react-sdk/tar.gz/b09c063d1b2cae9e26b336de0b0ed69f3d6afcc8"
dependencies:
"@babel/runtime" "^7.8.3"
blueimp-canvas-to-blob "^3.5.0"
@ -7498,7 +7494,6 @@ matrix-mock-request@^1.2.3:
flux "2.1.1"
focus-visible "^5.0.2"
fuse.js "^2.2.0"
gemini-scrollbar "github:matrix-org/gemini-scrollbar#91e1e566"
gfm.css "^1.1.1"
glob-to-regexp "^0.4.1"
highlight.js "^9.15.8"
@ -7519,7 +7514,6 @@ matrix-mock-request@^1.2.3:
react-beautiful-dnd "^4.0.1"
react-dom "^16.9.0"
react-focus-lock "^2.2.1"
react-gemini-scrollbar "github:matrix-org/react-gemini-scrollbar#9cf17f63b7c0b0ec5f31df27da0f82f7238dc594"
resize-observer-polyfill "^1.5.0"
sanitize-html "^1.18.4"
text-encoding-utf-8 "^1.0.1"
@ -9903,12 +9897,6 @@ react-focus-lock@^2.2.1:
use-callback-ref "^1.2.1"
use-sidecar "^1.0.1"
"react-gemini-scrollbar@github:matrix-org/react-gemini-scrollbar#9cf17f63b7c0b0ec5f31df27da0f82f7238dc594":
version "2.1.5"
resolved "https://codeload.github.com/matrix-org/react-gemini-scrollbar/tar.gz/9cf17f63b7c0b0ec5f31df27da0f82f7238dc594"
dependencies:
gemini-scrollbar matrix-org/gemini-scrollbar#91e1e566
react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4:
version "16.13.0"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.0.tgz#0f37c3613c34fe6b37cd7f763a0d6293ab15c527"