From 7d22bbc00f49356cd5fec3565a19376ef8b0ef05 Mon Sep 17 00:00:00 2001 From: Bryan Kok Date: Sat, 17 Oct 2020 23:52:18 +0800 Subject: [PATCH 001/479] Trim spurious whitespace of nicknames --- src/components/views/settings/ProfileSettings.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/views/settings/ProfileSettings.js b/src/components/views/settings/ProfileSettings.js index 92851ccaa0..294f80acd1 100644 --- a/src/components/views/settings/ProfileSettings.js +++ b/src/components/views/settings/ProfileSettings.js @@ -77,10 +77,12 @@ export default class ProfileSettings extends React.Component { const client = MatrixClientPeg.get(); const newState = {}; + const displayName = this.state.displayName.trim(); try { if (this.state.originalDisplayName !== this.state.displayName) { - await client.setDisplayName(this.state.displayName); - newState.originalDisplayName = this.state.displayName; + await client.setDisplayName(displayName); + newState.originalDisplayName = displayName; + newState.displayName = displayName; } if (this.state.avatarFile) { From fcbaea640daf3a036d55cb1bda5d7fed552c2d4e Mon Sep 17 00:00:00 2001 From: Bryan Kok Date: Sun, 18 Oct 2020 14:36:50 +0800 Subject: [PATCH 002/479] Trim room names changed through the UI --- src/components/views/room_settings/RoomProfileSettings.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/views/room_settings/RoomProfileSettings.js b/src/components/views/room_settings/RoomProfileSettings.js index ca09c3093a..b894663c16 100644 --- a/src/components/views/room_settings/RoomProfileSettings.js +++ b/src/components/views/room_settings/RoomProfileSettings.js @@ -95,10 +95,11 @@ export default class RoomProfileSettings extends React.Component { const newState = {}; // TODO: What do we do about errors? - + const displayName = this.state.displayName.trim(); if (this.state.originalDisplayName !== this.state.displayName) { - await client.setRoomName(this.props.roomId, this.state.displayName); - newState.originalDisplayName = this.state.displayName; + await client.setRoomName(this.props.roomId, displayName); + newState.originalDisplayName = displayName; + newState.displayName = displayName; } if (this.state.avatarFile) { From 2f988bc97fc1e414bd70149ac5f77301a3ef2833 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 26 Nov 2020 13:51:03 +0100 Subject: [PATCH 003/479] Added UI --- .../views/settings/SpellCheckSettings.tsx | 111 ++++++++++++++++++ .../tabs/user/GeneralUserSettingsTab.js | 18 +++ 2 files changed, 129 insertions(+) create mode 100644 src/components/views/settings/SpellCheckSettings.tsx diff --git a/src/components/views/settings/SpellCheckSettings.tsx b/src/components/views/settings/SpellCheckSettings.tsx new file mode 100644 index 0000000000..1bdcd882c9 --- /dev/null +++ b/src/components/views/settings/SpellCheckSettings.tsx @@ -0,0 +1,111 @@ +/* +Copyright 2019 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 React from 'react'; +import LanguageDropdown from "../../../components/views/elements/LanguageDropdown"; +import AccessibleButton from "../../../components/views/elements/AccessibleButton"; +import {_t} from "../../../languageHandler"; + +interface ExistingSpellCheckLanguageIProps { + language: string, + onRemoved(language: string), +}; + +interface SpellCheckLanguagesIProps { + languages: Array, + onLanguagesChange(languages: Array), +}; + +interface SpellCheckLanguagesIState { + newLanguage: string, +} + +export class ExistingSpellCheckLanguage extends React.Component { + _onRemove = (e) => { + e.stopPropagation(); + e.preventDefault(); + + return this.props.onRemoved(this.props.language); + }; + + render() { + return ( +
+ {this.props.language} + + {_t("Remove")} + +
+ ); + } +} + +export default class SpellCheckLanguages extends React.Component { + constructor(props) { + super(props); + this.state = { + newLanguage: "", + } + } + + _onRemoved = (language) => { + const languages = this.props.languages.filter((e) => e !== language); + this.props.onLanguagesChange(languages); + }; + + _onAddClick = (e) => { + e.stopPropagation(); + e.preventDefault(); + + const language = this.state.newLanguage; + + if (!language) return; + if (this.props.languages.includes(language)) return; + + this.props.languages.push(language) + this.props.onLanguagesChange(this.props.languages); + }; + + _onNewLanguageChange = (language: string) => { + if (this.state.newLanguage === language) return; + this.setState({newLanguage: language}); + }; + + render() { + const existingSpellCheckLanguages = this.props.languages.map((e) => { + return ; + }); + + let addButton = ( + + {_t("Add")} + + ); + + return ( +
+ {existingSpellCheckLanguages} +
+ + {addButton} + +
+ ); + }; +} diff --git a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js index 35285351ab..6d04d83047 100644 --- a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js @@ -22,6 +22,7 @@ import ProfileSettings from "../../ProfileSettings"; import * as languageHandler from "../../../../../languageHandler"; import SettingsStore from "../../../../../settings/SettingsStore"; import LanguageDropdown from "../../../elements/LanguageDropdown"; +import SpellCheckSettings from "../../SpellCheckSettings" import AccessibleButton from "../../../elements/AccessibleButton"; import DeactivateAccountDialog from "../../../dialogs/DeactivateAccountDialog"; import PropTypes from "prop-types"; @@ -49,6 +50,7 @@ export default class GeneralUserSettingsTab extends React.Component { this.state = { language: languageHandler.getCurrentLanguage(), + spellCheckLanguages: [], haveIdServer: Boolean(MatrixClientPeg.get().getIdentityServerUrl()), serverSupportsSeparateAddAndBind: null, idServerHasUnsignedTerms: false, @@ -182,6 +184,10 @@ export default class GeneralUserSettingsTab extends React.Component { PlatformPeg.get().reload(); }; + _onSpellCheckLanguagesChange = (languages) => { + this.setState({spellCheckLanguages: languages}) + }; + _onPasswordChangeError = (err) => { // TODO: Figure out a design that doesn't involve replacing the current dialog let errMsg = err.error || ""; @@ -303,6 +309,17 @@ export default class GeneralUserSettingsTab extends React.Component { ); } + _renderSpellCheckSection() { + return ( +
+ {_t("Spell checking")} + +
+ ); + } + _renderDiscoverySection() { const SetIdServer = sdk.getComponent("views.settings.SetIdServer"); @@ -409,6 +426,7 @@ export default class GeneralUserSettingsTab extends React.Component { {this._renderProfileSection()} {this._renderAccountSection()} {this._renderLanguageSection()} + {this._renderSpellCheckSection()} { discoverySection } {this._renderIntegrationManagerSection() /* Has its own title */} { accountManagementSection } From 051368eaab50e4a7d6f2ce554ddff0ed957bb965 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 26 Nov 2020 13:53:22 +0100 Subject: [PATCH 004/479] Fix i18n --- src/i18n/strings/en_EN.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 0d50128f32..7fbcc1a350 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1109,6 +1109,7 @@ "Use an Integration Manager to manage bots, widgets, and sticker packs.": "Use an Integration Manager to manage bots, widgets, and sticker packs.", "Manage integrations": "Manage integrations", "Integration Managers receive configuration data, and can modify widgets, send room invites, and set power levels on your behalf.": "Integration Managers receive configuration data, and can modify widgets, send room invites, and set power levels on your behalf.", + "Add": "Add", "Error encountered (%(errorDetail)s).": "Error encountered (%(errorDetail)s).", "Checking for an update...": "Checking for an update...", "No update available.": "No update available.", @@ -1140,6 +1141,7 @@ "Set a new account password...": "Set a new account password...", "Account": "Account", "Language and region": "Language and region", + "Spell checking": "Spell checking", "Agree to the identity server (%(serverName)s) Terms of Service to allow yourself to be discoverable by email address or phone number.": "Agree to the identity server (%(serverName)s) Terms of Service to allow yourself to be discoverable by email address or phone number.", "Account management": "Account management", "Deactivating your account is a permanent action - be careful!": "Deactivating your account is a permanent action - be careful!", @@ -1337,7 +1339,6 @@ "Invalid Email Address": "Invalid Email Address", "This doesn't appear to be a valid email address": "This doesn't appear to be a valid email address", "Unable to add email address": "Unable to add email address", - "Add": "Add", "We've sent you an email to verify your address. Please follow the instructions there and then click the button below.": "We've sent you an email to verify your address. Please follow the instructions there and then click the button below.", "Email Address": "Email Address", "Remove %(phone)s?": "Remove %(phone)s?", From 557e650a2c2e2eb24584f21bd4175e69cc7500a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sat, 28 Nov 2020 19:37:49 +0100 Subject: [PATCH 005/479] Added spell-check-languages setting --- src/settings/Settings.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index 31e133be72..409cd293d2 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -402,6 +402,10 @@ export const SETTINGS: {[setting: string]: ISetting} = { supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG, default: "en", }, + "spell-check-languages": { + supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG, + default: [], + }, "breadcrumb_rooms": { // not really a setting supportedLevels: [SettingLevel.ACCOUNT], From 43daec03e24820a485f97da0b5cb0311f137e729 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sat, 28 Nov 2020 19:38:52 +0100 Subject: [PATCH 006/479] Added setSpellCheckLanguages() method --- src/languageHandler.tsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/languageHandler.tsx b/src/languageHandler.tsx index b61f57d4b3..9b9e304294 100644 --- a/src/languageHandler.tsx +++ b/src/languageHandler.tsx @@ -346,6 +346,13 @@ export function setLanguage(preferredLangs: string | string[]) { }); } +export function setSpellCheckLanguages(preferredLangs: string[]) { + const plaf = PlatformPeg.get(); + if (plaf) { + plaf.setLanguage(preferredLangs); + } +} + export function getAllLanguagesFromJson() { return getLangsJson().then((langsObject) => { const langs = []; From 5e4f9907cf87e02b41791ce729b38d7474dcbf01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sat, 28 Nov 2020 19:39:09 +0100 Subject: [PATCH 007/479] Added persistance --- .../views/settings/tabs/user/GeneralUserSettingsTab.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js index 6d04d83047..585f4fd5b7 100644 --- a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js @@ -50,7 +50,7 @@ export default class GeneralUserSettingsTab extends React.Component { this.state = { language: languageHandler.getCurrentLanguage(), - spellCheckLanguages: [], + spellCheckLanguages: SettingsStore.getValue("spell-check-languages", null, /*excludeDefault=*/true), haveIdServer: Boolean(MatrixClientPeg.get().getIdentityServerUrl()), serverSupportsSeparateAddAndBind: null, idServerHasUnsignedTerms: false, @@ -185,7 +185,9 @@ export default class GeneralUserSettingsTab extends React.Component { }; _onSpellCheckLanguagesChange = (languages) => { + SettingsStore.setValue("spell-check-languages", null, SettingLevel.DEVICE, languages); this.setState({spellCheckLanguages: languages}) + PlatformPeg.get().reload(); }; _onPasswordChangeError = (err) => { From f0bbed0c44270f8411c0ce0f4ee0cf08142a1c1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sun, 29 Nov 2020 12:17:07 +0100 Subject: [PATCH 008/479] Allow default value --- .../views/settings/tabs/user/GeneralUserSettingsTab.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js index 585f4fd5b7..68a16463b0 100644 --- a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js @@ -50,7 +50,7 @@ export default class GeneralUserSettingsTab extends React.Component { this.state = { language: languageHandler.getCurrentLanguage(), - spellCheckLanguages: SettingsStore.getValue("spell-check-languages", null, /*excludeDefault=*/true), + spellCheckLanguages: SettingsStore.getValue("spell-check-languages", null, false), haveIdServer: Boolean(MatrixClientPeg.get().getIdentityServerUrl()), serverSupportsSeparateAddAndBind: null, idServerHasUnsignedTerms: false, From 8f40cd39fda1ee83ec6b177ba7935f913ed5a45b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sun, 29 Nov 2020 12:29:05 +0100 Subject: [PATCH 009/479] Added styling --- res/css/_components.scss | 1 + .../views/settings/_SpellCheckLanguages.scss | 36 +++++++++++++++++++ .../views/settings/SpellCheckSettings.tsx | 9 +++-- .../tabs/user/GeneralUserSettingsTab.js | 7 ++-- 4 files changed, 44 insertions(+), 9 deletions(-) create mode 100644 res/css/views/settings/_SpellCheckLanguages.scss diff --git a/res/css/_components.scss b/res/css/_components.scss index 445ed70ff4..1eb4b91a31 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -207,6 +207,7 @@ @import "./views/settings/_DevicesPanel.scss"; @import "./views/settings/_E2eAdvancedPanel.scss"; @import "./views/settings/_EmailAddresses.scss"; +@import "./views/settings/_SpellCheckLanguages.scss"; @import "./views/settings/_IntegrationManager.scss"; @import "./views/settings/_Notifications.scss"; @import "./views/settings/_PhoneNumbers.scss"; diff --git a/res/css/views/settings/_SpellCheckLanguages.scss b/res/css/views/settings/_SpellCheckLanguages.scss new file mode 100644 index 0000000000..734f669f0e --- /dev/null +++ b/res/css/views/settings/_SpellCheckLanguages.scss @@ -0,0 +1,36 @@ +/* +Copyright 2019 New Vector Ltd +Copyright 2019 The Matrix.org Foundation C.I.C. + +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. +*/ + +.mx_ExistingSpellCheckLanguage { + display: flex; + align-items: center; + margin-bottom: 5px; +} + +.mx_ExistingSpellCheckLanguage_language { + flex: 1; + margin-right: 10px; +} + +.mx_GeneralUserSettingsTab_spellCheckLanguageInput { + margin-top: 1em; + margin-bottom: 1em; +} + +.mx_SpellCheckLanguages { + @mixin mx_Settings_fullWidthField; +} \ No newline at end of file diff --git a/src/components/views/settings/SpellCheckSettings.tsx b/src/components/views/settings/SpellCheckSettings.tsx index 1bdcd882c9..befd98112e 100644 --- a/src/components/views/settings/SpellCheckSettings.tsx +++ b/src/components/views/settings/SpellCheckSettings.tsx @@ -43,8 +43,8 @@ export class ExistingSpellCheckLanguage extends React.Component - {this.props.language} +
+ {this.props.language} {_t("Remove")} @@ -96,10 +96,9 @@ export default class SpellCheckLanguages extends React.Component +
{existingSpellCheckLanguages} -
+ diff --git a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js index 68a16463b0..258ff6d318 100644 --- a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js @@ -313,11 +313,10 @@ export default class GeneralUserSettingsTab extends React.Component { _renderSpellCheckSection() { return ( -
+
{_t("Spell checking")} - +
); } From 7609f2004e6a004c22e0da189f58cee823bf4468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sun, 29 Nov 2020 13:22:50 +0100 Subject: [PATCH 010/479] Added newline to end --- res/css/views/settings/_SpellCheckLanguages.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/css/views/settings/_SpellCheckLanguages.scss b/res/css/views/settings/_SpellCheckLanguages.scss index 734f669f0e..ddfa0bf9e0 100644 --- a/res/css/views/settings/_SpellCheckLanguages.scss +++ b/res/css/views/settings/_SpellCheckLanguages.scss @@ -33,4 +33,4 @@ limitations under the License. .mx_SpellCheckLanguages { @mixin mx_Settings_fullWidthField; -} \ No newline at end of file +} From ead00dcdede9e6a24904599baba39bc91de0681a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sun, 29 Nov 2020 14:46:09 +0100 Subject: [PATCH 011/479] Set spell-check languages without reloading --- .../views/settings/tabs/user/GeneralUserSettingsTab.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js index 258ff6d318..ad7e04d677 100644 --- a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js @@ -187,7 +187,11 @@ export default class GeneralUserSettingsTab extends React.Component { _onSpellCheckLanguagesChange = (languages) => { SettingsStore.setValue("spell-check-languages", null, SettingLevel.DEVICE, languages); this.setState({spellCheckLanguages: languages}) - PlatformPeg.get().reload(); + + const plaf = PlatformPeg.get(); + if (plaf) { + plaf.setLanguage(languages); + } }; _onPasswordChangeError = (err) => { From 38080c5b2bccafb7dae5c9737e69ad7f295f1d7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sun, 29 Nov 2020 20:46:47 +0100 Subject: [PATCH 012/479] Added getAvailableSpellCheckLanguages() methods --- src/BasePlatform.ts | 4 ++++ src/languageHandler.tsx | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/src/BasePlatform.ts b/src/BasePlatform.ts index 0a1f06f0b3..9ac35092a7 100644 --- a/src/BasePlatform.ts +++ b/src/BasePlatform.ts @@ -237,6 +237,10 @@ export default abstract class BasePlatform { setLanguage(preferredLangs: string[]) {} + getAvailableSpellCheckLanguages(): Promise | null { + return null; + } + protected getSSOCallbackUrl(fragmentAfterLogin: string): URL { const url = new URL(window.location.href); url.hash = fragmentAfterLogin || ""; diff --git a/src/languageHandler.tsx b/src/languageHandler.tsx index 9b9e304294..b827e83ded 100644 --- a/src/languageHandler.tsx +++ b/src/languageHandler.tsx @@ -353,6 +353,11 @@ export function setSpellCheckLanguages(preferredLangs: string[]) { } } +export async function getAvailableSpellCheckLanguages(): Promise { + const plaf = PlatformPeg.get(); + return plaf.getAvailableSpellCheckLanguages(); +} + export function getAllLanguagesFromJson() { return getLangsJson().then((langsObject) => { const langs = []; From 5d9f5ba979d3fc89bf6eec5ad2f319bea7168aec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 30 Nov 2020 08:35:51 +0100 Subject: [PATCH 013/479] Fix indentation --- src/components/views/elements/LanguageDropdown.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/views/elements/LanguageDropdown.js b/src/components/views/elements/LanguageDropdown.js index e37109caff..03ec456af5 100644 --- a/src/components/views/elements/LanguageDropdown.js +++ b/src/components/views/elements/LanguageDropdown.js @@ -100,10 +100,10 @@ export default class LanguageDropdown extends React.Component { let language = SettingsStore.getValue("language", null, /*excludeDefault:*/true); let value = null; if (language) { - value = this.props.value || language; + value = this.props.value || language; } else { - language = navigator.language || navigator.userLanguage; - value = this.props.value || language; + language = navigator.language || navigator.userLanguage; + value = this.props.value || language; } return Date: Tue, 1 Dec 2020 16:59:02 +0100 Subject: [PATCH 014/479] Change label --- .../views/settings/tabs/user/GeneralUserSettingsTab.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js index ad7e04d677..8d06ea3b36 100644 --- a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js @@ -318,7 +318,7 @@ export default class GeneralUserSettingsTab extends React.Component { _renderSpellCheckSection() { return (
- {_t("Spell checking")} + {_t("Spell check dictionaries")}
From cf61d50df40614a45c36c0d9886c3583ca69513e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 1 Dec 2020 16:59:21 +0100 Subject: [PATCH 015/479] Added SpellCheckLanguagesDropdown --- .../elements/SpellCheckLanguagesDropdown.tsx | 125 ++++++++++++++++++ .../views/settings/SpellCheckSettings.tsx | 4 +- 2 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 src/components/views/elements/SpellCheckLanguagesDropdown.tsx diff --git a/src/components/views/elements/SpellCheckLanguagesDropdown.tsx b/src/components/views/elements/SpellCheckLanguagesDropdown.tsx new file mode 100644 index 0000000000..db158fa3dd --- /dev/null +++ b/src/components/views/elements/SpellCheckLanguagesDropdown.tsx @@ -0,0 +1,125 @@ +/* +Copyright 2017 Marcel Radzio (MTRNord) +Copyright 2017 Vector Creations 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 React from 'react'; +import PropTypes from 'prop-types'; + +import Dropdown from "../../views/elements/Dropdown" +import PlatformPeg from "../../../PlatformPeg"; +import * as sdk from '../../../index'; +import * as languageHandler from '../../../languageHandler'; +import SettingsStore from "../../../settings/SettingsStore"; +import { _t } from "../../../languageHandler"; + +function languageMatchesSearchQuery(query, language) { + if (language.label.toUpperCase().includes(query.toUpperCase())) return true; + if (language.value.toUpperCase() === query.toUpperCase()) return true; + return false; +} + +interface SpellCheckLanguagesDropdownIProps { + className: string, + value: string, + onOptionChange(language: string), +}; + +interface SpellCheckLanguagesDropdownIState { + searchQuery: string, + languages: any, +} + +export default class SpellCheckLanguagesDropdown extends React.Component { + constructor(props) { + super(props); + this._onSearchChange = this._onSearchChange.bind(this); + + this.state = { + searchQuery: '', + languages: null, + }; + } + + componentDidMount() { + languageHandler.getAvailableSpellCheckLanguages().then((languages) => { + languages.sort(function(a, b) { + if (a < b) return -1; + if (a > b) return 1; + return 0; + }); + var langs = []; + languages.forEach((language) => { + langs.push({ + label: language, + value: language, + }) + }) + this.setState({languages: langs}); + }).catch((e) => { + this.setState({languages: ['en']}); + }); + } + + _onSearchChange(search) { + this.setState({ + searchQuery: search, + }); + } + + render() { + if (this.state.languages === null) { + const Spinner = sdk.getComponent('elements.Spinner'); + return ; + } + + let displayedLanguages; + if (this.state.searchQuery) { + displayedLanguages = this.state.languages.filter((lang) => { + return languageMatchesSearchQuery(this.state.searchQuery, lang); + }); + } else { + displayedLanguages = this.state.languages; + } + + const options = displayedLanguages.map((language) => { + return
+ { language.label } +
; + }); + + // default value here too, otherwise we need to handle null / undefined; + // values between mounting and the initial value propgating + let language = SettingsStore.getValue("language", null, /*excludeDefault:*/true); + let value = null; + if (language) { + value = this.props.value || language; + } else { + language = navigator.language || navigator.userLanguage; + value = this.props.value || language; + } + + return + { options } + ; + } +} diff --git a/src/components/views/settings/SpellCheckSettings.tsx b/src/components/views/settings/SpellCheckSettings.tsx index befd98112e..37476d5f34 100644 --- a/src/components/views/settings/SpellCheckSettings.tsx +++ b/src/components/views/settings/SpellCheckSettings.tsx @@ -15,7 +15,7 @@ limitations under the License. */ import React from 'react'; -import LanguageDropdown from "../../../components/views/elements/LanguageDropdown"; +import SpellCheckLanguagesDropdown from "../../../components/views/elements/SpellCheckLanguagesDropdown"; import AccessibleButton from "../../../components/views/elements/AccessibleButton"; import {_t} from "../../../languageHandler"; @@ -99,7 +99,7 @@ export default class SpellCheckLanguages extends React.Component {existingSpellCheckLanguages} - {addButton} From a6d6af1a937fb6bc6cec2e320fbff453bef3c680 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 1 Dec 2020 17:19:45 +0100 Subject: [PATCH 016/479] Added defaults --- src/settings/Settings.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index 409cd293d2..c83dbab897 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -404,7 +404,7 @@ export const SETTINGS: {[setting: string]: ISetting} = { }, "spell-check-languages": { supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG, - default: [], + default: ["en"], }, "breadcrumb_rooms": { // not really a setting From e9203d75715dbd6a677849dbb83a3d4706b2e6e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 1 Dec 2020 17:21:23 +0100 Subject: [PATCH 017/479] Removed unnecessary imports --- src/components/views/elements/SpellCheckLanguagesDropdown.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/views/elements/SpellCheckLanguagesDropdown.tsx b/src/components/views/elements/SpellCheckLanguagesDropdown.tsx index db158fa3dd..5e0fe3132c 100644 --- a/src/components/views/elements/SpellCheckLanguagesDropdown.tsx +++ b/src/components/views/elements/SpellCheckLanguagesDropdown.tsx @@ -16,10 +16,8 @@ limitations under the License. */ import React from 'react'; -import PropTypes from 'prop-types'; import Dropdown from "../../views/elements/Dropdown" -import PlatformPeg from "../../../PlatformPeg"; import * as sdk from '../../../index'; import * as languageHandler from '../../../languageHandler'; import SettingsStore from "../../../settings/SettingsStore"; From 8287f197f40869941d402e45da87c88d19514545 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 1 Dec 2020 19:49:31 +0100 Subject: [PATCH 018/479] Fix i18n --- src/i18n/strings/en_EN.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 282c1ce686..9ccd0e1e75 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1149,7 +1149,7 @@ "Set a new account password...": "Set a new account password...", "Account": "Account", "Language and region": "Language and region", - "Spell checking": "Spell checking", + "Spell check dictionaries": "Spell check dictionaries", "Agree to the identity server (%(serverName)s) Terms of Service to allow yourself to be discoverable by email address or phone number.": "Agree to the identity server (%(serverName)s) Terms of Service to allow yourself to be discoverable by email address or phone number.", "Account management": "Account management", "Deactivating your account is a permanent action - be careful!": "Deactivating your account is a permanent action - be careful!", From 44a363f188fb95927fff942b4c6b5a3914dbe31d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 1 Dec 2020 20:16:48 +0100 Subject: [PATCH 019/479] Fix default value --- src/settings/Settings.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index c83dbab897..3540767a99 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -404,7 +404,7 @@ export const SETTINGS: {[setting: string]: ISetting} = { }, "spell-check-languages": { supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG, - default: ["en"], + default: ["en-US"], }, "breadcrumb_rooms": { // not really a setting From 3c2bb6e4f6d19e337d902613adbddf42fcba2f3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 1 Dec 2020 20:17:24 +0100 Subject: [PATCH 020/479] Cleanup --- src/BasePlatform.ts | 2 ++ .../views/settings/tabs/user/GeneralUserSettingsTab.js | 5 +---- src/languageHandler.tsx | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/BasePlatform.ts b/src/BasePlatform.ts index 9ac35092a7..2af2ea51c5 100644 --- a/src/BasePlatform.ts +++ b/src/BasePlatform.ts @@ -237,6 +237,8 @@ export default abstract class BasePlatform { setLanguage(preferredLangs: string[]) {} + setSpellCheckLanguages(preferredLangs: string[]) {} + getAvailableSpellCheckLanguages(): Promise | null { return null; } diff --git a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js index 8d06ea3b36..6ed887d749 100644 --- a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js @@ -188,10 +188,7 @@ export default class GeneralUserSettingsTab extends React.Component { SettingsStore.setValue("spell-check-languages", null, SettingLevel.DEVICE, languages); this.setState({spellCheckLanguages: languages}) - const plaf = PlatformPeg.get(); - if (plaf) { - plaf.setLanguage(languages); - } + languageHandler.setSpellCheckLanguages(languages); }; _onPasswordChangeError = (err) => { diff --git a/src/languageHandler.tsx b/src/languageHandler.tsx index b827e83ded..38d3c8347a 100644 --- a/src/languageHandler.tsx +++ b/src/languageHandler.tsx @@ -349,7 +349,7 @@ export function setLanguage(preferredLangs: string | string[]) { export function setSpellCheckLanguages(preferredLangs: string[]) { const plaf = PlatformPeg.get(); if (plaf) { - plaf.setLanguage(preferredLangs); + plaf.setSpellCheckLanguages(preferredLangs); } } From db5bc0cb7ade92fc056283af639e3c782d384e4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 1 Dec 2020 20:36:25 +0100 Subject: [PATCH 021/479] Fix formatting --- .../elements/SpellCheckLanguagesDropdown.tsx | 7 ++++--- .../views/settings/SpellCheckSettings.tsx | 17 +++++++++-------- .../tabs/user/GeneralUserSettingsTab.js | 6 +++--- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/components/views/elements/SpellCheckLanguagesDropdown.tsx b/src/components/views/elements/SpellCheckLanguagesDropdown.tsx index 5e0fe3132c..53c3f310b7 100644 --- a/src/components/views/elements/SpellCheckLanguagesDropdown.tsx +++ b/src/components/views/elements/SpellCheckLanguagesDropdown.tsx @@ -33,14 +33,15 @@ interface SpellCheckLanguagesDropdownIProps { className: string, value: string, onOptionChange(language: string), -}; +} interface SpellCheckLanguagesDropdownIState { searchQuery: string, languages: any, } -export default class SpellCheckLanguagesDropdown extends React.Component { +export default class SpellCheckLanguagesDropdown extends React.Component { constructor(props) { super(props); this._onSearchChange = this._onSearchChange.bind(this); @@ -58,7 +59,7 @@ export default class SpellCheckLanguagesDropdown extends React.Component b) return 1; return 0; }); - var langs = []; + const langs = []; languages.forEach((language) => { langs.push({ label: language, diff --git a/src/components/views/settings/SpellCheckSettings.tsx b/src/components/views/settings/SpellCheckSettings.tsx index 37476d5f34..bfe0774570 100644 --- a/src/components/views/settings/SpellCheckSettings.tsx +++ b/src/components/views/settings/SpellCheckSettings.tsx @@ -22,12 +22,12 @@ import {_t} from "../../../languageHandler"; interface ExistingSpellCheckLanguageIProps { language: string, onRemoved(language: string), -}; +} interface SpellCheckLanguagesIProps { languages: Array, onLanguagesChange(languages: Array), -}; +} interface SpellCheckLanguagesIState { newLanguage: string, @@ -71,7 +71,7 @@ export default class SpellCheckLanguages extends React.Component; }); - let addButton = ( + const addButton = ( {_t("Add")} @@ -99,12 +99,13 @@ export default class SpellCheckLanguages extends React.Component {existingSpellCheckLanguages} - + {addButton}
); - }; + } } diff --git a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js index 6ed887d749..95a8abbb24 100644 --- a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js @@ -22,7 +22,7 @@ import ProfileSettings from "../../ProfileSettings"; import * as languageHandler from "../../../../../languageHandler"; import SettingsStore from "../../../../../settings/SettingsStore"; import LanguageDropdown from "../../../elements/LanguageDropdown"; -import SpellCheckSettings from "../../SpellCheckSettings" +import SpellCheckSettings from "../../SpellCheckSettings"; import AccessibleButton from "../../../elements/AccessibleButton"; import DeactivateAccountDialog from "../../../dialogs/DeactivateAccountDialog"; import PropTypes from "prop-types"; @@ -186,8 +186,8 @@ export default class GeneralUserSettingsTab extends React.Component { _onSpellCheckLanguagesChange = (languages) => { SettingsStore.setValue("spell-check-languages", null, SettingLevel.DEVICE, languages); - this.setState({spellCheckLanguages: languages}) - + this.setState({spellCheckLanguages: languages}); + languageHandler.setSpellCheckLanguages(languages); }; From bab541a652e402c1aede8caa00b22b13a2adb0c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 2 Dec 2020 20:14:58 +0100 Subject: [PATCH 022/479] Hide spell-check settings if not using Electron --- src/BasePlatform.ts | 8 ++++++++ .../views/settings/tabs/user/GeneralUserSettingsTab.js | 5 ++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/BasePlatform.ts b/src/BasePlatform.ts index 2af2ea51c5..54d15675cb 100644 --- a/src/BasePlatform.ts +++ b/src/BasePlatform.ts @@ -128,6 +128,14 @@ export default abstract class BasePlatform { hideUpdateToast(); } + /** + * Return true if platform supports multi-language + * spell-checking, otherwise false. + */ + supportsMultiLanguageSpellCheck(): boolean { + return false; + } + /** * Returns true if the platform supports displaying * notifications, otherwise false. diff --git a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js index 95a8abbb24..4d1210dc40 100644 --- a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js @@ -400,6 +400,9 @@ export default class GeneralUserSettingsTab extends React.Component { } render() { + const plaf = PlatformPeg.get(); + const supportsMultiLanguageSpellCheck = plaf.supportsMultiLanguageSpellCheck() ? true : false; + const discoWarning = this.state.requiredPolicyInfo.hasTerms ? Date: Thu, 3 Dec 2020 11:50:08 +0100 Subject: [PATCH 023/479] Simplifie --- .../views/settings/tabs/user/GeneralUserSettingsTab.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js index 4d1210dc40..febbcc8e36 100644 --- a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js @@ -401,7 +401,7 @@ export default class GeneralUserSettingsTab extends React.Component { render() { const plaf = PlatformPeg.get(); - const supportsMultiLanguageSpellCheck = plaf.supportsMultiLanguageSpellCheck() ? true : false; + const supportsMultiLanguageSpellCheck = plaf.supportsMultiLanguageSpellCheck(); const discoWarning = this.state.requiredPolicyInfo.hasTerms ? Date: Thu, 3 Dec 2020 11:50:20 +0100 Subject: [PATCH 024/479] Added in if statement --- src/languageHandler.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/languageHandler.tsx b/src/languageHandler.tsx index 38d3c8347a..985719fce7 100644 --- a/src/languageHandler.tsx +++ b/src/languageHandler.tsx @@ -355,7 +355,9 @@ export function setSpellCheckLanguages(preferredLangs: string[]) { export async function getAvailableSpellCheckLanguages(): Promise { const plaf = PlatformPeg.get(); - return plaf.getAvailableSpellCheckLanguages(); + if (plaf) { + return plaf.getAvailableSpellCheckLanguages(); + } } export function getAllLanguagesFromJson() { From 89bc4435945bfb207355cf5e5e290925f7d7f7aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 16 Dec 2020 16:02:27 +0100 Subject: [PATCH 025/479] Fix file drop UI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/structures/_MainSplit.scss | 2 +- res/css/structures/_RoomView.scss | 13 +++++-------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/res/css/structures/_MainSplit.scss b/res/css/structures/_MainSplit.scss index ad1656efbb..3de68b000d 100644 --- a/res/css/structures/_MainSplit.scss +++ b/res/css/structures/_MainSplit.scss @@ -22,7 +22,7 @@ limitations under the License. } .mx_MainSplit > .mx_RightPanel_ResizeWrapper { - padding: 5px; + padding: 0 5px 5px 5px; // margin left to not allow the handle to not encroach on the space for the scrollbar margin-left: 8px; height: calc(100vh - 51px); // height of .mx_RoomHeader.light-panel diff --git a/res/css/structures/_RoomView.scss b/res/css/structures/_RoomView.scss index 572c7166d2..0a70b027ae 100644 --- a/res/css/structures/_RoomView.scss +++ b/res/css/structures/_RoomView.scss @@ -23,24 +23,21 @@ limitations under the License. .mx_RoomView_fileDropTarget { min-width: 0px; width: 100%; + height: 100%; + + margin-left: 6.25px; + font-size: $font-18px; text-align: center; pointer-events: none; - padding-left: 12px; - padding-right: 12px; - margin-left: -12px; - border-top-left-radius: 10px; border-top-right-radius: 10px; background-color: $droptarget-bg-color; - border: 2px #e1dddd solid; - border-bottom: none; + position: absolute; - top: 52px; - bottom: 0px; z-index: 3000; } From 41e2ffdf0df43104ef171b690b344a6e22b286f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 16 Dec 2020 19:51:49 +0100 Subject: [PATCH 026/479] Added background MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/structures/_RoomView.scss | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/res/css/structures/_RoomView.scss b/res/css/structures/_RoomView.scss index 0a70b027ae..9292a400bc 100644 --- a/res/css/structures/_RoomView.scss +++ b/res/css/structures/_RoomView.scss @@ -39,13 +39,19 @@ limitations under the License. position: absolute; z-index: 3000; + + display: flex; + justify-content: center; + align-items: center; } .mx_RoomView_fileDropTargetLabel { - top: 50%; - width: 100%; - margin-top: -50px; position: absolute; + + border-radius: 10px; + padding: 10px; + + background-color: $menu-bg-color; } .mx_RoomView_auxPanel { From da97d18332c5740499913506b0e059e5b4c7616c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 16 Dec 2020 21:33:05 +0100 Subject: [PATCH 027/479] Added a comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/structures/_RoomView.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/res/css/structures/_RoomView.scss b/res/css/structures/_RoomView.scss index 9292a400bc..dd63be3a11 100644 --- a/res/css/structures/_RoomView.scss +++ b/res/css/structures/_RoomView.scss @@ -25,6 +25,7 @@ limitations under the License. width: 100%; height: 100%; + // This is an ugly fix for centering this element margin-left: 6.25px; font-size: $font-18px; From dcb30b72b0ed1adc6fb075ee9cc26ca0338177bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 17 Dec 2020 13:25:22 +0100 Subject: [PATCH 028/479] Fix left panel resizer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/structures/_MainSplit.scss | 32 ++++++++++++++++---------- res/css/structures/_RoomView.scss | 12 ++++++---- src/components/structures/RoomView.tsx | 28 +++++++++++----------- 3 files changed, 43 insertions(+), 29 deletions(-) diff --git a/res/css/structures/_MainSplit.scss b/res/css/structures/_MainSplit.scss index 3de68b000d..6875ef12e0 100644 --- a/res/css/structures/_MainSplit.scss +++ b/res/css/structures/_MainSplit.scss @@ -22,22 +22,30 @@ limitations under the License. } .mx_MainSplit > .mx_RightPanel_ResizeWrapper { - padding: 0 5px 5px 5px; - // margin left to not allow the handle to not encroach on the space for the scrollbar - margin-left: 8px; + padding: 0 5px 5px 0px; height: calc(100vh - 51px); // height of .mx_RoomHeader.light-panel + + .mx_RightPanel_ResizeHandle { + width: 9px; + } &:hover .mx_RightPanel_ResizeHandle { - // Need to use important to override element style attributes - // set by re-resizable - top: 50% !important; - transform: translate(0, -50%); + &::before { + position: absolute; + left: 6px; + top: 50%; + transform: translate(0, -50%); - height: 64px !important; // to match width of the ones on roomlist - width: 4px !important; - border-radius: 4px !important; + height: 64px; + width: 4px; + border-radius: 4px; - background-color: $primary-fg-color; - opacity: 0.8; + content: ' '; + + background-color: $primary-fg-color; + opacity: 0.8; + + margin-left: -10px; + } } } diff --git a/res/css/structures/_RoomView.scss b/res/css/structures/_RoomView.scss index dd63be3a11..0a12a86c33 100644 --- a/res/css/structures/_RoomView.scss +++ b/res/css/structures/_RoomView.scss @@ -25,9 +25,6 @@ limitations under the License. width: 100%; height: 100%; - // This is an ugly fix for centering this element - margin-left: 6.25px; - font-size: $font-18px; text-align: center; @@ -120,16 +117,23 @@ limitations under the License. height: 50px; } -.mx_RoomView_body { +.mx_RoomView_container { position: relative; //for .mx_RoomView_auxPanel_fullHeight display: flex; flex-direction: column; +} + +.mx_RoomView_body { + display: flex; + flex-direction: column; flex: 1; min-width: 0; .mx_RoomView_messagePanel, .mx_RoomView_messagePanelSpinner, .mx_RoomView_messagePanelSearchSpinner { order: 2; } + + margin-right: 10px; } .mx_RoomView_body .mx_RoomView_timeline { diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index 0ee847fbc9..3d62c06e4b 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -2003,22 +2003,24 @@ export default class RoomView extends React.Component { appsShown={this.state.showApps} /> -
+
{auxPanel} -
- {topUnreadMessagesBar} - {jumpToBottom} - {messagePanel} - {searchResultsPanel} -
-
-
-
- {statusBar} +
+
+ {topUnreadMessagesBar} + {jumpToBottom} + {messagePanel} + {searchResultsPanel}
+
+
+
+ {statusBar} +
+
+ {previewBar} + {messageComposer}
- {previewBar} - {messageComposer}
From e70dee08d0ea7b303a51fb807929376b2dad79dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 17 Dec 2020 19:50:59 +0100 Subject: [PATCH 029/479] Fix flickering MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/structures/RoomView.tsx | 42 ++++++++++++++++++++------ 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index 3d62c06e4b..67f9663597 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -187,6 +187,7 @@ export interface IState { rejecting?: boolean; rejectError?: Error; hasPinnedWidgets?: boolean; + dragCounter: number; } export default class RoomView extends React.Component { @@ -237,6 +238,7 @@ export default class RoomView extends React.Component { canReply: false, useIRCLayout: SettingsStore.getValue("useIRCLayout"), matrixClientIsReady: this.context && this.context.isInitialSyncComplete(), + dragCounter: 0, }; this.dispatcherRef = dis.register(this.onAction); @@ -525,8 +527,8 @@ export default class RoomView extends React.Component { if (!roomView.ondrop) { roomView.addEventListener('drop', this.onDrop); roomView.addEventListener('dragover', this.onDragOver); - roomView.addEventListener('dragleave', this.onDragLeaveOrEnd); - roomView.addEventListener('dragend', this.onDragLeaveOrEnd); + roomView.addEventListener('dragenter', this.onDragEnter); + roomView.addEventListener('dragleave', this.onDragLeave); } } @@ -1108,6 +1110,31 @@ export default class RoomView extends React.Component { this.updateTopUnreadMessagesBar(); }; + private onDragEnter = ev => { + ev.stopPropagation(); + ev.preventDefault(); + + this.setState({ + dragCounter: this.state.dragCounter + 1, + draggingFile: true, + }); + }; + + private onDragLeave = ev => { + ev.stopPropagation(); + ev.preventDefault(); + + this.setState({ + dragCounter: this.state.dragCounter - 1, + }); + + if (this.state.dragCounter == 0) { + this.setState({ + draggingFile: false, + }); + } + }; + private onDragOver = ev => { ev.stopPropagation(); ev.preventDefault(); @@ -1115,7 +1142,6 @@ export default class RoomView extends React.Component { ev.dataTransfer.dropEffect = 'none'; if (ev.dataTransfer.types.includes("Files") || ev.dataTransfer.types.includes("application/x-moz-file")) { - this.setState({ draggingFile: true }); ev.dataTransfer.dropEffect = 'copy'; } }; @@ -1126,14 +1152,12 @@ export default class RoomView extends React.Component { ContentMessages.sharedInstance().sendContentListToRoom( ev.dataTransfer.files, this.state.room.roomId, this.context, ); - this.setState({ draggingFile: false }); dis.fire(Action.FocusComposer); - }; - private onDragLeaveOrEnd = ev => { - ev.stopPropagation(); - ev.preventDefault(); - this.setState({ draggingFile: false }); + this.setState({ + draggingFile: false, + dragCounter: this.state.dragCounter - 1, + }); }; private injectSticker(url, info, text) { From 044e02b06ad46b417d3aa8fc33f24c1374fdcb56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 17 Dec 2020 20:16:53 +0100 Subject: [PATCH 030/479] Remove spaces in empty line MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/structures/_MainSplit.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/css/structures/_MainSplit.scss b/res/css/structures/_MainSplit.scss index 6875ef12e0..f05f24d0d7 100644 --- a/res/css/structures/_MainSplit.scss +++ b/res/css/structures/_MainSplit.scss @@ -24,7 +24,7 @@ limitations under the License. .mx_MainSplit > .mx_RightPanel_ResizeWrapper { padding: 0 5px 5px 0px; height: calc(100vh - 51px); // height of .mx_RoomHeader.light-panel - + .mx_RightPanel_ResizeHandle { width: 9px; } From 365d252d3f0eb64755f502318c95f855a4404f56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 17 Dec 2020 20:25:12 +0100 Subject: [PATCH 031/479] Fix removing event listeners MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/structures/RoomView.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index 67f9663597..d910940a73 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -572,8 +572,8 @@ export default class RoomView extends React.Component { const roomView = this.roomView.current; roomView.removeEventListener('drop', this.onDrop); roomView.removeEventListener('dragover', this.onDragOver); - roomView.removeEventListener('dragleave', this.onDragLeaveOrEnd); - roomView.removeEventListener('dragend', this.onDragLeaveOrEnd); + roomView.removeEventListener('dragenter', this.onDragEnter); + roomView.removeEventListener('dragleave', this.onDragLeave); } dis.unregister(this.dispatcherRef); if (this.context) { From 5d7e45e6cf85e14f4143923f7e29642f97965fc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 17 Dec 2020 20:29:33 +0100 Subject: [PATCH 032/479] Added dragCounter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/contexts/RoomContext.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/contexts/RoomContext.ts b/src/contexts/RoomContext.ts index 082dcc4e6b..1b9097e337 100644 --- a/src/contexts/RoomContext.ts +++ b/src/contexts/RoomContext.ts @@ -42,6 +42,7 @@ const RoomContext = createContext({ canReply: false, useIRCLayout: false, matrixClientIsReady: false, + dragCounter: 0, }); RoomContext.displayName = "RoomContext"; export default RoomContext; From d589c6100069c5ddae0c7372760c63d40ecd84ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sat, 9 Jan 2021 09:09:14 +0100 Subject: [PATCH 033/479] Added send message button MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/rooms/_MessageComposer.scss | 5 +++++ src/components/views/rooms/MessageComposer.js | 14 ++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/res/css/views/rooms/_MessageComposer.scss b/res/css/views/rooms/_MessageComposer.scss index 71c0db947e..897167f745 100644 --- a/res/css/views/rooms/_MessageComposer.scss +++ b/res/css/views/rooms/_MessageComposer.scss @@ -239,6 +239,7 @@ limitations under the License. mask-image: url('$(res)/img/element-icons/call/video-call.svg'); } + .mx_MessageComposer_emoji::before { mask-image: url('$(res)/img/element-icons/room/composer/emoji.svg'); } @@ -247,6 +248,10 @@ limitations under the License. mask-image: url('$(res)/img/element-icons/room/composer/sticker.svg'); } +.mx_MessageComposer_sendMessage::before { + mask-image: url('$(res)/img/element-icons/call/video-call.svg'); +} + .mx_MessageComposer_formatting { cursor: pointer; margin: 0 11px; diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 4ddff8f4b0..86ad3ddbdd 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -393,6 +393,10 @@ export default class MessageComposer extends React.Component { }); } + sendMessage = () => { + this.messageComposerInput._sendMessage(); + } + render() { const controls = [ this.state.me ? : null, @@ -450,6 +454,16 @@ export default class MessageComposer extends React.Component { ); } } + + if (true) { + controls.push(( + + )); + } } else if (this.state.tombstone) { const replacementRoomId = this.state.tombstone.getContent()['replacement_room']; From c64b2a585f3c2d1e75392657995d6b1813250f32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sat, 9 Jan 2021 09:17:40 +0100 Subject: [PATCH 034/479] Added option to disable send button MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/MessageComposer.js | 2 +- .../views/settings/tabs/user/PreferencesUserSettingsTab.js | 1 + src/settings/Settings.ts | 5 +++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 86ad3ddbdd..315b1b78c7 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -455,7 +455,7 @@ export default class MessageComposer extends React.Component { } } - if (true) { + if (SettingsStore.getValue("MessageComposerInput.sendButton")) { controls.push(( Date: Sat, 9 Jan 2021 09:18:10 +0100 Subject: [PATCH 035/479] i18n MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/i18n/strings/en_EN.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index ac18ccb23e..6baccf95de 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -799,6 +799,7 @@ "Show typing notifications": "Show typing notifications", "Use Command + Enter to send a message": "Use Command + Enter to send a message", "Use Ctrl + Enter to send a message": "Use Ctrl + Enter to send a message", + "Show send message button": "Show send message button", "Automatically replace plain text Emoji": "Automatically replace plain text Emoji", "Mirror local video feed": "Mirror local video feed", "Enable Community Filter Panel": "Enable Community Filter Panel", @@ -1412,6 +1413,7 @@ "Send a reply…": "Send a reply…", "Send an encrypted message…": "Send an encrypted message…", "Send a message…": "Send a message…", + "Send message": "Send message", "The conversation continues here.": "The conversation continues here.", "This room has been replaced and is no longer active.": "This room has been replaced and is no longer active.", "You do not have permission to post to this room": "You do not have permission to post to this room", From 4538274e74938294f840abcae070ac75d052d311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sat, 9 Jan 2021 09:25:29 +0100 Subject: [PATCH 036/479] Added send message icon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/rooms/_MessageComposer.scss | 2 +- res/img/element-icons/send-message.svg | 54 +++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 res/img/element-icons/send-message.svg diff --git a/res/css/views/rooms/_MessageComposer.scss b/res/css/views/rooms/_MessageComposer.scss index 897167f745..8c2a997490 100644 --- a/res/css/views/rooms/_MessageComposer.scss +++ b/res/css/views/rooms/_MessageComposer.scss @@ -249,7 +249,7 @@ limitations under the License. } .mx_MessageComposer_sendMessage::before { - mask-image: url('$(res)/img/element-icons/call/video-call.svg'); + mask-image: url('$(res)/img/element-icons/send-message.svg'); } .mx_MessageComposer_formatting { diff --git a/res/img/element-icons/send-message.svg b/res/img/element-icons/send-message.svg new file mode 100644 index 0000000000..2e74745e21 --- /dev/null +++ b/res/img/element-icons/send-message.svg @@ -0,0 +1,54 @@ + + + + + + image/svg+xml + + + + + + + + + From 263f2136502c657c4dcbb07674e965576ad562ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sat, 9 Jan 2021 09:27:02 +0100 Subject: [PATCH 037/479] Remove an empty line MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/rooms/_MessageComposer.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/res/css/views/rooms/_MessageComposer.scss b/res/css/views/rooms/_MessageComposer.scss index 8c2a997490..8b34318f1d 100644 --- a/res/css/views/rooms/_MessageComposer.scss +++ b/res/css/views/rooms/_MessageComposer.scss @@ -239,7 +239,6 @@ limitations under the License. mask-image: url('$(res)/img/element-icons/call/video-call.svg'); } - .mx_MessageComposer_emoji::before { mask-image: url('$(res)/img/element-icons/room/composer/emoji.svg'); } From 7d120f7183eef575f16d78b1e9b4fdfabf7d2848 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sat, 9 Jan 2021 09:33:11 +0100 Subject: [PATCH 038/479] Simplifie svg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/img/element-icons/send-message.svg | 55 +------------------------- 1 file changed, 2 insertions(+), 53 deletions(-) diff --git a/res/img/element-icons/send-message.svg b/res/img/element-icons/send-message.svg index 2e74745e21..ce35bf8bc8 100644 --- a/res/img/element-icons/send-message.svg +++ b/res/img/element-icons/send-message.svg @@ -1,54 +1,3 @@ - - - - - - image/svg+xml - - - - - - - - + + From 9f1113b3bd47295d1e6f0d2e897bcb93773a06cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sat, 16 Jan 2021 16:35:50 +0100 Subject: [PATCH 039/479] Watch setting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/MessageComposer.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 315b1b78c7..a18dded04f 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -263,6 +263,7 @@ export default class MessageComposer extends React.Component { tombstone: this._getRoomTombstone(), canSendMessages: this.props.room.maySendMessage(), showCallButtons: SettingsStore.getValue("showCallButtonsInComposer"), + showSendButton: SettingsStore.getValue("MessageComposerInput.sendButton"), hasConference: WidgetStore.instance.doesRoomHaveConference(this.props.room), joinedConference: WidgetStore.instance.isJoinedToConferenceIn(this.props.room), }; @@ -280,6 +281,12 @@ export default class MessageComposer extends React.Component { } }; + onSendButtonChanged = () => { + this.setState({ + showSendButton: SettingsStore.getValue("MessageComposerInput.sendButton"), + }); + } + _onWidgetUpdate = () => { this.setState({hasConference: WidgetStore.instance.doesRoomHaveConference(this.props.room)}); }; @@ -292,6 +299,8 @@ export default class MessageComposer extends React.Component { this.dispatcherRef = dis.register(this.onAction); MatrixClientPeg.get().on("RoomState.events", this._onRoomStateEvents); this._waitForOwnMember(); + this.showSendButtonRef = SettingsStore.watchSetting( + "MessageComposerInput.sendButton", null, this.onSendButtonChanged); } _waitForOwnMember() { @@ -317,6 +326,7 @@ export default class MessageComposer extends React.Component { WidgetStore.instance.removeListener(UPDATE_EVENT, this._onWidgetUpdate); ActiveWidgetStore.removeListener('update', this._onActiveWidgetUpdate); dis.unregister(this.dispatcherRef); + SettingsStore.unwatchSetting(this.showSendButtonRef); } _onRoomStateEvents(ev, state) { @@ -455,7 +465,7 @@ export default class MessageComposer extends React.Component { } } - if (SettingsStore.getValue("MessageComposerInput.sendButton")) { + if (this.state.showSendButton) { controls.push(( Date: Sat, 16 Jan 2021 16:37:50 +0100 Subject: [PATCH 040/479] Rename setting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/MessageComposer.js | 6 +++--- .../views/settings/tabs/user/PreferencesUserSettingsTab.js | 2 +- src/settings/Settings.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index a18dded04f..1e43aa6652 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -263,7 +263,7 @@ export default class MessageComposer extends React.Component { tombstone: this._getRoomTombstone(), canSendMessages: this.props.room.maySendMessage(), showCallButtons: SettingsStore.getValue("showCallButtonsInComposer"), - showSendButton: SettingsStore.getValue("MessageComposerInput.sendButton"), + showSendButton: SettingsStore.getValue("MessageComposerInput.showSendButton"), hasConference: WidgetStore.instance.doesRoomHaveConference(this.props.room), joinedConference: WidgetStore.instance.isJoinedToConferenceIn(this.props.room), }; @@ -283,7 +283,7 @@ export default class MessageComposer extends React.Component { onSendButtonChanged = () => { this.setState({ - showSendButton: SettingsStore.getValue("MessageComposerInput.sendButton"), + showSendButton: SettingsStore.getValue("MessageComposerInput.showSendButton"), }); } @@ -300,7 +300,7 @@ export default class MessageComposer extends React.Component { MatrixClientPeg.get().on("RoomState.events", this._onRoomStateEvents); this._waitForOwnMember(); this.showSendButtonRef = SettingsStore.watchSetting( - "MessageComposerInput.sendButton", null, this.onSendButtonChanged); + "MessageComposerInput.showSendButton", null, this.onSendButtonChanged); } _waitForOwnMember() { diff --git a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js index 31971b7167..eff0824d59 100644 --- a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js @@ -34,7 +34,7 @@ export default class PreferencesUserSettingsTab extends React.Component { 'MessageComposerInput.suggestEmoji', 'sendTypingNotifications', 'MessageComposerInput.ctrlEnterToSend', - `MessageComposerInput.sendButton`, + `MessageComposerInput.showSendButton`, ]; static TIMELINE_SETTINGS = [ diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index 50d0f919e6..2d8385240c 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -336,7 +336,7 @@ export const SETTINGS: {[setting: string]: ISetting} = { displayName: isMac ? _td("Use Command + Enter to send a message") : _td("Use Ctrl + Enter to send a message"), default: false, }, - "MessageComposerInput.sendButton": { + "MessageComposerInput.showSendButton": { supportedLevels: LEVELS_ACCOUNT_SETTINGS, displayName: _td("Show send message button"), default: false, From c9f5c90047e0140da31050d97d0f831bf50858c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sat, 16 Jan 2021 16:43:47 +0100 Subject: [PATCH 041/479] Rename method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/MessageComposer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 1e43aa6652..9683c4c79e 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -281,7 +281,7 @@ export default class MessageComposer extends React.Component { } }; - onSendButtonChanged = () => { + onShowSendButtonChanged = () => { this.setState({ showSendButton: SettingsStore.getValue("MessageComposerInput.showSendButton"), }); @@ -300,7 +300,7 @@ export default class MessageComposer extends React.Component { MatrixClientPeg.get().on("RoomState.events", this._onRoomStateEvents); this._waitForOwnMember(); this.showSendButtonRef = SettingsStore.watchSetting( - "MessageComposerInput.showSendButton", null, this.onSendButtonChanged); + "MessageComposerInput.showSendButton", null, this.onShowSendButtonChanged); } _waitForOwnMember() { From 0c09158f2a1be05b6a80d8aa393af351b4f4f785 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 22 Jan 2021 08:41:39 +0100 Subject: [PATCH 042/479] Comment out unused code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- .../settings/tabs/user/AppearanceUserSettingsTab.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx b/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx index 209f245b11..c2f010695b 100644 --- a/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx @@ -28,13 +28,13 @@ import { FontWatcher } from "../../../../../settings/watchers/FontWatcher"; import { RecheckThemePayload } from '../../../../../dispatcher/payloads/RecheckThemePayload'; import { Action } from '../../../../../dispatcher/actions'; import { IValidationResult, IFieldState } from '../../../elements/Validation'; -import StyledRadioButton from '../../../elements/StyledRadioButton'; +//import StyledRadioButton from '../../../elements/StyledRadioButton'; import StyledCheckbox from '../../../elements/StyledCheckbox'; import SettingsFlag from '../../../elements/SettingsFlag'; import Field from '../../../elements/Field'; import EventTilePreview from '../../../elements/EventTilePreview'; import StyledRadioGroup from "../../../elements/StyledRadioGroup"; -import classNames from 'classnames'; +//import classNames from 'classnames'; import { SettingLevel } from "../../../../../settings/SettingLevel"; import {UIFeature} from "../../../../../settings/UIFeature"; @@ -213,7 +213,7 @@ export default class AppearanceUserSettingsTab extends React.Component): void => { + /*private onLayoutChange = (e: React.ChangeEvent): void => { const val = e.target.value === "true"; this.setState({ @@ -221,7 +221,7 @@ export default class AppearanceUserSettingsTab extends React.Component; } - private renderLayoutSection = () => { + /*private renderLayoutSection = () => { return
{_t("Message layout")} @@ -384,7 +384,7 @@ export default class AppearanceUserSettingsTab extends React.Component
; - }; + };*/ private renderAdvancedSection() { if (!SettingsStore.getValue(UIFeature.AdvancedSettings)) return null; From c69cc550ea00c9bf16a8d773f91c6733dec80a5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 22 Jan 2021 13:41:21 +0100 Subject: [PATCH 043/479] Added layout enum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/settings/Layout.ts | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/settings/Layout.ts diff --git a/src/settings/Layout.ts b/src/settings/Layout.ts new file mode 100644 index 0000000000..bfb86170e8 --- /dev/null +++ b/src/settings/Layout.ts @@ -0,0 +1,5 @@ +/* TODO: This should be later reworked into something more generic */ +export enum Layout { + IRC = "irc", + Group = "group" +} From 972c9470494ee571f9d2077bb2d1a54be1d1211f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 22 Jan 2021 13:44:45 +0100 Subject: [PATCH 044/479] More generic layout setting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/structures/MessagePanel.js | 10 +++--- src/components/structures/RoomView.tsx | 15 +++++---- src/components/structures/TimelinePanel.js | 7 ++-- .../views/elements/EventTilePreview.tsx | 9 +++--- src/components/views/elements/ReplyThread.js | 9 +++--- src/components/views/rooms/EventTile.js | 18 ++++++----- .../tabs/user/AppearanceUserSettingsTab.tsx | 32 +++++++++++++------ src/contexts/RoomContext.ts | 3 +- src/settings/Settings.ts | 8 ++--- 9 files changed, 65 insertions(+), 46 deletions(-) diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index 375545f819..7b40980714 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -26,6 +26,7 @@ import * as sdk from '../../index'; import {MatrixClientPeg} from '../../MatrixClientPeg'; import SettingsStore from '../../settings/SettingsStore'; +import {Layout} from "../../settings/Layout"; import {_t} from "../../languageHandler"; import {haveTileForEvent} from "../views/rooms/EventTile"; import {textForEvent} from "../../TextForEvent"; @@ -135,14 +136,13 @@ export default class MessagePanel extends React.Component { // whether to show reactions for an event showReactions: PropTypes.bool, - // whether to use the irc layout - useIRCLayout: PropTypes.bool, + // which layout to use + layout: Layout, // whether or not to show flair at all enableFlair: PropTypes.bool, }; - // Force props to be loaded for useIRCLayout constructor(props) { super(props); @@ -612,7 +612,7 @@ export default class MessagePanel extends React.Component { isSelectedEvent={highlight} getRelationsForEvent={this.props.getRelationsForEvent} showReactions={this.props.showReactions} - useIRCLayout={this.props.useIRCLayout} + layout={this.props.layout} enableFlair={this.props.enableFlair} /> @@ -810,7 +810,7 @@ export default class MessagePanel extends React.Component { } let ircResizer = null; - if (this.props.useIRCLayout) { + if (this.props.layout == Layout.IRC) { ircResizer = { statusBarVisible: false, canReact: false, canReply: false, - useIRCLayout: SettingsStore.getValue("useIRCLayout"), + layout: SettingsStore.getValue("layout"), matrixClientIsReady: this.context && this.context.isInitialSyncComplete(), }; @@ -263,7 +264,7 @@ export default class RoomView extends React.Component { this.showReadReceiptsWatchRef = SettingsStore.watchSetting("showReadReceipts", null, this.onReadReceiptsChange); - this.layoutWatcherRef = SettingsStore.watchSetting("useIRCLayout", null, this.onLayoutChange); + this.layoutWatcherRef = SettingsStore.watchSetting("layout", null, this.onLayoutChange); } // TODO: [REACT-WARNING] Move into constructor @@ -624,7 +625,7 @@ export default class RoomView extends React.Component { private onLayoutChange = () => { this.setState({ - useIRCLayout: SettingsStore.getValue("useIRCLayout"), + layout: SettingsStore.getValue("layout"), }); }; @@ -1915,8 +1916,8 @@ export default class RoomView extends React.Component { const messagePanelClassNames = classNames( "mx_RoomView_messagePanel", { - "mx_IRCLayout": this.state.useIRCLayout, - "mx_GroupLayout": !this.state.useIRCLayout, + "mx_IRCLayout": this.state.layout == Layout.IRC, + "mx_GroupLayout": this.state.layout == Layout.Group, }); // console.info("ShowUrlPreview for %s is %s", this.state.room.roomId, this.state.showUrlPreview); @@ -1939,7 +1940,7 @@ export default class RoomView extends React.Component { permalinkCreator={this.getPermalinkCreatorForRoom(this.state.room)} resizeNotifier={this.props.resizeNotifier} showReactions={true} - useIRCLayout={this.state.useIRCLayout} + layout={this.state.layout} />); let topUnreadMessagesBar = null; diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index 27a384ddb2..2d322b378d 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -18,6 +18,7 @@ limitations under the License. */ import SettingsStore from "../../settings/SettingsStore"; +import {Layout} from "../../settings/Layout"; import React, {createRef} from 'react'; import ReactDOM from "react-dom"; import PropTypes from 'prop-types'; @@ -111,8 +112,8 @@ class TimelinePanel extends React.Component { // whether to show reactions for an event showReactions: PropTypes.bool, - // whether to use the irc layout - useIRCLayout: PropTypes.bool, + // which layout to use + layout: Layout, } // a map from room id to read marker event timestamp @@ -1442,7 +1443,7 @@ class TimelinePanel extends React.Component { getRelationsForEvent={this.getRelationsForEvent} editState={this.state.editState} showReactions={this.props.showReactions} - useIRCLayout={this.props.useIRCLayout} + layout={this.props.layout} enableFlair={SettingsStore.getValue(UIFeature.Flair)} /> ); diff --git a/src/components/views/elements/EventTilePreview.tsx b/src/components/views/elements/EventTilePreview.tsx index 20cca35d62..49c97831bc 100644 --- a/src/components/views/elements/EventTilePreview.tsx +++ b/src/components/views/elements/EventTilePreview.tsx @@ -22,6 +22,7 @@ import * as Avatar from '../../../Avatar'; import { MatrixClientPeg } from '../../../MatrixClientPeg'; import EventTile from '../rooms/EventTile'; import SettingsStore from "../../../settings/SettingsStore"; +import {Layout} from "../../../settings/Layout"; import {UIFeature} from "../../../settings/UIFeature"; interface IProps { @@ -33,7 +34,7 @@ interface IProps { /** * Whether to use the irc layout or not */ - useIRCLayout: boolean; + layout: Layout; /** * classnames to apply to the wrapper of the preview @@ -121,14 +122,14 @@ export default class EventTilePreview extends React.Component { const event = this.fakeEvent(this.state); const className = classnames(this.props.className, { - "mx_IRCLayout": this.props.useIRCLayout, - "mx_GroupLayout": !this.props.useIRCLayout, + "mx_IRCLayout": this.props.layout == Layout.IRC, + "mx_GroupLayout": this.props.layout == Layout.Group, }); return
; diff --git a/src/components/views/elements/ReplyThread.js b/src/components/views/elements/ReplyThread.js index 24b49f2b13..74aa715642 100644 --- a/src/components/views/elements/ReplyThread.js +++ b/src/components/views/elements/ReplyThread.js @@ -24,6 +24,7 @@ import {wantsDateSeparator} from '../../../DateUtils'; import {MatrixEvent} from 'matrix-js-sdk'; import {makeUserPermalink, RoomPermalinkCreator} from "../../../utils/permalinks/Permalinks"; import SettingsStore from "../../../settings/SettingsStore"; +import {Layout} from "../../../settings/Layout"; import escapeHtml from "escape-html"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; import {Action} from "../../../dispatcher/actions"; @@ -42,7 +43,7 @@ export default class ReplyThread extends React.Component { onHeightChanged: PropTypes.func.isRequired, permalinkCreator: PropTypes.instanceOf(RoomPermalinkCreator).isRequired, // Specifies which layout to use. - useIRCLayout: PropTypes.bool, + layout: Layout, }; static contextType = MatrixClientContext; @@ -209,7 +210,7 @@ export default class ReplyThread extends React.Component { }; } - static makeThread(parentEv, onHeightChanged, permalinkCreator, ref, useIRCLayout) { + static makeThread(parentEv, onHeightChanged, permalinkCreator, ref, layout) { if (!ReplyThread.getParentEventId(parentEv)) { return
; } @@ -218,7 +219,7 @@ export default class ReplyThread extends React.Component { onHeightChanged={onHeightChanged} ref={ref} permalinkCreator={permalinkCreator} - useIRCLayout={useIRCLayout} + layout={layout} />; } @@ -386,7 +387,7 @@ export default class ReplyThread extends React.Component { permalinkCreator={this.props.permalinkCreator} isRedacted={ev.isRedacted()} isTwelveHour={SettingsStore.getValue("showTwelveHourTimestamps")} - useIRCLayout={this.props.useIRCLayout} + layout={this.props.layout} enableFlair={SettingsStore.getValue(UIFeature.Flair)} replacingEventId={ev.replacingEventId()} /> diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index 11277daa57..17ba61732a 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -27,6 +27,7 @@ import * as TextForEvent from "../../../TextForEvent"; import * as sdk from "../../../index"; import dis from '../../../dispatcher/dispatcher'; import SettingsStore from "../../../settings/SettingsStore"; +import {Layout} from "../../../settings/Layout"; import {EventStatus} from 'matrix-js-sdk'; import {formatTime} from "../../../DateUtils"; import {MatrixClientPeg} from '../../../MatrixClientPeg'; @@ -225,8 +226,8 @@ export default class EventTile extends React.Component { // whether to show reactions for this event showReactions: PropTypes.bool, - // whether to use the irc layout - useIRCLayout: PropTypes.bool, + // which layout to use + layout: Layout, // whether or not to show flair at all enableFlair: PropTypes.bool, @@ -732,7 +733,7 @@ export default class EventTile extends React.Component { // joins/parts/etc avatarSize = 14; needsSenderProfile = false; - } else if (this.props.useIRCLayout) { + } else if (this.props.layout == Layout.IRC) { avatarSize = 14; needsSenderProfile = true; } else if (this.props.continuation && this.props.tileShape !== "file_grid") { @@ -843,10 +844,11 @@ export default class EventTile extends React.Component { { timestamp } ; - const groupTimestamp = !this.props.useIRCLayout ? linkedTimestamp : null; - const ircTimestamp = this.props.useIRCLayout ? linkedTimestamp : null; - const groupPadlock = !this.props.useIRCLayout && !isBubbleMessage && this._renderE2EPadlock(); - const ircPadlock = this.props.useIRCLayout && !isBubbleMessage && this._renderE2EPadlock(); + const useIRCLayout = this.props.layout == Layout.IRC; + const groupTimestamp = !useIRCLayout ? linkedTimestamp : null; + const ircTimestamp = useIRCLayout ? linkedTimestamp : null; + const groupPadlock = !useIRCLayout && !isBubbleMessage && this._renderE2EPadlock(); + const ircPadlock = useIRCLayout && !isBubbleMessage && this._renderE2EPadlock(); switch (this.props.tileShape) { case 'notif': { @@ -941,7 +943,7 @@ export default class EventTile extends React.Component { this.props.onHeightChanged, this.props.permalinkCreator, this._replyThread, - this.props.useIRCLayout, + this.props.layout, ); // tab-index=-1 to allow it to be focusable but do not add tab stop for it, primarily for screen readers diff --git a/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx b/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx index c2f010695b..5d3596911f 100644 --- a/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx @@ -37,6 +37,7 @@ import StyledRadioGroup from "../../../elements/StyledRadioGroup"; //import classNames from 'classnames'; import { SettingLevel } from "../../../../../settings/SettingLevel"; import {UIFeature} from "../../../../../settings/UIFeature"; +import {Layout} from "../../../../../settings/Layout"; interface IProps { } @@ -62,7 +63,7 @@ interface IState extends IThemeState { useSystemFont: boolean; systemFont: string; showAdvanced: boolean; - useIRCLayout: boolean; + layout: Layout; } @@ -83,7 +84,7 @@ export default class AppearanceUserSettingsTab extends React.Component { + if (enabled) { + this.setState({layout: Layout.IRC}); + SettingsStore.setValue("layout", null, SettingLevel.DEVICE, Layout.IRC); + } else { + this.setState({layout: Layout.Group}); + SettingsStore.setValue("layout", null, SettingLevel.DEVICE, Layout.Group); + } + } + private renderThemeSection() { const themeWatcher = new ThemeWatcher(); let systemThemeSection: JSX.Element; @@ -306,7 +317,7 @@ export default class AppearanceUserSettingsTab extends React.Component
Aa
@@ -409,14 +420,15 @@ export default class AppearanceUserSettingsTab extends React.Component - this.setState({useIRCLayout: checked})} + disabled={this.state.layout == Layout.IRC} /> + this.onIRCLayoutChange(ev.target.checked)} + > + {_t("Enable experimental, compact IRC style layout")} + + ({ roomLoading: true, @@ -40,7 +41,7 @@ const RoomContext = createContext({ statusBarVisible: false, canReact: false, canReply: false, - useIRCLayout: false, + layout: Layout.Group, matrixClientIsReady: false, }); RoomContext.displayName = "RoomContext"; diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index 6ca009df61..3651e43d7d 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -36,6 +36,7 @@ import { isMac } from '../Keyboard'; import UIFeatureController from "./controllers/UIFeatureController"; import { UIFeature } from "./UIFeature"; import { OrderedMultiController } from "./controllers/OrderedMultiController"; +import {Layout} from "./Layout"; // These are just a bunch of helper arrays to avoid copy/pasting a bunch of times const LEVELS_ROOM_SETTINGS = [ @@ -623,10 +624,9 @@ export const SETTINGS: {[setting: string]: ISetting} = { displayName: _td("IRC display name width"), default: 80, }, - "useIRCLayout": { - supportedLevels: LEVELS_ACCOUNT_SETTINGS, - displayName: _td("Enable experimental, compact IRC style layout"), - default: false, + "layout": { + supportedLevels: LEVELS_ROOM_SETTINGS_WITH_ROOM, + default: Layout.Group, }, "showChatEffects": { supportedLevels: LEVELS_ACCOUNT_SETTINGS, From 90ad3360b628136f4e5dfc69db2c4fd81e07f0aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sun, 24 Jan 2021 09:15:11 +0100 Subject: [PATCH 045/479] Fixed read receipts? MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/rooms/_EventTile.scss | 8 +------- src/components/views/rooms/EventTile.js | 6 +++--- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/res/css/views/rooms/_EventTile.scss b/res/css/views/rooms/_EventTile.scss index 429ac7ed4b..e2cff70841 100644 --- a/res/css/views/rooms/_EventTile.scss +++ b/res/css/views/rooms/_EventTile.scss @@ -258,17 +258,11 @@ $left-gutter: 64px; display: inline-block; width: 14px; height: 14px; - top: 29px; + top: -20px; user-select: none; z-index: 1; } -.mx_EventTile_continuation .mx_EventTile_readAvatars, -.mx_EventTile_info .mx_EventTile_readAvatars, -.mx_EventTile_emote .mx_EventTile_readAvatars { - top: 7px; -} - .mx_EventTile_readAvatars .mx_BaseAvatar { position: absolute; display: inline-block; diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index 4df74f77ce..7a2047af70 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -950,9 +950,6 @@ export default class EventTile extends React.Component { return (
{ ircTimestamp } -
- { readAvatars } -
{ sender } { ircPadlock }
@@ -971,6 +968,9 @@ export default class EventTile extends React.Component { { reactionsRow } { actionBar }
+
+ { readAvatars } +
{ // The avatar goes after the event tile as it's absolutely positioned to be over the // event tile line, so needs to be later in the DOM so it appears on top (this avoids From 7efbd50e316f1d61b6aec98c6b451982e9d509b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 26 Jan 2021 13:30:34 +0100 Subject: [PATCH 046/479] Handle migration from useIRCLayout to layout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- .../handlers/DeviceSettingsHandler.ts | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/settings/handlers/DeviceSettingsHandler.ts b/src/settings/handlers/DeviceSettingsHandler.ts index 2096203598..208a265e04 100644 --- a/src/settings/handlers/DeviceSettingsHandler.ts +++ b/src/settings/handlers/DeviceSettingsHandler.ts @@ -20,6 +20,7 @@ import SettingsHandler from "./SettingsHandler"; import {MatrixClientPeg} from "../../MatrixClientPeg"; import {SettingLevel} from "../SettingLevel"; import { CallbackFn, WatchManager } from "../WatchManager"; +import { Layout } from "../Layout"; /** * Gets and sets settings at the "device" level for the current device. @@ -67,6 +68,13 @@ export default class DeviceSettingsHandler extends SettingsHandler { return val['value']; } + // Special case for old useIRCLayout setting + if (settingName === "layout") { + const settings = this.getSettings() || {}; + if (settings["useIRCLayout"]) return Layout.IRC; + return settings[settingName]; + } + const settings = this.getSettings() || {}; return settings[settingName]; } @@ -106,6 +114,18 @@ export default class DeviceSettingsHandler extends SettingsHandler { return Promise.resolve(); } + // Special case for old useIRCLayout setting + if (settingName === "layout") { + const settings = this.getSettings() || {}; + + delete settings["useIRCLayout"]; + settings["layout"] = newValue; + localStorage.setItem("mx_local_settings", JSON.stringify(settings)); + + this.watchers.notifyUpdate(settingName, null, SettingLevel.DEVICE, newValue); + return Promise.resolve(); + } + const settings = this.getSettings() || {}; settings[settingName] = newValue; localStorage.setItem("mx_local_settings", JSON.stringify(settings)); From 554c18cabdfbf79ce36108392e48cb6e7469a0b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 26 Jan 2021 13:36:47 +0100 Subject: [PATCH 047/479] i18n MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/i18n/strings/en_EN.json | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 274bd247e2..6e34bbdf1e 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -828,7 +828,6 @@ "How fast should messages be downloaded.": "How fast should messages be downloaded.", "Manually verify all remote sessions": "Manually verify all remote sessions", "IRC display name width": "IRC display name width", - "Enable experimental, compact IRC style layout": "Enable experimental, compact IRC style layout", "Show chat effects": "Show chat effects", "Collecting app version information": "Collecting app version information", "Collecting logs": "Collecting logs", @@ -1148,12 +1147,10 @@ "Custom theme URL": "Custom theme URL", "Add theme": "Add theme", "Theme": "Theme", - "Message layout": "Message layout", - "Compact": "Compact", - "Modern": "Modern", "Hide advanced": "Hide advanced", "Show advanced": "Show advanced", "Set the name of a font installed on your system & %(brand)s will attempt to use it.": "Set the name of a font installed on your system & %(brand)s will attempt to use it.", + "Enable experimental, compact IRC style layout": "Enable experimental, compact IRC style layout", "Customise your appearance": "Customise your appearance", "Appearance Settings only affect this %(brand)s session.": "Appearance Settings only affect this %(brand)s session.", "Flair": "Flair", From 5de92b68d954ba3f997f2d5713d954ee05303b2e Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Wed, 27 Jan 2021 11:39:57 +0000 Subject: [PATCH 048/479] Show a specific error for hs_disabled --- src/components/structures/LoggedInView.tsx | 2 +- src/components/structures/RoomStatusBar.js | 4 ++++ src/components/structures/auth/Login.tsx | 3 +++ src/components/structures/auth/Registration.tsx | 1 + src/toasts/ServerLimitToast.tsx | 1 + src/utils/ErrorUtils.js | 1 + 6 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/components/structures/LoggedInView.tsx b/src/components/structures/LoggedInView.tsx index 70ec2b7033..508b7f05e7 100644 --- a/src/components/structures/LoggedInView.tsx +++ b/src/components/structures/LoggedInView.tsx @@ -94,7 +94,7 @@ interface IProps { interface IUsageLimit { // eslint-disable-next-line camelcase - limit_type: "monthly_active_user" | string; + limit_type: "monthly_active_user" | "hs_disabled" | string; // eslint-disable-next-line camelcase admin_contact?: string; } diff --git a/src/components/structures/RoomStatusBar.js b/src/components/structures/RoomStatusBar.js index c1c4ad6292..aa4bceba74 100644 --- a/src/components/structures/RoomStatusBar.js +++ b/src/components/structures/RoomStatusBar.js @@ -195,6 +195,10 @@ export default class RoomStatusBar extends React.Component { "Your message wasn't sent because this homeserver has hit its Monthly Active User Limit. " + "Please contact your service administrator to continue using the service.", ), + 'hs_disabled': _td( + "Your message wasn't sent because this homeserver has been blocked by it's administrator. " + + "Please contact your service administrator to continue using the service.", + ), '': _td( "Your message wasn't sent because this homeserver has exceeded a resource limit. " + "Please contact your service administrator to continue using the service.", diff --git a/src/components/structures/auth/Login.tsx b/src/components/structures/auth/Login.tsx index 606aeb44ab..a9fd363763 100644 --- a/src/components/structures/auth/Login.tsx +++ b/src/components/structures/auth/Login.tsx @@ -218,6 +218,9 @@ export default class LoginComponent extends React.PureComponent 'monthly_active_user': _td( "This homeserver has hit its Monthly Active User limit.", ), + 'hs_blocked': _td( + "This homeserver has been blocked by it's administrator.", + ), '': _td( "This homeserver has exceeded one of its resource limits.", ), diff --git a/src/components/structures/auth/Registration.tsx b/src/components/structures/auth/Registration.tsx index 095f3d3433..f9d338902c 100644 --- a/src/components/structures/auth/Registration.tsx +++ b/src/components/structures/auth/Registration.tsx @@ -276,6 +276,7 @@ export default class Registration extends React.Component { response.data.admin_contact, { 'monthly_active_user': _td("This homeserver has hit its Monthly Active User limit."), + 'hs_blocked': _td("This homeserver has been blocked by it's administrator."), '': _td("This homeserver has exceeded one of its resource limits."), }, ); diff --git a/src/toasts/ServerLimitToast.tsx b/src/toasts/ServerLimitToast.tsx index d35140be3d..9dbe8c05f1 100644 --- a/src/toasts/ServerLimitToast.tsx +++ b/src/toasts/ServerLimitToast.tsx @@ -26,6 +26,7 @@ const TOAST_KEY = "serverlimit"; export const showToast = (limitType: string, adminContact?: string, syncError?: boolean) => { const errorText = messageForResourceLimitError(limitType, adminContact, { 'monthly_active_user': _td("Your homeserver has exceeded its user limit."), + 'hs_blocked': _td("This homeserver has been blocked by it's administrator."), '': _td("Your homeserver has exceeded one of its resource limits."), }); const contactText = messageForResourceLimitError(limitType, adminContact, { diff --git a/src/utils/ErrorUtils.js b/src/utils/ErrorUtils.js index f0a4d7c49e..2c6acd5503 100644 --- a/src/utils/ErrorUtils.js +++ b/src/utils/ErrorUtils.js @@ -62,6 +62,7 @@ export function messageForSyncError(err) { err.data.admin_contact, { 'monthly_active_user': _td("This homeserver has hit its Monthly Active User limit."), + 'hs_blocked': _td("This homeserver has been blocked by its administrator."), '': _td("This homeserver has exceeded one of its resource limits."), }, ); From 27724a93d28d7945e49f94b5fa1158095bd84d8d Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Wed, 27 Jan 2021 11:42:36 +0000 Subject: [PATCH 049/479] new strings --- src/i18n/strings/en_EN.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 8d047ea3f1..e55ab581ca 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -650,6 +650,7 @@ "Unexpected error resolving identity server configuration": "Unexpected error resolving identity server configuration", "The message you are trying to send is too large.": "The message you are trying to send is too large.", "This homeserver has hit its Monthly Active User limit.": "This homeserver has hit its Monthly Active User limit.", + "This homeserver has been blocked by its administrator.": "This homeserver has been blocked by its administrator.", "This homeserver has exceeded one of its resource limits.": "This homeserver has exceeded one of its resource limits.", "Please contact your service administrator to continue using the service.": "Please contact your service administrator to continue using the service.", "Unable to connect to Homeserver. Retrying...": "Unable to connect to Homeserver. Retrying...", @@ -727,6 +728,7 @@ "Enable desktop notifications": "Enable desktop notifications", "Enable": "Enable", "Your homeserver has exceeded its user limit.": "Your homeserver has exceeded its user limit.", + "This homeserver has been blocked by it's administrator.": "This homeserver has been blocked by it's administrator.", "Your homeserver has exceeded one of its resource limits.": "Your homeserver has exceeded one of its resource limits.", "Contact your server admin.": "Contact your server admin.", "Warning": "Warning", @@ -2471,6 +2473,7 @@ "Filter rooms and people": "Filter rooms and people", "You can't send any messages until you review and agree to our terms and conditions.": "You can't send any messages until you review and agree to our terms and conditions.", "Your message wasn't sent because this homeserver has hit its Monthly Active User Limit. Please contact your service administrator to continue using the service.": "Your message wasn't sent because this homeserver has hit its Monthly Active User Limit. Please contact your service administrator to continue using the service.", + "Your message wasn't sent because this homeserver has been blocked by it's administrator. Please contact your service administrator to continue using the service.": "Your message wasn't sent because this homeserver has been blocked by it's administrator. Please contact your service administrator to continue using the service.", "Your message wasn't sent because this homeserver has exceeded a resource limit. Please contact your service administrator to continue using the service.": "Your message wasn't sent because this homeserver has exceeded a resource limit. Please contact your service administrator to continue using the service.", "%(count)s of your messages have not been sent.|other": "Some of your messages have not been sent.", "%(count)s of your messages have not been sent.|one": "Your message was not sent.", From dea1faecfe6b0718268692c4826550d82864229c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 4 Feb 2021 18:15:15 +0100 Subject: [PATCH 050/479] Added license MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/settings/Layout.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/settings/Layout.ts b/src/settings/Layout.ts index bfb86170e8..e8d6e67797 100644 --- a/src/settings/Layout.ts +++ b/src/settings/Layout.ts @@ -1,3 +1,19 @@ +/* +Copyright 2021 Šimon Brandner + +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: This should be later reworked into something more generic */ export enum Layout { IRC = "irc", From 20193ad7fed0f8ccb54b56424820ea431a9fc1e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 5 Feb 2021 08:16:06 +0100 Subject: [PATCH 051/479] Added LayoutPropType MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/settings/Layout.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/settings/Layout.ts b/src/settings/Layout.ts index e8d6e67797..3a42b2b510 100644 --- a/src/settings/Layout.ts +++ b/src/settings/Layout.ts @@ -14,8 +14,13 @@ See the License for the specific language governing permissions and limitations under the License. */ +import PropTypes from 'prop-types'; + /* TODO: This should be later reworked into something more generic */ export enum Layout { IRC = "irc", Group = "group" } + +/* We need this because multiple components are still using JavaScript */ +export const LayoutPropType = PropTypes.oneOf(Object.values(Layout)); From f2d236d429a6272fed848d30b1ae05dc10d89903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 5 Feb 2021 08:17:30 +0100 Subject: [PATCH 052/479] Use LayoutPropType MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/structures/MessagePanel.js | 4 ++-- src/components/structures/TimelinePanel.js | 4 ++-- src/components/views/elements/ReplyThread.js | 4 ++-- src/components/views/rooms/EventTile.js | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index 7b40980714..5e6b94b9f8 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -26,7 +26,7 @@ import * as sdk from '../../index'; import {MatrixClientPeg} from '../../MatrixClientPeg'; import SettingsStore from '../../settings/SettingsStore'; -import {Layout} from "../../settings/Layout"; +import {Layout, LayoutPropType} from "../../settings/Layout"; import {_t} from "../../languageHandler"; import {haveTileForEvent} from "../views/rooms/EventTile"; import {textForEvent} from "../../TextForEvent"; @@ -137,7 +137,7 @@ export default class MessagePanel extends React.Component { showReactions: PropTypes.bool, // which layout to use - layout: Layout, + layout: LayoutPropType, // whether or not to show flair at all enableFlair: PropTypes.bool, diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index 2d322b378d..e8da5c42d0 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -18,7 +18,7 @@ limitations under the License. */ import SettingsStore from "../../settings/SettingsStore"; -import {Layout} from "../../settings/Layout"; +import {LayoutPropType} from "../../settings/Layout"; import React, {createRef} from 'react'; import ReactDOM from "react-dom"; import PropTypes from 'prop-types'; @@ -113,7 +113,7 @@ class TimelinePanel extends React.Component { showReactions: PropTypes.bool, // which layout to use - layout: Layout, + layout: LayoutPropType, } // a map from room id to read marker event timestamp diff --git a/src/components/views/elements/ReplyThread.js b/src/components/views/elements/ReplyThread.js index 74aa715642..27d773b099 100644 --- a/src/components/views/elements/ReplyThread.js +++ b/src/components/views/elements/ReplyThread.js @@ -24,7 +24,7 @@ import {wantsDateSeparator} from '../../../DateUtils'; import {MatrixEvent} from 'matrix-js-sdk'; import {makeUserPermalink, RoomPermalinkCreator} from "../../../utils/permalinks/Permalinks"; import SettingsStore from "../../../settings/SettingsStore"; -import {Layout} from "../../../settings/Layout"; +import {LayoutPropType} from "../../../settings/Layout"; import escapeHtml from "escape-html"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; import {Action} from "../../../dispatcher/actions"; @@ -43,7 +43,7 @@ export default class ReplyThread extends React.Component { onHeightChanged: PropTypes.func.isRequired, permalinkCreator: PropTypes.instanceOf(RoomPermalinkCreator).isRequired, // Specifies which layout to use. - layout: Layout, + layout: LayoutPropType, }; static contextType = MatrixClientContext; diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index 17ba61732a..bb10825b6e 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -27,7 +27,7 @@ import * as TextForEvent from "../../../TextForEvent"; import * as sdk from "../../../index"; import dis from '../../../dispatcher/dispatcher'; import SettingsStore from "../../../settings/SettingsStore"; -import {Layout} from "../../../settings/Layout"; +import {Layout, LayoutPropType} from "../../../settings/Layout"; import {EventStatus} from 'matrix-js-sdk'; import {formatTime} from "../../../DateUtils"; import {MatrixClientPeg} from '../../../MatrixClientPeg'; @@ -227,7 +227,7 @@ export default class EventTile extends React.Component { showReactions: PropTypes.bool, // which layout to use - layout: Layout, + layout: LayoutPropType, // whether or not to show flair at all enableFlair: PropTypes.bool, From cc38bcf333bc9fdd7d8ebc7d0b4d06330ba7e359 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sat, 6 Feb 2021 15:09:21 +0100 Subject: [PATCH 053/479] Display room name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/elements/Pill.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/elements/Pill.js b/src/components/views/elements/Pill.js index daa4cb70e2..f1527c48b1 100644 --- a/src/components/views/elements/Pill.js +++ b/src/components/views/elements/Pill.js @@ -226,7 +226,7 @@ class Pill extends React.Component { case Pill.TYPE_ROOM_MENTION: { const room = this.state.room; if (room) { - linkText = resource; + linkText = room.name; if (this.props.shouldShowPillAvatar) { avatar =
); } From e6da146b21c3e4df169cf90a189cb700ab8ac052 Mon Sep 17 00:00:00 2001 From: William Kray Date: Sun, 29 Nov 2020 16:53:50 -0800 Subject: [PATCH 061/479] pad url preview close button a bit --- res/css/views/rooms/_LinkPreviewWidget.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/res/css/views/rooms/_LinkPreviewWidget.scss b/res/css/views/rooms/_LinkPreviewWidget.scss index d06cd65502..27453cf352 100644 --- a/res/css/views/rooms/_LinkPreviewWidget.scss +++ b/res/css/views/rooms/_LinkPreviewWidget.scss @@ -57,6 +57,7 @@ limitations under the License. cursor: pointer; width: 18px; height: 18px; + padding: 0px 5px 5px 5px; img { flex: 0 0 40px; From fec230945129dea9074547b24e24112a4b658eb2 Mon Sep 17 00:00:00 2001 From: William Kray Date: Fri, 29 Jan 2021 01:30:08 -0800 Subject: [PATCH 062/479] move cancel button to the right --- res/css/views/rooms/_LinkPreviewWidget.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/res/css/views/rooms/_LinkPreviewWidget.scss b/res/css/views/rooms/_LinkPreviewWidget.scss index 27453cf352..5310bd3bbb 100644 --- a/res/css/views/rooms/_LinkPreviewWidget.scss +++ b/res/css/views/rooms/_LinkPreviewWidget.scss @@ -58,6 +58,8 @@ limitations under the License. width: 18px; height: 18px; padding: 0px 5px 5px 5px; + margin-left: auto; + margin-right: 0px; img { flex: 0 0 40px; From 392b47e200c91773144e68d86aaaf0e5e6dc33d2 Mon Sep 17 00:00:00 2001 From: PunitLodha Date: Tue, 9 Feb 2021 11:39:36 +0530 Subject: [PATCH 063/479] Add email only if the verification is complete --- .../views/settings/account/EmailAddresses.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/components/views/settings/account/EmailAddresses.js b/src/components/views/settings/account/EmailAddresses.js index ca66d5df65..07d2133e95 100644 --- a/src/components/views/settings/account/EmailAddresses.js +++ b/src/components/views/settings/account/EmailAddresses.js @@ -178,19 +178,21 @@ export default class EmailAddresses extends React.Component { e.preventDefault(); this.setState({continueDisabled: true}); - this.state.addTask.checkEmailLinkClicked().then(() => { - const email = this.state.newEmailAddress; + this.state.addTask.checkEmailLinkClicked().then(([finished]) => { + if (finished) { + const email = this.state.newEmailAddress; + const emails = [ + ...this.props.emails, + { address: email, medium: "email" }, + ]; + this.props.onEmailsChange(emails); + } this.setState({ addTask: null, continueDisabled: false, verifying: false, newEmailAddress: "", }); - const emails = [ - ...this.props.emails, - { address: email, medium: "email" }, - ]; - this.props.onEmailsChange(emails); }).catch((err) => { this.setState({continueDisabled: false}); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); From 673717d6c0675c6756beba822f679af9b8375214 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Wed, 10 Feb 2021 15:57:57 +0000 Subject: [PATCH 064/479] Upgrade matrix-js-sdk to 9.7.0-rc.1 --- package.json | 2 +- yarn.lock | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 2263c7de32..65201a1083 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "katex": "^0.12.0", "linkifyjs": "^2.1.9", "lodash": "^4.17.20", - "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop", + "matrix-js-sdk": "9.7.0-rc.1", "matrix-widget-api": "^0.1.0-beta.13", "minimist": "^1.2.5", "pako": "^2.0.3", diff --git a/yarn.lock b/yarn.lock index 1a350f697a..e3d7a5ac28 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5577,9 +5577,10 @@ mathml-tag-names@^2.1.3: resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3" integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg== -"matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop": - version "9.6.0" - resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/6ad3fb16b3813c717943f6bc8bca5a55fe325477" +matrix-js-sdk@9.7.0-rc.1: + version "9.7.0-rc.1" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-9.7.0-rc.1.tgz#30cabda3f2b416d09c95afc4fe138bba44534c76" + integrity sha512-y6D2bXYKQqGrtf1PLHjjHf6wW67DIhdrwQ77nKOhEd/rfaEqcMf99wqSvF/nzFexbG1Y7PG4IdM4YTdOQ9UD+g== dependencies: "@babel/runtime" "^7.12.5" another-json "^0.2.0" From 1dfbc73d4adcced75a258ecc55b9adc09770c303 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Wed, 10 Feb 2021 16:51:52 +0000 Subject: [PATCH 065/479] Prepare changelog for v3.14.0-rc.1 --- CHANGELOG.md | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 43a1494497..50880b1d53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,79 @@ +Changes in [3.14.0-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.14.0-rc.1) (2021-02-10) +=============================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v3.13.1...v3.14.0-rc.1) + + * Upgrade to JS SDK 9.7.0-rc.1 + * Translations update from Weblate + [\#5636](https://github.com/matrix-org/matrix-react-sdk/pull/5636) + * Add host signup modal with iframe + [\#5450](https://github.com/matrix-org/matrix-react-sdk/pull/5450) + * Fix duplication of codeblock elements + [\#5633](https://github.com/matrix-org/matrix-react-sdk/pull/5633) + * Handle undefined call stats + [\#5632](https://github.com/matrix-org/matrix-react-sdk/pull/5632) + * Avoid delayed displaying of sources in source picker + [\#5631](https://github.com/matrix-org/matrix-react-sdk/pull/5631) + * Give breadcrumbs toolbar an accessibility label. + [\#5628](https://github.com/matrix-org/matrix-react-sdk/pull/5628) + * Fix the %s in logs + [\#5627](https://github.com/matrix-org/matrix-react-sdk/pull/5627) + * Fix jumpy notifications settings UI + [\#5625](https://github.com/matrix-org/matrix-react-sdk/pull/5625) + * Improve displaying of code blocks + [\#5559](https://github.com/matrix-org/matrix-react-sdk/pull/5559) + * Fix desktop Matrix screen sharing and add a screen/window picker + [\#5525](https://github.com/matrix-org/matrix-react-sdk/pull/5525) + * Call "MatrixClientPeg.get()" only once in method "findOverrideMuteRule" + [\#5498](https://github.com/matrix-org/matrix-react-sdk/pull/5498) + * Close current modal when session is logged out + [\#5616](https://github.com/matrix-org/matrix-react-sdk/pull/5616) + * Switch room explorer list to CSS grid + [\#5551](https://github.com/matrix-org/matrix-react-sdk/pull/5551) + * Improve SSO login start screen and 3pid invite handling somewhat + [\#5622](https://github.com/matrix-org/matrix-react-sdk/pull/5622) + * Don't jump to bottom on reaction + [\#5621](https://github.com/matrix-org/matrix-react-sdk/pull/5621) + * Fix several profile settings oddities + [\#5620](https://github.com/matrix-org/matrix-react-sdk/pull/5620) + * Add option to hide the stickers button in the composer + [\#5530](https://github.com/matrix-org/matrix-react-sdk/pull/5530) + * Fix confusing right panel button behaviour + [\#5598](https://github.com/matrix-org/matrix-react-sdk/pull/5598) + * Fix jumping timestamp if hovering a message with e2e indicator bar + [\#5601](https://github.com/matrix-org/matrix-react-sdk/pull/5601) + * Fix avatar and trash alignment + [\#5614](https://github.com/matrix-org/matrix-react-sdk/pull/5614) + * Fix z-index of stickerpicker + [\#5617](https://github.com/matrix-org/matrix-react-sdk/pull/5617) + * Fix permalink via parsing for rooms + [\#5615](https://github.com/matrix-org/matrix-react-sdk/pull/5615) + * Fix "Terms and Conditions" checkbox alignment + [\#5613](https://github.com/matrix-org/matrix-react-sdk/pull/5613) + * Fix flair height after accent changes + [\#5611](https://github.com/matrix-org/matrix-react-sdk/pull/5611) + * Iterate Social Logins work around edge cases and branding + [\#5609](https://github.com/matrix-org/matrix-react-sdk/pull/5609) + * Lock widget room ID when added + [\#5607](https://github.com/matrix-org/matrix-react-sdk/pull/5607) + * Better errors for SSO failures + [\#5605](https://github.com/matrix-org/matrix-react-sdk/pull/5605) + * Increase language search bar width + [\#5549](https://github.com/matrix-org/matrix-react-sdk/pull/5549) + * Scroll to bottom on message_sent + [\#5565](https://github.com/matrix-org/matrix-react-sdk/pull/5565) + * Fix new rooms being titled 'Empty Room' + [\#5587](https://github.com/matrix-org/matrix-react-sdk/pull/5587) + * Fix saving the collapsed state of the left panel + [\#5593](https://github.com/matrix-org/matrix-react-sdk/pull/5593) + * Fix app-url hint in the e2e-test run script output + [\#5600](https://github.com/matrix-org/matrix-react-sdk/pull/5600) + * Fix RoomView re-mounting breaking peeking + [\#5602](https://github.com/matrix-org/matrix-react-sdk/pull/5602) + * Tweak a few room ID checks + [\#5592](https://github.com/matrix-org/matrix-react-sdk/pull/5592) + * Remove pills from event permalinks with text + [\#5575](https://github.com/matrix-org/matrix-react-sdk/pull/5575) + Changes in [3.13.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.13.1) (2021-02-04) ===================================================================================================== [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v3.13.0...v3.13.1) From d1524b2e9d243806e2ab55ebc414f2c17609629d Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Wed, 10 Feb 2021 16:51:52 +0000 Subject: [PATCH 066/479] v3.14.0-rc.1 --- package.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 65201a1083..5beb383791 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "3.13.1", + "version": "3.14.0-rc.1", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { @@ -27,7 +27,7 @@ "matrix-gen-i18n": "scripts/gen-i18n.js", "matrix-prune-i18n": "scripts/prune-i18n.js" }, - "main": "./src/index.js", + "main": "./lib/index.js", "matrix_src_main": "./src/index.js", "matrix_lib_main": "./lib/index.js", "matrix_lib_typings": "./lib/index.d.ts", @@ -190,5 +190,6 @@ "transformIgnorePatterns": [ "/node_modules/(?!matrix-js-sdk).+$" ] - } + }, + "typings": "./lib/index.d.ts" } From a61462bc8559815a4ea08d599268b773b681483c Mon Sep 17 00:00:00 2001 From: Hubert Chathi Date: Thu, 11 Feb 2021 16:34:15 -0500 Subject: [PATCH 067/479] use the default SSSS key if the default is set implements MSC2874 --- src/SecurityManager.ts | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/SecurityManager.ts b/src/SecurityManager.ts index 220320470a..11d228e7ab 100644 --- a/src/SecurityManager.ts +++ b/src/SecurityManager.ts @@ -98,11 +98,24 @@ async function getSecretStorageKey( { keys: keyInfos }: { keys: Record }, ssssItemName, ): Promise<[string, Uint8Array]> { - const keyInfoEntries = Object.entries(keyInfos); - if (keyInfoEntries.length > 1) { - throw new Error("Multiple storage key requests not implemented"); + const cli = MatrixClientPeg.get(); + let keyId = await cli.getDefaultSecretStorageKeyId(); + let keyInfo; + if (keyId) { + // use the default SSSS key if set + keyInfo = keyInfos[keyId]; + if (!keyInfo) { + throw new Error("Unable to use default SSSS key"); + } + } else { + // if no default SSSS key is set, fall back to a heuristic of using the + // only available key, if only one key is set + const keyInfoEntries = Object.entries(keyInfos); + if (keyInfoEntries.length > 1) { + throw new Error("Multiple storage key requests not implemented"); + } + [keyId, keyInfo] = keyInfoEntries[0]; } - const [keyId, keyInfo] = keyInfoEntries[0]; // Check the in-memory cache if (isCachingAllowed() && secretStorageKeys[keyId]) { From 33979b335446bf16bd02815ae88de7241540ed74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 12 Feb 2021 08:18:27 +0100 Subject: [PATCH 068/479] Added a tooltip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/elements/Pill.js | 39 +++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/src/components/views/elements/Pill.js b/src/components/views/elements/Pill.js index cbbe562754..5b3189f389 100644 --- a/src/components/views/elements/Pill.js +++ b/src/components/views/elements/Pill.js @@ -26,6 +26,7 @@ import FlairStore from "../../../stores/FlairStore"; import {getPrimaryPermalinkEntity, parseAppLocalLink} from "../../../utils/permalinks/Permalinks"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; import {Action} from "../../../dispatcher/actions"; +import Tooltip from './Tooltip'; class Pill extends React.Component { static roomNotifPos(text) { @@ -68,6 +69,8 @@ class Pill extends React.Component { group: null, // The room related to the room pill room: null, + // Is the user hovering the pill + hover: false, }; // TODO: [REACT-WARNING] Replace with appropriate lifecycle event @@ -154,6 +157,18 @@ class Pill extends React.Component { this._unmounted = true; } + onMouseOver = () => { + this.setState({ + hover: true, + }); + }; + + onMouseLeave = () => { + this.setState({ + hover: false, + }); + }; + doProfileLookup(userId, member) { MatrixClientPeg.get().getProfileInfo(userId).then((resp) => { if (this._unmounted) { @@ -256,16 +271,36 @@ class Pill extends React.Component { }); if (this.state.pillType) { + const {yOffset} = this.props; + + let tip; + if (this.state.hover) { + tip = ; + } + return { this.props.inMessage ? - + { avatar } { linkText } : - + { avatar } { linkText } } + {tip} ; } else { // Deliberately render nothing if the URL isn't recognised From a975de22efca2302aa5302b5d0142aafd235a701 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 12 Feb 2021 11:27:14 +0100 Subject: [PATCH 069/479] Fixed buggy tooltip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/elements/Pill.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/views/elements/Pill.js b/src/components/views/elements/Pill.js index 5b3189f389..68a87d40b9 100644 --- a/src/components/views/elements/Pill.js +++ b/src/components/views/elements/Pill.js @@ -290,6 +290,7 @@ class Pill extends React.Component { > { avatar } { linkText } + { tip } : { avatar } { linkText } + { tip } } - {tip} ; } else { // Deliberately render nothing if the URL isn't recognised From a075568e895c0e2b3e9e83c710cbc9c510b488bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 12 Feb 2021 11:34:09 +0100 Subject: [PATCH 070/479] Fixed tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the previous commits I have removed the native title/tooltip so it needs to be removed from the tests as well Signed-off-by: Šimon Brandner --- test/components/views/messages/TextualBody-test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/components/views/messages/TextualBody-test.js b/test/components/views/messages/TextualBody-test.js index d5b80b6756..a596825c09 100644 --- a/test/components/views/messages/TextualBody-test.js +++ b/test/components/views/messages/TextualBody-test.js @@ -208,7 +208,7 @@ describe("", () => { const content = wrapper.find(".mx_EventTile_body"); expect(content.html()).toBe('' + 'Hey ' + - '' + + '' + 'Member' + ''); @@ -267,8 +267,8 @@ describe("", () => { expect(content.html()).toBe( '' + 'A ' + '!ZxbRYPQXDXKGmDnJNg:example.com with vias', From cb5237a18be0bf17eede4768f8978dfc44e7c609 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 12 Feb 2021 14:21:07 +0100 Subject: [PATCH 071/479] Display room name instead of alias MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/editor/parts.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/editor/parts.ts b/src/editor/parts.ts index 8a7ccfcb7b..67f6a2c0c5 100644 --- a/src/editor/parts.ts +++ b/src/editor/parts.ts @@ -329,8 +329,8 @@ class NewlinePart extends BasePart implements IBasePart { } class RoomPillPart extends PillPart { - constructor(displayAlias, private room: Room) { - super(displayAlias, displayAlias); + constructor(resourceId: string, label: string, private room: Room) { + super(resourceId, label); } setAvatar(node: HTMLElement) { @@ -357,6 +357,10 @@ class RoomPillPart extends PillPart { } class AtRoomPillPart extends RoomPillPart { + constructor(text: string, room: Room) { + super(text, text, room); + } + get type(): IPillPart["type"] { return Type.AtRoomPill; } @@ -521,7 +525,7 @@ export class PartCreator { r.getAltAliases().includes(alias); }); } - return new RoomPillPart(alias, room); + return new RoomPillPart(alias, room ? room.name : alias, room); } atRoomPill(text: string) { From d8a9b84af94fac4321d700a9c9bfee29763e7fd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 12 Feb 2021 14:28:39 +0100 Subject: [PATCH 072/479] Don't show tooltip if there is nothing to display MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We do this because resource is undefined for @room Signed-off-by: Šimon Brandner --- src/components/views/elements/Pill.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/elements/Pill.js b/src/components/views/elements/Pill.js index 68a87d40b9..c6806c289e 100644 --- a/src/components/views/elements/Pill.js +++ b/src/components/views/elements/Pill.js @@ -274,7 +274,7 @@ class Pill extends React.Component { const {yOffset} = this.props; let tip; - if (this.state.hover) { + if (this.state.hover && resource) { tip = ; } From 17f09d3b7a4eb800d0d2076cc906500aeb914cc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 12 Feb 2021 15:16:07 +0100 Subject: [PATCH 073/479] Added onIsEmptyChanged prop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/SendMessageComposer.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/components/views/rooms/SendMessageComposer.js b/src/components/views/rooms/SendMessageComposer.js index 553fb44c04..99761ec8ba 100644 --- a/src/components/views/rooms/SendMessageComposer.js +++ b/src/components/views/rooms/SendMessageComposer.js @@ -117,6 +117,7 @@ export default class SendMessageComposer extends React.Component { placeholder: PropTypes.string, permalinkCreator: PropTypes.object.isRequired, replyToEvent: PropTypes.object, + onIsEmptyChanged: PropTypes.func, }; static contextType = MatrixClientContext; @@ -534,10 +535,15 @@ export default class SendMessageComposer extends React.Component { } } + onChange = () => { + this.props.onIsEmptyChanged(this.model.isEmpty); + } + render() { return (
Date: Fri, 12 Feb 2021 15:35:04 +0100 Subject: [PATCH 074/479] Extract send button into a function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/MessageComposer.js | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 9683c4c79e..0ea5d80c92 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -50,6 +50,22 @@ ComposerAvatar.propTypes = { me: PropTypes.object.isRequired, }; +function SendButton(props) { + return ( +
+ +
+ ); +} + +SendButton.propTypes = { + onClick: PropTypes.func.isRequired, +}; + function CallButton(props) { const onVoiceCallClick = (ev) => { dis.dispatch({ @@ -466,13 +482,9 @@ export default class MessageComposer extends React.Component { } if (this.state.showSendButton) { - controls.push(( - - )); + controls.push( + , + ); } } else if (this.state.tombstone) { const replacementRoomId = this.state.tombstone.getContent()['replacement_room']; From 42a48ee27d8e902e7f4835d8e221ae530af76570 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 12 Feb 2021 15:39:54 +0100 Subject: [PATCH 075/479] Added composerEmpty property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/MessageComposer.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 0ea5d80c92..8c13fa4dc8 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -282,6 +282,7 @@ export default class MessageComposer extends React.Component { showSendButton: SettingsStore.getValue("MessageComposerInput.showSendButton"), hasConference: WidgetStore.instance.doesRoomHaveConference(this.props.room), joinedConference: WidgetStore.instance.isJoinedToConferenceIn(this.props.room), + composerEmpty: true, }; } @@ -423,6 +424,12 @@ export default class MessageComposer extends React.Component { this.messageComposerInput._sendMessage(); } + onIsEmptyChanged = (isEmpty) => { + this.setState({ + composerEmpty: isEmpty, + }); + } + render() { const controls = [ this.state.me ? : null, @@ -448,6 +455,7 @@ export default class MessageComposer extends React.Component { resizeNotifier={this.props.resizeNotifier} permalinkCreator={this.props.permalinkCreator} replyToEvent={this.props.replyToEvent} + onIsEmptyChanged={this.onIsEmptyChanged} />, , , From 50b0a78132298fb906976b4f1e2824f1195c1fb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 12 Feb 2021 15:41:43 +0100 Subject: [PATCH 076/479] Renamed composerEmpty to isComposerEmpty MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/MessageComposer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 8c13fa4dc8..7918243631 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -282,7 +282,7 @@ export default class MessageComposer extends React.Component { showSendButton: SettingsStore.getValue("MessageComposerInput.showSendButton"), hasConference: WidgetStore.instance.doesRoomHaveConference(this.props.room), joinedConference: WidgetStore.instance.isJoinedToConferenceIn(this.props.room), - composerEmpty: true, + isComposerEmpty: true, }; } @@ -426,7 +426,7 @@ export default class MessageComposer extends React.Component { onIsEmptyChanged = (isEmpty) => { this.setState({ - composerEmpty: isEmpty, + isComposerEmpty: isEmpty, }); } From 35c0cb99d04690f2465f7b4eb69aa5b006ccd7e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 12 Feb 2021 15:42:30 +0100 Subject: [PATCH 077/479] Use isComposerEmpty for send button MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/MessageComposer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 7918243631..61d61b8f42 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -489,7 +489,7 @@ export default class MessageComposer extends React.Component { } } - if (this.state.showSendButton) { + if (!this.state.isComposerEmpty) { controls.push( , ); From ba2c68819f9d2108efb6d44ff1afe73397b4feae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 12 Feb 2021 15:42:59 +0100 Subject: [PATCH 078/479] Removed showSendButton setting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/MessageComposer.js | 10 ---------- .../settings/tabs/user/PreferencesUserSettingsTab.js | 1 - src/settings/Settings.ts | 5 ----- 3 files changed, 16 deletions(-) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index 61d61b8f42..f6fc8af55d 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -279,7 +279,6 @@ export default class MessageComposer extends React.Component { tombstone: this._getRoomTombstone(), canSendMessages: this.props.room.maySendMessage(), showCallButtons: SettingsStore.getValue("showCallButtonsInComposer"), - showSendButton: SettingsStore.getValue("MessageComposerInput.showSendButton"), hasConference: WidgetStore.instance.doesRoomHaveConference(this.props.room), joinedConference: WidgetStore.instance.isJoinedToConferenceIn(this.props.room), isComposerEmpty: true, @@ -298,12 +297,6 @@ export default class MessageComposer extends React.Component { } }; - onShowSendButtonChanged = () => { - this.setState({ - showSendButton: SettingsStore.getValue("MessageComposerInput.showSendButton"), - }); - } - _onWidgetUpdate = () => { this.setState({hasConference: WidgetStore.instance.doesRoomHaveConference(this.props.room)}); }; @@ -316,8 +309,6 @@ export default class MessageComposer extends React.Component { this.dispatcherRef = dis.register(this.onAction); MatrixClientPeg.get().on("RoomState.events", this._onRoomStateEvents); this._waitForOwnMember(); - this.showSendButtonRef = SettingsStore.watchSetting( - "MessageComposerInput.showSendButton", null, this.onShowSendButtonChanged); } _waitForOwnMember() { @@ -343,7 +334,6 @@ export default class MessageComposer extends React.Component { WidgetStore.instance.removeListener(UPDATE_EVENT, this._onWidgetUpdate); ActiveWidgetStore.removeListener('update', this._onActiveWidgetUpdate); dis.unregister(this.dispatcherRef); - SettingsStore.unwatchSetting(this.showSendButtonRef); } _onRoomStateEvents(ev, state) { diff --git a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js index eff0824d59..4d8493401e 100644 --- a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js @@ -34,7 +34,6 @@ export default class PreferencesUserSettingsTab extends React.Component { 'MessageComposerInput.suggestEmoji', 'sendTypingNotifications', 'MessageComposerInput.ctrlEnterToSend', - `MessageComposerInput.showSendButton`, ]; static TIMELINE_SETTINGS = [ diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index 2d8385240c..b239b809fe 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -336,11 +336,6 @@ export const SETTINGS: {[setting: string]: ISetting} = { displayName: isMac ? _td("Use Command + Enter to send a message") : _td("Use Ctrl + Enter to send a message"), default: false, }, - "MessageComposerInput.showSendButton": { - supportedLevels: LEVELS_ACCOUNT_SETTINGS, - displayName: _td("Show send message button"), - default: false, - }, "MessageComposerInput.autoReplaceEmoji": { supportedLevels: LEVELS_ACCOUNT_SETTINGS, displayName: _td('Automatically replace plain text Emoji'), From daff94ecbcdfb1592c483112289412296c8720b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 12 Feb 2021 15:47:33 +0100 Subject: [PATCH 079/479] i18n MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/i18n/strings/en_EN.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 6baccf95de..27ec207dda 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -799,7 +799,6 @@ "Show typing notifications": "Show typing notifications", "Use Command + Enter to send a message": "Use Command + Enter to send a message", "Use Ctrl + Enter to send a message": "Use Ctrl + Enter to send a message", - "Show send message button": "Show send message button", "Automatically replace plain text Emoji": "Automatically replace plain text Emoji", "Mirror local video feed": "Mirror local video feed", "Enable Community Filter Panel": "Enable Community Filter Panel", @@ -1404,6 +1403,7 @@ "Invited": "Invited", "Filter room members": "Filter room members", "%(userName)s (power %(powerLevelNumber)s)": "%(userName)s (power %(powerLevelNumber)s)", + "Send message": "Send message", "Voice call": "Voice call", "Video call": "Video call", "Hangup": "Hangup", @@ -1413,7 +1413,6 @@ "Send a reply…": "Send a reply…", "Send an encrypted message…": "Send an encrypted message…", "Send a message…": "Send a message…", - "Send message": "Send message", "The conversation continues here.": "The conversation continues here.", "This room has been replaced and is no longer active.": "This room has been replaced and is no longer active.", "You do not have permission to post to this room": "You do not have permission to post to this room", From b26951714938a40a73f23c77db44d4a2b98769bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 12 Feb 2021 15:52:42 +0100 Subject: [PATCH 080/479] Removed wrapper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/MessageComposer.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index f6fc8af55d..a78cf323c6 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -52,13 +52,11 @@ ComposerAvatar.propTypes = { function SendButton(props) { return ( -
- -
+ ); } From 97f5b6920c8d25588390aa6ff2c6f9dd54b379e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 12 Feb 2021 16:48:46 +0100 Subject: [PATCH 081/479] Check if the method is defined before calling it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/SendMessageComposer.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/views/rooms/SendMessageComposer.js b/src/components/views/rooms/SendMessageComposer.js index ca27141c02..9a14e33d05 100644 --- a/src/components/views/rooms/SendMessageComposer.js +++ b/src/components/views/rooms/SendMessageComposer.js @@ -538,7 +538,9 @@ export default class SendMessageComposer extends React.Component { } onChange = () => { - this.props.onIsEmptyChanged(this.model.isEmpty); + if (this.props.onIsEmptyChanged) { + this.props.onIsEmptyChanged(this.model.isEmpty); + } } render() { From 130e4f7bfddffb48d35a4a5a5adaf090d889905b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 12 Feb 2021 17:06:02 +0100 Subject: [PATCH 082/479] Added some styling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/rooms/_MessageComposer.scss | 26 +++++++++++++++++-- src/components/views/rooms/MessageComposer.js | 2 +- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/res/css/views/rooms/_MessageComposer.scss b/res/css/views/rooms/_MessageComposer.scss index 8b34318f1d..c24e4912d4 100644 --- a/res/css/views/rooms/_MessageComposer.scss +++ b/res/css/views/rooms/_MessageComposer.scss @@ -247,8 +247,30 @@ limitations under the License. mask-image: url('$(res)/img/element-icons/room/composer/sticker.svg'); } -.mx_MessageComposer_sendMessage::before { - mask-image: url('$(res)/img/element-icons/send-message.svg'); +.mx_MessageComposer_sendMessage { + cursor: pointer; + position: relative; + margin-right: 6px; + width: 32px; + height: 32px; + border-radius: 100%; + background-color: $button-bg-color; + + &:before { + position: absolute; + height: 16px; + width: 16px; + top: 8px; + left: 9px; + + mask-image: url('$(res)/img/element-icons/send-message.svg'); + mask-repeat: no-repeat; + mask-size: contain; + mask-position: center; + + background-color: $button-fg-color; + content: ''; + } } .mx_MessageComposer_formatting { diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index d023d334c3..d70f273be2 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -53,7 +53,7 @@ ComposerAvatar.propTypes = { function SendButton(props) { return ( From 3983c15302772ebfd3bc04670bf4d3dd7b7b1762 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 12 Feb 2021 17:11:24 +0100 Subject: [PATCH 083/479] Delint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/rooms/_MessageComposer.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/css/views/rooms/_MessageComposer.scss b/res/css/views/rooms/_MessageComposer.scss index c24e4912d4..2789ffdfb7 100644 --- a/res/css/views/rooms/_MessageComposer.scss +++ b/res/css/views/rooms/_MessageComposer.scss @@ -256,7 +256,7 @@ limitations under the License. border-radius: 100%; background-color: $button-bg-color; - &:before { + &::before { position: absolute; height: 16px; width: 16px; From 196507a730a6e64665fbac54f2d1c682c311783d Mon Sep 17 00:00:00 2001 From: David Baker Date: Fri, 12 Feb 2021 20:55:54 +0000 Subject: [PATCH 084/479] VoIP virtual rooms, mk II Does a thirdparty protocol lookup to the homeserver to get the corresponding native/virtual user for a matrix ID. Stores the mappings in room account data. Involves some slightly nasty workarounds for that fact that room account data has no local echo. --- src/@types/global.d.ts | 2 + src/CallHandler.tsx | 88 +++++++++--- src/SlashCommands.tsx | 4 +- src/VoipUserMapper.ts | 127 +++++++++++------- src/components/views/voip/DialPadModal.tsx | 5 +- src/dispatcher/actions.ts | 7 + src/stores/room-list/RoomListStore.ts | 37 +++++ .../room-list/filters/VisibilityProvider.ts | 8 +- test/VoipUserMapper-test.ts | 31 ----- 9 files changed, 208 insertions(+), 101 deletions(-) delete mode 100644 test/VoipUserMapper-test.ts diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts index 2a28c8e43f..28f22780a2 100644 --- a/src/@types/global.d.ts +++ b/src/@types/global.d.ts @@ -37,6 +37,7 @@ import CountlyAnalytics from "../CountlyAnalytics"; import UserActivity from "../UserActivity"; import {ModalWidgetStore} from "../stores/ModalWidgetStore"; import { WidgetLayoutStore } from "../stores/widgets/WidgetLayoutStore"; +import VoipUserMapper from "../VoipUserMapper"; declare global { interface Window { @@ -66,6 +67,7 @@ declare global { mxCountlyAnalytics: typeof CountlyAnalytics; mxUserActivity: UserActivity; mxModalWidgetStore: ModalWidgetStore; + mxVoipUserMapper: VoipUserMapper; } interface Document { diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index a6d3534fa1..ca9f96c7c2 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -84,10 +84,17 @@ import { CallError } from "matrix-js-sdk/src/webrtc/call"; import { logger } from 'matrix-js-sdk/src/logger'; import DesktopCapturerSourcePicker from "./components/views/elements/DesktopCapturerSourcePicker" import { Action } from './dispatcher/actions'; -import { roomForVirtualRoom, getOrCreateVirtualRoomForRoom } from './VoipUserMapper'; +import VoipUserMapper from './VoipUserMapper'; import { addManagedHybridWidget, isManagedHybridWidgetEnabled } from './widgets/ManagedHybrid'; -const CHECK_PSTN_SUPPORT_ATTEMPTS = 3; +export const PROTOCOL_PSTN = 'm.protocol.pstn'; +export const PROTOCOL_PSTN_PREFIXED = 'im.vector.protocol.pstn'; +export const PROTOCOL_SIP_NATIVE = 'im.vector.protocol.sip_native'; +export const PROTOCOL_SIP_VIRTUAL = 'im.vector.protocol.sip_virtual'; + +const CHECK_PROTOCOLS_ATTEMPTS = 3; +// Event type for room account data used to mark rooms as virtual rooms (and store the ID of their native room) +export const VIRTUAL_ROOM_EVENT_TYPE = 'im.vector.is_virtual_room'; enum AudioID { Ring = 'ringAudio', @@ -96,6 +103,12 @@ enum AudioID { Busy = 'busyAudio', } +interface ThirpartyLookupResponse { + userid: string, + protocol: string, + fields: {[key: string]: any}, +} + // Unlike 'CallType' in js-sdk, this one includes screen sharing // (because a screen sharing call is only a screen sharing call to the caller, // to the callee it's just a video call, at least as far as the current impl @@ -126,7 +139,12 @@ export default class CallHandler { private audioPromises = new Map>(); private dispatcherRef: string = null; private supportsPstnProtocol = null; + private pstnSupportPrefixed = null; // True if the server only support the prefixed pstn protocol + private supportsSipNativeVirtual = null; // im.vector.protocol.sip_virtual and im.vector.protocol.sip_native private pstnSupportCheckTimer: NodeJS.Timeout; // number actually because we're in the browser + // For rooms we've been invited to, true if they're from virtual user, false if we've checked and they aren't. + private invitedRoomsAreVirtual = new Map(); + private invitedRoomCheckInProgress = false; static sharedInstance() { if (!window.mxCallHandler) { @@ -140,9 +158,9 @@ export default class CallHandler { * Gets the user-facing room associated with a call (call.roomId may be the call "virtual room" * if a voip_mxid_translate_pattern is set in the config) */ - public static roomIdForCall(call: MatrixCall) { + public static roomIdForCall(call: MatrixCall): string { if (!call) return null; - return roomForVirtualRoom(call.roomId) || call.roomId; + return VoipUserMapper.sharedInstance().nativeRoomForVirtualRoom(call.roomId) || call.roomId; } start() { @@ -163,7 +181,7 @@ export default class CallHandler { MatrixClientPeg.get().on('Call.incoming', this.onCallIncoming); } - this.checkForPstnSupport(CHECK_PSTN_SUPPORT_ATTEMPTS); + this.checkProtocols(CHECK_PROTOCOLS_ATTEMPTS); } stop() { @@ -177,33 +195,73 @@ export default class CallHandler { } } - private async checkForPstnSupport(maxTries) { + private async checkProtocols(maxTries) { try { const protocols = await MatrixClientPeg.get().getThirdpartyProtocols(); - if (protocols['im.vector.protocol.pstn'] !== undefined) { - this.supportsPstnProtocol = protocols['im.vector.protocol.pstn']; - } else if (protocols['m.protocol.pstn'] !== undefined) { - this.supportsPstnProtocol = protocols['m.protocol.pstn']; + + if (protocols[PROTOCOL_PSTN] !== undefined) { + this.supportsPstnProtocol = Boolean(protocols[PROTOCOL_PSTN]); + if (this.supportsPstnProtocol) this.pstnSupportPrefixed = false; + } else if (protocols[PROTOCOL_PSTN_PREFIXED] !== undefined) { + this.supportsPstnProtocol = Boolean(protocols[PROTOCOL_PSTN_PREFIXED]); + if (this.supportsPstnProtocol) this.pstnSupportPrefixed = true; } else { this.supportsPstnProtocol = null; } + dis.dispatch({action: Action.PstnSupportUpdated}); + + if (protocols[PROTOCOL_SIP_NATIVE] !== undefined && protocols[PROTOCOL_SIP_VIRTUAL] !== undefined) { + this.supportsSipNativeVirtual = Boolean( + protocols[PROTOCOL_SIP_NATIVE] && protocols[PROTOCOL_SIP_VIRTUAL], + ); + } + + dis.dispatch({action: Action.VirtualRoomSupportUpdated}); } catch (e) { if (maxTries === 1) { - console.log("Failed to check for pstn protocol support and no retries remain: assuming no support", e); + console.log("Failed to check for protocol support and no retries remain: assuming no support", e); } else { - console.log("Failed to check for pstn protocol support: will retry", e); + console.log("Failed to check for protocol support: will retry", e); this.pstnSupportCheckTimer = setTimeout(() => { - this.checkForPstnSupport(maxTries - 1); + this.checkProtocols(maxTries - 1); }, 10000); } } } - getSupportsPstnProtocol() { + public getSupportsPstnProtocol() { return this.supportsPstnProtocol; } + public getSupportsVirtualRooms() { + return this.supportsPstnProtocol; + } + + public pstnLookup(phoneNumber: string): Promise { + return MatrixClientPeg.get().getThirdpartyUser( + this.pstnSupportPrefixed ? PROTOCOL_PSTN_PREFIXED : PROTOCOL_PSTN, { + 'm.id.phone': phoneNumber, + }, + ); + } + + public sipVirtualLookup(nativeMxid: string): Promise { + return MatrixClientPeg.get().getThirdpartyUser( + PROTOCOL_SIP_VIRTUAL, { + 'native_mxid': nativeMxid, + }, + ); + } + + public sipNativeLookup(virtualMxid: string): Promise { + return MatrixClientPeg.get().getThirdpartyUser( + PROTOCOL_SIP_NATIVE, { + 'virtual_mxid': virtualMxid, + }, + ); + } + private onCallIncoming = (call) => { // we dispatch this synchronously to make sure that the event // handlers on the call are set up immediately (so that if @@ -543,7 +601,7 @@ export default class CallHandler { Analytics.trackEvent('voip', 'placeCall', 'type', type); CountlyAnalytics.instance.trackStartCall(roomId, type === PlaceCallType.Video, false); - const mappedRoomId = (await getOrCreateVirtualRoomForRoom(roomId)) || roomId; + const mappedRoomId = (await VoipUserMapper.sharedInstance().getOrCreateVirtualRoomForRoom(roomId)) || roomId; logger.debug("Mapped real room " + roomId + " to room ID " + mappedRoomId); const call = createNewMatrixCall(MatrixClientPeg.get(), mappedRoomId); diff --git a/src/SlashCommands.tsx b/src/SlashCommands.tsx index a39ad33b04..8f20754027 100644 --- a/src/SlashCommands.tsx +++ b/src/SlashCommands.tsx @@ -1040,9 +1040,7 @@ export const Commands = [ return success((async () => { if (isPhoneNumber) { - const results = await MatrixClientPeg.get().getThirdpartyUser('im.vector.protocol.pstn', { - 'm.id.phone': userId, - }); + const results = await CallHandler.sharedInstance().pstnLookup(this.state.value); if (!results || results.length === 0 || !results[0].userid) { throw new Error("Unable to find Matrix ID for phone number"); } diff --git a/src/VoipUserMapper.ts b/src/VoipUserMapper.ts index a4f5822065..c317402327 100644 --- a/src/VoipUserMapper.ts +++ b/src/VoipUserMapper.ts @@ -17,63 +17,96 @@ limitations under the License. import { ensureDMExists, findDMForUser } from './createRoom'; import { MatrixClientPeg } from "./MatrixClientPeg"; import DMRoomMap from "./utils/DMRoomMap"; -import SdkConfig from "./SdkConfig"; +import CallHandler, { VIRTUAL_ROOM_EVENT_TYPE } from './CallHandler'; +import RoomListStore from './stores/room-list/RoomListStore'; +import { Room } from 'matrix-js-sdk/src/models/room'; -// Functions for mapping users & rooms for the voip_mxid_translate_pattern -// config option +// Functions for mapping virtual users & rooms. Currently the only lookup +// is sip virtual: there could be others in the future. -export function voipUserMapperEnabled(): boolean { - return SdkConfig.get()['voip_mxid_translate_pattern'] !== undefined; -} +export default class VoipUserMapper { + private virtualRoomIdCache = new Set(); -// only exported for tests -export function userToVirtualUser(userId: string, templateString?: string): string { - if (templateString === undefined) templateString = SdkConfig.get()['voip_mxid_translate_pattern']; - if (!templateString) return null; - return templateString.replace('${mxid}', encodeURIComponent(userId).replace(/%/g, '=').toLowerCase()); -} + public static sharedInstance(): VoipUserMapper { + if (window.mxVoipUserMapper === undefined) window.mxVoipUserMapper = new VoipUserMapper(); + return window.mxVoipUserMapper; + } -// only exported for tests -export function virtualUserToUser(userId: string, templateString?: string): string { - if (templateString === undefined) templateString = SdkConfig.get()['voip_mxid_translate_pattern']; - if (!templateString) return null; + private async userToVirtualUser(userId: string): Promise { + const results = await CallHandler.sharedInstance().sipVirtualLookup(userId); + if (results.length === 0) return null; + return results[0].userid; + } - const regexString = templateString.replace('${mxid}', '(.+)'); + public async getOrCreateVirtualRoomForRoom(roomId: string):Promise { + const userId = DMRoomMap.shared().getUserIdForRoomId(roomId); + if (!userId) return null; - const match = userId.match('^' + regexString + '$'); - if (!match) return null; + const virtualUser = await this.userToVirtualUser(userId); + if (!virtualUser) return null; - return decodeURIComponent(match[1].replace(/=/g, '%')); -} + // There's quite a bit of acromatics here to prevent the virtual room being shown + // while it's being created: forstly, we have to stop the RoomListStore from showing + // new rooms for a bit, because we can't set the room account data to say it's a virtual + // room until we have the room ID. Secondly, once we have the new room ID, we have to + // temporarily cache the fact it's a virtual room because there's no local echo on + // room account data so it won't show up in the room model until it comes down the + // sync stream again. Ick. + RoomListStore.instance.startHoldingNewRooms(); + try { + const virtualRoomId = await ensureDMExists(MatrixClientPeg.get(), virtualUser); + MatrixClientPeg.get().setRoomAccountData(virtualRoomId, VIRTUAL_ROOM_EVENT_TYPE, { + native_room: roomId, + }); + this.virtualRoomIdCache.add(virtualRoomId); -async function getOrCreateVirtualRoomForUser(userId: string):Promise { - const virtualUser = userToVirtualUser(userId); - if (!virtualUser) return null; + return virtualRoomId; + } finally { + RoomListStore.instance.stopHoldingNewRooms(); + } + } - return await ensureDMExists(MatrixClientPeg.get(), virtualUser); -} + public nativeRoomForVirtualRoom(roomId: string):string { + const virtualRoom = MatrixClientPeg.get().getRoom(roomId); + if (!virtualRoom) return null; + const virtualRoomEvent = virtualRoom.getAccountData(VIRTUAL_ROOM_EVENT_TYPE); + if (!virtualRoomEvent || !virtualRoomEvent.getContent()) return null; + return virtualRoomEvent.getContent()['native_room'] || null; + } -export async function getOrCreateVirtualRoomForRoom(roomId: string):Promise { - const user = DMRoomMap.shared().getUserIdForRoomId(roomId); - if (!user) return null; - return getOrCreateVirtualRoomForUser(user); -} + public isVirtualRoom(roomId: string):boolean { + if (this.nativeRoomForVirtualRoom(roomId)) return true; -export function roomForVirtualRoom(roomId: string):string { - const virtualUser = DMRoomMap.shared().getUserIdForRoomId(roomId); - if (!virtualUser) return null; - const realUser = virtualUserToUser(virtualUser); - const room = findDMForUser(MatrixClientPeg.get(), realUser); - if (room) { - return room.roomId; - } else { - return null; + return this.virtualRoomIdCache.has(roomId); + } + + public async onNewInvitedRoom(invitedRoom: Room) { + const inviterId = invitedRoom.getDMInviter(); + console.log(`Checking virtual-ness of room ID ${invitedRoom.roomId}, invited by ${inviterId}`); + const result = await CallHandler.sharedInstance().sipNativeLookup(inviterId); + if (result.length === 0) { + return true; + } + + if (result[0].fields.is_virtual) { + const nativeUser = result[0].userid; + const nativeRoom = findDMForUser(MatrixClientPeg.get(), nativeUser); + if (nativeRoom) { + // It's a virtual room with a matching native room, so set the room account data. This + // will make sure we know where how to map calls and also allow us know not to display + // it in the future. + MatrixClientPeg.get().setRoomAccountData(invitedRoom.roomId, VIRTUAL_ROOM_EVENT_TYPE, { + native_room: nativeRoom.roomId, + }); + // also auto-join the virtual room if we have a matching native room + // (possibly we should only join if we've also joined the native room, then we'd also have + // to make sure we joined virtual rooms on joining a native one) + MatrixClientPeg.get().joinRoom(invitedRoom.roomId); + } + + // also put this room in the virtual room ID cache so isVirtualRoom return the right answer + // in however long it takes for the echo of setAccountData to come down the sync + this.virtualRoomIdCache.add(invitedRoom.roomId); + } } } - -export function isVirtualRoom(roomId: string):boolean { - const virtualUser = DMRoomMap.shared().getUserIdForRoomId(roomId); - if (!virtualUser) return null; - const realUser = virtualUserToUser(virtualUser); - return Boolean(realUser); -} diff --git a/src/components/views/voip/DialPadModal.tsx b/src/components/views/voip/DialPadModal.tsx index 74b39e0721..9f031a48a3 100644 --- a/src/components/views/voip/DialPadModal.tsx +++ b/src/components/views/voip/DialPadModal.tsx @@ -24,6 +24,7 @@ import DialPad from './DialPad'; import dis from '../../../dispatcher/dispatcher'; import Modal from "../../../Modal"; import ErrorDialog from "../../views/dialogs/ErrorDialog"; +import CallHandler from "../../../CallHandler"; interface IProps { onFinished: (boolean) => void; @@ -64,9 +65,7 @@ export default class DialpadModal extends React.PureComponent { } onDialPress = async () => { - const results = await MatrixClientPeg.get().getThirdpartyUser('im.vector.protocol.pstn', { - 'm.id.phone': this.state.value, - }); + const results = await CallHandler.sharedInstance().pstnLookup(this.state.value); if (!results || results.length === 0 || !results[0].userid) { Modal.createTrackedDialog('', '', ErrorDialog, { title: _t("Unable to look up phone number"), diff --git a/src/dispatcher/actions.ts b/src/dispatcher/actions.ts index ce27f9b289..12bf4c57a3 100644 --- a/src/dispatcher/actions.ts +++ b/src/dispatcher/actions.ts @@ -106,4 +106,11 @@ export enum Action { * XXX: Is an action the right thing for this? */ PstnSupportUpdated = "pstn_support_updated", + + /** + * Similar to PstnSupportUpdated, fired when CallHandler has checked for virtual room support + * payload: none + * XXX: Ditto + */ + VirtualRoomSupportUpdated = "virtual_room_support_updated", } diff --git a/src/stores/room-list/RoomListStore.ts b/src/stores/room-list/RoomListStore.ts index 24a75c53e7..15e385f7e4 100644 --- a/src/stores/room-list/RoomListStore.ts +++ b/src/stores/room-list/RoomListStore.ts @@ -35,6 +35,7 @@ import { AsyncStoreWithClient } from "../AsyncStoreWithClient"; import { NameFilterCondition } from "./filters/NameFilterCondition"; import { RoomNotificationStateStore } from "../notifications/RoomNotificationStateStore"; import { VisibilityProvider } from "./filters/VisibilityProvider"; +import VoipUserMapper from "../../VoipUserMapper"; interface IState { tagsEnabled?: boolean; @@ -63,6 +64,9 @@ export class RoomListStoreClass extends AsyncStoreWithClient { } this.emit(LISTS_UPDATE_EVENT); }); + // When new rooms arrive, we may hold them here until we have enough info to know whether we should before display them. + private roomHoldingPen: Room[] = []; + private holdNewRooms = false; private readonly watchedSettings = [ 'feature_custom_tags', @@ -126,6 +130,24 @@ export class RoomListStoreClass extends AsyncStoreWithClient { this.updateFn.trigger(); } + // After calling this, any new rooms that appear are not displayed until stopHoldingNewRooms() + // is called. Be sure to always call this in a try/finally block to ensure stopHoldingNewRooms + // is called afterwards. + public startHoldingNewRooms() { + console.log("hold-new-rooms mode enabled."); + this.holdNewRooms = true; + } + + public stopHoldingNewRooms() { + console.log("hold-new-rooms mode disabled: processing " + this.roomHoldingPen.length + " held rooms"); + this.holdNewRooms = false; + for (const heldRoom of this.roomHoldingPen) { + console.log("Processing held room: " + heldRoom.roomId); + this.handleRoomUpdate(heldRoom, RoomUpdateCause.NewRoom); + } + this.roomHoldingPen = []; + } + private checkLoggingEnabled() { if (SettingsStore.getValue("advancedRoomListLogging")) { console.warn("Advanced room list logging is enabled"); @@ -398,6 +420,21 @@ export class RoomListStoreClass extends AsyncStoreWithClient { } private async handleRoomUpdate(room: Room, cause: RoomUpdateCause): Promise { + if (cause === RoomUpdateCause.NewRoom) { + if (this.holdNewRooms) { + console.log("Room updates are held: putting room " + room.roomId + " into the holding pen"); + this.roomHoldingPen.push(room); + return; + } else { + // we call straight out to VoipUserMapper here which is a bit of a hack: probably this + // should be calling the visibility provider which in turn farms out to various visibility + // providers? Anyway, the point of this is that we delay doing anything about this room + // until the VoipUserMapper had had a chance to do the things it needs to do to decide + // if we should show this room or not. + await VoipUserMapper.sharedInstance().onNewInvitedRoom(room); + } + } + if (!VisibilityProvider.instance.isRoomVisible(room)) { return; // don't do anything on rooms that aren't visible } diff --git a/src/stores/room-list/filters/VisibilityProvider.ts b/src/stores/room-list/filters/VisibilityProvider.ts index 6bc790bb1e..45233357c1 100644 --- a/src/stores/room-list/filters/VisibilityProvider.ts +++ b/src/stores/room-list/filters/VisibilityProvider.ts @@ -15,8 +15,9 @@ */ import {Room} from "matrix-js-sdk/src/models/room"; +import CallHandler from "../../../CallHandler"; import { RoomListCustomisations } from "../../../customisations/RoomList"; -import { isVirtualRoom, voipUserMapperEnabled } from "../../../VoipUserMapper"; +import VoipUserMapper from "../../../VoipUserMapper"; export class VisibilityProvider { private static internalInstance: VisibilityProvider; @@ -35,7 +36,10 @@ export class VisibilityProvider { let isVisible = true; // Returned at the end of this function let forced = false; // When true, this function won't bother calling the customisation points - if (voipUserMapperEnabled() && isVirtualRoom(room.roomId)) { + if ( + CallHandler.sharedInstance().getSupportsVirtualRooms() && + VoipUserMapper.sharedInstance().isVirtualRoom(room.roomId) + ) { isVisible = false; forced = true; } diff --git a/test/VoipUserMapper-test.ts b/test/VoipUserMapper-test.ts deleted file mode 100644 index ee45379e4c..0000000000 --- a/test/VoipUserMapper-test.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* -Copyright 2021 The Matrix.org Foundation C.I.C. - -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 { userToVirtualUser, virtualUserToUser } from '../src/VoipUserMapper'; - -const templateString = '@_greatappservice_${mxid}:frooble.example'; -const realUser = '@alice:boop.example'; -const virtualUser = "@_greatappservice_=40alice=3aboop.example:frooble.example"; - -describe('VoipUserMapper', function() { - it('translates users to virtual users', function() { - expect(userToVirtualUser(realUser, templateString)).toEqual(virtualUser); - }); - - it('translates users to virtual users', function() { - expect(virtualUserToUser(virtualUser, templateString)).toEqual(realUser); - }); -}); From 8afb74d0e16883f24a24fa2466efafdde74c772f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sat, 13 Feb 2021 08:53:25 +0100 Subject: [PATCH 085/479] Fix border radius when the panel is collapsed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/rooms/_RoomSublist.scss | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/res/css/views/rooms/_RoomSublist.scss b/res/css/views/rooms/_RoomSublist.scss index 27c7c7d0f7..92a475694e 100644 --- a/res/css/views/rooms/_RoomSublist.scss +++ b/res/css/views/rooms/_RoomSublist.scss @@ -197,6 +197,9 @@ limitations under the License. .mx_RoomSublist_resizerHandles { flex: 0 0 4px; + display: flex; + justify-content: center; + width: 100%; } // Class name comes from the ResizableBox component @@ -207,17 +210,12 @@ limitations under the License. border-radius: 3px; // Override styles from library - width: unset !important; + max-width: 64px; height: 4px !important; // Update RESIZE_HANDLE_HEIGHT if this changes // This is positioned directly below the 'show more' button. - position: absolute; + position: relative !important; bottom: 0 !important; // override from library - - // Together, these make the bar 64px wide - // These are also overridden from the library - left: calc(50% - 32px) !important; - right: calc(50% - 32px) !important; } &:hover, &.mx_RoomSublist_hasMenuOpen { From 82474074f22bedd27c69e60d53fde373ac19c0a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sat, 13 Feb 2021 13:03:26 +0100 Subject: [PATCH 086/479] Fix scrollbar color for non-Firefox MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/themes/dark/css/_dark.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/res/themes/dark/css/_dark.scss b/res/themes/dark/css/_dark.scss index 612b8e03bd..a878aa3cdd 100644 --- a/res/themes/dark/css/_dark.scss +++ b/res/themes/dark/css/_dark.scss @@ -259,6 +259,11 @@ $composer-shadow-color: rgba(0, 0, 0, 0.28); .mx_EventTile_content .markdown-body pre:hover { border-color: #808080 !important; // inverted due to rules below scrollbar-color: rgba(0, 0, 0, 0.2) transparent; // copied from light theme due to inversion below + // the code above works only in Firefox, this is for other browsers + // see https://developer.mozilla.org/en-US/docs/Web/CSS/scrollbar-color + &::-webkit-scrollbar-thumb { + background-color: rgba(0, 0, 0, 0.2); // copied from light theme due to inversion below + } } .mx_EventTile_content .markdown-body { pre, code { From 7dc6029f19502b9a450d998db5364d39b8872d95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sat, 13 Feb 2021 15:29:38 +0100 Subject: [PATCH 087/479] Move icons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This tweaks the icon positions to look a bit better. Espacially with a scrollbar on the side Signed-off-by: Šimon Brandner --- res/css/views/rooms/_EventTile.scss | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/res/css/views/rooms/_EventTile.scss b/res/css/views/rooms/_EventTile.scss index 42df3211de..60b7bb08d8 100644 --- a/res/css/views/rooms/_EventTile.scss +++ b/res/css/views/rooms/_EventTile.scss @@ -531,14 +531,14 @@ $left-gutter: 64px; display: inline-block; visibility: hidden; cursor: pointer; - top: 6px; - right: 12px; + top: 8px; + right: 8px; width: 19px; height: 19px; background-color: $message-action-bar-fg-color; } .mx_EventTile_buttonBottom { - top: 31px; + top: 33px; } .mx_EventTile_copyButton { mask-image: url($copy-button-url); From 74a6c1e8d887f793cdd078d8e5634e948f5cae8c Mon Sep 17 00:00:00 2001 From: PunitLodha Date: Sun, 14 Feb 2021 18:21:12 +0530 Subject: [PATCH 088/479] Dont clear email if verification cancelled by user --- src/components/views/settings/account/EmailAddresses.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/views/settings/account/EmailAddresses.js b/src/components/views/settings/account/EmailAddresses.js index 07d2133e95..a8de7693a9 100644 --- a/src/components/views/settings/account/EmailAddresses.js +++ b/src/components/views/settings/account/EmailAddresses.js @@ -179,6 +179,7 @@ export default class EmailAddresses extends React.Component { this.setState({continueDisabled: true}); this.state.addTask.checkEmailLinkClicked().then(([finished]) => { + let newEmailAddress = this.state.newEmailAddress; if (finished) { const email = this.state.newEmailAddress; const emails = [ @@ -186,12 +187,13 @@ export default class EmailAddresses extends React.Component { { address: email, medium: "email" }, ]; this.props.onEmailsChange(emails); + newEmailAddress = ""; } this.setState({ addTask: null, continueDisabled: false, verifying: false, - newEmailAddress: "", + newEmailAddress, }); }).catch((err) => { this.setState({continueDisabled: false}); From 0902936d3973581ae0464c4299d7b692ed04878f Mon Sep 17 00:00:00 2001 From: PunitLodha Date: Sun, 14 Feb 2021 18:21:39 +0530 Subject: [PATCH 089/479] Add phone number only if verification is complete --- .../views/settings/account/PhoneNumbers.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/components/views/settings/account/PhoneNumbers.js b/src/components/views/settings/account/PhoneNumbers.js index 02e995ac45..df54b5ca1f 100644 --- a/src/components/views/settings/account/PhoneNumbers.js +++ b/src/components/views/settings/account/PhoneNumbers.js @@ -177,21 +177,25 @@ export default class PhoneNumbers extends React.Component { this.setState({continueDisabled: true}); const token = this.state.newPhoneNumberCode; const address = this.state.verifyMsisdn; - this.state.addTask.haveMsisdnToken(token).then(() => { + this.state.addTask.haveMsisdnToken(token).then(([finished]) => { + let newPhoneNumber = this.state.newPhoneNumber; + if (finished) { + const msisdns = [ + ...this.props.msisdns, + { address, medium: "msisdn" }, + ]; + this.props.onMsisdnsChange(msisdns); + newPhoneNumber = ""; + } this.setState({ addTask: null, continueDisabled: false, verifying: false, verifyMsisdn: "", verifyError: null, - newPhoneNumber: "", + newPhoneNumber, newPhoneNumberCode: "", }); - const msisdns = [ - ...this.props.msisdns, - { address, medium: "msisdn" }, - ]; - this.props.onMsisdnsChange(msisdns); }).catch((err) => { this.setState({continueDisabled: false}); if (err.errcode !== 'M_THREEPID_AUTH_FAILED') { From f343aaa05a16d7cb185eff9b4ba996fc841f2e6f Mon Sep 17 00:00:00 2001 From: Michael Weimann Date: Sun, 14 Feb 2021 18:37:06 +0100 Subject: [PATCH 090/479] fix context menu padding calculation Signed-off-by: Michael Weimann --- src/components/structures/ContextMenu.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/ContextMenu.tsx b/src/components/structures/ContextMenu.tsx index aab7701f26..473b90ad77 100644 --- a/src/components/structures/ContextMenu.tsx +++ b/src/components/structures/ContextMenu.tsx @@ -299,7 +299,7 @@ export class ContextMenu extends React.PureComponent { // such that it does not leave the (padded) window. if (contextMenuRect) { const padding = 10; - adjusted = Math.min(position.top, document.body.clientHeight - contextMenuRect.height + padding); + adjusted = Math.min(position.top, document.body.clientHeight - contextMenuRect.height - padding); } position.top = adjusted; From d73648dfb03594e0a1a8e9772b9b15fd8cdcbe20 Mon Sep 17 00:00:00 2001 From: Jaiwanth Date: Mon, 15 Feb 2021 17:46:32 +0530 Subject: [PATCH 091/479] Modified regex to account for an immediate new line after slash commands Signed-off-by: Jaiwanth --- src/SlashCommands.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SlashCommands.tsx b/src/SlashCommands.tsx index a39ad33b04..38e5a95f7f 100644 --- a/src/SlashCommands.tsx +++ b/src/SlashCommands.tsx @@ -1182,7 +1182,7 @@ export function parseCommandString(input: string) { input = input.replace(/\s+$/, ''); if (input[0] !== '/') return {}; // not a command - const bits = input.match(/^(\S+?)(?: +((.|\n)*))?$/); + const bits = input.match(/^(\S+?)(?:[ \n]+((.|\n)*))?$/); let cmd; let args; if (bits) { From d7bf57af13de7aeb03bed98df0649071ca6a0b17 Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 15 Feb 2021 15:04:01 +0000 Subject: [PATCH 092/479] Add missing 'd' --- src/CallHandler.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index ca9f96c7c2..6cebae1093 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -103,7 +103,7 @@ enum AudioID { Busy = 'busyAudio', } -interface ThirpartyLookupResponse { +interface ThirdpartyLookupResponse { userid: string, protocol: string, fields: {[key: string]: any}, @@ -238,7 +238,7 @@ export default class CallHandler { return this.supportsPstnProtocol; } - public pstnLookup(phoneNumber: string): Promise { + public pstnLookup(phoneNumber: string): Promise { return MatrixClientPeg.get().getThirdpartyUser( this.pstnSupportPrefixed ? PROTOCOL_PSTN_PREFIXED : PROTOCOL_PSTN, { 'm.id.phone': phoneNumber, @@ -246,7 +246,7 @@ export default class CallHandler { ); } - public sipVirtualLookup(nativeMxid: string): Promise { + public sipVirtualLookup(nativeMxid: string): Promise { return MatrixClientPeg.get().getThirdpartyUser( PROTOCOL_SIP_VIRTUAL, { 'native_mxid': nativeMxid, @@ -254,7 +254,7 @@ export default class CallHandler { ); } - public sipNativeLookup(virtualMxid: string): Promise { + public sipNativeLookup(virtualMxid: string): Promise { return MatrixClientPeg.get().getThirdpartyUser( PROTOCOL_SIP_NATIVE, { 'virtual_mxid': virtualMxid, From 554dfdb6bf58a82f9f09b047f2cca6835a733d57 Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 15 Feb 2021 15:05:01 +0000 Subject: [PATCH 093/479] Typo Co-authored-by: J. Ryan Stinnett --- src/VoipUserMapper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/VoipUserMapper.ts b/src/VoipUserMapper.ts index c317402327..bf592de001 100644 --- a/src/VoipUserMapper.ts +++ b/src/VoipUserMapper.ts @@ -45,7 +45,7 @@ export default class VoipUserMapper { const virtualUser = await this.userToVirtualUser(userId); if (!virtualUser) return null; - // There's quite a bit of acromatics here to prevent the virtual room being shown + // There's quite a bit of acrobatics here to prevent the virtual room being shown // while it's being created: forstly, we have to stop the RoomListStore from showing // new rooms for a bit, because we can't set the room account data to say it's a virtual // room until we have the room ID. Secondly, once we have the new room ID, we have to From 65ef4f2f221fce653828a636131ebe202950f2e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 15 Feb 2021 16:05:14 +0100 Subject: [PATCH 094/479] Removed the commented out code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- .../tabs/user/AppearanceUserSettingsTab.tsx | 56 ------------------- 1 file changed, 56 deletions(-) diff --git a/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx b/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx index 5d3596911f..80a20d8afa 100644 --- a/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx @@ -28,13 +28,11 @@ import { FontWatcher } from "../../../../../settings/watchers/FontWatcher"; import { RecheckThemePayload } from '../../../../../dispatcher/payloads/RecheckThemePayload'; import { Action } from '../../../../../dispatcher/actions'; import { IValidationResult, IFieldState } from '../../../elements/Validation'; -//import StyledRadioButton from '../../../elements/StyledRadioButton'; import StyledCheckbox from '../../../elements/StyledCheckbox'; import SettingsFlag from '../../../elements/SettingsFlag'; import Field from '../../../elements/Field'; import EventTilePreview from '../../../elements/EventTilePreview'; import StyledRadioGroup from "../../../elements/StyledRadioGroup"; -//import classNames from 'classnames'; import { SettingLevel } from "../../../../../settings/SettingLevel"; import {UIFeature} from "../../../../../settings/UIFeature"; import {Layout} from "../../../../../settings/Layout"; @@ -214,16 +212,6 @@ export default class AppearanceUserSettingsTab extends React.Component): void => { - const val = e.target.value === "true"; - - this.setState({ - useIRCLayout: val, - }); - - SettingsStore.setValue("useIRCLayout", null, SettingLevel.DEVICE, val); - };*/ - private onIRCLayoutChange = (enabled: boolean) => { if (enabled) { this.setState({layout: Layout.IRC}); @@ -353,50 +341,6 @@ export default class AppearanceUserSettingsTab extends React.Component; } - /*private renderLayoutSection = () => { - return
- {_t("Message layout")} - -
-
- - - {_t("Compact")} - -
-
-
- - - {_t("Modern")} - -
-
-
; - };*/ - private renderAdvancedSection() { if (!SettingsStore.getValue(UIFeature.AdvancedSettings)) return null; From 0b574327d77e267422eb9929358315e8810c52f9 Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 15 Feb 2021 15:05:16 +0000 Subject: [PATCH 095/479] More typo Co-authored-by: J. Ryan Stinnett --- src/VoipUserMapper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/VoipUserMapper.ts b/src/VoipUserMapper.ts index bf592de001..ceb87c1829 100644 --- a/src/VoipUserMapper.ts +++ b/src/VoipUserMapper.ts @@ -46,7 +46,7 @@ export default class VoipUserMapper { if (!virtualUser) return null; // There's quite a bit of acrobatics here to prevent the virtual room being shown - // while it's being created: forstly, we have to stop the RoomListStore from showing + // while it's being created: firstly, we have to stop the RoomListStore from showing // new rooms for a bit, because we can't set the room account data to say it's a virtual // room until we have the room ID. Secondly, once we have the new room ID, we have to // temporarily cache the fact it's a virtual room because there's no local echo on From 064afab239adec142ee8c410378f2fb7adbecbcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 15 Feb 2021 16:06:38 +0100 Subject: [PATCH 096/479] Use LEVELS_ACCOUNT_SETTINGS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/settings/Settings.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index 3651e43d7d..d7d5ab8490 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -625,7 +625,7 @@ export const SETTINGS: {[setting: string]: ISetting} = { default: 80, }, "layout": { - supportedLevels: LEVELS_ROOM_SETTINGS_WITH_ROOM, + supportedLevels: LEVELS_ACCOUNT_SETTINGS, default: Layout.Group, }, "showChatEffects": { From d339dc447f83ab82c9f135e355eb140e237f0678 Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 15 Feb 2021 15:25:07 +0000 Subject: [PATCH 097/479] Add specific fields to third party lookup response fields --- src/CallHandler.tsx | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index 6cebae1093..63b849af4b 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -103,10 +103,27 @@ enum AudioID { Busy = 'busyAudio', } +interface ThirdpartyLookupResponseFields { + /* eslint-disable camelcase */ + + // im.vector.sip_native + virtual_mxid: string; + is_virtual: boolean; + + // im.vector.sip_virtual + native_mxid: string; + is_native: boolean; + + // common + lookup_success: boolean; + + /* eslint-enable camelcase */ +} + interface ThirdpartyLookupResponse { userid: string, protocol: string, - fields: {[key: string]: any}, + fields: ThirdpartyLookupResponseFields, } // Unlike 'CallType' in js-sdk, this one includes screen sharing From cd82d97c3eb3c1035cbbe73f6f4741665b3f3b45 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 15 Feb 2021 08:53:37 -0700 Subject: [PATCH 098/479] Use randomly generated conference names for Jitsi Fixes https://github.com/vector-im/element-web/issues/15205 Replaces https://github.com/matrix-org/matrix-react-sdk/pull/5322 This change uses a random ID for the Jitsi conference name to avoid any badly-named Jitsi calls, and overrides the "subject" (title) of the call so end users aren't typically exposed to the random ID. --- package.json | 1 - src/CallHandler.tsx | 5 +++-- src/utils/NamingUtils.ts | 29 ----------------------------- src/utils/WidgetUtils.ts | 1 + yarn.lock | 13 ------------- 5 files changed, 4 insertions(+), 45 deletions(-) delete mode 100644 src/utils/NamingUtils.ts diff --git a/package.json b/package.json index 2263c7de32..61c8cb7a2c 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,6 @@ "pako": "^2.0.3", "parse5": "^6.0.1", "png-chunks-extract": "^1.0.0", - "project-name-generator": "^2.1.9", "prop-types": "^15.7.2", "qrcode": "^1.4.4", "qs": "^6.9.6", diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index 41a5941092..e09a47cf97 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -64,7 +64,6 @@ import dis from './dispatcher/dispatcher'; import WidgetUtils from './utils/WidgetUtils'; import WidgetEchoStore from './stores/WidgetEchoStore'; import SettingsStore from './settings/SettingsStore'; -import {generateHumanReadableId} from "./utils/NamingUtils"; import {Jitsi} from "./widgets/Jitsi"; import {WidgetType} from "./widgets/WidgetType"; import {SettingLevel} from "./settings/SettingLevel"; @@ -86,6 +85,7 @@ import DesktopCapturerSourcePicker from "./components/views/elements/DesktopCapt import { Action } from './dispatcher/actions'; import { roomForVirtualRoom, getOrCreateVirtualRoomForRoom } from './VoipUserMapper'; import { addManagedHybridWidget, isManagedHybridWidgetEnabled } from './widgets/ManagedHybrid'; +import { randomString } from "matrix-js-sdk/lib/randomstring"; const CHECK_PSTN_SUPPORT_ATTEMPTS = 3; @@ -780,7 +780,7 @@ export default class CallHandler { confId = base32.stringify(Buffer.from(roomId), { pad: false }); } else { // Create a random human readable conference ID - confId = `JitsiConference${generateHumanReadableId()}`; + confId = `JitsiConference${randomString(32)}`; } let widgetUrl = WidgetUtils.getLocalJitsiWrapperUrl({auth: jitsiAuth}); @@ -796,6 +796,7 @@ export default class CallHandler { isAudioOnly: type === 'voice', domain: jitsiDomain, auth: jitsiAuth, + roomName: room.name, }; const widgetId = ( diff --git a/src/utils/NamingUtils.ts b/src/utils/NamingUtils.ts deleted file mode 100644 index 44ccb9b030..0000000000 --- a/src/utils/NamingUtils.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* -Copyright 2020 The Matrix.org Foundation C.I.C. - -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 * as projectNameGenerator from "project-name-generator"; - -/** - * Generates a human readable identifier. This should not be used for anything - * which needs secure/cryptographic random: just a level uniquness that is offered - * by something like Date.now(). - * @returns {string} The randomly generated ID - */ -export function generateHumanReadableId(): string { - return projectNameGenerator({words: 3}).raw.map(w => { - return w[0].toUpperCase() + w.substring(1).toLowerCase(); - }).join(''); -} diff --git a/src/utils/WidgetUtils.ts b/src/utils/WidgetUtils.ts index db2b10b295..c67f3bad13 100644 --- a/src/utils/WidgetUtils.ts +++ b/src/utils/WidgetUtils.ts @@ -477,6 +477,7 @@ export default class WidgetUtils { 'userId=$matrix_user_id', 'roomId=$matrix_room_id', 'theme=$theme', + 'roomName=$roomName', ]; if (opts.auth) { queryStringParts.push(`auth=${opts.auth}`); diff --git a/yarn.lock b/yarn.lock index 1a350f697a..9bd51f16a7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2477,11 +2477,6 @@ commander@^4.0.1: resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== -commander@^6.1.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" - integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== - commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -6453,14 +6448,6 @@ progress@^2.0.0: resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== -project-name-generator@^2.1.9: - version "2.1.9" - resolved "https://registry.yarnpkg.com/project-name-generator/-/project-name-generator-2.1.9.tgz#959177f1feb2355d74fa98745d72a65a5f75b674" - integrity sha512-QmLHqz2C4VHmAyDEAFlVfnuWAHr4vwZhK2bbm4IrwuHNzNKOdG9b4U+NmQbsm1uOoV4kGWv7+FVLsu7Bb/ieYQ== - dependencies: - commander "^6.1.0" - lodash "^4.17.20" - promise@^7.0.3, promise@^7.1.1: version "7.3.1" resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" From cb757b5b50a645932547a94f7b46d851ea34e9c1 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 15 Feb 2021 08:56:38 -0700 Subject: [PATCH 099/479] Fix import --- src/CallHandler.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index e09a47cf97..f106d75f8b 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -85,7 +85,7 @@ import DesktopCapturerSourcePicker from "./components/views/elements/DesktopCapt import { Action } from './dispatcher/actions'; import { roomForVirtualRoom, getOrCreateVirtualRoomForRoom } from './VoipUserMapper'; import { addManagedHybridWidget, isManagedHybridWidgetEnabled } from './widgets/ManagedHybrid'; -import { randomString } from "matrix-js-sdk/lib/randomstring"; +import { randomString } from "matrix-js-sdk/src/randomstring"; const CHECK_PSTN_SUPPORT_ATTEMPTS = 3; From d96043d5ab3e246cec1f6891352066ed2782a932 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Mon, 15 Feb 2021 17:34:28 +0000 Subject: [PATCH 100/479] Use config for host signup branding --- res/css/structures/_UserMenu.scss | 2 +- src/components/structures/HostSignupAction.tsx | 13 ++++++++++++- src/i18n/strings/en_EN.json | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/res/css/structures/_UserMenu.scss b/res/css/structures/_UserMenu.scss index f2577938e5..2a4453df70 100644 --- a/res/css/structures/_UserMenu.scss +++ b/res/css/structures/_UserMenu.scss @@ -128,7 +128,7 @@ limitations under the License. } .mx_UserMenu_contextMenu { - width: 247px; + width: 258px; // These override the styles already present on the user menu rather than try to // define a new menu. They are specifically for the stacked menu when a community diff --git a/src/components/structures/HostSignupAction.tsx b/src/components/structures/HostSignupAction.tsx index 39185acd05..9cf84a9379 100644 --- a/src/components/structures/HostSignupAction.tsx +++ b/src/components/structures/HostSignupAction.tsx @@ -21,6 +21,7 @@ import { } from "../views/context_menus/IconizedContextMenu"; import { _t } from "../../languageHandler"; import { HostSignupStore } from "../../stores/HostSignupStore"; +import SdkConfig from "../../SdkConfig"; interface IProps {} @@ -32,11 +33,21 @@ export default class HostSignupAction extends React.PureComponent diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index a9d31bb9f2..d023984f7d 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2450,7 +2450,7 @@ "Send a Direct Message": "Send a Direct Message", "Explore Public Rooms": "Explore Public Rooms", "Create a Group Chat": "Create a Group Chat", - "Upgrade to pro": "Upgrade to pro", + "Upgrade to %(hostSignupBrand)s": "Upgrade to %(hostSignupBrand)s", "Explore rooms": "Explore rooms", "Failed to reject invitation": "Failed to reject invitation", "Cannot create rooms in this community": "Cannot create rooms in this community", From 234f1bf2c47369c86d8c1a437c959dff828a1cb5 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Mon, 15 Feb 2021 17:38:11 +0000 Subject: [PATCH 101/479] Test domains in config directly --- src/components/structures/UserMenu.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/UserMenu.tsx b/src/components/structures/UserMenu.tsx index 5b34d36d09..7f96e2d142 100644 --- a/src/components/structures/UserMenu.tsx +++ b/src/components/structures/UserMenu.tsx @@ -300,7 +300,7 @@ export default class UserMenu extends React.Component { const hostSignupDomains = hostSignupConfig.domains || []; const mxDomain = MatrixClientPeg.get().getDomain(); const validDomains = hostSignupDomains.filter(d => (d === mxDomain || mxDomain.endsWith(`.${d}`))); - if (!hostSignupDomains || validDomains.length > 0) { + if (!hostSignupConfig.domains || validDomains.length > 0) { topSection =
; From 3919fcd80e6f709ae74ec4cf7b93d36ea3d2f651 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Mon, 15 Feb 2021 17:34:28 +0000 Subject: [PATCH 102/479] Use config for host signup branding --- res/css/structures/_UserMenu.scss | 2 +- src/components/structures/HostSignupAction.tsx | 13 ++++++++++++- src/i18n/strings/en_EN.json | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/res/css/structures/_UserMenu.scss b/res/css/structures/_UserMenu.scss index f2577938e5..2a4453df70 100644 --- a/res/css/structures/_UserMenu.scss +++ b/res/css/structures/_UserMenu.scss @@ -128,7 +128,7 @@ limitations under the License. } .mx_UserMenu_contextMenu { - width: 247px; + width: 258px; // These override the styles already present on the user menu rather than try to // define a new menu. They are specifically for the stacked menu when a community diff --git a/src/components/structures/HostSignupAction.tsx b/src/components/structures/HostSignupAction.tsx index 39185acd05..9cf84a9379 100644 --- a/src/components/structures/HostSignupAction.tsx +++ b/src/components/structures/HostSignupAction.tsx @@ -21,6 +21,7 @@ import { } from "../views/context_menus/IconizedContextMenu"; import { _t } from "../../languageHandler"; import { HostSignupStore } from "../../stores/HostSignupStore"; +import SdkConfig from "../../SdkConfig"; interface IProps {} @@ -32,11 +33,21 @@ export default class HostSignupAction extends React.PureComponent diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index a9d31bb9f2..d023984f7d 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2450,7 +2450,7 @@ "Send a Direct Message": "Send a Direct Message", "Explore Public Rooms": "Explore Public Rooms", "Create a Group Chat": "Create a Group Chat", - "Upgrade to pro": "Upgrade to pro", + "Upgrade to %(hostSignupBrand)s": "Upgrade to %(hostSignupBrand)s", "Explore rooms": "Explore rooms", "Failed to reject invitation": "Failed to reject invitation", "Cannot create rooms in this community": "Cannot create rooms in this community", From b2834d7f919ff655ad1a85fcc8931d1ffd40260b Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Mon, 15 Feb 2021 17:38:11 +0000 Subject: [PATCH 103/479] Test domains in config directly --- src/components/structures/UserMenu.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/UserMenu.tsx b/src/components/structures/UserMenu.tsx index 5b34d36d09..7f96e2d142 100644 --- a/src/components/structures/UserMenu.tsx +++ b/src/components/structures/UserMenu.tsx @@ -300,7 +300,7 @@ export default class UserMenu extends React.Component { const hostSignupDomains = hostSignupConfig.domains || []; const mxDomain = MatrixClientPeg.get().getDomain(); const validDomains = hostSignupDomains.filter(d => (d === mxDomain || mxDomain.endsWith(`.${d}`))); - if (!hostSignupDomains || validDomains.length > 0) { + if (!hostSignupConfig.domains || validDomains.length > 0) { topSection =
; From 89b2dae035f33728c45a8193d234d688b6ba209b Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 15 Feb 2021 18:13:13 +0000 Subject: [PATCH 104/479] Send onNewInvitedRoom via VisibilityProvider --- src/stores/room-list/RoomListStore.ts | 12 ++++++------ src/stores/room-list/filters/VisibilityProvider.ts | 4 ++++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/stores/room-list/RoomListStore.ts b/src/stores/room-list/RoomListStore.ts index 15e385f7e4..a050442eae 100644 --- a/src/stores/room-list/RoomListStore.ts +++ b/src/stores/room-list/RoomListStore.ts @@ -426,12 +426,12 @@ export class RoomListStoreClass extends AsyncStoreWithClient { this.roomHoldingPen.push(room); return; } else { - // we call straight out to VoipUserMapper here which is a bit of a hack: probably this - // should be calling the visibility provider which in turn farms out to various visibility - // providers? Anyway, the point of this is that we delay doing anything about this room - // until the VoipUserMapper had had a chance to do the things it needs to do to decide - // if we should show this room or not. - await VoipUserMapper.sharedInstance().onNewInvitedRoom(room); + // Let the visibility provider know that there is a new invited room. It would be nice + // if this could just be an event that things listen for but the point of this is that + // we delay doing anything about this room until the VoipUserMapper had had a chance + // to do the things it needs to do to decide if we should show this room or not, so + // an even wouldn't et us do that. + await VisibilityProvider.instance.onNewInvitedRoom(room); } } diff --git a/src/stores/room-list/filters/VisibilityProvider.ts b/src/stores/room-list/filters/VisibilityProvider.ts index 45233357c1..2239f9e1ac 100644 --- a/src/stores/room-list/filters/VisibilityProvider.ts +++ b/src/stores/room-list/filters/VisibilityProvider.ts @@ -32,6 +32,10 @@ export class VisibilityProvider { return VisibilityProvider.internalInstance; } + public async onNewInvitedRoom(room: Room) { + await VoipUserMapper.sharedInstance().onNewInvitedRoom(room); + } + public isRoomVisible(room: Room): boolean { let isVisible = true; // Returned at the end of this function let forced = false; // When true, this function won't bother calling the customisation points From 79455d99b477d42f1738120780a34f83e903b1a2 Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 15 Feb 2021 19:38:17 +0000 Subject: [PATCH 105/479] Unused import --- src/stores/room-list/RoomListStore.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/stores/room-list/RoomListStore.ts b/src/stores/room-list/RoomListStore.ts index a050442eae..f420dd2b08 100644 --- a/src/stores/room-list/RoomListStore.ts +++ b/src/stores/room-list/RoomListStore.ts @@ -35,7 +35,6 @@ import { AsyncStoreWithClient } from "../AsyncStoreWithClient"; import { NameFilterCondition } from "./filters/NameFilterCondition"; import { RoomNotificationStateStore } from "../notifications/RoomNotificationStateStore"; import { VisibilityProvider } from "./filters/VisibilityProvider"; -import VoipUserMapper from "../../VoipUserMapper"; interface IState { tagsEnabled?: boolean; From f9d4d679ee6cdb3fb66bd54e4a89d755c3b21f68 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 16 Feb 2021 10:59:39 +0000 Subject: [PATCH 106/479] Upgrade matrix-js-sdk to 9.7.0 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 5beb383791..4700f6d0cb 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "katex": "^0.12.0", "linkifyjs": "^2.1.9", "lodash": "^4.17.20", - "matrix-js-sdk": "9.7.0-rc.1", + "matrix-js-sdk": "9.7.0", "matrix-widget-api": "^0.1.0-beta.13", "minimist": "^1.2.5", "pako": "^2.0.3", diff --git a/yarn.lock b/yarn.lock index e3d7a5ac28..6aff5fecdc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5577,10 +5577,10 @@ mathml-tag-names@^2.1.3: resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3" integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg== -matrix-js-sdk@9.7.0-rc.1: - version "9.7.0-rc.1" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-9.7.0-rc.1.tgz#30cabda3f2b416d09c95afc4fe138bba44534c76" - integrity sha512-y6D2bXYKQqGrtf1PLHjjHf6wW67DIhdrwQ77nKOhEd/rfaEqcMf99wqSvF/nzFexbG1Y7PG4IdM4YTdOQ9UD+g== +matrix-js-sdk@9.7.0: + version "9.7.0" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-9.7.0.tgz#fbd03c188546f9733b28ea1752476b22ca63d2f2" + integrity sha512-cVBHhQVGk2WWQ2kv0Ov8CTcgZVJhMuZBejXZnKqp6qEgSpmb4xQRxewbxjF53ixO7uRUzGFtAlDiW4BeHZnN/g== dependencies: "@babel/runtime" "^7.12.5" another-json "^0.2.0" From a99f080e97acf82ed774b98b7eb62ccdf16a0127 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 16 Feb 2021 11:05:24 +0000 Subject: [PATCH 107/479] Prepare changelog for v3.14.0 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 50880b1d53..c87f1c62e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +Changes in [3.14.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.14.0) (2021-02-16) +===================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v3.14.0-rc.1...v3.14.0) + + * Upgrade to JS SDK 9.7.0 + * [Release] Use config for host signup branding + [\#5651](https://github.com/matrix-org/matrix-react-sdk/pull/5651) + Changes in [3.14.0-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.14.0-rc.1) (2021-02-10) =============================================================================================================== [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v3.13.1...v3.14.0-rc.1) From e70085ed2e14a74dc4f482645b89bbb82101de38 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 16 Feb 2021 11:05:25 +0000 Subject: [PATCH 108/479] v3.14.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4700f6d0cb..203673eef4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "3.14.0-rc.1", + "version": "3.14.0", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From df3a9526a5780c4a71e8c951cf47991bbd43b9ec Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 16 Feb 2021 11:06:42 +0000 Subject: [PATCH 109/479] Resetting package fields for development --- package.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index c05a007d70..9b2f60655c 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "matrix-gen-i18n": "scripts/gen-i18n.js", "matrix-prune-i18n": "scripts/prune-i18n.js" }, - "main": "./lib/index.js", + "main": "./src/index.js", "matrix_src_main": "./src/index.js", "matrix_lib_main": "./lib/index.js", "matrix_lib_typings": "./lib/index.d.ts", @@ -189,6 +189,5 @@ "transformIgnorePatterns": [ "/node_modules/(?!matrix-js-sdk).+$" ] - }, - "typings": "./lib/index.d.ts" + } } From b6a4876c8a6d6b12b5eaad93ee91869422f02837 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 16 Feb 2021 11:06:55 +0000 Subject: [PATCH 110/479] Reset matrix-js-sdk back to develop branch --- package.json | 2 +- yarn.lock | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 9b2f60655c..d4f931d811 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "katex": "^0.12.0", "linkifyjs": "^2.1.9", "lodash": "^4.17.20", - "matrix-js-sdk": "9.7.0", + "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop", "matrix-widget-api": "^0.1.0-beta.13", "minimist": "^1.2.5", "pako": "^2.0.3", diff --git a/yarn.lock b/yarn.lock index 4108c0499c..01450908cc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5572,10 +5572,9 @@ mathml-tag-names@^2.1.3: resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz#4ddadd67308e780cf16a47685878ee27b736a0a3" integrity sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg== -matrix-js-sdk@9.7.0: +"matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop": version "9.7.0" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-9.7.0.tgz#fbd03c188546f9733b28ea1752476b22ca63d2f2" - integrity sha512-cVBHhQVGk2WWQ2kv0Ov8CTcgZVJhMuZBejXZnKqp6qEgSpmb4xQRxewbxjF53ixO7uRUzGFtAlDiW4BeHZnN/g== + resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/c82bc35202f93efa2cb9b27b140f83df37c64ab2" dependencies: "@babel/runtime" "^7.12.5" another-json "^0.2.0" From 75d789bb4330b497c9cd43cbe7b38c6e1c1d4f19 Mon Sep 17 00:00:00 2001 From: waclaw66 Date: Tue, 16 Feb 2021 12:07:36 +0000 Subject: [PATCH 111/479] Translated using Weblate (Czech) Currently translated at 100.0% (2764 of 2764 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/cs/ --- src/i18n/strings/cs.json | 229 +++++++++++++++++++++------------------ 1 file changed, 121 insertions(+), 108 deletions(-) diff --git a/src/i18n/strings/cs.json b/src/i18n/strings/cs.json index c304623544..864c6208fa 100644 --- a/src/i18n/strings/cs.json +++ b/src/i18n/strings/cs.json @@ -55,7 +55,7 @@ "Custom Server Options": "Vlastní nastavení serveru", "Add a widget": "Přidat widget", "Accept": "Přijmout", - "%(targetName)s accepted an invitation.": "%(targetName)s přijal/a pozvání.", + "%(targetName)s accepted an invitation.": "%(targetName)s přijal(a) pozvání.", "Account": "Účet", "Access Token:": "Přístupový token:", "Add": "Přidat", @@ -86,10 +86,10 @@ "Bans user with given id": "Vykáže uživatele s daným id", "Cannot add any more widgets": "Nelze přidat žádné další widgety", "Change Password": "Změnit heslo", - "%(senderName)s changed their profile picture.": "%(senderName)s změnil/a svůj profilový obrázek.", - "%(senderDisplayName)s changed the room name to %(roomName)s.": "%(senderDisplayName)s změnil/a název místnosti na %(roomName)s.", - "%(senderDisplayName)s removed the room name.": "%(senderDisplayName)s odstranil/a název místnosti.", - "%(senderDisplayName)s changed the topic to \"%(topic)s\".": "%(senderDisplayName)s změnil/a téma na „%(topic)s“.", + "%(senderName)s changed their profile picture.": "%(senderName)s změnil(a) svůj profilový obrázek.", + "%(senderDisplayName)s changed the room name to %(roomName)s.": "%(senderDisplayName)s změnil(a) název místnosti na %(roomName)s.", + "%(senderDisplayName)s removed the room name.": "%(senderDisplayName)s odstranil(a) název místnosti.", + "%(senderDisplayName)s changed the topic to \"%(topic)s\".": "%(senderDisplayName)s změnil(a) téma na „%(topic)s“.", "Changes your display nickname": "Změní vaši zobrazovanou přezdívku", "Command error": "Chyba příkazu", "Commands": "Příkazy", @@ -113,8 +113,8 @@ "Email address": "E-mailová adresa", "Emoji": "Emoji", "Enable automatic language detection for syntax highlighting": "Zapnout automatické rozpoznávání jazyků pro zvýrazňování syntaxe", - "%(senderName)s ended the call.": "%(senderName)s ukončil/a hovor.", - "Enter passphrase": "Zadejte heslo", + "%(senderName)s ended the call.": "%(senderName)s ukončil(a) hovor.", + "Enter passphrase": "Zadejte přístupovou frázi", "Error decrypting attachment": "Chyba při dešifrování přílohy", "Error: Problem communicating with the given homeserver.": "Chyba: problém v komunikaci s daným domovským serverem.", "Existing Call": "Probíhající hovor", @@ -136,18 +136,18 @@ "Forget room": "Zapomenout místnost", "For security, this session has been signed out. Please sign in again.": "Z bezpečnostních důvodů bylo toto přihlášení ukončeno. Přihlašte se prosím znovu.", "and %(count)s others...|other": "a %(count)s další...", - "%(widgetName)s widget modified by %(senderName)s": "%(senderName)s upravil/a widget %(widgetName)s", - "%(widgetName)s widget removed by %(senderName)s": "%(senderName)s odstranil/a widget %(widgetName)s", - "%(widgetName)s widget added by %(senderName)s": "%(senderName)s přidal/a widget %(widgetName)s", + "%(widgetName)s widget modified by %(senderName)s": "%(senderName)s upravil(a) widget %(widgetName)s", + "%(widgetName)s widget removed by %(senderName)s": "%(senderName)s odstranil(a) widget %(widgetName)s", + "%(widgetName)s widget added by %(senderName)s": "%(senderName)s přidal(a) widget %(widgetName)s", "Automatically replace plain text Emoji": "Automaticky nahrazovat textové emoji", "Failed to upload image": "Obrázek se nepodařilo nahrát", - "%(senderName)s answered the call.": "%(senderName)s přijal/a hovor.", + "%(senderName)s answered the call.": "%(senderName)s přijal(a) hovor.", "Click to mute audio": "Klepněte pro vypnutí zvuku", "Failed to verify email address: make sure you clicked the link in the email": "E-mailovou adresu se nepodařilo ověřit. Přesvědčte se, že jste klepli na odkaz v e-mailové zprávě", "Guests cannot join this room even if explicitly invited.": "Hosté nemohou vstoupit do této místnosti, i když jsou přímo pozváni.", "Homeserver is": "Domovský server je", "Identity Server is": "Server identity je", - "I have verified my email address": "Ověřil/a jsem svou e-mailovou adresu", + "I have verified my email address": "Ověřil(a) jsem svou e-mailovou adresu", "Import": "Importovat", "Import E2E room keys": "Importovat end-to-end klíče místností", "Incoming call from %(name)s": "Příchozí hovor od %(name)s", @@ -156,12 +156,12 @@ "Incorrect username and/or password.": "Nesprávné uživatelské jméno nebo heslo.", "Incorrect verification code": "Nesprávný ověřovací kód", "Invalid Email Address": "Neplatná e-mailová adresa", - "%(senderName)s invited %(targetName)s.": "%(senderName)s pozval/a uživatele %(targetName)s.", + "%(senderName)s invited %(targetName)s.": "%(senderName)s pozval(a) uživatele %(targetName)s.", "Invites": "Pozvánky", "Invites user with given id to current room": "Pozve do aktuální místnosti uživatele s daným id", "Join Room": "Vstoupit do místnosti", - "%(targetName)s joined the room.": "%(targetName)s vstoupil/a do místnosti.", - "%(senderName)s kicked %(targetName)s.": "%(senderName)s vykopl/a uživatele %(targetName)s.", + "%(targetName)s joined the room.": "%(targetName)s vstoupil(a) do místnosti.", + "%(senderName)s kicked %(targetName)s.": "%(senderName)s vykopl(a) uživatele %(targetName)s.", "Kick": "Vykopnout", "Kicks user with given id": "Vykopne uživatele s daným id", "Last seen": "Naposledy aktivní", @@ -184,7 +184,7 @@ "Passwords can't be empty": "Hesla nemohou být prázdná", "Permissions": "Oprávnění", "Phone": "Telefon", - "%(senderName)s changed the power level of %(powerLevelDiffText)s.": "%(senderName)s změnil/a úroveň oprávnění o %(powerLevelDiffText)s.", + "%(senderName)s changed the power level of %(powerLevelDiffText)s.": "%(senderName)s změnil(a) úroveň oprávnění o %(powerLevelDiffText)s.", "Define the power level of a user": "Stanovte úroveň oprávnění uživatele", "Failed to change power level": "Nepodařilo se změnit úroveň oprávnění", "Power level must be positive integer.": "Úroveň oprávnění musí být kladné celé číslo.", @@ -201,15 +201,15 @@ "%(roomName)s is not accessible at this time.": "Místnost %(roomName)s není v tuto chvíli dostupná.", "Save": "Uložit", "Send Reset Email": "Poslat resetovací e-mail", - "%(senderDisplayName)s sent an image.": "%(senderDisplayName)s poslal/a obrázek.", - "%(senderName)s sent an invitation to %(targetDisplayName)s to join the room.": "%(senderName)s pozval/a uživatele %(targetDisplayName)s ke vstupu do místnosti.", + "%(senderDisplayName)s sent an image.": "%(senderDisplayName)s poslal(a) obrázek.", + "%(senderName)s sent an invitation to %(targetDisplayName)s to join the room.": "%(senderName)s pozval(a) uživatele %(targetDisplayName)s ke vstupu do místnosti.", "Server error": "Chyba serveru", "Server may be unavailable, overloaded, or search timed out :(": "Server může být nedostupný, přetížený nebo vyhledávání vypršelo :(", "Server may be unavailable, overloaded, or you hit a bug.": "Server může být nedostupný, přetížený nebo jste narazili na chybu.", "Server unavailable, overloaded, or something else went wrong.": "Server je nedostupný, přetížený nebo se něco pokazilo.", "Session ID": "ID sezení", - "%(senderName)s set a profile picture.": "%(senderName)s si nastavil/a profilový obrázek.", - "%(senderName)s set their display name to %(displayName)s.": "%(senderName)s si změnil/a zobrazované jméno na %(displayName)s.", + "%(senderName)s set a profile picture.": "%(senderName)s si nastavil(a) profilový obrázek.", + "%(senderName)s set their display name to %(displayName)s.": "%(senderName)s si změnil(a) zobrazované jméno na %(displayName)s.", "Show timestamps in 12 hour format (e.g. 2:30pm)": "Zobrazovat čas v 12hodinovém formátu (např. 2:30 odp.)", "Sign in": "Přihlásit", "Sign out": "Odhlásit", @@ -235,9 +235,9 @@ "Online": "Online", "Offline": "Offline", "Check for update": "Zkontrolovat aktualizace", - "%(targetName)s accepted the invitation for %(displayName)s.": "%(targetName)s přijal/a pozvání pro %(displayName)s.", + "%(targetName)s accepted the invitation for %(displayName)s.": "%(targetName)s přijal(a) pozvání pro %(displayName)s.", "Active call (%(roomName)s)": "Probíhající hovor (%(roomName)s)", - "%(senderName)s banned %(targetName)s.": "%(senderName)s vykázal/a uživatele %(targetName)s.", + "%(senderName)s banned %(targetName)s.": "%(senderName)s vykázal(a) uživatele %(targetName)s.", "Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or enable unsafe scripts.": "Nelze se připojit k domovskému serveru přes HTTP, pokud je v adresním řádku HTTPS. Buď použijte HTTPS, nebo povolte nezabezpečené skripty.", "Click here to fix": "Pro opravu klepněte zde", "Click to mute video": "Klepněte pro zakázání videa", @@ -258,7 +258,7 @@ "Unable to remove contact information": "Nepodařilo se smazat kontaktní údaje", "Unable to verify email address.": "Nepodařilo se ověřit e-mailovou adresu.", "Unban": "Přijmout zpět", - "%(senderName)s unbanned %(targetName)s.": "%(senderName)s přijal/a zpět uživatele %(targetName)s.", + "%(senderName)s unbanned %(targetName)s.": "%(senderName)s přijal(a) zpět uživatele %(targetName)s.", "Unable to capture screen": "Nepodařilo se zachytit obrazovku", "Unable to enable Notifications": "Nepodařilo se povolit oznámení", "unknown caller": "neznámý volající", @@ -305,11 +305,11 @@ "Reason": "Důvod", "VoIP conference started.": "VoIP konference započata.", "VoIP conference finished.": "VoIP konference ukončena.", - "%(targetName)s left the room.": "%(targetName)s opustil/a místnost.", + "%(targetName)s left the room.": "%(targetName)s opustil(a) místnost.", "You are already in a call.": "Již máte probíhající hovor.", "%(senderName)s requested a VoIP conference.": "Uživatel %(senderName)s požádal o VoIP konferenci.", - "%(senderName)s removed their profile picture.": "%(senderName)s odstranil/a svůj profilový obrázek.", - "%(targetName)s rejected the invitation.": "%(targetName)s odmítl/a pozvání.", + "%(senderName)s removed their profile picture.": "%(senderName)s odstranil(a) svůj profilový obrázek.", + "%(targetName)s rejected the invitation.": "%(targetName)s odmítl(a) pozvání.", "Communities": "Skupiny", "Message Pinning": "Připíchnutí zprávy", "Your browser does not support the required cryptography extensions": "Váš prohlížeč nepodporuje požadovaná kryptografická rozšíření", @@ -320,20 +320,20 @@ "Admin Tools": "Nástroje pro správce", "No pinned messages.": "Žádné připíchnuté zprávy.", "Pinned Messages": "Připíchnuté zprávy", - "%(senderName)s removed their display name (%(oldDisplayName)s).": "%(senderName)s odstranil/a své zobrazované jméno (%(oldDisplayName)s).", - "%(senderName)s withdrew %(targetName)s's invitation.": "%(senderName)s zrušil/a pozvání pro uživatele %(targetName)s.", - "%(senderName)s made future room history visible to all room members, from the point they are invited.": "%(senderName)s nastavil/a viditelnost budoucích zpráv v této místnosti pro všechny její členy, a to od chvíle jejich pozvání.", - "%(senderName)s made future room history visible to all room members, from the point they joined.": "%(senderName)s nastavil/a viditelnost budoucích zpráv v této místnosti pro všechny její členy, a to od chvíle jejich vstupu.", - "%(senderName)s made future room history visible to all room members.": "%(senderName)s nastavil/a viditelnost budoucích zpráv v této místnosti pro všechny její členy.", - "%(senderName)s made future room history visible to anyone.": "%(senderName)s nastavil/a viditelnost budoucích zpráv pro kohokoliv.", - "%(senderName)s changed the pinned messages for the room.": "%(senderName)s změnil/a připíchnuté zprávy této místnosti.", + "%(senderName)s removed their display name (%(oldDisplayName)s).": "%(senderName)s odstranil(a) své zobrazované jméno (%(oldDisplayName)s).", + "%(senderName)s withdrew %(targetName)s's invitation.": "%(senderName)s zrušil(a) pozvání pro uživatele %(targetName)s.", + "%(senderName)s made future room history visible to all room members, from the point they are invited.": "%(senderName)s nastavil(a) viditelnost budoucích zpráv v této místnosti pro všechny její členy, a to od chvíle jejich pozvání.", + "%(senderName)s made future room history visible to all room members, from the point they joined.": "%(senderName)s nastavil(a) viditelnost budoucích zpráv v této místnosti pro všechny její členy, a to od chvíle jejich vstupu.", + "%(senderName)s made future room history visible to all room members.": "%(senderName)s nastavil(a) viditelnost budoucích zpráv v této místnosti pro všechny její členy.", + "%(senderName)s made future room history visible to anyone.": "%(senderName)s nastavil(a) viditelnost budoucích zpráv pro kohokoliv.", + "%(senderName)s changed the pinned messages for the room.": "%(senderName)s změnil(a) připíchnuté zprávy této místnosti.", "Authentication check failed: incorrect password?": "Kontrola ověření selhala: špatné heslo?", "You need to be able to invite users to do that.": "Pro tuto akci musíte mít právo zvát uživatele.", "Delete Widget": "Smazat widget", "Error decrypting image": "Chyba při dešifrování obrázku", "Error decrypting video": "Chyba při dešifrování videa", - "%(senderDisplayName)s removed the room avatar.": "%(senderDisplayName)s odstranil/a avatar místnosti.", - "%(senderDisplayName)s changed the room avatar to ": "%(senderDisplayName)s změnil/a avatar místnosti na ", + "%(senderDisplayName)s removed the room avatar.": "%(senderDisplayName)s odstranil(a) avatar místnosti.", + "%(senderDisplayName)s changed the room avatar to ": "%(senderDisplayName)s změnil(a) avatar místnosti na ", "Copied!": "Zkopírováno!", "Failed to copy": "Nepodařilo se zkopírovat", "Deleting a widget removes it for all users in this room. Are you sure you want to delete this widget?": "Smazáním widgetu ho odstraníte všem uživatelům v této místnosti. Opravdu chcete tento widget smazat?", @@ -384,9 +384,9 @@ "Invalid community ID": "Neplatné ID skupiny", "'%(groupId)s' is not a valid community ID": "'%(groupId)s' není platné ID skupiny", "New community ID (e.g. +foo:%(localDomain)s)": "Nové ID skupiny (např. +neco:%(localDomain)s)", - "%(senderName)s sent an image": "%(senderName)s poslal/a obrázek", - "%(senderName)s sent a video": "%(senderName)s poslal/a video", - "%(senderName)s uploaded a file": "%(senderName)s nahrál/a soubor", + "%(senderName)s sent an image": "%(senderName)s poslal(a) obrázek", + "%(senderName)s sent a video": "%(senderName)s poslal(a) video", + "%(senderName)s uploaded a file": "%(senderName)s nahrál(a) soubor", "Disinvite this user?": "Odvolat pozvání tohoto uživatele?", "Kick this user?": "Vykopnout tohoto uživatele?", "Unban this user?": "Přijmout zpět tohoto uživatele?", @@ -398,16 +398,16 @@ "You have disabled URL previews by default.": "Vypnuli jste automatické náhledy webových adres.", "You have enabled URL previews by default.": "Zapnuli jste automatické náhledy webových adres.", "URL Previews": "Náhledy webových adres", - "%(senderDisplayName)s changed the avatar for %(roomName)s": "%(senderDisplayName)s změnil/a avatar místnosti %(roomName)s", + "%(senderDisplayName)s changed the avatar for %(roomName)s": "%(senderDisplayName)s změnil(a) avatar místnosti %(roomName)s", "Add an Integration": "Přidat začlenění", "An email has been sent to %(emailAddress)s": "Na adresu %(emailAddress)s jsme poslali e-mail", "File to import": "Soubor k importu", - "Passphrases must match": "Hesla se musí shodovat", - "Passphrase must not be empty": "Heslo nesmí být prázdné", + "Passphrases must match": "Přístupové fráze se musí shodovat", + "Passphrase must not be empty": "Přístupová fráze nesmí být prázdná", "Export room keys": "Exportovat klíče místnosti", "This process allows you to export the keys for messages you have received in encrypted rooms to a local file. You will then be able to import the file into another Matrix client in the future, so that client will also be able to decrypt these messages.": "Tento proces vám umožňuje exportovat do souboru klíče ke zprávám, které jste dostali v šifrovaných místnostech. Když pak tento soubor importujete do jiného Matrix klienta, všechny tyto zprávy bude možné opět dešifrovat.", - "The exported file will allow anyone who can read it to decrypt any encrypted messages that you can see, so you should be careful to keep it secure. To help with this, you should enter a passphrase below, which will be used to encrypt the exported data. It will only be possible to import the data by using the same passphrase.": "Kdokoliv, kdo získá přístup k exportovanému souboru, bude moci dešifrovat všechny vaše přijaté zprávy, a proto je třeba dbát zvýšenou pozornost jeho zabezpečení. Z toho důvodu byste měli do kolonky níže zadat heslo, se kterým exportovaná data zašifrujeme. Import pak bude možný pouze se znalostí zadaného hesla.", - "Confirm passphrase": "Potvrďte heslo", + "The exported file will allow anyone who can read it to decrypt any encrypted messages that you can see, so you should be careful to keep it secure. To help with this, you should enter a passphrase below, which will be used to encrypt the exported data. It will only be possible to import the data by using the same passphrase.": "Kdokoliv, kdo získá přístup k exportovanému souboru, bude moci dešifrovat všechny vaše přijaté zprávy, a proto je třeba dbát zvýšenou pozornost jeho zabezpečení. Z toho důvodu byste měli do kolonky níže zadat přístupovou frázi, se kterým exportovaná data zašifrujeme. Import pak bude možný pouze se znalostí zadané přístupové fráze.", + "Confirm passphrase": "Potvrďte přístupovou frázi", "Import room keys": "Importovat klíče místnosti", "Call Timeout": "Časový limit hovoru", "Show these rooms to non-members on the community page and room list?": "Zobrazovat tyto místnosti na domovské stránce skupiny a v seznamu místností i pro nečleny?", @@ -466,18 +466,18 @@ "%(nameList)s %(transitionList)s": "%(nameList)s %(transitionList)s", "%(severalUsers)sjoined %(count)s times|other": "%(severalUsers)s%(count)s krát vstoupili", "%(severalUsers)sjoined %(count)s times|one": "%(severalUsers)svstoupili", - "%(oneUser)sjoined %(count)s times|one": "%(oneUser)svstoupil/a", + "%(oneUser)sjoined %(count)s times|one": "%(oneUser)svstoupil(a)", "%(severalUsers)sleft %(count)s times|other": "%(severalUsers)s %(count)s krát opustili", "%(severalUsers)sleft %(count)s times|one": "%(severalUsers)sopustili", "%(oneUser)sleft %(count)s times|other": "%(oneUser)s %(count)s krát opustil", "%(oneUser)sleft %(count)s times|one": "%(oneUser)sopustil", "%(severalUsers)sjoined and left %(count)s times|other": "%(severalUsers)s %(count)s krát vstoupili a opustili", "%(severalUsers)sjoined and left %(count)s times|one": "%(severalUsers)svstoupili a opustili", - "%(oneUser)sjoined and left %(count)s times|other": "%(oneUser)s %(count)s krát vstoupil/a a opustil/a", - "%(oneUser)sjoined and left %(count)s times|one": "%(oneUser)svstoupil/a a opustil/a", + "%(oneUser)sjoined and left %(count)s times|other": "%(oneUser)s %(count)s krát vstoupil(a) a opustil(a)", + "%(oneUser)sjoined and left %(count)s times|one": "%(oneUser)svstoupil(a) a opustil(a)", "%(severalUsers)sleft and rejoined %(count)s times|other": "%(severalUsers)s %(count)s krát opustili a znovu vstoupili", "%(severalUsers)sleft and rejoined %(count)s times|one": "%(severalUsers)sopustili a znovu vstoupili", - "%(oneUser)sleft and rejoined %(count)s times|other": "%(oneUser)s %(count)s krát opustil/a a znovu vstoupil/a", + "%(oneUser)sleft and rejoined %(count)s times|other": "%(oneUser)s %(count)s krát opustil(a) a znovu vstoupil(a)", "%(oneUser)sleft and rejoined %(count)s times|one": "%(oneUser)sopustil a znovu vstoupil", "%(severalUsers)srejected their invitations %(count)s times|other": "%(severalUsers)s %(count)s krát odmítli pozvání", "%(severalUsers)srejected their invitations %(count)s times|one": "%(severalUsers)sodmítli pozvání", @@ -505,12 +505,12 @@ "was kicked %(count)s times|one": "byl vyhozen", "%(severalUsers)schanged their name %(count)s times|other": "%(severalUsers)s si %(count)s krát změnili jméno", "%(severalUsers)schanged their name %(count)s times|one": "%(severalUsers)s si změnili jméno", - "%(oneUser)schanged their name %(count)s times|other": "%(oneUser)s si %(count)s krát změnil/a jméno", - "%(oneUser)schanged their name %(count)s times|one": "%(oneUser)s si změnil/ jméno", + "%(oneUser)schanged their name %(count)s times|other": "%(oneUser)s si %(count)s krát změnil(a) jméno", + "%(oneUser)schanged their name %(count)s times|one": "%(oneUser)s si změnil(a) jméno", "%(severalUsers)schanged their avatar %(count)s times|other": "%(severalUsers)ssi %(count)s krát změnili avatary", "%(severalUsers)schanged their avatar %(count)s times|one": "%(severalUsers)ssi změnili avatary", - "%(oneUser)schanged their avatar %(count)s times|other": "%(oneUser)s si %(count)s krát změnil/a avatar", - "%(oneUser)schanged their avatar %(count)s times|one": "%(oneUser)s si změnil/a avatar", + "%(oneUser)schanged their avatar %(count)s times|other": "%(oneUser)s si %(count)s krát změnil(a) avatar", + "%(oneUser)schanged their avatar %(count)s times|one": "%(oneUser)s si změnil(a) avatar", "%(items)s and %(count)s others|other": "%(items)s a %(count)s další", "%(items)s and %(count)s others|one": "%(items)s a jeden další", "%(items)s and %(lastItem)s": "%(items)s a také %(lastItem)s", @@ -539,7 +539,7 @@ "To get started, please pick a username!": "Začněte tím, že si zvolíte uživatelské jméno!", "This will be your account name on the homeserver, or you can pick a different server.": "Toto bude název vašeho účtu na domovském serveru , anebo si můžete zvolit jiný server.", "If you already have a Matrix account you can log in instead.": "Pokud už účet v síti Matrix máte, můžete se ihned Přihlásit.", - "%(oneUser)sjoined %(count)s times|other": "%(oneUser)s %(count)s krát vstoupil/a", + "%(oneUser)sjoined %(count)s times|other": "%(oneUser)s %(count)s krát vstoupil(a)", "Private Chat": "Soukromá konverzace", "Public Chat": "Veřejná konverzace", "You must register to use this functionality": "Pro využívání této funkce se zaregistrujte", @@ -564,7 +564,7 @@ "These rooms are displayed to community members on the community page. Community members can join the rooms by clicking on them.": "Tyto místnosti se zobrazují všem členům na stránce skupiny. Členové skupiny mohou vstoupit do místnosti klepnutím.", "Featured Rooms:": "Hlavní místnosti:", "Featured Users:": "Významní uživatelé:", - "%(inviter)s has invited you to join this community": "%(inviter)s vás pozval/a do této skupiny", + "%(inviter)s has invited you to join this community": "%(inviter)s vás pozval(a) do této skupiny", "You are an administrator of this community": "Jste správcem této skupiny", "You are a member of this community": "Jste členem této skupiny", "Your community hasn't got a Long Description, a HTML page to show to community members.
Click here to open settings and give it one!": "Vaše skupina nemá vyplněný dlouhý popis, který je součástí HTML stránky skupiny a která se zobrazuje jejím členům.
Klepnutím zde otevřete nastavení, kde ho můžete doplnit!", @@ -606,7 +606,7 @@ "Notify the whole room": "Oznámení pro celou místnost", "Room Notification": "Oznámení místnosti", "This process allows you to import encryption keys that you had previously exported from another Matrix client. You will then be able to decrypt any messages that the other client could decrypt.": "Tento proces vás provede importem šifrovacích klíčů, které jste si stáhli z jiného Matrix klienta. Po úspěšném naimportování budete v tomto klientovi moci dešifrovat všechny zprávy, které jste mohli dešifrovat v původním klientovi.", - "The export file will be protected with a passphrase. You should enter the passphrase here, to decrypt the file.": "Stažený soubor je chráněn heslem. Soubor můžete naimportovat pouze pokud zadáte odpovídající heslo.", + "The export file will be protected with a passphrase. You should enter the passphrase here, to decrypt the file.": "Stažený soubor je chráněn přístupovou frází. Soubor můžete naimportovat pouze pokud zadáte odpovídající přístupovou frázi.", "Call Failed": "Hovor selhal", "Send": "Odeslat", "collapse": "sbalit", @@ -753,7 +753,7 @@ "%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s": "%(weekDayName)s, %(day)s %(monthName)s %(fullYear)s", "Missing roomId.": "Chybějící ID místnosti.", "Opens the Developer Tools dialog": "Otevře dialog nástrojů pro vývojáře", - "%(oldDisplayName)s changed their display name to %(displayName)s.": "%(oldDisplayName)s si změnil/a zobrazované jméno na %(displayName)s.", + "%(oldDisplayName)s changed their display name to %(displayName)s.": "%(oldDisplayName)s si změnil(a) zobrazované jméno na %(displayName)s.", "Always show encryption icons": "Vždy zobrazovat ikonu stavu šifrovaní", "Send analytics data": "Odesílat analytická data", "Enable widget screenshots on supported widgets": "Povolit screenshot widgetu pro podporované widgety", @@ -943,14 +943,14 @@ "Upgrades a room to a new version": "Upgraduje místnost na novou verzi", "This room has no topic.": "Tato místnost nemá žádné specifické téma.", "Sets the room name": "Nastaví název místnosti", - "%(senderDisplayName)s upgraded this room.": "%(senderDisplayName)s upgradoval/a místnost.", - "%(senderDisplayName)s made the room public to whoever knows the link.": "%(senderDisplayName)s zveřejnil/a místnost pro všechny s odkazem.", - "%(senderDisplayName)s made the room invite only.": "%(senderDisplayName)s zpřístupnil/a místnost pouze na pozvání.", - "%(senderDisplayName)s changed the join rule to %(rule)s": "%(senderDisplayName)s změnil/a pravidlo k připojení na %(rule)s", - "%(senderDisplayName)s has allowed guests to join the room.": "%(senderDisplayName)s povolil/a přístup hostům.", - "%(senderDisplayName)s has prevented guests from joining the room.": "%(senderDisplayName)s zakázal/a přístup hostům.", - "%(senderDisplayName)s changed guest access to %(rule)s": "%(senderDisplayName)s změnil/a pravidlo pro přístup hostů na %(rule)s", - "%(senderName)s set the main address for this room to %(address)s.": "%(senderName)s nastavil/a hlavní adresu této místnosti na %(address)s.", + "%(senderDisplayName)s upgraded this room.": "%(senderDisplayName)s upgradoval(a) místnost.", + "%(senderDisplayName)s made the room public to whoever knows the link.": "%(senderDisplayName)s zveřejnil(a) místnost pro všechny s odkazem.", + "%(senderDisplayName)s made the room invite only.": "%(senderDisplayName)s zpřístupnil(a) místnost pouze na pozvání.", + "%(senderDisplayName)s changed the join rule to %(rule)s": "%(senderDisplayName)s změnil(a) pravidlo k připojení na %(rule)s", + "%(senderDisplayName)s has allowed guests to join the room.": "%(senderDisplayName)s povolil(a) přístup hostům.", + "%(senderDisplayName)s has prevented guests from joining the room.": "%(senderDisplayName)s zakázal(a) přístup hostům.", + "%(senderDisplayName)s changed guest access to %(rule)s": "%(senderDisplayName)s změnil(a) pravidlo pro přístup hostů na %(rule)s", + "%(senderName)s set the main address for this room to %(address)s.": "%(senderName)s nastavil(a) hlavní adresu této místnosti na %(address)s.", "%(senderName)s removed the main address for this room.": "%(senderName)s zrušil hlavní adresu této místnosti.", "%(displayName)s is typing …": "%(displayName)s píše …", "%(names)s and %(count)s others are typing …|other": "%(names)s a %(count)s dalších píše …", @@ -1231,10 +1231,10 @@ "You cannot modify widgets in this room.": "V této místnosti nemůžete manipulovat s widgety.", "Sends the given message coloured as a rainbow": "Pošle zprávu v barvách duhy", "Sends the given emote coloured as a rainbow": "Pošle reakci v barvách duhy", - "%(senderDisplayName)s enabled flair for %(groups)s in this room.": "%(senderDisplayName)s přidal/a této místnosti příslušnost ke skupině %(groups)s.", - "%(senderDisplayName)s disabled flair for %(groups)s in this room.": "%(senderDisplayName)s odebral/a této místnosti příslušnost ke skupině %(groups)s.", - "%(senderDisplayName)s enabled flair for %(newGroups)s and disabled flair for %(oldGroups)s in this room.": "%(senderDisplayName)s přidal/a této místnosti příslušnost ke skupině %(newGroups)s a odebral/a k %(oldGroups)s.", - "%(senderName)s revoked the invitation for %(targetDisplayName)s to join the room.": "%(senderName)s zrušil/a pozvání do této místnosti pro uživatele %(targetDisplayName)s.", + "%(senderDisplayName)s enabled flair for %(groups)s in this room.": "%(senderDisplayName)s přidal(a) této místnosti příslušnost ke skupině %(groups)s.", + "%(senderDisplayName)s disabled flair for %(groups)s in this room.": "%(senderDisplayName)s odebral(a) této místnosti příslušnost ke skupině %(groups)s.", + "%(senderDisplayName)s enabled flair for %(newGroups)s and disabled flair for %(oldGroups)s in this room.": "%(senderDisplayName)s přidal(a) této místnosti příslušnost ke skupině %(newGroups)s a odebral(a) k %(oldGroups)s.", + "%(senderName)s revoked the invitation for %(targetDisplayName)s to join the room.": "%(senderName)s zrušil(a) pozvání do této místnosti pro uživatele %(targetDisplayName)s.", "No homeserver URL provided": "Nebyla zadána URL adresa domovského server", "Unexpected error resolving homeserver configuration": "Chyba při zjišťování konfigurace domovského serveru", "The user's homeserver does not support the version of the room.": "Uživatelův domovský server nepodporuje verzi této místnosti.", @@ -1253,11 +1253,11 @@ "Join the conversation with an account": "Připojte se ke konverzaci s účtem", "Sign Up": "Zaregistrovat se", "Sign In": "Přihlásit se", - "You were kicked from %(roomName)s by %(memberName)s": "%(memberName)s vás vykopl/a z místnosti %(roomName)s", + "You were kicked from %(roomName)s by %(memberName)s": "%(memberName)s vás vykopl(a) z místnosti %(roomName)s", "Reason: %(reason)s": "Důvod: %(reason)s", "Forget this room": "Zapomenout na tuto místnost", "Re-join": "Znovu vstoupit", - "You were banned from %(roomName)s by %(memberName)s": "%(memberName)s vás vykázal/a z místnosti %(roomName)s", + "You were banned from %(roomName)s by %(memberName)s": "%(memberName)s vás vykázal(a) z místnosti %(roomName)s", "Something went wrong with your invite to %(roomName)s": "S vaší pozvánkou do místnosti %(roomName)s se něco pokazilo", "You can only join it with a working invite.": "Vstoupit můžete jen s funkční pozvánkou.", "You can still join it because this is a public room.": "I přesto můžete vstoupit, protože tato místnost je veřejná.", @@ -1265,7 +1265,7 @@ "Try to join anyway": "Stejně se pokusit vstoupit", "Do you want to chat with %(user)s?": "Chcete si povídat s %(user)s?", "Do you want to join %(roomName)s?": "Chcete vstoupit do místnosti %(roomName)s?", - " invited you": " vás pozval/a", + " invited you": " vás pozval(a)", "You're previewing %(roomName)s. Want to join it?": "Nahlížíte do místnosti %(roomName)s. Chcete do ní vstoupit?", "%(roomName)s can't be previewed. Do you want to join it?": "%(roomName)s si nelze jen tak prohlížet. Chcete do ní vstoupit?", "This room doesn't exist. Are you sure you're at the right place?": "Tato místnost neexistuje. Jste si jistí, že jste na správném místě?", @@ -1280,7 +1280,7 @@ "Invited by %(sender)s": "Pozván od uživatele %(sender)s", "Error updating flair": "Nepovedlo se změnit příslušnost ke skupině", "There was an error updating the flair for this room. The server may not allow it or a temporary error occurred.": "Pro tuto místnost se nepovedlo změnit příslušnost ke skupině. Možná to server neumožňuje, nebo došlo k dočasné chybě.", - "reacted with %(shortName)s": " reagoval/a s %(shortName)s", + "reacted with %(shortName)s": " reagoval(a) s %(shortName)s", "edited": "upraveno", "Maximize apps": "Maximalizovat aplikace", "Rotate Left": "Otočit doleva", @@ -1509,11 +1509,11 @@ "Show image": "Zobrazit obrázek", "You verified %(name)s": "Ověřili jste %(name)s", "You cancelled verifying %(name)s": "Zrušili jste ověření %(name)s", - "%(name)s cancelled verifying": "%(name)s zrušil/a ověření", + "%(name)s cancelled verifying": "%(name)s zrušil(a) ověření", "You accepted": "Přijali jste", - "%(name)s accepted": "%(name)s přijal/a", + "%(name)s accepted": "%(name)s přijal(a)", "You cancelled": "Zrušili jste", - "%(name)s cancelled": "%(name)s zrušil/a", + "%(name)s cancelled": "%(name)s zrušil(a)", "%(name)s wants to verify": "%(name)s chce ověřit", "You sent a verification request": "Poslali jste požadavek na ověření", "Show all": "Zobrazit vše", @@ -1532,8 +1532,8 @@ "Please create a new issue on GitHub so that we can investigate this bug.": "Vyrobte prosím nové issue na GitHubu abychom mohli chybu opravit.", "%(severalUsers)smade no changes %(count)s times|other": "%(severalUsers)s neudělali %(count)s krát žádnou změnu", "%(severalUsers)smade no changes %(count)s times|one": "%(severalUsers)s neudělali žádnou změnu", - "%(oneUser)smade no changes %(count)s times|other": "%(oneUser)s neudělal/a %(count)s krát žádnou změnu", - "%(oneUser)smade no changes %(count)s times|one": "%(oneUser)s neudělal/a žádnou změnu", + "%(oneUser)smade no changes %(count)s times|other": "%(oneUser)s neudělal(a) %(count)s krát žádnou změnu", + "%(oneUser)smade no changes %(count)s times|one": "%(oneUser)s neudělal(a) žádnou změnu", "e.g. my-room": "např. moje-mistnost", "Use bots, bridges, widgets and sticker packs": "Použít roboty, propojení, widgety a balíky samolepek", "Terms of Service": "Podmínky použití", @@ -1555,7 +1555,7 @@ "Explore": "Procházet", "Filter": "Filtr místností", "Filter rooms…": "Najít místnost…", - "%(creator)s created and configured the room.": "%(creator)s vytvořil/a a nakonfiguroval/a místnost.", + "%(creator)s created and configured the room.": "%(creator)s vytvořil(a) a nakonfiguroval(a) místnost.", "Preview": "Náhled", "View": "Zobrazit", "Find a room…": "Najít místnost…", @@ -1593,23 +1593,23 @@ "%(senderName)s placed a voice call. (not supported by this browser)": "%(senderName)s spustil hovor. (není podporováno tímto prohlížečem)", "%(senderName)s placed a video call.": "%(senderName)s spustil videohovor.", "%(senderName)s placed a video call. (not supported by this browser)": "%(senderName)s spustil videohovor. (není podporováno tímto prohlížečem)", - "%(senderName)s removed the rule banning users matching %(glob)s": "%(senderName)s odstranil/a pravidlo blokující uživatele odpovídající %(glob)s", + "%(senderName)s removed the rule banning users matching %(glob)s": "%(senderName)s odstranil(a) pravidlo blokující uživatele odpovídající %(glob)s", "%(senderName)s removed the rule banning rooms matching %(glob)s": "%(senderName)s odstranil pravidlo blokující místnosti odpovídající %(glob)s", "%(senderName)s removed the rule banning servers matching %(glob)s": "%(senderName)s odstranil pravidlo blokující servery odpovídající %(glob)s", "%(senderName)s removed a ban rule matching %(glob)s": "%(senderName)s odstranil blokující pravidlo %(glob)s", "%(senderName)s updated an invalid ban rule": "%(senderName)s aktualizoval neplatné pravidlo blokování", - "%(senderName)s updated the rule banning users matching %(glob)s for %(reason)s": "%(senderName)s aktualizoval/a pravidlo blokující uživatele odpovídající %(glob)s z důvodu %(reason)s", + "%(senderName)s updated the rule banning users matching %(glob)s for %(reason)s": "%(senderName)s aktualizoval(a) pravidlo blokující uživatele odpovídající %(glob)s z důvodu %(reason)s", "%(senderName)s updated the rule banning rooms matching %(glob)s for %(reason)s": "%(senderName)s aktualizoval pravidlo blokující místnosti odpovídající %(glob)s z důvodu %(reason)s", "%(senderName)s updated the rule banning servers matching %(glob)s for %(reason)s": "%(senderName)s aktualizoval pravidlo blokující servery odpovídající %(glob)s z důvodu %(reason)s", "%(senderName)s updated a ban rule matching %(glob)s for %(reason)s": "%(senderName)s aktualizoval blokovací pravidlo odpovídající %(glob)s z důvodu %(reason)s", - "%(senderName)s created a rule banning users matching %(glob)s for %(reason)s": "%(senderName)s vytvořil/a pravidlo blokující uživatele odpovídající %(glob)s z důvodu %(reason)s", + "%(senderName)s created a rule banning users matching %(glob)s for %(reason)s": "%(senderName)s vytvořil(a) pravidlo blokující uživatele odpovídající %(glob)s z důvodu %(reason)s", "%(senderName)s created a rule banning rooms matching %(glob)s for %(reason)s": "%(senderName)s vytvořil pravidlo blokující místnosti odpovídající %(glob)s z důvodu %(reason)s", "%(senderName)s created a rule banning servers matching %(glob)s for %(reason)s": "%(senderName)s vytvořil pravidlo blokující servery odpovídající %(glob)s z důvodu %(reason)s", "%(senderName)s created a ban rule matching %(glob)s for %(reason)s": "%(senderName)s vytvořil blokovací pravidlo odpovídající %(glob)s z důvodu %(reason)s", - "%(senderName)s changed a rule that was banning users matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s změnil/a pravidlo blokující uživatele odpovídající %(oldGlob)s na uživatele odpovídající %(newGlob)s z důvodu %(reason)s", - "%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s změnil/a pravidlo blokující místnosti odpovídající %(oldGlob)s na místnosti odpovídající %(newGlob)s z důvodu %(reason)s", - "%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s změnil/a pravidlo blokující servery odpovídající %(oldGlob)s na servery odpovídající %(newGlob)s z důvodu %(reason)s", - "%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s změnil/a blokovací pravidlo odpovídající %(oldGlob)s na odpovídající %(newGlob)s z důvodu %(reason)s", + "%(senderName)s changed a rule that was banning users matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s změnil(a) pravidlo blokující uživatele odpovídající %(oldGlob)s na uživatele odpovídající %(newGlob)s z důvodu %(reason)s", + "%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s změnil(a) pravidlo blokující místnosti odpovídající %(oldGlob)s na místnosti odpovídající %(newGlob)s z důvodu %(reason)s", + "%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s změnil(a) pravidlo blokující servery odpovídající %(oldGlob)s na servery odpovídající %(newGlob)s z důvodu %(reason)s", + "%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s změnil(a) blokovací pravidlo odpovídající %(oldGlob)s na odpovídající %(newGlob)s z důvodu %(reason)s", "Try out new ways to ignore people (experimental)": "Vyzkoušejte nové metody ignorování lidí (experimentální)", "Match system theme": "Nastavit podle vzhledu systému", "My Ban List": "Můj seznam zablokovaných", @@ -1873,7 +1873,7 @@ "New session": "Nová relace", "Use this session to verify your new one, granting it access to encrypted messages:": "Použijte tuto relaci pro ověření nové a udělení jí přístupu k vašim šifrovaným zprávám:", "If you didn’t sign in to this session, your account may be compromised.": "Pokud jste se do této nové relace nepřihlásili, váš účet může být kompromitován.", - "This wasn't me": "To jsem nebyl/a já", + "This wasn't me": "To jsem nebyl(a) já", "This will allow you to return to your account after signing out, and sign in on other sessions.": "Toto vám umožní se přihlásit do dalších relací a vrátit se ke svému účtu poté, co se odhlásíte.", "Recovery key mismatch": "Obnovovací klíč neodpovídá", "Incorrect recovery passphrase": "Nesprávné heslo pro obnovení", @@ -1893,7 +1893,7 @@ "Warning: Your personal data (including encryption keys) is still stored in this session. Clear it if you're finished using this session, or want to sign in to another account.": "Varování: Vaše osobní data (včetně šifrovacích klíčů) jsou tu pořád uložena. Smažte je, pokud chcete tuto relaci zahodit, nebo se přihlaste pod jiný účet.", "If you cancel now, you won't complete verifying the other user.": "Pokud teď proces zrušíte, tak nebude druhý uživatel ověřen.", "If you cancel now, you won't complete verifying your other session.": "Pokud teď proces zrušíte, tak nebude druhá relace ověřena.", - "Cancel entering passphrase?": "Zrušit zadávání hesla?", + "Cancel entering passphrase?": "Zrušit zadávání přístupové fráze?", "Setting up keys": "Příprava klíčů", "%(brand)s is missing some components required for securely caching encrypted messages locally. If you'd like to experiment with this feature, build a custom %(brand)s Desktop with search components added.": "%(brand)su chybí nějaké komponenty, které jsou potřeba pro vyhledávání v zabezpečených místnostech. Pokud chcete s touto funkcí experimentovat, tak si pořiďte vlastní %(brand)s Desktop s přidanými komponentami.", "Subscribing to a ban list will cause you to join it!": "Odebíráním seznamu zablokovaných uživatelů se přidáte do jeho místnosti!", @@ -1922,7 +1922,7 @@ "The session you are trying to verify doesn't support scanning a QR code or emoji verification, which is what %(brand)s supports. Try with a different client.": "Relace, kterou se snažíte ověřit, neumožňuje ověření QR kódem ani pomocí emoji, což je to, co %(brand)s podporuje. Zkuste použít jiného klienta.", "Verify by scanning": "Ověřte naskenováním", "You declined": "Odmítli jste", - "%(name)s declined": "%(name)s odmítl/a", + "%(name)s declined": "%(name)s odmítl(a)", "Keep a copy of it somewhere secure, like a password manager or even a safe.": "Uschovejte si kopii na bezpečném místě, například ve správci hesel nebo v trezoru.", "Your recovery key": "Váš obnovovací klíč", "Copy": "Zkopírovat", @@ -1948,7 +1948,7 @@ "Show shortcuts to recently viewed rooms above the room list": "Zobrazovat zkratky do nedávno zobrazených místností navrchu", "Cancelling…": "Rušení…", "Your homeserver does not support cross-signing.": "Váš domovský server nepodporuje cross-signing.", - "Homeserver feature support:": "Funkce podporované domovským serverem:", + "Homeserver feature support:": "Funkce podporovaná domovským serverem:", "Accepting…": "Přijímání…", "Accepting …": "Přijímání…", "Declining …": "Odmítání…", @@ -1963,14 +1963,14 @@ "Mark all as read": "Označit vše jako přečtené", "Not currently indexing messages for any room.": "Aktuálně neindexujeme žádné zprávy.", "%(doneRooms)s out of %(totalRooms)s": "%(doneRooms)s z %(totalRooms)s", - "%(senderDisplayName)s changed the room name from %(oldRoomName)s to %(newRoomName)s.": "%(senderDisplayName)s změnil/a jméno místnosti z %(oldRoomName)s na %(newRoomName)s.", - "%(senderName)s added the alternative addresses %(addresses)s for this room.|other": "%(senderName)s přidal/a této místnosti alternativní adresy %(addresses)s.", - "%(senderName)s added the alternative addresses %(addresses)s for this room.|one": "%(senderName)s přidal/a této místnosti alternativní adresu %(addresses)s.", - "%(senderName)s removed the alternative addresses %(addresses)s for this room.|other": "%(senderName)s odebral/a této místnosti alternativní adresy %(addresses)s.", - "%(senderName)s removed the alternative addresses %(addresses)s for this room.|one": "%(senderName)s odebral/a této místnosti alternativní adresu %(addresses)s.", - "%(senderName)s changed the alternative addresses for this room.": "%(senderName)s změnil/a alternativní adresy této místnosti.", - "%(senderName)s changed the main and alternative addresses for this room.": "%(senderName)s změnil/a hlavní a alternativní adresy této místnosti.", - "%(senderName)s changed the addresses for this room.": "%(senderName)s změnil/a adresy této místnosti.", + "%(senderDisplayName)s changed the room name from %(oldRoomName)s to %(newRoomName)s.": "%(senderDisplayName)s změnil(a) jméno místnosti z %(oldRoomName)s na %(newRoomName)s.", + "%(senderName)s added the alternative addresses %(addresses)s for this room.|other": "%(senderName)s přidal(a) této místnosti alternativní adresy %(addresses)s.", + "%(senderName)s added the alternative addresses %(addresses)s for this room.|one": "%(senderName)s přidal(a) této místnosti alternativní adresu %(addresses)s.", + "%(senderName)s removed the alternative addresses %(addresses)s for this room.|other": "%(senderName)s odebral(a) této místnosti alternativní adresy %(addresses)s.", + "%(senderName)s removed the alternative addresses %(addresses)s for this room.|one": "%(senderName)s odebral(a) této místnosti alternativní adresu %(addresses)s.", + "%(senderName)s changed the alternative addresses for this room.": "%(senderName)s změnil(a) alternativní adresy této místnosti.", + "%(senderName)s changed the main and alternative addresses for this room.": "%(senderName)s změnil(a) hlavní a alternativní adresy této místnosti.", + "%(senderName)s changed the addresses for this room.": "%(senderName)s změnil(a) adresy této místnosti.", "Manually Verify by Text": "Manuální textové ověření", "Interactively verify by Emoji": "Interaktivní ověření s emotikonami", "Support adding custom themes": "Umožnit přidání vlastního vzhledu", @@ -2044,7 +2044,7 @@ "Start verification again from their profile.": "Proces ověření začněte znovu z profilu kontaktu.", "Verification timed out.": "Ověření vypršelo.", "You cancelled verification on your other session.": "Na druhé relace jste proces ověření zrušili.", - "%(displayName)s cancelled verification.": "%(displayName)s zrušil/a proces ověření.", + "%(displayName)s cancelled verification.": "%(displayName)s zrušil(a) proces ověření.", "You cancelled verification.": "Zrušili jste proces ověření.", "Message deleted": "Zpráva smazána", "Message deleted by %(name)s": "Zpráva smazána uživatelem %(name)s", @@ -2104,7 +2104,7 @@ "Restart": "Restartovat", "Upgrade your %(brand)s": "Aktualizovat %(brand)s", "A new version of %(brand)s is available!": "Je dostupná nová verze %(brand)su!", - "Are you sure you want to cancel entering passphrase?": "Chcete určitě zrušit zadávání hesla?", + "Are you sure you want to cancel entering passphrase?": "Chcete určitě zrušit zadávání přístupové fráze?", "Use your account to sign in to the latest version": "Přihlašte se za pomoci svého účtu do nejnovější verze", "Riot is now Element!": "Riot je nyní Element!", "Learn More": "Zjistit více", @@ -2172,7 +2172,7 @@ "%(senderName)s left the call": "%(senderName)s opustil/a hovor", "Call ended": "Hovor skončil", "You started a call": "Začali jste hovor", - "%(senderName)s started a call": "%(senderName)s začal/a hovor", + "%(senderName)s started a call": "%(senderName)s začal(a) hovor", "Waiting for answer": "Čekání na odpověď", "%(senderName)s is calling": "%(senderName)s volá", "* %(senderName)s %(emote)s": "* %(senderName)s %(emote)s", @@ -2193,7 +2193,7 @@ "Incoming call": "Příchozí hovor", "Your server isn't responding to some requests.": "Váš server neodpovídá na některé požadavky.", "Master private key:": "Hlavní soukromý klíč:", - "%(brand)s can't securely cache encrypted messages locally while running in a web browser. Use %(brand)s Desktop for encrypted messages to appear in search results.": "%(brand)s nemůže v prohlížeči lokálně bezpečně uložit zprávy. Použijte %(brand)s Desktop aby fungovalo vyhledávání v šifrovaných zprávách.", + "%(brand)s can't securely cache encrypted messages locally while running in a web browser. Use %(brand)s Desktop for encrypted messages to appear in search results.": "%(brand)s nemůže bezpečně ukládat šifrované zprávy lokálně v prohlížeči. Pro zobrazení šifrovaných zpráv ve výsledcích vyhledávání použijte %(brand)s Desktop.", "Your server admin has disabled end-to-end encryption by default in private rooms & Direct Messages.": "Váš administrátor vypnul šifrování ve výchozím nastavení soukromých místností a přímých chatů.", "To link to this room, please add an address.": "Přidejte prosím místnosti adresu aby na ní šlo odkazovat.", "The authenticity of this encrypted message can't be guaranteed on this device.": "Pravost této šifrované zprávy nelze na tomto zařízení ověřit.", @@ -2256,7 +2256,7 @@ "Start a new chat": "Založit novou konverzaci", "Which officially provided instance you are using, if any": "Kterou oficiální instanci Riot.im používáte (a jestli vůbec)", "Change the topic of this room": "Změnit téma této místnosti", - "%(senderName)s declined the call.": "%(senderName)s odmítl/a hovor.", + "%(senderName)s declined the call.": "%(senderName)s odmítl(a) hovor.", "(an error occurred)": "(došlo k chybě)", "(their device couldn't start the camera / microphone)": "(zařízení druhé strany nemohlo spustit kameru / mikrofon)", "(connection failed)": "(spojení selhalo)", @@ -2295,7 +2295,7 @@ "Attach files from chat or just drag and drop them anywhere in a room.": "Připojte soubory z chatu nebo je jednoduše přetáhněte kamkoli do místnosti.", "No files visible in this room": "V této místnosti nejsou viditelné žádné soubory", "Show files": "Zobrazit soubory", - "%(count)s people|other": "%(count)s lidé/í", + "%(count)s people|other": "%(count)s lidí", "About": "O", "You’re all caught up": "Vše vyřízeno", "You have no visible notifications in this room.": "V této místnosti nemáte žádná viditelná oznámení.", @@ -2333,10 +2333,10 @@ "Switch to light mode": "Přepnout do světlého režimu", "User settings": "Uživatelská nastavení", "Community settings": "Nastavení skupiny", - "Confirm your recovery passphrase": "Potvrďte vaši frázi pro obnovení", + "Confirm your recovery passphrase": "Potvrďte vaši přístupovou frázi pro obnovení", "Repeat your recovery passphrase...": "Opakujte přístupovou frázi pro obnovení...", "Please enter your recovery passphrase a second time to confirm.": "Potvrďte prosím podruhé svou frázi pro obnovení.", - "Use a different passphrase?": "Použít jinou frázi?", + "Use a different passphrase?": "Použít jinou přístupovou frázi?", "Great! This recovery passphrase looks strong enough.": "Skvělé! Tato fráze pro obnovení vypadá dostatečně silně.", "Enter a recovery passphrase": "Zadejte frázi pro obnovení", "%(ssoButtons)s Or %(usernamePassword)s": "%(ssoButtons)s nebo %(usernamePassword)s", @@ -2439,7 +2439,7 @@ "There are two ways you can provide feedback and help us improve %(brand)s.": "Jsou dva způsoby, jak můžete poskytnout zpětnou vazbu a pomoci nám vylepšit %(brand)s.", "Rate %(brand)s": "Ohodnotit %(brand)s", "You've previously used a newer version of %(brand)s with this session. To use this version again with end to end encryption, you will need to sign out and back in again.": "V této relaci jste již dříve používali novější verzi %(brand)s. Chcete-li tuto verzi znovu použít s šifrováním, budete se muset odhlásit a znovu přihlásit.", - "Homeserver": "Homeserver", + "Homeserver": "Domovský server", "Continue with %(provider)s": "Pokračovat s %(provider)s", "Server Options": "Možnosti serveru", "This version of %(brand)s does not support viewing some encrypted files": "Tato verze %(brand)s nepodporuje zobrazení některých šifrovaných souborů", @@ -2789,7 +2789,7 @@ "Fill Screen": "Vyplnit obrazovku", "Voice Call": "Hlasový hovor", "Video Call": "Videohovor", - "%(senderName)s ended the call": "%(senderName)s ukončil/a hovor", + "%(senderName)s ended the call": "%(senderName)s ukončil(a) hovor", "You ended the call": "Ukončili jste hovor", "New version of %(brand)s is available": "K dispozici je nová verze %(brand)s", "Error leaving room": "Při opouštění místnosti došlo k chybě", @@ -2879,7 +2879,7 @@ "Prepends (╯°□°)╯︵ ┻━┻ to a plain-text message": "Vloží (╯°□°)╯︵ ┻━┻ na začátek zprávy", "Remain on your screen while running": "Při běhu zůstává na obrazovce", "Remain on your screen when viewing another room, when running": "Při prohlížení jiné místnosti zůstává při běhu na obrazovce", - "%(senderDisplayName)s changed the server ACLs for this room.": "%(senderDisplayName)s změnil/a seznam přístupů serveru pro tuto místnost.", + "%(senderDisplayName)s changed the server ACLs for this room.": "%(senderDisplayName)s změnil(a) seznam přístupů serveru pro tuto místnost.", "Offline encrypted messaging using dehydrated devices": "Offline šifrovaná komunikace pomocí dehydrovaných zařízení", "See emotes posted to your active room": "Prohlédněte si emoji zveřejněné ve vaší aktivní místnosti", "See emotes posted to this room": "Prohlédněte si emoji zveřejněné v této místnosti", @@ -2968,5 +2968,18 @@ "Share your screen": "Sdílejte svou obrazovku", "Expand code blocks by default": "Ve výchozím nastavení rozbalit bloky kódu", "Show line numbers in code blocks": "Zobrazit čísla řádků v blocích kódu", - "Recently visited rooms": "Nedávno navštívené místnosti" + "Recently visited rooms": "Nedávno navštívené místnosti", + "Upgrade to pro": "Upgradujte na profesionální verzi", + "Minimize dialog": "Minimalizovat dialog", + "Maximize dialog": "Maximalizovat dialog", + "%(hostSignupBrand)s Setup": "Nastavení %(hostSignupBrand)s", + "You should know": "Měli byste vědět", + "Privacy Policy": "Zásady ochrany osobních údajů", + "Cookie Policy": "Zásady používání souborů cookie", + "Learn more in our , and .": "Další informace najdete v našich , a .", + "Continuing temporarily allows the %(hostSignupBrand)s setup process to access your account to fetch verified email addresses. This data is not stored.": "Dočasné pokračování umožňuje procesu nastavení %(hostSignupBrand)s přístup k vašemu účtu za účelem načtení ověřených e-mailových adres. Tato data se neukládají.", + "Failed to connect to your homeserver. Please close this dialog and try again.": "Připojení k domovskému serveru se nezdařilo. Zavřete toto dialogové okno a zkuste to znovu.", + "Abort": "Přerušit", + "Are you sure you wish to abort creation of the host? The process cannot be continued.": "Opravdu chcete přerušit vytváření hostitele? Proces nemůže být navázán.", + "Confirm abort of host creation": "Potvrďte přerušení vytváření hostitele" } From 5535d7fb97da0af2e1bdd776c6ded1030e5392ee Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 16 Feb 2021 14:52:11 +0000 Subject: [PATCH 112/479] Prepare to encrypt when a call arrives So we're ready to send an answer straight away if the user answers --- src/CallHandler.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index f106d75f8b..2be1c34a9f 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -681,6 +681,12 @@ export default class CallHandler { Analytics.trackEvent('voip', 'receiveCall', 'type', call.type); this.calls.set(mappedRoomId, call) this.setCallListeners(call); + + // get ready to send encrypted events in the room, so if the user does answer + // the call, we'll be ready to send. NB. This is the protocol-level room ID not + // the mapped one: that's where we'll send the events. + const cli = MatrixClientPeg.get(); + cli.prepareToEncrypt(cli.getRoom(call.roomId)); } break; case 'hangup': From bb6659f9839b87e94e4235ce113c6102bf7f1cc8 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 16 Feb 2021 15:48:58 +0000 Subject: [PATCH 113/479] Set ICE candidate pool size option So we can start candidate gathering in advance --- src/MatrixClientPeg.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/MatrixClientPeg.ts b/src/MatrixClientPeg.ts index bb4be663b6..98ca446532 100644 --- a/src/MatrixClientPeg.ts +++ b/src/MatrixClientPeg.ts @@ -279,6 +279,10 @@ class _MatrixClientPeg implements IMatrixClientPeg { timelineSupport: true, forceTURN: !SettingsStore.getValue('webRtcAllowPeerToPeer'), fallbackICEServerAllowed: !!SettingsStore.getValue('fallbackICEServerAllowed'), + // Gather up to 20 ICE candidates when a call arrives: this should be more than we'd + // ever normally need, so effectively this should make all the gathering happen when + // the call arrives. + iceCandidatePoolSize: 20, verificationMethods: [ verificationMethods.SAS, SHOW_QR_CODE_METHOD, From 6cb3381df59d576389ac69f1e4b01c99515fb0e6 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 16 Feb 2021 18:03:12 +0000 Subject: [PATCH 114/479] Remove redundant lockOrigin parameter from usercontent now that each Element has its own, and not usercontent.riot.im it only has to permit its own origin --- src/components/views/messages/MFileBody.js | 2 +- src/usercontent/index.js | 9 +-------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/components/views/messages/MFileBody.js b/src/components/views/messages/MFileBody.js index d17a1c4ce3..770cd4fff3 100644 --- a/src/components/views/messages/MFileBody.js +++ b/src/components/views/messages/MFileBody.js @@ -288,7 +288,7 @@ export default class MFileBody extends React.Component {