diff --git a/.gitignore b/.gitignore index c1a042341a..4dd3a26213 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ electron/pub /config.local*.json /src/component-index.js /.tmp +/webpack-stats.json diff --git a/.modernizr.json b/.modernizr.json index 764a320b26..9b3990345d 100644 --- a/.modernizr.json +++ b/.modernizr.json @@ -25,6 +25,9 @@ "test/svg/asimg", "test/svg/filters", + "test/url/parser", + "test/url/urlsearchparams", + "test/cors", "test/iframe/sandbox", "test/json", diff --git a/CHANGELOG.md b/CHANGELOG.md index 49d43a93d7..1e34705284 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) diff --git a/config.sample.json b/config.sample.json index 69dc396884..b8dc2fbb4c 100644 --- a/config.sample.json +++ b/config.sample.json @@ -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" } } diff --git a/docs/config.md b/docs/config.md index d11d8638cd..40e71361bb 100644 --- a/docs/config.md +++ b/docs/config.md @@ -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 diff --git a/docs/shortcuts.md b/docs/shortcuts.md deleted file mode 100644 index bc741e153a..0000000000 --- a/docs/shortcuts.md +++ /dev/null @@ -1,15 +0,0 @@ -# Keyboard Shortcuts - -The modifier is Ctrl on Windows & Linux and on Mac. - -- Ctrl/+m - toggle markdown -- Ctrl/+d - toggle mic mute -- Ctrl/+e - toggle video on/off -- Ctrl/+k - jump to named room -- / - navigate old messages to edit when the composer is in focus -- / - next/prev room when focus in room list -- Alt+/ - resend previous messages when the composer is in focus -- PageUp/PageDown - scroll timeline up/down -- Ctrl/+Home/End - jump to - start/end of the composer when focused, otherwise jump to timeline start/end -- Ctrl/+` - toggle the top left menu diff --git a/electron_app/package.json b/electron_app/package.json index 418375e80c..284a308254 100644 --- a/electron_app/package.json +++ b/electron_app/package.json @@ -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": { diff --git a/electron_app/src/vectormenu.js b/electron_app/src/vectormenu.js index a8f998befc..b6e00d509d 100644 --- a/electron_app/src/vectormenu.js +++ b/electron_app/src/vectormenu.js @@ -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' }, ], diff --git a/electron_app/yarn.lock b/electron_app/yarn.lock index 4723d3e828..d61172bc1c 100644 --- a/electron_app/yarn.lock +++ b/electron_app/yarn.lock @@ -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" diff --git a/package.json b/package.json index 02a3a9d4e8..50f6808e6d 100644 --- a/package.json +++ b/package.json @@ -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/**" diff --git a/scripts/docker-write-version.sh b/scripts/docker-write-version.sh index 14368fd461..87014b4ff1 100644 --- a/scripts/docker-write-version.sh +++ b/scripts/docker-write-version.sh @@ -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) diff --git a/scripts/redeploy.py b/scripts/redeploy.py index 6e9d29c382..064bbfaa29 100755 --- a/scripts/redeploy.py +++ b/scripts/redeploy.py @@ -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): diff --git a/src/i18n/strings/bg.json b/src/i18n/strings/bg.json index 747c4cbe59..9232d0abb7 100644 --- a/src/i18n/strings/bg.json +++ b/src/i18n/strings/bg.json @@ -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": "Отидете в браузъра за да завършите влизането" } diff --git a/src/i18n/strings/cy.json b/src/i18n/strings/cy.json index 8f031b3e2f..85986d02da 100644 --- a/src/i18n/strings/cy.json +++ b/src/i18n/strings/cy.json @@ -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" } diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 82bfe50a12..b501e70a4d 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -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" } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 36f19a75a6..b77de12273 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -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", diff --git a/src/i18n/strings/eu.json b/src/i18n/strings/eu.json index 77d84539c7..f8e204c34f 100644 --- a/src/i18n/strings/eu.json +++ b/src/i18n/strings/eu.json @@ -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" } diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index 2ec3a58e69..7deba39b82 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -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 l’analyseur 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" } diff --git a/src/i18n/strings/oc.json b/src/i18n/strings/oc.json new file mode 100644 index 0000000000..875bd575ca --- /dev/null +++ b/src/i18n/strings/oc.json @@ -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 d’actualizar la pagina.", + "The message from the parser is: %(message)s": "Lo messatge de l’analisaire 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 l’aplicacion. 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 & collaboration powered by [matrix]": "Messatjariá chifrada, descentralizada e collaborativa propulsada per [matrix]", + "Sign In": "Se connectar", + "Create Account": "Crear un compte", + "Need help?": "Besonh d’ajuda ?", + "Chat with Riot Bot": "Charrar amb lo robòt Riot", + "Explore rooms": "Percórrer las salas", + "Room Directory": "Annuari de las sala" +} diff --git a/src/i18n/strings/pt.json b/src/i18n/strings/pt.json index 2e987ad851..e7a5b028d9 100644 --- a/src/i18n/strings/pt.json +++ b/src/i18n/strings/pt.json @@ -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 & collaboration powered by [matrix]": "Chat descentralizado, encriptado & colaborativo alimentado por [matrix]", + "Decentralised, encrypted chat & collaboration powered by [matrix]": "Chat descentralizado, encriptado & 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" } diff --git a/src/i18n/strings/sq.json b/src/i18n/strings/sq.json index 18c8a9cdfd..b7c435a8ac 100644 --- a/src/i18n/strings/sq.json +++ b/src/i18n/strings/sq.json @@ -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" } diff --git a/src/i18n/strings/tr.json b/src/i18n/strings/tr.json index 339add2db6..07fa305a69 100644 --- a/src/i18n/strings/tr.json +++ b/src/i18n/strings/tr.json @@ -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" } diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index fcb5cf1659..eb2a6ba511 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -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": "開啟使用者設定" } diff --git a/src/vector/app.js b/src/vector/app.js index da46dffd76..6a1635dd50 100644 --- a/src/vector/app.js +++ b/src/vector/app.js @@ -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 = (

@@ -260,7 +234,7 @@ export async function loadApp() {

{_t( "The message from the parser is: %(message)s", - {message: configError.err.message || _t("Invalid JSON")}, + {message: configInfo.configError.err.message || _t("Invalid JSON")}, )}

@@ -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(
Unable to load config file: please refresh the page to try again.
, 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()} diff --git a/src/vector/index.js b/src/vector/index.js index 3f34f2c1dc..ff31d7b62c 100644 --- a/src/vector/index.js +++ b/src/vector/index.js @@ -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'); diff --git a/src/vector/initial-load.ts b/src/vector/initial-load.ts new file mode 100644 index 0000000000..7bd73c5a4d --- /dev/null +++ b/src/vector/initial-load.ts @@ -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 ((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}; +} diff --git a/src/vector/jitsi/index.html b/src/vector/jitsi/index.html new file mode 100644 index 0000000000..58184e0a5d --- /dev/null +++ b/src/vector/jitsi/index.html @@ -0,0 +1,19 @@ + + + + + Jitsi Widget + + +
+
+
+
+ +

Jitsi Video Conference

+ +
+
+
+ + diff --git a/src/vector/jitsi/index.scss b/src/vector/jitsi/index.scss new file mode 100644 index 0000000000..fc33c9d8d0 --- /dev/null +++ b/src/vector/jitsi/index.scss @@ -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; +} diff --git a/src/vector/jitsi/index.ts b/src/vector/jitsi/index.ts new file mode 100644 index 0000000000..75b017a269 --- /dev/null +++ b/src/vector/jitsi/index.ts @@ -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 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 = ""; + }); +} diff --git a/src/vector/modernizr.js b/src/vector/modernizr.js index 81e218dbc7..e4c09d4107 100644 --- a/src/vector/modernizr.js +++ b/src/vector/modernizr.js @@ -1,3 +1,3 @@ /*! modernizr 3.8.0 (Custom Build) | MIT * - * https://modernizr.com/download/?-cors-cssanimations-cssfilters-displaytable-es5date-es5function-es5object-es5undefined-es6array-es6collections-es6string-fetch-flexbox-json-localstorage-objectfit-promises-sandbox-svg-svgasimg-svgfilters-setclasses-cssclassprefix:modernizr_ !*/ -!function(e,t,n){function r(e,t){return typeof e===t}function o(e){var t=T.className,n=Modernizr._config.classPrefix||"";if(C&&(t=t.baseVal),Modernizr._config.enableJSClass){var r=new RegExp("(^|\\s)"+n+"no-js(\\s|$)");t=t.replace(r,"$1"+n+"js$2")}Modernizr._config.enableClasses&&(e.length>0&&(t+=" "+n+e.join(" "+n)),C?T.className.baseVal=t:T.className=t)}function i(e,t){return!!~(""+e).indexOf(t)}function s(){return"function"!=typeof t.createElement?t.createElement(arguments[0]):C?t.createElementNS.call(t,"http://www.w3.org/2000/svg",arguments[0]):t.createElement.apply(t,arguments)}function a(){var e=t.body;return e||(e=s(C?"svg":"body"),e.fake=!0),e}function l(e,n,r,o){var i,l,f,u,d="modernizr",p=s("div"),c=a();if(parseInt(r,10))for(;r--;)f=s("div"),f.id=o?o[r]:d+(r+1),p.appendChild(f);return i=s("style"),i.type="text/css",i.id="s"+d,(c.fake?c:p).appendChild(i),c.appendChild(p),i.styleSheet?i.styleSheet.cssText=e:i.appendChild(t.createTextNode(e)),p.id=d,c.fake&&(c.style.background="",c.style.overflow="hidden",u=T.style.overflow,T.style.overflow="hidden",T.appendChild(c)),l=n(p,e),c.fake?(c.parentNode.removeChild(c),T.style.overflow=u,T.offsetHeight):p.parentNode.removeChild(p),!!l}function f(e){return e.replace(/([A-Z])/g,function(e,t){return"-"+t.toLowerCase()}).replace(/^ms-/,"-ms-")}function u(t,n,r){var o;if("getComputedStyle"in e){o=getComputedStyle.call(e,t,n);var i=e.console;if(null!==o)r&&(o=o.getPropertyValue(r));else if(i){var s=i.error?"error":"log";i[s].call(i,"getComputedStyle returning null, its possible modernizr test results are inaccurate")}}else o=!n&&t.currentStyle&&t.currentStyle[r];return o}function d(t,r){var o=t.length;if("CSS"in e&&"supports"in e.CSS){for(;o--;)if(e.CSS.supports(f(t[o]),r))return!0;return!1}if("CSSSupportsRule"in e){for(var i=[];o--;)i.push("("+f(t[o])+":"+r+")");return i=i.join(" or "),l("@supports ("+i+") { #modernizr { position: absolute; } }",function(e){return"absolute"===u(e,null,"position")})}return n}function p(e){return e.replace(/([a-z])-([a-z])/g,function(e,t,n){return t+n.toUpperCase()}).replace(/^-/,"")}function c(e,t,o,a){function l(){u&&(delete j.style,delete j.modElem)}if(a=!r(a,"undefined")&&a,!r(o,"undefined")){var f=d(e,o);if(!r(f,"undefined"))return f}for(var u,c,y,m,g,v=["modernizr","tspan","samp"];!j.style&&v.length;)u=!0,j.modElem=s(v.shift()),j.style=j.modElem.style;for(y=e.length,c=0;c9)}),Modernizr.addTest("flexbox",v("flexBasis","1px",!0));var z=function(t){var r,o=E.length,i=e.CSSRule;if(void 0===i)return n;if(!t)return!1;if(t=t.replace(/^@/,""),(r=t.replace(/-/g,"_").toUpperCase()+"_RULE")in i)return"@"+t;for(var s=0;s0&&(t+=" "+n+e.join(" "+n)),C?T.className.baseVal=t:T.className=t)}function i(e,t){return!!~(""+e).indexOf(t)}function s(){return"function"!=typeof t.createElement?t.createElement(arguments[0]):C?t.createElementNS.call(t,"http://www.w3.org/2000/svg",arguments[0]):t.createElement.apply(t,arguments)}function a(){var e=t.body;return e||(e=s(C?"svg":"body"),e.fake=!0),e}function l(e,n,r,o){var i,l,f,u,d="modernizr",c=s("div"),p=a();if(parseInt(r,10))for(;r--;)f=s("div"),f.id=o?o[r]:d+(r+1),c.appendChild(f);return i=s("style"),i.type="text/css",i.id="s"+d,(p.fake?p:c).appendChild(i),p.appendChild(c),i.styleSheet?i.styleSheet.cssText=e:i.appendChild(t.createTextNode(e)),c.id=d,p.fake&&(p.style.background="",p.style.overflow="hidden",u=T.style.overflow,T.style.overflow="hidden",T.appendChild(p)),l=n(c,e),p.fake?(p.parentNode.removeChild(p),T.style.overflow=u,T.offsetHeight):c.parentNode.removeChild(c),!!l}function f(e){return e.replace(/([A-Z])/g,function(e,t){return"-"+t.toLowerCase()}).replace(/^ms-/,"-ms-")}function u(t,n,r){var o;if("getComputedStyle"in e){o=getComputedStyle.call(e,t,n);var i=e.console;if(null!==o)r&&(o=o.getPropertyValue(r));else if(i){var s=i.error?"error":"log";i[s].call(i,"getComputedStyle returning null, its possible modernizr test results are inaccurate")}}else o=!n&&t.currentStyle&&t.currentStyle[r];return o}function d(t,r){var o=t.length;if("CSS"in e&&"supports"in e.CSS){for(;o--;)if(e.CSS.supports(f(t[o]),r))return!0;return!1}if("CSSSupportsRule"in e){for(var i=[];o--;)i.push("("+f(t[o])+":"+r+")");return i=i.join(" or "),l("@supports ("+i+") { #modernizr { position: absolute; } }",function(e){return"absolute"===u(e,null,"position")})}return n}function c(e){return e.replace(/([a-z])-([a-z])/g,function(e,t,n){return t+n.toUpperCase()}).replace(/^-/,"")}function p(e,t,o,a){function l(){u&&(delete j.style,delete j.modElem)}if(a=!r(a,"undefined")&&a,!r(o,"undefined")){var f=d(e,o);if(!r(f,"undefined"))return f}for(var u,p,y,m,g,h=["modernizr","tspan","samp"];!j.style&&h.length;)u=!0,j.modElem=s(h.shift()),j.style=j.modElem.style;for(y=e.length,p=0;p9)}),Modernizr.addTest("flexbox",h("flexBasis","1px",!0));var N=function(t){var r,o=E.length,i=e.CSSRule;if(void 0===i)return n;if(!t)return!1;if(t=t.replace(/^@/,""),(r=t.replace(/-/g,"_").toUpperCase()+"_RULE")in i)return"@"+t;for(var s=0;s { + return this._ipcCall('deleteEvent', eventId); + } + async isEventIndexEmpty(): Promise { 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 { diff --git a/webpack.config.js b/webpack.config.js index fbee94766d..d62b6f0755 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -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', diff --git a/yarn.lock b/yarn.lock index ad7345b2a0..68423fc233 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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"