From 53db386731422c88d4e24e299e9e56a150dad3cf Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 10 Aug 2020 22:06:30 -0600 Subject: [PATCH 0001/1449] Add support for blurhash (MSC2448) MSC: https://github.com/matrix-org/matrix-doc/pull/2448 While the image loads, we can show a blurred version of it (calculated at upload time) so we don't have a blank space in the timeline. --- package.json | 1 + src/ContentMessages.tsx | 10 +++- .../views/elements/BlurhashPlaceholder.tsx | 56 +++++++++++++++++++ src/components/views/messages/MImageBody.js | 18 +++--- yarn.lock | 5 ++ 5 files changed, 81 insertions(+), 9 deletions(-) create mode 100644 src/components/views/elements/BlurhashPlaceholder.tsx diff --git a/package.json b/package.json index 548b33f353..989672d414 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "@babel/runtime": "^7.10.5", "await-lock": "^2.0.1", "blueimp-canvas-to-blob": "^3.27.0", + "blurhash": "^1.1.3", "browser-encrypt-attachment": "^0.3.0", "browser-request": "^0.3.3", "classnames": "^2.2.6", diff --git a/src/ContentMessages.tsx b/src/ContentMessages.tsx index 6f55a75d0c..7e57b34ff7 100644 --- a/src/ContentMessages.tsx +++ b/src/ContentMessages.tsx @@ -334,6 +334,7 @@ function uploadFile(matrixClient: MatrixClient, roomId: string, file: File | Blo if (file.type) { encryptInfo.mimetype = file.type; } + // TODO: Blurhash for encrypted media? return {"file": encryptInfo}; }); (prom as IAbortablePromise).abort = () => { @@ -344,11 +345,15 @@ function uploadFile(matrixClient: MatrixClient, roomId: string, file: File | Blo } else { const basePromise = matrixClient.uploadContent(file, { progressHandler: progressHandler, + onlyContentUri: false, }); - const promise1 = basePromise.then(function(url) { + const promise1 = basePromise.then(function(body) { if (canceled) throw new UploadCanceledError(); // If the attachment isn't encrypted then include the URL directly. - return {"url": url}; + return { + "url": body.content_uri, + "blurhash": body["xyz.amorgan.blurhash"], // TODO: Use `body.blurhash` when MSC2448 lands + }; }); promise1.abort = () => { canceled = true; @@ -550,6 +555,7 @@ export default class ContentMessages { return upload.promise.then(function(result) { content.file = result.file; content.url = result.url; + content.info['xyz.amorgan.blurhash'] = result.blurhash; // TODO: Use `blurhash` when MSC2448 lands }); }).then(() => { // Await previous message being sent into the room diff --git a/src/components/views/elements/BlurhashPlaceholder.tsx b/src/components/views/elements/BlurhashPlaceholder.tsx new file mode 100644 index 0000000000..bed45bfe5a --- /dev/null +++ b/src/components/views/elements/BlurhashPlaceholder.tsx @@ -0,0 +1,56 @@ +/* + 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 React from 'react'; +import {decode} from "blurhash"; + +interface IProps { + blurhash: string; + width: number; + height: number; +} + +export default class BlurhashPlaceholder extends React.PureComponent { + private canvas: React.RefObject = React.createRef(); + + public componentDidMount() { + this.draw(); + } + + public componentDidUpdate() { + this.draw(); + } + + private draw() { + if (!this.canvas.current) return; + + try { + const {width, height} = this.props; + + const pixels = decode(this.props.blurhash, Math.ceil(width), Math.ceil(height)); + const ctx = this.canvas.current.getContext("2d"); + const imgData = ctx.createImageData(width, height); + imgData.data.set(pixels); + ctx.putImageData(imgData, 0, 0); + } catch (e) { + console.error("Error rendering blurhash: ", e); + } + } + + public render() { + return ; + } +} diff --git a/src/components/views/messages/MImageBody.js b/src/components/views/messages/MImageBody.js index c92ae475bf..e0ac24c641 100644 --- a/src/components/views/messages/MImageBody.js +++ b/src/components/views/messages/MImageBody.js @@ -27,6 +27,7 @@ import { _t } from '../../../languageHandler'; import SettingsStore from "../../../settings/SettingsStore"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; import InlineSpinner from '../elements/InlineSpinner'; +import BlurhashPlaceholder from "../elements/BlurhashPlaceholder"; export default class MImageBody extends React.Component { static propTypes = { @@ -53,6 +54,8 @@ export default class MImageBody extends React.Component { this.onClick = this.onClick.bind(this); this._isGif = this._isGif.bind(this); + const imageInfo = this.props.mxEvent.getContent().info; + this.state = { decryptedUrl: null, decryptedThumbnailUrl: null, @@ -63,6 +66,7 @@ export default class MImageBody extends React.Component { loadedImageDimensions: null, hover: false, showImage: SettingsStore.getValue("showImages"), + blurhash: imageInfo ? imageInfo['xyz.amorgan.blurhash'] : null, // TODO: Use `blurhash` when MSC2448 lands. }; this._image = createRef(); @@ -329,7 +333,8 @@ export default class MImageBody extends React.Component { infoWidth = content.info.w; infoHeight = content.info.h; } else { - // Whilst the image loads, display nothing. + // Whilst the image loads, display nothing. We also don't display a blurhash image + // because we don't really know what size of image we'll end up with. // // Once loaded, use the loaded image dimensions stored in `loadedImageDimensions`. // @@ -368,8 +373,7 @@ export default class MImageBody extends React.Component { if (content.file !== undefined && this.state.decryptedUrl === null) { placeholder = ; } else if (!this.state.imgLoaded) { - // Deliberately, getSpinner is left unimplemented here, MStickerBody overides - placeholder = this.getPlaceholder(); + placeholder = this.getPlaceholder(maxWidth, maxHeight); } let showPlaceholder = Boolean(placeholder); @@ -391,7 +395,7 @@ export default class MImageBody extends React.Component { if (!this.state.showImage) { img = ; - showPlaceholder = false; // because we're hiding the image, so don't show the sticker icon. + showPlaceholder = false; // because we're hiding the image, so don't show the placeholder. } if (this._isGif() && !SettingsStore.getValue("autoplayGifsAndVideos") && !this.state.hover) { @@ -433,9 +437,9 @@ export default class MImageBody extends React.Component { } // Overidden by MStickerBody - getPlaceholder() { - // MImageBody doesn't show a placeholder whilst the image loads, (but it could do) - return null; + getPlaceholder(width, height) { + if (!this.state.blurhash) return null; + return ; } // Overidden by MStickerBody diff --git a/yarn.lock b/yarn.lock index 98fe42ef13..f1cace67a1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2493,6 +2493,11 @@ blueimp-canvas-to-blob@^3.27.0: resolved "https://registry.yarnpkg.com/blueimp-canvas-to-blob/-/blueimp-canvas-to-blob-3.27.0.tgz#a2bd5c43587b95dedf0f6998603452d1bfcc9b9e" integrity sha512-AcIj+hCw6WquxzJuzC6KzgYmqxLFeTWe88KuY2BEIsW1zbEOfoinDAGlhyvFNGt+U3JElkVSK7anA1FaSdmmfA== +blurhash@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/blurhash/-/blurhash-1.1.3.tgz#dc325af7da836d07a0861d830bdd63694382483e" + integrity sha512-yUhPJvXexbqbyijCIE/T2NCXcj9iNPhWmOKbPTuR/cm7Q5snXYIfnVnz6m7MWOXxODMz/Cr3UcVkRdHiuDVRDw== + bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.4.0: version "4.11.9" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828" From e33f4ba9c0e8c29cf074f566cbb69c27007f6c57 Mon Sep 17 00:00:00 2001 From: Resynth Date: Sun, 25 Oct 2020 22:04:39 +0000 Subject: [PATCH 0002/1449] Warn on Access Token reveal Signed-off-by: Resynth --- .../views/dialogs/AccessTokenDialog.tsx | 39 +++++++++++++++++++ .../settings/tabs/user/HelpUserSettingsTab.js | 14 ++++++- 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 src/components/views/dialogs/AccessTokenDialog.tsx diff --git a/src/components/views/dialogs/AccessTokenDialog.tsx b/src/components/views/dialogs/AccessTokenDialog.tsx new file mode 100644 index 0000000000..81c48f219a --- /dev/null +++ b/src/components/views/dialogs/AccessTokenDialog.tsx @@ -0,0 +1,39 @@ + /* +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 { _t } from '../../../languageHandler'; +import QuestionDialog from './QuestionDialog'; + +type IProps = Exclude< + React.ComponentProps, + "title" | "danger" | "description" + >; + +export default function AccessTokenDialog (props: IProps) { + return ( + + ); +} diff --git a/src/components/views/settings/tabs/user/HelpUserSettingsTab.js b/src/components/views/settings/tabs/user/HelpUserSettingsTab.js index 85ba22a353..585a54ff86 100644 --- a/src/components/views/settings/tabs/user/HelpUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/HelpUserSettingsTab.js @@ -27,6 +27,7 @@ import * as sdk from "../../../../../"; import PlatformPeg from "../../../../../PlatformPeg"; import * as KeyboardShortcuts from "../../../../../accessibility/KeyboardShortcuts"; import UpdateCheckButton from "../../UpdateCheckButton"; +import AccessTokenDialog from '../../../dialogs/AccessTokenDialog'; export default class HelpUserSettingsTab extends React.Component { static propTypes = { @@ -148,6 +149,17 @@ export default class HelpUserSettingsTab extends React.Component { ); } + onAccessTokenSpoilerClick = async (event) => { + // React throws away the event before we can use it (we are async, after all). + event.persist(); + + // We make the user accept a scary popup to combat Social Engineering. No peeking! + await Modal.createTrackedDialog('Reveal Access Token', '', AccessTokenDialog).finished; + + // Pass it onto the handler. + this._showSpoiler(event); + } + render() { const brand = SdkConfig.get().brand; @@ -266,7 +278,7 @@ export default class HelpUserSettingsTab extends React.Component { {_t("Homeserver is")} {MatrixClientPeg.get().getHomeserverUrl()}
{_t("Identity Server is")} {MatrixClientPeg.get().getIdentityServerUrl()}
{_t("Access Token:") + ' '} - <{ _t("click to reveal") }> From ae29168e077be47a83628f10b7765d6bcc9a7a0a Mon Sep 17 00:00:00 2001 From: Resynth Date: Sun, 25 Oct 2020 22:05:44 +0000 Subject: [PATCH 0003/1449] Lint Signed-off-by: Resynth --- src/components/views/dialogs/AccessTokenDialog.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/views/dialogs/AccessTokenDialog.tsx b/src/components/views/dialogs/AccessTokenDialog.tsx index 81c48f219a..f95effd523 100644 --- a/src/components/views/dialogs/AccessTokenDialog.tsx +++ b/src/components/views/dialogs/AccessTokenDialog.tsx @@ -1,4 +1,4 @@ - /* +/* Copyright 2017 Vector Creations Ltd Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,7 +23,7 @@ type IProps = Exclude< "title" | "danger" | "description" >; -export default function AccessTokenDialog (props: IProps) { +export default function AccessTokenDialog(props: IProps) { return ( ); From 76edd551e5833cb1c94c1025fa069aeb79a9faa2 Mon Sep 17 00:00:00 2001 From: Resynth Date: Mon, 26 Oct 2020 00:34:14 +0000 Subject: [PATCH 0004/1449] Fix i18n Signed-off-by: Resynth --- src/i18n/strings/en_EN.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index eda69d68ea..ad6593f704 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1585,6 +1585,7 @@ "Add a new server...": "Add a new server...", "%(networkName)s rooms": "%(networkName)s rooms", "Matrix rooms": "Matrix rooms", + "Do not reveal your Access Token to anyone, under any circumstances. Sharing your Access Token with someone would allow them to login to your account, and access your private information.": "Do not reveal your Access Token to anyone, under any circumstances. Sharing your Access Token with someone would allow them to login to your account, and access your private information.", "Matrix ID": "Matrix ID", "Matrix Room ID": "Matrix Room ID", "email address": "email address", From a3212c0477ec0fc9166a56a49a9579bae4712d5f Mon Sep 17 00:00:00 2001 From: Resynth Date: Mon, 26 Oct 2020 23:46:53 +0000 Subject: [PATCH 0005/1449] Fix weird formatting Signed-off-by: Resynth --- src/components/views/dialogs/AccessTokenDialog.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/views/dialogs/AccessTokenDialog.tsx b/src/components/views/dialogs/AccessTokenDialog.tsx index f95effd523..2d96d8ec20 100644 --- a/src/components/views/dialogs/AccessTokenDialog.tsx +++ b/src/components/views/dialogs/AccessTokenDialog.tsx @@ -1,5 +1,6 @@ /* Copyright 2017 Vector Creations Ltd +Copyright 2020 Resynth Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -21,7 +22,7 @@ import QuestionDialog from './QuestionDialog'; type IProps = Exclude< React.ComponentProps, "title" | "danger" | "description" - >; +>; export default function AccessTokenDialog(props: IProps) { return ( From 34fbed3fbbbbb0ffc17a15631d256b855080b1ee Mon Sep 17 00:00:00 2001 From: Qt Resynth Date: Fri, 20 Nov 2020 01:15:58 +0000 Subject: [PATCH 0006/1449] Update src/components/views/dialogs/AccessTokenDialog.tsx --- src/components/views/dialogs/AccessTokenDialog.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/views/dialogs/AccessTokenDialog.tsx b/src/components/views/dialogs/AccessTokenDialog.tsx index 2d96d8ec20..6a943eb5a8 100644 --- a/src/components/views/dialogs/AccessTokenDialog.tsx +++ b/src/components/views/dialogs/AccessTokenDialog.tsx @@ -31,9 +31,7 @@ export default function AccessTokenDialog(props: IProps) { title="Reveal Access Token" danger={true} description={_t( - "Do not reveal your Access Token to anyone, under any circumstances. " + - "Sharing your Access Token with someone would allow them to login to " + - "your account, and access your private information.", + "Your access token gives full access to your account. Do not share it with anyone." )} > ); From 0e4d656e4bfc0fd16d4628ac44668f6aa2f5ae83 Mon Sep 17 00:00:00 2001 From: Resynth Date: Fri, 20 Nov 2020 18:21:39 +0000 Subject: [PATCH 0007/1449] Update src/i18n/strings/en_EN.json --- 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 ad6593f704..8005f1cdef 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1585,7 +1585,7 @@ "Add a new server...": "Add a new server...", "%(networkName)s rooms": "%(networkName)s rooms", "Matrix rooms": "Matrix rooms", - "Do not reveal your Access Token to anyone, under any circumstances. Sharing your Access Token with someone would allow them to login to your account, and access your private information.": "Do not reveal your Access Token to anyone, under any circumstances. Sharing your Access Token with someone would allow them to login to your account, and access your private information.", + "Your access token gives full access to your account. Do not share it with anyone.", "Matrix ID": "Matrix ID", "Matrix Room ID": "Matrix Room ID", "email address": "email address", From 1b48b08525f75035b9a09993124a12d442d0f2e2 Mon Sep 17 00:00:00 2001 From: Resynth Date: Fri, 20 Nov 2020 18:23:18 +0000 Subject: [PATCH 0008/1449] Update src/i18n/strings/en_EN.json --- 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 8005f1cdef..a57a68e7b4 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1585,7 +1585,7 @@ "Add a new server...": "Add a new server...", "%(networkName)s rooms": "%(networkName)s rooms", "Matrix rooms": "Matrix rooms", - "Your access token gives full access to your account. Do not share it with anyone.", + "Your access token gives full access to your account. Do not share it with anyone.": "Your access token gives full access to your account. Do not share it with anyone.", "Matrix ID": "Matrix ID", "Matrix Room ID": "Matrix Room ID", "email address": "email address", From d44aab6d321d04deb6733d9ace5f54b5fe1104bf Mon Sep 17 00:00:00 2001 From: Resynth Date: Mon, 23 Nov 2020 12:57:06 +0000 Subject: [PATCH 0009/1449] Update src/components/views/dialogs/AccessTokenDialog.tsx Co-authored-by: Michael Telatynski <7t3chguy@googlemail.com> --- src/components/views/dialogs/AccessTokenDialog.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/dialogs/AccessTokenDialog.tsx b/src/components/views/dialogs/AccessTokenDialog.tsx index 6a943eb5a8..c0b1b929df 100644 --- a/src/components/views/dialogs/AccessTokenDialog.tsx +++ b/src/components/views/dialogs/AccessTokenDialog.tsx @@ -31,7 +31,7 @@ export default function AccessTokenDialog(props: IProps) { title="Reveal Access Token" danger={true} description={_t( - "Your access token gives full access to your account. Do not share it with anyone." + "Your access token gives full access to your account. Do not share it with anyone.", )} >
); From 6f464feded9c3ea9541bd2be9a5a704bc70ba2b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 23 Feb 2021 18:12:46 +0100 Subject: [PATCH 0010/1449] Quit sticker picker on m.sticker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/elements/AppTile.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index 213351889f..9a345a7bf6 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -226,6 +226,7 @@ export default class AppTile extends React.Component { case 'm.sticker': if (this._sgWidget.widgetApi.hasCapability(MatrixCapabilities.StickerSending)) { dis.dispatch({action: 'post_sticker_message', data: payload.data}); + dis.dispatch({action: 'stickerpicker_close'}); } else { console.warn('Ignoring sticker message. Invalid capability'); } From 40b684d7de997f667d858ad13a1c8bb9d373c576 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Tue, 23 Feb 2021 19:41:23 -0500 Subject: [PATCH 0011/1449] Vectorize spinners This replaces most of the GIF spinners used throughout the app with an SVG that respects the user's theme. However, spinner.gif is still retained for the room timeline avatar uploader component, since it is more difficult to replace. Signed-off-by: Robin Townsend --- res/css/views/elements/_InlineSpinner.scss | 19 +- res/css/views/elements/_Spinner.scss | 16 ++ res/img/logo-spinner.svg | 141 +++++++++++ res/img/spinner.svg | 235 +++++++----------- .../views/elements/InlineSpinner.js | 26 +- src/components/views/elements/Spinner.js | 28 ++- 6 files changed, 304 insertions(+), 161 deletions(-) create mode 100644 res/img/logo-spinner.svg diff --git a/res/css/views/elements/_InlineSpinner.scss b/res/css/views/elements/_InlineSpinner.scss index 6b91e45923..c850191b93 100644 --- a/res/css/views/elements/_InlineSpinner.scss +++ b/res/css/views/elements/_InlineSpinner.scss @@ -18,7 +18,24 @@ limitations under the License. display: inline; } -.mx_InlineSpinner_spin img { +.mx_InlineSpinner img, .mx_InlineSpinner_icon { margin: 0px 6px; vertical-align: -3px; } + +@keyframes spin { + from { + transform: rotateZ(0deg); + } + to { + transform: rotateZ(360deg); + } +} + +.mx_InlineSpinner_icon { + display: inline-block; + background-color: $primary-fg-color; + mask: url('$(res)/img/spinner.svg'); + mask-size: contain; + animation: 1.1s steps(12, end) infinite spin; +} diff --git a/res/css/views/elements/_Spinner.scss b/res/css/views/elements/_Spinner.scss index 01b4f23c2c..93d5e2d96c 100644 --- a/res/css/views/elements/_Spinner.scss +++ b/res/css/views/elements/_Spinner.scss @@ -26,3 +26,19 @@ limitations under the License. .mx_MatrixChat_middlePanel .mx_Spinner { height: auto; } + +@keyframes spin { + from { + transform: rotateZ(0deg); + } + to { + transform: rotateZ(360deg); + } +} + +.mx_Spinner_icon { + background-color: $primary-fg-color; + mask: url('$(res)/img/spinner.svg'); + mask-size: contain; + animation: 1.1s steps(12, end) infinite spin; +} diff --git a/res/img/logo-spinner.svg b/res/img/logo-spinner.svg new file mode 100644 index 0000000000..08965e982e --- /dev/null +++ b/res/img/logo-spinner.svg @@ -0,0 +1,141 @@ + + + start + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/img/spinner.svg b/res/img/spinner.svg index 08965e982e..c3680f19d2 100644 --- a/res/img/spinner.svg +++ b/res/img/spinner.svg @@ -1,141 +1,96 @@ - - - start - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/src/components/views/elements/InlineSpinner.js b/src/components/views/elements/InlineSpinner.js index 73316157f4..2dad9ebe1e 100644 --- a/src/components/views/elements/InlineSpinner.js +++ b/src/components/views/elements/InlineSpinner.js @@ -24,23 +24,29 @@ export default class InlineSpinner extends React.Component { const h = this.props.h || 16; const imgClass = this.props.imgClassName || ""; - let imageSource; + let icon; if (SettingsStore.getValue('feature_new_spinner')) { - imageSource = require("../../../../res/img/spinner.svg"); - } else { - imageSource = require("../../../../res/img/spinner.gif"); - } - - return ( -
+ icon = ( -
+ ); + } else { + icon = ( +
+ ); + } + + return ( +
{ icon }
); } } diff --git a/src/components/views/elements/Spinner.js b/src/components/views/elements/Spinner.js index 4d2dcea90a..43030d01d5 100644 --- a/src/components/views/elements/Spinner.js +++ b/src/components/views/elements/Spinner.js @@ -21,23 +21,31 @@ import {_t} from "../../../languageHandler"; import SettingsStore from "../../../settings/SettingsStore"; const Spinner = ({w = 32, h = 32, imgClassName, message}) => { - let imageSource; + let icon; if (SettingsStore.getValue('feature_new_spinner')) { - imageSource = require("../../../../res/img/spinner.svg"); - } else { - imageSource = require("../../../../res/img/spinner.gif"); - } - - return ( -
- { message &&
{ message}
 
} + icon = ( + ); + } else { + icon = ( +
+ ); + } + + return ( +
+ { message &&
{ message }
 
} + { icon }
); }; From 62e9d7f46bfb6ee07b012904a993d443ee87590e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sat, 6 Mar 2021 09:02:15 +0100 Subject: [PATCH 0012/1449] Cleaner imports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/CallView.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/views/voip/CallView.tsx b/src/components/views/voip/CallView.tsx index b4dad3b19a..fbd30cbc9b 100644 --- a/src/components/views/voip/CallView.tsx +++ b/src/components/views/voip/CallView.tsx @@ -22,8 +22,7 @@ import {MatrixClientPeg} from '../../../MatrixClientPeg'; import { _t, _td } from '../../../languageHandler'; import VideoFeed, { VideoFeedType } from "./VideoFeed"; import RoomAvatar from "../avatars/RoomAvatar"; -import { CallState, CallType, MatrixCall } from 'matrix-js-sdk/src/webrtc/call'; -import { CallEvent } from 'matrix-js-sdk/src/webrtc/call'; +import { CallState, CallType, MatrixCall, CallEvent } from 'matrix-js-sdk/src/webrtc/call'; import classNames from 'classnames'; import AccessibleButton from '../elements/AccessibleButton'; import {isOnlyCtrlOrCmdKeyEvent, Key} from '../../../Keyboard'; From bb13dc49a6d89a1f1a50c762b3c241fc5d4b9757 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sun, 7 Mar 2021 08:13:35 +0100 Subject: [PATCH 0013/1449] Make CallView use CallFeed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/voip/_CallView.scss | 1 + res/css/views/voip/_VideoFeed.scss | 18 +++- src/CallHandler.tsx | 12 +-- src/components/views/voip/CallView.tsx | 122 ++++++++++++++++++------ src/components/views/voip/VideoFeed.tsx | 100 ++++++++++++++----- 5 files changed, 185 insertions(+), 68 deletions(-) diff --git a/res/css/views/voip/_CallView.scss b/res/css/views/voip/_CallView.scss index 7e2d12e539..ed3ff2afa9 100644 --- a/res/css/views/voip/_CallView.scss +++ b/res/css/views/voip/_CallView.scss @@ -112,6 +112,7 @@ limitations under the License. z-index: 30; border-radius: 8px; overflow: hidden; + display: flex; } .mx_CallView_video_hold { diff --git a/res/css/views/voip/_VideoFeed.scss b/res/css/views/voip/_VideoFeed.scss index 8ead8bba3e..46cdf4f52c 100644 --- a/res/css/views/voip/_VideoFeed.scss +++ b/res/css/views/voip/_VideoFeed.scss @@ -14,11 +14,21 @@ See the License for the specific language governing permissions and limitations under the License. */ -.mx_VideoFeed_remote { - width: 100%; - height: 100%; +.mx_VideoFeed_voice { + // We don't want to collide with the call controls that have 52px of height + padding-bottom: 52px; + background-color: $inverted-bg-color; +} + +.mx_VideoFeed_video { background-color: #000; - z-index: 50; +} + +.mx_VideoFeed_remote { + flex: 1; + display: flex; + justify-content: center; + align-items: center; } .mx_VideoFeed_local { diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index 42a38c7a54..e090270c95 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -621,7 +621,6 @@ export default class CallHandler { private async placeCall( roomId: string, type: PlaceCallType, - localElement: HTMLVideoElement, remoteElement: HTMLVideoElement, ) { Analytics.trackEvent('voip', 'placeCall', 'type', type); CountlyAnalytics.instance.trackStartCall(roomId, type === PlaceCallType.Video, false); @@ -643,10 +642,7 @@ export default class CallHandler { if (type === PlaceCallType.Voice) { call.placeVoiceCall(); } else if (type === 'video') { - call.placeVideoCall( - remoteElement, - localElement, - ); + call.placeVideoCall(); } else if (type === PlaceCallType.ScreenSharing) { const screenCapErrorString = PlatformPeg.get().screenCaptureErrorString(); if (screenCapErrorString) { @@ -660,8 +656,6 @@ export default class CallHandler { } call.placeScreenSharingCall( - remoteElement, - localElement, async () : Promise => { const {finished} = Modal.createDialog(DesktopCapturerSourcePicker); const [source] = await finished; @@ -715,14 +709,12 @@ export default class CallHandler { } else if (members.length === 2) { console.info(`Place ${payload.type} call in ${payload.room_id}`); - this.placeCall(payload.room_id, payload.type, payload.local_element, payload.remote_element); + this.placeCall(payload.room_id, payload.type); } else { // > 2 dis.dispatch({ action: "place_conference_call", room_id: payload.room_id, type: payload.type, - remote_element: payload.remote_element, - local_element: payload.local_element, }); } } diff --git a/src/components/views/voip/CallView.tsx b/src/components/views/voip/CallView.tsx index fbd30cbc9b..86b17dcab2 100644 --- a/src/components/views/voip/CallView.tsx +++ b/src/components/views/voip/CallView.tsx @@ -20,7 +20,7 @@ import dis from '../../../dispatcher/dispatcher'; import CallHandler from '../../../CallHandler'; import {MatrixClientPeg} from '../../../MatrixClientPeg'; import { _t, _td } from '../../../languageHandler'; -import VideoFeed, { VideoFeedType } from "./VideoFeed"; +import VideoFeed from './VideoFeed'; import RoomAvatar from "../avatars/RoomAvatar"; import { CallState, CallType, MatrixCall, CallEvent } from 'matrix-js-sdk/src/webrtc/call'; import classNames from 'classnames'; @@ -30,6 +30,7 @@ import {alwaysAboveLeftOf, alwaysAboveRightOf, ChevronFace, ContextMenuButton} f import CallContextMenu from '../context_menus/CallContextMenu'; import { avatarUrlForMember } from '../../../Avatar'; import DialpadContextMenu from '../context_menus/DialpadContextMenu'; +import { CallFeed } from 'matrix-js-sdk/src/webrtc/callFeed'; interface IProps { // The call for us to display @@ -58,6 +59,7 @@ interface IState { controlsVisible: boolean, showMoreMenu: boolean, showDialpad: boolean, + feeds: CallFeed[], } function getFullScreenElement() { @@ -112,6 +114,7 @@ export default class CallView extends React.Component { controlsVisible: true, showMoreMenu: false, showDialpad: false, + feeds: this.props.call.getFeeds(), } this.updateCallListeners(null, this.props.call); @@ -169,11 +172,13 @@ export default class CallView extends React.Component { oldCall.removeListener(CallEvent.State, this.onCallState); oldCall.removeListener(CallEvent.LocalHoldUnhold, this.onCallLocalHoldUnhold); oldCall.removeListener(CallEvent.RemoteHoldUnhold, this.onCallRemoteHoldUnhold); + oldCall.removeListener(CallEvent.FeedsChanged, this.onFeedsChanged); } if (newCall) { newCall.on(CallEvent.State, this.onCallState); newCall.on(CallEvent.LocalHoldUnhold, this.onCallLocalHoldUnhold); newCall.on(CallEvent.RemoteHoldUnhold, this.onCallRemoteHoldUnhold); + newCall.on(CallEvent.FeedsChanged, this.onFeedsChanged); } } @@ -183,6 +188,10 @@ export default class CallView extends React.Component { }); }; + private onFeedsChanged = (newFeeds: Array) => { + this.setState({feeds: newFeeds}); + } + private onCallLocalHoldUnhold = () => { this.setState({ isLocalOnHold: this.props.call.isLocalOnHold(), @@ -486,44 +495,71 @@ export default class CallView extends React.Component { }); } - if (this.props.call.type === CallType.Video) { - let localVideoFeed = null; - let onHoldContent = null; - let onHoldBackground = null; - const backgroundStyle: CSSProperties = {}; - const containerClasses = classNames({ - mx_CallView_video: true, - mx_CallView_video_hold: isOnHold, - }); - if (isOnHold) { - onHoldContent =
- {onHoldText} -
; + const avatarSize = this.props.pipMode ? 76 : 160; + if (isOnHold) { + if (this.props.call.type === CallType.Video) { + const containerClasses = classNames({ + mx_CallView_video: true, + mx_CallView_video_hold: isOnHold, + }); + let onHoldContent = null; + let onHoldBackground = null; + const backgroundStyle: CSSProperties = {}; + onHoldContent = ( +
+ {onHoldText} +
+ ); const backgroundAvatarUrl = avatarUrlForMember( - // is it worth getting the size of the div to pass here? + // is it worth getting the size of the div to pass here? this.props.call.getOpponentMember(), 1024, 1024, 'crop', ); backgroundStyle.backgroundImage = 'url(' + backgroundAvatarUrl + ')'; onHoldBackground =
; - } - if (!this.state.vidMuted) { - localVideoFeed = ; - } - contentView =
- {onHoldBackground} - - {localVideoFeed} - {onHoldContent} - {callControls} -
; - } else { - const avatarSize = this.props.pipMode ? 76 : 160; + contentView = ( +
+ {onHoldBackground} + {onHoldContent} + {callControls} +
+ ); + } else { + const classes = classNames({ + mx_CallView_voice: true, + mx_CallView_voice_hold: isOnHold, + }); + + contentView =( +
+
+
+ +
+
+
{onHoldText}
+ {callControls} +
+ ); + } + } else if (this.props.call.noIncomingFeeds()) { + // Here we're reusing the css classes from voice on hold, because + // I am lazy. If this gets merged, the CallView might be subject + // to change anyway - I might take an axe to this file in order to + // try to get other things working const classes = classNames({ mx_CallView_voice: true, - mx_CallView_voice_hold: isOnHold, }); + // Saying "Connecting" here isn't really true, but the best thing + // I can come up with, but this might be subject to change as well contentView =
@@ -534,7 +570,33 @@ export default class CallView extends React.Component { />
-
{onHoldText}
+
{_t("Connecting")}
+ {callControls} +
; + } else { + const containerClasses = classNames({ + mx_CallView_video: true, + }); + + // TODO: Later the CallView should probably be reworked to support any + // number of feeds but now we can always expect there to be two feeds + const feeds = this.state.feeds.map((feed, i) => { + // Here we check to hide local audio feeds to achieve the same UI/UX + // as before. But once again this might be subject to change + if (feed.isAudioOnly() && feed.isLocal()) return; + return ( + + ); + }); + + contentView =
+ {feeds} {callControls}
; } diff --git a/src/components/views/voip/VideoFeed.tsx b/src/components/views/voip/VideoFeed.tsx index 1e950f3a2a..be674630b3 100644 --- a/src/components/views/voip/VideoFeed.tsx +++ b/src/components/views/voip/VideoFeed.tsx @@ -18,50 +18,81 @@ import classnames from 'classnames'; import { MatrixCall } from 'matrix-js-sdk/src/webrtc/call'; import React, {createRef} from 'react'; import SettingsStore from "../../../settings/SettingsStore"; - -export enum VideoFeedType { - Local, - Remote, -} +import { CallFeed, CallFeedEvent } from 'matrix-js-sdk/src/webrtc/callFeed'; +import { MatrixClientPeg } from '../../../MatrixClientPeg'; +import { logger } from 'matrix-js-sdk/src/logger'; +import MemberAvatar from "../avatars/MemberAvatar" +import CallHandler from '../../../CallHandler'; interface IProps { call: MatrixCall, - type: VideoFeedType, + feed: CallFeed, + + // Whether this call view is for picture-in-pictue mode + // otherwise, it's the larger call view when viewing the room the call is in. + // This is sort of a proxy for a number of things but we currently have no + // need to control those things separately, so this is simpler. + pipMode?: boolean; // a callback which is called when the video element is resized // due to a change in video metadata onResize?: (e: Event) => void, } -export default class VideoFeed extends React.Component { +interface IState { + audioOnly: boolean; +} + +export default class VideoFeed extends React.Component { private vid = createRef(); - componentDidMount() { - this.vid.current.addEventListener('resize', this.onResize); - this.setVideoElement(); + constructor(props: IProps) { + super(props); + + this.state = { + audioOnly: this.props.feed.isAudioOnly(), + }; } - componentDidUpdate(prevProps) { - if (this.props.call !== prevProps.call) { - this.setVideoElement(); + componentDidMount() { + this.props.feed.addListener(CallFeedEvent.NewStream, this.onNewStream); + if (!this.vid.current) return; + // A note on calling methods on media elements: + // We used to have queues per media element to serialise all calls on those elements. + // The reason given for this was that load() and play() were racing. However, we now + // never call load() explicitly so this seems unnecessary. However, serialising every + // operation was causing bugs where video would not resume because some play command + // had got stuck and all media operations were queued up behind it. If necessary, we + // should serialise the ones that need to be serialised but then be able to interrupt + // them with another load() which will cancel the pending one, but since we don't call + // load() explicitly, it shouldn't be a problem. - Dave + this.vid.current.srcObject = this.props.feed.stream; + this.vid.current.autoplay = true; + this.vid.current.muted = true; + try { + this.vid.current.play(); + } catch (e) { + logger.info("Failed to play video element with feed", this.props.feed, e); } } componentWillUnmount() { + this.props.feed.removeListener(CallFeedEvent.NewStream, this.onNewStream); + if (!this.vid.current) return; this.vid.current.removeEventListener('resize', this.onResize); + this.vid.current.pause(); + this.vid.current.srcObject = null; } - private setVideoElement() { - if (this.props.type === VideoFeedType.Local) { - this.props.call.setLocalVideoElement(this.vid.current); - } else { - this.props.call.setRemoteVideoElement(this.vid.current); - } + onNewStream = (newStream: MediaStream) => { + this.setState({ audioOnly: this.props.feed.isAudioOnly()}); + if (!this.vid.current) return; + this.vid.current.srcObject = newStream; } onResize = (e) => { - if (this.props.onResize) { + if (this.props.onResize && !this.props.feed.isLocal()) { this.props.onResize(e); } }; @@ -69,14 +100,35 @@ export default class VideoFeed extends React.Component { render() { const videoClasses = { mx_VideoFeed: true, - mx_VideoFeed_local: this.props.type === VideoFeedType.Local, - mx_VideoFeed_remote: this.props.type === VideoFeedType.Remote, + mx_VideoFeed_local: this.props.feed.isLocal(), + mx_VideoFeed_remote: !this.props.feed.isLocal(), + mx_VideoFeed_voice: this.state.audioOnly, + mx_VideoFeed_video: !this.state.audioOnly, mx_VideoFeed_mirror: ( - this.props.type === VideoFeedType.Local && + this.props.feed.isLocal() && SettingsStore.getValue('VideoView.flipVideoHorizontally') ), }; - return
); } else { return ( -
+
+ {_t("Keybindings")} + {this._renderGroup(PreferencesUserSettingsTab.KEYBINDINGS_SETTINGS)} +
+ +
+ {_t("Displaying time")} + {this._renderGroup(PreferencesUserSettingsTab.TIME_SETTINGS)} +
+
{_t("Composer")} {this._renderGroup(PreferencesUserSettingsTab.COMPOSER_SETTINGS)}
+
+ {_t("Code blocks")} + {this._renderGroup(PreferencesUserSettingsTab.CODE_BLOCKS_SETTINGS)} +
+ +
+ {_t("Images, GIFs and videos")} + {this._renderGroup(PreferencesUserSettingsTab.IMAGES_AND_VIDEOS_SETTINGS)} +
+ +
+ {_t("Hide things on the timeline")} + {this._renderGroup(PreferencesUserSettingsTab.THINGS_TO_HIDE_ON_TIMELINE_SETTINGS)} +
+
{_t("Timeline")} {this._renderGroup(PreferencesUserSettingsTab.TIMELINE_SETTINGS)} From 951a807e249d2049eeb5bba7c94876f0988cec2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 10 Mar 2021 15:34:50 +0100 Subject: [PATCH 0018/1449] 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, 5 insertions(+) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 267721b533..4f07d8fde2 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1284,7 +1284,12 @@ "Show tray icon and minimize window to it on close": "Show tray icon and minimize window to it on close", "Preferences": "Preferences", "Room list": "Room list", + "Keybindings": "Keybindings", + "Displaying time": "Displaying time", "Composer": "Composer", + "Code blocks": "Code blocks", + "Images, GIFs and videos": "Images, GIFs and videos", + "Hide things on the timeline": "Hide things on the timeline", "Timeline": "Timeline", "Autocomplete delay (ms)": "Autocomplete delay (ms)", "Read Marker lifetime (ms)": "Read Marker lifetime (ms)", From 6fdc7a0860131ad5be0950e6e6365d520b801785 Mon Sep 17 00:00:00 2001 From: Aaron Raimist Date: Fri, 12 Mar 2021 05:45:22 -0600 Subject: [PATCH 0019/1449] remove old copyright notice, this is a new file Signed-off-by: Aaron Raimist --- src/components/views/dialogs/AccessTokenDialog.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/views/dialogs/AccessTokenDialog.tsx b/src/components/views/dialogs/AccessTokenDialog.tsx index c0b1b929df..220047ac21 100644 --- a/src/components/views/dialogs/AccessTokenDialog.tsx +++ b/src/components/views/dialogs/AccessTokenDialog.tsx @@ -1,5 +1,4 @@ /* -Copyright 2017 Vector Creations Ltd Copyright 2020 Resynth Licensed under the Apache License, Version 2.0 (the "License"); From ec824c714a5cfd443b00d1f7b2dbc6a3b5acbd39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 17 Mar 2021 16:09:58 +0100 Subject: [PATCH 0020/1449] Make sure video plays onNewStream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/VideoFeed.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/views/voip/VideoFeed.tsx b/src/components/views/voip/VideoFeed.tsx index be674630b3..9874dd07df 100644 --- a/src/components/views/voip/VideoFeed.tsx +++ b/src/components/views/voip/VideoFeed.tsx @@ -89,6 +89,7 @@ export default class VideoFeed extends React.Component { this.setState({ audioOnly: this.props.feed.isAudioOnly()}); if (!this.vid.current) return; this.vid.current.srcObject = newStream; + this.vid.current.play(); } onResize = (e) => { From 6c5a30109430c561c737dd816b3711fafdc8bffb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 17 Mar 2021 16:10:50 +0100 Subject: [PATCH 0021/1449] Make sure video plays onNewStream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/VideoFeed.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/views/voip/VideoFeed.tsx b/src/components/views/voip/VideoFeed.tsx index 4ad41b322e..2b75ba73da 100644 --- a/src/components/views/voip/VideoFeed.tsx +++ b/src/components/views/voip/VideoFeed.tsx @@ -117,6 +117,7 @@ export default class VideoFeed extends React.Component { this.setState({ audioOnly: this.props.feed.isAudioOnly()}); const currentMedia = this.getCurrentMedia(); currentMedia.srcObject = newStream; + currentMedia.play(); } onResize = (e) => { From 3df9557df2f886db13185872641b2f763baf41aa Mon Sep 17 00:00:00 2001 From: Ayush PS Date: Wed, 24 Mar 2021 14:00:09 +0530 Subject: [PATCH 0022/1449] Dial Pad UI fix --- res/css/views/voip/_DialPad.scss | 1 + res/css/views/voip/_DialPadContextMenu.scss | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/res/css/views/voip/_DialPad.scss b/res/css/views/voip/_DialPad.scss index 0c7bff0ce8..fd7c5f56f6 100644 --- a/res/css/views/voip/_DialPad.scss +++ b/res/css/views/voip/_DialPad.scss @@ -30,6 +30,7 @@ limitations under the License. text-align: center; vertical-align: middle; line-height: 40px; + color: #15191e; } .mx_DialPad_deleteButton, .mx_DialPad_dialButton { diff --git a/res/css/views/voip/_DialPadContextMenu.scss b/res/css/views/voip/_DialPadContextMenu.scss index 520f51cf93..c400060b6c 100644 --- a/res/css/views/voip/_DialPadContextMenu.scss +++ b/res/css/views/voip/_DialPadContextMenu.scss @@ -27,9 +27,11 @@ limitations under the License. } .mx_DialPadContextMenu_dialled { - height: 1em; + height: 1.5em; font-size: 18px; font-weight: 600; + max-width: 150px; + overflow: auto; } .mx_DialPadContextMenu_dialPad { From 1488457c3322b6d5dd6ef7882d5b14d9bf49e20f Mon Sep 17 00:00:00 2001 From: Ayush PS Date: Thu, 25 Mar 2021 01:31:45 +0530 Subject: [PATCH 0023/1449] Added the class -button-bg-color for all themes --- res/css/views/voip/_DialPad.scss | 3 +-- res/themes/dark/css/_dark.scss | 2 ++ res/themes/legacy-dark/css/_legacy-dark.scss | 1 + res/themes/legacy-light/css/_legacy-light.scss | 2 ++ res/themes/light/css/_light.scss | 2 ++ 5 files changed, 8 insertions(+), 2 deletions(-) diff --git a/res/css/views/voip/_DialPad.scss b/res/css/views/voip/_DialPad.scss index fd7c5f56f6..483b131bfe 100644 --- a/res/css/views/voip/_DialPad.scss +++ b/res/css/views/voip/_DialPad.scss @@ -23,14 +23,13 @@ limitations under the License. .mx_DialPad_button { width: 40px; height: 40px; - background-color: $theme-button-bg-color; + background-color: $dialpad-button-bg-color; border-radius: 40px; font-size: 18px; font-weight: 600; text-align: center; vertical-align: middle; line-height: 40px; - color: #15191e; } .mx_DialPad_deleteButton, .mx_DialPad_dialButton { diff --git a/res/themes/dark/css/_dark.scss b/res/themes/dark/css/_dark.scss index 7a751ad9c1..42d592c1e1 100644 --- a/res/themes/dark/css/_dark.scss +++ b/res/themes/dark/css/_dark.scss @@ -114,6 +114,8 @@ $voipcall-plinth-color: #21262c; // ******************** $theme-button-bg-color: #e3e8f0; +$dialpad-button-bg-color: #545454; + $roomlist-button-bg-color: rgba(141, 151, 165, 0.2); // Buttons include the filter box, explore button, and sublist buttons $roomlist-filter-active-bg-color: $bg-color; diff --git a/res/themes/legacy-dark/css/_legacy-dark.scss b/res/themes/legacy-dark/css/_legacy-dark.scss index 764b8f302a..ae98141d06 100644 --- a/res/themes/legacy-dark/css/_legacy-dark.scss +++ b/res/themes/legacy-dark/css/_legacy-dark.scss @@ -111,6 +111,7 @@ $voipcall-plinth-color: #f2f5f8; // ******************** $theme-button-bg-color: #e3e8f0; +$dialpad-button-bg-color: #545454; $roomlist-button-bg-color: #1A1D23; // Buttons include the filter box, explore button, and sublist buttons $roomlist-filter-active-bg-color: $roomlist-button-bg-color; diff --git a/res/themes/legacy-light/css/_legacy-light.scss b/res/themes/legacy-light/css/_legacy-light.scss index 9ad154dd93..4313e3c0b6 100644 --- a/res/themes/legacy-light/css/_legacy-light.scss +++ b/res/themes/legacy-light/css/_legacy-light.scss @@ -178,6 +178,8 @@ $voipcall-plinth-color: #f2f5f8; // ******************** $theme-button-bg-color: #e3e8f0; +$dialpad-button-bg-color: #e3e8f0; + $roomlist-button-bg-color: #fff; // Buttons include the filter box, explore button, and sublist buttons $roomlist-filter-active-bg-color: $roomlist-button-bg-color; diff --git a/res/themes/light/css/_light.scss b/res/themes/light/css/_light.scss index 25fbd0201b..81330d07c9 100644 --- a/res/themes/light/css/_light.scss +++ b/res/themes/light/css/_light.scss @@ -169,6 +169,8 @@ $voipcall-plinth-color: #f2f5f8; // ******************** $theme-button-bg-color: #e3e8f0; +$dialpad-button-bg-color: #e3e8f0; + $roomlist-button-bg-color: rgba(141, 151, 165, 0.2); // Buttons include the filter box, explore button, and sublist buttons $roomlist-filter-active-bg-color: #ffffff; From a308a5418323f9529986791a59e27e37ce2eebae Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Wed, 31 Mar 2021 12:28:24 +0100 Subject: [PATCH 0024/1449] Clicking jump to bottom resets room hash --- res/css/views/rooms/_JumpToBottomButton.scss | 1 + src/components/structures/RoomView.tsx | 1 + src/components/views/rooms/JumpToBottomButton.js | 2 ++ 3 files changed, 4 insertions(+) diff --git a/res/css/views/rooms/_JumpToBottomButton.scss b/res/css/views/rooms/_JumpToBottomButton.scss index 6cb3b6bce9..a8dc2ce11c 100644 --- a/res/css/views/rooms/_JumpToBottomButton.scss +++ b/res/css/views/rooms/_JumpToBottomButton.scss @@ -52,6 +52,7 @@ limitations under the License. .mx_JumpToBottomButton_scrollDown { position: relative; + display: block; height: 38px; border-radius: 19px; box-sizing: border-box; diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index a180afba29..e08461b511 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -2037,6 +2037,7 @@ export default class RoomView extends React.Component { highlight={this.state.room.getUnreadNotificationCount('highlight') > 0} numUnreadMessages={this.state.numUnreadMessages} onScrollToBottomClick={this.jumpToLiveTimeline} + roomId={this.state.roomId} />); } diff --git a/src/components/views/rooms/JumpToBottomButton.js b/src/components/views/rooms/JumpToBottomButton.js index b6cefc1231..2c62877dc3 100644 --- a/src/components/views/rooms/JumpToBottomButton.js +++ b/src/components/views/rooms/JumpToBottomButton.js @@ -29,6 +29,8 @@ export default (props) => { } return (
From 4c64dacba42c2b52480cdb2d9d1d7d8cba8550d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sat, 3 Apr 2021 09:16:08 +0200 Subject: [PATCH 0025/1449] Fix class MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/CallView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/voip/CallView.tsx b/src/components/views/voip/CallView.tsx index b831e8c87b..a2ca914373 100644 --- a/src/components/views/voip/CallView.tsx +++ b/src/components/views/voip/CallView.tsx @@ -601,7 +601,7 @@ export default class CallView extends React.Component { />
-
{_t("Connecting")}
+
{_t("Connecting")}
{callControls} ; } else { From c5952f7e236140503a53e253771bc152744fdceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sun, 4 Apr 2021 08:02:51 +0200 Subject: [PATCH 0026/1449] Remove VideoFeedType MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/VideoFeed.tsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/components/views/voip/VideoFeed.tsx b/src/components/views/voip/VideoFeed.tsx index ce91f2332a..925e25cee9 100644 --- a/src/components/views/voip/VideoFeed.tsx +++ b/src/components/views/voip/VideoFeed.tsx @@ -26,11 +26,6 @@ import CallHandler from '../../../CallHandler'; import CallMediaHandler from "../../../CallMediaHandler"; import {replaceableComponent} from "../../../utils/replaceableComponent"; -export enum VideoFeedType { - Local, - Remote, -} - interface IProps { call: MatrixCall, From 346784e53072dfc44d6a1fa0df28b6709949ebd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sun, 4 Apr 2021 08:33:53 +0200 Subject: [PATCH 0027/1449] Add getMember() to CallFeed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/VideoFeed.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/components/views/voip/VideoFeed.tsx b/src/components/views/voip/VideoFeed.tsx index 925e25cee9..ad199f18ae 100644 --- a/src/components/views/voip/VideoFeed.tsx +++ b/src/components/views/voip/VideoFeed.tsx @@ -19,10 +19,8 @@ import { MatrixCall } from 'matrix-js-sdk/src/webrtc/call'; import React, {createRef} from 'react'; import SettingsStore from "../../../settings/SettingsStore"; import { CallFeed, CallFeedEvent } from 'matrix-js-sdk/src/webrtc/callFeed'; -import { MatrixClientPeg } from '../../../MatrixClientPeg'; import { logger } from 'matrix-js-sdk/src/logger'; import MemberAvatar from "../avatars/MemberAvatar" -import CallHandler from '../../../CallHandler'; import CallMediaHandler from "../../../CallMediaHandler"; import {replaceableComponent} from "../../../utils/replaceableComponent"; @@ -143,9 +141,7 @@ export default class VideoFeed extends React.Component { }; if (this.state.audioOnly) { - const callRoomId = CallHandler.roomIdForCall(this.props.call); - const callRoom = MatrixClientPeg.get().getRoom(callRoomId); - const member = callRoom.getMember(this.props.feed.userId); + const member = this.props.feed.getMember(); const avatarSize = this.props.pipMode ? 76 : 160; return ( From 9324dec0d64d8d6c4d96b73dea1d8e6234dc016a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sun, 4 Apr 2021 08:50:25 +0200 Subject: [PATCH 0028/1449] Rename audioOnly to videoMuted MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes more sense and will match a possible mute events MSC Signed-off-by: Šimon Brandner --- src/components/views/voip/CallView.tsx | 2 +- src/components/views/voip/VideoFeed.tsx | 17 +++++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/components/views/voip/CallView.tsx b/src/components/views/voip/CallView.tsx index a2ca914373..8e99437218 100644 --- a/src/components/views/voip/CallView.tsx +++ b/src/components/views/voip/CallView.tsx @@ -614,7 +614,7 @@ export default class CallView extends React.Component { const feeds = this.state.feeds.map((feed, i) => { // Here we check to hide local audio feeds to achieve the same UI/UX // as before. But once again this might be subject to change - if (feed.isAudioOnly() && feed.isLocal()) return; + if (feed.isVideoMuted() && feed.isLocal()) return; return ( { super(props); this.state = { - audioOnly: this.props.feed.isAudioOnly(), + audioMuted: this.props.feed.isAudioMuted(), + videoMuted: this.props.feed.isVideoMuted(), }; } @@ -115,7 +117,10 @@ export default class VideoFeed extends React.Component { } onNewStream = (newStream: MediaStream) => { - this.setState({ audioOnly: this.props.feed.isAudioOnly()}); + this.setState({ + audioMuted: this.props.feed.isAudioMuted(), + videoMuted: this.props.feed.isVideoMuted(), + }); const currentMedia = this.getCurrentMedia(); currentMedia.srcObject = newStream; currentMedia.play(); @@ -132,15 +137,15 @@ export default class VideoFeed extends React.Component { mx_VideoFeed: true, mx_VideoFeed_local: this.props.feed.isLocal(), mx_VideoFeed_remote: !this.props.feed.isLocal(), - mx_VideoFeed_voice: this.state.audioOnly, - mx_VideoFeed_video: !this.state.audioOnly, + mx_VideoFeed_voice: this.state.videoMuted, + mx_VideoFeed_video: !this.state.videoMuted, mx_VideoFeed_mirror: ( this.props.feed.isLocal() && SettingsStore.getValue('VideoView.flipVideoHorizontally') ), }; - if (this.state.audioOnly) { + if (this.state.videoMuted) { const member = this.props.feed.getMember(); const avatarSize = this.props.pipMode ? 76 : 160; From 16e6f84f89d2f64b3fe68c51a6da5078d945e86f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sun, 4 Apr 2021 09:04:17 +0200 Subject: [PATCH 0029/1449] Display local feeds when connecting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/CallView.tsx | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/components/views/voip/CallView.tsx b/src/components/views/voip/CallView.tsx index 8e99437218..ea5411486f 100644 --- a/src/components/views/voip/CallView.tsx +++ b/src/components/views/voip/CallView.tsx @@ -589,9 +589,25 @@ export default class CallView extends React.Component { mx_CallView_voice: true, }); + const feeds = this.state.feeds.map((feed, i) => { + // Here we check to hide local audio feeds to achieve the same UI/UX + // as before. But once again this might be subject to change + if (feed.isVideoMuted() && feed.isLocal()) return; + return ( + + ); + }); + // Saying "Connecting" here isn't really true, but the best thing // I can come up with, but this might be subject to change as well contentView =
+ {feeds}
Date: Tue, 6 Apr 2021 17:26:32 +0100 Subject: [PATCH 0030/1449] reset highlighted event on room timeline scroll --- src/components/structures/MessagePanel.js | 4 ++++ src/components/structures/RoomView.tsx | 12 ++++++++++++ src/components/structures/ScrollPanel.js | 13 +++++++++++++ src/components/structures/TimelinePanel.js | 8 +++++++- 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index 41a3015721..371ee5dce7 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -120,6 +120,9 @@ export default class MessagePanel extends React.Component { // callback which is called when the panel is scrolled. onScroll: PropTypes.func, + // callback which is called when the user interacts with the room timeline + onUserScroll: PropTypes.func, + // callback which is called when more content is needed. onFillRequest: PropTypes.func, @@ -869,6 +872,7 @@ export default class MessagePanel extends React.Component { ref={this._scrollPanel} className={className} onScroll={this.props.onScroll} + onUserScroll={this.props.onUserScroll} onResize={this.onResize} onFillRequest={this.props.onFillRequest} onUnfillRequest={this.props.onUnfillRequest} diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index e08461b511..8d815c79a1 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -637,6 +637,17 @@ export default class RoomView extends React.Component { SettingsStore.unwatchSetting(this.layoutWatcherRef); } + private onUserScroll = () => { + if (this.state.initialEventId && this.state.isInitialEventHighlighted) { + dis.dispatch({ + action: 'view_room', + room_id: this.state.room.roomId, + event_id: this.state.initialEventId, + highlighted: false, + }); + } + } + private onLayoutChange = () => { this.setState({ layout: SettingsStore.getValue("layout"), @@ -2011,6 +2022,7 @@ export default class RoomView extends React.Component { eventId={this.state.initialEventId} eventPixelOffset={this.state.initialEventPixelOffset} onScroll={this.onMessageListScroll} + onUserScroll={this.onUserScroll} onReadMarkerUpdated={this.updateTopUnreadMessagesBar} showUrlPreview = {this.state.showUrlPreview} className={messagePanelClassNames} diff --git a/src/components/structures/ScrollPanel.js b/src/components/structures/ScrollPanel.js index 3a9b2b8a77..5cb9437b81 100644 --- a/src/components/structures/ScrollPanel.js +++ b/src/components/structures/ScrollPanel.js @@ -133,6 +133,10 @@ export default class ScrollPanel extends React.Component { */ onScroll: PropTypes.func, + /* onUserScroll: callback which is called when the user interacts with the room timeline + */ + onUserScroll: PropTypes.func, + /* className: classnames to add to the top-level div */ className: PropTypes.string, @@ -535,31 +539,39 @@ export default class ScrollPanel extends React.Component { * @param {object} ev the keyboard event */ handleScrollKey = ev => { + let isScrolling = false; switch (ev.key) { case Key.PAGE_UP: if (!ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) { + isScrolling = true; this.scrollRelative(-1); } break; case Key.PAGE_DOWN: if (!ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) { + isScrolling = true; this.scrollRelative(1); } break; case Key.HOME: if (ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) { + isScrolling = true; this.scrollToTop(); } break; case Key.END: if (ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) { + isScrolling = true; this.scrollToBottom(); } break; } + if (isScrolling && this.props.onUserScroll) { + this.props.onUserScroll(ev); + } }; /* Scroll the panel to bring the DOM node with the scroll token @@ -896,6 +908,7 @@ export default class ScrollPanel extends React.Component { // list-style-type: none; is no longer a list return ( { this.props.fixedChildren }
diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index 12f5d6e890..b1d1e16719 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -92,6 +92,9 @@ class TimelinePanel extends React.Component { // callback which is called when the panel is scrolled. onScroll: PropTypes.func, + // callback which is called when the user interacts with the room timeline + onUserScroll: PropTypes.func, + // callback which is called when the read-up-to mark is updated. onReadMarkerUpdated: PropTypes.func, @@ -255,7 +258,9 @@ class TimelinePanel extends React.Component { console.warn("Replacing timelineSet on a TimelinePanel - confusion may ensue"); } - if (newProps.eventId != this.props.eventId) { + const differentEventId = newProps.eventId != this.props.eventId; + const differentHighlightedEventId = newProps.highlightedEventId != this.props.highlightedEventId; + if (differentEventId || differentHighlightedEventId) { console.log("TimelinePanel switching to eventId " + newProps.eventId + " (was " + this.props.eventId + ")"); return this._initTimeline(newProps); @@ -1438,6 +1443,7 @@ class TimelinePanel extends React.Component { ourUserId={MatrixClientPeg.get().credentials.userId} stickyBottom={stickyBottom} onScroll={this.onMessageListScroll} + onUserScroll={this.props.onUserScroll} onFillRequest={this.onMessageListFillRequest} onUnfillRequest={this.onMessageListUnfillRequest} isTwelveHour={this.state.isTwelveHour} From a3da5ee6e6fec3dfce097a16bdfeeae6a0754aca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 8 Apr 2021 14:32:53 +0200 Subject: [PATCH 0031/1449] Don't play audio if the feed is local MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/VideoFeed.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/views/voip/VideoFeed.tsx b/src/components/views/voip/VideoFeed.tsx index 8e518981f8..663c2e4613 100644 --- a/src/components/views/voip/VideoFeed.tsx +++ b/src/components/views/voip/VideoFeed.tsx @@ -68,7 +68,8 @@ export default class VideoFeed extends React.Component { currentMedia.srcObject = this.props.feed.stream; currentMedia.autoplay = true; - currentMedia.muted = false; + // Don't play audio if the feed is local + currentMedia.muted = this.props.feed.isLocal(); try { if (audioOutput) { From ef1da6acddf04530100c467274d0fb1f4dae7907 Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Fri, 9 Apr 2021 09:02:47 +0100 Subject: [PATCH 0032/1449] remove wrongly committed orig file --- src/components/structures/ScrollPanel.js.orig | 938 ------------------ 1 file changed, 938 deletions(-) delete mode 100644 src/components/structures/ScrollPanel.js.orig diff --git a/src/components/structures/ScrollPanel.js.orig b/src/components/structures/ScrollPanel.js.orig deleted file mode 100644 index 5909632aa6..0000000000 --- a/src/components/structures/ScrollPanel.js.orig +++ /dev/null @@ -1,938 +0,0 @@ -/* -Copyright 2015, 2016 OpenMarket 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, {createRef} from "react"; -import PropTypes from 'prop-types'; -import Timer from '../../utils/Timer'; -import AutoHideScrollbar from "./AutoHideScrollbar"; -import {replaceableComponent} from "../../utils/replaceableComponent"; -import {getKeyBindingsManager, RoomAction} from "../../KeyBindingsManager"; - -const DEBUG_SCROLL = false; - -// The amount of extra scroll distance to allow prior to unfilling. -// See _getExcessHeight. -const UNPAGINATION_PADDING = 6000; -// The number of milliseconds to debounce calls to onUnfillRequest, to prevent -// many scroll events causing many unfilling requests. -const UNFILL_REQUEST_DEBOUNCE_MS = 200; -// _updateHeight makes the height a ceiled multiple of this so we -// don't have to update the height too often. It also allows the user -// to scroll past the pagination spinner a bit so they don't feel blocked so -// much while the content loads. -const PAGE_SIZE = 400; - -let debuglog; -if (DEBUG_SCROLL) { - // using bind means that we get to keep useful line numbers in the console - debuglog = console.log.bind(console, "ScrollPanel debuglog:"); -} else { - debuglog = function() {}; -} - -/* This component implements an intelligent scrolling list. - * - * It wraps a list of
  • children; when items are added to the start or end - * of the list, the scroll position is updated so that the user still sees the - * same position in the list. - * - * It also provides a hook which allows parents to provide more list elements - * when we get close to the start or end of the list. - * - * Each child element should have a 'data-scroll-tokens'. This string of - * comma-separated tokens may contain a single token or many, where many indicates - * that the element contains elements that have scroll tokens themselves. The first - * token in 'data-scroll-tokens' is used to serialise the scroll state, and returned - * as the 'trackedScrollToken' attribute by getScrollState(). - * - * IMPORTANT: INDIVIDUAL TOKENS WITHIN 'data-scroll-tokens' MUST NOT CONTAIN COMMAS. - * - * Some notes about the implementation: - * - * The saved 'scrollState' can exist in one of two states: - * - * - stuckAtBottom: (the default, and restored by resetScrollState): the - * viewport is scrolled down as far as it can be. When the children are - * updated, the scroll position will be updated to ensure it is still at - * the bottom. - * - * - fixed, in which the viewport is conceptually tied at a specific scroll - * offset. We don't save the absolute scroll offset, because that would be - * affected by window width, zoom level, amount of scrollback, etc. Instead - * we save an identifier for the last fully-visible message, and the number - * of pixels the window was scrolled below it - which is hopefully near - * enough. - * - * The 'stickyBottom' property controls the behaviour when we reach the bottom - * of the window (either through a user-initiated scroll, or by calling - * scrollToBottom). If stickyBottom is enabled, the scrollState will enter - * 'stuckAtBottom' state - ensuring that new additions cause the window to - * scroll down further. If stickyBottom is disabled, we just save the scroll - * offset as normal. - */ - -@replaceableComponent("structures.ScrollPanel") -export default class ScrollPanel extends React.Component { - static propTypes = { - /* stickyBottom: if set to true, then once the user hits the bottom of - * the list, any new children added to the list will cause the list to - * scroll down to show the new element, rather than preserving the - * existing view. - */ - stickyBottom: PropTypes.bool, - - /* startAtBottom: if set to true, the view is assumed to start - * scrolled to the bottom. - * XXX: It's likely this is unnecessary and can be derived from - * stickyBottom, but I'm adding an extra parameter to ensure - * behaviour stays the same for other uses of ScrollPanel. - * If so, let's remove this parameter down the line. - */ - startAtBottom: PropTypes.bool, - - /* onFillRequest(backwards): a callback which is called on scroll when - * the user nears the start (backwards = true) or end (backwards = - * false) of the list. - * - * This should return a promise; no more calls will be made until the - * promise completes. - * - * The promise should resolve to true if there is more data to be - * retrieved in this direction (in which case onFillRequest may be - * called again immediately), or false if there is no more data in this - * directon (at this time) - which will stop the pagination cycle until - * the user scrolls again. - */ - onFillRequest: PropTypes.func, - - /* onUnfillRequest(backwards): a callback which is called on scroll when - * there are children elements that are far out of view and could be removed - * without causing pagination to occur. - * - * This function should accept a boolean, which is true to indicate the back/top - * of the panel and false otherwise, and a scroll token, which refers to the - * first element to remove if removing from the front/bottom, and last element - * to remove if removing from the back/top. - */ - onUnfillRequest: PropTypes.func, - - /* onScroll: a callback which is called whenever any scroll happens. - */ - onScroll: PropTypes.func, - - /* onUserScroll: callback which is called when the user interacts with the room timeline - */ - onUserScroll: PropTypes.func, - - /* className: classnames to add to the top-level div - */ - className: PropTypes.string, - - /* style: styles to add to the top-level div - */ - style: PropTypes.object, - - /* resizeNotifier: ResizeNotifier to know when middle column has changed size - */ - resizeNotifier: PropTypes.object, - - /* fixedChildren: allows for children to be passed which are rendered outside - * of the wrapper - */ - fixedChildren: PropTypes.node, - }; - - static defaultProps = { - stickyBottom: true, - startAtBottom: true, - onFillRequest: function(backwards) { return Promise.resolve(false); }, - onUnfillRequest: function(backwards, scrollToken) {}, - onScroll: function() {}, - }; - - constructor(props) { - super(props); - - this._pendingFillRequests = {b: null, f: null}; - - if (this.props.resizeNotifier) { - this.props.resizeNotifier.on("middlePanelResizedNoisy", this.onResize); - } - - this.resetScrollState(); - - this._itemlist = createRef(); - } - - componentDidMount() { - this.checkScroll(); - } - - componentDidUpdate() { - // after adding event tiles, we may need to tweak the scroll (either to - // keep at the bottom of the timeline, or to maintain the view after - // adding events to the top). - // - // This will also re-check the fill state, in case the paginate was inadequate - this.checkScroll(); - this.updatePreventShrinking(); - } - - componentWillUnmount() { - // set a boolean to say we've been unmounted, which any pending - // promises can use to throw away their results. - // - // (We could use isMounted(), but facebook have deprecated that.) - this.unmounted = true; - - if (this.props.resizeNotifier) { - this.props.resizeNotifier.removeListener("middlePanelResizedNoisy", this.onResize); - } - } - - onScroll = ev => { - // skip scroll events caused by resizing - if (this.props.resizeNotifier && this.props.resizeNotifier.isResizing) return; - debuglog("onScroll", this._getScrollNode().scrollTop); - this._scrollTimeout.restart(); - this._saveScrollState(); - this.updatePreventShrinking(); - this.props.onScroll(ev); - this.checkFillState(); - }; - - onResize = () => { - debuglog("onResize"); - this.checkScroll(); - // update preventShrinkingState if present - if (this.preventShrinkingState) { - this.preventShrinking(); - } - }; - - // after an update to the contents of the panel, check that the scroll is - // where it ought to be, and set off pagination requests if necessary. - checkScroll = () => { - if (this.unmounted) { - return; - } - this._restoreSavedScrollState(); - this.checkFillState(); - }; - - // return true if the content is fully scrolled down right now; else false. - // - // note that this is independent of the 'stuckAtBottom' state - it is simply - // about whether the content is scrolled down right now, irrespective of - // whether it will stay that way when the children update. - isAtBottom = () => { - const sn = this._getScrollNode(); - // fractional values (both too big and too small) - // for scrollTop happen on certain browsers/platforms - // when scrolled all the way down. E.g. Chrome 72 on debian. - // so check difference <= 1; - return Math.abs(sn.scrollHeight - (sn.scrollTop + sn.clientHeight)) <= 1; - }; - - // returns the vertical height in the given direction that can be removed from - // the content box (which has a height of scrollHeight, see checkFillState) without - // pagination occuring. - // - // padding* = UNPAGINATION_PADDING - // - // ### Region determined as excess. - // - // .---------. - - - // |#########| | | - // |#########| - | scrollTop | - // | | | padding* | | - // | | | | | - // .-+---------+-. - - | | - // : | | : | | | - // : | | : | clientHeight | | - // : | | : | | | - // .-+---------+-. - - | - // | | | | | | - // | | | | | clientHeight | scrollHeight - // | | | | | | - // `-+---------+-' - | - // : | | : | | - // : | | : | clientHeight | - // : | | : | | - // `-+---------+-' - - | - // | | | padding* | - // | | | | - // |#########| - | - // |#########| | - // `---------' - - _getExcessHeight(backwards) { - const sn = this._getScrollNode(); - const contentHeight = this._getMessagesHeight(); - const listHeight = this._getListHeight(); - const clippedHeight = contentHeight - listHeight; - const unclippedScrollTop = sn.scrollTop + clippedHeight; - - if (backwards) { - return unclippedScrollTop - sn.clientHeight - UNPAGINATION_PADDING; - } else { - return contentHeight - (unclippedScrollTop + 2*sn.clientHeight) - UNPAGINATION_PADDING; - } - } - - // check the scroll state and send out backfill requests if necessary. - checkFillState = async (depth=0) => { - if (this.unmounted) { - return; - } - - const isFirstCall = depth === 0; - const sn = this._getScrollNode(); - - // if there is less than a screenful of messages above or below the - // viewport, try to get some more messages. - // - // scrollTop is the number of pixels between the top of the content and - // the top of the viewport. - // - // scrollHeight is the total height of the content. - // - // clientHeight is the height of the viewport (excluding borders, - // margins, and scrollbars). - // - // - // .---------. - - - // | | | scrollTop | - // .-+---------+-. - - | - // | | | | | | - // | | | | | clientHeight | scrollHeight - // | | | | | | - // `-+---------+-' - | - // | | | - // | | | - // `---------' - - // - - // as filling is async and recursive, - // don't allow more than 1 chain of calls concurrently - // do make a note when a new request comes in while already running one, - // so we can trigger a new chain of calls once done. - if (isFirstCall) { - if (this._isFilling) { - debuglog("_isFilling: not entering while request is ongoing, marking for a subsequent request"); - this._fillRequestWhileRunning = true; - return; - } - debuglog("_isFilling: setting"); - this._isFilling = true; - } - - const itemlist = this._itemlist.current; - const firstTile = itemlist && itemlist.firstElementChild; - const contentTop = firstTile && firstTile.offsetTop; - const fillPromises = []; - - // if scrollTop gets to 1 screen from the top of the first tile, - // try backward filling - if (!firstTile || (sn.scrollTop - contentTop) < sn.clientHeight) { - // need to back-fill - fillPromises.push(this._maybeFill(depth, true)); - } - // if scrollTop gets to 2 screens from the end (so 1 screen below viewport), - // try forward filling - if ((sn.scrollHeight - sn.scrollTop) < sn.clientHeight * 2) { - // need to forward-fill - fillPromises.push(this._maybeFill(depth, false)); - } - - if (fillPromises.length) { - try { - await Promise.all(fillPromises); - } catch (err) { - console.error(err); - } - } - if (isFirstCall) { - debuglog("_isFilling: clearing"); - this._isFilling = false; - } - - if (this._fillRequestWhileRunning) { - this._fillRequestWhileRunning = false; - this.checkFillState(); - } - }; - - // check if unfilling is possible and send an unfill request if necessary - _checkUnfillState(backwards) { - let excessHeight = this._getExcessHeight(backwards); - if (excessHeight <= 0) { - return; - } - - const origExcessHeight = excessHeight; - - const tiles = this._itemlist.current.children; - - // The scroll token of the first/last tile to be unpaginated - let markerScrollToken = null; - - // Subtract heights of tiles to simulate the tiles being unpaginated until the - // excess height is less than the height of the next tile to subtract. This - // prevents excessHeight becoming negative, which could lead to future - // pagination. - // - // If backwards is true, we unpaginate (remove) tiles from the back (top). - let tile; - for (let i = 0; i < tiles.length; i++) { - tile = tiles[backwards ? i : tiles.length - 1 - i]; - // Subtract height of tile as if it were unpaginated - excessHeight -= tile.clientHeight; - //If removing the tile would lead to future pagination, break before setting scroll token - if (tile.clientHeight > excessHeight) { - break; - } - // The tile may not have a scroll token, so guard it - if (tile.dataset.scrollTokens) { - markerScrollToken = tile.dataset.scrollTokens.split(',')[0]; - } - } - - if (markerScrollToken) { - // Use a debouncer to prevent multiple unfill calls in quick succession - // This is to make the unfilling process less aggressive - if (this._unfillDebouncer) { - clearTimeout(this._unfillDebouncer); - } - this._unfillDebouncer = setTimeout(() => { - this._unfillDebouncer = null; - debuglog("unfilling now", backwards, origExcessHeight); - this.props.onUnfillRequest(backwards, markerScrollToken); - }, UNFILL_REQUEST_DEBOUNCE_MS); - } - } - - // check if there is already a pending fill request. If not, set one off. - _maybeFill(depth, backwards) { - const dir = backwards ? 'b' : 'f'; - if (this._pendingFillRequests[dir]) { - debuglog("Already a "+dir+" fill in progress - not starting another"); - return; - } - - debuglog("starting "+dir+" fill"); - - // onFillRequest can end up calling us recursively (via onScroll - // events) so make sure we set this before firing off the call. - this._pendingFillRequests[dir] = true; - - // wait 1ms before paginating, because otherwise - // this will block the scroll event handler for +700ms - // if messages are already cached in memory, - // This would cause jumping to happen on Chrome/macOS. - return new Promise(resolve => setTimeout(resolve, 1)).then(() => { - return this.props.onFillRequest(backwards); - }).finally(() => { - this._pendingFillRequests[dir] = false; - }).then((hasMoreResults) => { - if (this.unmounted) { - return; - } - // Unpaginate once filling is complete - this._checkUnfillState(!backwards); - - debuglog(""+dir+" fill complete; hasMoreResults:"+hasMoreResults); - if (hasMoreResults) { - // further pagination requests have been disabled until now, so - // it's time to check the fill state again in case the pagination - // was insufficient. - return this.checkFillState(depth + 1); - } - }); - } - - /* get the current scroll state. This returns an object with the following - * properties: - * - * boolean stuckAtBottom: true if we are tracking the bottom of the - * scroll. false if we are tracking a particular child. - * - * string trackedScrollToken: undefined if stuckAtBottom is true; if it is - * false, the first token in data-scroll-tokens of the child which we are - * tracking. - * - * number bottomOffset: undefined if stuckAtBottom is true; if it is false, - * the number of pixels the bottom of the tracked child is above the - * bottom of the scroll panel. - */ - getScrollState = () => this.scrollState; - - /* reset the saved scroll state. - * - * This is useful if the list is being replaced, and you don't want to - * preserve scroll even if new children happen to have the same scroll - * tokens as old ones. - * - * This will cause the viewport to be scrolled down to the bottom on the - * next update of the child list. This is different to scrollToBottom(), - * which would save the current bottom-most child as the active one (so is - * no use if no children exist yet, or if you are about to replace the - * child list.) - */ - resetScrollState = () => { - this.scrollState = { - stuckAtBottom: this.props.startAtBottom, - }; - this._bottomGrowth = 0; - this._pages = 0; - this._scrollTimeout = new Timer(100); - this._heightUpdateInProgress = false; - }; - - /** - * jump to the top of the content. - */ - scrollToTop = () => { - this._getScrollNode().scrollTop = 0; - this._saveScrollState(); - }; - - /** - * jump to the bottom of the content. - */ - scrollToBottom = () => { - // the easiest way to make sure that the scroll state is correctly - // saved is to do the scroll, then save the updated state. (Calculating - // it ourselves is hard, and we can't rely on an onScroll callback - // happening, since there may be no user-visible change here). - const sn = this._getScrollNode(); - sn.scrollTop = sn.scrollHeight; - this._saveScrollState(); - }; - - /** - * Page up/down. - * - * @param {number} mult: -1 to page up, +1 to page down - */ - scrollRelative = mult => { - const scrollNode = this._getScrollNode(); - const delta = mult * scrollNode.clientHeight * 0.5; - scrollNode.scrollBy(0, delta); - this._saveScrollState(); - }; - - /** - * Scroll up/down in response to a scroll key - * @param {object} ev the keyboard event - */ - handleScrollKey = ev => { -<<<<<<< HEAD - let isScrolling = false; - switch (ev.key) { - case Key.PAGE_UP: - if (!ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) { - isScrolling = true; - this.scrollRelative(-1); - } - break; - - case Key.PAGE_DOWN: - if (!ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) { - isScrolling = true; - this.scrollRelative(1); - } - break; - - case Key.HOME: - if (ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) { - isScrolling = true; - this.scrollToTop(); - } - break; - - case Key.END: - if (ev.ctrlKey && !ev.shiftKey && !ev.altKey && !ev.metaKey) { - isScrolling = true; - this.scrollToBottom(); - } -======= - const roomAction = getKeyBindingsManager().getRoomAction(ev); - switch (roomAction) { - case RoomAction.ScrollUp: - this.scrollRelative(-1); - break; - case RoomAction.RoomScrollDown: - this.scrollRelative(1); - break; - case RoomAction.JumpToFirstMessage: - this.scrollToTop(); - break; - case RoomAction.JumpToLatestMessage: - this.scrollToBottom(); ->>>>>>> develop - break; - } - if (isScrolling && this.props.onUserScroll) { - this.props.onUserScroll(ev); - } - }; - - /* Scroll the panel to bring the DOM node with the scroll token - * `scrollToken` into view. - * - * offsetBase gives the reference point for the pixelOffset. 0 means the - * top of the container, 1 means the bottom, and fractional values mean - * somewhere in the middle. If omitted, it defaults to 0. - * - * pixelOffset gives the number of pixels *above* the offsetBase that the - * node (specifically, the bottom of it) will be positioned. If omitted, it - * defaults to 0. - */ - scrollToToken = (scrollToken, pixelOffset, offsetBase) => { - pixelOffset = pixelOffset || 0; - offsetBase = offsetBase || 0; - - // set the trackedScrollToken so we can get the node through _getTrackedNode - this.scrollState = { - stuckAtBottom: false, - trackedScrollToken: scrollToken, - }; - const trackedNode = this._getTrackedNode(); - const scrollNode = this._getScrollNode(); - if (trackedNode) { - // set the scrollTop to the position we want. - // note though, that this might not succeed if the combination of offsetBase and pixelOffset - // would position the trackedNode towards the top of the viewport. - // This because when setting the scrollTop only 10 or so events might be loaded, - // not giving enough content below the trackedNode to scroll downwards - // enough so it ends up in the top of the viewport. - debuglog("scrollToken: setting scrollTop", {offsetBase, pixelOffset, offsetTop: trackedNode.offsetTop}); - scrollNode.scrollTop = (trackedNode.offsetTop - (scrollNode.clientHeight * offsetBase)) + pixelOffset; - this._saveScrollState(); - } - }; - - _saveScrollState() { - if (this.props.stickyBottom && this.isAtBottom()) { - this.scrollState = { stuckAtBottom: true }; - debuglog("saved stuckAtBottom state"); - return; - } - - const scrollNode = this._getScrollNode(); - const viewportBottom = scrollNode.scrollHeight - (scrollNode.scrollTop + scrollNode.clientHeight); - - const itemlist = this._itemlist.current; - const messages = itemlist.children; - let node = null; - - // TODO: do a binary search here, as items are sorted by offsetTop - // loop backwards, from bottom-most message (as that is the most common case) - for (let i = messages.length-1; i >= 0; --i) { - if (!messages[i].dataset.scrollTokens) { - continue; - } - node = messages[i]; - // break at the first message (coming from the bottom) - // that has it's offsetTop above the bottom of the viewport. - if (this._topFromBottom(node) > viewportBottom) { - // Use this node as the scrollToken - break; - } - } - - if (!node) { - debuglog("unable to save scroll state: found no children in the viewport"); - return; - } - const scrollToken = node.dataset.scrollTokens.split(',')[0]; - debuglog("saving anchored scroll state to message", node && node.innerText, scrollToken); - const bottomOffset = this._topFromBottom(node); - this.scrollState = { - stuckAtBottom: false, - trackedNode: node, - trackedScrollToken: scrollToken, - bottomOffset: bottomOffset, - pixelOffset: bottomOffset - viewportBottom, //needed for restoring the scroll position when coming back to the room - }; - } - - async _restoreSavedScrollState() { - const scrollState = this.scrollState; - - if (scrollState.stuckAtBottom) { - const sn = this._getScrollNode(); - if (sn.scrollTop !== sn.scrollHeight) { - sn.scrollTop = sn.scrollHeight; - } - } else if (scrollState.trackedScrollToken) { - const itemlist = this._itemlist.current; - const trackedNode = this._getTrackedNode(); - if (trackedNode) { - const newBottomOffset = this._topFromBottom(trackedNode); - const bottomDiff = newBottomOffset - scrollState.bottomOffset; - this._bottomGrowth += bottomDiff; - scrollState.bottomOffset = newBottomOffset; - const newHeight = `${this._getListHeight()}px`; - if (itemlist.style.height !== newHeight) { - itemlist.style.height = newHeight; - } - debuglog("balancing height because messages below viewport grew by", bottomDiff); - } - } - if (!this._heightUpdateInProgress) { - this._heightUpdateInProgress = true; - try { - await this._updateHeight(); - } finally { - this._heightUpdateInProgress = false; - } - } else { - debuglog("not updating height because request already in progress"); - } - } - - // need a better name that also indicates this will change scrollTop? Rebalance height? Reveal content? - async _updateHeight() { - // wait until user has stopped scrolling - if (this._scrollTimeout.isRunning()) { - debuglog("updateHeight waiting for scrolling to end ... "); - await this._scrollTimeout.finished(); - } else { - debuglog("updateHeight getting straight to business, no scrolling going on."); - } - - // We might have unmounted since the timer finished, so abort if so. - if (this.unmounted) { - return; - } - - const sn = this._getScrollNode(); - const itemlist = this._itemlist.current; - const contentHeight = this._getMessagesHeight(); - const minHeight = sn.clientHeight; - const height = Math.max(minHeight, contentHeight); - this._pages = Math.ceil(height / PAGE_SIZE); - this._bottomGrowth = 0; - const newHeight = `${this._getListHeight()}px`; - - const scrollState = this.scrollState; - if (scrollState.stuckAtBottom) { - if (itemlist.style.height !== newHeight) { - itemlist.style.height = newHeight; - } - if (sn.scrollTop !== sn.scrollHeight) { - sn.scrollTop = sn.scrollHeight; - } - debuglog("updateHeight to", newHeight); - } else if (scrollState.trackedScrollToken) { - const trackedNode = this._getTrackedNode(); - // if the timeline has been reloaded - // this can be called before scrollToBottom or whatever has been called - // so don't do anything if the node has disappeared from - // the currently filled piece of the timeline - if (trackedNode) { - const oldTop = trackedNode.offsetTop; - if (itemlist.style.height !== newHeight) { - itemlist.style.height = newHeight; - } - const newTop = trackedNode.offsetTop; - const topDiff = newTop - oldTop; - // important to scroll by a relative amount as - // reading scrollTop and then setting it might - // yield out of date values and cause a jump - // when setting it - sn.scrollBy(0, topDiff); - debuglog("updateHeight to", {newHeight, topDiff}); - } - } - } - - _getTrackedNode() { - const scrollState = this.scrollState; - const trackedNode = scrollState.trackedNode; - - if (!trackedNode || !trackedNode.parentElement) { - let node; - const messages = this._itemlist.current.children; - const scrollToken = scrollState.trackedScrollToken; - - for (let i = messages.length-1; i >= 0; --i) { - const m = messages[i]; - // 'data-scroll-tokens' is a DOMString of comma-separated scroll tokens - // There might only be one scroll token - if (m.dataset.scrollTokens && - m.dataset.scrollTokens.split(',').indexOf(scrollToken) !== -1) { - node = m; - break; - } - } - if (node) { - debuglog("had to find tracked node again for " + scrollState.trackedScrollToken); - } - scrollState.trackedNode = node; - } - - if (!scrollState.trackedNode) { - debuglog("No node with ; '"+scrollState.trackedScrollToken+"'"); - return; - } - - return scrollState.trackedNode; - } - - _getListHeight() { - return this._bottomGrowth + (this._pages * PAGE_SIZE); - } - - _getMessagesHeight() { - const itemlist = this._itemlist.current; - const lastNode = itemlist.lastElementChild; - const lastNodeBottom = lastNode ? lastNode.offsetTop + lastNode.clientHeight : 0; - const firstNodeTop = itemlist.firstElementChild ? itemlist.firstElementChild.offsetTop : 0; - // 18 is itemlist padding - return lastNodeBottom - firstNodeTop + (18 * 2); - } - - _topFromBottom(node) { - // current capped height - distance from top = distance from bottom of container to top of tracked element - return this._itemlist.current.clientHeight - node.offsetTop; - } - - /* get the DOM node which has the scrollTop property we care about for our - * message panel. - */ - _getScrollNode() { - if (this.unmounted) { - // this shouldn't happen, but when it does, turn the NPE into - // something more meaningful. - throw new Error("ScrollPanel._getScrollNode called when unmounted"); - } - - if (!this._divScroll) { - // Likewise, we should have the ref by this point, but if not - // turn the NPE into something meaningful. - throw new Error("ScrollPanel._getScrollNode called before AutoHideScrollbar ref collected"); - } - - return this._divScroll; - } - - _collectScroll = divScroll => { - this._divScroll = divScroll; - }; - - /** - Mark the bottom offset of the last tile so we can balance it out when - anything below it changes, by calling updatePreventShrinking, to keep - the same minimum bottom offset, effectively preventing the timeline to shrink. - */ - preventShrinking = () => { - const messageList = this._itemlist.current; - const tiles = messageList && messageList.children; - if (!messageList) { - return; - } - let lastTileNode; - for (let i = tiles.length - 1; i >= 0; i--) { - const node = tiles[i]; - if (node.dataset.scrollTokens) { - lastTileNode = node; - break; - } - } - if (!lastTileNode) { - return; - } - this.clearPreventShrinking(); - const offsetFromBottom = messageList.clientHeight - (lastTileNode.offsetTop + lastTileNode.clientHeight); - this.preventShrinkingState = { - offsetFromBottom: offsetFromBottom, - offsetNode: lastTileNode, - }; - debuglog("prevent shrinking, last tile ", offsetFromBottom, "px from bottom"); - }; - - /** Clear shrinking prevention. Used internally, and when the timeline is reloaded. */ - clearPreventShrinking = () => { - const messageList = this._itemlist.current; - const balanceElement = messageList && messageList.parentElement; - if (balanceElement) balanceElement.style.paddingBottom = null; - this.preventShrinkingState = null; - debuglog("prevent shrinking cleared"); - }; - - /** - update the container padding to balance - the bottom offset of the last tile since - preventShrinking was called. - Clears the prevent-shrinking state ones the offset - from the bottom of the marked tile grows larger than - what it was when marking. - */ - updatePreventShrinking = () => { - if (this.preventShrinkingState) { - const sn = this._getScrollNode(); - const scrollState = this.scrollState; - const messageList = this._itemlist.current; - const {offsetNode, offsetFromBottom} = this.preventShrinkingState; - // element used to set paddingBottom to balance the typing notifs disappearing - const balanceElement = messageList.parentElement; - // if the offsetNode got unmounted, clear - let shouldClear = !offsetNode.parentElement; - // also if 200px from bottom - if (!shouldClear && !scrollState.stuckAtBottom) { - const spaceBelowViewport = sn.scrollHeight - (sn.scrollTop + sn.clientHeight); - shouldClear = spaceBelowViewport >= 200; - } - // try updating if not clearing - if (!shouldClear) { - const currentOffset = messageList.clientHeight - (offsetNode.offsetTop + offsetNode.clientHeight); - const offsetDiff = offsetFromBottom - currentOffset; - if (offsetDiff > 0) { - balanceElement.style.paddingBottom = `${offsetDiff}px`; - debuglog("update prevent shrinking ", offsetDiff, "px from bottom"); - } else if (offsetDiff < 0) { - shouldClear = true; - } - } - if (shouldClear) { - this.clearPreventShrinking(); - } - } - }; - - render() { - // TODO: the classnames on the div and ol could do with being updated to - // reflect the fact that we don't necessarily contain a list of messages. - // it's not obvious why we have a separate div and ol anyway. - - // give the
      an explicit role=list because Safari+VoiceOver seems to think an ordered-list with - // list-style-type: none; is no longer a list - return ( - { this.props.fixedChildren } -
      -
        - { this.props.children } -
      -
      -
      - ); - } -} From d450822bfd99824bc0aa8b61aec603c71ddd4dd0 Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Fri, 9 Apr 2021 11:17:50 +0100 Subject: [PATCH 0033/1449] fix linting issues in ScrollPanel --- src/components/structures/ScrollPanel.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/structures/ScrollPanel.js b/src/components/structures/ScrollPanel.js index 80447fd556..3c305524b8 100644 --- a/src/components/structures/ScrollPanel.js +++ b/src/components/structures/ScrollPanel.js @@ -539,24 +539,24 @@ export default class ScrollPanel extends React.Component { * @param {object} ev the keyboard event */ handleScrollKey = ev => { - let isScrolling = false; + let isScrolling = false; const roomAction = getKeyBindingsManager().getRoomAction(ev); switch (roomAction) { case RoomAction.ScrollUp: this.scrollRelative(-1); - isScrolling = true; + isScrolling = true; break; case RoomAction.RoomScrollDown: this.scrollRelative(1); - isScrolling = true; + isScrolling = true; break; case RoomAction.JumpToFirstMessage: this.scrollToTop(); - isScrolling = true; + isScrolling = true; break; case RoomAction.JumpToLatestMessage: this.scrollToBottom(); - isScrolling = true; + isScrolling = true; break; } if (isScrolling && this.props.onUserScroll) { From d148b521f5ab71498ba5a63559871273c6334d49 Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Fri, 9 Apr 2021 11:23:41 +0100 Subject: [PATCH 0034/1449] Revert JumpToBottom to button and use dispatcher to view room --- src/components/structures/RoomView.tsx | 6 ++++-- src/components/views/rooms/JumpToBottomButton.js | 2 -- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index 8d815c79a1..52608d1db1 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -1509,8 +1509,10 @@ export default class RoomView extends React.Component { // jump down to the bottom of this room, where new events are arriving private jumpToLiveTimeline = () => { - this.messagePanel.jumpToLiveTimeline(); - dis.fire(Action.FocusComposer); + dis.dispatch({ + action: 'view_room', + room_id: this.state.room.roomId, + }); }; // jump up to wherever our read marker is diff --git a/src/components/views/rooms/JumpToBottomButton.js b/src/components/views/rooms/JumpToBottomButton.js index 2c62877dc3..b6cefc1231 100644 --- a/src/components/views/rooms/JumpToBottomButton.js +++ b/src/components/views/rooms/JumpToBottomButton.js @@ -29,8 +29,6 @@ export default (props) => { } return (
      From 56b15edc58e5c7dc09f765674c659ca77f18c698 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 12 Apr 2021 16:19:05 +0200 Subject: [PATCH 0035/1449] Properly handle media MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This might have resulted in the wrong speaker being used or worse Signed-off-by: Šimon Brandner --- src/components/views/voip/VideoFeed.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/components/views/voip/VideoFeed.tsx b/src/components/views/voip/VideoFeed.tsx index 663c2e4613..43696defb9 100644 --- a/src/components/views/voip/VideoFeed.tsx +++ b/src/components/views/voip/VideoFeed.tsx @@ -63,6 +63,10 @@ export default class VideoFeed extends React.Component { componentDidMount() { this.props.feed.addListener(CallFeedEvent.NewStream, this.onNewStream); + this.playMedia(); + } + + playMedia() { const audioOutput = CallMediaHandler.getAudioOutput(); const currentMedia = this.getCurrentMedia(); @@ -117,14 +121,12 @@ export default class VideoFeed extends React.Component { return this.audio.current || this.video.current; } - onNewStream = (newStream: MediaStream) => { + onNewStream = () => { this.setState({ audioMuted: this.props.feed.isAudioMuted(), videoMuted: this.props.feed.isVideoMuted(), }); - const currentMedia = this.getCurrentMedia(); - currentMedia.srcObject = newStream; - currentMedia.play(); + this.playMedia(); } onResize = (e) => { From ace3a62bacefe27dbbe77a2aeb3633528353d361 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 13 Apr 2021 14:52:26 +0100 Subject: [PATCH 0036/1449] Allow click inserting mentions into the edit composer too --- src/components/structures/TimelinePanel.js | 48 +++++++++++++------ .../views/rooms/BasicMessageComposer.tsx | 19 ++++++++ .../views/rooms/EditMessageComposer.js | 8 ++++ .../views/rooms/SendMessageComposer.js | 23 +-------- 4 files changed, 63 insertions(+), 35 deletions(-) diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index 12f5d6e890..093e20b8b6 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -450,21 +450,41 @@ class TimelinePanel extends React.Component { }; onAction = payload => { - if (payload.action === 'ignore_state_changed') { - this.forceUpdate(); - } - if (payload.action === "edit_event") { - const editState = payload.event ? new EditorStateTransfer(payload.event) : null; - this.setState({editState}, () => { - if (payload.event && this._messagePanel.current) { - this._messagePanel.current.scrollToEventIfNeeded( - payload.event.getId(), - ); + switch (payload.action) { + case "ignore_state_changed": + this.forceUpdate(); + break; + + case "edit_event": { + const editState = payload.event ? new EditorStateTransfer(payload.event) : null; + this.setState({editState}, () => { + if (payload.event && this._messagePanel.current) { + this._messagePanel.current.scrollToEventIfNeeded( + payload.event.getId(), + ); + } + }); + break; + } + + case "insert_mention": { + if (this.state.editState) { + dis.dispatch({ + ...payload, + action: "insert_mention_edit_composer", + }); + } else { + dis.dispatch({ + ...payload, + action: "insert_mention_send_composer", + }); } - }); - } - if (payload.action === "scroll_to_bottom") { - this.jumpToLiveTimeline(); + break; + } + + case "scroll_to_bottom": + this.jumpToLiveTimeline(); + break; } }; diff --git a/src/components/views/rooms/BasicMessageComposer.tsx b/src/components/views/rooms/BasicMessageComposer.tsx index 9d9e3a1ba0..b8ebde75cc 100644 --- a/src/components/views/rooms/BasicMessageComposer.tsx +++ b/src/components/views/rooms/BasicMessageComposer.tsx @@ -713,4 +713,23 @@ export default class BasicMessageEditor extends React.Component focus() { this.editorRef.current.focus(); } + + public insertMention(userId: string) { + const {model} = this.props; + const {partCreator} = model; + const member = this.props.room.getMember(userId); + const displayName = member ? + member.rawDisplayName : userId; + const caret = this.getCaret(); + const position = model.positionForOffset(caret.offset, caret.atNodeEnd); + // index is -1 if there are no parts but we only care for if this would be the part in position 0 + const insertIndex = position.index > 0 ? position.index : 0; + const parts = partCreator.createMentionParts(insertIndex, displayName, userId); + model.transform(() => { + const addedLen = model.insert(parts, position); + return model.positionForOffset(caret.offset + addedLen, true); + }); + // refocus on composer, as we just clicked "Mention" + this.focus(); + } } diff --git a/src/components/views/rooms/EditMessageComposer.js b/src/components/views/rooms/EditMessageComposer.js index b006fe8c8d..1c2b3aed1c 100644 --- a/src/components/views/rooms/EditMessageComposer.js +++ b/src/components/views/rooms/EditMessageComposer.js @@ -120,6 +120,7 @@ export default class EditMessageComposer extends React.Component { saveDisabled: true, }; this._createEditorModel(); + this.dispatcherRef = dis.register(this.onAction); } _setEditorRef = ref => { @@ -235,6 +236,7 @@ export default class EditMessageComposer extends React.Component { // then when mounting the editor again with the same editor state, // it will set the cursor at the end. this.props.editState.setEditorState(caret, parts); + dis.unregister(this.dispatcherRef); } _createEditorModel() { @@ -278,6 +280,12 @@ export default class EditMessageComposer extends React.Component { }); }; + onAction = payload => { + if (payload.action === "insert_mention_edit_composer" && this._editorRef) { + this._editorRef.insertMention(payload.user_id); + } + }; + render() { const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); return (
      diff --git a/src/components/views/rooms/SendMessageComposer.js b/src/components/views/rooms/SendMessageComposer.js index 75bc943146..aaeadffae1 100644 --- a/src/components/views/rooms/SendMessageComposer.js +++ b/src/components/views/rooms/SendMessageComposer.js @@ -482,8 +482,8 @@ export default class SendMessageComposer extends React.Component { case Action.FocusComposer: this._editorRef && this._editorRef.focus(); break; - case 'insert_mention': - this._insertMention(payload.user_id); + case 'insert_mention_send_composer': + this._editorRef && this._editorRef.insertMention(payload.user_id); break; case 'quote': this._insertQuotedMessage(payload.event); @@ -494,25 +494,6 @@ export default class SendMessageComposer extends React.Component { } }; - _insertMention(userId) { - const {model} = this; - const {partCreator} = model; - const member = this.props.room.getMember(userId); - const displayName = member ? - member.rawDisplayName : userId; - const caret = this._editorRef.getCaret(); - const position = model.positionForOffset(caret.offset, caret.atNodeEnd); - // index is -1 if there are no parts but we only care for if this would be the part in position 0 - const insertIndex = position.index > 0 ? position.index : 0; - const parts = partCreator.createMentionParts(insertIndex, displayName, userId); - model.transform(() => { - const addedLen = model.insert(parts, position); - return model.positionForOffset(caret.offset + addedLen, true); - }); - // refocus on composer, as we just clicked "Mention" - this._editorRef && this._editorRef.focus(); - } - _insertQuotedMessage(event) { const {model} = this; const {partCreator} = model; From 5f59e399582a958374a8bf7d634bb1ea19d77f95 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 13 Apr 2021 15:09:37 +0100 Subject: [PATCH 0037/1449] Apply the same to quoting & inserting of emoji then consolidate --- src/components/structures/TimelinePanel.js | 7 ++-- .../views/context_menus/MessageContextMenu.js | 2 +- src/components/views/messages/TextualBody.js | 4 +- src/components/views/right_panel/UserInfo.tsx | 4 +- .../views/rooms/BasicMessageComposer.tsx | 29 ++++++++++++- .../views/rooms/EditMessageComposer.js | 10 ++++- src/components/views/rooms/EventTile.js | 4 +- src/components/views/rooms/MessageComposer.js | 4 +- .../views/rooms/SendMessageComposer.js | 42 ++++--------------- src/dispatcher/actions.ts | 5 +++ .../payloads/ComposerInsertPayload.ts | 42 +++++++++++++++++++ src/editor/model.ts | 2 +- 12 files changed, 105 insertions(+), 50 deletions(-) create mode 100644 src/dispatcher/payloads/ComposerInsertPayload.ts diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index 093e20b8b6..c7e252d667 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -467,16 +467,17 @@ class TimelinePanel extends React.Component { break; } - case "insert_mention": { + case "composer_insert": { + // re-dispatch to the correct composer if (this.state.editState) { dis.dispatch({ ...payload, - action: "insert_mention_edit_composer", + action: "edit_composer_insert", }); } else { dis.dispatch({ ...payload, - action: "insert_mention_send_composer", + action: "send_composer_insert", }); } break; diff --git a/src/components/views/context_menus/MessageContextMenu.js b/src/components/views/context_menus/MessageContextMenu.js index 56f070ba36..8c23906c68 100644 --- a/src/components/views/context_menus/MessageContextMenu.js +++ b/src/components/views/context_menus/MessageContextMenu.js @@ -233,7 +233,7 @@ export default class MessageContextMenu extends React.Component { onQuoteClick = () => { dis.dispatch({ - action: 'quote', + action: "composer_insert", event: this.props.mxEvent, }); this.closeMenu(); diff --git a/src/components/views/messages/TextualBody.js b/src/components/views/messages/TextualBody.js index 353f40b6a9..83f6c80937 100644 --- a/src/components/views/messages/TextualBody.js +++ b/src/components/views/messages/TextualBody.js @@ -390,8 +390,8 @@ export default class TextualBody extends React.Component { onEmoteSenderClick = event => { const mxEvent = this.props.mxEvent; dis.dispatch({ - action: 'insert_mention', - user_id: mxEvent.getSender(), + action: "composer_insert", + userId: mxEvent.getSender(), }); }; diff --git a/src/components/views/right_panel/UserInfo.tsx b/src/components/views/right_panel/UserInfo.tsx index b862cc84d4..61eaa54639 100644 --- a/src/components/views/right_panel/UserInfo.tsx +++ b/src/components/views/right_panel/UserInfo.tsx @@ -360,8 +360,8 @@ const UserOptionsSection: React.FC<{ const onInsertPillButton = function() { dis.dispatch({ - action: 'insert_mention', - user_id: member.userId, + action: "composer_insert", + userId: member.userId, }); }; diff --git a/src/components/views/rooms/BasicMessageComposer.tsx b/src/components/views/rooms/BasicMessageComposer.tsx index b8ebde75cc..ebf97a1d09 100644 --- a/src/components/views/rooms/BasicMessageComposer.tsx +++ b/src/components/views/rooms/BasicMessageComposer.tsx @@ -18,6 +18,7 @@ limitations under the License. import classNames from 'classnames'; import React, {createRef, ClipboardEvent} from 'react'; import {Room} from 'matrix-js-sdk/src/models/room'; +import {MatrixEvent} from 'matrix-js-sdk/src/models/event'; import EMOTICON_REGEX from 'emojibase-regex/emoticon'; import EditorModel from '../../../editor/model'; @@ -32,7 +33,7 @@ import { import {getCaretOffsetAndText, getRangeForSelection} from '../../../editor/dom'; import Autocomplete, {generateCompletionDomId} from '../rooms/Autocomplete'; import {getAutoCompleteCreator} from '../../../editor/parts'; -import {parsePlainTextMessage} from '../../../editor/deserialize'; +import {parseEvent, parsePlainTextMessage} from '../../../editor/deserialize'; import {renderModel} from '../../../editor/render'; import TypingStore from "../../../stores/TypingStore"; import SettingsStore from "../../../settings/SettingsStore"; @@ -732,4 +733,30 @@ export default class BasicMessageEditor extends React.Component // refocus on composer, as we just clicked "Mention" this.focus(); } + + public insertQuotedMessage(event: MatrixEvent) { + const {model} = this.props; + const {partCreator} = model; + const quoteParts = parseEvent(event, partCreator, {isQuotedMessage: true}); + // add two newlines + quoteParts.push(partCreator.newline()); + quoteParts.push(partCreator.newline()); + model.transform(() => { + const addedLen = model.insert(quoteParts, model.positionForOffset(0)); + return model.positionForOffset(addedLen, true); + }); + // refocus on composer, as we just clicked "Quote" + this.focus(); + } + + public insertPlaintext(text: string) { + const {model} = this.props; + const {partCreator} = model; + const caret = this.getCaret(); + const position = model.positionForOffset(caret.offset, caret.atNodeEnd); + model.transform(() => { + const addedLen = model.insert([partCreator.plain(text)], position); + return model.positionForOffset(caret.offset + addedLen, true); + }); + } } diff --git a/src/components/views/rooms/EditMessageComposer.js b/src/components/views/rooms/EditMessageComposer.js index 1c2b3aed1c..39fafe486c 100644 --- a/src/components/views/rooms/EditMessageComposer.js +++ b/src/components/views/rooms/EditMessageComposer.js @@ -281,8 +281,14 @@ export default class EditMessageComposer extends React.Component { }; onAction = payload => { - if (payload.action === "insert_mention_edit_composer" && this._editorRef) { - this._editorRef.insertMention(payload.user_id); + if (payload.action === "edit_composer_insert" && this._editorRef) { + if (payload.user_id) { + this._editorRef.insertMention(payload.userId); + } else if (payload.event) { + this._editorRef.insertQuotedMessage(payload.event); + } else if (payload.text) { + this._editorRef.insertPlaintext(payload.text); + } } }; diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index d51f4c00f1..fe4fd95d24 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -644,8 +644,8 @@ export default class EventTile extends React.Component { onSenderProfileClick = event => { const mxEvent = this.props.mxEvent; dis.dispatch({ - action: 'insert_mention', - user_id: mxEvent.getSender(), + action: "composer_insert", + userId: mxEvent.getSender(), }); }; diff --git a/src/components/views/rooms/MessageComposer.js b/src/components/views/rooms/MessageComposer.js index b7078766fb..09b9fb4a36 100644 --- a/src/components/views/rooms/MessageComposer.js +++ b/src/components/views/rooms/MessageComposer.js @@ -312,8 +312,8 @@ export default class MessageComposer extends React.Component { addEmoji(emoji) { dis.dispatch({ - action: "insert_emoji", - emoji, + action: "composer_insert", + text: emoji, }); } diff --git a/src/components/views/rooms/SendMessageComposer.js b/src/components/views/rooms/SendMessageComposer.js index aaeadffae1..ab6aac8be8 100644 --- a/src/components/views/rooms/SendMessageComposer.js +++ b/src/components/views/rooms/SendMessageComposer.js @@ -482,44 +482,18 @@ export default class SendMessageComposer extends React.Component { case Action.FocusComposer: this._editorRef && this._editorRef.focus(); break; - case 'insert_mention_send_composer': - this._editorRef && this._editorRef.insertMention(payload.user_id); - break; - case 'quote': - this._insertQuotedMessage(payload.event); - break; - case 'insert_emoji': - this._insertEmoji(payload.emoji); + case "send_composer_insert": + if (payload.userId) { + this._editorRef && this._editorRef.insertMention(payload.userId); + } else if (payload.event) { + this._editorRef && this._editorRef.insertQuotedMessage(payload.event); + } else if (payload.text) { + this._editorRef && this._editorRef.insertPlaintext(payload.emoji); + } break; } }; - _insertQuotedMessage(event) { - const {model} = this; - const {partCreator} = model; - const quoteParts = parseEvent(event, partCreator, {isQuotedMessage: true}); - // add two newlines - quoteParts.push(partCreator.newline()); - quoteParts.push(partCreator.newline()); - model.transform(() => { - const addedLen = model.insert(quoteParts, model.positionForOffset(0)); - return model.positionForOffset(addedLen, true); - }); - // refocus on composer, as we just clicked "Quote" - this._editorRef && this._editorRef.focus(); - } - - _insertEmoji = (emoji) => { - const {model} = this; - const {partCreator} = model; - const caret = this._editorRef.getCaret(); - const position = model.positionForOffset(caret.offset, caret.atNodeEnd); - model.transform(() => { - const addedLen = model.insert([partCreator.plain(emoji)], position); - return model.positionForOffset(caret.offset + addedLen, true); - }); - }; - _onPaste = (event) => { const {clipboardData} = event; // Prioritize text on the clipboard over files as Office on macOS puts a bitmap diff --git a/src/dispatcher/actions.ts b/src/dispatcher/actions.ts index cd32c3743f..0a01e02b9a 100644 --- a/src/dispatcher/actions.ts +++ b/src/dispatcher/actions.ts @@ -138,4 +138,9 @@ export enum Action { * Fired when an upload is cancelled by the user. Should be used with UploadCanceledPayload. */ UploadCanceled = "upload_canceled", + + /** + * Inserts content into the active composer. Should be used with ComposerInsertPayload + */ + ComposerInsert = "composer_insert", } diff --git a/src/dispatcher/payloads/ComposerInsertPayload.ts b/src/dispatcher/payloads/ComposerInsertPayload.ts new file mode 100644 index 0000000000..9702855432 --- /dev/null +++ b/src/dispatcher/payloads/ComposerInsertPayload.ts @@ -0,0 +1,42 @@ +/* +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 { MatrixEvent } from "matrix-js-sdk/src/models/event"; + +import { ActionPayload } from "../payloads"; +import { Action } from "../actions"; + +interface IBaseComposerInsertPayload extends ActionPayload { + action: Action.ComposerInsert, +} + +interface IComposerInsertMentionPayload extends IBaseComposerInsertPayload { + userId: string; +} + +interface IComposerInsertQuotePayload extends IBaseComposerInsertPayload { + event: MatrixEvent; +} + +interface IComposerInsertPlaintextPayload extends IBaseComposerInsertPayload { + text: string; +} + +export type ComposerInsertPayload = + IComposerInsertMentionPayload | + IComposerInsertQuotePayload | + IComposerInsertPlaintextPayload; + diff --git a/src/editor/model.ts b/src/editor/model.ts index 2e70b872e9..8c4a2dbd0d 100644 --- a/src/editor/model.ts +++ b/src/editor/model.ts @@ -390,7 +390,7 @@ export default class EditorModel { return addLen; } - positionForOffset(totalOffset: number, atPartEnd: boolean) { + positionForOffset(totalOffset: number, atPartEnd = false) { let currentOffset = 0; const index = this._parts.findIndex(part => { const partLen = part.text.length; From 4af7935e35ebb78b128550931c9fe635a90547b4 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 13 Apr 2021 15:11:46 +0100 Subject: [PATCH 0038/1449] fix typos --- src/components/views/rooms/EditMessageComposer.js | 2 +- src/components/views/rooms/SendMessageComposer.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/EditMessageComposer.js b/src/components/views/rooms/EditMessageComposer.js index 39fafe486c..628e030ddb 100644 --- a/src/components/views/rooms/EditMessageComposer.js +++ b/src/components/views/rooms/EditMessageComposer.js @@ -282,7 +282,7 @@ export default class EditMessageComposer extends React.Component { onAction = payload => { if (payload.action === "edit_composer_insert" && this._editorRef) { - if (payload.user_id) { + if (payload.userId) { this._editorRef.insertMention(payload.userId); } else if (payload.event) { this._editorRef.insertQuotedMessage(payload.event); diff --git a/src/components/views/rooms/SendMessageComposer.js b/src/components/views/rooms/SendMessageComposer.js index ab6aac8be8..14893a6bd2 100644 --- a/src/components/views/rooms/SendMessageComposer.js +++ b/src/components/views/rooms/SendMessageComposer.js @@ -488,7 +488,7 @@ export default class SendMessageComposer extends React.Component { } else if (payload.event) { this._editorRef && this._editorRef.insertQuotedMessage(payload.event); } else if (payload.text) { - this._editorRef && this._editorRef.insertPlaintext(payload.emoji); + this._editorRef && this._editorRef.insertPlaintext(payload.text); } break; } From 86b6fc3473279e56905a9190abe689f620bd3a92 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 13 Apr 2021 15:15:11 +0100 Subject: [PATCH 0039/1449] delint --- src/components/views/rooms/SendMessageComposer.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/views/rooms/SendMessageComposer.js b/src/components/views/rooms/SendMessageComposer.js index 14893a6bd2..efb3dd3754 100644 --- a/src/components/views/rooms/SendMessageComposer.js +++ b/src/components/views/rooms/SendMessageComposer.js @@ -30,7 +30,6 @@ import { import {CommandPartCreator} from '../../../editor/parts'; import BasicMessageComposer from "./BasicMessageComposer"; import ReplyThread from "../elements/ReplyThread"; -import {parseEvent} from '../../../editor/deserialize'; import {findEditableEvent} from '../../../utils/EventUtils'; import SendHistoryManager from "../../../SendHistoryManager"; import {CommandCategories, getCommand} from '../../../SlashCommands'; From 33fd09d7771fb014b97c1ae0425c5e33c96722ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Apr 2021 20:21:03 +0200 Subject: [PATCH 0040/1449] Make private MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/VideoFeed.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/views/voip/VideoFeed.tsx b/src/components/views/voip/VideoFeed.tsx index 43696defb9..23e51626d9 100644 --- a/src/components/views/voip/VideoFeed.tsx +++ b/src/components/views/voip/VideoFeed.tsx @@ -66,7 +66,7 @@ export default class VideoFeed extends React.Component { this.playMedia(); } - playMedia() { + private playMedia() { const audioOutput = CallMediaHandler.getAudioOutput(); const currentMedia = this.getCurrentMedia(); @@ -117,11 +117,11 @@ export default class VideoFeed extends React.Component { // seem to be necessary - Šimon } - getCurrentMedia() { + private getCurrentMedia() { return this.audio.current || this.video.current; } - onNewStream = () => { + private onNewStream = () => { this.setState({ audioMuted: this.props.feed.isAudioMuted(), videoMuted: this.props.feed.isVideoMuted(), @@ -129,7 +129,7 @@ export default class VideoFeed extends React.Component { this.playMedia(); } - onResize = (e) => { + private onResize = (e) => { if (this.props.onResize && !this.props.feed.isLocal()) { this.props.onResize(e); } From f32eee94755e8f1692a1d50105e1ceb14bed1ad7 Mon Sep 17 00:00:00 2001 From: Jaiwanth Date: Wed, 14 Apr 2021 16:01:42 +0530 Subject: [PATCH 0041/1449] Added slashcommands support to edit message composer Signed-off-by: Jaiwanth --- .../views/rooms/EditMessageComposer.js | 126 ++++++++++++++++-- src/i18n/strings/en_EN.json | 14 +- 2 files changed, 125 insertions(+), 15 deletions(-) diff --git a/src/components/views/rooms/EditMessageComposer.js b/src/components/views/rooms/EditMessageComposer.js index b006fe8c8d..a12a6497ad 100644 --- a/src/components/views/rooms/EditMessageComposer.js +++ b/src/components/views/rooms/EditMessageComposer.js @@ -16,7 +16,7 @@ limitations under the License. */ import React from 'react'; import * as sdk from '../../../index'; -import {_t} from '../../../languageHandler'; +import {_t, _td} from '../../../languageHandler'; import PropTypes from 'prop-types'; import dis from '../../../dispatcher/dispatcher'; import EditorModel from '../../../editor/model'; @@ -24,16 +24,18 @@ import {getCaretOffsetAndText} from '../../../editor/dom'; import {htmlSerializeIfNeeded, textSerialize, containsEmote, stripEmoteCommand} from '../../../editor/serialize'; import {findEditableEvent} from '../../../utils/EventUtils'; import {parseEvent} from '../../../editor/deserialize'; -import {PartCreator} from '../../../editor/parts'; +import {CommandPartCreator} from '../../../editor/parts'; import EditorStateTransfer from '../../../utils/EditorStateTransfer'; import classNames from 'classnames'; import {EventStatus} from 'matrix-js-sdk/src/models/event'; import BasicMessageComposer from "./BasicMessageComposer"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; +import {CommandCategories, getCommand} from '../../../SlashCommands'; import {Action} from "../../../dispatcher/actions"; import CountlyAnalytics from "../../../CountlyAnalytics"; import {getKeyBindingsManager, MessageComposerAction} from '../../../KeyBindingsManager'; import {replaceableComponent} from "../../../utils/replaceableComponent"; +import Modal from '../../../Modal'; function _isReply(mxEvent) { const relatesTo = mxEvent.getContent()["m.relates_to"]; @@ -177,6 +179,21 @@ export default class EditMessageComposer extends React.Component { dis.dispatch({action: "edit_event", event: null}); dis.fire(Action.FocusComposer); } + _isSlashCommand() { + const parts = this.model.parts; + const firstPart = parts[0]; + if (firstPart) { + if (firstPart.type === "command" && firstPart.text.startsWith("/") && !firstPart.text.startsWith("//")) { + return true; + } + + if (firstPart.text.startsWith("/") && !firstPart.text.startsWith("//") + && (firstPart.type === "plain" || firstPart.type === "pill-candidate")) { + return true; + } + } + return false; + } _isContentModified(newContent) { // if nothing has changed then bail @@ -190,19 +207,112 @@ export default class EditMessageComposer extends React.Component { return true; } - _sendEdit = () => { + _getSlashCommand() { + const commandText = this.model.parts.reduce((text, part) => { + // use mxid to textify user pills in a command + if (part.type === "user-pill") { + return text + part.resourceId; + } + return text + part.text; + }, ""); + const {cmd, args} = getCommand(commandText); + return [cmd, args, commandText]; + } + + async _runSlashCommand(cmd, args, roomId) { + const result = cmd.run(roomId, args); + let messageContent; + let error = result.error; + if (result.promise) { + try { + if (cmd.category === CommandCategories.messages) { + messageContent = await result.promise; + } else { + await result.promise; + } + } catch (err) { + error = err; + } + } + if (error) { + console.error("Command failure: %s", error); + const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); + // assume the error is a server error when the command is async + const isServerError = !!result.promise; + const title = isServerError ? _td("Server error") : _td("Command error"); + + let errText; + if (typeof error === 'string') { + errText = error; + } else if (error.message) { + errText = error.message; + } else { + errText = _t("Server unavailable, overloaded, or something else went wrong."); + } + + Modal.createTrackedDialog(title, '', ErrorDialog, { + title: _t(title), + description: errText, + }); + } else { + console.log("Command success."); + if (messageContent) return messageContent; + } + } + + _sendEdit = async () => { const startTime = CountlyAnalytics.getTimestamp(); const editedEvent = this.props.editState.getEvent(); const editContent = createEditContent(this.model, editedEvent); const newContent = editContent["m.new_content"]; + let shouldSend = true; // If content is modified then send an updated event into the room if (this._isContentModified(newContent)) { const roomId = editedEvent.getRoomId(); - this._cancelPreviousPendingEdit(); - const prom = this.context.sendMessage(roomId, editContent); - dis.dispatch({action: "message_sent"}); - CountlyAnalytics.instance.trackSendMessage(startTime, prom, roomId, true, false, editContent); + if (!containsEmote(this.model) && this._isSlashCommand()) { + const [cmd, args, commandText] = this._getSlashCommand(); + if (cmd) { + if (cmd.category === CommandCategories.messages) { + editContent["m.new_content"] = await this._runSlashCommand(cmd, args, roomId); + } else { + this._runSlashCommand(cmd, args, roomId); + shouldSend = false; + } + } else { + // ask the user if their unknown command should be sent as a message + const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); + const {finished} = Modal.createTrackedDialog("Unknown command", "", QuestionDialog, { + title: _t("Unknown Command"), + description:
      +

      + { _t("Unrecognised command: %(commandText)s", {commandText}) } +

      +

      + { _t("You can use /help to list available commands. " + + "Did you mean to send this as a message?", {}, { + code: t => { t }, + }) } +

      +

      + { _t("Hint: Begin your message with // to start it with a slash.", {}, { + code: t => { t }, + }) } +

      +
      , + button: _t('Send as message'), + }); + const [sendAnyway] = await finished; + // if !sendAnyway bail to let the user edit the composer and try again + if (!sendAnyway) return; + } + } + if (shouldSend) { + this._cancelPreviousPendingEdit(); + const prom = this.context.sendMessage(roomId, editContent); + dis.dispatch({action: "message_sent"}); + CountlyAnalytics.instance.trackSendMessage(startTime, prom, roomId, true, false, editContent); + } } // close the event editing and focus composer @@ -240,7 +350,7 @@ export default class EditMessageComposer extends React.Component { _createEditorModel() { const {editState} = this.props; const room = this._getRoom(); - const partCreator = new PartCreator(room, this.context); + const partCreator = new CommandPartCreator(room, this.context); let parts; if (editState.hasEditorState()) { // if restoring state from a previous editor, diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 02236f9997..f30040c6be 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1436,6 +1436,13 @@ "Someone is using an unknown session": "Someone is using an unknown session", "This room is end-to-end encrypted": "This room is end-to-end encrypted", "Everyone in this room is verified": "Everyone in this room is verified", + "Server error": "Server error", + "Server unavailable, overloaded, or something else went wrong.": "Server unavailable, overloaded, or something else went wrong.", + "Unknown Command": "Unknown Command", + "Unrecognised command: %(commandText)s": "Unrecognised command: %(commandText)s", + "You can use /help to list available commands. Did you mean to send this as a message?": "You can use /help to list available commands. Did you mean to send this as a message?", + "Hint: Begin your message with // to start it with a slash.": "Hint: Begin your message with // to start it with a slash.", + "Send as message": "Send as message", "Edit message": "Edit message", "Mod": "Mod", "This event could not be displayed": "This event could not be displayed", @@ -1622,13 +1629,6 @@ "This Room": "This Room", "All Rooms": "All Rooms", "Search…": "Search…", - "Server error": "Server error", - "Server unavailable, overloaded, or something else went wrong.": "Server unavailable, overloaded, or something else went wrong.", - "Unknown Command": "Unknown Command", - "Unrecognised command: %(commandText)s": "Unrecognised command: %(commandText)s", - "You can use /help to list available commands. Did you mean to send this as a message?": "You can use /help to list available commands. Did you mean to send this as a message?", - "Hint: Begin your message with // to start it with a slash.": "Hint: Begin your message with // to start it with a slash.", - "Send as message": "Send as message", "Failed to connect to integration manager": "Failed to connect to integration manager", "You don't currently have any stickerpacks enabled": "You don't currently have any stickerpacks enabled", "Add some now": "Add some now", From 2cfd4659e13543caa4cc913be06ca199a820d34d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 16 Apr 2021 12:50:23 +0200 Subject: [PATCH 0042/1449] Add separate mx_CallView_content class MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/voip/_CallView.scss | 12 ++++++------ src/components/views/voip/CallView.tsx | 4 ++++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/res/css/views/voip/_CallView.scss b/res/css/views/voip/_CallView.scss index 90a3ca4209..0a3865479a 100644 --- a/res/css/views/voip/_CallView.scss +++ b/res/css/views/voip/_CallView.scss @@ -64,14 +64,17 @@ limitations under the License. } } -.mx_CallView_voice { +.mx_CallView_content { position: relative; display: flex; - flex-direction: column; + border-radius: 8px; +} + +.mx_CallView_voice { align-items: center; justify-content: center; + flex-direction: column; background-color: $inverted-bg-color; - border-radius: 8px; } .mx_CallView_voice_avatarsContainer { @@ -108,11 +111,8 @@ limitations under the License. .mx_CallView_video { width: 100%; height: 100%; - position: relative; z-index: 30; - border-radius: 8px; overflow: hidden; - display: flex; } .mx_CallView_video_hold { diff --git a/src/components/views/voip/CallView.tsx b/src/components/views/voip/CallView.tsx index ea5411486f..544e54ec9d 100644 --- a/src/components/views/voip/CallView.tsx +++ b/src/components/views/voip/CallView.tsx @@ -536,6 +536,7 @@ export default class CallView extends React.Component { if (isOnHold || transfereeCall) { if (this.props.call.type === CallType.Video) { const containerClasses = classNames({ + mx_CallView_content: true, mx_CallView_video: true, mx_CallView_video_hold: isOnHold, }); @@ -557,6 +558,7 @@ export default class CallView extends React.Component { ); } else { const classes = classNames({ + mx_CallView_content: true, mx_CallView_voice: true, mx_CallView_voice_hold: isOnHold, }); @@ -586,6 +588,7 @@ export default class CallView extends React.Component { // to change anyway - I might take an axe to this file in order to // try to get other things working const classes = classNames({ + mx_CallView_content: true, mx_CallView_voice: true, }); @@ -622,6 +625,7 @@ export default class CallView extends React.Component {
      ; } else { const containerClasses = classNames({ + mx_CallView_content: true, mx_CallView_video: true, }); From 61a260cd405eacac4c52777bd048657a9fda3702 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sun, 18 Apr 2021 15:40:56 +0200 Subject: [PATCH 0043/1449] Format mxid --- res/css/views/messages/_SenderProfile.scss | 12 ++++++ .../views/messages/SenderProfile.js | 43 ++++++++++++++----- 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/res/css/views/messages/_SenderProfile.scss b/res/css/views/messages/_SenderProfile.scss index 655cb39489..e3a38bad6d 100644 --- a/res/css/views/messages/_SenderProfile.scss +++ b/res/css/views/messages/_SenderProfile.scss @@ -15,6 +15,18 @@ limitations under the License. */ .mx_SenderProfile_name { + display: flex; + align-items: center; + gap: 5px; +} + +.mx_SenderProfile_displayName { font-weight: 600; } +.mx_SenderProfile_mxid { + font-weight: 600; + font-family: monospace; + font-size: 1rem; + color: gray; +} diff --git a/src/components/views/messages/SenderProfile.js b/src/components/views/messages/SenderProfile.js index bd10526799..264d4ed3de 100644 --- a/src/components/views/messages/SenderProfile.js +++ b/src/components/views/messages/SenderProfile.js @@ -89,7 +89,21 @@ export default class SenderProfile extends React.Component { render() { const {mxEvent} = this.props; const colorClass = getUserNameColorClass(mxEvent.getSender()); - const name = mxEvent.sender ? mxEvent.sender.name : mxEvent.getSender(); + + let disambiguate; + let displayName; + let mxid; + + const sender = mxEvent.sender; + if (sender) { + disambiguate = sender.disambiguate; + displayName = sender.rawDisplayName; + mxid = sender.userId; + } else { + disambiguate = false; + displayName = mxEvent.getSender(); + mxid = mxEvent.getSender(); + } const {msgtype} = mxEvent.getContent(); if (msgtype === 'm.emote') { @@ -108,20 +122,29 @@ export default class SenderProfile extends React.Component { />; } - const nameElem = name || ''; - - // Name + flair - const nameFlair = - - { nameElem } + const displayNameElement = ( + + { displayName || '' } - { flair } - ; + ); + + let mxidElement; + if (disambiguate) { + mxidElement = ( + + { `[${mxid || ""}]` } + + ); + } return (
      - { nameFlair } +
      + { displayNameElement } + { mxidElement } + { flair } +
      ); From 758112dda95d36c0a09891b9e86482a92ee49ea9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 19 Apr 2021 07:42:32 +0200 Subject: [PATCH 0044/1449] Add missing somicolons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/CallView.tsx | 2 +- src/components/views/voip/VideoFeed.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/voip/CallView.tsx b/src/components/views/voip/CallView.tsx index 544e54ec9d..549e3da188 100644 --- a/src/components/views/voip/CallView.tsx +++ b/src/components/views/voip/CallView.tsx @@ -192,7 +192,7 @@ export default class CallView extends React.Component { private onFeedsChanged = (newFeeds: Array) => { this.setState({feeds: newFeeds}); - } + }; private onCallLocalHoldUnhold = () => { this.setState({ diff --git a/src/components/views/voip/VideoFeed.tsx b/src/components/views/voip/VideoFeed.tsx index 23e51626d9..f3ffdd62c5 100644 --- a/src/components/views/voip/VideoFeed.tsx +++ b/src/components/views/voip/VideoFeed.tsx @@ -127,7 +127,7 @@ export default class VideoFeed extends React.Component { videoMuted: this.props.feed.isVideoMuted(), }); this.playMedia(); - } + }; private onResize = (e) => { if (this.props.onResize && !this.props.feed.isLocal()) { From 39eb487f49718453ac152d97119f764527a67821 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 20 Apr 2021 11:09:03 +0200 Subject: [PATCH 0045/1449] TS conversion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- .../{SenderProfile.js => SenderProfile.tsx} | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) rename src/components/views/messages/{SenderProfile.js => SenderProfile.tsx} (82%) diff --git a/src/components/views/messages/SenderProfile.js b/src/components/views/messages/SenderProfile.tsx similarity index 82% rename from src/components/views/messages/SenderProfile.js rename to src/components/views/messages/SenderProfile.tsx index 264d4ed3de..fa635eaedb 100644 --- a/src/components/views/messages/SenderProfile.js +++ b/src/components/views/messages/SenderProfile.tsx @@ -15,26 +15,37 @@ */ import React from 'react'; -import PropTypes from 'prop-types'; import Flair from '../elements/Flair.js'; import FlairStore from '../../../stores/FlairStore'; import {getUserNameColorClass} from '../../../utils/FormattingUtils'; import MatrixClientContext from "../../../contexts/MatrixClientContext"; import {replaceableComponent} from "../../../utils/replaceableComponent"; +import MatrixEvent from "matrix-js-sdk/src/models/event"; + +interface IProps { + mxEvent: MatrixEvent; + onClick(): void; + enableFlair: boolean; +} + +interface IState { + userGroups; + relatedGroups; +} @replaceableComponent("views.messages.SenderProfile") -export default class SenderProfile extends React.Component { - static propTypes = { - mxEvent: PropTypes.object.isRequired, // event whose sender we're showing - onClick: PropTypes.func, - }; - +export default class SenderProfile extends React.Component { static contextType = MatrixClientContext; + unmounted: boolean; - state = { - userGroups: null, - relatedGroups: [], - }; + constructor(props: IProps) { + super(props) + + this.state = { + userGroups: null, + relatedGroups: [], + }; + } componentDidMount() { this.unmounted = false; @@ -89,28 +100,17 @@ export default class SenderProfile extends React.Component { render() { const {mxEvent} = this.props; const colorClass = getUserNameColorClass(mxEvent.getSender()); - - let disambiguate; - let displayName; - let mxid; - - const sender = mxEvent.sender; - if (sender) { - disambiguate = sender.disambiguate; - displayName = sender.rawDisplayName; - mxid = sender.userId; - } else { - disambiguate = false; - displayName = mxEvent.getSender(); - mxid = mxEvent.getSender(); - } const {msgtype} = mxEvent.getContent(); + const disambiguate = mxEvent.sender?.disambiguate; + const displayName = mxEvent.sender?.rawDisplayName || mxEvent.getSender() || ""; + const mxid = mxEvent.sender?.userId || mxEvent.getSender() || ""; + if (msgtype === 'm.emote') { return ; // emote message must include the name so don't duplicate it } - let flair =
      ; + let flair; if (this.props.enableFlair) { const displayedGroups = this._getDisplayedGroups( this.state.userGroups, this.state.relatedGroups, @@ -124,7 +124,7 @@ export default class SenderProfile extends React.Component { const displayNameElement = ( - { displayName || '' } + { displayName } ); @@ -132,7 +132,7 @@ export default class SenderProfile extends React.Component { if (disambiguate) { mxidElement = ( - { `[${mxid || ""}]` } + { `[${mxid}]` } ); } From faca498523460e59215bbe819521fcda01069729 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 20 Apr 2021 11:12:16 +0200 Subject: [PATCH 0046/1449] Don't use gap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/messages/_SenderProfile.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/css/views/messages/_SenderProfile.scss b/res/css/views/messages/_SenderProfile.scss index e3a38bad6d..d7763cda08 100644 --- a/res/css/views/messages/_SenderProfile.scss +++ b/res/css/views/messages/_SenderProfile.scss @@ -17,7 +17,6 @@ limitations under the License. .mx_SenderProfile_name { display: flex; align-items: center; - gap: 5px; } .mx_SenderProfile_displayName { @@ -29,4 +28,5 @@ limitations under the License. font-family: monospace; font-size: 1rem; color: gray; + margin-left: 5px; } From 4e1409dc2c7258816e51efb204a09ef608055117 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 20 Apr 2021 11:40:50 +0200 Subject: [PATCH 0047/1449] Add private Co-authored-by: Michael Telatynski <7t3chguy@googlemail.com> --- src/components/views/messages/SenderProfile.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/messages/SenderProfile.tsx b/src/components/views/messages/SenderProfile.tsx index fa635eaedb..f0dd77f746 100644 --- a/src/components/views/messages/SenderProfile.tsx +++ b/src/components/views/messages/SenderProfile.tsx @@ -36,7 +36,7 @@ interface IState { @replaceableComponent("views.messages.SenderProfile") export default class SenderProfile extends React.Component { static contextType = MatrixClientContext; - unmounted: boolean; + private unmounted: boolean; constructor(props: IProps) { super(props) From ffcd79f4a3215c1153e50ec599a8cd18b2d1e5a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 21 Apr 2021 17:34:03 +0200 Subject: [PATCH 0048/1449] Remove brackets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/messages/SenderProfile.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/messages/SenderProfile.tsx b/src/components/views/messages/SenderProfile.tsx index f0dd77f746..b2bfe00168 100644 --- a/src/components/views/messages/SenderProfile.tsx +++ b/src/components/views/messages/SenderProfile.tsx @@ -132,7 +132,7 @@ export default class SenderProfile extends React.Component { if (disambiguate) { mxidElement = ( - { `[${mxid}]` } + { mxid } ); } From eee1294374c568ee3e9c956b5fb3acaf537918a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 21 Apr 2021 17:37:25 +0200 Subject: [PATCH 0049/1449] Make both have the same baseline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/messages/_SenderProfile.scss | 5 ----- src/components/views/messages/SenderProfile.tsx | 8 +++----- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/res/css/views/messages/_SenderProfile.scss b/res/css/views/messages/_SenderProfile.scss index d7763cda08..14e8f6583f 100644 --- a/res/css/views/messages/_SenderProfile.scss +++ b/res/css/views/messages/_SenderProfile.scss @@ -14,11 +14,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -.mx_SenderProfile_name { - display: flex; - align-items: center; -} - .mx_SenderProfile_displayName { font-weight: 600; } diff --git a/src/components/views/messages/SenderProfile.tsx b/src/components/views/messages/SenderProfile.tsx index b2bfe00168..70040e4ef7 100644 --- a/src/components/views/messages/SenderProfile.tsx +++ b/src/components/views/messages/SenderProfile.tsx @@ -140,11 +140,9 @@ export default class SenderProfile extends React.Component { return (
      -
      - { displayNameElement } - { mxidElement } - { flair } -
      + { displayNameElement } + { mxidElement } + { flair }
      ); From 9658a760c8bd96dd91498d064e7898c5a70fe19f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 21 Apr 2021 17:41:21 +0200 Subject: [PATCH 0050/1449] Use timestamp color MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/messages/_SenderProfile.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/css/views/messages/_SenderProfile.scss b/res/css/views/messages/_SenderProfile.scss index 14e8f6583f..378d9e6f1a 100644 --- a/res/css/views/messages/_SenderProfile.scss +++ b/res/css/views/messages/_SenderProfile.scss @@ -22,6 +22,6 @@ limitations under the License. font-weight: 600; font-family: monospace; font-size: 1rem; - color: gray; + color: $event-timestamp-color; margin-left: 5px; } From 55365e632b524015f3dca528e18d2c593861bf0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 22 Apr 2021 07:52:39 +0200 Subject: [PATCH 0051/1449] Use the correct selector in E2EE tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- test/end-to-end-tests/src/usecases/timeline.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/end-to-end-tests/src/usecases/timeline.js b/test/end-to-end-tests/src/usecases/timeline.js index 3889dce108..01dc618571 100644 --- a/test/end-to-end-tests/src/usecases/timeline.js +++ b/test/end-to-end-tests/src/usecases/timeline.js @@ -122,7 +122,7 @@ function getAllEventTiles(session) { } async function getMessageFromEventTile(eventTile) { - const senderElement = await eventTile.$(".mx_SenderProfile_name"); + const senderElement = await eventTile.$(".mx_SenderProfile_displayName"); const className = await (await eventTile.getProperty("className")).jsonValue(); const classNames = className.split(" "); const bodyElement = await eventTile.$(".mx_EventTile_body"); From bf444ce22ef36f4ac9f830fe31365b096a0d3ee2 Mon Sep 17 00:00:00 2001 From: Aaron Raimist Date: Fri, 23 Apr 2021 11:31:27 -0500 Subject: [PATCH 0052/1449] Typo: initilisation -> initialisation Signed-off-by: Aaron Raimist --- src/components/views/settings/EventIndexPanel.js | 2 +- src/i18n/strings/en_EN.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/settings/EventIndexPanel.js b/src/components/views/settings/EventIndexPanel.js index d1a02de16d..4af5ad6123 100644 --- a/src/components/views/settings/EventIndexPanel.js +++ b/src/components/views/settings/EventIndexPanel.js @@ -229,7 +229,7 @@ export default class EventIndexPanel extends React.Component {

      {this.state.enabling ? - : _t("Message search initilisation failed") + : _t("Message search initialisation failed") }

      {EventIndexPeg.error && ( diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index f1b700540f..5910ee803c 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1086,7 +1086,7 @@ "Securely cache encrypted messages locally for them to appear in search results.": "Securely cache encrypted messages locally for them to appear in search results.", "%(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)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)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 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.", - "Message search initilisation failed": "Message search initilisation failed", + "Message search initialisation failed": "Message search initialisation failed", "Connecting to integration manager...": "Connecting to integration manager...", "Cannot connect to integration manager": "Cannot connect to integration manager", "The integration manager is offline or it cannot reach your homeserver.": "The integration manager is offline or it cannot reach your homeserver.", From 284b9e48cee1698fad9cf571709ba66e284e3aa8 Mon Sep 17 00:00:00 2001 From: Aaron Raimist Date: Fri, 23 Apr 2021 11:38:53 -0500 Subject: [PATCH 0053/1449] Also fix translations --- src/i18n/strings/cs.json | 2 +- src/i18n/strings/de_DE.json | 2 +- src/i18n/strings/es.json | 2 +- src/i18n/strings/et.json | 2 +- src/i18n/strings/fr.json | 2 +- src/i18n/strings/gl.json | 2 +- src/i18n/strings/hu.json | 2 +- src/i18n/strings/it.json | 2 +- src/i18n/strings/nl.json | 2 +- src/i18n/strings/sq.json | 2 +- src/i18n/strings/sv.json | 2 +- src/i18n/strings/zh_Hant.json | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/i18n/strings/cs.json b/src/i18n/strings/cs.json index 7f9ff9341c..87dbb6c70c 100644 --- a/src/i18n/strings/cs.json +++ b/src/i18n/strings/cs.json @@ -3168,7 +3168,7 @@ "Open": "Otevřít", "Share decryption keys for room history when inviting users": "Při pozvání uživatelů sdílet dešifrovací klíče pro historii místnosti", "Manage & explore rooms": "Spravovat a prozkoumat místnosti", - "Message search initilisation failed": "Inicializace vyhledávání zpráv se nezdařila", + "Message search initialisation failed": "Inicializace vyhledávání zpráv se nezdařila", "%(count)s people you know have already joined|one": "%(count)s osoba, kterou znáte, se již připojila", "Invited people will be able to read old messages.": "Pozvaní lidé budou moci číst staré zprávy.", "If you do, please note that none of your messages will be deleted, but the search experience might be degraded for a few momentswhilst the index is recreated": "Pokud tak učiníte, nezapomeňte, že žádná z vašich zpráv nebude smazána, ale vyhledávání může být na několik okamžiků degradováno, zatímco index bude znovu vytvářen", diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 9551f00e55..133cfc430d 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -3227,7 +3227,7 @@ "This homeserver has been blocked by it's administrator.": "Dieser Heimserver wurde von seiner Administration blockiert.", "You have unverified logins": "Du hast nicht-bestätigte Anmeldungen", "Review to ensure your account is safe": "Überprüfen, um sicher zu sein, dass dein Konto sicher ist", - "Message search initilisation failed": "Initialisierung der Nachrichtensuche fehlgeschlagen", + "Message search initialisation failed": "Initialisierung der Nachrichtensuche fehlgeschlagen", "Support": "Unterstützen", "This room is suggested as a good one to join": "Dieser Raum wurde als gut zum Beitreten vorgeschlagen", "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.": "Deine Nachricht wurde nicht versendet, weil dieser Heimserver von dessen Administrator gesperrt wurde. Bitte kontaktiere deinen Dienstadministrator um den Dienst weiterzunutzen.", diff --git a/src/i18n/strings/es.json b/src/i18n/strings/es.json index d396cc318f..a41dc65cc3 100644 --- a/src/i18n/strings/es.json +++ b/src/i18n/strings/es.json @@ -3213,7 +3213,7 @@ "Review to ensure your account is safe": "Revisa que tu cuenta esté segura", "Sends the given message as a spoiler": "Envía el mensaje como un spoiler", "Consulting with %(transferTarget)s. Transfer to %(transferee)s": "Consultando a %(transferTarget)s. Transferir a %(transferee)s", - "Message search initilisation failed": "Ha fallado la inicialización de la búsqueda de mensajes", + "Message search initialisation failed": "Ha fallado la inicialización de la búsqueda de mensajes", "Reset event store?": "¿Restablecer almacenamiento de eventos?", "You most likely do not want to reset your event index store": "Lo más probable es que no quieras restablecer tu almacenamiento de índice de ecentos", "If you do, please note that none of your messages will be deleted, but the search experience might be degraded for a few momentswhilst the index is recreated": "Si lo haces, ten en cuenta que no se borrarán tus mensajes, pero la experiencia de búsqueda será peor durante unos momentos mientras se recrea el índice", diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index 444475deea..509008012d 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -3249,7 +3249,7 @@ "Reset event store": "Lähtesta sündmuste andmekogu", "Verify other login": "Verifitseeri muu sisselogimissessioon", "Consulting with %(transferTarget)s. Transfer to %(transferee)s": "Suhtlen teise osapoolega %(transferTarget)s. Saadan andmeid kasutajale %(transferee)s", - "Message search initilisation failed": "Sõnumite otsingu alustamine ei õnnestunud", + "Message search initialisation failed": "Sõnumite otsingu alustamine ei õnnestunud", "Invite messages are hidden by default. Click to show the message.": "Kutsed on vaikimisi peidetud. Sõnumi nägemiseks klõpsi.", "Accept on your other login…": "Nõustu oma teise sisselogimissessiooniga…", "Avatar": "Tunnuspilt", diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index fcc5ec9afe..3962525271 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -3254,7 +3254,7 @@ "Quick actions": "Actions rapides", "Invite to just this room": "Inviter seulement dans ce salon", "Warn before quitting": "Avertir avant de quitter", - "Message search initilisation failed": "Échec de l’initialisation de la recherche de message", + "Message search initialisation failed": "Échec de l’initialisation de la recherche de message", "Manage & explore rooms": "Gérer et découvrir les salons", "Consulting with %(transferTarget)s. Transfer to %(transferee)s": "Consultation avec %(transferTarget)s. Transfert à %(transferee)s", "unknown person": "personne inconnue", diff --git a/src/i18n/strings/gl.json b/src/i18n/strings/gl.json index f6ebce684f..4ac3e1bcdd 100644 --- a/src/i18n/strings/gl.json +++ b/src/i18n/strings/gl.json @@ -3269,7 +3269,7 @@ "unknown person": "persoa descoñecida", "Consulting with %(transferTarget)s. Transfer to %(transferee)s": "Consultando con %(transferTarget)s. Transferir a %(transferee)s", "Manage & explore rooms": "Xestionar e explorar salas", - "Message search initilisation failed": "Fallo a inicialización da busca de mensaxes", + "Message search initialisation failed": "Fallo a inicialización da busca de mensaxes", "Quick actions": "Accións rápidas", "Invite messages are hidden by default. Click to show the message.": "As mensaxes de convite están agochadas por defecto. Preme para amosar a mensaxe.", "Record a voice message": "Gravar mensaxe de voz", diff --git a/src/i18n/strings/hu.json b/src/i18n/strings/hu.json index 2ec5af8a17..64949ad848 100644 --- a/src/i18n/strings/hu.json +++ b/src/i18n/strings/hu.json @@ -3272,7 +3272,7 @@ "Quick actions": "Gyors műveletek", "Invite to just this room": "Meghívás csak ebbe a szobába", "Warn before quitting": "Kilépés előtt figyelmeztet", - "Message search initilisation failed": "Üzenet keresés beállítása sikertelen", + "Message search initialisation failed": "Üzenet keresés beállítása sikertelen", "Manage & explore rooms": "Szobák kezelése és felderítése", "Consulting with %(transferTarget)s. Transfer to %(transferee)s": "Egyeztetés vele: %(transferTarget)s. Átadás ide: %(transferee)s", "unknown person": "ismeretlen személy", diff --git a/src/i18n/strings/it.json b/src/i18n/strings/it.json index 2d0edb77e6..c4ed6cd640 100644 --- a/src/i18n/strings/it.json +++ b/src/i18n/strings/it.json @@ -3260,7 +3260,7 @@ "Invite to just this room": "Invita solo in questa stanza", "%(count)s people you know have already joined|other": "%(count)s persone che conosci sono già entrate", "%(count)s people you know have already joined|one": "%(count)s persona che conosci è già entrata", - "Message search initilisation failed": "Inizializzazione ricerca messaggi fallita", + "Message search initialisation failed": "Inizializzazione ricerca messaggi fallita", "Add existing rooms": "Aggiungi stanze esistenti", "Warn before quitting": "Avvisa prima di uscire", "Invited people will be able to read old messages.": "Le persone invitate potranno leggere i vecchi messaggi.", diff --git a/src/i18n/strings/nl.json b/src/i18n/strings/nl.json index de98a878e8..aa6482ccf5 100644 --- a/src/i18n/strings/nl.json +++ b/src/i18n/strings/nl.json @@ -3163,7 +3163,7 @@ "Quick actions": "Snelle acties", "Invite to just this room": "Uitnodigen voor alleen dit gesprek", "Warn before quitting": "Waarschuwen voordat u afsluit", - "Message search initilisation failed": "Zoeken in berichten opstarten is mislukt", + "Message search initialisation failed": "Zoeken in berichten opstarten is mislukt", "Manage & explore rooms": "Beheer & ontdek gesprekken", "Consulting with %(transferTarget)s. Transfer to %(transferee)s": "Overleggen met %(transferTarget)s. Verstuur naar %(transferee)s", "unknown person": "onbekend persoon", diff --git a/src/i18n/strings/sq.json b/src/i18n/strings/sq.json index ad768b59cb..1eabf09cac 100644 --- a/src/i18n/strings/sq.json +++ b/src/i18n/strings/sq.json @@ -3265,7 +3265,7 @@ "Quick actions": "Veprime të shpejta", "Invite to just this room": "Ftoje thjesht te kjo dhomë", "Warn before quitting": "Sinjalizo përpara daljes", - "Message search initilisation failed": "Dështoi gatitje kërkimi mesazhesh", + "Message search initialisation failed": "Dështoi gatitje kërkimi mesazhesh", "Manage & explore rooms": "Administroni & eksploroni dhoma", "unknown person": "person i panjohur", "Sends the given message as a spoiler": "E dërgon mesazhin e dhënë si spoiler", diff --git a/src/i18n/strings/sv.json b/src/i18n/strings/sv.json index 42a7f78268..6e839750ff 100644 --- a/src/i18n/strings/sv.json +++ b/src/i18n/strings/sv.json @@ -3212,7 +3212,7 @@ "Verification requested": "Verifiering begärd", "Sends the given message as a spoiler": "Skickar det angivna meddelandet som en spoiler", "Manage & explore rooms": "Hantera och utforska rum", - "Message search initilisation failed": "Initialisering av meddelandesökning misslyckades", + "Message search initialisation failed": "Initialisering av meddelandesökning misslyckades", "Please choose a strong password": "Vänligen välj ett starkt lösenord", "Use another login": "Använd annan inloggning", "Verify your identity to access encrypted messages and prove your identity to others.": "Verifiera din identitet för att komma åt krypterade meddelanden och bevisa din identitet för andra.", diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index c9bb9bb2d7..6d0e0854ed 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -3254,7 +3254,7 @@ "You have unverified logins": "您有未驗證的登入", "unknown person": "不明身份的人", "Consulting with %(transferTarget)s. Transfer to %(transferee)s": "與 %(transferTarget)s 進行協商。轉讓至 %(transferee)s", - "Message search initilisation failed": "訊息搜尋初始化失敗", + "Message search initialisation failed": "訊息搜尋初始化失敗", "Invite to just this room": "邀請到此聊天室", "If you do, please note that none of your messages will be deleted, but the search experience might be degraded for a few momentswhilst the index is recreated": "如果這樣做,請注意,您的任何訊息都不會被刪除,但是在重新建立索引的同時,搜索體驗可能會降低片刻", "Let's create a room for each of them.": "讓我們為每個主題建立一個聊天室吧。", From fbb8cfb1884fc62beb3be22a5baef21b84803418 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 23 Apr 2021 19:41:55 +0200 Subject: [PATCH 0054/1449] Rework how media element are handled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/voip/_VideoFeed.scss | 2 + src/components/views/voip/VideoFeed.tsx | 81 +++++++++++++++---------- 2 files changed, 51 insertions(+), 32 deletions(-) diff --git a/res/css/views/voip/_VideoFeed.scss b/res/css/views/voip/_VideoFeed.scss index 46cdf4f52c..6f51353552 100644 --- a/res/css/views/voip/_VideoFeed.scss +++ b/res/css/views/voip/_VideoFeed.scss @@ -22,6 +22,8 @@ limitations under the License. .mx_VideoFeed_video { background-color: #000; + width: 100%; + height: 100%; } .mx_VideoFeed_remote { diff --git a/src/components/views/voip/VideoFeed.tsx b/src/components/views/voip/VideoFeed.tsx index f3ffdd62c5..75206e177f 100644 --- a/src/components/views/voip/VideoFeed.tsx +++ b/src/components/views/voip/VideoFeed.tsx @@ -62,32 +62,40 @@ export default class VideoFeed extends React.Component { componentDidMount() { this.props.feed.addListener(CallFeedEvent.NewStream, this.onNewStream); - - this.playMedia(); + this.playAllMedia(); } - private playMedia() { - const audioOutput = CallMediaHandler.getAudioOutput(); - const currentMedia = this.getCurrentMedia(); + componentWillUnmount() { + this.props.feed.removeListener(CallFeedEvent.NewStream, this.onNewStream); + this.video.current?.removeEventListener('resize', this.onResize); + this.stopAllMedia(); + } - currentMedia.srcObject = this.props.feed.stream; - currentMedia.autoplay = true; - // Don't play audio if the feed is local - currentMedia.muted = this.props.feed.isLocal(); + private playMediaElement(element: HTMLVideoElement | HTMLAudioElement) { + if (element instanceof HTMLAudioElement) { + const audioOutput = CallMediaHandler.getAudioOutput(); - try { - if (audioOutput) { - // This seems quite unreliable in Chrome, although I haven't yet managed to make a jsfiddle where - // it fails. - // It seems reliable if you set the sink ID after setting the srcObject and then set the sink ID - // back to the default after the call is over - Dave - currentMedia.setSinkId(audioOutput); + // Don't play audio if the feed is local + element.muted = this.props.feed.isLocal(); + + if (audioOutput && !element.muted) { + try { + // This seems quite unreliable in Chrome, although I haven't yet managed to make a jsfiddle where + // it fails. + // It seems reliable if you set the sink ID after setting the srcObject and then set the sink ID + // back to the default after the call is over - Dave + element.setSinkId(audioOutput); + } catch (e) { + console.error("Couldn't set requested audio output device: using default", e); + logger.warn("Couldn't set requested audio output device: using default", e); + } } - } catch (e) { - console.error("Couldn't set requested audio output device: using default", e); - logger.warn("Couldn't set requested audio output device: using default", e); + } else { + element.muted = true; } + element.srcObject = this.props.feed.stream; + element.autoplay = true; try { // A note on calling methods on media elements: // We used to have queues per media element to serialise all calls on those elements. @@ -98,27 +106,30 @@ export default class VideoFeed extends React.Component { // should serialise the ones that need to be serialised but then be able to interrupt // them with another load() which will cancel the pending one, but since we don't call // load() explicitly, it shouldn't be a problem. - Dave - currentMedia.play() + element.play() } catch (e) { logger.info("Failed to play media element with feed", this.props.feed, e); } } - componentWillUnmount() { - this.props.feed.removeListener(CallFeedEvent.NewStream, this.onNewStream); - this.video.current?.removeEventListener('resize', this.onResize); + private stopMediaElement(element: HTMLAudioElement | HTMLVideoElement) { + element.pause(); + element.src = null; - const currentMedia = this.getCurrentMedia(); - currentMedia.pause(); - currentMedia.srcObject = null; // As per comment in componentDidMount, setting the sink ID back to the // default once the call is over makes setSinkId work reliably. - Dave // Since we are not using the same element anymore, the above doesn't // seem to be necessary - Šimon } - private getCurrentMedia() { - return this.audio.current || this.video.current; + private playAllMedia() { + this.playMediaElement(this.audio.current); + if (this.video.current) this.playMediaElement(this.video.current); + } + + private stopAllMedia() { + this.stopMediaElement(this.audio.current) + if (this.video.current) this.stopMediaElement(this.video.current); } private onNewStream = () => { @@ -126,7 +137,7 @@ export default class VideoFeed extends React.Component { audioMuted: this.props.feed.isAudioMuted(), videoMuted: this.props.feed.isVideoMuted(), }); - this.playMedia(); + this.playAllMedia(); }; private onResize = (e) => { @@ -141,13 +152,16 @@ export default class VideoFeed extends React.Component { mx_VideoFeed_local: this.props.feed.isLocal(), mx_VideoFeed_remote: !this.props.feed.isLocal(), mx_VideoFeed_voice: this.state.videoMuted, - mx_VideoFeed_video: !this.state.videoMuted, mx_VideoFeed_mirror: ( this.props.feed.isLocal() && SettingsStore.getValue('VideoView.flipVideoHorizontally') ), }; + const audio = ( +
      ); } else { return ( -
  • -
    -
    - -
    -
    - -
    +
    + +
    +
    + +
    -
    - -
    -
    - -
    +
    + +
    +
    + +
    diff --git a/src/components/structures/FilePanel.js b/src/components/structures/FilePanel.js index 32db5c251c..d5e4b092e2 100644 --- a/src/components/structures/FilePanel.js +++ b/src/components/structures/FilePanel.js @@ -200,10 +200,10 @@ class FilePanel extends React.Component { previousPhase={RightPanelPhases.RoomSummary} >
    - { _t("You must register to use this functionality", - {}, - { 'a': (sub) => { sub } }) - } + { _t("You must register to use this functionality", + {}, + { 'a': (sub) => { sub } }) + }
    ; } else if (this.noRoom) { diff --git a/src/components/structures/GroupFilterPanel.js b/src/components/structures/GroupFilterPanel.js index 976b2d81a5..7c050e7433 100644 --- a/src/components/structures/GroupFilterPanel.js +++ b/src/components/structures/GroupFilterPanel.js @@ -153,17 +153,17 @@ class GroupFilterPanel extends React.Component { type="draggable-TagTile" > { (provided, snapshot) => ( -
    - { this.renderGlobalIcon() } - { tags } -
    - {createButton} -
    - { provided.placeholder } +
    + { this.renderGlobalIcon() } + { tags } +
    + {createButton}
    + { provided.placeholder } +
    ) } diff --git a/src/components/structures/GroupView.js b/src/components/structures/GroupView.js index ed6167cbe7..ef74499473 100644 --- a/src/components/structures/GroupView.js +++ b/src/components/structures/GroupView.js @@ -43,7 +43,7 @@ import {mediaFromMxc} from "../../customisations/Media"; import {replaceableComponent} from "../../utils/replaceableComponent"; const LONG_DESC_PLACEHOLDER = _td( -`

    HTML for your community's page

    + `

    HTML for your community's page

    Use the long description to introduce new members to the community, or distribute some important links @@ -111,13 +111,14 @@ class CategoryRoomList extends React.Component { Modal.createTrackedDialog( 'Failed to add the following room to the group summary', '', ErrorDialog, - { + { title: _t( "Failed to add the following rooms to the summary of %(groupId)s:", {groupId: this.props.groupId}, ), description: errorList.join(", "), - }); + }, + ); }); }, }, /*className=*/null, /*isPriority=*/false, /*isStatic=*/true); @@ -145,9 +146,10 @@ class CategoryRoomList extends React.Component { let catHeader =

    ; if (this.props.category && this.props.category.profile) { - catHeader =
    - { this.props.category.profile.name } -
    ; + catHeader =
    + { this.props.category.profile.name } +
    ; } return
    { catHeader } @@ -190,13 +192,14 @@ class FeaturedRoom extends React.Component { Modal.createTrackedDialog( 'Failed to remove room from group summary', '', ErrorDialog, - { + { title: _t( "Failed to remove the room from the summary of %(groupId)s", {groupId: this.props.groupId}, ), description: _t("The room '%(roomName)s' could not be removed from the summary.", {roomName}), - }); + }, + ); }); }; @@ -283,13 +286,13 @@ class RoleUserList extends React.Component { Modal.createTrackedDialog( 'Failed to add the following users to the community summary', '', ErrorDialog, - { + { title: _t( "Failed to add the following users to the summary of %(groupId)s:", {groupId: this.props.groupId}, ), description: errorList.join(", "), - }); + }); }); }, }, /*className=*/null, /*isPriority=*/false, /*isStatic=*/true); @@ -299,11 +302,11 @@ class RoleUserList extends React.Component { const TintableSvg = sdk.getComponent("elements.TintableSvg"); const addButton = this.props.editing ? ( - -
    - { _t('Add a User') } -
    -
    ) :
    ; + +
    + { _t('Add a User') } +
    + ) :
    ; const userNodes = this.props.users.map((u) => { return - { _t("Leave %(groupName)s?", {groupName: this.props.groupId}) } - { warnings } + { _t("Leave %(groupName)s?", {groupName: this.props.groupId}) } + { warnings } ), button: _t("Leave"), @@ -1059,7 +1063,7 @@ export default class GroupView extends React.Component { 'mx_RoomHeader_textButton', 'mx_GroupView_textButton', ], - membershipButtonExtraClasses, + membershipButtonExtraClasses, ); const membershipContainerClasses = classnames( diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index 132d9ab4c3..c93f07fa0f 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -427,8 +427,10 @@ export default class MessagePanel extends React.Component { // we get a new DOM node (restarting the animation) when the ghost // moves to a different event. return ( -
  • +
  • { hr }
  • ); @@ -1014,13 +1016,13 @@ class CreationGrouper { ret.push( - { eventTiles } + { eventTiles } , ); @@ -1222,11 +1224,11 @@ class MemberGrouper { ret.push( - { eventTiles } + { eventTiles } , ); diff --git a/src/components/structures/RoomStatusBar.js b/src/components/structures/RoomStatusBar.js index ab4f524faf..ed8efab3b5 100644 --- a/src/components/structures/RoomStatusBar.js +++ b/src/components/structures/RoomStatusBar.js @@ -196,20 +196,22 @@ export default class RoomStatusBar extends React.Component { } else if (resourceLimitError) { title = messageForResourceLimitError( resourceLimitError.data.limit_type, - resourceLimitError.data.admin_contact, { - 'monthly_active_user': _td( - "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.", - ), - }); + resourceLimitError.data.admin_contact, + { + 'monthly_active_user': _td( + "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.", + ), + }, + ); } else { title = _t('Some of your messages have not been sent'); } @@ -261,7 +263,7 @@ export default class RoomStatusBar extends React.Component {
    /!\ + height="24" title="/!\ " alt="/!\ " />
    {_t('Connectivity to the server has been lost.')} diff --git a/src/components/structures/ScrollPanel.js b/src/components/structures/ScrollPanel.js index 976734680c..93a4c29b81 100644 --- a/src/components/structures/ScrollPanel.js +++ b/src/components/structures/ScrollPanel.js @@ -884,16 +884,19 @@ export default class ScrollPanel extends React.Component { // give the
      an explicit role=list because Safari+VoiceOver seems to think an ordered-list with // list-style-type: none; is no longer a list - return ( - { this.props.fixedChildren } -
      -
        - { this.props.children } -
      -
      -
      - ); + return ( + { this.props.fixedChildren } +
      +
        + { this.props.children } +
      +
      +
      + ); } } diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index 12f5d6e890..bf7794f0b0 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -785,8 +785,10 @@ class TimelinePanel extends React.Component { return; } const lastDisplayedEvent = this.state.events[lastDisplayedIndex]; - this._setReadMarker(lastDisplayedEvent.getId(), - lastDisplayedEvent.getTs()); + this._setReadMarker( + lastDisplayedEvent.getId(), + lastDisplayedEvent.getTs(), + ); // the read-marker should become invisible, so that if the user scrolls // down, they don't see it. @@ -872,7 +874,7 @@ class TimelinePanel extends React.Component { // The messagepanel knows where the RM is, so we must have loaded // the relevant event. this._messagePanel.current.scrollToEvent(this.state.readMarkerEventId, - 0, 1/3); + 0, 1/3); return; } @@ -1044,7 +1046,7 @@ class TimelinePanel extends React.Component { } if (eventId) { this._messagePanel.current.scrollToEvent(eventId, pixelOffset, - offsetBase); + offsetBase); } else { this._messagePanel.current.scrollToBottom(); } @@ -1418,8 +1420,8 @@ class TimelinePanel extends React.Component { ['PREPARED', 'CATCHUP'].includes(this.state.clientSyncState) ); const events = this.state.firstVisibleEventIndex - ? this.state.events.slice(this.state.firstVisibleEventIndex) - : this.state.events; + ? this.state.events.slice(this.state.firstVisibleEventIndex) + : this.state.events; return ( - { errorSection } + { errorSection }
    ); } @@ -375,7 +375,7 @@ export class TermsAuthEntry extends React.Component { if (this.props.showContinue !== false) { // XXX: button classes submitButton = ; + onClick={this._trySubmit} disabled={!allChecked}>{_t("Accept")}; } return ( diff --git a/src/components/views/context_menus/MessageContextMenu.js b/src/components/views/context_menus/MessageContextMenu.js index 142b8c80a8..35efd12c9c 100644 --- a/src/components/views/context_menus/MessageContextMenu.js +++ b/src/components/views/context_menus/MessageContextMenu.js @@ -350,7 +350,7 @@ export default class MessageContextMenu extends React.Component { > { _t('Source URL') } - ); + ); } if (this.props.collapseReplyThread) { diff --git a/src/components/views/dialogs/BugReportDialog.js b/src/components/views/dialogs/BugReportDialog.js index 8948c14c7c..cbe0130649 100644 --- a/src/components/views/dialogs/BugReportDialog.js +++ b/src/components/views/dialogs/BugReportDialog.js @@ -184,7 +184,7 @@ export default class BugReportDialog extends React.Component { return (
    diff --git a/src/components/views/dialogs/ChangelogDialog.js b/src/components/views/dialogs/ChangelogDialog.js index 50bc13cff5..efbeba3977 100644 --- a/src/components/views/dialogs/ChangelogDialog.js +++ b/src/components/views/dialogs/ChangelogDialog.js @@ -95,7 +95,7 @@ export default class ChangelogDialog extends React.Component { description={content} button={_t("Update")} onFinished={this.props.onFinished} - /> + /> ); } } diff --git a/src/components/views/dialogs/ConfirmWipeDeviceDialog.js b/src/components/views/dialogs/ConfirmWipeDeviceDialog.js index 4faaad0f7e..333e1522f1 100644 --- a/src/components/views/dialogs/ConfirmWipeDeviceDialog.js +++ b/src/components/views/dialogs/ConfirmWipeDeviceDialog.js @@ -39,9 +39,12 @@ export default class ConfirmWipeDeviceDialog extends React.Component { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); return ( - +

    {_t( diff --git a/src/components/views/dialogs/DevtoolsDialog.js b/src/components/views/dialogs/DevtoolsDialog.js index 9f5513e0a3..8a035263cc 100644 --- a/src/components/views/dialogs/DevtoolsDialog.js +++ b/src/components/views/dialogs/DevtoolsDialog.js @@ -70,8 +70,16 @@ class GenericEditor extends React.PureComponent { } textInput(id, label) { - return ; + return ; } } @@ -155,7 +163,7 @@ export class SendCustomEvent extends GenericEditor {
    + autoComplete="off" value={this.state.evContent} onChange={this._onChange} element="textarea" />

    @@ -239,7 +247,7 @@ class SendAccountData extends GenericEditor {
    + autoComplete="off" value={this.state.evContent} onChange={this._onChange} element="textarea" />
    @@ -315,15 +323,15 @@ class FilteredList extends React.PureComponent { const TruncatedList = sdk.getComponent("elements.TruncatedList"); return
    + type="text" autoComplete="off" value={this.props.query} onChange={this.onQuery} + className="mx_TextInputDialog_input mx_DevTools_RoomStateExplorer_query" + // force re-render so that autoFocus is applied when this component is re-used + key={this.props.children[0] ? this.props.children[0].key : ''} /> + getChildCount={this.getChildCount} + truncateAt={this.state.truncateAt} + createOverflowElement={this.createOverflowElement} />
    ; } } @@ -647,7 +655,7 @@ function VerificationRequest({txnId, request}) { /* Note that request.timeout is a getter, so its value changes */ const id = setInterval(() => { - setRequestTimeout(request.timeout); + setRequestTimeout(request.timeout); }, 500); return () => { clearInterval(id); }; @@ -941,35 +949,35 @@ class SettingsExplorer extends React.Component { /> - - - - - + + + + + - {allSettings.map(i => ( - - + - - - - ))} + + + + + + ))}
    {_t("Setting ID")}{_t("Value")}{_t("Value in this room")}
    {_t("Setting ID")}{_t("Value")}{_t("Value in this room")}
    - this.onViewClick(e, i)}> - {i} - - this.onEditClick(e, i)} - className='mx_DevTools_SettingsExplorer_edit' - > + {allSettings.map(i => ( +
    + this.onViewClick(e, i)}> + {i} + + this.onEditClick(e, i)} + className='mx_DevTools_SettingsExplorer_edit' + > ✏ - - - {this.renderSettingValue(SettingsStore.getValue(i))} - - - {this.renderSettingValue(SettingsStore.getValue(i, room.roomId))} - -
    + {this.renderSettingValue(SettingsStore.getValue(i))} + + + {this.renderSettingValue(SettingsStore.getValue(i, room.roomId))} + +
    @@ -998,11 +1006,11 @@ class SettingsExplorer extends React.Component {
    - - - - - + + + + + {LEVEL_ORDER.map(lvl => ( diff --git a/src/components/views/dialogs/IntegrationsDisabledDialog.js b/src/components/views/dialogs/IntegrationsDisabledDialog.js index 0e9878f4bc..dd7a51420e 100644 --- a/src/components/views/dialogs/IntegrationsDisabledDialog.js +++ b/src/components/views/dialogs/IntegrationsDisabledDialog.js @@ -42,9 +42,12 @@ export default class IntegrationsDisabledDialog extends React.Component { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); return ( - +

    {_t("Enable 'Manage Integrations' in Settings to do this.")}

    diff --git a/src/components/views/dialogs/IntegrationsImpossibleDialog.js b/src/components/views/dialogs/IntegrationsImpossibleDialog.js index 9bc9d02ba6..e14d40aaef 100644 --- a/src/components/views/dialogs/IntegrationsImpossibleDialog.js +++ b/src/components/views/dialogs/IntegrationsImpossibleDialog.js @@ -37,9 +37,12 @@ export default class IntegrationsImpossibleDialog extends React.Component { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); return ( - +

    {_t( diff --git a/src/components/views/dialogs/KeySignatureUploadFailedDialog.js b/src/components/views/dialogs/KeySignatureUploadFailedDialog.js index 25eb7a90d2..bcb4d4f9b9 100644 --- a/src/components/views/dialogs/KeySignatureUploadFailedDialog.js +++ b/src/components/views/dialogs/KeySignatureUploadFailedDialog.js @@ -24,7 +24,7 @@ export default function KeySignatureUploadFailedDialog({ source, continuation, onFinished, - }) { +}) { const RETRIES = 2; const BaseDialog = sdk.getComponent('dialogs.BaseDialog'); const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); @@ -84,10 +84,10 @@ export default function KeySignatureUploadFailedDialog({ } else { body = (

    {success ? - {_t("Upload completed")} : - cancelled ? - {_t("Cancelled signature upload")} : - {_t("Unable to upload")}} + {_t("Upload completed")} : + cancelled ? + {_t("Cancelled signature upload")} : + {_t("Unable to upload")}} + {content} ); diff --git a/src/components/views/dialogs/RoomSettingsDialog.js b/src/components/views/dialogs/RoomSettingsDialog.js index 9c2f23ef22..c052b5c5bb 100644 --- a/src/components/views/dialogs/RoomSettingsDialog.js +++ b/src/components/views/dialogs/RoomSettingsDialog.js @@ -117,7 +117,7 @@ export default class RoomSettingsDialog extends React.Component { const roomName = MatrixClientPeg.get().getRoom(this.props.roomId).name; return ( + onFinished={this.props.onFinished} title={_t("Room Settings - %(roomName)s", {roomName})}>
    diff --git a/src/components/views/dialogs/SessionRestoreErrorDialog.js b/src/components/views/dialogs/SessionRestoreErrorDialog.js index 50d7fbea09..43e73a2f83 100644 --- a/src/components/views/dialogs/SessionRestoreErrorDialog.js +++ b/src/components/views/dialogs/SessionRestoreErrorDialog.js @@ -98,7 +98,7 @@ export default class SessionRestoreErrorDialog extends React.Component { "may be incompatible with this version. Close this window and return " + "to the more recent version.", { brand }, - ) }

    + ) }

    { _t( "Clearing your browser's storage may fix the problem, but will sign you " + diff --git a/src/components/views/dialogs/StorageEvictedDialog.js b/src/components/views/dialogs/StorageEvictedDialog.js index 15c5347644..629990032f 100644 --- a/src/components/views/dialogs/StorageEvictedDialog.js +++ b/src/components/views/dialogs/StorageEvictedDialog.js @@ -46,9 +46,10 @@ export default class StorageEvictedDialog extends React.Component { if (SdkConfig.get().bug_report_endpoint_url) { logRequest = _t( "To help us prevent this in future, please send us logs.", {}, - { + { a: text => {text}, - }); + }, + ); } return ( diff --git a/src/components/views/dialogs/UserSettingsDialog.js b/src/components/views/dialogs/UserSettingsDialog.js index eb9eaeb5dd..8d99ffb5cd 100644 --- a/src/components/views/dialogs/UserSettingsDialog.js +++ b/src/components/views/dialogs/UserSettingsDialog.js @@ -156,7 +156,7 @@ export default class UserSettingsDialog extends React.Component { return ( + onFinished={this.props.onFinished} title={_t("Settings")}>

    diff --git a/src/components/views/dialogs/VerificationRequestDialog.js b/src/components/views/dialogs/VerificationRequestDialog.js index 205597a1c4..9281275e6a 100644 --- a/src/components/views/dialogs/VerificationRequestDialog.js +++ b/src/components/views/dialogs/VerificationRequestDialog.js @@ -52,11 +52,13 @@ export default class VerificationRequestDialog extends React.Component { const title = request && request.isSelfVerification ? _t("Verify other login") : _t("Verification Request"); - return + return + onFinished={this.props.onFinished} + title={_t("Allow this widget to verify your identity")}>

    {_t("The widget will verify your user ID, but won't be able to perform actions for you:")} diff --git a/src/components/views/dialogs/security/ConfirmDestroyCrossSigningDialog.js b/src/components/views/dialogs/security/ConfirmDestroyCrossSigningDialog.js index 43fb25f152..dabd7950b4 100644 --- a/src/components/views/dialogs/security/ConfirmDestroyCrossSigningDialog.js +++ b/src/components/views/dialogs/security/ConfirmDestroyCrossSigningDialog.js @@ -40,10 +40,10 @@ export default class ConfirmDestroyCrossSigningDialog extends React.Component { return ( + className='mx_ConfirmDestroyCrossSigningDialog' + hasCancel={true} + onFinished={this.props.onFinished} + title={_t("Destroy cross-signing keys?")}>

    {_t( diff --git a/src/components/views/dialogs/security/RestoreKeyBackupDialog.js b/src/components/views/dialogs/security/RestoreKeyBackupDialog.js index 1fafe03d95..faabbacb81 100644 --- a/src/components/views/dialogs/security/RestoreKeyBackupDialog.js +++ b/src/components/views/dialogs/security/RestoreKeyBackupDialog.js @@ -374,7 +374,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { "If you've forgotten your Security Phrase you can "+ "use your Security Key or " + "set up new recovery options" - , {}, { + , {}, { button1: s => {s} , - })} + })}

    ; } else { title = _t("Enter Security Key"); @@ -436,14 +436,14 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { {_t( "If you've forgotten your Security Key you can "+ "" - , {}, { + , {}, { button: s => {s} , - })} + })}
    ; } @@ -452,9 +452,9 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { onFinished={this.props.onFinished} title={title} > -
    - {content} -
    +
    + {content} +
    ); } diff --git a/src/components/views/elements/ActionButton.js b/src/components/views/elements/ActionButton.js index 1714891cb5..9903c631b2 100644 --- a/src/components/views/elements/ActionButton.js +++ b/src/components/views/elements/ActionButton.js @@ -70,8 +70,8 @@ export default class ActionButton extends React.Component { } const icon = this.props.iconPath ? - () : - undefined; + () : + undefined; const classNames = ["mx_RoleButton"]; if (this.props.className) { diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index e206fda797..b898ad2ebc 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -109,7 +109,7 @@ export default class AppTile extends React.Component { const childContentProtocol = u.protocol; if (parentContentProtocol === 'https:' && childContentProtocol !== 'https:') { console.warn("Refusing to load mixed-content app:", - parentContentProtocol, childContentProtocol, window.location, this.props.app.url); + parentContentProtocol, childContentProtocol, window.location, this.props.app.url); return true; } return false; diff --git a/src/components/views/elements/EditableItemList.js b/src/components/views/elements/EditableItemList.js index ff62f169fa..e3fe54333a 100644 --- a/src/components/views/elements/EditableItemList.js +++ b/src/components/views/elements/EditableItemList.js @@ -65,12 +65,18 @@ export class EditableItem extends React.Component { {_t("Are you sure?")} - + {_t("Yes")} - + {_t("No")}
    @@ -122,10 +128,10 @@ export default class EditableItemList extends React.Component { _renderNewItemField() { return (
    + noValidate={true} className="mx_EditableItemList_newItem"> + autoComplete="off" value={this.props.newItem || ""} onChange={this._onNewItemChanged} + list={this.props.suggestionsListId} /> {_t("Add")} diff --git a/src/components/views/elements/EditableText.js b/src/components/views/elements/EditableText.js index 638fd02553..7c38ac1777 100644 --- a/src/components/views/elements/EditableText.js +++ b/src/components/views/elements/EditableText.js @@ -221,13 +221,15 @@ export default class EditableText extends React.Component {
    ; } else { // show the content editable div, but manually manage its contents as react and contentEditable don't play nice together - editableEl =
    ; + editableEl =
    ; } return editableEl; diff --git a/src/components/views/elements/LabelledToggleSwitch.js b/src/components/views/elements/LabelledToggleSwitch.js index e6378f0e6a..ef60eeed7b 100644 --- a/src/components/views/elements/LabelledToggleSwitch.js +++ b/src/components/views/elements/LabelledToggleSwitch.js @@ -46,8 +46,12 @@ export default class LabelledToggleSwitch extends React.Component { // This is a minimal version of a SettingsFlag let firstPart = {this.props.label}; - let secondPart = ; + let secondPart = ; if (this.props.toggleInFront) { const temp = firstPart; diff --git a/src/components/views/elements/LanguageDropdown.js b/src/components/views/elements/LanguageDropdown.js index 2e961be700..b8734c5afb 100644 --- a/src/components/views/elements/LanguageDropdown.js +++ b/src/components/views/elements/LanguageDropdown.js @@ -60,10 +60,10 @@ export default class LanguageDropdown extends React.Component { // doesn't know this, therefore we do this. const language = SettingsStore.getValue("language", null, /*excludeDefault:*/true); if (language) { - this.props.onOptionChange(language); + this.props.onOptionChange(language); } else { - const language = languageHandler.normalizeLanguageKey(languageHandler.getLanguageFromBrowser()); - this.props.onOptionChange(language); + const language = languageHandler.normalizeLanguageKey(languageHandler.getLanguageFromBrowser()); + this.props.onOptionChange(language); } } } diff --git a/src/components/views/elements/Pill.js b/src/components/views/elements/Pill.js index a8e16813e6..ace41db39d 100644 --- a/src/components/views/elements/Pill.js +++ b/src/components/views/elements/Pill.js @@ -225,19 +225,19 @@ class Pill extends React.Component { } break; case Pill.TYPE_USER_MENTION: { - // If this user is not a member of this room, default to the empty member - const member = this.state.member; - if (member) { - userId = member.userId; - member.rawDisplayName = member.rawDisplayName || ''; - linkText = member.rawDisplayName; - if (this.props.shouldShowPillAvatar) { - avatar =
    -
    {_t("Level")}{_t("Settable at global")}{_t("Settable at room")}
    {_t("Level")}{_t("Settable at global")}{_t("Settable at room")}
    {_t("Homeserver feature support:")} {homeserverSupportsCrossSigning ? _t("exists") : _t("not found")}
    + {errorSection} {actionRow} diff --git a/src/components/views/settings/DevicesPanel.js b/src/components/views/settings/DevicesPanel.js index e7d300b0f8..b1ad605a37 100644 --- a/src/components/views/settings/DevicesPanel.js +++ b/src/components/views/settings/DevicesPanel.js @@ -214,7 +214,7 @@ export default class DevicesPanel extends React.Component { const deleteButton = this.state.deleting ? : - { _t("Delete %(count)s sessions", {count: this.state.selectedDevices.length}) } + { _t("Delete %(count)s sessions", {count: this.state.selectedDevices.length})} ; const classes = classNames(this.props.className, "mx_DevicesPanel"); diff --git a/src/components/views/settings/Notifications.js b/src/components/views/settings/Notifications.js index 25fe434994..5756536085 100644 --- a/src/components/views/settings/Notifications.js +++ b/src/components/views/settings/Notifications.js @@ -100,7 +100,7 @@ export default class Notifications extends React.Component { MatrixClientPeg.get().setPushRuleEnabled( 'global', self.state.masterPushRule.kind, self.state.masterPushRule.rule_id, !checked, ).then(function() { - self._refreshFromServer(); + self._refreshFromServer(); }); }; @@ -580,12 +580,12 @@ export default class Notifications extends React.Component { "vectorRuleId": "_keywords", "description": ( - { _t('Messages containing keywords', - {}, - { 'span': (sub) => - {sub}, - }, - )} + { _t('Messages containing keywords', + {}, + { 'span': (sub) => + {sub}, + }, + )} ), "vectorState": self.state.vectorContentRules.vectorState, @@ -743,8 +743,8 @@ export default class Notifications extends React.Component { emailNotificationsRow(address, label) { return ; + onChange={this.onEnableEmailNotificationsChange.bind(this, address)} + label={label} key={`emailNotif_${label}`} />; } render() { @@ -757,8 +757,8 @@ export default class Notifications extends React.Component { let masterPushRuleDiv; if (this.state.masterPushRule) { masterPushRuleDiv = ; + onChange={this.onEnableNotificationsChange} + label={_t('Enable notifications for this account')} />; } let clearNotificationsButton; @@ -874,16 +874,16 @@ export default class Notifications extends React.Component { { spinner } + onChange={this.onEnableDesktopNotificationsChange} + label={_t('Enable desktop notifications for this session')} /> + onChange={this.onEnableDesktopNotificationBodyChange} + label={_t('Show message in desktop notification')} /> + onChange={this.onEnableAudioNotificationsChange} + label={_t('Enable audible notifications for this session')} /> { emailNotificationsRows } diff --git a/src/components/views/settings/ProfileSettings.js b/src/components/views/settings/ProfileSettings.js index 971b868751..9ecf369eba 100644 --- a/src/components/views/settings/ProfileSettings.js +++ b/src/components/views/settings/ProfileSettings.js @@ -170,8 +170,12 @@ export default class ProfileSettings extends React.Component { noValidate={true} className="mx_ProfileSettings_profileForm" > - +
    {_t("Profile")} diff --git a/src/components/views/settings/account/EmailAddresses.js b/src/components/views/settings/account/EmailAddresses.js index 1ebd374173..a36369cf88 100644 --- a/src/components/views/settings/account/EmailAddresses.js +++ b/src/components/views/settings/account/EmailAddresses.js @@ -90,12 +90,18 @@ export class ExistingEmailAddress extends React.Component { {_t("Remove %(email)s?", {email: this.props.email.address} )} - + {_t("Remove")} - + {_t("Cancel")}
    @@ -228,21 +234,28 @@ export default class EmailAddresses extends React.Component { ); if (this.state.verifying) { addButton = ( -
    -
    {_t("We've sent you an email to verify your address. Please follow the instructions there and then click the button below.")}
    - - {_t("Continue")} - -
    +
    +
    {_t("We've sent you an email to verify your address. Please follow the instructions there and then click the button below.")}
    + + {_t("Continue")} + +
    ); } return (
    {existingEmailElements} - + {_t("Remove %(phone)s?", {phone: this.props.msisdn.address})} - + {_t("Remove")} - + {_t("Cancel")}
    @@ -246,8 +252,11 @@ export default class PhoneNumbers extends React.Component { value={this.state.newPhoneNumberCode} onChange={this._onChangeNewPhoneNumberCode} /> - + {_t("Continue")} diff --git a/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.js b/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.js index cd4a043622..139cfd5fbd 100644 --- a/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.js +++ b/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.js @@ -80,9 +80,11 @@ export default class GeneralRoomSettingsTab extends React.Component { flairSection = <> {_t("Flair")}
    - +
    ; } @@ -97,8 +99,8 @@ export default class GeneralRoomSettingsTab extends React.Component {
    {_t("Room Addresses")}
    + canSetCanonicalAlias={canSetCanonical} canSetAliases={canSetAliases} + canonicalAliasEvent={canonicalAliasEv} aliasEvents={aliasEvents} />
    {_t("Other")}
    { flairSection } diff --git a/src/components/views/settings/tabs/room/NotificationSettingsTab.js b/src/components/views/settings/tabs/room/NotificationSettingsTab.js index baefb5ae20..fa56fa2cb6 100644 --- a/src/components/views/settings/tabs/room/NotificationSettingsTab.js +++ b/src/components/views/settings/tabs/room/NotificationSettingsTab.js @@ -155,7 +155,7 @@ export default class NotificationsSettingsTab extends React.Component {
    {_t("Notification sound")}: {this.state.currentSound}
    - {_t("Reset")} + {_t("Reset")}
    @@ -167,11 +167,11 @@ export default class NotificationsSettingsTab extends React.Component { {currentUploadedFile} - {_t("Browse")} + {_t("Browse")} - {_t("Save")} + {_t("Save")}
    diff --git a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js index b1ad9f3d23..fe2c9ad0fa 100644 --- a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js @@ -319,8 +319,11 @@ export default class GeneralUserSettingsTab extends React.Component { return (
    {_t("Language and region")} - +
    ); } @@ -329,8 +332,10 @@ export default class GeneralUserSettingsTab extends React.Component { return (
    {_t("Spell check dictionaries")} - +
    ); } diff --git a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js index 8a70811399..9e1e9b03a9 100644 --- a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js @@ -257,13 +257,12 @@ export default class SecurityUserSettingsTab extends React.Component { if (!ignoredUserIds || ignoredUserIds.length === 0) return null; - const userIds = ignoredUserIds - .map((u) => ); + const userIds = ignoredUserIds.map((u) => ); return (
    diff --git a/src/components/views/settings/tabs/user/VoiceUserSettingsTab.js b/src/components/views/settings/tabs/user/VoiceUserSettingsTab.js index d8adab55f6..362059f8ed 100644 --- a/src/components/views/settings/tabs/user/VoiceUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/VoiceUserSettingsTab.js @@ -176,8 +176,8 @@ export default class VoiceUserSettingsTab extends React.Component { const defaultDevice = getDefaultDevice(audioOutputs); speakerDropdown = ( + value={this.state.activeAudioOutput || defaultDevice} + onChange={this._setAudioOutput}> {this._renderDeviceOptions(audioOutputs, 'audioOutput')} ); @@ -188,8 +188,8 @@ export default class VoiceUserSettingsTab extends React.Component { const defaultDevice = getDefaultDevice(audioInputs); microphoneDropdown = ( + value={this.state.activeAudioInput || defaultDevice} + onChange={this._setAudioInput}> {this._renderDeviceOptions(audioInputs, 'audioInput')} ); @@ -200,8 +200,8 @@ export default class VoiceUserSettingsTab extends React.Component { const defaultDevice = getDefaultDevice(videoInputs); webcamDropdown = ( + value={this.state.activeVideoInput || defaultDevice} + onChange={this._setVideoInput}> {this._renderDeviceOptions(videoInputs, 'videoInput')} ); diff --git a/src/components/views/verification/VerificationCancelled.js b/src/components/views/verification/VerificationCancelled.js index 0bbaea1804..c57094d9b5 100644 --- a/src/components/views/verification/VerificationCancelled.js +++ b/src/components/views/verification/VerificationCancelled.js @@ -29,14 +29,14 @@ export default class VerificationCancelled extends React.Component { render() { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); return
    -

    {_t( - "The other party cancelled the verification.", - )}

    - +

    {_t( + "The other party cancelled the verification.", + )}

    +
    ; } } diff --git a/src/indexing/EventIndex.js b/src/indexing/EventIndex.js index 2dcdb9e3a3..2584ee9172 100644 --- a/src/indexing/EventIndex.js +++ b/src/indexing/EventIndex.js @@ -127,8 +127,13 @@ export default class EventIndex extends EventEmitter { this.crawlerCheckpoints.push(forwardCheckpoint); } } catch (e) { - console.log("EventIndex: Error adding initial checkpoints for room", - room.roomId, backCheckpoint, forwardCheckpoint, e); + console.log( + "EventIndex: Error adding initial checkpoints for room", + room.roomId, + backCheckpoint, + forwardCheckpoint, + e, + ); } })); } @@ -379,8 +384,12 @@ export default class EventIndex extends EventEmitter { try { await indexManager.addCrawlerCheckpoint(checkpoint); } catch (e) { - console.log("EventIndex: Error adding new checkpoint for room", - room.roomId, checkpoint, e); + console.log( + "EventIndex: Error adding new checkpoint for room", + room.roomId, + checkpoint, + e, + ); } this.crawlerCheckpoints.push(checkpoint); @@ -459,7 +468,7 @@ export default class EventIndex extends EventEmitter { } catch (e) { if (e.httpStatus === 403) { console.log("EventIndex: Removing checkpoint as we don't have ", - "permissions to fetch messages from this room.", checkpoint); + "permissions to fetch messages from this room.", checkpoint); try { await indexManager.removeCrawlerCheckpoint(checkpoint); } catch (e) { @@ -589,7 +598,7 @@ export default class EventIndex extends EventEmitter { // to do here anymore. if (!newCheckpoint) { console.log("EventIndex: The server didn't return a valid ", - "new checkpoint, not continuing the crawl.", checkpoint); + "new checkpoint, not continuing the crawl.", checkpoint); continue; } @@ -599,12 +608,12 @@ export default class EventIndex extends EventEmitter { // the new checkpoint to be used by the crawler. if (eventsAlreadyAdded === true && newCheckpoint.fullCrawl !== true) { console.log("EventIndex: Checkpoint had already all events", - "added, stopping the crawl", checkpoint); + "added, stopping the crawl", checkpoint); await indexManager.removeCrawlerCheckpoint(newCheckpoint); } else { if (eventsAlreadyAdded === true) { console.log("EventIndex: Checkpoint had already all events", - "added, but continuing due to a full crawl", checkpoint); + "added, but continuing due to a full crawl", checkpoint); } this.crawlerCheckpoints.push(newCheckpoint); } @@ -777,7 +786,7 @@ export default class EventIndex extends EventEmitter { * timeline, false otherwise. */ async populateFileTimeline(timelineSet, timeline, room, limit = 10, - fromEvent = null, direction = EventTimeline.BACKWARDS) { + fromEvent = null, direction = EventTimeline.BACKWARDS) { const matrixEvents = await this.loadFileEvents(room, limit, fromEvent, direction); // If this is a normal fill request, not a pagination request, we need @@ -807,7 +816,7 @@ export default class EventIndex extends EventEmitter { } console.log("EventIndex: Populating file panel with", matrixEvents.length, - "events and setting the pagination token to", paginationToken); + "events and setting the pagination token to", paginationToken); timeline.setPaginationToken(paginationToken, EventTimeline.BACKWARDS); return ret; diff --git a/src/stores/CustomRoomTagStore.js b/src/stores/CustomRoomTagStore.js index edfc0003cf..060f1f3749 100644 --- a/src/stores/CustomRoomTagStore.js +++ b/src/stores/CustomRoomTagStore.js @@ -125,14 +125,14 @@ class CustomRoomTagStore extends EventEmitter { this._setState({tags}); } } - break; + break; case 'on_client_not_viable': case 'on_logged_out': { // we assume to always have a tags object in the state this._state = {tags: {}}; RoomListStore.instance.off(LISTS_UPDATE_EVENT, this._onListsUpdated); } - break; + break; } } diff --git a/src/stores/GroupFilterOrderStore.js b/src/stores/GroupFilterOrderStore.js index 492322146e..b18abaa001 100644 --- a/src/stores/GroupFilterOrderStore.js +++ b/src/stores/GroupFilterOrderStore.js @@ -168,7 +168,7 @@ class GroupFilterOrderStore extends Store { Analytics.trackEvent('FilterStore', 'select_tag'); } - break; + break; case 'deselect_tags': if (payload.tag) { // if a tag is passed, only deselect that tag @@ -181,7 +181,7 @@ class GroupFilterOrderStore extends Store { }); } Analytics.trackEvent('FilterStore', 'deselect_tags'); - break; + break; case 'on_client_not_viable': case 'on_logged_out': { // Reset state without pushing an update to the view, which generally assumes that @@ -207,8 +207,8 @@ class GroupFilterOrderStore extends Store { groupIds.forEach(groupId => { const rooms = GroupStore.getGroupRooms(groupId) - .map(r => client.getRoom(r.roomId)) // to Room objects - .filter(r => r !== null && r !== undefined); // filter out rooms we haven't joined from the group + .map(r => client.getRoom(r.roomId)) // to Room objects + .filter(r => r !== null && r !== undefined); // filter out rooms we haven't joined from the group const badge = rooms && RoomNotifs.aggregateNotificationCount(rooms); changedBadges[groupId] = (badge && badge.count !== 0) ? badge : undefined; }); diff --git a/src/utils/MegolmExportEncryption.js b/src/utils/MegolmExportEncryption.js index be7472901a..20f3cd6cb6 100644 --- a/src/utils/MegolmExportEncryption.js +++ b/src/utils/MegolmExportEncryption.js @@ -311,7 +311,7 @@ function unpackMegolmKeyFile(data) { while (1) { const lineEnd = fileStr.indexOf('\n', lineStart); const line = fileStr.slice(lineStart, lineEnd < 0 ? undefined : lineEnd) - .trim(); + .trim(); if (line === TRAILER_LINE) { break; } diff --git a/test/autocomplete/QueryMatcher-test.js b/test/autocomplete/QueryMatcher-test.js index 3d383f08d7..cae71841d4 100644 --- a/test/autocomplete/QueryMatcher-test.js +++ b/test/autocomplete/QueryMatcher-test.js @@ -177,7 +177,7 @@ describe('QueryMatcher', function() { const qm = new QueryMatcher(NONWORDOBJECTS, { keys: ["name"], shouldMatchWordsOnly: false, - }); + }); const results = qm.match('bob'); expect(results.length).toBe(1); diff --git a/test/components/views/dialogs/AccessSecretStorageDialog-test.js b/test/components/views/dialogs/AccessSecretStorageDialog-test.js index 13b39ab0d0..d9e07a2d74 100644 --- a/test/components/views/dialogs/AccessSecretStorageDialog-test.js +++ b/test/components/views/dialogs/AccessSecretStorageDialog-test.js @@ -26,9 +26,9 @@ describe("AccessSecretStorageDialog", function() { it("Closes the dialog if _onRecoveryKeyNext is called with a valid key", (done) => { const testInstance = TestRenderer.create( p && p.recoveryKey && p.recoveryKey == "a"} - onFinished={(v) => { - if (v) { done(); } + checkPrivateKey={(p) => p && p.recoveryKey && p.recoveryKey == "a"} + onFinished={(v) => { + if (v) { done(); } }} />, ); @@ -43,7 +43,7 @@ describe("AccessSecretStorageDialog", function() { it("Considers a valid key to be valid", async function() { const testInstance = TestRenderer.create( true} + checkPrivateKey={() => true} />, ); const v = "asdf"; @@ -61,7 +61,7 @@ describe("AccessSecretStorageDialog", function() { it("Notifies the user if they input an invalid Security Key", async function(done) { const testInstance = TestRenderer.create( false} + checkPrivateKey={async () => false} />, ); const e = { target: { value: "a" } }; @@ -87,12 +87,14 @@ describe("AccessSecretStorageDialog", function() { it("Notifies the user if they input an invalid passphrase", async function(done) { const testInstance = TestRenderer.create( false} - onFinished={() => {}} - keyInfo={ { passphrase: { - salt: 'nonempty', - iterations: 2, - } } } + checkPrivateKey={() => false} + onFinished={() => {}} + keyInfo={{ + passphrase: { + salt: 'nonempty', + iterations: 2, + }, + }} />, ); const e = { target: { value: "a" } }; diff --git a/test/components/views/elements/MemberEventListSummary-test.js b/test/components/views/elements/MemberEventListSummary-test.js index dd6febc7d7..9386d8cf4a 100644 --- a/test/components/views/elements/MemberEventListSummary-test.js +++ b/test/components/views/elements/MemberEventListSummary-test.js @@ -246,8 +246,8 @@ describe('MemberEventListSummary', function() { }); it('truncates multiple sequences of repetitions with other events between', - function() { - const events = generateEvents([ + function() { + const events = generateEvents([ { userId: "@user_1:some.domain", prevMembership: "ban", @@ -276,28 +276,29 @@ describe('MemberEventListSummary', function() { membership: "invite", senderId: "@some_other_user:some.domain", }, - ]); - const props = { + ]); + const props = { events: events, children: generateTiles(events), summaryLength: 1, avatarsMaxLength: 5, threshold: 3, - }; + }; - const instance = ReactTestUtils.renderIntoDocument( - , - ); - const summary = ReactTestUtils.findRenderedDOMComponentWithClass( - instance, "mx_EventListSummary_summary", - ); - const summaryText = summary.textContent; + const instance = ReactTestUtils.renderIntoDocument( + , + ); + const summary = ReactTestUtils.findRenderedDOMComponentWithClass( + instance, "mx_EventListSummary_summary", + ); + const summaryText = summary.textContent; - expect(summaryText).toBe( - "user_1 was unbanned, joined and left 2 times, was banned, " + + expect(summaryText).toBe( + "user_1 was unbanned, joined and left 2 times, was banned, " + "joined and left 3 times and was invited", - ); - }); + ); + }, + ); it('handles multiple users following the same sequence of memberships', function() { const events = generateEvents([ @@ -396,8 +397,8 @@ describe('MemberEventListSummary', function() { }); it('correctly orders sequences of transitions by the order of their first event', - function() { - const events = generateEvents([ + function() { + const events = generateEvents([ { userId: "@user_2:some.domain", prevMembership: "ban", @@ -424,28 +425,29 @@ describe('MemberEventListSummary', function() { {userId: "@user_2:some.domain", prevMembership: "join", membership: "leave"}, {userId: "@user_2:some.domain", prevMembership: "leave", membership: "join"}, {userId: "@user_2:some.domain", prevMembership: "join", membership: "leave"}, - ]); - const props = { + ]); + const props = { events: events, children: generateTiles(events), summaryLength: 1, avatarsMaxLength: 5, threshold: 3, - }; + }; - const instance = ReactTestUtils.renderIntoDocument( - , - ); - const summary = ReactTestUtils.findRenderedDOMComponentWithClass( - instance, "mx_EventListSummary_summary", - ); - const summaryText = summary.textContent; + const instance = ReactTestUtils.renderIntoDocument( + , + ); + const summary = ReactTestUtils.findRenderedDOMComponentWithClass( + instance, "mx_EventListSummary_summary", + ); + const summaryText = summary.textContent; - expect(summaryText).toBe( - "user_2 was unbanned and joined and left 2 times, user_1 was unbanned, " + + expect(summaryText).toBe( + "user_2 was unbanned and joined and left 2 times, user_1 was unbanned, " + "joined and left 2 times and was banned", - ); - }); + ); + }, + ); it('correctly identifies transitions', function() { const events = generateEvents([ @@ -569,8 +571,8 @@ describe('MemberEventListSummary', function() { }); it('handles invitation plurals correctly when there are multiple invites', - function() { - const events = generateEvents([ + function() { + const events = generateEvents([ { userId: "@user_1:some.domain", prevMembership: "invite", @@ -581,27 +583,28 @@ describe('MemberEventListSummary', function() { prevMembership: "invite", membership: "leave", }, - ]); - const props = { + ]); + const props = { events: events, children: generateTiles(events), summaryLength: 1, avatarsMaxLength: 5, threshold: 1, // threshold = 1 to force collapse - }; + }; - const instance = ReactTestUtils.renderIntoDocument( - , - ); - const summary = ReactTestUtils.findRenderedDOMComponentWithClass( - instance, "mx_EventListSummary_summary", - ); - const summaryText = summary.textContent; + const instance = ReactTestUtils.renderIntoDocument( + , + ); + const summary = ReactTestUtils.findRenderedDOMComponentWithClass( + instance, "mx_EventListSummary_summary", + ); + const summaryText = summary.textContent; - expect(summaryText).toBe( - "user_1 rejected their invitation 2 times", - ); - }); + expect(summaryText).toBe( + "user_1 rejected their invitation 2 times", + ); + }, + ); it('handles a summary length = 2, with no "others"', function() { const events = generateEvents([ diff --git a/test/components/views/rooms/MemberList-test.js b/test/components/views/rooms/MemberList-test.js index 068d358dcd..093e5588d0 100644 --- a/test/components/views/rooms/MemberList-test.js +++ b/test/components/views/rooms/MemberList-test.js @@ -100,7 +100,7 @@ describe('MemberList', () => { memberList = r; }; root = ReactDOM.render(, parentDiv); + wrappedRef={gatherWrappedRef} />, parentDiv); }); afterEach((done) => { diff --git a/test/components/views/rooms/RoomList-test.js b/test/components/views/rooms/RoomList-test.js index d3211f564c..bfb8e1afd4 100644 --- a/test/components/views/rooms/RoomList-test.js +++ b/test/components/views/rooms/RoomList-test.js @@ -70,8 +70,9 @@ describe('RoomList', () => { root = ReactDOM.render( {}} /> - - , parentDiv); + , + parentDiv, + ); ReactTestUtils.findRenderedComponentWithType(root, RoomList); movingRoom = createRoom({name: 'Moving room'}); diff --git a/test/end-to-end-tests/src/session.js b/test/end-to-end-tests/src/session.js index 433baa5e48..4c611ef877 100644 --- a/test/end-to-end-tests/src/session.js +++ b/test/end-to-end-tests/src/session.js @@ -93,10 +93,10 @@ module.exports = class ElementSession { const type = req.resourceType(); const response = await req.response(); //if (type === 'xhr' || type === 'fetch') { - buffer += `${type} ${response.status()} ${req.method()} ${req.url()} \n`; - // if (req.method() === "POST") { - // buffer += " Post data: " + req.postData(); - // } + buffer += `${type} ${response.status()} ${req.method()} ${req.url()} \n`; + // if (req.method() === "POST") { + // buffer += " Post data: " + req.postData(); + // } //} }); return { diff --git a/test/utils/MegolmExportEncryption-test.js b/test/utils/MegolmExportEncryption-test.js index e0ed5ba26a..07ec03860b 100644 --- a/test/utils/MegolmExportEncryption-test.js +++ b/test/utils/MegolmExportEncryption-test.js @@ -84,22 +84,22 @@ describe('MegolmExportEncryption', function() { it('should handle missing header', function() { const input=stringToArray(`-----`); return MegolmExportEncryption.decryptMegolmKeyFile(input, '') - .then((res) => { - throw new Error('expected to throw'); - }, (error) => { - expect(error.message).toEqual('Header line not found'); - }); + .then((res) => { + throw new Error('expected to throw'); + }, (error) => { + expect(error.message).toEqual('Header line not found'); + }); }); it('should handle missing trailer', function() { const input=stringToArray(`-----BEGIN MEGOLM SESSION DATA----- -----`); return MegolmExportEncryption.decryptMegolmKeyFile(input, '') - .then((res) => { - throw new Error('expected to throw'); - }, (error) => { - expect(error.message).toEqual('Trailer line not found'); - }); + .then((res) => { + throw new Error('expected to throw'); + }, (error) => { + expect(error.message).toEqual('Trailer line not found'); + }); }); it('should handle a too-short body', function() { @@ -109,11 +109,11 @@ cissyYBxjsfsAn -----END MEGOLM SESSION DATA----- `); return MegolmExportEncryption.decryptMegolmKeyFile(input, '') - .then((res) => { - throw new Error('expected to throw'); - }, (error) => { - expect(error.message).toEqual('Invalid file: too short'); - }); + .then((res) => { + throw new Error('expected to throw'); + }, (error) => { + expect(error.message).toEqual('Invalid file: too short'); + }); }); // TODO find a subtlecrypto shim which doesn't break this test diff --git a/test/utils/ShieldUtils-test.js b/test/utils/ShieldUtils-test.js index bea3d26565..fdf4f527ee 100644 --- a/test/utils/ShieldUtils-test.js +++ b/test/utils/ShieldUtils-test.js @@ -26,7 +26,7 @@ describe("mkClient self-test", function() { ["@TF:h", true], ["@FT:h", false], ["@FF:h", false]], - )("behaves well for user trust %s", (userId, trust) => { + )("behaves well for user trust %s", (userId, trust) => { expect(mkClient().checkUserTrust(userId).isCrossSigningVerified()).toBe(trust); }); @@ -35,7 +35,7 @@ describe("mkClient self-test", function() { ["@TF:h", false], ["@FT:h", true], ["@FF:h", false]], - )("behaves well for device trust %s", (userId, trust) => { + )("behaves well for device trust %s", (userId, trust) => { expect(mkClient().checkDeviceTrust(userId, "device").isVerified()).toBe(trust); }); }); From c5f653245a2a2a55b9512ebb95671653f9746bb0 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 27 Apr 2021 16:29:42 +0100 Subject: [PATCH 0090/1449] Show Spaces beta card in Labs & My Communities view the image is temporary --- res/css/_components.scss | 2 + res/css/structures/_MyGroups.scss | 6 ++ res/css/views/beta/_BetaCard.scss | 70 ++++++++++++++++++ .../tabs/user/_LabsUserSettingsTab.scss | 25 +++++++ res/img/betas/spaces.png | Bin 0 -> 136319 bytes src/components/structures/MyGroups.js | 2 + src/components/views/beta/BetaCard.tsx | 60 +++++++++++++++ .../views/dialogs/UserSettingsDialog.js | 5 +- .../settings/tabs/user/LabsUserSettingsTab.js | 45 ++++++++--- src/i18n/strings/en_EN.json | 11 ++- src/settings/Settings.ts | 24 +++++- src/settings/SettingsStore.ts | 4 + 12 files changed, 236 insertions(+), 18 deletions(-) create mode 100644 res/css/views/beta/_BetaCard.scss create mode 100644 res/css/views/settings/tabs/user/_LabsUserSettingsTab.scss create mode 100644 res/img/betas/spaces.png create mode 100644 src/components/views/beta/BetaCard.tsx diff --git a/res/css/_components.scss b/res/css/_components.scss index 253f97bf42..da18936b47 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -54,6 +54,7 @@ @import "./views/avatars/_MemberStatusMessageAvatar.scss"; @import "./views/avatars/_PulsedAvatar.scss"; @import "./views/avatars/_WidgetAvatar.scss"; +@import "./views/beta/_BetaCard.scss"; @import "./views/context_menus/_CallContextMenu.scss"; @import "./views/context_menus/_IconizedContextMenu.scss"; @import "./views/context_menus/_MessageContextMenu.scss"; @@ -236,6 +237,7 @@ @import "./views/settings/tabs/user/_AppearanceUserSettingsTab.scss"; @import "./views/settings/tabs/user/_GeneralUserSettingsTab.scss"; @import "./views/settings/tabs/user/_HelpUserSettingsTab.scss"; +@import "./views/settings/tabs/user/_LabsUserSettingsTab.scss"; @import "./views/settings/tabs/user/_MjolnirUserSettingsTab.scss"; @import "./views/settings/tabs/user/_NotificationUserSettingsTab.scss"; @import "./views/settings/tabs/user/_PreferencesUserSettingsTab.scss"; diff --git a/res/css/structures/_MyGroups.scss b/res/css/structures/_MyGroups.scss index 73f1332cd0..24b9213336 100644 --- a/res/css/structures/_MyGroups.scss +++ b/res/css/structures/_MyGroups.scss @@ -35,6 +35,12 @@ limitations under the License. margin: 40px; } +.mx_MyGroups { + .mx_BetaCard { + margin: 0 40px; + } +} + .mx_MyGroups_headerCard { flex: 1 0 50%; margin-bottom: 30px; diff --git a/res/css/views/beta/_BetaCard.scss b/res/css/views/beta/_BetaCard.scss new file mode 100644 index 0000000000..a860473732 --- /dev/null +++ b/res/css/views/beta/_BetaCard.scss @@ -0,0 +1,70 @@ +/* +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. +*/ + +.mx_BetaCard { + margin-bottom: 20px; + padding: 24px; + background-color: $settings-profile-placeholder-bg-color; + border-radius: 8px; + display: flex; + box-sizing: border-box; + + > div { + .mx_BetaCard_title { + font-weight: $font-semi-bold; + font-size: $font-18px; + line-height: $font-22px; + color: $primary-fg-color; + margin: 4px 0 14px; + } + + .mx_BetaCard_caption { + font-size: $font-15px; + line-height: $font-20px; + color: $secondary-fg-color; + } + + .mx_AccessibleButton { + display: block; + margin: 20px 0; + padding: 12px 40px; + } + + .mx_BetaCard_disclaimer { + font-size: $font-12px; + line-height: $font-15px; + color: $secondary-fg-color; + } + } + + > img { + margin: auto 0 auto 20px; + width: 300px; + object-fit: contain; + height: 100%; + } +} + +.mx_BetaCard_betaPill { + background-color: $accent-color-alt; + padding: 4px 10px; + border-radius: 8px; + margin-left: 12px; + text-transform: uppercase; + font-size: 12px; + line-height: 15px; + color: #FFFFFF; +} diff --git a/res/css/views/settings/tabs/user/_LabsUserSettingsTab.scss b/res/css/views/settings/tabs/user/_LabsUserSettingsTab.scss new file mode 100644 index 0000000000..540db48d65 --- /dev/null +++ b/res/css/views/settings/tabs/user/_LabsUserSettingsTab.scss @@ -0,0 +1,25 @@ +/* +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. +*/ + +.mx_LabsUserSettingsTab { + .mx_SettingsTab_section { + margin-top: 32px; + + .mx_SettingsFlag { + margin-right: 0; // remove right margin to align with beta cards + } + } +} diff --git a/res/img/betas/spaces.png b/res/img/betas/spaces.png new file mode 100644 index 0000000000000000000000000000000000000000..b487e477af3741dd6beb769ce75be1813b50ea6b GIT binary patch literal 136319 zcmV)nK%KvdP)guZRob#Pir!>@+xw*M(pyPJC-F};{ z>qB_0ykh0R{{4u?6VOnG-KJsF=FLdO>UAg<3m83d9MCj4Z8jcfLsNcr^L$kwXvm?)IXXX05 znZ|4DdeJ<*dXJK>t2?N3xzWvk)P1?Va-W*NU1t3qZXf#BuQ%#o)C9qS00(q-o)!IW^zboOYr(Utg8+2Xj-*fSsDs9`222Ud5qjg z*BpFcFE`ux044anb`-%+F2d^@&!d-(cC+(&Tt2o3?_125;9$Gxc3mDEg`6~;4u{JQ zyGw`D?ojRNu-jC-+iebXwhhAT@#FBpBZ$UgmG@$`nf1MT^)OmnThOT3SkL;liAJNW zdI^z81cQTv7#|;3&(_w~#^){?@563Kp-_O&=flXz2s|DShK7c4?AS4N?z(mBaOB7l zc)eb9cXz8}e;2$s*k_y@5;8U*xg8K99_m3KTpVio6FeM?lmOpkxVqG<13$6ao|) z+)*Hq6#2;%c@2W+h1<8|&%b#W0l8fHXsm3f}gtm-FV=>hhV`{RZJS? z)BpTQ+;;md%f^=gu-E6U0Imi4Pd)V%ve~Qx{AZti7Jk1U!C(-F4joe0_=7+A0~|ei z6#w>b|AwZfCcO8(@5PtC^d$xQ*Is)q{^oD~2A5rSnL6)+3ogLD_uh-Ht}Y~#Nem1O zVDH|&N?7#t^xz{O`3M4m0De@(dd708j6@=#1eZKht>A0)d9AEmM8L}@m&#x5aKQ5(W^}%>%U0HK_W&3MbbnZojrhJ@E zrzi^li^|J2#Q5t3^cCQXW>0NPf&FXc)hljikb~cWp^%^8?^Yu}P0ey7mQyqWm1<;i zd3^V4U%`7n^kMW5ufh+${uQj*u#qp%joW|reV7^>g^QY)R*qs**hh`tLvZ$BhJ(3~ zbwZ=YUnWFD^N}m%-a1l<2|H32*#RCz*tAvDcY0>o&qMK^O(2C&`JQk zt~G@DLI8)-LCm^?C>8T?CMKchqpW{P(JW3|33;OXVwPHUwv1M{jwUDI<@Ey;3_0$z zHyE__CV3*2$3aqAc88PT&3l#dIDY&TF23+$TzkVM{F~3=^$x>@H*Zn|{MaC<}*2X4JZ7hKZ2yA(ghn% zrGbfb8IfGs$kXTW{H|S?n4QDe#3^#~WeS}H z5^+BFe3}~eW_ZchPfef1=*Sd2?A(2Qq&jvVB^A?(;qy8$us)1UH|Xf>o`z0=>)^hg4maF63IKN*>AW4WNDPb9Nz9%~VdrBL zm^u}Q+vg@7K`KTMOY^Cs>BbYP-}Mj94Nh`Ujlj;>z4Q#BZ61I8aRtBv)Kd2B*@J)h zhksDNfA@EPSM3w?UBF!Enx~(B8Xx=E$CO#0&*#-XDe^6x{-;0vY4x|zL~`yAe((d_ zbI(1h4kBQreD<@S#gk7yseW7AWWQC1)0MLU=KAN?&Y%?3YWt zj#8oY$1(t3lb)}B$r5m+tER~h=ZGykpMH_F#0KoR*&A>JNIH{A&NEUZN~ri2Y-wg9(zP_xrLIU!H<*AJ`qi!FW|+x_7)5e`7xK$a6H+H zNTH1?9nrTKC!LWb@Y|KZ$&-tTP#ceCby7Y$`hyPTge_}^i&mVbLS>Z8C2F`)eqtDG zZo%cD0Fp%?_Qt#zwe?Y>?SeNo4SOL<-aezabK&ou6dMUTJq7T+#Z5=}Uf@X#qq&7ZVKt`Olh3+fy( z z&Lt3gvyb}2%#|o&+b?&(14h# zOK}{JL=mJ33E&;n(5DwtaNFF7M$5>~CgBb^ zFh9pOT;<0MpQWkb#_(VZ>6kpS5egSRTT?gdrL%qb3i}6|E1JD>*Q)SWBb3!D0_Is# zEH00`zA=Cma8M$dB)Ud8cL80|#y4!(pg{N5TW`gdEn8GnjST2eD5Q>&XdBVQCnhG8 zM*rM%&*3+I<2UeEfAv?`y?eJ398$#5D*{ErG{5-8FJkT5wJHQu?k7S;qJD0^`DP^m zT3T8_rypkMthPA+a|Q2ON9@_0TMP29ariHa5QX2wL=*b@x543c zqO-3Zw$&OAzc7moHS|0w8oR@$oTP1SZY0yByE@&Zw0Q4CnRR1x@KM%m?8d@kobQC~ z%>7O`pOr$Or9EIin*sKv}kv$S>DIC4j z)!M#!^X3Xj-g)Pp>RYHBt9<7>->Ke`$9?KkpQ;=$z+PKq+ne9~X0>0ehtp9{_1kKn zt}YS7V=6PaQO@BY2t#mv|!F2CjqeD~{L z!)9t;t5>bX-~Qi^hBmx4h%0apN1`h$kO?4BsM8TcqV6@$eERn3u?(QXVtuJjUW#Y-nr36?ACYH6IQU z*pJLQkn#5+ke;VNnNym4s#HWQFCmvD9F7(cc1nmPu%XFe`T)uXU~8I+?3ty8KSO>w zOc323^1((;aDOUHx@QBa2U-)3z>0uim2kTkgPU4W9*NQ4Kdm0Tu39prDu?#x1i^%`xfzfOIrb;_QpzOR*+US0$IA7$aF4|@vmiiSs>?>#^Bc53xGOpj0D zb6@*U{NQ_cKPQL|ZS25F?Vj$T9A_ieOJl>b$LZ;>r85fzQ8vh+Kc#kDU~Di_CTVf8o&^WI zbZnRC#7-`zSf7mY$Jl)Z#7Bxqq}gV4i06x?%JWnq-*{%3?6!G*FJ9PtQq2fH9VdM{ zaH|K=b3Ok|$JPsidMf2i*KYJ&XA(YVd+pcC%P+41{*SPD?IAh|?P`{(24hmvH$L_E zIC=O8uDJFd{MH9Pg5Um=k78hOSV2WzC%sZO9Aug4LpXKpIDYAWe*n9m+e=WB$SMae zz3z7GdHzLw>?6O1kN)yURA^_=w2#&%ZYs#6e!yk(z@&x4=4xgI8A|MYaXgbn<%0vkwOB=nl|fY&no=4G5@t z36Keb_b!5FlP86C=Pb4~pLynHDptg)!x?JRnwpRnr8D-tt*bD3VwS#*3}#QH(Xqjg zi>^8!z3p9i{+WAlU?2V<-I-k0X_)UxB>$ zaCi$HzulM^J&CEwaSE3bx@ZZx@^%dRJ&*{}v5jqTgy}<}B_@8BsnH~o2V<4wjG4?r=X8-$^V46G%NLB9&ZYn~xz#1w?T?Ft z@}<<_m8^GdJDiQx@>)4_c@6M?gvD-mD4=)SoCHdzqFm zYKq$a75LzXKcXCO59~gQ;^)7L#kqNW{Ij1ze0oBiGe0qfYu|J&ZvWX|#SOPzg}cA` zP5kg1UsWLE5I#R|Xr1Cf6%VRTjbB1S)1sBr3OEs?mYSQu^HVbf!yqo|Y{6x1E<80J zz_F+oiL7YPG2}u2fhOnjQ?}tyyo{5nJUTo!kbcL;W*2FyvI%k&HpH*FbOtfu@FS55 zXI}-wIt@QVp^+dJ6{T>Ck@gx%!*&U2oVEbc)uirNiz{1Q?<-i^rorfcsfzCQKH}z2BHsR41PojO{A&l?bjlC~Ejd0kD zeNzei^aVYbo|;1|t$?GcII@`{f)r@^9Ix%=8<9z5=_0S=f~UoYENQIlLI%$~0SKrt(kM5Se5Z={ORD!;ArKONXsdj8iUc3ygU4e)=2rC5@% zJ!-|EW=PO{=KhB;IWdEg`53sz zta5Sc53I{UYpWtB}}D-G>=4N7E46~(4a4wN?%*@G8352 zQI}7H({Ic=jSnTQAU&>L94v zF_A2imU2Q*C6ohqguapy`y_n95KbODi5~g`F1olA$LT>&jz=&ai6TP~Psd{vFj?pn zE=Bq?=)-26oe1!6e}InJU|uD3TbRnwKT(3yb`9pHi4t(+t z{z3tT-R^?d?SsqVMKL%;V7J4UStJO~kjj?aNoAx7(vsswW`#;pwSdc*ACTd8nRQD! zKv2zL-wYk5GEn= z8#b~@ihxldcZR}8CQwWCrH)Xi8vzQPL_CR^V^Q?14P#(a7Z&D$!~&_KR*m$}EV^5I z=%^j1eDcuW9x#zq|(cKf>ZA$hh4t z;{P;;wQhq=K9ZW38grA&t+eG4`WmMTbQ%^6a==gU@AEs+-_wgibW%BC=cwIhO4LNj zQ49Ec3GxLxTJxk}9CkW}3Ccc#f63R1oV^=%I&1COIo@-gKu>^|bi%y4X!kNfG~l$8 z;t|KLPENk4GH%Kgf%$X-r=lqghW)sHRVUtHb7R-66VK0hu}A@yFUFB6@Se7!dM*(t zCkXx%**yAvHfsEKG#Be4FdB?m*)M{lrH52as~^*o5#%!kWsQvPBbY`CYF{CcBAt?k zKkPCRqUqwOEh0S~hZZPf=ZlkYxm~cibToInk;`f-J##Lbgulau8Ja3bpPodx&57=- zH>u=mvy%yUN#Sf++l$HPMlm;$!j@G{c$(K#)C=1so1&HC=C}BP#eH40VZ)Xd=zKRt zEyK1B8hKzUk60zG*7mnkibjzul+o!YHC6N66-^&2N3n=Ae0ot5!KLUoD5!8u<@hy4 z%Boev|79tSU(NDLIHg}JOUrA3|066ZQUnrgA|URSfnJtW!Uo_sQM;a^X5H_zt58P? zee8A;{G3iq(b2ann#ToK-30q1-yt27B;Q_Ce0rLKAwdw3NEO-*@Z0@#wCdE@>3A&^ z;7P}nrk`~N;qmrT>U6_dBtMfHr{$1AN}P!FB@~Jpt&K8;h4>h#*_u7WN#K|G{Ns@X zP7?UN6bxHC+we2%?U+p3v2!+zqfs9z72d0yBywle{mJy;a8k!1YRXw^#Y?D*+L%SN zIQaaX!#=Fq*o+tM8$+naje*sDv__oDd792-sJ&-#-F26sB^+kQb;3jIu^#yF4N)b;_z!V*(0aM@xD)f21!2q%p>>WXRhClpCPUHcYptBeErTx zP%P%r-Q9(|@BU#WbEZtnl4NT#sY+5ONLmC5;gm^Pvdx-kDHEt%Q>E$)R z{}GmEt)%j~OtZ5F9d3j<7-cyQ8RW5|%$C)0inNI2k{3XU>1DJNS0w8sDQv_d3p}rt zg2Ri6Od4JG3_>2EWip`8lv;Zc$r8EfLPDigaN0bICn-q8jy^}B;)Bl{M$y+o2k2%v zaxsK#)co}rwfekT1Vs{^rHjJP%WT^c{G=}I)Uw42D2ru4q44y$q;RlfpecwqtqSp+ zAijB=)Kt>V>lKhJlB<^c!q7xx#WT|sVfqVtSNm}Exdk+L1hM0qK@1M{K`*g&Sf5xd zVdSWn9!uV7KE4QFnY2$Ki}}R@G=kXlsTAfTMFhGC`ndw!Ap)D-iLl43ghP&?-My|E z1FzeLxw$DcHPiV@3nu6b!rk7F)?3Qx*guZ>Q&Z?76_jVYttaQdrZtSa_D_;3%2NQ@ z)f@_q^v)joOFAZl=;&h|^R^|9XiLCt817M8c_8FemV?u`bjY1)#_1VY@U2h<{eC9YH|jD_U9kRSHAoO%+Ai@eeZjp%A51pV~?r) zH>0DY3fN`#tT>7#p_&8&NHVn_XTX0A*kAeb8sPs3OIC8_NZu@6D1i)ut`KqrkPc@X z$g(4m&(N8h<*&Q~TcK!~R|{8XH=gsg1jfq+<9toxy8YuZFJCDk2q@C70gO+pF^5 zv*D1*##H+~{mdkyC#TWc8bFJdrZb#cGO3ca10nQvw%~7nxYGc8wt<_x{EpYRB1Wnv zJ4ath(2JHOq|Et+lt4zK>bt;^`&%@vFI#Yc|z@+#D^tTt*zx4*cea ze^yywKEDecbX5P$+it<1{oTKka-y@`oaHMi82ihv%$wVkc#ak#MH4`Qyo7VcsWw)7P1Ge>Ht zfOx))EH(6GQR)h`(IM-1h{kX5&XUSuE|nuSq+?%X5v#&>{OpzxrV}MRGaJPI`3UK& zx^)&BP&(n}Fe1?mfz?OL#7SOy0CV$E_=7D-ERNy$$x(Fow&AG<_mB=x$--cm8H=Dy z3&$o-Ro3aRcIHvC$?}6vxLA*_jxKWiP9)zlsqMwFN zV99yZ*TMF8V#l^&yzi&4H4dkM5^BfF$Z6%#mwY<{@RBFTD%ScJl7P)RroJ@NvL!>O zoGV#4U&(T|%ND+-`M>n?BLV!g$)$0+@>0%ebdB1&ob5GN$|2HdLdcnlvF56<%sO1u zd+h`x5BX%fgsA9w1c(GBJ2g%LX$pX}BcNuxMrj#5JkI^TJnTK~GTDuW#!3#5S_$2X` zJB>m2A{?F&BAy=Z>!n5-BY@7Kn2)MFFd3dSoibL35) zI&~h#Ws>D#AN^oElnbA$QpXl^xN0bbW1cM1(GnaK zaNax#Icna)Ru^KEF$4>>OP^4{(;=LuFl_4SrU13WLF%Z8m|9YCN&i|wvsL}g6NbJR zN1p9_{DFtjmb(ZCAKZx+g7d@o-mj>cH($4vz#dlTOifLx{P|(}IYgru2d~^i5}!%> zWVz;f=bfjLs0m=paRT6DV`It^5Pn~Tf}A5%kR(l$>qx@3XP$XRSrC$pZ8a^X{{H?- zBDPnhXiMATwTV|Rzr3n|-zbjuT+*r5UT39pE}8dUN~ui;&}e(@?=yBpNq$z2ky?;g zb+r2*UOb2ey#ujq z8pjFt>!`^2-2Fwq8G`*xF>>z-$HYsw_l2>~wEwg%gFE9M#WSSC2HjtUO9;Pd>#vnNknHznZ+iM zCLPt<9Yj-Wi;B@tkjEd7&STxs2B`>2bbYio^JR3#c98~Z?;%CyrJ#w$DWKXwwoIkHSlXFZ=q{4Ltht1@ zWuM3O^uHuF+$yssuy*YReDUFj@U8vF)Pn89-A#&`k|KaCX_2iI#sb!o6JOT3U07I9 zfG*!wc1>~Owzsz{OF)E&oG(H{gn~GAC0nOh3nDCJ9bKuD_yy#+S7n7fZE3q$a}{1I zuS|Kx0sm}(vC)+2a=Ee&+i%$_3I0>>Gh}{qgm6Jd*%xWC1L>rz|;0pcF-4 zvyt0&CP7egD+-Cspw@DHI&iR zgkF_cO$5~mS_BWyr185(1FTqxr?}@^`!Te-A8&bIH=cNW7upC)UOIC%$&VAVp>v>v zg2jfApP)2DN~)Yz{((!bJdfOX4%rJ+$Rr%(t5a}z3F`gyEoibRco9=4BXEcLzDS?7 zcQqpv4v`uuBTiwtX~TMGQlx<*h)Vyh0ROIc|>Q*AiGYLfK^O%_6wezKA8tY1N__v+-E;P?5 zinC!fwRmuHdII^tS`;680%Z!`kT*zrhmLh)x|;%F(Z)MEIx2l~>(;Fbysgy9QiR)I zX_Y(4x+z68{@Su`-8#JLrHN}DVp zni{zZAEDesOCZI8-7b0QsS!tbo8x0gu{sz)nSvn2K`p6^Z9J#hL9L7q#xyA*0pOC# z*jQE|FAJ#1TDme#sEHcCBw3U62my!WNF#4g@QV@9<3%Sa94CU#6b3_cIIo%1N5GE* zv0h9j6Yxo{em%uHX8BAu6~dX5S*F78tJSZdB95}4!<#G&24wgr1$ zJOP)_fuZ4k%uX(#In>FgkI_*&i)effM~+M(91NkgJqx=li6%Os*KQnAt2doIH3^%? zt)f_p6i8lz^%OySpsSBmj!(^W?(OP8_E?nu4j(#)&R2r4IoL++m6j9z5wod0*1zd8 zG_9Y;vtNIl!X$?%!8=8Nh>KQ}o6j4d169%;3x(yjo0OeqQ=fb)gQ?W zn6V6@_?Ija=tsaso<^4}jK;}AnYakZ&3c-!S4J-#f{8)~V~GSdH`}q8&!S9+ry#t8 zpxfpQspMbzQd*Me@HgvAfhe;FDt~`s z(ShT!Jh}sEbbEEIZl|-j7{+w29Sd33n+`<}t(KgMV$qbwujZQyeO1?P)~9x+?bk=k+*gr z9T&%_8xse}hm)2$|CY@-^!)=EqhnU)q{(Ec=8gbn=c3fS9m>Cv^jvqO2 zoV-7s@O19V0_QG?kl}N=U3HXBHL2#Z{!=FJKSSZ~CpDJ)v;RP-y$hk_Ebihtt5@|P z*uNeN8Tx6a=heAFyGR6%X!!Ciz<=b(5nO-$^=kRU{rmT;uTW`(9j}4? z%PTJ%@XtnjuLr1G8 zYxk%buw??X&ru-VLz+g#)Z0`lU#I5BDCvd>HS@isA`1C=YV3Jxm3{>_ClfIR#1YA% zQ*gp7N!-QCC-}I@`)dT8l2{e=5!hItfK2b#%xD{aOGglmJVuM7m4Fnm%QnpfeqCkF zT$Bl3kqiz;?L4MHtv`=GkCPS%?G~svL*f!#yREx8lAa8N9!X?+v z4(;g}#9}N0pVyCEA&>dUEXGF;!s+rV$Fj-NhLlApNO~rXQ%9$GFAC-yX)H=PyF+s3B(a{>#L3a)m?s64$t2O= z-bSk?g2b3pMc7E}e5vHbvkxAFKj6Y(vkNaw=}K@m2>??VNyz6U-`N1285`DZQP1?w zTdqJC#w39<94m8}P-<~Q zN~55Q*UGt0;Wn3s(a~1&J&wWQWo2Ax@WZRBhOJN6pgD0kjc`5W_Vg7t-ii)vRMKe zoi<}?yvr7V(?QLU{{?LA$P!d#SwpWqL!iv@xDqw#1gV5L`E?(3I@yZ(2=e8O0%*G} zMF($~Kwm~DNoA+KL;;XNlI_{-aHENQzr@r_s%5)GiV!$u9oD?eq#}T7;y6}w19Sz< zA_u0aF?P8L`s9XBkq+_mc&`Sv)~&RCmfZbVCXcDCL*|_-`l6X9x*YOEPB=VW1WG~tOmYp(VHb=ogs)@g6CsSx@mt6X!YUax5BDha4 zMBoZGlhzU|p#`xtowIzOvKY%kY6cUF)9{gkYwvPk{CE;=O&+Z33?c3;W6ioQ?0WVT z`d3pxIg0q*|Mj=z$NSZ@y#4*Zi2TGM#G`ZYkV451^rD=nvztP!Fg?jZP+j}B-Zxa= zE}n}o!sSQyLi0_bY~O%DiFMp^2p^(vq`9>TJ=D~_p=LPUjrn-FuB=o0lTh>qmS7|Q z*=u0`(#tFAv|Wkko;z_2$L_lWsiRLIK}X|}2x*4SF05%4&Xg+ ze+%C8u}`aA1qzr*WWiX6Q?GWUg^`npj*kl5W79R)($o&9?Q)!=8_d;&q-#l9W4pru z^~WE50`LF%4-+U$mOI)rD9y)Mr*nU$$JGEDG)*1tGe&O=W_~ zRJiq$(x+X@$=K=ZM}&Zy$d2&dMHR-mn9UIQlduQDa|odG)@|LhmAu>T2CI|Zec=F7SY#}urWERe;rT?t3KusO=VK#-;om?Mo7 zXLAL}Q%hz@$#?J8pcViTiRD%47YP0`E4L(>_Q|YsSBu25lRk16rg#p44sPCqK8tee zl73Q4gIPt|=%&~G3^uO01S8|e)WR^DP$Q(A{C;Zr;&`SHBa=>1Y2f>o$RZBQzSvke^=T!{|+_baaf`Kw=E65ub> z>}$ZS9`sK>|1`e&d%uqECMP)>PGMF@5ct3@R84c8?)c|G!DWfp2^r2k!cRXmuO8+0~MVc?z>|4_Y=~fV?||$O1K5$wHZ1fIWEx9p!_( ze;#{c5`ai;->E5~Big)h{gPHWUlJP1hIUGV6ip3DgFKxnsJ2_Ah2doz#|pAa6x+3A zyeEsd7b|I{sI30(HR|)@R?b^}PKT4qaif1j;~4d5B)WtOY-Ab!B!S<#_`*(C&h{FO zqWtu;4ER{lS*~eV$rss(rfn46x6-}OrmjD#^2%uVX1r`Y*k_`P_~FO@m}+(w!9W1M z)()hTr^tO~&`#>XCetNNLD5R>Japj&=vloU{`OT$>l#0_6Eou@SXhkF3ZBRMwS8E< zrGpxp2ZxV`aN^V{a=l66S#bN-0fc=XXr3UR-**_YbaR>7-@knPukn@7ejVvV5*^g$ zM)L~_yd+n}baJA@a2QkB~m0V0!V3$Zgq3P0nB8X04Y?T@*PR9fy)`K$8^7PEtCg z9Z*&@i!@u5roW`+J!;=b2j&sq_*FL+?v4o(`Qc4?{Fz0p-`s*r zNMVfcn#F-{K8opa3L-}rJgGf!W?3HB@MN-+!}&jJvbV&&*Mq%sn7;z$l>**#Ew5CN#JMB6y3ciq~3^?uAo*Lk%C!7Jvpt^KxsKl_cZVqta+?X7e)r6TAb zd;F2t>a)~0fE>Au35JV`*y#e0KdP#55N53 zU%(yTyBFIo+>T%U@XsmkdvyQvIPuJ#b~#en%m!LG*Hd^6Q;h*`Z?(cbP(o4 z_70>R8ES(WAwMX9d}#Is@I>nkNRU4+wFmKFdLEvn6Rk~U^j>le<_oJ4e%tS0V&^O{ zm%=j1!TYWIdr`1gP8xp*J1nZ596ZgcOlk4h*IbI7}|0To@#Hw zi;u^Ujo5MMnFwri6L`apUflZT8*y+?2cCcG1r%IuC`TTJBR8$mJ7h{w&Sk*R_GLZW z4zEL5O_%og5TX_E;6z&a3+xU}(MLjEdFX@i+RMu{DEY|bpkOHYKgN_7piigLmFKsj zb2MYgE2Dk%mptFbHBe#Eb)>Sq7aem``2=Z*G##)JOl9KKYMs>Z zL%8M*x1qhK8@qPy!?ka`6~~Sq#}9sZANCwLPBzMp?|$nJ1^9Yo6eH8kq-n}%iN`Be zk2RQ8n;0HjrO7)r^3C?3%CllC#>tTvvFKifC-p%JI#MOA1DN0aByt4vwqN@lv~1mk z$+;|YU%m?mpPz<(KC1ZpQX-2|M+n(B-wbqzV88bVYJJ$TPyG#_A&*PGau4!jhcWZM zUqc||$Nf1QqEiLrX3|*QNA8`1B6@5F`eS=hSi2VIZ{3O@h0$ZrJqLGa6*6&xRCZjo zmC+eBwQ!0y5#nkIhJIVzLMuI%#R`S~1Td5t`~F}cVk5lA)|gQZSOl7W+?<>mAH zDk*#ayB0}tkV>X1+I=Gm!4d*zYx2L+8vVuQdpvT=utUfez|;^qAS5MGSO$F?R4d#UrGNCmwp?|2>H=|=9k-N>AJ9)q{N z2a(h)*00}=2mbjh@U7{>(8X8bx|{lOj7HGjXHLSAvcvE6qA59t_+%2%1=3idZoUU6 zCg%CO?Q&e89mX6jqICQ)(z%?PK`UMVI6b>Adk)*_lkEz+RpiemQe-;``q_dkZeB*v zX{3c%BKXYqus}Z%Pmta-CM(ryy6V^($NZ0Vv9$GC4&HiRO2bMpKut7QLjbCqc$G^; zaP)`&f?Q;bz9A^~TUxrq1Xi_NQC zh|QNZzW?fN0A)kNdRYx2JgJm{Kqmp!t3X`S-SCmacS?R=Er*$+1B>M-u4oUS*XzRF zlTkPwhBn&jA$aEsn9Ip^bZl&~Ba$nt(9zXvhOuG&Y8*Ur0%dpMo_9f6jqcS_KpIxlCqqC?+S-?8zZTi(q7K1TlX*HaO<7 zvCT^g&5l_<_zboBIFWqULQVnQ>-+4=u^e(~*wF06qf>ch-$>|auDrC5SdLpOT1Po? zrJv}fin5@W^|R`4=Ta(z(FEtpJHg5hyJhFDaNXM9wV+@7u{8+&tz6TrQ@sXx^3iW% zX8&XGdyNHO=y`&J*5O_E?L;w>#vL`Qu3=F6&nj!=wJEn{g5d^i#&(0QD&!uh7wXEdeY^3$q{$2muI%lQ7>(8@}u>k&b z{qA)ALqCm=z`FiQzKYs&Pe);$i{Pj)=LGm?Gx%z^WwO+tNwGKypc*v|s{1PUiLdW` z+;rPj2(@-AM{eyPv958p4|%%n7rf~je0=j4RJ!48$)T1IbWp322%Lm;{9*>OMn-@j z^|PYE(mN>;JVv}a)NItK)SuriZhIw>)Mr2UX*}}q<9Ldiew-SZQ>YbLU5d|HF6PkQ z-noJqX@*h?r9;6JZCQ;2t*bFPItlm2O~|H);0ZQSn%4MHK1SEeHH?+nbSj z=IijUe?1moxDz(H2K^f(&JfRyA^b#++Fl44T?~x^sQlRDq*szy$i(0bva>lt zD7JOtjsRjnoxhW19Hte~$LGB^T|_5+8qRd}Z${N&)gG^hlnb-Dd3+Nm6Q&f5T+GsbcWFnKsDrD5^Jp_HP z--}G9h+`+F@xcpQ@bp*`W7A1&EF{!5BrE1xQgf0(P1;8$TuJ%_nOSQsdLn@b0``&# z^K8a+Bl_t~=e*Ri5}k9V<4(7KrDJOEak}fA4Y;078`Oe+y+tTxnGmb%=e6O?FBSA( zJxYh4iJ7FD$m8>9h^I;jdTH|C{%crw`HecTtU^)~g9 z=Qw!qXmui%&^3~JPBD)-K8d`_+P+7^;D4!mY+29eAZhCPzBfDDnN8CvEj z1=<3p$mCC@%J4fxAePa@_uA`oV!-c2BCq42(HO!`8Y%_WiGQC@%V>X8tfZ=0e7a65 z{h+ol)qkH=sny}v*j1weHpd{>&NUhy%k0*!tp>h&Jc@TqW+qCBu` z6isZacr>m;Wktx^&54H6h9CXtN7ea~C{4Cqdg-MrYQ$$#8c`uDU8j*|TCcg*Zd*xv zKhw1v-T$Quo->{IN(rzB2xeAh+!HOdoquAu*txY`FSXtiR$WrCnI(m(3Zk!ZrRR7OD5QzHtY>|AqfVkd%Zdrpsk*-MJ&1lgWZxU>SC zE*F|ei}|$-HGEPbMQVTS6y;J1LG2iV<#~)fc!ac#&_V@hp0%(I>_Fl2ZAia316Mo; zPb#HWauTyX7M;f-I)1$_QZ%tyWQ#EZ4C$Hd0-d!nxXTV?%2^ecU(!mXY@9~oHCjH$ z6J@X}==VF&<+EewLLQwSBX53`fInL_pnjFs7%;3-YYx{AirQ_B%8I~XTN#jEN;w+< zsvoSi$1K^VEj?H5Ye3~xICm59oh}=WPNwj$-+KX_&az5P{r4}Xcz_SFBn7Xj^wC>!&} zI9&?p`nG$y{96NRlS6+Fg+E(vC zdhx{<5sgOG(rmZgcAHwDLC%qmCuv(HBchn8*7YPmw{%+Rgp%)jZf;H;C)ojIp$7ps zIaYF=NTxtBb*00fIB`OmzjD4rQp930^;?oqH7df3KJv&T*uH(c8Vpi?;~j6twRhg3 zmcJ{Kd-l?iw!~C7Uzpau9Yx7^-_(n8YcnP$=Fr?tic6DaH}Yt@WG!-~^AOvz75b^Y zNI!ia+^I1%yUS{}tk2VlS(iuo0g7dtvGy&`4e&-y9+~(gGhr9#e5RAo)&{NXGI)2q z6UqKz*!L{LGdTy>$rqpnW#MiDIH#0pBTYXQs7~6a+ESV8YQSsKmGO+e2_Vk(3$DI?}pi%GA_sSaEQlsYA=+FpH#& z5}ATZw$_l!Q6~VE*>SI;CjU|Zpb_ZHZx01%N6@3FnU%EEl}vll@aGeGeCEM%ym(}u zekcv?Jt4$$IySQp9f;)db0Fdz`3!cchlY2;i zmvJKCFJn!{&%uKS)pQ*=0DFveNU_7xljNs%EXEGUOs@`|seM&Qt9N@Bw zk92U!6eys6@4fe;ySrOyHUjL@+2uSDA_DxDpb)2){1*OGG$Iiul3h@)SzlyzAc-Hh zC@Coutm`i=#*m^=Awh*9e;ju;0E^PX95vmMk8epiU&@>JANFa$DX6f z?xTrbP_O2iZ~^N&gNSE+Nav$iD5O+s<1(G!Imv0G3CROA@p~>;R)8z?fH?JLY#ZS0 zxeTRKC*d8L=gWuy3n!s9)3F<9fmWjSpNaP@k`IKYGS4ftPoJKx(b z#7Ox#%etb0B*SOAm{;i;3c9WYj>qOul!6F4kEB}GjI<3F#ib%t^u~S1Do17$xO?v; zCg_Az{ioU~@Do{T2ebL@rQhS)^_{q4O}m=IP*DQ3rBNjHW#4ENfBV(FSV-hB&>lpY zV`@H;Ml6%3-$YaIB~5=#K48Us(h&$|0|;5 zucYyZWu>KP4AFue4?X-m{8vAN+ut#)gv1-)_(mK$bO_c%)IY$sZQIlmYhrQ=KnwUv ze(xPSb|~N$%|n3w&2N6Q`j&gkl51iq$bQjMEGLzK_=OishM;iN#nQ40<42p3u3e=3X0{EMaDBS z9Tu|S2_1bUmjdMS!N*ai5YkA?XvMOTrkG&kaEvKOG(Eet782CJ+we%|FuC~{Hgz?@ zw|Og(<}jwC6DXB)Ds^*KtP1)I1gso3Nz*JTl<;k!fJ2H#A_Dv#REL#Uj5>G5y-VSG1&Q|HKH4LhTC_v(9jV6t4pmi zsjwj*hx_@D!Vx{F0J74o`0rCRkZz3~h4a*%$X@(^QEuM6B28Fd&P4#catolK8jfjw zo}EwN-sgAH9c?Smw3}#-dc$Twlrwr!5dXrLdj~20JpW0kJT}UhleZsYZqZY zn+29FEvL4KDSNsifG;1b$Y471-~;%;b(dm&90ojK8GxLl2-sz zDv{Q47#@6~0DQI_=HmNN&S)xorDmf>uk*XidPNBW$!X}pPFg7o1p65Rc{5sRN%e0I zBA5Z@?|1=w9{oIpND57C#zoRlnUcg;IaTD6gfivQMSj`H?bESL-$kKh6Z=gqb}sWA zq?BatgJk!&FYUNi2aTrl_~Cv!sY|-4=~x7}soa~}v~z&ovjqWd#ot=P?Pqt*8Yt50 z&ev?}IS$Vx@W8d|f!4n6(7#PeUYhR1? z9j$PXlF?5dtz1X?!l`7 z?JGSxL#JyDm@>3V&#JdVyWo1PI{6i>ZH~ewsgennLGtGwYR}D1I`Hgn&_$;{LEa}# zenk?oNjRw_FiV$J0td8uGFZrp(BoSv%|KV{UU5$`!hbuES%^{q(CNo3b@X;%BQ2V( zk9`Kukmr9f8CTcv*hF0DhStp^<8-#S`(3P8iO;|*7mfTs!spA|mW-9c-4~QKp;bV< zSQk@owat^q=M~t)bX?XJO{w`dqyD;vT6tiN_zIO@r%>zGCG{GUx$;l-*xKXj&#%2# z?X}JhY_!IkbYuI@u|?dvt#=t^)u_*0bj=Nj-uD+c8j-w2YtUjJ!p%24kJ0fK{Nr6o zJaS|P9ZdoJ>um<7-rL)YpZmF=Q@=&S7tUQQW2?x@S3j<$kyY%Ndk*%+J!+QvPbf^B zbFpRT;W+*cas2*ssFOgeD=`Or9}`qXg2Dy^Nj5W~jZ&q#ql$Z&-yl zUbN1L@UcNn`InC2^fsYq#w@)NX1=TOWRP&)Y{vXOCuTLw;d3;yk&{sKj^Lh*&Xax9g2&Opm5Ol9xD zk>jL~=&+nWIzeB+U_&!Y1Y()Aj-Fe9#INW@$w*c-e)9oxC!T=TyAj{n{t-NN^eKEG zbOPz*5v&eTOXf33IyPClaF!Z=G;2c`LiuR$QxF8H`L{^AUOvmLq%}Z6(K@l5k@wyJ zPeCm1qae|BhnjETX~_F8_&zKF1pP~u%?#wgW~KZ?~bgqdCC$JcoWPf1_^$3dHE?m=P$5niR>tMoS0>1vZOy<$a6RI@Mn_wGG= z)nBn#Tu~(QU{l8qA{PyytFsk40pCT_vn4ExX|vSyWjsj^C zO;R?@WU#v30nczdM&d=39(w_f`Ta)bkNSIn}zES^0WA47;ft4ewto#xyV5L*dgO}ivR)2z~7BaU0 z|4hX*u!H>O4z$;7lZc#i%-H;6U+Tj$Rm75iAA-1pmd_}8-5)fYqz3#xC@iVr!h8@!=NvV!gvZJCl}xtJpx-Yk6vvK@r$oR zgnW6K0w_Sxmu$aTkAu{TO{M>J_;px{$*ht$$8Q`Z6Rd4FGSwy zg+0>-U+)D-QVULI638!{fGu_$?YV<+W=7zpQ`n(Xps}rdEt}!)*rpQMmB{^jd)LF; zKY%7W@3xf25kf*Ony#^pB*j5Ym-^b&I;~kgLl~x&rWw{mELT#3L{0wUds*alCFQh4 z5#`FVpo@`9$GJi$t9DvVX}%J=*wy4kv(KpjKg4eV#YYd#EZ4eg!ZPc@zWTG4)6tjt zQ7sa(DkbV1r)pQ7hF){Hw(MXmsnkmKwWu9ktG0vw-yz)OgA(bNG!W6j+m~Btm0#Uo(dK+VF-gT^zi#c;LW{nvf-D$ZA63 zJd&`mIY$stS3lajhLI(W@Si{U2C~^b_`qAPfZH{sK>u|+Rw0>t1OD+}@5FSxfY)u^ zfIs}{*Q2S!i==-L`KfV&vIEYcb?TZjJ2X9Y+-N*A=eX9n9-b@Th)^nm3pVv2F_D1# z$Ya>>b8p3oNA^LRpGEiUUr+wC4A(;mv=Qv*3GNQkL2h1C9@XcP{O|;~5UC9xwc4^D zJ>7lSJu`-9PmIIS*}J4YtP*qw;dQzQh;Eb%Lha1+fDp8%Avh>-&>W(ZEdZO#hcc}P zZFT`AnN4|e7h>(}(R%4MuoaxJ(UIpO%_5QO2rbDYm2AS>2E zxm?T7)D3kDeYKTzcCBW=`M1^pF7%q~)D9MXB}rmA5A+7SPu;zjOCW0qtB3?QX5mI`!u~gfrgnHKdtmW0@A5$_2pIs`M`(=Ac3Dv5D2G!q+{xh#rE-&pP6;2R_ z-^jYJ9H-J6K&?(!eZ}0y@nRjP*EyMt`2dDRtnOnmBBB`EY!!vWux6|)Sbb4bRjeWy<|)da|qZwRH8Mzk0c2JE=gd1?!*Z0d*%@4qVxFj-~Row zh!puw*{Q*{_Rvb5#zIaO8W90PYb8rZYIBbY$>hU9Uzmb6L*9Jq1oUlJK@ShY-WEji ziuLG8lyLF&-PD3h$Rs4}w1jsNHwBVEvZc;HLmArZXr6 zT}TIbPp1JTt;!300wYn)B6>VqDo?a5RYXl2uW^Nh-IQiS@Gc1ELEoQsR08#!n@|c^T zFC9*RSd>%iwaOBnHiLe&`nWpY0(;pe`;`DN&ylg+dnGXYBG1pM@ga~S2@-XwgBj4E zjuZSa?_mT0*eU`^)!k+ZEK{M<%UEdw;*Ts2zY%x8Qn}#mzlm~AB0)skx2s7w!u?)L zfbh5U&{56sa zvb$jSv?Dcs3h}uKUcm#ctrOW$-phK(TDlBb56cEdXx zM=n9Ybh^<^O*k|&f<4cF1RNR6~ni)|j*O2WJAtqy6 ztFZ=@Hm)p*vZlf+4gLxZ1*tNNIlLJ9>;YR&(Q+n_EQt=FLdj%y@idf*C(tEf>Jiafwme5lWXrCSdF~fj;W`2K_geQYE2Ick3EN{p8hVPkr);w{lR7eA-Q?O(1LPI z!bT3eRHQ&FVU9v3lZ*>Th3~{7nE2{9u7v8e}k8v>ewQ*{x!J3sUuFn9jBimdUO#*iI|y*!@Icyq5f7r zPa37RVQ9%T91D{uh3FWZ9L4CGVWeq^tfj#6(|Yi!y!NDl7G^Op5JteYh!^fZ2$w6! z)GW)sl8nsiZ`4)jF|g##!Ydl)XALQ=9O@Ogtyn-X}kxVh?-e8yannmPY=YF03% z@$k)dOAkAJxnQUTw_h-T|9I>e9q0-8`A+`VjT^CRG=lH%9zWyxLu~>4;1mBy1mkw zuoV~VxL65<+9L7zG9N`|mn(%sTN(nbtl$PIoBu0IZIn*6y=+S3HJF@g@3IuIiq>t> zKX$ib7u4TQ4|PGZ2&--*7fS`R`8?q8SD`KJ0XBaCXju;&`!*YTC$QmXm7;~w`(eN_ zuQl-qvA`V zK(80GhokTb;E9kVLUaxFou6e<#Ey{sga5SOo zhWEi0aG|HG8G9dm0cm!2|3D{BjZL6%XeTzk;RzCk6oFK1+5+JtuajRo+P->qpWpeuU|v!JONw=4{4TGwpDOp z4);FteYiTWM`Ch6UrY+Q60HqdAvQ04An;>8&t1GKH2ZNJ8V@IU0^zq#b=zrp_{q*_tqAloATECy$Z{6NUhpt=A%-uH; z!Md&xuHDe3CU4!pe-hW8*U5KHL3-)15)koB0Y5%PtNdHTTp8Q6(>rZ7~46?hb}B%W4|7wy^Dp!`aTXV*=w zx@^)i0_?#dVEiHA(mw!B+(}wt8-e^AK>LMMa!AXB27x303GDbk(8eC%w#(T_3*?(u z5xn1F+;d^SVL>b$0y=p9^8)N|r}jgC+~Cc?i=P0_{|JS^DPZd_1J8Vn7RHSo;A2`;J5qn@wQr ztv8}DHjQF535|jz-R48?}b}KYn=f zS(Ni9sp-4vBwmGb@)TS>o8cl*=QgiKC=!RG*@3Iqc&KH&@$h2{ICUTi0 zS_I{TpF?b5h|~+W`&n^awS1y{Oi|UDM>pBhT$c`E@_fQ(2p~Zs@To6k1k6 z9~(s~KTY97;FsL~97M-jHsaP_z6g^~K7_ev9^ku3D8W?Fjg$=nA(@h{!eTA@Qz)Nk zK}X+NaQIS$zGHeJ1>smyzVf5 zYR4d=CcrPIa>~;9@hi2{63;#@+lk2-P9^*pUbhMV__YVHr)LZPKR$adHGoS7J?QKi z#6u4}i07Z(Nx(Pq-MsB>Z&PVPZn)tFm6=v39|=>IKn4MM(fZ~0O6f!XD@#R-wHX6O zuN_AOa7DT3RqCTcmFP9ja9Yanb{IlJfVPx2_Rqb@!MTg$g%k`G8O+ie9KDa7hV;*l z-{HQ!{QF^G`)?YQP(MLr!+U{KcLBXu8KCTr0AmmG{61jn2~rc!z^Ev{3RE;t^4Rr1 z&EsfQkZ#5NJ_;LJ&7mQ{3LdEO{fn=mqBO&zs4PBTf5oUAtGuMJ%#{GXUQ;O&RGK&_ z6QgMb28*NvTF3z#R+&Z({sfNhIe>LrH{qgdUq_(ND)7kX$~b;-KOVX34t7qDia<$_ zUoRB07@0`pj{A0^{XMs$+mS=Sk;gB;?`ljZgH)RNIF10`_~zHE`zO-Wdp*7IXmLvV zD0V-z7hyKAi*(4gpML{(fBV}gZrOqK(P>2g-{U;tAj08cw7C}0)znPEGK4Y7F>~Yr zOgz7j+U8$YeDSu}0)a9QJ1L~Or=LZO%LhL_x?#7U-^hEabXzfvM;|_t~YAMQ4u z>1YY-FW;;j!BhM8z|q-?B6<8gX)P});#^F_3u9DfE`2>51fb(Pzk)P@RV`MoLD6ct zl1b^Pfoja{m4pngvxGOvr*j{*^>Ngd@52@aOAhk+YE zM<68d$4?s8ht1UJt!EWFO0(!IBiKPXdTGfhKSG1{`H>}0I}^ayS8DR!<2Z4A93A|f zu*s}UtF;YtMuc5F8dJx&c6Ab<$%#wKT~ZEi=V9gW%agiEX9;EwW0HzYsvVzNz=PEE zf9j1_!j(QnhvWhVyIT>@1?W7@qqEzsj@`1gA7fKv(Hw|j>yz*M33K#mf~et)7p-=?zl;XkrpMwTomfr zDR?j5fxYDG1mF_MIka|M0N=D1X^$86xh~Y-y0NUGbW9t;zECQu*|3L6yKHZ<*$Ja*Y&_42;D$C# zO;PAlfRqyniOpnfMVO?J)m=C`KZZ_0zv8!duvnx)67C=sN0{e!{X3$1hN z`_SiT5xBy%mQTuxGpM}9dw!0;Xnmac4zHhve%}Xqy#loGDns~mT|z73knt>)cWtZA z)2VUl!=iz$-!*Mh+eVGr?QF`+TH+9udNt1XT*~G#Pm?r7+g{{hm?or6d7}*=&`~9+ zqKN{MnUdk)<9^BJH^$CcE*6y#Ef7q^d`qRX>KZ3TrV!U#5YQqhXBOc}oIu&O7BjOY ztlnTGH|yRogkSoLkKtec^dCfv9UrKj#jQ}Q@^&c6ZIz3Fv0 zJZ48zVLe{ICV(IAKZ^N66wMnq;}<{ri^g+_Ux?2WBYhHF-H$>n0k0>B)udH^`wxE? zU-|r(aO}j$van3!V^hy8aTdjr;h2|?@aCC(7z?pBcmnNs=YRu8vKoFkc0?^U(n|T2 zJG2`Gmm6A+9fj13#=%(PbL%OBeeoEtxCna_&CLECY7JkPyQCtbiah_obH^#fL}=PD zc6b_k|0;BE8$?^L4YTt(B#J2%9drs$C!o)g64|f@PC5ncxj4$R<0$nGa!~L-3!_+Y z=P=@RBSoPg`Q7C?bW>xMMa<=SBnOZ1IWqPN&WooOuzj#u0pNHfjUVT7w&Exj zk0X;xVPO4Qw9ta>Chg~-FzelQ7==Ipt9#opQ)Ztv(-{khO9DUvb;(96+PpY#CFQZC z4wrr?px)o#uK-;@UXFk6x#v`3LZN>oKfX*{loaEV2K+|>_EuTK-vbKR4Tr66M(L=n z#sP|}xA=VHAKl~=wG5S`G(lYuMFa%QfEOjPk%NJl8chgpLCrJbutSNL%M$W9K*d9*pgD6uW#Ikz$+ zMd;Yr2F2J>1@=;G;jM6!uS||-;2b9hACOL%hkJGup{;9h^pU+NcCCl+{BAn339vgO zu*XT2(LZr?_aWFNj8eG#cJ4pM>&j~9nS}CJ=u@ZQ3;N);6_KaKl_(cYpw|?gBmbpK zhNIS@sQ^?p2xUw-&w|p~PsKn!wdLM@ReI(#j~-pJ@A0Fv>Qh_3@Z<^n*cM9()oQdk zYu9Ns{K>HiWXc*wMkf)8C$SJu!@;pMKj*}u!zXdg8?M6uuiP_W1Of|(|BiPU4n}d< zHY(y56Tu)w09~~Ep`jtg>Hj!TK1=+A@}p)ASc8+%Dl|wXpOVRo8;YdO6b8D%k;{^! zjv#5CPa1YH^_A)@k!qHc6kYv;k2{1G&9bIYIEmGq07F3ODx$~;A2og#4JyhMXsRv}Dr(*DG}_Wig5Y%Jl}nG@pwn*N z)glunzmv>#uAd3o}>vmO3^~nnKUAa1tZ3qTBXFtdMQ8z z^s@xAndv#D0eI|f@E7QajZDJR+=?7E6l=XIos>{v=VK_x7c2GB%n2A)yzJ8W3G+PT zNVSHjeRvaWeQRMI86P=G%ViAy-d=1h<`L%$dMf0@=fC)6{Pm~)1|7ZK4b3ha!LmSy zu8l7~S2mnXcDobJ)QBfY>jbF5mHnOYd7P&8W5;#vtvEtUWP0id9jL>U5qV{P+MIUe zXP)PEWp=8Q0%!}Z(SGDeiTPG_qp8V_x!TeUZOsL6E{-Gn#5bXxe>t7QA(ZG7D2uatah}4(K`JthghuVpYd8C+wq$jx ztOES9>5{CP=Js=-8|6^HTYMYE$~cse%c)p~K9e)e*gbve3VBpC(0_^cU+H2dG69ts z{L|4o4*F3%1ms9OgC;5zL2BMH0{>Gp^YD|d(d@>IXouaPJY|8NC!c&$ts^00ND>pu zl7^z;i$*Wtt^y&Nn-%EG3Rl+3aRT&0`AEi1(fnnhp^=dhB}Am2vO3)>HTp4$nn`w~MF_q0Mk{1wA-yx~1YC6AEynS6@o z7?l!POemi){WY55V}q&aS&=!KVKL|>W2UfSQIxCJixMbRp}SJwsHct3ro3W+Umv+6 z<=Kc0uKp&hrUvZkBnM33SD6&eXVGgUY2@(3n3|ZVNNGo57Cm$vddSfh=o~HSc_YM@ zFFH)~b^GRZm^k#53fq%UN5GA6If-EA5S{dE)HO?UlZgK1hhd9~Ca6_rTiamqgT|{U zv19C-NnkE7%lO%`p~a`TVG#`0C>LmMI{X-T$8S+!>PQ_X_ZSXiK3YQZ#D0VV9yAHX zadHMZPrC~HZ0!vqPcmP!9pr5#75h(Vj538vE;7e~#M)DX&r2rHR2;ToJ3*Ysr6l`i z7T$m?rX8RVkQuS%8ZoIOTPzz3YMbv@npbEauk-9WhevFQ;6;sYm%8zV_@X{Ai2ba7+DoX|%*%>)+DG_$YiUoRaD@I5 zx<^u(3+FFUJ|a9M+*6dYAK4_Y8XjA*-0ZWO6>ASu)3#}q@J2PZMU%EbUuor9Kf1<92kH!KQYE3oFR(Dwg_(%h>l8Oo+}R;#90FtuGpS?T871M}JR zQpvPVmaYweN|P)fPd}3M$SZBLG?(H;6w?I44efkr4*WKsT}{U?nITlR8cs)&sEOl4 zTA{#BR;1=E+M-OnlEx~P)TDjI-+MhSy!_lp(4 z7eR302S0%0Cypc9z7LnJUxg3cdNV%xEAU58{XK?<~K(mUh_*q*Kso73I85$nAd;(Ice7TunrdpiEswva^kJ4xh=_2Zzi`&bFZ3*8}vn z05eT$0rPxQ8}yJLjyQcNw504RG?N;jq>Lt=5J|?=>{{b3RyBQjd&*a;*;E2H)xr4N zYd_%p-?qUS_Cgt;%X>tIKvIGK@XWFM3HUQ?NcsT}e3lRXZs-mVd3rJg`#wWuCI%OG}A$7RiKx&C8p!nIMx99it=gB8IWgGJw($QT7Sy|LQHIX)sm+fZviWMo-9+I zWG@nnbfA^&=YuC9Tr*xUuYqIWyY|5ZBBIA!(?QOc5JzyacTqE`**< z;OF0Pq0(yJch5n5{npI{=dzJ!KN(e%K8%;6!xivh&Cme6Z@L+&uY3V>U-&XE<^8Yw z)nCIm?)dgHr>&Hbvj{f`z!YBl$gBH(O&AU|Q!_5`IVCoq){0A#zU7q3I7DaJcv=Rw zMw%ytMVj)UKq$nYgh~|(nPe42d14ZI^8H?4hTjf&!hW>-9hlh9#%>-&(bb|}m4|+U zj7(f{78@1U8wFRmx^~SyD<#T2)a}Ic+`AQVFFQ*$DstgG=o*#Cn*`m7Ss6YONQ_~ownUgUff7aK@_en1Z)BHi+LUCP9gRe zasJB$uWY`oQZm2)sw)PUFe_u+OC3up2N(YlX`xNP@$VAo=h$GY42xmrISPTxmOO<;Gno%ab9?D# z5Qo(hR0yW!cPMGfPgvV-m9}Zru4myRv&t);EwfV8vzAnYOh(AbJ9P9097@`XbW?gx zO+5!zt;Sn^`e!jdazdGo@>xeAfO3^17HUC~61m8Aw>5|1^SP-}I}EK|GCUHHR;}NH zK)AJ1hjP)7q=x0ERXUSyI))Es3fQW9&`iMGxqmObv>aNfc0V=~$34dvaNCCVN}?pi zv#I>~Mkn0={kze-V%Oa*D3*;jiulp z?gpl2k(-HfKj|epk#i~5ffiFfS;87m0n>SL+~rY_=o{%|vNrBKHJ8L9?4%8fIkqze z68r&D2X^G9C#m72P~^R`C5k0dOk0}0e4Y~hGNc0vWwo@SxN=j+ZSOgajw<%8lu00b9@DEY5fAZKob_}=T!2{FS zHqcBV5ki93I5C${5kHbwU(TCL7&A;|6|t?f7L4_IjkS11pnO**a#6DnQ!q&O&a2mV zVm_Hwf+YG1(Eg_0w`5y=(y&H@x38~PeSQ?>Y(V*?mb1C8;V`WMealG;Th*zlCSRG{ zp_%bguYfZu+`sDE7Wk7_$K(H7#lstpSnhx1*J$EUTQ8)cPd-ZSo{C~-)<|=(>+g;8 zpZY^1@<23snP?>zz~m#`M!_o}FIv9L%3Yv!kdGQxf&^f|;Oh07XE5UM?Wm-Dw&L+^ z=JP0FWqdaR_u9VkQe*L7cJj2-g=(syZoZ@}ZGErXQz6kcU0XH)!p$w}W0kA%GK*$R z>tE6=W`vN`sX#P3KA*(Mx9`L4$vGT*_9&goC7eIhp%$muGoQkn%WXnLqtXL~mu~T* zl*+@;cb=moEJHKewRSZ+$ipAb=CFETT}>!vRnvFS!8(&`Lr>Q_`X+p&pQbQ6KZ65w zmbNx&xTL47B9o+nB(Hxi&+jsM+H@3ct({0kvnZBiK?su%)V*p2uL8l_Ma?hB3TdQt zvg}U_=?u!GHH>&=3Mp#uI|B~mzrwocen?A$Yl zp!-{p7qFK>NVBy_YbZ^BOqkSMf{t~0Hlb_0cA<3am3aFy!P^Qsm3%v;v%rtz1m|l? zop|pRs};arLajW?=h{bF@a8QB*a@}rtJiO!F_Oc{`D%i^B};48TvHa{5gO=%!B$Ms zA`pkIjUS6T677B4K#Tc)me%Jmwf+}rO}uGqA6B;q)%mYXu{2bpXbl9wN~Io*R|4mk z1KQ_u-YYE}mTC7=)a0w$*j|$+s8Qaa)^R8s>pkn{F&6i4ol>NAJpPFBqQxQ*dsMREaA?WWRX}&4|;Nvjybaw;OT%qjxKAUIDj88b@Z_!o(Me{TD$JA2Guoz5@l*v!3ka7Na3-7RXx@^kf$;u>#Hd zH(b62A@Y-Ltzq10oveNly*OhTx&OMT^;1L9q_jYP|6Gj;qyGo|#r=jIiu+7a-yJrV)8Bm!!Wul1yyj>c)tr^9c2}7F-1(A-< zVL_A0W<@n=tXNf2lveMsW)nk}Jk%*5bj0&#&aOJTkitLGF?-wgK3qf1dXfP9g(ps^ z?3V{7A}Ypznre2IPRb{a&Z>45?S7u%pDh?OZF8*5Y|NOa(eC%CS-BFsA0_vF=dLka zNbncob7D53CT__+4^Bp@&1WjWdvrRkw0og(uG!GZW0TlDwuo1=ob9-3#N{?BF9(Fr z7R1lW%0I{JTbVHRDnVaEjTlEL2dBeI$XK>6YK{#nLd+QK%CT!vI-0F|tdYOiNL5^+ zgDN+JZu$}}=dYwbR*^b7D!h7SPC(hRG+x<1{SLVE(CUThEdY+nOob-X0G>pk)Rh}slPhn!l7+6NT zT0#NUm{`LVZ&*m?sb#%tBWSj6oSK-!U{4#hU9Zs?R-{cOgO}0aBnm`QIJDCN9G#xV zgU{`UlP`LBs2fuU4q$zE6GjilaPW8xmuziQW`Avwh=*yOCo>fTbT~^|2yxiv=|r<} zTX$EtakrY65eT;s$j}L@QTskZM{Q5vW;Av6)1Rxt8Q9A? z<k%!GciLGfB#i$)C}BDKXk}sdv*E;(x&-e#zP0kQ4Jr} z6jdno_=ZIAn6K=CgHxzDQ>%DTGY+*HW?skgaaX$@Z!Hgd=F|%Hi3(Q&*p((d)>{JB zy=vpO8(9l0Sq$}ct*0zccmMk1R;t62<6-(WDxAD#hALWd@n!RMm{B__tg+@;i?g>t zU4?LJRdBbCQx8*C(P>&}fLedtn1JO98yPVrje@K~C+9f*s%9#;zNf{Q*j2fg85&YH zW&x|{AQc&;8G=VISLPp8s2t4zH#K`$_-(yZ6+9B<)1bX;+vi6@=@|7qJBhxwl@7=@ zHx|hYJDdE0YGgWp~c3>fzGyvZ^ zul7c!z>p{hnSMX=#6HY+Qgbc%kR%n33uRrlu z_>ceiEV=F+TAG^?2nNwY`sC2@5u`IYf_)F}x#!+x?cwr=39=Iex&#u5B>H=LAxpg5 z=)85iGdP(};9@#q?ZLIs0&7VDkp?37?vEa&uXfs;R?g$e&BMkHIZD855@#X>L2eP{ zya$P?X{3dF0D?e$zxTS~a8Ra_U#3k9EsE*04zQjAX$aqgF0yqOG%xzEU+&)71Xm$Un3az%~N@ z`tvG(*J#+M1CulE)2rVrDXH~!sV~(Tx8-UZT9cG)riEKcnJhqS3Re*ZrgEp5Ghr)$ zY&m=_z!$ALI7sgAa%d?!VVhP%iySd#&5|upz`yQYM!Mz9oZ|Xb(lz1pGc$DhnlpAS zC!aM3#b#I)nrW$2^86SF84*3^Z`B`6g-EL`(4rZWvb2@k>qo}nTQ{q}`Lbj9UzqgG zFdb~Nu*p=mtnzj19xoyURyV=KQTtFznA?naS~TtmWyNoc2is|M)*7`-x7vz-jn6)h zq24!`PIBEeo2tD}P1ul>z623JJIV!HhUlCO(81Y6fLy?1ca0+x%fqXA)S}%}vsrYs z8`I0Dr>5{v|NM{exjdwLD9ETuOOmms0Kt|*E0fJtG^N`3S*dR@9YG?#s6w*>-hlFj zM5*1|2v~*m1YdlbT5_KCDyaIZgsBuv(o9jF=kTk{H0(=0`1>~~YobJr95!km6eczv zQ*LTSnF6ao?mg!rhhGv9mb4T(m4>0Ee-H^$76o4S*t3UVBh_QqGAa^BXe&KGPfe$p zLWs1`{H#jPQ0`l$^4bSIHbkc9mGz;M*2z_KS5Xe>io$7f8k&v>V9~~<#@S+HN=N#) z-Db{`grU9ZEA(MefDTU^X|L^OyBf+s*^I%i1y*r#XU$^`E&goAMk6y?{iS0`y|fy| zq+$WomnBL@wR7qw7%th3ni-Q=0SHO8rM~kp^hk2anT>x}h1rV7>h;^TrRP>n7i9s} zUD!Ov8vjf8RkvwNj@RgC@?E(Wp6vsuFDpi(m}9sST4}cB(iyeZ`KlvSz_b$cUQqWo(bht{tmWfxX325TvZ9AXN+$W#~srkoGk;?TMz%SZ2g@G<}11f?^ zDq-^PnypGPsXl7roR#EFuU(GOcs9M_cd(wZRH<*HtOoVJ&$hg*iC3r9@};9l8ew*d zZgFr36_zidWRtw@KFnqo(CMx&jiH+_N;46^_R48e6%lgX$9Fx2Kua5jHeP_{u0fMa zGw!9CgHjsV>oFX06^E^PF|863YV;GCvFpr~aPq-J7`piaB<3S{@}Xzo3pmm5cEOp~ zRJO+qk4Y!~e+!Qn=$Vwf$1D@r=;f`BAjdc@%ZGAeo85 z?XjzChoD2S-jCt+iqnkY@L;zB2Xk- zd-d6Ly2}VG!a?{ z9;2D*hThQ!P0}Sq6Gm98R3bTr(5gPfs38un>O|`31oDe<(?BZ zE0rt#b8`9!5*&y<9cyWZJ1QFca}RtU$B!Px)mL1NA<_}Dv6X|=E(@ZNBJsHW$mLV& zep7S1`FRFght0HS8dMk_YU`|97MDgEhdOde=oJrs@2%(KfroZusHX{mkRO}Q@51q^ zF*r3NR=ZFzw1^@*St6N0jy$qTe8!8d8tlLm&!1ERW1z1ao7S#g)^5@+b{?Ch^Yq2h z6Bv$8(GlsxL?TY0O<`-Fhd^3XD@Pe&S-JvJnMWW~-=(9M3Whnalh?P?lE`KAis!e- zljPl9u=kK>r*%+{QZq?OW<-zbR5BCM>&YWCpMplqWN~~3B@tA93J1T;+$p0b)YBc=Q7W1{M{QQ#GnpR@*(8GwG+KVLpNQrl%SsJu%UeC;3W9F^V z&D1KIM9wIuuxS+-TA?9mDzWo53EV0mg39qK^|@wH%UZeCDXUk7i`u4FTnNhIP?s|1 zCK*GYE|2=G8vlegb?Z@ni!|(+B z=-U)Rbbkzig05!UTIUOpNxE2F)_Be5)bLwB*n?B!bF?;`ICg46g$dRddHxs$TqK`C zP?CeC2;_O;n1j^FTk+w)_+=#L7I6R9pHOKfdWU=Ap~)-tmw0;5P!aJ3Hw90xqH^rQ zD-vjJY%_7J7P1m&nlm~W+izlW4$1k1(e~sUTUKv^v$+j?REIWzx*rw%cnn$ zuYBpt$fVPXH?KlnRqJ2Ymtd^%TWzDtD_VAB<%|l3)D8q)%~GyX&9&}d3T!^dy2U3D zO6)@}7{Ppd5oxc6c`8`RfCI-C7I5(KdvW-_@4?M?amnrP!=@{5Q48u=sdCjdtuCZ3 z)69I@#q-NtyG_T>G#s#ww4fV1MP5a9x^5&PM8^2 zJDQOC(!=n7;6`p+fMazxaxb2wMORpMhn4QU?0)su0)H20spu@G=$EQVLxQCZYfYwt zwP=V^t;N=W+hECBVRPrBCw`>SE->P3i@B7m-C9;SH%JbgQK>Q8=~bh2 zRtgoXFG_3Cj7)GUqqSyKy|t?ij?OMT{q!NY32aWgQH7(&o}qaihKr67NueNg$-d_v z!`#Uexbd<};d6Qj;uleq^~ z%CtgeWG+BiH1jl?JKE4p!7)Z^KteZN%>m-POM!iX$CW9FbRR3*(jtkCM3sk_8ycUj zDdbZiu#aE~6;c(-<@!#C z>U3x8aN`)Q28^qN!vYE;U(>cS-*Hn8C2tR+6y7a-j@#i(g-q()0 z2R}opKc=ykT~23UOJ$My-m|cEHBo8sQPW=lPSR07M=(AziGuu|j6f}Vpa69FomK+> z6%VqkE-Ewj)bf7UjNp&B1uqA=aTTa0$7NQu+8(xX4CMw z`{1bQnHIgK8uEsBBXQZy@a_Bpel9EP#&#fca2(lp+{*rtRxe7zAnh(cO5}K*9nCnI z^Pp$-5ElJ?s`=NgU5oCnE()1$m31&fppGXq6jTIJavVj|`(HmPLjIPN0}_fjU&z3z z%uqUgS^xQo5q$YiKT4kh!L;*20%so2Jn)Qiu;wU4zWVrMCe%0?+z*bbz)Aj?Ij#K*$t;qgvop_Sl^Q!C@U^N`jlvQzHfvlqYg{`afCX<1XE zwM#n~>0xmi?W0_y#guFMcOxBNuW-x8-Wu+|E-#aDJyDTL*ik;kXBQrr^aa~hgq)p9 z1KBtv^Cj$>h#_9m)M{N~mg~x2k;9YU`vL+Ks#|Y*n{ipK8p7B}>uUUrHA27|(E3sh z|4haI-dm9Vj~}Q!M>X~W^fQ2eV=%6Qf9b>wiu|a*4~|vOG8;Ml%_lAT8a1ZM5=uv} zxhl+>>Gc)R8&(9(AGr>iZ|R!4mB_ogj`|_chT(X5IA~n#g38P|NdM z4qDC9{42DdB}R0dPSbzYD4j+VCMr}%xdDvV`80VAz9o8c?o}%2_2#(6XXT#g=U$I#E~ZL0`6v7P^6-Yl7cv$ zFdRkF??0{sR;07| zoYQlQI6g6p7f;1;G?L@H&{PPlZmq^DQ`} zO-sg<`dyc4&feF7rhoWNME}>{kybHs0adigs)Snxl2v>@8!%{W1yn9whwS=UU#A9? zYXpY>hK*?b%^R1TY2imLty2NY8YiaF%<>M3)`{l9WmpkghNRLe!a-TwLZw&<%B(ne zb0sUKky~|C6SXuWhrZ32t*hQy*`!Tu=5_U2>&|+%G7Rg~c*knIDrc)nHw@@Lttcd; zus{7GY;S!NvdJvchYp~>w-@fkXK~QK1uc9*k;Mc?CKoXu%i|(aLL_<6yQT|m$tjFJ zzYimeS!(;PCEC4JwqLjv_uTb3rs$KfN%EyKK~vV0C0L20P$F@ZMIP;JpCZHUjJ5J!{CDJHLb>qeIpCSP<|>a zCe<8Mt3XLet{Y1onVvUXj@C8($lXh;k9A+FM%R8X|E;gEed#r{CEF|bUQseFAVO6T zqpJPuwSu6kn4%KDZ?PaU8Sr&$;lF+(e>+iIipAmz8opMI_cghE-HM!P(9V(&(F*mQ z&W7=&XEbaY2;l00dHSDnKr0hlXfY1NKm0ln&zCf{%J z`NG#rVnQW2)GT>ZSvIr&TEfOw;}bCYph1V9MzSs`ud37bT#9t?vdzeq{=m)|YOIH` zw#%zDdwGX9+;AiM`v=sqc`x~IamY^V*f{)t^sl-A5B%^>6y_&z@2pI8@MGBSL2yF= z@zgPBi+O5n5zI}^!b<=wfZy%`Oiu4bTZg#@r&82NMNr*LfA#Y?{M?J^dgljW_XhA# z(T&J=zKYAqV>lY~unm+l@2oYqxbc8Ohp22+=UI+Vu1K76hN;I{0;QVWD zhu2nuQ_CPRK7lz7LRsU|rjm2HmT6ViVE*Z!eJ8&9&ATxB{2ZEXF3b}|eIB>bF@y?K z6EMmOoD~q;bwnu~H2z&C*edPAPfpkCGBkrS?=>+F3=EOOCtu&!tHmV zn2e!dhJ2PR?Z>2VO1c>_!Eaei;}<^ofrkCVjw(H(RfL4raPrksjviI>%|e@s;#~!= zem#l+{ST4xQT+Y?`+@@YOV*IbpNhll6d|Cij{=#pWi}gTxrJMkNB3g;jc-@)L+KG( zt!Agy@%goO$ntHP31+%E*q2$#%9tuumL04u&b9sO^WU*Z8>EtEGCX~$)uSdkRo=C! zb(hUBNv$erq;(^X)%fg_4h;BX=x%l4n@=Zcd3WLNy>UD>cM-O=j^nz%Ni@5&Rm|r{ zv$TJ;p{z7ig9WOw7%hK71+48Ra91ri^?n8POC^)7(T%hsJZ{34!W#PC4DH<%D&?{% z#7ZXJSHqIjDFr_k9R5nhdSSP}kQ0ONsyK@1NMSI%+fy=ZCz zqBG>m-Mx6``Q4aJ+Ylw7b`WG^Yqw)?T?nU+jG%AGkI|V2N%i>1fUvO^O9;1gVq$hT z6;(IJ$%$8rE}4PLNM%cCvyb43zxg$ET>M5f!-uZpg~~C~-gdQmmPSg)>;QZjp1BBi zJ~xTUXeZvr{jtbA_CNCoLg6-akWLxgaG?U@^H+Dkz9o*Gn$D5Z)jY*e3} zLXjGJIZCS_;54X584Se)g+qw{dlB+#h~)`y9w(_QCvp>M=nE7ULgT0rLxJLKM?pdW zC4WvZC=(SZi8JN|ld@V%RjjH^&X^5cp&`wVWKL@_o0QgDPY=HK&2OO^39%I5%;33d zzcIhdx&`iKGhIS?spfBjvZaz6Lrq(P|4s_4#RCuHWFU&s1IKWDbOyihjvFvd3+-4s zOWMti)_{hov|X9+TE*{E3)sN?_(|TWXgI_x%g`&v{EXt2%70|mpcVMQm^_7BnY z#L`HUuJh9Zv)k?X?_Pw;iO1qg7VEZtE1E~fh*qN%=q4~*>tdT!PO|kHJb5BOCUX+^ z>={Qimcj?${U-d`-+vZ)TF@6>9K?gU)!3WbfbGp=xVVkJ9bXm`QJ}v$Z-#-Jd3yMV zt*BQ84a{#v_lRYp8=#KbF>bzFYoZrB@u6f6&ygCBkH73m%SSaY={_het!F z(_{mabgYXtrzY%>rPuv_^@ktnRHDL?tbtw z*hoc4#>Cd-gcDeOAvt*<2?ojJJ6md{blo`C=sk(>!1@1+zwJxonhFM zra+LzStyX~ZLKKMfZ(XmgmsVF_ zm1Lb%gqDiWPpDP)(X3dS<>l!Dst$6qSlY17 zqCX4)Dok9-5x|~F_UpNmcyZSO4Abv%)%qa*?KA&Dzn%j@nytaY1aYE?6loJ4E3HS` zwGo#GQuxa|@5lK)I^K7UP341vnf$B_BX7Nx0l-=gRRtN>TD=Z@DKUk2dOFZu*3EUGjOWoRR*Y7mc3@u4YMc6YtZlQiDX&=a zG(*dJ=^gRZzB$D6VPxV-q^W@|oII(LcTJ_|5w&MAxP|}~oJAH%#EM>0Ds(=g6*CJb zXgPQ=dh7&3ZDHb58i`m$T~pUhM?1B4S9=h?mNsM)QT1XDB?yiLR9m4M0Z`D5+R#X-Afb-&63bn({pcw+Y{bx-MoUwC028Alj{m)x?Xove?g z)w*0ReDH%mt3LIbZ+&SbIBNGbdN+;st#t0`9P!IS22XRnmFigg4E4oU?*z4!DWHa4 zL1m)VlKa)l3C#pci&N%rPaufvFFPOWdjmMOa|C{87OMyQaDHbWF1v6u4n6ZM_8wZm ziG@5J@5RbRmDr$3?V@W++W2gizpIS`saH^}%3Bm&BVe}by;3yEN)v>%Mt%&fQmIOR zu&9&T_;;8StOQu?g%~z^4&(bLvsk}s0Gm3>cTkla*(4TYF|^taVk+N< zt5=6`^G2DZ7(gyp#2qgdabzxl4_{kAf0Kq6CxQD97BE9Aq1~sUBcNk@zY~|P_Lxpz zvrQ~VYb9#Oz?>N>R2{SkM{;SD+!WpmC8Q~tj*}`~6KugP_BOQ1+R1@^gn3$YK&g6?lOU>ECaFya%h(wSmZNbd( z5pu}=C5@lfpiJiN2=;A(HlG#Ja5)BR{#5n_M)d%eb;_n8y{6m1P{o_rP~u zkoe3ROG5q=YHcAyUrx}4jT<+pa9dqRC89{ztYN5IVxSVWp;sV(X=ROV=4@Lmcj#Ln zU)vWd+jKJtcF;`o_2UXH_i_TXC&>_mxvG@0o5;;AV9=Ai(#^!adTB97z42w7++l@%+* zpnN`bZ42IeSqSYx(|K=H!7wb#hQO2X-XF{^;HSIV)iZ=O2NejHO2FAmi%q&)k(NZe zS z#nhXfIu5?@9Nu`-TX5S@2%TZ`{+f1LE%{tQw$iqzu?SwxQh(pmY4xWo)oW-51yg%H zbF+D1jhe&5TdyDq$lu=2cE^z*(mm&ieTm+zJydkwBRVzyVlUUuA1ydk}ln=_l$Ob1Q8SiL0V|K^CEF{nt4iA}p>XT2-N;g?y>4yYYVXxpIWkggSE^$6 z30cf%&tyBk`S2u$T5WjXk;f_G-B{ZZpsz{%A8rx^B_uszTzkV!xaQVd@%(rG4R<}d z2OIi3aQiiz@chXLV#J!&z0DBsR3PZVKi~NrCT1h(ln_#vrdD)IlW~w$+hPg&a$Gii zYmXOi-l`i;Kbuh}iA>8k6}!OGUrxhP&QDYZiV0DdKasu-E4huxtZibYwEl>@OL;fRo>^6XgK zAHd-Q$LPe;Xa!`*n+KH1S1!{0rsJ};t(hPkfWsZYO*h=Gu4!-YLF-@tCmfI53wO6$ zjo5JK9GZJK!`3p2j{n`Q=3@%2V^Iq&<}~Rp)_*lW!+hDpmtBh0bU;h#q@Umo*IcCD z^?_Zx5!F&~tXe~pF@h7{{#TrEhOoP@7w`PXU#mWxwzN%_nB;Z8&twU_lI2V@_)b^q z0logaA+-Q3(@JbwZF0Mskjx6!7}}GWT0})sR452@!j+{h8|gdb#4^&|TX6{o`misL zr=Q-53~3x&Hi<`{n!pcsjbO*xel$t6gfm7*Ka2^2dNmVbgxbB+7sAGiFNeh7iv!zc zB}ucUy&FN#tpZk4AuReXG7$S9kTd&5VyXN+ZoyYS`RB-_(s;v_TX5$SNAaB(CKaZ}(q**h88|&fJoMB!TFISX zw{;K$twDIn9AwGyN7+G6P*HqlbPjWiY3w=WKr|gjQ`lk5q$NHr7P8nKO{1IJ-Wu-2 z=N2a5o^ukHJn(u-==3`YwhpYZw0j*!x)+eGq5rl-+1Fi0WN zg?6Wdyx`q%H}#-raeUczYTKt!D&XYYNp_-BNMsTwCt0KQ)tzhgk6KNucHi>zmR~_@ zu(|q*w93Dh^KI#IT8$Q0cOk8MeT#4PIlbs_8NjNxRSgHabxmP>?V4VxN4auXRjb#n z$t)F+ftjzUTxm1ozQ%p5bw`m(p_v2r!Ke0MY-?jvl_-=5EP=q_i&!z|~p>OSDm|Ev zza`(%Xu*w8Q*)J$QUchTd1_9?<8}8Ro4|ac&`{{CM8_!LuC*v?0bQ)=FqNm9Zo)5o z-~*_2h%apyGXtfXHEyTX<-|Wf>cYfW0^Kb-o;|Vvr@skBI!McTvDEEw`&x0u#apmt zQx8s_IE5!3d=zU4yn{Q2m7>-hbfTl+#k&4B%*V4hH6Np2(1(yef$MskaQ;viiuoeq z>_d5134XS7SF@iAsU6?mJ%Wk(6dpR9#!p>nQ|s$WUH8*cxU?;VU9kjyn4QDsQWK)> zX{_%8+RA=4BR@!s(r2r+S~X*}HqBhWz@)5nbH+OAExDTZuC(JhX!lZHkwwhUR_i}q zDbmbwdNRl^F2GZYAXiQzpOM%I5Bj^C3Ghj*Ueis0ZN~Ui94;3fx(PR2z9KfC*N<@P zc7(%T?Av!Ij|JZQmXG4qC}Jkg&qvhE(8;h^yCLji4t8G^o4Hw5)0r9*dZ%99!w=m4svFEwn~Lts3T8vSlziHjmfed;|7A z_Y9uja~!u`vkhN=co#+p{^?W_C*~5EN@dlcQy^zb51BltIsCZb^*56`D5-4xhm2RP%z95ymNkgSQ z)T5V6%f~FVW$pS>wES1ZX{*fXx?DQvS{aeB=|mEad>nd_jn&@^S0=|nnL>L=$MXjh zq+7_<+r3CfIS6eDoVT_UtIzYo;Y(m-{1~QoCJ{*WQRCl?SF2=m1x!$5%*P{Y6)6FI z8EBDMin^g_hGjfDI)mRvHA=^7H_0vY{oOyrV#-KGYmw3owe(uRHjk~t@Z!#=@%2ZZ$L*JGKu3E}sm3zEPR^z=zLa~|LO93K1LS1T5S zUc)JNHzH)1IZRZUo{drumcQYpqeEvs}OHk%Q_rfJIs5>T}S)Y`GO5?%`Rw~~Um zq|Nv_cwj&N^iTc>fBmVf7S3+w@(ujw!eRV%B zyPzNQlP55?XA&1~-3CV~h2;1?>^poAi?fq-+Gf<`O!2|_NDmK)GWk>%0TglTb(i7P z#0(;{9N*N)C4=qJxfq_L;;@j)VJ(lnu)hU&9h}0k>9n%)ZG5jssl=`I`Ea|t4PTm^ zC4Onh^1&|mHBsnl%0g_nxe#{R&52#cY+>UO&4?f64=^l!^|7qA)3j|pm3lViWyRsw zYp}KDTs8cjt`3xAkHM9nqrlYB+0ufGF24kiKlB)87U%c^QZ(1xl*9|jrSoWQ*AWOO zaA0p1qa!h7Xws!J8q#wk`0y{@f>*0ZTI4RIF;A_~>vkeaia?f1?CxquXM2lU#5@r2 zSB@{&@WT7p@fHb!23S@H;gV7h^jJxo*J=+(<*bI<{L(AdI!%{dtp)&=3K(rE$ZJb4 zpw-pex$ay{o)(SpiSgH>kmgg|E?o)lWnFHkPb3KyS(2Ox#n7xNZs$ z4!&$t3tBune*3+*(){;g&%P6wjV09mMix?PQJ!ivjTH)LT;sCqu7{giTS>EHX^X7P z&o>%?CT>?I?o=$8dZA$c{p1h74qJ5+aiz_*3NqUa8UQc>-Fjx!@Zd%&W&sd8`=45$ zK!dSnfJ)S5EG?Qzjqjytn%Y{IgL)u0dLWXq)S&(KWaT@ zc}Age)IvuvoVGA!xS7b!@`b$8{=1hIhri63WY{W8ww-PHz2Eo%o_X+Yj2$b|UtU(G zq%0WTO{x0ei75p9Er>6a;R`Jw&?Ft+g~Pi77#o=<$R<_%eSi*=4RpA?_r1S@SF3pF zbjbu;;R|Rg#eg$SFT9f;eoFY}CO?WapIa!bYPEaodvtNEG0@k6@-o0!QnVT%&{jHV znUK(yngC0#w)9nL%kES8GJ$o8wV|zGp_u!m2)#4hx=Q_)c2OL>I?sls)`SIz){Sbe zTOI$krpJ;SDx9=tM)KPpTtzyt7c+Bn`1Z5A@$l{wh-HmrR;6;SP^r1N)Q$d_Ef-&` zZfYjVHLkB&cR@{MmcO%QMXMfbEVEZVr=AXtN9HO3CmMDr+=@hW4ps^QHCfGsdjr_5 zi9l9E>6Ofm;$*I*im$v+YqF3@D(D7pUr#Gkp2=ok79#j^N@F@gQ!{QQB5w)MRrSJN(VV=%eF(`?j?>_QGR4zl^o#pAT0cjKeQJjFTsiVmg{vns^)O z-tEI7tm!Hv?3RUsisbL-5z@Ta+SNjZvkgwYfS&Fyv^d#6Xu0=v4IxOayp0N7D;+2U zbi8&4T-e;xgtTz~DGy%PtKoBtqj-ONFFrpqhp+kP@Q(gwT(riG6Z8?KGB&ik99Si* z^oj7&jd?+`8doY)#t#lP;n`C~tnc;WgBL|A-Cku))t5)~oxUBKwAgPmi{BD&$Oe?w&nMykPl)FSyQ zoY=haQna^s;MFSY)~`cHR}bQ`sLFwp&J>i?_R$F_n!X{ujbkgJbrz*#%@||}cmrq+ zw5V;VTv~PPTrr1C-dF*wA<)+ehWdl*wd^IpY#v|5>{@}Kt#F_EbG0SlQm@UU{+j0Y zY%x;-daGTm<7zDj&7>&QBqQruRuqF)HZN~eR7CAL7VK8Lp8?TFjvv8;U%P`2+XNC> zwzI4U14Dzd9G%ObAMlc1Y*Q(n4RE$K1a(vMgjK(#ZMeMDQd3o6T^6|_wKqGEhnnN9 z@BiP}|LlXvXKBHbMieczwX>Ul7f_(XUm{OtP8~JcLs20{qZz5(?MBvBalC3qDqyX$ z8ktRL+LrdO?kzq8i^H$9sa_X4dv2xPp<5MjRSm!LZ5~tk7!PHfV>2ue+0;f{c-POq z8-Y+ejy-WV4nOk<`a7GkP;%fq-@TJhokgDJUMg3jgEok*YrB-Qw#^tMvACEw}_k8_u$%VFCuNbi1nS^?sck#bY%I{vP_x^c}WTB*sy&7 z^DSj;_XY8h6VKoe`&Q#)Pfj9cPs1J~L*Wgh)oq7M*4Z#ECzX3&eFNXwi4Sx6cejh*h-uEy$ zIe|`c_woWoyXfj^Roc>${4plCYWO&+cDhWa36tY%_BSgZKq{M5YurA4^y%8W;q18i z(}R5Nxm7c|uJhCYZ_UHj{ajAjRBobG>r#L9T8prD(5v-sZFSeFal9IW$+kp5DHyY% zvLC34(_iv5qy^90j6(Z5EY9quvpub-5X%ZcP5gZA1w_!u1UtLRR;elOy&?cBG>(oc zXKo1i+L(2Nz0sD`NI!$+TkFWKh%f@vQ}=ugO>LcM>FmY$k-gaQ`rD9Ln5Fy3kB**x zoY?nb1By;l5k1j>bZxc%6)t79=Qd&>` zF_opVe*pSbpF(oy19;>c|A>uidf;>0@W{al(2tD*51NV=Rmy}+zKC?mg*W(P)as4& z*1FpbZD^2`9~Cq`1l`w+d}}j$3HCu!LE-Qr_{+x;3i!y|r|2K>(@9LFj_=b!N~TC9 zufy-c+Erfk_6IOcW$l=@fZx9KX8hSBkKkfj`sbb3gzv{@aL3pjHabK2g`OS-{E}Er zg!xRN14p&XkX_S(H?1ktiikst?ZGl+{CD|7DVH?w2Ot1rGqiZ!d}l@}FBL4B4HciR ziPOp=Si*(FJm0uS<63$(_M=r`q-|gu{bqK>aYwCd1qM`)1bv_ zVBK2eL+CA=kF?v!fy|^}1%N zG}lswH^0kKF@`9wS| zehjw-anl=nRI+So|-&@R4k8Q2o94Hvg6tLGDIyE~U|ADk+r} zeQGseYoDe4Rm|L4jjc}Ws@byaCD)#|1caABRNZlC0P^)t##h8PnGs1EWNaZoXP~xTn^9fKY=T@xsalu?|a>q zm`oP%BK?EAr(&uO@q!Iqq6id=C^owh9&%zKlSPC){fSrvYg>9$`i_#*3vVchuf(P? z5OLvMUG4BH)5M??4`esO?Q-JSk^NY;W*z2cr_{O=3sIdGe;3YgnO199XjnlKR+?og zF8oLVzhQYPD#1^1u|Ul#4IM04-Yi-JO?l~cYxdRLtL`GF1^MOosk=BD36teFSbmRX zcQE&9wWk?cvaT=F@>NnStp?gGRarwt%dG4>Lx--VTk1JagWJ}zmVE5iYcIjn;TPbE z#Ay1vaq&ePIrvUu|40(gO(c;hmDT#l|M7{xL}YRjm%ibh2(`5u*EOH50>Ud6eHo== zZMOuVw!-;KQYFYW>`KS3giuz!dN4q_vMw+TfVbI9JwjK)N7cc|7*ii`cYbSgnAz z^T;XmY&Z{FH?BdhRKUK8IgHXVo74RSOgpaF(MrwSj!!=QJpTNqYjE(fD00pyQj0|l z_lI#2DI+`j@%WQ_lp^6bU*%j(vSxdb#W`m1saCsc z=m>S7zinWtB`&Ya?JJ8d20 zUiF{l^<24Fwt*b>mS6mR1j4Px?_c_Ttl4@w-u~-amx+;iu8wHwc3*HfDEPmW5tJIbD9$jp*(hSh1d+ot^mN7r&@}4-5?8)1Uq{ z&bCBI#+%_z++U~F^_Qx(iB9Qet?OQ<8YSJrbVMwR>fMeXfKULc}Y<^^<3<0 zluor&Ol1q~muNOxjV7%jNbr646+cac@R6aB#7mt&GU!rE#-qeJEy#Slnr#R|xQ#1P4G~vK_5~K07S{P;c znqR=)@I`1kuOA5qP4R>Sd*=%9=n<^%3}U#)j)1d4EPmq#tANazEftva4WyKD*&E-9 zXYTnrQt^3Qb^Fg@|1%F^hT!0G`*F*Mehaa=8N?Q5=+y1Q6>oYsHeGxz9{tw8!$xlU zx_5pEqlb6nnS1ZRMK`?-J;Uqq!u{XEjX(G6IJM^z-1*P{7y4`lmtK7{0)Y^od-6eC zck^3`TLnD#)Wf*_o$tf3!+Y_?fBGxjbn}}quzou}|M}08Hy_7GKJpRe%i6YWo2qFn z7Q>-Khj8homtw<)4HzCC#wR}U2_%!r(?2gv-CwJ1sygnU`swU(5~k&%9QV4?@?9=! z`RpP4_8h>Cm%fVvHjI|;LClOEhes>I*G!tm_}OQY^W%!zYYI1`m`TCo z^i0VHQ#G&h@Gql^;(>S%|Wku|v9U3wIm}GY zVEu;m_;D>uwbtd&W0|N`P1)Ff?WSu~DCSq6{3=@MV7zSYrRZwzQrEa}=tAU6c|39C ziOTVkN9DRr*CFf;<~~eB zCe*&}aJS0kbMdN+acJrwE?Ipkd@e8cj_<>%`IA-Kpy6xLDq4FjCRc&J7O<N|x+SjRQ6Gf`h!RZXRDJ*T+6UpP?A~4hjZ00#W7oW#oeNwCDwUx2e z&DK5LV=3Q;Zn%f#uwVbXZ=#sbqOE5L&28Pd=*G7q&?f0b+K|s?vGKC&urM_Shs%Y| z!8N#of?@l$Z^n~%ehxRj=hsL(>$v{iAHlOf{0apF1z2Prk-14)J1JR68MnRj130+n zITiJj&1EpSYJ-wb(dYsqi}M&*y&kvoI-mZhf5N~2`@iGvyYE&&|Mb&OS91F_H#g(w zfBxs;C3x-Fu>+%{qxjH=K7_yh+rI@)<9yU=DXgVCYF?yXd7(oC-8ei+Cu%ZBOVx>h zCuJR_sE|@2M@M!6UWq}X1uQvnWQo)1F%%%jKH)FSSCI*Qw`Ux!aT_5^-@+ZJ@VviRiv&!Rvd z&}X0Bg{{M_=yTI|Tox@}S84Cl`4SGf<8V{quyg!A@bJU9@uoMaXg!I~cYFQl^3NNK zr)y@?BmI?k+MW}ovn0ae|7Y(l!0fn=wBfh=GR@rK(TqmSOlFEPapE|(D9T`1>KR@|rq)AJ;eBI^f8SfGN>lGWWutD#_;^O5OqcPNAQ!?eNv}hYeW9XHXjiy;tPc2GD9l{v`S=n>P{^xKaR?tO4OVcX< ztluHCT5^O95ir=9G4K#+Zj)PXLn$^6Gn*4Dq>C;;>Sr!Qq$x_;^Cb2i&S6*6C74+I zUg&GiLWF?DG`Q@fORW5Md5FEG{rru71Y08Twbf(H=fiUa6ZafVU|07j+-_GDm7@zy z&ZR4@-SIbF6H!72r_wEpx*vSvE%?e?Uxv~C!?0EvdkM@AY<&WUcWzZr$;7rt?m+i* z8xagg(LQGpy#6qDK6xK{5A4R{H~$(NUh#U&n70^dy5B?FHwkAYuXIimr~KF7{{)>~ z^UyhSE?GQ{ND|e-YhVuU--+h-4&-QC&g1jG}KtTwCJaX|d&?JG@J`3w!bp@V!aw}Y=9P*@$ zK6&6M4oqgSXEXsH=P$|-^+VRe#^*+{W#}B7HshVxIJ5}K%xVORL>&>B2gy3uVjdhG z)8&+itrJ*S+^TEL*-D58Qu07A#nR z`|i6R?|j!g?R{3SSxp0nxUd`kBDDVf2livZ{Q39?(jHig`0;s16! z7R6-)B;*ue>ZU2&B;NDFvbKgclK8p^zgyV8koOYWxTOU*lNI3i__1N$28<`i3Ah5{ z`z?pJAVWaDZr*zG^veWPkL-C^Y|9#admU-8E-y-SzBpqauW`E>I`( z-ULX~XRBa}CU0FZoNP_``8w~ZVh4L4t){QTIYykx$jYs@#;i?=-B;((BqtmvjlM6Z zVIa?`HsV+~v=tYfyAXxc2uifC+Z#rdKuaS$*Zl=N8(E7-GYuG}J}IO}&~xvDXj-!t z4a*nN0SmNUNNR;1uM#$#n9M|5U09^B^aMQE(>;XZo>8n>&`JWL0GaN<%AZqt{Zl`c zn-mOX=OWWJTvInkns;n$82MaQBoBM&uRp^-eECO6i;|rtGRXviQ4u-%jsI@?{uglW zRqr4NVG@tt@<*(>;Bo=<>hX%-bI4Vw8p!3Y0zeJoXN9Q@P zXFJ~b_7CDaU->Z3zTh>u`s%Ck;DZn1H^2Ff_&a#;AO;5q#dWg9&a@6wIO%j6S+YEi zP3Oq5CB}qv%vio!+i9y-0*mn^W24-fA(R;-pM;e@8zRbz4HmbE*lBJh-ab`_{Ny-M zd0w*Sib$j~=-xYy@qr@FyLujsj^Y03BLHPZ=fUWMSF7#PFdVV zcyky{o<{N!nAkj?K#+t#TMg_#8z0rt5b7e~(S}p!o<-v$hqO6}0~4E2Pc#m(a6pir zO-83}Gz1#**tP9xj1V)sa`8OOr!knOK5A%cglpF07>JkfhwNeeQ}Ys;4z;?+rUCgE z0{$mFO6OSG|NZwrfK)1tPks7RUSe*UwcVfl*X2nK_=>WVAz zm4E$;*ypJypTv{&*V@{K#~*tPm%aKjeCl65C4>YEi;FJ05W~X>T=|+SuzAZf_^)nG z;pcS7l?QAkC+P&zr}jOCbC;b%mDm*IZCuq z0mF$Q1U*5FCPpiK4C>7k%Er1E_48EpvIT{Dtr`+#TE~>D3a$J!Q-It$u!&0Gm(IuX z$#uGagS2@a69t1Nw=Sxtjc?rtzmY+-V-Y$#Cy`H0z(-oTNM7X%;IZL4+&i`iqglF+ zAPL|35#$p@7Z8YzZ+(`yU+SwfSBp9gItvF<)pU;F(DWJrUwe`YYC^Z}SHm~2d!_C0|N6UMPQa1J{%0OV=YlmtacVXD(P>JkTYglV7F4ggONFJDL_dNRAk&cb%$c^K-!&yP_?lUX;!x8i zD^|coR*63n#lCF^5Qzj)*HlmUl7Jpd;F+Vd$S)AW$}T_Z!eJUe1(aysjT80qi$C0k zb5}1CilpDAi3MG$Y*FOGX(le;j3 zlkv#m!?@%2JH+u4A7geLIK#fY`H}^W;xZu zn%S$xcL#?Lp)uTmWHyQYL;JCT{xLOkaQGl%q>c09typFfGe{8J{_JgHJLdO!@*f&G zC^-AJ`Znz8-;HqsJm&HP-XMWh7J6YFNLCz>dX?%@M6^@BqAis4fO=qtWs_ zd@pTOOlh)+xoPiNQJBLP8HW9P^&zY+vV_JD4ULngRtJ~g1DEN>#FkxXAqBiZPPJ!9 zd+(fZVNE>&qQ^vxoPIYS37{t#ge#mU%gKY$;S`;pCvcoVB7ziIOv&y&WGN&t=jG=S z=zHPu77=g}XHRB#3(+PdVo6|n1V=m>C%{O@i7qhk$3Hwr{PhN+fh-F}Lq+7tF`CqR zH4#_OcV5ip<*Hv3Lc8ZaVm|-Cvrmc|5)3#KLwy9kGK~UT6^4kPCrT@w6k0Fu%i2F{ z_?Ey-5I=8G;|!A498M9vBlEJ$YfmJ`6`gF_V9za+$xOL+*6OFdFRd)RCCh0$S!!-8 z?!n353tpRO6<#RDg^>tsJ#Lqx_BEM5$dGFW!u2!`2*5)vZMgH{+tAX{jv_sqL;VTN zhIP7(fKAv$H}_WMISc$mXPy*754Q$hdHy|H0Fvpw68=~ zPf?_{K76E?tfK+sNI_ZGSs<=|CXBWOc8|sI$HD+Yb6U`K3=ps8@GJXx`u3s#zh=b6 zakST5aRt8ljc?-J?|PST==}N5e@3LP4p+VQwfMpJe;_p7V>K)37PncmX43Y-$_3y%N`YVroO+@Pq(w_yqvGjz!^OO6Zs5sE0 zdmj;RxA#0}pXbqikBZkKX?YLreF%=zigxeLyKP{9;=p6at<6_`EkOdP)aD%rvM#ea zQpbAL9pQswf6eh8Wi8inR7aB_S|lJCBalmy^D*e-QkcY_KD3*hc6k)(y+IDkY$}FZ zx`WtRoJ7XoicFxD9C|cXym?tNb0SGjGcUcSNn`dP9g8E})`$#q{zOj?}k=~LxbIsKJyMEl&uMCW`_9RBiu{4$=t>joU$y$$S(u*&ut zV%eB1IIi2t=E_e{vlqarOVwYHtM7T5)d8|EG}D~o(~$J15|XCFvSVRa$VUTc#JHH28@kQU}Q2*Lb8A# z?ij%Q7B3$799@Uoz*ZWMn~$c@PWR<|p5ElXa^m9iwU?A0x%$2HB5E~`xViVf`|#;c zeG30Vw9MSOb8yQow}>#Vv(7#XO^uBrY1%pGoP(L<&^?v-H3svsv2k?G>ca5Qu(-L? zPdkks>U`XM>#g|w=RPNn{hsUIi~pO=8F^wgO=-5yia$;bI^+w>ed$jmO;ZkE{*C$f zB^^t#?dY@i@i=^QZu4C19@uS1{gj&nWKlcHMsuLBQ}|T8t)Ob0?`!;yDzc)+_R^{A zcwg}fXcfgk)Ej{^5+pShS718tK^69xTOP+fzyCfiecMN|c->ie@P=Pt_fz-b;%oj1i%&Th z_x|qtBAFla-D_TUnRqU&`Lniq?Z5mR>KahYn!Y+<64_!-ZAJ?cM46p) z{$&WdefZtiKZZLt6>vu=MgEc_nAILdOO*U%$u!1E(B!FKC+Hclb9Zr@4--kEVVhhy zy*YwYT@j4ep2YG+;jS|w;R)C9YsK9kuXb;>CG-Gpy!j?U!#Fki8~*Ya`~97F-z8pO zap^0>>s#OUwu)o?;ZJ|G-#`55Bly4Bs@EilHZ5mesV!f&?lLron}zv$bnGbZ+IFWM zpYA6I>e9}o*gLqFc;c*h&g@)0cj~{;%1ZNv}}vClO~mb_na%qbw{A=E~1WJ+59#=1)S1WAa2$WbqpHoBZ4kIlpe%H zAMHcOs%!8geULncMMwB^aq9xs=eHYDwhyhQKCim>lew=;! zT!Cu(@fM|q49jCm&P^7|yT9~f{QCcV5ObGrz$q8M77JFLhMRu)WxVT4KgC_45LTUg zDQ^7k=kd`W-HN}_>+B_~F?-P}{Or^3z#BjDEdrW@V!xk#@-6t_4{jAs+qT&Y@!;>j zjqCp7CgA^k&VGzm58LZ*tsg{5NxbAX6)KdeV?ADV5f#8?SkIqJ{}F$#`^75PVh&~N z$&?Goc&sp~^~C09v4TJ|N@E~78NulOO*8GwM93_iN<*&0>PaBu76j>k7k1 zio#p|y$82^ZVtj+7;8H4c36i_N=H9VE9@mLymGc#n|C*gLQnuU`9VY?!+Njgcl1n#oZ&974&FHLJT;V}9FwJ9RSe z$+7oyNZXHRTdR6IRqLoB-(`D{X0aQc3nd=X_Mm^I(mRR4}Joc0dK zODGA4E%!*#^dOT?34zE}tAul#!Csd|YDV3}5X>~uLVk@p($s^kCid(*gxM|iFvtncuY#m4KJ zBX-@oF7c-{W$X89E5QC9aK^xrg$=Kh<-IQsnWAH%)B{SLN1a5Hk* zG(Pc*yK&o3zJ~FE9{TQ9Jp9*R;*x7Wh|xZ}*5o7(?RZ8!l%BoYaCFaB;{Nww)6jw*QYLQdkJldvk{f_q!q?1-|J#Al2mOu^2tq(@)Bg?I0%6& zeH(6~>-{8{-SByd$|K7xPvF|t+Kd)*s-}uUjEH+2A?IpSORKC8O#K`uM}2~xEeFfb zBZuy$r#E5iwr!Yk-pjD^b+5&eSH22sUhxXdUb9ZDf-M#b;+4nlOcDY!+B?vDm;}Y% z=P)sR1cweD!0>=+*S~4wCM;jR3~zYj8}ZxU{6-w3L=XQR?|eJ?0M5p~efx0Z z-~J|!_2##{S(s~^Hf=(RBsfo=x4+{ZLO}faPk$!Az!h}wp$KwCIK)LU5#C6q3_%@@Yl?eK+i(MvLKw)iv3cd%~xyo z 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
    */}
    +
    { contentHeader } { content } diff --git a/src/components/views/beta/BetaCard.tsx b/src/components/views/beta/BetaCard.tsx new file mode 100644 index 0000000000..9516ce975c --- /dev/null +++ b/src/components/views/beta/BetaCard.tsx @@ -0,0 +1,60 @@ +/* +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 React from "react"; + +import {_t} from "../../../languageHandler"; +import AccessibleButton from "../elements/AccessibleButton"; +import SettingsStore from "../../../settings/SettingsStore"; +import {SettingLevel} from "../../../settings/SettingLevel"; + +interface IProps { + title?: string; + featureId: string; +} + +export const BetaPill = ({ onClick }) => { + return + { _t("Beta") } + ; +}; + +const BetaCard = ({ title: titleOverride, featureId }: IProps) => { + const { title, caption, disclaimer, image } = SettingsStore.getBetaInfo(featureId); + const value = SettingsStore.getValue(featureId); + + return
    +
    +

    + { titleOverride || _t(title) } + +

    + { _t(caption) } + SettingsStore.setValue(featureId, null, SettingLevel.DEVICE, !value)} + kind="primary" + > + { value ? _t("Leave the beta") : _t("Join the beta") } + + { disclaimer &&
    + { typeof disclaimer === "string" ? _t(disclaimer) : disclaimer() } +
    } +
    + +
    ; +}; + +export default BetaCard; diff --git a/src/components/views/dialogs/UserSettingsDialog.js b/src/components/views/dialogs/UserSettingsDialog.js index eb9eaeb5dd..0cee622fdc 100644 --- a/src/components/views/dialogs/UserSettingsDialog.js +++ b/src/components/views/dialogs/UserSettingsDialog.js @@ -125,7 +125,10 @@ export default class UserSettingsDialog extends React.Component { "mx_UserSettingsDialog_securityIcon", , )); - if (SdkConfig.get()['showLabsSettings']) { + // Show the Labs tab if enabled or if there are any active betas + if (SdkConfig.get()['showLabsSettings'] + || SettingsStore.getFeatureSettingNames().some(k => SettingsStore.getBetaInfo(k)) + ) { tabs.push(new Tab( USER_LABS_TAB, _td("Labs"), diff --git a/src/components/views/settings/tabs/user/LabsUserSettingsTab.js b/src/components/views/settings/tabs/user/LabsUserSettingsTab.js index f515f1862b..98148b19e0 100644 --- a/src/components/views/settings/tabs/user/LabsUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/LabsUserSettingsTab.js @@ -22,6 +22,8 @@ import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch"; import * as sdk from "../../../../../index"; import {SettingLevel} from "../../../../../settings/SettingLevel"; import {replaceableComponent} from "../../../../../utils/replaceableComponent"; +import SdkConfig from "../../../../../SdkConfig"; +import BetaCard from "../../../beta/BetaCard"; export class LabsSettingToggle extends React.Component { static propTypes = { @@ -48,14 +50,40 @@ export default class LabsUserSettingsTab extends React.Component { } render() { - const SettingsFlag = sdk.getComponent("views.elements.SettingsFlag"); - const flags = SettingsStore.getFeatureSettingNames().map(f => ); + const features = SettingsStore.getFeatureSettingNames(); + const [labs, betas] = features.reduce((arr, f) => { + arr[SettingsStore.getBetaInfo(f) ? 1 : 0].push(f); + return arr; + }, [[], []]); + + let betaSection; + if (betas.length) { + betaSection =
    + { betas.map(f => ) } +
    ; + } + + let labsSection; + if (SdkConfig.get()['showLabsSettings']) { + const SettingsFlag = sdk.getComponent("views.elements.SettingsFlag"); + const flags = labs.map(f => ); + + labsSection =
    + {flags} + + + + +
    ; + } + return ( -
    +
    {_t("Labs")}
    ); } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index c6f7a8d25e..857c1cd568 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -784,7 +784,9 @@ "%(senderName)s: %(reaction)s": "%(senderName)s: %(reaction)s", "%(senderName)s: %(stickerName)s": "%(senderName)s: %(stickerName)s", "Change notification settings": "Change notification settings", - "Spaces prototype. Incompatible with Communities, Communities v2 and Custom Tags. Requires compatible homeserver for some features.": "Spaces prototype. Incompatible with Communities, Communities v2 and Custom Tags. Requires compatible homeserver for some features.", + "Spaces": "Spaces", + "Spaces are a new way to group people and rooms for fun, work, yourself or anything in between.": "Spaces are a new way to group people and rooms for fun, work, yourself or anything in between.", + "%(brand)s will reload with Spaces enabled, and communities and custom tags disabled. You can leave the beta at anytime. Certain features will require a compatible homeserver. Beta only available for Web, Desktop, and Android.": "%(brand)s will reload with Spaces enabled, and communities and custom tags disabled. You can leave the beta at anytime. Certain features will require a compatible homeserver. Beta only available for Web, Desktop, and Android.", "Show options to enable 'Do not disturb' mode": "Show options to enable 'Do not disturb' mode", "Send and receive voice messages (in development)": "Send and receive voice messages (in development)", "Render LaTeX maths in messages": "Render LaTeX maths in messages", @@ -1254,7 +1256,7 @@ "click to reveal": "click to reveal", "Clear cache and reload": "Clear cache and reload", "Labs": "Labs", - "Customise your experience with experimental labs features. Learn more.": "Customise your experience with experimental labs features. Learn more.", + "Feeling experimental? Labs are the best way to get things early, test out new features and help shape them before they actually launch. Learn more.": "Feeling experimental? Labs are the best way to get things early, test out new features and help shape them before they actually launch. Learn more.", "Ignored/Blocked": "Ignored/Blocked", "Error adding ignored user/server": "Error adding ignored user/server", "Something went wrong. Please try again or view your console for hints.": "Something went wrong. Please try again or view your console for hints.", @@ -2020,7 +2022,6 @@ "Space selection": "Space selection", "Add existing rooms": "Add existing rooms", "Filter your rooms and spaces": "Filter your rooms and spaces", - "Spaces": "Spaces", "Direct Messages": "Direct Messages", "Don't want to add an existing room?": "Don't want to add an existing room?", "Create a new room": "Create a new room", @@ -2451,6 +2452,9 @@ "Revoke permissions": "Revoke permissions", "Move left": "Move left", "Move right": "Move right", + "Beta": "Beta", + "Leave the beta": "Leave the beta", + "Join the beta": "Join the beta", "Avatar": "Avatar", "This room is public": "This room is public", "Away": "Away", @@ -2584,6 +2588,7 @@ "Error whilst fetching joined communities": "Error whilst fetching joined communities", "Create a new community": "Create a new community", "Create a community to group together users and rooms! Build a custom homepage to mark out your space in the Matrix universe.": "Create a community to group together users and rooms! Build a custom homepage to mark out your space in the Matrix universe.", + "Communities are changing to spaces": "Communities are changing to spaces", "You’re all caught up": "You’re all caught up", "You have no visible notifications.": "You have no visible notifications.", "%(brand)s failed to get the protocol list from the homeserver. The homeserver may be too old to support third party networks.": "%(brand)s failed to get the protocol list from the homeserver. The homeserver may be too old to support third party networks.", diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index 2a26eeac13..99f0ebecbb 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -16,8 +16,9 @@ limitations under the License. */ import { MatrixClient } from 'matrix-js-sdk/src/client'; +import type { ReactNode } from "react"; -import { _td } from '../languageHandler'; +import { _t, _td } from '../languageHandler'; import { NotificationBodyEnabledController, NotificationsEnabledController, @@ -39,6 +40,7 @@ import { OrderedMultiController } from "./controllers/OrderedMultiController"; import { Layout } from "./Layout"; import ReducedMotionController from './controllers/ReducedMotionController'; import IncompatibleController from "./controllers/IncompatibleController"; +import SdkConfig from "../SdkConfig"; // These are just a bunch of helper arrays to avoid copy/pasting a bunch of times const LEVELS_ROOM_SETTINGS = [ @@ -117,16 +119,32 @@ export interface ISetting { // historical settings which we don't want existing user's values be wiped. Do // not use this for new settings. invertedSettingName?: string; + + betaInfo?: { + title: string; // _td + caption: string; // _td + disclaimer?: (() => ReactNode) | string; // _td + image: string; // require(...) + }; } export const SETTINGS: {[setting: string]: ISetting} = { "feature_spaces": { isFeature: true, - displayName: _td("Spaces prototype. Incompatible with Communities, Communities v2 and Custom Tags. " + - "Requires compatible homeserver for some features."), supportedLevels: LEVELS_FEATURE, default: false, controller: new ReloadOnChangeController(), + betaInfo: { + title: _td("Spaces"), + caption: _td("Spaces are a new way to group people and rooms for fun, " + + "work, yourself or anything in between."), + disclaimer: () => _t("%(brand)s will reload with Spaces enabled, " + + "and communities and custom tags disabled. " + + "You can leave the beta at anytime. " + + "Certain features will require a compatible homeserver. " + + "Beta only available for Web, Desktop, and Android.", { brand: SdkConfig.get().brand }), + image: require("../../res/img/betas/spaces.png"), + }, }, "feature_dnd": { isFeature: true, diff --git a/src/settings/SettingsStore.ts b/src/settings/SettingsStore.ts index c2675bd8f8..ff3a5371b0 100644 --- a/src/settings/SettingsStore.ts +++ b/src/settings/SettingsStore.ts @@ -257,6 +257,10 @@ export default class SettingsStore { return SETTINGS[settingName].isFeature; } + public static getBetaInfo(settingName: string) { + return SETTINGS[settingName]?.betaInfo; + } + /** * Determines if a setting is enabled. * If a setting is disabled then it should be hidden from the user. From 46d35411b4fe9b538e0003f433583f0733eebc6f Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 27 Apr 2021 17:01:22 +0100 Subject: [PATCH 0091/1449] Add animated mx_BetaDot atop the legacy Communities button --- res/css/structures/_GroupFilterPanel.scss | 6 ++++ res/css/views/beta/_BetaCard.scss | 33 +++++++++++++++++++ src/components/structures/GroupFilterPanel.js | 9 ++++- src/components/structures/MatrixChat.tsx | 2 ++ src/components/views/elements/ActionButton.js | 5 ++- 5 files changed, 53 insertions(+), 2 deletions(-) diff --git a/res/css/structures/_GroupFilterPanel.scss b/res/css/structures/_GroupFilterPanel.scss index e5a8ef6df2..444435dd57 100644 --- a/res/css/structures/_GroupFilterPanel.scss +++ b/res/css/structures/_GroupFilterPanel.scss @@ -56,6 +56,12 @@ limitations under the License. .mx_GroupFilterPanel .mx_TagTile { // opacity: 0.5; position: relative; + + .mx_BetaDot { + position: absolute; + right: -13px; + top: -11px; + } } .mx_GroupFilterPanel .mx_TagTile.mx_TagTile_prototype { diff --git a/res/css/views/beta/_BetaCard.scss b/res/css/views/beta/_BetaCard.scss index a860473732..1527df68e2 100644 --- a/res/css/views/beta/_BetaCard.scss +++ b/res/css/views/beta/_BetaCard.scss @@ -68,3 +68,36 @@ limitations under the License. line-height: 15px; color: #FFFFFF; } + +$pulse-color: $accent-color-alt; +$dot-size: 12px; + +.mx_BetaDot { + background: black; + border-radius: 50%; + margin: 10px; + height: $dot-size; + width: $dot-size; + transform: scale(1); + background: rgba($pulse-color, 1); + box-shadow: 0 0 0 0 rgba($pulse-color, 1); + animation: mx_Beta_bluePulse 2s infinite; + animation-iteration-count: 20; +} + +@keyframes mx_Beta_bluePulse { + 0% { + transform: scale(0.95); + box-shadow: 0 0 0 0 rgba($pulse-color, 0.7); + } + + 70% { + transform: scale(1); + box-shadow: 0 0 0 10px rgba($pulse-color, 0); + } + + 100% { + transform: scale(0.95); + box-shadow: 0 0 0 0 rgba($pulse-color, 0); + } +} diff --git a/src/components/structures/GroupFilterPanel.js b/src/components/structures/GroupFilterPanel.js index 976b2d81a5..066178c976 100644 --- a/src/components/structures/GroupFilterPanel.js +++ b/src/components/structures/GroupFilterPanel.js @@ -123,12 +123,19 @@ class GroupFilterPanel extends React.Component { mx_GroupFilterPanel_items_selected: itemsSelected, }); + let betaDot; + if (!SettingsStore.getValue("feature_spaces") && !localStorage.getItem("mx_seenSpacesBeta")) { + betaDot =
    ; + } + let createButton = ( + className="mx_TagTile mx_TagTile_plus"> + { betaDot } + ); if (SettingsStore.getValue("feature_communities_v2_prototypes")) { diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index 078b296295..3da5d3b6dc 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -740,6 +740,8 @@ export default class MatrixChat extends React.PureComponent { this.showScreenAfterLogin(); break; case 'toggle_my_groups': + // persist that the user has interacted with this, use it to dismiss the beta dot + localStorage.setItem("mx_seenSpacesBeta", "1"); // We just dispatch the page change rather than have to worry about // what the logic is for each of these branches. if (this.state.page_type === PageTypes.MyGroups) { diff --git a/src/components/views/elements/ActionButton.js b/src/components/views/elements/ActionButton.js index 1714891cb5..4be3fe020b 100644 --- a/src/components/views/elements/ActionButton.js +++ b/src/components/views/elements/ActionButton.js @@ -32,6 +32,7 @@ export default class ActionButton extends React.Component { label: PropTypes.string.isRequired, iconPath: PropTypes.string, className: PropTypes.string, + children: PropTypes.node, }; static defaultProps = { @@ -79,7 +80,8 @@ export default class ActionButton extends React.Component { } return ( - { icon } { tooltip } + { this.props.children } ); } From 4f02dc905035372ef7a6106a7d6cf3c4ef35751c Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 27 Apr 2021 17:19:34 +0100 Subject: [PATCH 0092/1449] delint --- res/css/structures/_MyGroups.scss | 10 ++++------ res/css/views/beta/_BetaCard.scss | 1 - src/components/views/beta/BetaCard.tsx | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/res/css/structures/_MyGroups.scss b/res/css/structures/_MyGroups.scss index 24b9213336..1f84ccb9cf 100644 --- a/res/css/structures/_MyGroups.scss +++ b/res/css/structures/_MyGroups.scss @@ -17,6 +17,10 @@ limitations under the License. .mx_MyGroups { display: flex; flex-direction: column; + + .mx_BetaCard { + margin: 0 40px; + } } .mx_MyGroups .mx_RoomHeader_simpleHeader { @@ -35,12 +39,6 @@ limitations under the License. margin: 40px; } -.mx_MyGroups { - .mx_BetaCard { - margin: 0 40px; - } -} - .mx_MyGroups_headerCard { flex: 1 0 50%; margin-bottom: 30px; diff --git a/res/css/views/beta/_BetaCard.scss b/res/css/views/beta/_BetaCard.scss index 1527df68e2..c8da313f8c 100644 --- a/res/css/views/beta/_BetaCard.scss +++ b/res/css/views/beta/_BetaCard.scss @@ -73,7 +73,6 @@ $pulse-color: $accent-color-alt; $dot-size: 12px; .mx_BetaDot { - background: black; border-radius: 50%; margin: 10px; height: $dot-size; diff --git a/src/components/views/beta/BetaCard.tsx b/src/components/views/beta/BetaCard.tsx index 9516ce975c..cbd2488249 100644 --- a/src/components/views/beta/BetaCard.tsx +++ b/src/components/views/beta/BetaCard.tsx @@ -26,7 +26,7 @@ interface IProps { featureId: string; } -export const BetaPill = ({ onClick }) => { +export const BetaPill = ({ onClick }: { onClick?: () => void }) => { return { _t("Beta") } ; From 7509481bb9339e038027efa6564df9746b73518a Mon Sep 17 00:00:00 2001 From: Ayush PS Date: Wed, 28 Apr 2021 02:46:43 +0530 Subject: [PATCH 0093/1449] Added the LTR support for the dialpad --- res/css/views/voip/_DialPadContextMenu.scss | 14 ++++++++++++-- .../views/context_menus/DialpadContextMenu.tsx | 13 ++++++++++++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/res/css/views/voip/_DialPadContextMenu.scss b/res/css/views/voip/_DialPadContextMenu.scss index 9879b7da1c..c01ce0f2d9 100644 --- a/res/css/views/voip/_DialPadContextMenu.scss +++ b/res/css/views/voip/_DialPadContextMenu.scss @@ -30,8 +30,18 @@ limitations under the License. height: 1.5em; font-size: 18px; font-weight: 600; - max-width: 155px; - overflow: auto; + max-width: 150px; + border: none; + margin: 0px; + +} +.mx_DialPadContextMenu_dialled input{ + font-size: 18px; + font-weight: 600; + overflow: hidden; + text-align: left; + direction: rtl; + background-color: rgb(0, 0, 0, 0); } .mx_DialPadContextMenu_dialPad { diff --git a/src/components/views/context_menus/DialpadContextMenu.tsx b/src/components/views/context_menus/DialpadContextMenu.tsx index 17abce0c61..0a1d8184f2 100644 --- a/src/components/views/context_menus/DialpadContextMenu.tsx +++ b/src/components/views/context_menus/DialpadContextMenu.tsx @@ -18,6 +18,7 @@ import React from 'react'; import { _t } from '../../../languageHandler'; import { ContextMenu, IProps as IContextMenuProps } from '../../structures/ContextMenu'; import { MatrixCall } from 'matrix-js-sdk/src/webrtc/call'; +import Field from "../elements/Field"; import Dialpad from '../voip/DialPad'; import {replaceableComponent} from "../../../utils/replaceableComponent"; @@ -44,13 +45,23 @@ export default class DialpadContextMenu extends React.Component this.setState({value: this.state.value + digit}); } + onChange = (ev) => { + this.setState({value: ev.target.value}); + } + + render() { return
    {_t("Dial pad")}
    -
    {this.state.value}
    +
    + +
    From 79e03332e32b128226a7e61c58857771e2ef8ae3 Mon Sep 17 00:00:00 2001 From: Aaron Raimist Date: Tue, 27 Apr 2021 16:51:49 -0500 Subject: [PATCH 0094/1449] Another change from recovery passphrase to Security Phrase Signed-off-by: Aaron Raimist --- .../views/dialogs/security/CreateSecretStorageDialog.js | 4 ++-- src/i18n/strings/en_EN.json | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/async-components/views/dialogs/security/CreateSecretStorageDialog.js b/src/async-components/views/dialogs/security/CreateSecretStorageDialog.js index 84cb58536a..a7d21349a5 100644 --- a/src/async-components/views/dialogs/security/CreateSecretStorageDialog.js +++ b/src/async-components/views/dialogs/security/CreateSecretStorageDialog.js @@ -647,7 +647,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent { } return

    {_t( - "Enter your recovery passphrase a second time to confirm it.", + "Enter your Security Phrase a second time to confirm it.", )}

    diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index f1b700540f..7158156105 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2831,8 +2831,7 @@ "You'll need to authenticate with the server to confirm the upgrade.": "You'll need to authenticate with the server to confirm the upgrade.", "Upgrade this session to allow it to verify other sessions, granting them access to encrypted messages and marking them as trusted for other users.": "Upgrade this session to allow it to verify other sessions, granting them access to encrypted messages and marking them as trusted for other users.", "Enter a security phrase only you know, as it’s used to safeguard your data. To be secure, you shouldn’t re-use your account password.": "Enter a security phrase only you know, as it’s used to safeguard your data. To be secure, you shouldn’t re-use your account password.", - "Enter your recovery passphrase a second time to confirm it.": "Enter your recovery passphrase a second time to confirm it.", - "Confirm your recovery passphrase": "Confirm your recovery passphrase", + "Enter your Security Phrase a second time to confirm it.": "Enter your Security Phrase a second time to confirm it.", "Store your Security Key somewhere safe, like a password manager or a safe, as it’s used to safeguard your encrypted data.": "Store your Security Key somewhere safe, like a password manager or a safe, as it’s used to safeguard your encrypted data.", "Unable to query secret storage status": "Unable to query secret storage status", "If you cancel now, you may lose encrypted messages & data if you lose access to your logins.": "If you cancel now, you may lose encrypted messages & data if you lose access to your logins.", From 6754a0b48388d6349c499f9c7b231bf32c0d6fa4 Mon Sep 17 00:00:00 2001 From: Aaron Raimist Date: Tue, 27 Apr 2021 19:12:20 -0500 Subject: [PATCH 0095/1449] Switch to
    Signed-off-by: Aaron Raimist --- .../tabs/user/_HelpUserSettingsTab.scss | 31 +++++++++++++ .../views/dialogs/AccessTokenDialog.tsx | 38 ---------------- .../settings/tabs/user/HelpUserSettingsTab.js | 44 +++++++++++++------ src/i18n/strings/en_EN.json | 7 ++- 4 files changed, 64 insertions(+), 56 deletions(-) delete mode 100644 src/components/views/dialogs/AccessTokenDialog.tsx diff --git a/res/css/views/settings/tabs/user/_HelpUserSettingsTab.scss b/res/css/views/settings/tabs/user/_HelpUserSettingsTab.scss index 109edfff81..0f879d209e 100644 --- a/res/css/views/settings/tabs/user/_HelpUserSettingsTab.scss +++ b/res/css/views/settings/tabs/user/_HelpUserSettingsTab.scss @@ -22,3 +22,34 @@ limitations under the License. .mx_HelpUserSettingsTab span.mx_AccessibleButton { word-break: break-word; } + +.mx_HelpUserSettingsTab code { + word-break: break-all; + user-select: all; +} + +.mx_HelpUserSettingsTab_accessToken { + display: flex; + justify-content: space-between; + border-radius: 5px; + border: solid 1px $light-fg-color; + margin-bottom: 10px; + margin-top: 10px; + padding: 10px; +} + +.mx_HelpUserSettingsTab_accessToken_copy { + flex-shrink: 0; + cursor: pointer; + margin-left: 20px; + display: inherit; +} + +.mx_HelpUserSettingsTab_accessToken_copy > div { + mask-image: url($copy-button-url); + background-color: $message-action-bar-fg-color; + margin-left: 5px; + width: 20px; + height: 20px; + background-repeat: no-repeat; +} diff --git a/src/components/views/dialogs/AccessTokenDialog.tsx b/src/components/views/dialogs/AccessTokenDialog.tsx deleted file mode 100644 index c0b1b929df..0000000000 --- a/src/components/views/dialogs/AccessTokenDialog.tsx +++ /dev/null @@ -1,38 +0,0 @@ -/* -Copyright 2017 Vector Creations Ltd -Copyright 2020 Resynth - -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 { _t } from '../../../languageHandler'; -import QuestionDialog from './QuestionDialog'; - -type IProps = Exclude< - React.ComponentProps, - "title" | "danger" | "description" ->; - -export default function AccessTokenDialog(props: IProps) { - return ( - - ); -} diff --git a/src/components/views/settings/tabs/user/HelpUserSettingsTab.js b/src/components/views/settings/tabs/user/HelpUserSettingsTab.js index e52bc1a3fb..cf1a28ef76 100644 --- a/src/components/views/settings/tabs/user/HelpUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/HelpUserSettingsTab.js @@ -20,6 +20,7 @@ import PropTypes from 'prop-types'; import {_t, getCurrentLanguage} from "../../../../../languageHandler"; import {MatrixClientPeg} from "../../../../../MatrixClientPeg"; import AccessibleButton from "../../../elements/AccessibleButton"; +import AccessibleTooltipButton from '../../../elements/AccessibleTooltipButton'; import SdkConfig from "../../../../../SdkConfig"; import createRoom from "../../../../../createRoom"; import Modal from "../../../../../Modal"; @@ -27,8 +28,11 @@ import * as sdk from "../../../../../"; import PlatformPeg from "../../../../../PlatformPeg"; import * as KeyboardShortcuts from "../../../../../accessibility/KeyboardShortcuts"; import UpdateCheckButton from "../../UpdateCheckButton"; -import AccessTokenDialog from '../../../dialogs/AccessTokenDialog'; import {replaceableComponent} from "../../../../../utils/replaceableComponent"; +import {copyPlaintext} from "../../../../../utils/strings"; +import * as ContextMenu from "../../../../structures/ContextMenu"; +import {toRightOf} from "../../../../structures/ContextMenu"; + @replaceableComponent("views.settings.tabs.user.HelpUserSettingsTab") export default class HelpUserSettingsTab extends React.Component { @@ -151,15 +155,18 @@ export default class HelpUserSettingsTab extends React.Component { ); } - onAccessTokenSpoilerClick = async (event) => { - // React throws away the event before we can use it (we are async, after all). - event.persist(); + onAccessTokenCopyClick = async (e) => { + e.preventDefault(); + const target = e.target; // copy target before we go async and React throws it away - // We make the user accept a scary popup to combat Social Engineering. No peeking! - await Modal.createTrackedDialog('Reveal Access Token', '', AccessTokenDialog).finished; - - // Pass it onto the handler. - this._showSpoiler(event); + const successful = await copyPlaintext(MatrixClientPeg.get().getAccessToken()); + const buttonRect = target.getBoundingClientRect(); + const GenericTextContextMenu = sdk.getComponent('context_menus.GenericTextContextMenu'); + const {close} = ContextMenu.createMenu(GenericTextContextMenu, { + ...toRightOf(buttonRect, 2), + message: successful ? _t('Copied!') : _t('Failed to copy'), + }); + target.onmouseleave = close; } render() { @@ -279,11 +286,20 @@ export default class HelpUserSettingsTab extends React.Component {
    {_t("Homeserver is")} {MatrixClientPeg.get().getHomeserverUrl()}
    {_t("Identity Server is")} {MatrixClientPeg.get().getIdentityServerUrl()}
    - {_t("Access Token:") + ' '} - - <{ _t("click to reveal") }> - +
    +
    + {_t("Access Token")}
    + { _t("Your access token gives full access to your account." + + " Do not share it with anyone." ) } +
    + {MatrixClientPeg.get().getAccessToken()} + +
    +

    {_t("Clear cache and reload")} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index b110af8749..99451dabd6 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1251,8 +1251,9 @@ "olm version:": "olm version:", "Homeserver is": "Homeserver is", "Identity Server is": "Identity Server is", - "Access Token:": "Access Token:", - "click to reveal": "click to reveal", + "Access Token": "Access Token", + "Your access token gives full access to your account. Do not share it with anyone.": "Your access token gives full access to your account. Do not share it with anyone.", + "Copy": "Copy", "Clear cache and reload": "Clear cache and reload", "Labs": "Labs", "Customise your experience with experimental labs features. Learn more.": "Customise your experience with experimental labs features. Learn more.", @@ -2016,7 +2017,6 @@ "Add a new server...": "Add a new server...", "%(networkName)s rooms": "%(networkName)s rooms", "Matrix rooms": "Matrix rooms", - "Your access token gives full access to your account. Do not share it with anyone.": "Your access token gives full access to your account. Do not share it with anyone.", "Space selection": "Space selection", "Add existing rooms": "Add existing rooms", "Filter your rooms and spaces": "Filter your rooms and spaces", @@ -2336,7 +2336,6 @@ "Share Community": "Share Community", "Share Room Message": "Share Room Message", "Link to selected message": "Link to selected message", - "Copy": "Copy", "Command Help": "Command Help", "Failed to save space settings.": "Failed to save space settings.", "Space settings": "Space settings", From 505b200a87d9185b2fe3050352bb4c36ea4fd66c Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 28 Apr 2021 08:05:25 +0100 Subject: [PATCH 0096/1449] fix beta pill styling --- res/css/views/beta/_BetaCard.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/res/css/views/beta/_BetaCard.scss b/res/css/views/beta/_BetaCard.scss index c8da313f8c..986ca1d4c5 100644 --- a/res/css/views/beta/_BetaCard.scss +++ b/res/css/views/beta/_BetaCard.scss @@ -67,6 +67,8 @@ limitations under the License. font-size: 12px; line-height: 15px; color: #FFFFFF; + display: inline-block; + vertical-align: text-bottom; } $pulse-color: $accent-color-alt; From 18a01d92710e2b0179f1ebc62d4291ada73d552e Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 28 Apr 2021 08:41:31 +0100 Subject: [PATCH 0097/1449] Show spaces beta prompt when viewing a space without the beta --- res/css/structures/_SpaceRoomView.scss | 22 +++++++++ res/css/views/beta/_BetaCard.scss | 4 ++ src/components/structures/RoomView.tsx | 2 +- src/components/structures/SpaceRoomView.tsx | 52 +++++++++++++++++++-- src/components/views/beta/BetaCard.tsx | 8 +++- src/i18n/strings/en_EN.json | 2 + 6 files changed, 85 insertions(+), 5 deletions(-) diff --git a/res/css/structures/_SpaceRoomView.scss b/res/css/structures/_SpaceRoomView.scss index 269f16beb7..bfb796af3c 100644 --- a/res/css/structures/_SpaceRoomView.scss +++ b/res/css/structures/_SpaceRoomView.scss @@ -123,6 +123,28 @@ $SpaceRoomViewInnerWidth: 428px; box-sizing: border-box; box-shadow: 2px 15px 30px $dialog-shadow-color; border-radius: 8px; + position: relative; + + // XXX remove this when spaces leaves Beta + .mx_BetaCard_betaPill { + position: absolute; + right: 24px; + top: 32px; + } + // XXX remove this when spaces leaves Beta + .mx_SpaceRoomView_preview_spaceBetaPrompt { + font-size: $font-15px; + line-height: $font-24px; + color: $secondary-fg-color; + margin-top: 14px; + + .mx_AccessibleButton_kind_link { + display: inline; + padding: 0; + font-size: inherit; + line-height: inherit; + } + } .mx_SpaceRoomView_preview_inviter { display: flex; diff --git a/res/css/views/beta/_BetaCard.scss b/res/css/views/beta/_BetaCard.scss index 986ca1d4c5..8369e5ee19 100644 --- a/res/css/views/beta/_BetaCard.scss +++ b/res/css/views/beta/_BetaCard.scss @@ -69,6 +69,10 @@ limitations under the License. color: #FFFFFF; display: inline-block; vertical-align: text-bottom; + + &.mx_BetaCard_betaPill_clickable { + cursor: pointer; + } } $pulse-color: $accent-color-alt; diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index 7168b7d139..906d612ea5 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -1910,7 +1910,7 @@ export default class RoomView extends React.Component { ); } - if (SettingsStore.getValue("feature_spaces") && this.state.room?.isSpaceRoom()) { + if (this.state.room?.isSpaceRoom()) { return {
    }; +const onBetaClick = () => { + defaultDispatcher.dispatch({ + action: Action.ViewUserSettings, + initialTabId: USER_LABS_TAB, + }); +}; + const SpacePreview = ({ space, onJoinButtonClicked, onRejectButtonClicked }) => { const cli = useContext(MatrixClientContext); const myMembership = useMyRoomMembership(space); const [busy, setBusy] = useState(false); + const spacesEnabled = SettingsStore.getValue("feature_spaces"); + let inviterSection; let joinButtons; - if (myMembership === "invite") { + if (myMembership === "join") { + // XXX remove this when spaces leaves Beta + joinButtons = ( + { + setBusy(true); + dis.dispatch({ + action: "leave_room", + room_id: space.roomId, + }); + }} + > + { _t("Leave") } + + ); + } else if (myMembership === "invite") { const inviteSender = space.getMember(cli.getUserId())?.events.member?.getSender(); const inviter = inviteSender && space.getMember(inviteSender); @@ -171,6 +200,7 @@ const SpacePreview = ({ space, onJoinButtonClicked, onRejectButtonClicked }) => setBusy(true); onJoinButtonClicked(); }} + disabled={!spacesEnabled} > { _t("Accept") } @@ -183,10 +213,11 @@ const SpacePreview = ({ space, onJoinButtonClicked, onRejectButtonClicked }) => setBusy(true); onJoinButtonClicked(); }} + disabled={!spacesEnabled} > { _t("Join") } - ) + ); } if (busy) { @@ -194,6 +225,7 @@ const SpacePreview = ({ space, onJoinButtonClicked, onRejectButtonClicked }) => } return
    + { inviterSection }

    @@ -211,6 +243,20 @@ const SpacePreview = ({ space, onJoinButtonClicked, onRejectButtonClicked }) =>
    { joinButtons }
    + { !spacesEnabled &&
    + { myMembership === "join" + ? _t("To view %(spaceName)s, turn on the Spaces beta", { + spaceName: space.name, + }, { + a: sub => { sub }, + }) + : _t("To join %(spaceName)s, turn on the Spaces beta", { + spaceName: space.name, + }, { + a: sub => { sub }, + }) + } +
    }

    ; }; @@ -631,7 +677,7 @@ export default class SpaceRoomView extends React.PureComponent { private renderBody() { switch (this.state.phase) { case Phase.Landing: - if (this.state.myMembership === "join") { + if (this.state.myMembership === "join" && SettingsStore.getValue("feature_spaces")) { return ; } else { return void }) => { - return + return { _t("Beta") } ; }; diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 857c1cd568..ab2614af95 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2660,6 +2660,8 @@ "Public space": "Public space", "Private space": "Private space", " invites you": " invites you", + "To view %(spaceName)s, turn on the Spaces beta": "To view %(spaceName)s, turn on the Spaces beta", + "To join %(spaceName)s, turn on the Spaces beta": "To join %(spaceName)s, turn on the Spaces beta", "Add existing rooms & spaces": "Add existing rooms & spaces", "Welcome to ": "Welcome to ", "Random": "Random", From 9dff5cd59625678e584055f5199d9a9d9c66df95 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 28 Apr 2021 08:59:02 +0100 Subject: [PATCH 0098/1449] tweak leave space on preview --- src/components/structures/SpaceRoomView.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx index 963f99e94d..2e080d67f7 100644 --- a/src/components/structures/SpaceRoomView.tsx +++ b/src/components/structures/SpaceRoomView.tsx @@ -154,7 +154,6 @@ const SpacePreview = ({ space, onJoinButtonClicked, onRejectButtonClicked }) => { - setBusy(true); dis.dispatch({ action: "leave_room", room_id: space.roomId, From 9a16fcb6fc27868fe5f452a6df70b3c7980dbdd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 28 Apr 2021 10:31:49 +0200 Subject: [PATCH 0099/1449] Emit in removeCallForRoom() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/CallHandler.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index 8e8f120852..e9c85db84e 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -552,6 +552,7 @@ export default class CallHandler extends EventEmitter { private removeCallForRoom(roomId: string) { this.calls.delete(roomId); + this.emit(CallHandlerEvent.CallsChanged, this.calls); } private showICEFallbackPrompt() { From c0f11fd3167c0dc2cc65cd86099b6226b5237ccf Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 28 Apr 2021 09:35:25 +0100 Subject: [PATCH 0100/1449] Fix communities spaces beta card layout --- res/css/structures/_MyGroups.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/res/css/structures/_MyGroups.scss b/res/css/structures/_MyGroups.scss index 1f84ccb9cf..6ecc5570f4 100644 --- a/res/css/structures/_MyGroups.scss +++ b/res/css/structures/_MyGroups.scss @@ -20,6 +20,7 @@ limitations under the License. .mx_BetaCard { margin: 0 40px; + max-width: 960px; } } @@ -34,7 +35,7 @@ limitations under the License. flex-wrap: wrap; } -.mx_MyGroups > :not(.mx_RoomHeader) { +.mx_MyGroups > :not(.mx_RoomHeader):not(.mx_BetaCard) { max-width: 960px; margin: 40px; } From e5b61f063249c0f3f6d74bd1eae303b230c4e9b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 28 Apr 2021 11:29:05 +0200 Subject: [PATCH 0101/1449] Keep rendering AudioFeeds on hold MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- .../views/voip/AudioFeedArrayForCall.tsx | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/components/views/voip/AudioFeedArrayForCall.tsx b/src/components/views/voip/AudioFeedArrayForCall.tsx index fac2a22dcd..bfe232d799 100644 --- a/src/components/views/voip/AudioFeedArrayForCall.tsx +++ b/src/components/views/voip/AudioFeedArrayForCall.tsx @@ -25,7 +25,6 @@ interface IProps { interface IState { feeds: Array; - onHold: boolean; } export default class AudioFeedArrayForCall extends React.Component { @@ -34,18 +33,15 @@ export default class AudioFeedArrayForCall extends React.Component { @@ -54,20 +50,11 @@ export default class AudioFeedArrayForCall extends React.Component { - this.setState({onHold: onHold}); - } - render() { - // If we are onHold don't render any audio elements - if (this.state.onHold) return null; - - const feeds = this.state.feeds.map((feed, i) => { + return this.state.feeds.map((feed, i) => { return ( ); }); - - return feeds; } } From 40748d3c9471ebb0ff968485e7ca6661a2acb5d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 28 Apr 2021 11:49:07 +0200 Subject: [PATCH 0102/1449] Make CallHandler emit CallChangeRoom MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's hope I changed the tests correctly Signed-off-by: Šimon Brandner --- src/CallHandler.tsx | 6 ++---- src/components/views/voip/CallPreview.tsx | 26 +++++++++++++---------- src/dispatcher/actions.ts | 3 --- test/CallHandler-test.ts | 11 +++++----- 4 files changed, 22 insertions(+), 24 deletions(-) diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index 4f33714fef..0268ebfe46 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -141,6 +141,7 @@ export enum PlaceCallType { export enum CallHandlerEvent { CallsChanged = "calls_changed", + CallChangeRoom = "call_change_room", } export default class CallHandler extends EventEmitter { @@ -537,10 +538,7 @@ export default class CallHandler extends EventEmitter { this.removeCallForRoom(mappedRoomId); mappedRoomId = newMappedRoomId; this.calls.set(mappedRoomId, call); - dis.dispatch({ - action: Action.CallChangeRoom, - call, - }); + this.emit(CallHandlerEvent.CallChangeRoom, call); } } }); diff --git a/src/components/views/voip/CallPreview.tsx b/src/components/views/voip/CallPreview.tsx index d31afddec9..80fd64a820 100644 --- a/src/components/views/voip/CallPreview.tsx +++ b/src/components/views/voip/CallPreview.tsx @@ -19,7 +19,7 @@ import React from 'react'; import CallView from "./CallView"; import RoomViewStore from '../../../stores/RoomViewStore'; -import CallHandler from '../../../CallHandler'; +import CallHandler, { CallHandlerEvent } from '../../../CallHandler'; import dis from '../../../dispatcher/dispatcher'; import { ActionPayload } from '../../../dispatcher/payloads'; import PersistentApp from "../elements/PersistentApp"; @@ -27,7 +27,6 @@ import SettingsStore from "../../../settings/SettingsStore"; import { CallEvent, CallState, MatrixCall } from 'matrix-js-sdk/src/webrtc/call'; import { MatrixClientPeg } from '../../../MatrixClientPeg'; import {replaceableComponent} from "../../../utils/replaceableComponent"; -import { Action } from '../../../dispatcher/actions'; const SHOW_CALL_IN_STATES = [ CallState.Connected, @@ -110,12 +109,14 @@ export default class CallPreview extends React.Component { } public componentDidMount() { + CallHandler.sharedInstance().addListener(CallHandlerEvent.CallChangeRoom, this.updateCalls); this.roomStoreToken = RoomViewStore.addListener(this.onRoomViewStoreUpdate); this.dispatcherRef = dis.register(this.onAction); MatrixClientPeg.get().on(CallEvent.RemoteHoldUnhold, this.onCallRemoteHold); } public componentWillUnmount() { + CallHandler.sharedInstance().removeListener(CallHandlerEvent.CallChangeRoom, this.updateCalls); MatrixClientPeg.get().removeListener(CallEvent.RemoteHoldUnhold, this.onCallRemoteHold); if (this.roomStoreToken) { this.roomStoreToken.remove(); @@ -143,21 +144,24 @@ export default class CallPreview extends React.Component { switch (payload.action) { // listen for call state changes to prod the render method, which // may hide the global CallView if the call it is tracking is dead - case Action.CallChangeRoom: case 'call_state': { - const [primaryCall, secondaryCalls] = getPrimarySecondaryCalls( - CallHandler.sharedInstance().getAllActiveCallsNotInRoom(this.state.roomId), - ); - - this.setState({ - primaryCall: primaryCall, - secondaryCall: secondaryCalls[0], - }); + this.updateCalls(); break; } } }; + private updateCalls = () => { + const [primaryCall, secondaryCalls] = getPrimarySecondaryCalls( + CallHandler.sharedInstance().getAllActiveCallsNotInRoom(this.state.roomId), + ); + + this.setState({ + primaryCall: primaryCall, + secondaryCall: secondaryCalls[0], + }); + }; + private onCallRemoteHold = () => { const [primaryCall, secondaryCalls] = getPrimarySecondaryCalls( CallHandler.sharedInstance().getAllActiveCallsNotInRoom(this.state.roomId), diff --git a/src/dispatcher/actions.ts b/src/dispatcher/actions.ts index 46c962f160..cd32c3743f 100644 --- a/src/dispatcher/actions.ts +++ b/src/dispatcher/actions.ts @@ -114,9 +114,6 @@ export enum Action { */ VirtualRoomSupportUpdated = "virtual_room_support_updated", - // Probably would be better to have a VoIP states in a store and have the store emit changes - CallChangeRoom = "call_change_room", - /** * Fired when an upload has started. Should be used with UploadStartedPayload. */ diff --git a/test/CallHandler-test.ts b/test/CallHandler-test.ts index 754610b223..f7e2c27993 100644 --- a/test/CallHandler-test.ts +++ b/test/CallHandler-test.ts @@ -16,7 +16,7 @@ limitations under the License. import './skinned-sdk'; -import CallHandler, { PlaceCallType } from '../src/CallHandler'; +import CallHandler, { PlaceCallType, CallHandlerEvent } from '../src/CallHandler'; import { stubClient, mkStubRoom } from './test-utils'; import { MatrixClientPeg } from '../src/MatrixClientPeg'; import dis from '../src/dispatcher/dispatcher'; @@ -172,11 +172,9 @@ describe('CallHandler', () => { let callRoomChangeEventCount = 0; const roomChangePromise = new Promise(resolve => { - dispatchHandle = dis.register(payload => { - if (payload.action === Action.CallChangeRoom) { - ++callRoomChangeEventCount; - resolve(); - } + CallHandler.sharedInstance().addListener(CallHandlerEvent.CallChangeRoom, () => { + ++callRoomChangeEventCount; + resolve(); }); }); @@ -202,6 +200,7 @@ describe('CallHandler', () => { await roomChangePromise; dis.unregister(dispatchHandle); + CallHandler.sharedInstance().removeAllListeners(); // If everything's gone well, we should have seen only one room change // event and the call should now be in user 3's room. From 653591e8066fe44e9a7e31ef1acc1a93430d86b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 28 Apr 2021 11:56:26 +0200 Subject: [PATCH 0103/1449] Use CallChangeRoom in CallViewForRoom MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/CallViewForRoom.tsx | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/components/views/voip/CallViewForRoom.tsx b/src/components/views/voip/CallViewForRoom.tsx index 7540dbc8d9..0c785f758d 100644 --- a/src/components/views/voip/CallViewForRoom.tsx +++ b/src/components/views/voip/CallViewForRoom.tsx @@ -16,13 +16,12 @@ limitations under the License. import { CallState, MatrixCall } from 'matrix-js-sdk/src/webrtc/call'; import React from 'react'; -import CallHandler from '../../../CallHandler'; +import CallHandler, { CallHandlerEvent } from '../../../CallHandler'; import CallView from './CallView'; import dis from '../../../dispatcher/dispatcher'; import {Resizable} from "re-resizable"; import ResizeNotifier from "../../../utils/ResizeNotifier"; import {replaceableComponent} from "../../../utils/replaceableComponent"; -import { Action } from '../../../dispatcher/actions'; interface IProps { // What room we should display the call for @@ -55,25 +54,30 @@ export default class CallViewForRoom extends React.Component { public componentDidMount() { this.dispatcherRef = dis.register(this.onAction); + CallHandler.sharedInstance().addListener(CallHandlerEvent.CallChangeRoom, this.updateCall); } public componentWillUnmount() { dis.unregister(this.dispatcherRef); + CallHandler.sharedInstance().removeListener(CallHandlerEvent.CallChangeRoom, this.updateCall); } private onAction = (payload) => { switch (payload.action) { - case Action.CallChangeRoom: case 'call_state': { - const newCall = this.getCall(); - if (newCall !== this.state.call) { - this.setState({call: newCall}); - } + this.updateCall(); break; } } }; + private updateCall = () => { + const newCall = this.getCall(); + if (newCall !== this.state.call) { + this.setState({call: newCall}); + } + }; + private getCall(): MatrixCall { const call = CallHandler.sharedInstance().getCallForRoom(this.props.roomId); From 5a921bf38a65e1b78600873ae8a5bf6f066cfce2 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 28 Apr 2021 12:10:03 +0100 Subject: [PATCH 0104/1449] Add beta pill to space create menu --- res/css/views/spaces/_SpaceCreateMenu.scss | 8 ++++++++ src/components/structures/SpaceRoomView.tsx | 2 +- src/components/views/spaces/SpaceCreateMenu.tsx | 12 +++++++++++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/res/css/views/spaces/_SpaceCreateMenu.scss b/res/css/views/spaces/_SpaceCreateMenu.scss index ef3fea351b..ef15206d22 100644 --- a/res/css/views/spaces/_SpaceCreateMenu.scss +++ b/res/css/views/spaces/_SpaceCreateMenu.scss @@ -29,6 +29,7 @@ $spacePanelWidth: 71px; width: 480px; box-sizing: border-box; background-color: $primary-bg-color; + position: relative; > div { > h2 { @@ -44,6 +45,13 @@ $spacePanelWidth: 71px; } } + // XXX remove this when spaces leaves Beta + .mx_BetaCard_betaPill { + position: absolute; + top: 24px; + right: 24px; + } + .mx_SpaceCreateMenuType { @mixin SpacePillButton; } diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx index 2e080d67f7..3d73a1b953 100644 --- a/src/components/structures/SpaceRoomView.tsx +++ b/src/components/structures/SpaceRoomView.tsx @@ -152,7 +152,7 @@ const SpacePreview = ({ space, onJoinButtonClicked, onRejectButtonClicked }) => // XXX remove this when spaces leaves Beta joinButtons = ( { dis.dispatch({ action: "leave_room", diff --git a/src/components/views/spaces/SpaceCreateMenu.tsx b/src/components/views/spaces/SpaceCreateMenu.tsx index 9c42b9c7c4..569197a06c 100644 --- a/src/components/views/spaces/SpaceCreateMenu.tsx +++ b/src/components/views/spaces/SpaceCreateMenu.tsx @@ -17,6 +17,7 @@ limitations under the License. import React, {useContext, useState} from "react"; import classNames from "classnames"; import {EventType, RoomType, RoomCreateTypeField} from "matrix-js-sdk/src/@types/event"; +import FocusLock from "react-focus-lock"; import {_t} from "../../../languageHandler"; import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; @@ -25,7 +26,10 @@ import createRoom, {IStateEvent, Preset} from "../../../createRoom"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; import SpaceBasicSettings from "./SpaceBasicSettings"; import AccessibleButton from "../elements/AccessibleButton"; -import FocusLock from "react-focus-lock"; +import {BetaPill} from "../beta/BetaCard"; +import defaultDispatcher from "../../../dispatcher/dispatcher"; +import {Action} from "../../../dispatcher/actions"; +import {USER_LABS_TAB} from "../dialogs/UserSettingsDialog"; const SpaceCreateMenuType = ({ title, description, className, onClick }) => { return ( @@ -164,6 +168,12 @@ const SpaceCreateMenu = ({ onFinished }) => { managed={false} > + { + defaultDispatcher.dispatch({ + action: Action.ViewUserSettings, + initialTabId: USER_LABS_TAB, + }); + }} /> { body } ; From b6324a816f2b3d4c19a514c0eb51d9fcf52e70a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 28 Apr 2021 13:33:15 +0200 Subject: [PATCH 0105/1449] Use CallHandler correctly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- test/CallHandler-test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/CallHandler-test.ts b/test/CallHandler-test.ts index f7e2c27993..4b326cde25 100644 --- a/test/CallHandler-test.ts +++ b/test/CallHandler-test.ts @@ -172,7 +172,7 @@ describe('CallHandler', () => { let callRoomChangeEventCount = 0; const roomChangePromise = new Promise(resolve => { - CallHandler.sharedInstance().addListener(CallHandlerEvent.CallChangeRoom, () => { + callHandler.addListener(CallHandlerEvent.CallChangeRoom, () => { ++callRoomChangeEventCount; resolve(); }); @@ -200,7 +200,7 @@ describe('CallHandler', () => { await roomChangePromise; dis.unregister(dispatchHandle); - CallHandler.sharedInstance().removeAllListeners(); + callHandler.removeAllListeners(); // If everything's gone well, we should have seen only one room change // event and the call should now be in user 3's room. From 9aaf321e4eaf670c8d71f37a73fe965c31684a01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 28 Apr 2021 13:39:09 +0200 Subject: [PATCH 0106/1449] Remove dis call which doesn't seem to be necessary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- test/CallHandler-test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/test/CallHandler-test.ts b/test/CallHandler-test.ts index 4b326cde25..1e3f92e788 100644 --- a/test/CallHandler-test.ts +++ b/test/CallHandler-test.ts @@ -199,7 +199,6 @@ describe('CallHandler', () => { fakeCall.emit(CallEvent.AssertedIdentityChanged); await roomChangePromise; - dis.unregister(dispatchHandle); callHandler.removeAllListeners(); // If everything's gone well, we should have seen only one room change From 58d83d0309a507ed3060c6bf8832a261e95ef05f Mon Sep 17 00:00:00 2001 From: libexus Date: Tue, 27 Apr 2021 07:05:53 +0000 Subject: [PATCH 0107/1449] Translated using Weblate (German) Currently translated at 99.0% (2896 of 2924 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 5cbdd20a36..54afb5c22a 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -3264,5 +3264,10 @@ "Zoom in": "Vergrößern", "Zoom out": "Verkleinern", "%(seconds)ss left": "%(seconds)s vergangen", - "Change server ACLs": "ACLs des Servers bearbeiten" + "Change server ACLs": "ACLs des Servers bearbeiten", + "Failed to send": "Fehler beim Senden", + "View all %(count)s members|other": "Alle %(count)s Mitglieder anzeigen", + "View all %(count)s members|one": "Mitglied anzeigen", + "%(count)s members including %(commaSeparatedMembers)s|one": "%(commaSeparatedMembers)s", + "Some of your messages have not been sent": "Einige Nachrichten konnten nicht gesendet werden" } From 021469044111cbc1cb77d34eb3cf506d2a805e35 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Mon, 26 Apr 2021 16:31:02 +0000 Subject: [PATCH 0108/1449] Translated using Weblate (English (United States)) Currently translated at 20.1% (588 of 2924 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/en_US/ --- src/i18n/strings/en_US.json | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/en_US.json b/src/i18n/strings/en_US.json index bfc21a81d3..4a97b60a2e 100644 --- a/src/i18n/strings/en_US.json +++ b/src/i18n/strings/en_US.json @@ -658,5 +658,12 @@ "Single Sign On": "Single Sign On", "Confirm adding this email address by using Single Sign On to prove your identity.": "Confirm adding this email address by using Single Sign On to prove your identity.", "Use Single Sign On to continue": "Use Single Sign On to continue", - "Message search initilisation failed": "Message search initialization failed" + "Message search initilisation failed": "Message search initialization failed", + "%(brand)s now uses 3-5x less memory, by only loading information about other users when needed. Please wait whilst we resynchronise with the server!": "%(brand)s now uses 3-5x less memory, by only loading information about other users when needed. Please wait while we resynchronize with the server!", + "Customise your experience with experimental labs features. Learn more.": "Customize your experience with experimental labs features. Learn more.", + "Customise your appearance": "Customize your appearance", + "Unrecognised command: %(commandText)s": "Unrecognized command: %(commandText)s", + "Add some details to help people recognise it.": "Add some details to help people recognize it.", + "Unrecognised room address:": "Unrecognized room address:", + "A private space to organise your rooms": "A private space to organize your rooms" } From dd0a30c0dc76755e7e70e5ffb545b8451e7fca8d Mon Sep 17 00:00:00 2001 From: Thibault Martin Date: Tue, 27 Apr 2021 06:01:45 +0000 Subject: [PATCH 0109/1449] Translated using Weblate (French) Currently translated at 100.0% (2924 of 2924 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/fr/ --- src/i18n/strings/fr.json | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index 5fc5b1d10b..3db86ad59b 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -3274,5 +3274,16 @@ "Zoom out": "Dé-zoomer", "%(seconds)ss left": "%(seconds)s secondes restantes", "Change server ACLs": "Modifier les ACL du serveur", - "Show options to enable 'Do not disturb' mode": "Afficher une option pour activer le mode « Ne pas déranger »" + "Show options to enable 'Do not disturb' mode": "Afficher une option pour activer le mode « Ne pas déranger »", + "You can select all or individual messages to retry or delete": "Vous pouvez choisir de renvoyer ou supprimer tous les messages ou seulement certains", + "Sending": "Envoi", + "Retry all": "Tout renvoyer", + "Delete all": "Tout supprimer", + "Some of your messages have not been sent": "Certains de vos messages n’ont pas été envoyés", + "%(count)s members including %(commaSeparatedMembers)s|one": "%(commaSeparatedMembers)s", + "%(count)s members including %(commaSeparatedMembers)s|other": "%(count)s membres dont %(commaSeparatedMembers)s", + "Including %(commaSeparatedMembers)s": "Dont %(commaSeparatedMembers)s", + "View all %(count)s members|one": "Afficher le membre", + "View all %(count)s members|other": "Afficher les %(count)s membres", + "Failed to send": "Échec de l’envoi" } From 4661fd2d2ea39a22a545cd21a932573717f9e47c Mon Sep 17 00:00:00 2001 From: Szimszon Date: Tue, 27 Apr 2021 05:48:56 +0000 Subject: [PATCH 0110/1449] Translated using Weblate (Hungarian) Currently translated at 100.0% (2924 of 2924 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/hu/ --- src/i18n/strings/hu.json | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/hu.json b/src/i18n/strings/hu.json index 252badd54a..e6e5575674 100644 --- a/src/i18n/strings/hu.json +++ b/src/i18n/strings/hu.json @@ -3292,5 +3292,16 @@ "Zoom in": "Nagyít", "Zoom out": "Kicsinyít", "%(seconds)ss left": "%(seconds)s mp van vissza", - "Show options to enable 'Do not disturb' mode": "Mutassa a lehetőséget a „Ne zavarjanak” módhoz" + "Show options to enable 'Do not disturb' mode": "Mutassa a lehetőséget a „Ne zavarjanak” módhoz", + "You can select all or individual messages to retry or delete": "Újraküldéshez vagy törléshez kiválaszthatja az üzeneteket egyenként vagy az összeset együtt", + "Retry all": "Mind újraküldése", + "Sending": "Küldés", + "Delete all": "Mind törlése", + "Some of your messages have not been sent": "Néhány üzenete nem lett elküldve", + "%(count)s members including %(commaSeparatedMembers)s|one": "%(commaSeparatedMembers)s", + "%(count)s members including %(commaSeparatedMembers)s|other": "%(count)s résztvevő beleértve: %(commaSeparatedMembers)s", + "Including %(commaSeparatedMembers)s": "Beleértve: %(commaSeparatedMembers)s", + "View all %(count)s members|one": "1 résztvevő megmutatása", + "View all %(count)s members|other": "Az összes %(count)s résztvevő megmutatása", + "Failed to send": "Küldés sikertelen" } From e3e0de5f36ca50695a38a597fe9a7a63cdc6c2f4 Mon Sep 17 00:00:00 2001 From: jelv Date: Tue, 27 Apr 2021 11:11:59 +0000 Subject: [PATCH 0111/1449] Translated using Weblate (Dutch) Currently translated at 100.0% (2924 of 2924 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/nl/ --- src/i18n/strings/nl.json | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/nl.json b/src/i18n/strings/nl.json index 10a921b11d..8b2dea7885 100644 --- a/src/i18n/strings/nl.json +++ b/src/i18n/strings/nl.json @@ -3183,5 +3183,16 @@ "Zoom out": "Uitzoomen", "%(seconds)ss left": "%(seconds)s's over", "Change server ACLs": "Wijzig server ACL's", - "Show options to enable 'Do not disturb' mode": "Toon opties om de 'Niet storen' modus in te schakelen" + "Show options to enable 'Do not disturb' mode": "Toon opties om de 'Niet storen' modus in te schakelen", + "You can select all or individual messages to retry or delete": "U kunt alles selecteren of per individueel bericht opnieuw verzenden of verwijderen", + "Sending": "Wordt verstuurd", + "Retry all": "Alles opnieuw proberen", + "Delete all": "Verwijder alles", + "Some of your messages have not been sent": "Enkele van uw berichten zijn niet verstuurd", + "%(count)s members including %(commaSeparatedMembers)s|one": "%(commaSeparatedMembers)s", + "%(count)s members including %(commaSeparatedMembers)s|other": "%(count)s leden inclusief %(commaSeparatedMembers)s", + "Including %(commaSeparatedMembers)s": "Inclusief %(commaSeparatedMembers)s", + "View all %(count)s members|one": "Bekijk 1 lid", + "View all %(count)s members|other": "Bekijk alle %(count)s leden", + "Failed to send": "Verzenden is mislukt" } From bbb1670b509413ec41c601d6b0457db6695a2add Mon Sep 17 00:00:00 2001 From: vintergatan Date: Tue, 27 Apr 2021 16:12:19 +0000 Subject: [PATCH 0112/1449] Translated using Weblate (Swedish) Currently translated at 99.7% (2916 of 2924 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/sv/ --- src/i18n/strings/sv.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/sv.json b/src/i18n/strings/sv.json index 3517173ded..63db2ccee2 100644 --- a/src/i18n/strings/sv.json +++ b/src/i18n/strings/sv.json @@ -3228,5 +3228,8 @@ "Zoom out": "Zooma ut", "%(seconds)ss left": "%(seconds)ss kvar", "Change server ACLs": "Ändra server-ACLer", - "Show options to enable 'Do not disturb' mode": "Visa alternativ för att aktivera 'Stör ej'-läget" + "Show options to enable 'Do not disturb' mode": "Visa alternativ för att aktivera 'Stör ej'-läget", + "Delete all": "Radera alla", + "View all %(count)s members|one": "Visa 1 medlem", + "View all %(count)s members|other": "Visa alla %(count)s medlemmar" } From 7430d0db17922e95244e5db6a3fe90bb9766d3df Mon Sep 17 00:00:00 2001 From: Jeff Huang Date: Tue, 27 Apr 2021 02:00:20 +0000 Subject: [PATCH 0113/1449] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (2924 of 2924 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/zh_Hant/ --- src/i18n/strings/zh_Hant.json | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index cedbb8f52c..134f61a435 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -3300,5 +3300,16 @@ "Zoom out": "縮小", "%(seconds)ss left": "剩%(seconds)s秒", "Change server ACLs": "變更伺服器 ACL", - "Show options to enable 'Do not disturb' mode": "顯示啟用「勿打擾」模式的選項" + "Show options to enable 'Do not disturb' mode": "顯示啟用「勿打擾」模式的選項", + "You can select all or individual messages to retry or delete": "您可以選取全部或單獨的訊息來重試或刪除", + "Sending": "正在傳送", + "Retry all": "重試全部", + "Delete all": "刪除全部", + "Some of your messages have not been sent": "您的部份訊息未傳送", + "%(count)s members including %(commaSeparatedMembers)s|one": "%(commaSeparatedMembers)s", + "%(count)s members including %(commaSeparatedMembers)s|other": "%(count)s 個成員包含 %(commaSeparatedMembers)s", + "Including %(commaSeparatedMembers)s": "包含 %(commaSeparatedMembers)s", + "View all %(count)s members|one": "檢視 1 個成員", + "View all %(count)s members|other": "檢視全部 %(count)s 個成員", + "Failed to send": "傳送失敗" } From 434cf65598f6ccc87042fe51ffd4f9be3d10d911 Mon Sep 17 00:00:00 2001 From: Tirifto Date: Tue, 27 Apr 2021 12:59:01 +0000 Subject: [PATCH 0114/1449] Translated using Weblate (Esperanto) Currently translated at 98.6% (2884 of 2924 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/eo/ --- src/i18n/strings/eo.json | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/eo.json b/src/i18n/strings/eo.json index 62e8e1f98a..f4d30b40b7 100644 --- a/src/i18n/strings/eo.json +++ b/src/i18n/strings/eo.json @@ -3188,5 +3188,35 @@ "Space options": "Agordoj de aro", "Space Home": "Hejmo de aro", "with state key %(stateKey)s": "kun statŝlosilo %(stateKey)s", - "with an empty state key": "kun malplena statŝlosilo" + "with an empty state key": "kun malplena statŝlosilo", + "Invited people will be able to read old messages.": "Invititoj povos legi malnovajn mesaĝojn.", + "Adding...": "Aldonante…", + "Add existing rooms": "Aldoni jamajn ĉambrojn", + "View message": "Montri mesaĝon", + "Zoom in": "Zomi", + "Zoom out": "Malzomi", + "%(count)s people you know have already joined|one": "%(count)s persono, kiun vi konas, jam aliĝis", + "%(count)s people you know have already joined|other": "%(count)s personoj, kiujn vi konas, jam aliĝis", + "%(count)s members including %(commaSeparatedMembers)s|one": "%(commaSeparatedMembers)s", + "%(count)s members including %(commaSeparatedMembers)s|other": "%(count)s anoj inkluzive je %(commaSeparatedMembers)s", + "Including %(commaSeparatedMembers)s": "Inkluzive je %(commaSeparatedMembers)s", + "View all %(count)s members|one": "Montri 1 anon", + "View all %(count)s members|other": "Montri ĉiujn %(count)s anojn", + "Accept on your other login…": "Akceptu per via alia saluto…", + "Stop & send recording": "Ĉesi kaj sendi registrajon", + "Record a voice message": "Registri voĉmesaĝon", + "Quick actions": "Rapidaj agoj", + "Invite to just this room": "Inviti nur al ĉi tiu ĉambro", + "%(seconds)ss left": "%(seconds)s sekundoj restas", + "Failed to send": "Malsukcesis sendi", + "Change server ACLs": "Ŝanĝi servilblokajn listojn", + "Warn before quitting": "Averti antaŭ ĉesigo", + "Workspace: ": "Laborspaco: ", + "Manage & explore rooms": "Administri kaj esplori ĉambrojn", + "unknown person": "nekonata persono", + "Send and receive voice messages (in development)": "Sendi kaj ricevi voĉmesaĝojn (evoluigate)", + "Show options to enable 'Do not disturb' mode": "Montri elekteblojn por ŝalti sendistran reĝimon", + "%(deviceId)s from %(ip)s": "%(deviceId)s de %(ip)s", + "Review to ensure your account is safe": "Kontrolu por certigi sekurecon de via konto", + "Sends the given message as a spoiler": "Sendas la donitan mesaĝon kiel malkaŝon de intrigo" } From 70d0df53256a5081694b43b9a635a6ea391f8296 Mon Sep 17 00:00:00 2001 From: random Date: Tue, 27 Apr 2021 15:57:04 +0000 Subject: [PATCH 0115/1449] Translated using Weblate (Italian) Currently translated at 100.0% (2924 of 2924 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/it/ --- src/i18n/strings/it.json | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/it.json b/src/i18n/strings/it.json index 5e53aced69..98272f9e49 100644 --- a/src/i18n/strings/it.json +++ b/src/i18n/strings/it.json @@ -3297,5 +3297,16 @@ "Zoom out": "Rimpicciolisci", "%(seconds)ss left": "%(seconds)ss rimanenti", "Change server ACLs": "Modifica le ACL del server", - "Show options to enable 'Do not disturb' mode": "Mostra opzioni per attivare la modalità \"Non disturbare\"" + "Show options to enable 'Do not disturb' mode": "Mostra opzioni per attivare la modalità \"Non disturbare\"", + "You can select all or individual messages to retry or delete": "Puoi selezionare tutti o alcuni messaggi da riprovare o eliminare", + "Sending": "Invio in corso", + "Retry all": "Riprova tutti", + "Delete all": "Elimina tutti", + "Some of your messages have not been sent": "Alcuni tuoi messaggi non sono stati inviati", + "%(count)s members including %(commaSeparatedMembers)s|one": "%(commaSeparatedMembers)s", + "%(count)s members including %(commaSeparatedMembers)s|other": "%(count)s membri inclusi %(commaSeparatedMembers)s", + "Including %(commaSeparatedMembers)s": "Inclusi %(commaSeparatedMembers)s", + "View all %(count)s members|one": "Vedi 1 membro", + "View all %(count)s members|other": "Vedi tutti i %(count)s membri", + "Failed to send": "Invio fallito" } From bd5178d96fdaf7f2d0eece9130d83e2e9a2252b3 Mon Sep 17 00:00:00 2001 From: Hivaa Date: Tue, 27 Apr 2021 11:48:40 +0000 Subject: [PATCH 0116/1449] Translated using Weblate (Persian) Currently translated at 20.5% (600 of 2924 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/fa/ --- src/i18n/strings/fa.json | 322 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 320 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/fa.json b/src/i18n/strings/fa.json index d036a55c23..5948048561 100644 --- a/src/i18n/strings/fa.json +++ b/src/i18n/strings/fa.json @@ -223,7 +223,7 @@ "Home": "خانه", "Hangup": "قطع", "For security, this session has been signed out. Please sign in again.": "برای امنیت، این نشست نامعتبر شده است. لطفاً دوباره وارد سیستم شوید.", - "We couldn't log you in": "ما نتوانستیم شما را وارد حسابتان کنیم", + "We couldn't log you in": "نتوانستیم شما را وارد کنیم", "Trust": "اعتماد کن", "Only continue if you trust the owner of the server.": "تنها در صورتی که به صاحب سرور اطمینان دارید، ادامه دهید.", "Identity server has no terms of service": "سرور هویت‌سنجی، شرایط استفاده از خدمت (terms of service) را مشخص نکرده‌است", @@ -314,5 +314,323 @@ "e.g. %(exampleValue)s": "برای مثال %(exampleValue)s", "Explore rooms": "کاوش اتاق", "Sign In": "ورود", - "Create Account": "ایجاد اکانت" + "Create Account": "ایجاد اکانت", + "Use an identity server": "از سرور هویت‌سنجی استفاده کنید", + "Invites user with given id to current room": "کاربر با شناسه داده شده را به اتاق فعلی دعوت کن", + "Sets the room name": "نام اتاق را تنظیم می کند", + "This room has no topic.": "این اتاق هیچ موضوعی ندارد.", + "Failed to set topic": "تنظیم موضوع موفقیت‌آمیز نبود", + "Gets or sets the room topic": "موضوع اتاق را دریافت یا تنظیم می‌کند", + "Changes your avatar in all rooms": "تصویر نمایه خود را در همه‌ی اتاق‌ها تغییر دهید", + "Changes your avatar in this current room only": "تصویر نمایه خود را تنها در این اتاق تغییر دهید", + "Changes the avatar of the current room": "تصویر نمایه اتاق فعلی را تغییر دهید", + "Changes your display nickname": "نام نمایشی خود را تغییر دهید", + "Changes your display nickname in the current room only": "نام نمایشی خود را تنها در اتاق فعلی تغییر دهید", + "Double check that your server supports the room version chosen and try again.": "بررسی کنید که کارگزار شما از نسخه اتاق انتخاب‌شده پشتیبانی کرده و دوباره امتحان کنید.", + "Error upgrading room": "خطا در ارتقاء نسخه اتاق", + "You do not have the required permissions to use this command.": "شما مجوزهای لازم را برای استفاده از این دستور ندارید.", + "Upgrades a room to a new version": "یک اتاق را به نسخه جدید ارتقا دهید", + "To use it, just wait for autocomplete results to load and tab through them.": "برای استفاده از آن ، لطفا منتظر بمانید تا نتایج تکمیل خودکار بارگیری شده و آنها را مرور کنید.", + "Searches DuckDuckGo for results": "در سایت DuckDuckGo جستجو می‌کند", + "Sends a message as html, without interpreting it as markdown": "پیام را به صورت html می فرستد ، بدون اینکه آن را به عنوان markdown تفسیر کند", + "Sends a message as plain text, without interpreting it as markdown": "پیام را به صورت متن ساده و بدون تفسیر آن به عنوان markdown ارسال می کند", + "Prepends ( ͡° ͜ʖ ͡°) to a plain-text message": "(͡ ° ͜ʖ ͡ °) را به ابتدای یک پیام متنی ساده اضافه می‌کند", + "Prepends ┬──┬ ノ( ゜-゜ノ) to a plain-text message": "┬──┬ ノ (゜ - ゜ ノ) را به ابتدای یک پیام متنی ساده اضافه می‌کند", + "Prepends (╯°□°)╯︵ ┻━┻ to a plain-text message": "(╯ ° □ °) ╯︵ ┻━┻) را به ابتدای یک پیام متنی ساده اضافه می‌کند", + "Prepends ¯\\_(ツ)_/¯ to a plain-text message": "¯ \\ _ (ツ) _ / ¯ را به ابتدای یک پیام متنی ساده اضافه می‌کند", + "Sends the given message as a spoiler": "پیام داده شده را به عنوان اسپویلر ارسال می کند", + "Usage": "استفاده", + "Other": "دیگر", + "Effects": "جلوه‌ها", + "Actions": "اقدامات", + "Messages": "پیام ها", + "Setting up keys": "تنظیم کلیدها", + "Go Back": "برگرد", + "Are you sure you want to cancel entering passphrase?": "آیا مطمئن هستید که می خواهید وارد کردن عبارت امنیتی را لغو کنید؟", + "Cancel entering passphrase?": "وارد کردن عبارت امنیتی لغو شود؟", + "Missing room_id in request": "room_id در صورت درخواست وجود ندارد", + "Missing user_id in request": "user_id در صورت درخواست وجود ندارد", + "Room %(roomId)s not visible": "اتاق %(roomId)s قابل مشاهده نیست", + "You do not have permission to do that in this room.": "شما مجاز به انجام این کار در این اتاق نیستید.", + "You are not in this room.": "شما در این اتاق نیستید.", + "Power level must be positive integer.": "سطح قدرت باید عدد صحیح مثبت باشد.", + "This room is not recognised.": "این اتاق شناخته نشده است.", + "Missing roomId.": "شناسه‌ی اتاق گم‌شده", + "Unable to create widget.": "ایجاد ابزارک امکان پذیر نیست.", + "You need to be able to invite users to do that.": "نیاز است که شما قادر به دعوت کاربران به آن باشید.", + "You need to be logged in.": "شما باید وارد شوید.", + "Failed to invite the following users to the %(roomName)s room:": "دعوت کاربران زیر به اتاق %(roomName)s موفقیت‌آمیز نبود:", + "Failed to invite users to the room:": "دعوت کاربران به اتاق موفقیت‌آمیز نبود:", + "Failed to invite": "دعوت موفقیت‌آمیز نبود", + "Custom (%(level)s)": "%(level)s دلخواه", + "Moderator": "معاون", + "Restricted": "ممنوع", + "Use your account or create a new one to continue.": "برای ادامه کار از حساب کاربری خود استفاده کرده و یا حساب کاربری جدیدی ایجاد کنید.", + "Sign In or Create Account": "وارد شوید یا حساب کاربری بسازید", + "Zimbabwe": "زیمبابوه", + "Zambia": "زامبیا", + "Yemen": "یمن", + "Western Sahara": "صحرای غربی", + "Wallis & Futuna": "والیس و فوتونا", + "Vietnam": "ویتنام", + "Venezuela": "ونزوئلا", + "Vatican City": "شهر واتیکان", + "Vanuatu": "وانواتو", + "Uzbekistan": "ازبکستان", + "Uruguay": "اروگوئه", + "United Arab Emirates": "امارات متحده عربی", + "Ukraine": "اوکراین", + "Uganda": "اوگاندا", + "U.S. Virgin Islands": "جزایر ویرجین ایالات متحده", + "Tuvalu": "تووالو", + "Turks & Caicos Islands": "جزایر ترک و کایکوس", + "Turkmenistan": "ترکمنستان", + "Turkey": "بوقلمون", + "Tunisia": "تونس", + "Trinidad & Tobago": "ترینیداد و توباگو", + "Tonga": "تونگا", + "Tokelau": "توكلائو", + "Togo": "رفتن", + "Timor-Leste": "تیمور-لسته", + "Thailand": "تایلند", + "Tanzania": "تانزانیا", + "Tajikistan": "تاجیکستان", + "Taiwan": "تایوان", + "São Tomé & Príncipe": "سائو تومه و پرنسیپ", + "Syria": "سوریه", + "Switzerland": "سوئیس", + "Sweden": "سوئد", + "Swaziland": "سوازیلند", + "Svalbard & Jan Mayen": "سوالبارد و جان ماین", + "Suriname": "سورینام", + "Sudan": "سودان", + "St. Vincent & Grenadines": "سنت وینسنت و گرنادین ها", + "St. Pierre & Miquelon": "سنت پیر و میکلون", + "St. Martin": "سنت مارتین", + "St. Lucia": "سنت لوسیا", + "St. Kitts & Nevis": "سنت کیتس و نویس", + "St. Helena": "سنت هلنا", + "St. Barthélemy": "سنت بارتلمی", + "Sri Lanka": "سری لانکا", + "Spain": "اسپانیا", + "South Sudan": "سودان جنوبی", + "South Korea": "کره جنوبی", + "South Georgia & South Sandwich Islands": "جزایر جورجیا جنوبی", + "South Africa": "آفریقای جنوبی", + "Somalia": "سومالی", + "Solomon Islands": "جزایر سلیمان", + "Slovenia": "اسلوونی", + "Slovakia": "اسلواکی", + "Sint Maarten": "سینت مارتن", + "Singapore": "سنگاپور", + "Sierra Leone": "سیرا لئون", + "Seychelles": "سیشل", + "Serbia": "صربستان", + "Senegal": "سنگال", + "Saudi Arabia": "عربستان سعودی", + "San Marino": "سان مارینو", + "Samoa": "ساموآ", + "Réunion": "ریونیون", + "Rwanda": "رواندا", + "Russia": "روسیه", + "Romania": "رومانی", + "Qatar": "قطر", + "Puerto Rico": "پورتوریکو", + "Portugal": "کشور پرتغال", + "Poland": "لهستان", + "Pitcairn Islands": "جزایر پیتکرن", + "Philippines": "فیلیپین", + "Peru": "پرو", + "Paraguay": "پاراگوئه", + "Papua New Guinea": "پاپوآ گینه نو", + "Panama": "پاناما", + "Palestine": "فلسطین", + "Palau": "پالائو", + "Pakistan": "پاکستان", + "Oman": "عمان", + "Norway": "نروژ", + "Northern Mariana Islands": "جزایر ماریانای شمالی", + "North Korea": "کره شمالی", + "Norfolk Island": "جزیره نورفولک", + "Niue": "نیوئه", + "Nigeria": "نیجریه", + "Niger": "نیجر", + "Nicaragua": "نیکاراگوئه", + "New Zealand": "نیوزلند", + "New Caledonia": "کالدونیای جدید", + "Netherlands": "هلند", + "Nepal": "نپال", + "Nauru": "نائورو", + "Namibia": "ناميبيا", + "Myanmar": "میانمار", + "Mozambique": "موزامبیک", + "Morocco": "مراکش", + "Montserrat": "مونتسرات", + "Montenegro": "مونته نگرو", + "Mongolia": "مغولستان", + "Monaco": "موناکو", + "Moldova": "مولداوی", + "Micronesia": "میکرونزی", + "Mexico": "مکزیک", + "Mayotte": "مایوت", + "Mauritius": "موریس", + "Mauritania": "موریتانی", + "Martinique": "مارتینیک", + "Marshall Islands": "جزایر مارشال", + "Malta": "مالت", + "Mali": "مالی", + "Maldives": "مالدیو", + "Malaysia": "مالزی", + "Malawi": "مالاوی", + "Madagascar": "ماداگاسکار", + "Macedonia": "مقدونیه", + "Macau": "ماکائو", + "Luxembourg": "لوکزامبورگ", + "Lithuania": "لیتوانی", + "Liechtenstein": "لیختن اشتاین", + "Libya": "لیبی", + "Liberia": "لیبریا", + "Lesotho": "لسوتو", + "Lebanon": "لبنان", + "Latvia": "لتونی", + "Laos": "لائوس", + "Kyrgyzstan": "قرقیزستان", + "Kuwait": "کویت", + "Kosovo": "کوزوو", + "Kiribati": "کیریباتی", + "Kenya": "کنیا", + "Kazakhstan": "قزاقستان", + "Jordan": "اردن", + "Jersey": "جرسی", + "Japan": "ژاپن", + "Jamaica": "جامائیکا", + "Italy": "ایتالیا", + "Israel": "رژیم غاصب صهیونیستی", + "Isle of Man": "جزیره من", + "Ireland": "ایرلند", + "Iraq": "عراق", + "Iran": "ایران", + "Indonesia": "اندونزی", + "India": "هند", + "Iceland": "ایسلند", + "Hungary": "مجارستان", + "Hong Kong": "هنگ کنگ", + "Honduras": "هندوراس", + "Heard & McDonald Islands": "جزایر هرد و مک دونالد", + "Haiti": "هائیتی", + "Guyana": "گویان", + "Guinea-Bissau": "گینه بیسائو", + "Guinea": "گینه", + "Guernsey": "گرنزی", + "Guatemala": "گواتمالا", + "Guam": "گوام", + "Guadeloupe": "گوادلوپ", + "Grenada": "گرنادا", + "Greenland": "گرینلند", + "Greece": "یونان", + "Gibraltar": "جبل الطارق", + "Ghana": "غنا", + "Germany": "آلمان", + "Georgia": "گرجستان", + "Gambia": "گامبیا", + "Gabon": "گابن", + "French Southern Territories": "سرزمین های جنوبی فرانسه", + "French Polynesia": "پلینزی فرانسه", + "French Guiana": "گویان فرانسه", + "France": "فرانسه", + "Finland": "فنلاند", + "Fiji": "فیجی", + "Faroe Islands": "جزایر فارو", + "Falkland Islands": "جزایر فالکلند", + "Ethiopia": "اتیوپی", + "Estonia": "استونی", + "Eritrea": "اریتره", + "Equatorial Guinea": "گینه استوایی", + "El Salvador": "السالوادور", + "Egypt": "مصر", + "Ecuador": "اکوادور", + "Dominican Republic": "جمهوری دومینیکن", + "Dominica": "دومینیکا", + "Djibouti": "جیبوتی", + "Denmark": "دانمارک", + "Côte d’Ivoire": "ساحل عاج", + "Czech Republic": "جمهوری چک", + "Cyprus": "قبرس", + "Curaçao": "کوراسائو", + "Cuba": "کوبا", + "Croatia": "کرواسی", + "Costa Rica": "کاستاریکا", + "Cook Islands": "جزایر کوک", + "Congo - Kinshasa": "کنگو - کینشاسا", + "Congo - Brazzaville": "کنگو - برازاویل", + "Comoros": "کومور", + "Colombia": "کلمبیا", + "Cocos (Keeling) Islands": "جزایر کوکوس (کیلینگ)", + "Christmas Island": "جزیره کریسمس", + "China": "چین", + "Chile": "شیلی", + "Chad": "چاد", + "Central African Republic": "جمهوری آفریقای مرکزی", + "Cayman Islands": "جزایر کیمن", + "Caribbean Netherlands": "کارائیب هلند", + "Cape Verde": "کیپ ورد", + "Canada": "کانادا", + "Cameroon": "کامرون", + "Cambodia": "کامبوج", + "Burundi": "بوروندی", + "Burkina Faso": "بورکینافاسو", + "Bulgaria": "بلغارستان", + "Brunei": "برونئی", + "British Virgin Islands": "جزایر ویرجین بریتانیا", + "British Indian Ocean Territory": "قلمرو اقیانوس هند بریتانیا", + "Brazil": "برزیل", + "Bouvet Island": "جزیره بووت", + "Botswana": "بوتسوانا", + "Bosnia": "بوسنی", + "Bolivia": "بولیوی", + "Bhutan": "بوتان", + "Bermuda": "برمودا", + "Benin": "بنین", + "Belize": "بلیز", + "Belgium": "بلژیک", + "Belarus": "بلاروس", + "Barbados": "باربادوس", + "Bangladesh": "بنگلادش", + "Bahrain": "بحرین", + "Bahamas": "باهاما", + "Azerbaijan": "آذربایجان", + "Austria": "اتریش", + "Australia": "استرالیا", + "Aruba": "آروبا", + "Armenia": "ارمنستان", + "Argentina": "آرژانتین", + "Antigua & Barbuda": "آنتیگوا و باربودا", + "Antarctica": "جنوبگان", + "Anguilla": "آنگویلا", + "Angola": "آنگولا", + "Andorra": "آندورا", + "American Samoa": "ساموآ آمریکایی", + "Algeria": "الجزایر", + "Albania": "آلبانی", + "Åland Islands": "جزایر الند", + "Afghanistan": "افغانستان", + "United States": "ایالات متحده", + "United Kingdom": "انگلستان", + "Your email address does not appear to be associated with a Matrix ID on this Homeserver.": "به نظر نمی‌رسد آدرس ایمیل شما با هیچ کدام از شناسه ماتریکس در این سرور مرتبط باشد.", + "This email address was not found": "این آدرس ایمیل یافت نشد", + "Unable to enable Notifications": "فعال کردن اعلان ها امکان پذیر نیست", + "%(brand)s was not given permission to send notifications - please try again": "به %(brand)s اجازه ارسال اعلان داده نشده است - لطفاً دوباره امتحان کنید", + "%(brand)s does not have permission to send you notifications - please check your browser settings": "%(brand)s اجازه ارسال اعلان به شما را ندارد - لطفاً تنظیمات مرورگر خود را بررسی کنید", + "%(name)s is requesting verification": "%(name)s درخواست تائید دارد", + "Your homeserver rejected your log in attempt. This could be due to things just taking too long. Please try again. If this continues, please contact your homeserver administrator.": "سرور درخواست ورود شما را رد کرد. این می‌تواند به خاطر طولانی شدن فرآیندها باشد. لطفا دوباره امتحان کنید. اگر این مشکل ادامه داشت، لطفا با مدیر سرور تماس بگیرید.", + "Your homeserver was unreachable and was not able to log you in. Please try again. If this continues, please contact your homeserver administrator.": "سرور شما در دسترس نبود و امکان ورود شما میسر نیست. لطفا دوباره امتحان کنید. اگر مشکل ادامه داشت، لطفا با مدیر سرور تماس بگیرید.", + "Try again": "دوباره امتحان کنید", + "Whether you're using %(brand)s on a device where touch is the primary input mechanism": "این که شما از %(brand)s روی دستگاهی استفاده می‌کنید که در آن لامسه مکانیزم اصلی ورودی است", + "We asked the browser to remember which homeserver you use to let you sign in, but unfortunately your browser has forgotten it. Go to the sign in page and try again.": "ما از مرورگر خواستیم تا سروری را که شما برای ورود استفاده می‌کنید به خاطر بسپارد، اما متاسفانه مرورگر شما آن را فراموش کرده‌است. به صفحه‌ی ورود بروید و دوباره امتحان کنید.", + "This action requires accessing the default identity server to validate an email address or phone number, but the server does not have any terms of service.": "این اقدام نیاز به دسترسی به سرور هویت‌سنجی پیش‌فرض برای تایید آدرس ایمیل یا شماره تماس دارد، اما کارگزار هیچ گونه شرایط خدماتی (terms of service) ندارد.", + "The remote side failed to pick up": "طرف دیگر قادر به پاسخ‌دادن نیست", + "Where this page includes identifiable information, such as a room, user or group ID, that data is removed before being sent to the server.": "هرگاه این صفحه شامل اطلاعات قابل شناسایی مانند شناسه‌ی اتاق ، کاربر یا گروه باشد ، این داده‌ها قبل از ارسال به سرور حذف می شوند.", + "Your user agent": "نماینده کاربری شما", + "Whether you're using %(brand)s as an installed Progressive Web App": "این که آیا شما از%(brand)s به عنوان یک PWA استفاده می‌کنید یا نه", + "Whether or not you're using the 'breadcrumbs' feature (avatars above the room list)": "این که آیا از ویژگی 'breadcrumbs' (نمایه‌ی کاربری بالای فهرست اتاق‌ها) استفاده می‌کنید یا خیر" } From 18bd19c3fb0357d652d368c249eeeacab0cc89fb Mon Sep 17 00:00:00 2001 From: waclaw66 Date: Mon, 26 Apr 2021 17:31:35 +0000 Subject: [PATCH 0117/1449] Translated using Weblate (Czech) Currently translated at 100.0% (2924 of 2924 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 | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/cs.json b/src/i18n/strings/cs.json index ac81b49d95..714d34abfa 100644 --- a/src/i18n/strings/cs.json +++ b/src/i18n/strings/cs.json @@ -3214,5 +3214,16 @@ "Zoom out": "Oddálit", "%(seconds)ss left": "Zbývá %(seconds)ss", "Change server ACLs": "Změnit seznamy přístupů serveru", - "Show options to enable 'Do not disturb' mode": "Zobrazit možnosti pro povolení režimu „Nerušit“" + "Show options to enable 'Do not disturb' mode": "Zobrazit možnosti pro povolení režimu „Nerušit“", + "You can select all or individual messages to retry or delete": "Můžete vybrat všechny nebo jednotlivé zprávy, které chcete zkusit poslat znovu nebo odstranit", + "Sending": "Odesílání", + "Retry all": "Zkusit všechny znovu", + "Delete all": "Smazat všechny", + "Some of your messages have not been sent": "Některé z vašich zpráv nebyly odeslány", + "%(count)s members including %(commaSeparatedMembers)s|one": "%(commaSeparatedMembers)s", + "%(count)s members including %(commaSeparatedMembers)s|other": "%(count)s členů včetně %(commaSeparatedMembers)s", + "Including %(commaSeparatedMembers)s": "Včetně %(commaSeparatedMembers)s", + "View all %(count)s members|one": "Zobrazit jednoho člena", + "View all %(count)s members|other": "Zobrazit všech %(count)s členů", + "Failed to send": "Odeslání se nezdařilo" } From 9c6ae0de8ad5beb346e8ee9b6c73f57d45a8f94a Mon Sep 17 00:00:00 2001 From: XoseM Date: Tue, 27 Apr 2021 05:03:05 +0000 Subject: [PATCH 0118/1449] Translated using Weblate (Galician) Currently translated at 100.0% (2924 of 2924 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/gl/ --- src/i18n/strings/gl.json | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/gl.json b/src/i18n/strings/gl.json index 1300815a4c..7b816e94cd 100644 --- a/src/i18n/strings/gl.json +++ b/src/i18n/strings/gl.json @@ -3297,5 +3297,16 @@ "Zoom out": "Alonxar", "%(seconds)ss left": "%(seconds)ss restantes", "Change server ACLs": "Cambiar ACLs do servidor", - "Show options to enable 'Do not disturb' mode": "Mostrar opcións para activar o modo 'Non molestar'" + "Show options to enable 'Do not disturb' mode": "Mostrar opcións para activar o modo 'Non molestar'", + "You can select all or individual messages to retry or delete": "Podes elexir todo ou mensaxes individuais para reintentar ou eliminar", + "Sending": "Enviando", + "Retry all": "Reintentar todo", + "Delete all": "Eliminar todo", + "Some of your messages have not been sent": "Algunha das túas mensaxes non se enviou", + "%(count)s members including %(commaSeparatedMembers)s|one": "%(commaSeparatedMembers)s", + "%(count)s members including %(commaSeparatedMembers)s|other": "%(count)s membros, incluíndo a %(commaSeparatedMembers)s", + "Including %(commaSeparatedMembers)s": "Incluíndo a %(commaSeparatedMembers)s", + "View all %(count)s members|one": "Ver 1 membro", + "View all %(count)s members|other": "Ver tódolos %(count)s membros", + "Failed to send": "Fallou o envío" } From d422066a72c22f281e69f9ed2f11f58fcd5a95ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Mon, 26 Apr 2021 15:40:44 +0000 Subject: [PATCH 0119/1449] Translated using Weblate (Estonian) Currently translated at 100.0% (2924 of 2924 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/et/ --- src/i18n/strings/et.json | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index 282b3f77cf..56f456b6e4 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -3275,5 +3275,16 @@ "Zoom out": "Suumi välja", "%(seconds)ss left": "jäänud %(seconds)s sekundit", "Change server ACLs": "Muuda serveri ligipääsuõigusi", - "Show options to enable 'Do not disturb' mode": "Näita valikuid „Ära sega“ režiimi sisse lülitamiseks" + "Show options to enable 'Do not disturb' mode": "Näita valikuid „Ära sega“ režiimi sisse lülitamiseks", + "You can select all or individual messages to retry or delete": "Sa võid valida kas kõik või mõned sõnumid kas kustutamiseks või uuesti saatmiseks", + "Sending": "Saadan", + "Retry all": "Proovi kõikidega uuesti", + "Delete all": "Kustuta kõik", + "Some of your messages have not been sent": "Mõned sinu sõnumid on saatmata", + "%(count)s members including %(commaSeparatedMembers)s|one": "%(commaSeparatedMembers)s", + "%(count)s members including %(commaSeparatedMembers)s|other": "%(count)s liiget, sealhulgas %(commaSeparatedMembers)s", + "Including %(commaSeparatedMembers)s": "Sealhulgas %(commaSeparatedMembers)s", + "View all %(count)s members|one": "Vaata üht liiget", + "View all %(count)s members|other": "Vaata kõiki %(count)s liiget", + "Failed to send": "Saatmine ei õnnestunud" } From 22ac0359743dc99cd93a04f61702d255798647e9 Mon Sep 17 00:00:00 2001 From: Hakim Oubouali Date: Tue, 27 Apr 2021 09:35:53 +0000 Subject: [PATCH 0120/1449] Translated using Weblate (Central Atlas Tamazight) Currently translated at 1.1% (35 of 2924 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/tzm/ --- src/i18n/strings/tzm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/tzm.json b/src/i18n/strings/tzm.json index ba63af5fb0..6b0fa316e6 100644 --- a/src/i18n/strings/tzm.json +++ b/src/i18n/strings/tzm.json @@ -4,7 +4,7 @@ "Actions": "Tugawin", "Messages": "Tuzinin", "Cancel": "Sser", - "Create Account": "Ssenflul amiḍan", + "Create Account": "senflul amiḍan", "Sign In": "Kcem", "Name or Matrix ID": "Isem neɣ ID Matrix", "Dec": "Duj", From 8b644e783edd9da0b2935239a646e49e12458341 Mon Sep 17 00:00:00 2001 From: Ayush PS Date: Wed, 28 Apr 2021 23:23:51 +0530 Subject: [PATCH 0121/1449] Finally fixes two todays --- src/components/structures/MessagePanel.js | 26 +++++++++++++---------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index 132d9ab4c3..cc4ab1b2d4 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -542,11 +542,13 @@ export default class MessagePanel extends React.Component { } if (!grouper) { const wantTile = this._shouldShowEvent(mxEv); + const isGrouped =false if (wantTile) { // make sure we unpack the array returned by _getTilesForEvent, // otherwise react will auto-generate keys and we will end up // replacing all of the DOM elements every time we paginate. - ret.push(...this._getTilesForEvent(prevEvent, mxEv, last, nextEvent, nextTile)); + ret.push(...this._getTilesForEvent(prevEvent, mxEv, last, isGrouped, + nextEvent, nextTile)); prevEvent = mxEv; } @@ -562,7 +564,7 @@ export default class MessagePanel extends React.Component { return ret; } - _getTilesForEvent(prevEvent, mxEv, last, nextEvent, nextEventWithTile) { + _getTilesForEvent(prevEvent, mxEv, last, isGrouped=false, nextEvent, nextEventWithTile) { const TileErrorBoundary = sdk.getComponent('messages.TileErrorBoundary'); const EventTile = sdk.getComponent('rooms.EventTile'); const DateSeparator = sdk.getComponent('messages.DateSeparator'); @@ -582,7 +584,7 @@ export default class MessagePanel extends React.Component { // do we need a date separator since the last event? const wantsDateSeparator = this._wantsDateSeparator(prevEvent, eventDate); - if (wantsDateSeparator) { + if (wantsDateSeparator && !isGrouped) { const dateSeparator =
  • ; ret.push(dateSeparator); } @@ -966,9 +968,9 @@ class CreationGrouper { const DateSeparator = sdk.getComponent('messages.DateSeparator'); const EventListSummary = sdk.getComponent('views.elements.EventListSummary'); - const panel = this.panel; const ret = []; + const isGrouped=true; const createEvent = this.createEvent; const lastShownEvent = this.lastShownEvent; @@ -982,12 +984,12 @@ class CreationGrouper { // If this m.room.create event should be shown (room upgrade) then show it before the summary if (panel._shouldShowEvent(createEvent)) { // pass in the createEvent as prevEvent as well so no extra DateSeparator is rendered - ret.push(...panel._getTilesForEvent(createEvent, createEvent, false)); + ret.push(...panel._getTilesForEvent(createEvent, createEvent)); } for (const ejected of this.ejectedEvents) { ret.push(...panel._getTilesForEvent( - createEvent, ejected, createEvent === lastShownEvent, + createEvent, ejected, createEvent === lastShownEvent,isGrouped )); } @@ -996,7 +998,7 @@ class CreationGrouper { // of EventListSummary, render each member event as if the previous // one was itself. This way, the timestamp of the previous event === the // timestamp of the current event, and no DateSeparator is inserted. - return panel._getTilesForEvent(e, e, e === lastShownEvent); + return panel._getTilesForEvent(e, e, e === lastShownEvent, isGrouped); }).reduce((a, b) => a.concat(b), []); // Get sender profile from the latest event in the summary as the m.room.create doesn't contain one const ev = this.events[this.events.length - 1]; @@ -1081,7 +1083,7 @@ class RedactionGrouper { const DateSeparator = sdk.getComponent('messages.DateSeparator'); const EventListSummary = sdk.getComponent('views.elements.EventListSummary'); - + const isGrouped=true; const panel = this.panel; const ret = []; const lastShownEvent = this.lastShownEvent; @@ -1098,10 +1100,12 @@ class RedactionGrouper { ); const senders = new Set(); + let eventTiles = this.events.map((e, i) => { senders.add(e.sender); const prevEvent = i === 0 ? this.prevEvent : this.events[i - 1]; - return panel._getTilesForEvent(prevEvent, e, e === lastShownEvent, this.nextEvent, this.nextEventTile); + return panel._getTilesForEvent( + prevEvent, e, e === lastShownEvent, isGrouped, this.nextEvent, this.nextEventTile); }).reduce((a, b) => a.concat(b), []); if (eventTiles.length === 0) { @@ -1180,7 +1184,7 @@ class MemberGrouper { const DateSeparator = sdk.getComponent('messages.DateSeparator'); const MemberEventListSummary = sdk.getComponent('views.elements.MemberEventListSummary'); - + const isGrouped=true; const panel = this.panel; const lastShownEvent = this.lastShownEvent; const ret = []; @@ -1213,7 +1217,7 @@ class MemberGrouper { // of MemberEventListSummary, render each member event as if the previous // one was itself. This way, the timestamp of the previous event === the // timestamp of the current event, and no DateSeparator is inserted. - return panel._getTilesForEvent(e, e, e === lastShownEvent); + return panel._getTilesForEvent(e, e, e === lastShownEvent, isGrouped); }).reduce((a, b) => a.concat(b), []); if (eventTiles.length === 0) { From 81f2e6744377dc3f2f84575b46403a6328785150 Mon Sep 17 00:00:00 2001 From: Ayush PS Date: Wed, 28 Apr 2021 23:40:23 +0530 Subject: [PATCH 0122/1449] Fixed Linting errors --- src/components/structures/MessagePanel.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index cc4ab1b2d4..c6d45f87d8 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -542,12 +542,12 @@ export default class MessagePanel extends React.Component { } if (!grouper) { const wantTile = this._shouldShowEvent(mxEv); - const isGrouped =false + const isGrouped =false; if (wantTile) { // make sure we unpack the array returned by _getTilesForEvent, // otherwise react will auto-generate keys and we will end up // replacing all of the DOM elements every time we paginate. - ret.push(...this._getTilesForEvent(prevEvent, mxEv, last, isGrouped, + ret.push(...this._getTilesForEvent(prevEvent, mxEv, last, isGrouped, nextEvent, nextTile)); prevEvent = mxEv; } @@ -989,7 +989,7 @@ class CreationGrouper { for (const ejected of this.ejectedEvents) { ret.push(...panel._getTilesForEvent( - createEvent, ejected, createEvent === lastShownEvent,isGrouped + createEvent, ejected, createEvent === lastShownEvent, isGrouped, )); } From 1802adb4d23699e7a14bd7b1ab29e4ff39a2b7a7 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 28 Apr 2021 22:47:08 +0100 Subject: [PATCH 0123/1449] Iterate styling and decoration for the beta prompts --- res/css/structures/_SpaceRoomView.scss | 18 +++++++++++++ res/css/views/beta/_BetaCard.scss | 5 +++- res/img/betas/spaces.png | Bin 136319 -> 1603479 bytes src/components/structures/SpaceRoomView.tsx | 18 +++++++++++-- src/components/views/beta/BetaCard.tsx | 2 +- src/i18n/strings/en_EN.json | 6 ++++- src/settings/{Settings.ts => Settings.tsx} | 28 +++++++++++++++----- 7 files changed, 65 insertions(+), 12 deletions(-) rename src/settings/{Settings.ts => Settings.tsx} (96%) diff --git a/res/css/structures/_SpaceRoomView.scss b/res/css/structures/_SpaceRoomView.scss index bfb796af3c..d3b437d6d5 100644 --- a/res/css/structures/_SpaceRoomView.scss +++ b/res/css/structures/_SpaceRoomView.scss @@ -81,6 +81,7 @@ $SpaceRoomViewInnerWidth: 428px; color: $secondary-fg-color; margin-top: 12px; margin-bottom: 24px; + max-width: $SpaceRoomViewInnerWidth; } .mx_SpaceRoomView_buttons { @@ -374,6 +375,23 @@ $SpaceRoomViewInnerWidth: 428px; } .mx_SpaceRoomView_inviteTeammates { + // XXX remove this when spaces leaves Beta + .mx_SpaceRoomView_inviteTeammates_betaDisclaimer { + padding: 58px 16px 16px; + position: relative; + border-radius: 8px; + background-color: $header-panel-bg-color; + max-width: $SpaceRoomViewInnerWidth; + margin: 20px 0 30px; + box-sizing: border-box; + + .mx_BetaCard_betaPill { + position: absolute; + left: 16px; + top: 16px; + } + } + .mx_SpaceRoomView_inviteTeammates_buttons { color: $secondary-fg-color; margin-top: 28px; diff --git a/res/css/views/beta/_BetaCard.scss b/res/css/views/beta/_BetaCard.scss index 8369e5ee19..34b84515ce 100644 --- a/res/css/views/beta/_BetaCard.scss +++ b/res/css/views/beta/_BetaCard.scss @@ -29,6 +29,10 @@ limitations under the License. line-height: $font-22px; color: $primary-fg-color; margin: 4px 0 14px; + + .mx_BetaCard_betaPill { + margin-left: 12px; + } } .mx_BetaCard_caption { @@ -62,7 +66,6 @@ limitations under the License. background-color: $accent-color-alt; padding: 4px 10px; border-radius: 8px; - margin-left: 12px; text-transform: uppercase; font-size: 12px; line-height: 15px; diff --git a/res/img/betas/spaces.png b/res/img/betas/spaces.png index b487e477af3741dd6beb769ce75be1813b50ea6b..87394e0a5b107b216e32a17de9415e82d2565385 100644 GIT binary patch literal 1603479 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

    n|J!1vCv5-Guy2NTz-bIsz9rPG1{ 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 z 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

    U>o}PL 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 z

    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:L-^3yxnmF&pOGk-MyoPmi*a-e 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

      SYFg z+%VcLtxNnkY2NrbB@J3~K0}`S-S;<6YEDV)8%vv?E7Q2Sld3UnrTAjxwfcma!?ej^Ff@C79uGu=d*Cc$;KxT#hKQn_wKH^SgYde zucfRygT|d&6Oi{=7o*>L<_h_>Cni{H6+C@57d`vGb*D2!#Q0U(T0u}pjkh`0l{zvC zX~ho2QZ*sIuA8~t8#aFchc+IF@UHbeP;a3Nu)8&4DjW<6(A3uyVO4`eqpnLe9EL?p zV0slLr&Uu+tFZK6vbQQ@ckb>C41`zXsG%-YLxEGg20A*Z^+m8$#liuc2$0Dix(+

      L$HPbnSyjjZ@$TSG*Sb} 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

      eWoB+s z{!0&@$7`>?EE@!{>@^)Zazy^}&;FczC&wTE;qMs$E1H<-xVq+3FtoHO1Xz2p>q#eN zS}_ST>4=u|0_@o>Luzf@{eR+pCm7^da)J$J)LwDg%$aGJu(1IChVxpzbcz;gslnz-B) zU1%c+f!a%`uGsX}idFFo2}}ynQjb5%?EtCx;-G5%RWwx)!_&BRnl? ziM79sIwq{ma+z}L@aX!1eYae_d0jPqfB3yWAgQU8-nYw_FUV`Jyr2{E<`x%JcWZ8D zQL2pFkE>c|58+!W>QCE4QE~;X5L+c#?68d1JZ!PXqb=k!<7wDA4vE>65&)nCfcqw% zb3Rp&UEH$_wSocG@9gbKK3x=DLDZE3*fodzhhSDeFibACjuXI{7#)GlYRksfrfNbF z$jYWd?G#{~m(OtmYXt?tqKfSEeaU)H|IHTj4S>7!8F}PbdjQ`iCZ}W%AZb36lU)=V zbZ7x?OckHo*K74r=pTV?%t&*$sSLJW&sA0$WTg23rP6HqQ$0y`D|Af0 zK#fl7L3?KMGPUN&lqcJ>u6k;5?QWuM3|j^{^)=KXaH2oswQEJSXF3;B1i)|(^>S5G z$dMU0xB7q1!1^;d_SZb3$WyFC2nN-Q$k>}8Z@=+3?{W469qMP?0RR#?$%r;g%Bq<_ zVrAZ)VHj<`+OgHn&^o{%az%Fpp8AW*Hlt(F<`61%u@Qq-MS|3blmY6HB@yEFcOiKCr}rU&>{P`an~{y>vefWh8`Zvy zjU&kgcJW*G^_VTMp)KQ&45FER`DvRIuUb$MBmt&c@ zi~wO@Sh^-VFP@Wsb8}mE;Y{zj>$v2{rsdvKCu9M}AR?Tb_NPFrmbp?!{?6b28>$1g zyi<{{z4Dq;E=RISWt0%9=BVfc0JV~U8p7R8@i$jt3`1$-!|HH;9e@N)c%uN7<^Z5y zKTPQ)APS&X;6TH!Yd{DlxfC}VpM3}(IW$fi@&pg7Mq9M2%0@fg82Qhg9?r#$%(oVFJ(t|(jc|8S(dP~3xL3mC1%1(V5^4;S~4$XJYOarMHsa-TY&nm zH0r35>?L6I6Y|m7X(??sVT2J_Wa9uka`MvEbqNv^Qa!vV56|w(PO~OQG9z*vfZQTjBA@c@~6I!!RH6WEvp z1(aRDUTk-|gXhQVXK=!VPgw#n&kB)-DsD>c83rw}P!&pzy>|@@j=&v*3MRy@t_cV| z*ds@;#dH~mk)MgC^>D;Del)^qqxd&Ra2x+%*eKDoB~NL6eN^=trb221M0z?t3qH>v z7S{x7WMo8X;AB&grk)@`%3y_l2Ai+TwHug`;eOvypiZ@i*y6`EL`or9Ps*}GFpAG~ zY(VVURW|IPeC-5F=E+#r8CsAa%{EUa}7f;@{0-_1qRfOG-ouB4o$Vt zXt6o_+WL)cxp@TRG1**SiEsw{+ydFpj{lC1ec|3)I`lM*o||Ln0Qz?_W}R@@w#Z)*pyrg+ zJ`!+hGjR{8J}K7j#j~#|P#uF0+X9fav%8}@dFyLyT3JtEU*zT{Wp%rPgeGI`9}->) zu8)uAx5uUKzY5n zypC+Av)aWuH4&R~3M=#KKBs6kItB#7?Vp$&*Fhtkz_yEP8o{-2I-p@&nF(f|W2ae) z*hzmwwo~*d`MrE5oUrK1khvGd`H`Mg6i-L&o&oqvJ0~WA*3S(04Ucf5g1I|fI#Eg= z4l@zg?j6U*oMaX;J}0P4MhV5KJ36J$XcR^{hHC}mJv$LP=2@n`8?i>c0igW)siAM> z_|`VS`L-a|SZNaXuZMMBLt>j(pWJM=)Q7NG>ze*D1CNu3PLU;RdC^a3O2XfQ9=_*K;sGrqj1 z+Er$Vhhb)$&V;yvDKVYu%!(_bVr8+n+Q^&wb`J!08ZzZA+_c$5jIUKjp|8)HtWCy? zoUqL}$SLM^e`Qc5W-dofObXN&v!g1uUQA?VWo=7yTkiRCy<)%^eC|fMt$s0uwU;mC z6u8;g!u^F^W(PqoGsO`ua{1DE#4xaj$Oox`$=H+()imD2c(0g2d`Ms`UsUOa5(B zWHuMZ@=_{H1N_?4y+CG~P8y6Oj&6~e$bw`{i=z(i4?CjUoPO(w#?@@6G!x0L0b>XW&l6 z{#+z#mm3xt!oeiJz|3nl?-|gIBgEMmRAZw0i>WLH`>?Zc5J(Q#U&BmP!hJ!T2FDgm zbFCNFHlNV651K5}GBI5D4gkyGX0CO%wyGUnO&AUmngJ;0IJWOOyrbfxcg#*aY+OAj zPNOWv`yY`YJ0o2n_B}VLPUL3*K3z>;l2*AP$DUb|rF=|ors8rCfzr(40aP;1ND@f! zBsSLHJvy!D?F86{2!bwE>+&!hwOjDy{PmiA@|&0B==_ANl&?xL)sp*99+!7NcE2W> zOR=I{dO4!1(nZ7pOSyGg~|!Qq>mmuEWdtkSyH28 z@-uhMi+u8bmOhf{uf6b+Y65+-G$H*Gz>dX5dB=VC$?=1WvQWxvOG*OYRReO~!^W&( zgO({ODikCKVAJuX+BKB`t&-u~k^p9ok0oUHHmW)>2rUoJER~m)<+@BsM`}%9HW7I4 zg-KaoS(dpYa{!TW-%(j|atZUq2|7$Iz!;p=z=W)XF1|nY)Q`!dTv_P8&b#$3naIMJjvSJI{`;?r0|WV)zpx<5 zt!25`&&vPx3zrZm7UUNm>`S`6DyjKnvImf59N^@3+>DwxlfmF(dKDO|Nok(s={B$VGog_Xdp`)2yIJC9wqWm$cCS&og+%;X4FD&iJ&pmit z#&FF}!jrfAU@%Hnhll&e7IodgVpvkND=F%N#Z9ZOVGD>&lo+C!vEV9DZKuzfDRhBO zo+Egz^yEJOi`tQW!`vf`#Y&m$YBI75$3(l6!n5Q+gMq-Utz2dkMxHvRlk+@lr+hv4 z4gw`Yfe9UH9hhpFW7em!JqB>#=;2rKjf zFB>4oML{f%>rElBYSrs-mN8`+=7KHk|nIsX!q_8GIZ%!*?g_!yc8kB{BvIq!_MS!G9W=snR?@MnV z1DL<3<{69HeVeE#B*+$xq-oFV_@H}frzaw+WPC8zdnI2B11=p9gi)*Z0v6vPY75Ex~_1!5->n)|GO58fO|3M1CIO~eW8&Hxno(|}j| zkIBhtY1V2|?rsg*OM3mc24F?)Ej$+kXnf}|Ry5U?)ofHc9BI&9GKqlb(Q-rJGMscCuj%vrhj^l8;D*+L<)2|GtXXmq5Y$<4vpha{gb zsHR=5TUQ{7`+29)R`x9IJ8kDAs{0>#_@q2?*C8q9lCrkEE}wq!vi$u2=^x5T6zAGo zYcf(Q%9V@fWp441%pN)>Q@3u&tLHDEDxZ+MPaf7pZ}!j$dF1hT$juu!WVAS{ZGhR* zsEVD_268_(5ChTsw`*9}unXH8h%fSaWjsvJ&dV#$KO+nH(?_yHEtT8Lw`F{6427(k z+B_zYWZ06e-bF&jcDxb*D2jZuMUQ)*t%=%I5c8CAta8snaU?cM8`x z@w>jY*J2CTo@Jax)4m9fy2^g0CYomkZs-srPk!_#{*rtr$ACp+0p)MoCg^Z?vJG=7o(pl^$*p-gR%Jn5Vao-^n zBDZAarDf~^6y=(A8O@i>a29rNP>%^QM78w^PIK+S+bBlI7rugfivT zJF|wyn1U>S%A;7xide!BG5o+V;>5~Scy^*@81!ucLo_ocD_$jCG&rW1H&8 zXh{b@HQGCfH9`PV4V@s`=pz4A0I3d}-IKYgv}&Nb08(#m)?lkja&vi8a)l9oFk&mw zK|ghT*3{IfP8Ck!-ja3C*6|hOm(0hvwzo`I1mnU+S9UfxWqf*Eilfsq0=w06}8dynd%H@5&aW=&=tt1@zyQMh8Jht0U`fO?Cjzj8Bfhc?AGL z>hk<*OQx|oPRxWdj!hJFni?SNZf;8wfWyjsS~}a;k;rA`EC&uBlM+SRIsFd_N}s}oxA&xf^O`*OzC!m)$6hZ#C)^T67oAnXD4M10VSvXy^O#!2h^Muv$ZM!A)I5Ag4#%=*$Ub9DNq{9 z?gj$4R4CVOY)S_p#@?%|(w|t6;PFQ^(4Zi?R?EzI8a#`Hp|#uK$RuJmI0}pg7im0N z(Xe!Qwi%Hg`UD*7qpZ$mOX^HiJqONV;(>R_Xrn4V5d9d8ehh{$J$neK{Y4dZPQu9L z(g;**hoqZWk!@5rDvJ{`>$W8}dQibBhm_K;BZm{7wz+X!E&-Mh#_H*Uxm{#sS|}t zOuJRp(Y4wR7qV3)C0nqs%SasZ`m?xP-F4)*FTvPXD)Lu<>>cvit53_1e{4#|yU}!- zxA({Gv(PU|aX5<2a#Gtk13K|;=o3W1!E@-5WW(;(P^^9>C3xNq1* zciJt(Mli$Tur3gQc$_Gz^y#+RB?3d&u3d%Wj2kgu042(T>X`~1^&yl|L z2@!Q22#d6PrYI0qtCh{8z*JwK36n#el;sa6w3+*5Xz4u-j76Qk-VYsF92zlGY6AGC z?VG?9Y1u*B_y%RR5d_q1$lN}oA0`Si8%?mT?&+QiYl|{7`3-H$wBw*i?ssaT4g3$a zLGYPtD{FEuKJQ20|1P<5{Fo6qB^cH>ZHEk`_`I2Px4Io|P1Lp>+wLiju_LVVKXK0~ z>8_sB%4oOUQ-)U%6?_=HvV9UK!|PF71OPAA>)DBhW(0WP7#%GB&Q-7u_suilr6yjE zVONHsGiV_(efXwrn(ektinj6{u2~xgjC1h@X(TwZf zcT51-+1uMRKty2LZ(n)oc{zXXteKjrKl63HnNZ7I!;k*NUwp$Eec`j8mNT!uY?f+h zR_)a*SL9cJ>3eu89V6!5;#CY!0~p)5>~$zS`ak4v(#DVHu^mCH*Ta(T5ZKl#`H zJ2`dVY3c5)OL=oiR&L)y(!M8NDkqDl?w6AfKOq@Z$(L^3Qu{TtI4M=cFR{e5+;jgE zk}4J@iSHp`RYw({*VOJebw5;atsI$N-r2%^sUkkA0idhPiW5C z`^h8L9vhj_R(fM6hrpL_?Yf!RY3vsF2f=`#+cv(s|DCrG4(>)MZ_vH^_V(b;g8*Yj z!KAk2idmhiOFuR>IV0O-p;UG?@%5-V*)Qx zeoUy!`Uv*f-}{*#7jk2gNuzDly;+s{xr1`ggA4GzxSlJaymIB6GLxN?;zCJYz4S6- z08iOXIphEh?EiRxT%bv50k)W>b?^a60!Ojg=_pwfyW_)Q25z~k8nXi3T z{903Rnr1M8K1Ki$eWSUmtYtFR^*IHqb;_8NjPaGN(0#jNR+|7%D|T7k@N6#$wUgeeJx-W5g+1aYf-dO@5w3v z%vk_FMdY|`4%LDk3t42u_vcU;m>DlgHWk;&sGM}YwO0kmT#;D+n(A(mU77~abo0hK zfTVHQ@hNdB!NcM^_V_65yu&UejYC|c0ogToWPD^?+G)gNjTPD5+16r39`?_TnWAC< z0L>*B9}FIzWYNk09|?I;%hR}+L8l>G1*3NHwHw12i4QP&2<$s z&0SiT*u%%=d<}us^Ot3|xhAJG+cJJ=URnSoo<4s~*2)OXkaV6JnUX`9xLiWzaD1#N zPyDr?GYK`E-4z6!{WH(YA3lFwF5Oy_J@(*Y!#z4ykf$EHTMpmK(Xo3v(kfpN`3963Dk#l#v30Pfl}?zVcUoT3m@pm0fn-~>;Dt|{Z=WAsIZ#?;g(Hdf9akyy0zJtY~F$6#I=T|J!qyBlTZA;kK>$CDM@Bv#IPP$ z&&tX8iu}zJ93}&Y;O|K%g^KO^63#6t&wlM`c^1a)1^|W+&1Pjf;hFQ-RxcR59w)Kk zG>PuGJz0^2?2Ie|RGULk+(Kogt)iY?JU_>UqlQha0)P-ZVXsE&xQ@F;AREt_icyTC zaNDYP@OB?$=247SEArHNvB0>BjZ3uuO%>7eoB;zXFymSfX!offi8X215x&8Cv;~99 zq3u)8%2f>+1-EU0%s+@%xMpyVRPk))lSco_#2JBMb%m}14h-hCwSrY+GI-d=MnHl= zGQZgNvpXg$984lqlqE3QT!?G{-~ymTu+Xek^c?yKOfIinm$9*!X-USH8di`IVrP}q zv=XqDGNx>$p0-aK7MMl@+9xMi$G$wv}5hHWonSpdO_Py;h+rfu!D5tJZsD5hkL z!?Kd7@Z$b95e&Awp=GxkAhFN(M2;^e_=qmg}2pr)pG*W1oF!CK)TK-KKJZP-;@JKPszgJ6Ec7Qahz*Xb!1#^&$A=q_xUs0ifA~A z(IPR)0DVonQiO^G0}?cYGF; zuxMH9rb#*n4i!?gwp zRLMt5195OBE*$`XoNUDt&cN=?!?s;L^C}YBZMnTwmXUl`P8^<>k9_P00GPMb|1MuT zCzmf@Q^06y#-z?@-T+Y6z_}2p z5*=34(4;s+Jys-Kd=8vuWhS4+G?8OVOAY@K@Y&qj(pDa}(PYwTwO3Vq57%4YH~UWQ zx@&D&1aR*IEhBqIC+caUE(7K(k0JPF>?Lg$nPUlE(^2s$w5xwOfJxW8{as{_%Gl$U%yV-6`gPSG%VVt^Ik+f?j~ta5B&j7N#wxNOi|s3@M-xBAvK9Lp z2Sy~xsLjzZ)86_N)H{md`>x^5K=C&Nw#W)&>t7=6Dr1IuST2Kj771=HSCVqQDwWMm z6gCp@!#&+koJ2e`eHiP~lM6R4XrYsX6pkD_CU@O^3U=XD-AjaZ$;Q@6&N>0NuZ5PF z`T(O9Or0Z!fiXKh9qd)MtM7n=!ffU|JqMG9q7oWnE?`Cgjyys{nl2Mi$EQ zwj*<6IdR634~!(FybC)Y>qxuWmB!93fU#wO8>8~xr#>hT)Ys&d^8mI`NS~PQ%MS9D zv9Y||TDc_^eD}w{@BLCbl8}G@TfYU+t1AWUd8g$`VJ0sdyGwY^8TtIP-;nvyqF%qo zRTSSFn z?kNCXZ2`c+d$LKxf^K%qd$sLL0|DxYy84-6%+Vae(;|?g?u>verGB-2P|QSXGlkQ3 zgGeN8qg+NY0^;yFt~bbugJ?JC@DM`|;ki);M6_i+)HZCgDg92Mc}5cZUE^BjK>&qx ziXQd{Ma~G+dTo*c0Gi`@`#S(|a1Y5wti$j3m_xXRy_M#GET;#*vI<)SKoGI>;n@R{ zPp9y?1Uvh(23zN=CSObr%*-kSHHqTvZRCDgylylFe|2~Uz*G^hts&n`%FZq&R=V0D zQyfL%l;?qy9Z43YglEf6gXNt)DFAHRLSf+UBS&QI_NvUy&BJ!aWomXBIb%z1udiUA z80i8fF(CdQotx6G9V0s-QrX$n!Zlf8xqJzQ>73kNx}n8W+Ju}A7DHdjQq|gc>p-Byw00h-E|PC?FevPlJ#;w5+Vi+c|eIts*Yv zzS7Jv6NdIbd(P4SMrEKViEyoR4MR;}#J1K%XQ>X>CM1y{q#7j8 zRM$hRhZR^ysNHB14j5$n8C%i48U%XU-{#5L*Ito(igCGe>za65J2L*nyW|@eE=n9p zV9IYv32*v57W)cN=J(EYq>(xx2Sz5OmztF;^_FaQH|4cw0~tetS37~AuNIe+nMo;) z&WK~>={eEj#L2s*e-mKXJ5I~qR8IC#^;>`g8_ywt39*5$ydW3;t^LEjbXGhv zI`C(+?`v@Rg$t`PJ$nQwwlB}Tc3#EqCgEU8iIlvr(3Vdx*W?{X4$0i?yljjely7`? zMGbKh_o)R$yi0Zk98Md+#CRsJmCarJJB9myZOb zxWK^0Loyp&4YU;Pm8jYu;4+xup8avMgmi`Vuzp@gD| z%?_#}F*#M3mvJTx2sF>^ph^PZFdf^KL-O_>6tE?fsFMQ48MJdni7P(Yq94ly96sdts<#_I*>0i)tq);?IT;3Xz2*TbHs5Q ziB>8NaLUaZR*`FLDp@sTUBv7JKY}e}E%DH?@YKkP#dHFwY1cOTOgf#83?G7hxE{W* zi$JXB8yzMy@y^#kiBORs2tT0OKNqEZ37{NiMj7}vX4pXXj4W|ROmFf#IIK@!_(0HxmI>VH5~7ekRiM3M~-J0y*0NJUfP2JycXV4^5H8uwYD!PQb}R_&f@iuGd7aZ2MB{ z@!SK|M%idqM?NEIbocD{YoI>`12BQhPe-?`d0 zVKgzrfslIyED%^V{?trV@_tCUIgCgQH19i+hjLe&B?ZO&%kg)?Bi1r}WVk)QY}`GJpp z{EpA40|fZT|LE_ds$L&{XE>-gMi)5%@RaR^&wa;}@0Ne^&;G?5&gu5jEhN@S`S?%% zoZNHQDXF7~)o3)eWun!r$TMI064qiB-&@uspjppx+5-~SJ%HI={e~=j-Aw=$yf>xN zgiZEh0FZKW>C$y&RjeX8Swz8x@7qnV+T8&-KV@1m`fXJI6SA>-OD7b%7q>J@BBSl% zm1_XxscV>#dk)OX%!BWd(R@a>U--IQdgTSVc>T8ATHn$n7Z5m%TUugBS}4li#NPIC zt^`R~pi0B;bQ=H#8Z|qGlkHfd?73}#ZVD{ICbe*_HG&QRj`rwNVC%MbwqaPD=T_r{GngSb|?m+v0;~B|nUYE!PBXCx2(yERjBz4B~xdiHd2de5=QPU}~Tb_9j5p zw_;^w6KrS8D`RZDl!L$TXxn5GK8Q&+MX)Oq)7omfySJ&aUUhc|{t19>Zd5@oY8!ES z=9NpAWNUj11e=tuOOj5=Fwc*RtjB9CI`liSi5-7o*s8kyA z{KW?D)27U#m|p4Dq>VV?(pFpbMw79wT-$8Op^>bt?Q~?T+{d*9Qph*}yAVsYGO|C34ucNqIl*ixk5&6XL{g!<8%b%7*Ge;#enU)*3mQb(`Mt3sN&;GZ7Fy_WO}R@Yo*knX=-BDCDuECq%$3j>ki~4nrZ$8L zvVS(N)$N|yw;RYq4HF!IcF>ZMF@Wg(rb^s&It|(0 zt;+o5j84Suz&`C(cko|B(y4+pYIV8m*xl6nK)lhC0BeE*>s!0q0Ga0H_`;%W!&cUD zt-IA-nVdKv*|8CahdTqi@~S@FL1?L=_>8FJ=C{O#8u ze*N*ir-2nANzOhx?Eu^fhrz5wlL!N22*Y4FveqJ6Lt`G^!E`Yn`6fZ1V}e50wx|rn z)t!B(W?tt+x)Tv-WzW-ysk?Wuzyc@2yG#kUOJDq&Yy)`l5de*im9WWusi49+ zHkDN*x}Alg#-^NrL)chjo0G4mwGXGZ!-;|%ldTzROqPy6CevG&abBm-@NqrTd=mQ@W=*3;h4B-}~R? zQyWbw96T;RFcJvDJUQ~9&6vC|EL{@6+?JSC%)edh%F~UWEW$v>^8iPZF&m6ITCqzbur4nx zON26OT6URA%%68Y}RElhyU)mOZr#0WEO$X@BhC)hvHRIvWIH&LvPGW{;M7Z zI724EI>|3I8a$f#_oGBAYD*E@N@!o}no5o(fxg0|t zs?a%bJ%D~D38~{=v+b44luqA%zhiVfxV{+tXxpmlI)w_(ICdfsE4ligZ-muTt`Trl zFvK@<+g2jM2&-aErbfplT)Hf^-F3ONvLYk-m;@2X#TLF+M?nK)k}MDfV1<<^214y- z-{`+}L#5OQs>?(QxtRhOiP-b{DTp2d7~|wdPUI%u&S^TlY19@=b98YsrilpOOSVJ{ z*TLzVbykG2=g1yNbE+6#=it9Qs>7t%Gx!h%XDA#SC<}z*oowkaF`dyF>2*35h%pHZ zt5e#ZC}xr%nOmt$OsB)Bpffd|Xit$WvO-L-xlJZq*i!(fuhlZFbBzFfI~CGoD1l|g z^7(PLMG3&7PNGGy#{f+yAF>jQzegY&E3zD|ZHoB5j%g+s$+bvkAlF5^VW-7C(rnc0r_YD@?S|Vo4w<+$daL+ z$oS-}tgdY%Vd=^YfS-IxMbY$g{^GF*WpC@2+`RaTbn6Wy5@l`cuT&~Xw0Cp>#nRGk zomhD3>;-x9z3-Lr@iEy(!ZkHLCojJEDgfjJK%^XsHBHGTrzFkkz(`b@wW(*l__FPj;NuPFJuzm2ixmgbih_B8ehlF74smkr%$n5y zHAR~kb+A&(-YK{(j(sj*xK6NQZ8z}S<`dn`LiI(%J~mZ`@KwY!3do)Ay9YRoUH>mufG{$rC5#RQd?^`#Oqp9Tn5| z?Sx*&KP>HY9heEZJxyG@*zm-zG=^|{3WRoiYG2|!uqVpfy9VIGIgXT4h(kKkF8gv7 zF=h#1Kn=dJ)AKaWukKQBDJ9dHuH0H%m0Ra7%aMiClEL#kG<_UEMOv?xU(efB{bLlwasY11E%7VZ zzv&$N`2g;vwXjJhS#C6qP3OzYXP(g(Ujl?r}ru)ZftB~vK=)$Ir zFwzbat-inO#4#C3_2rxAu4=FCQ7rVkvDr6Dd8uDsfgyC|@R=KOxpQ4UxqCyI5#LC& zVj0R9HbKfwNuGK;PFqeaEXW5QdqDQ!7+$;ZB{^{KT`GOitWZ63O4Py#Fu!n9Mx#h+Ny+lK=FTXXNskD{?TX$ti637Z`xu4rD#$ zsrYIuq8EkBd1!hqV$^baYr!tZ#CQ<1?MFvjc>=!?)ZE4d*Qq{BC;zU-77r}+J zxum|1%;R4#N|aLp-O?@EvR zVpIh*Z)QiOjp|l>tS@zdoB7z=Ujc9vhJmF8EZPR{Wkp^By>})_^KEcwL1UfJ(^uNI zX>l6h8cW4ct?#R@kH!;@v1iN`sM8R& zgBgIu8vs{TTKBZsQs~rQwq` zT^d1!jzDSBGS33jX36`&X=4O=XjKUSa(r@M-G%`nO(8QF042OWu6rgRj%(Tm3A(9I z=?111fH7dNsXN}~#8B4&>!fw_dPs|>m^{}6bCeX$lZjd!&y3T#_`H+0WzguB8G-oF z7Akz(MoxdAge%XBtc%(cQ}uMLXt1N#r#usQIMa3EE5m5Lin~lrXNiNivaGx zx6ERHpzY|#Y$Kl?hN9PL{a^%4_0`vh)~7p~2ssSmtRIY~%tb5*YOtx+m6+mA&>OZU zMJ$M@W+vYS0bIm}GU1LRW@4KG%Y%Kx0roSm_9vymw@HGd=V^%_gZJ`&=h;@qp#{{p z!6J(PDXOtX2GBxPmdU0JF4tTKpW)cVxcvOz{d;eC@2~&bugDiZ`x&wP8_PB@cff>B zfo;bPOj{Ekabav+{^39TM{fYH$U5EF*woSNOei0D>0vM64% zm5}y~_ejO+>rL4~!qrqD%-Ry1_g1;8g6*_R1a-(bW5Vij3@T!c2OfS%?Xc=e#$vkm zT+g$Ax(c52e0B1*Lk6G$3!HjfxGeTN*eXji_qf*>C4I_5 z0I=z%+Y0_Zc+Y*ZI6Etw+f(xL*;mw`B@ln^tZl$g^vxg~Et(lI>Qq0;ub0zW@^XY!XFv_|iW72nx2zY+Ac;NKPOFjE=3^s%xu$mN`J2Lns2P3+bXT z-qkqm7>e{uC`NB>m$mptO{4(zc=H3XLl*5GOYcKyH+oTq>!%{{=~Px*0TVhUxUZA&GWbj~@CkfUO2L3+ zOzMp`g<Xl*qsirRBz2O97l-pX@BMPhpqX`tD)Pppds(-jP$Yqk63@HnebF zn|oDpk;^iD;UJ0Et~L7+W>CI zrl-UVV6_@q94Mrs_^>zBmP=+On)1kd#1=!YNq%m()z7^waq&;*n@}rpmA20 z(hY&y8-pKoHJ9V}?QL(WiJ|_Nwk^WeH(;yDBsit{NFXl_g)L3btV##nnVU* zR8+apRKpr-Qw<)1MG-4&_<9)x<3YH;@7qL)`e}i6bRxDgyq};f1Klf2qmrm4!?l5Y zG?kQ&z8|0e_IQ%&&+x@U_lLFh;h&T3Z#h%}xm27RFFaVY3I{VmS!}mnhCgTjv zH7+3_;^I$JpMc`R6xD%I;S`&0MkoImZ0iAZ`+I&x*Z=RL22(a2U zPbNx8vKyS}fNv-QfT;IS$;`m`BH;xR+z1kKZu^3K{oD)kQ3X3h4$jR;2 zThvv$eMOvP5lLo6MsSTOw;}%4rtD!OZ?Gke;=Y`qg@Bv-5FCeEE@WkDHZMo(=ViU& z%JKJoNao|%tV^r%{1V5eda^h&hAkbJwWnW_;!aCC557}^*%2AR_niOwm!%i;v?A*S zc4`>GCL-BnyojB|p|mrrH-^7fS_mG4m{dD4$*rRzlrBmRjt2E2nA0Yz12E*&)Z#N^ zSq09C8cTeF2@haEViXU$iNALhAaZrfnglIw1^YL4Tk^?OU+zCNDGz5o`O0%=Wfw;I z_~NWQFkTX;(w4KEH|3!t6EYSa)Z{&hH&U3sVucOqbvTYTlc7i;03-Z9M)m?c5`_-? zFpdp?m415{K?4&)7;uCV7b`u>NU$b4u-1oyV96uv?wq9;=mBhuQbh|d5N*H?$LNxFf8U~GkY?D(Vdb{`x=OE4jH z%w#wQVoJe|89h4{gLO3%fM2G3jST~0~qqDiQ*`r zLBZ?{*;frmS}+3nIKKt~4_kW?sP7?YB*_uo?6y5Pv1C5}iX;%bD zlTO&yG*M<@66=HpLEA$t!$#P<|(2~@3;rj-#N*hJFRMYU@U|0VEYOupilLCK^dlZ`2hfZaJv_6V}X zIrY;GR2)+*JBW05f?cZRg?maWcQjFw!7_i&d*AM;>YZilM&PbvG`sA?z--)%3TJ^L zhYBwP$_PYI!C;-><=PR(mPzD9Y+`R;)!c}s29^=Xz&;vgq9BfEh13Z<2a!)ReoaT! z!v`=qX8UuX*J=C*$E8zqjUunsS(*2HrmaRnKoxaQ*olFmb%9pb#kKGQZE~-#Z2_#B zw-`u?VTv(%>D$&aZ6^)v6jq6Rnh|Xu$WO6)?Ct}YTxU=T4y-VHXzeEx6xBD|&!W)c zS6~4y)1a^5j|PqI;Cw^dQtL#;E0KX#&D(XDpff7iMFlQ*z{=9sh-IC>33xRWd;gZ- zpwHCZ$5bCf5I=_G`oDA%VRUZVerkpDqbaEo2$#*~9At}{dTun%7%2LXxdp}3kvz1%*;)x=FP--QGW2Q(~>D> zW$Da|QbM8>&y7h6V7rq_$<~)XBP|N1>l7;_7$_c&ptzXFXXyIm^iyR?0&GI!6xS9v zB!oD((eZI9@9yZHBm1ff(4~eyDMUOeex=drs|^p-w)A9cuWSme zwv~DZKv-b?gpOCYzK-nIqlXV7>F!A7{3Y02U+uL{9CJ9h1N*(!P&Rm6fk$Jb9Mynz zWMXpCOi#7z-BVCr?Br1MJPCZbwnZUg2dX`^ZBCIcpqij)4?9L1%`v^>+S)kCAsmr? zf+70=92-;HfZbqlfil;wUArRBJo63JydpFB;DJTC>(~J~b&!@le5XhFUkHAED-Em)o?X6JlxDRp z*<@PUVH=5VUF~)gaX8s<6mu`vYO=VnD5tT<-uL*Eh)KUGO(fa*QcDz2sBYAV4BZ_vW|qj z*9nZ+H)7#@4ly_4sA_Wu@htLzI)GW=h53vpNv9*DCB!EF9=EOdj_Hpa~1j)MVY>x}ota2kA%)pWQ8(=iJ8r2Z-XwT`km&aB?xOCl8>HvD512 zp0>=9)zb#hn@OZ)v%Do2ZeEc9Yak5(TxBOiGbo2(T!O90l2BlRaZ{5zk}=PqMcqJ| zPLxq#ZrAAs$^d1M#yv$=HutTPDcH`7f74Eop&n`x)9f$3x5_5(ne;c{Kps=9CdeDu zeP9?^CN2!Eq={-{IZ^qnHz)=LPEQM0^vV1jo=d1Yzm95MQJ0GCacukLfDGCxTJ#Qp ztIeG)Weo+&MshUHoQ6LlSgv51-&YpeF5=QS3lVH##5qv=Y-xQP&n_*ycs}Ft5V=KB zr~Gx0r|xZS$-$`^dG^`YWTcpcEk6K|u^|WNr{vnkmMpDZ$LI7lHt6|vJhzOt>9vXt z8Ou%}{_wG0igMxVMfG9hqhkP+eB{@cXk}Nv<9J&7}q8>3)T`OgfK#?U2A3+^OWmAzMi*sbuREI6s zK}yUiR9`h=v{orH%>2MHgD_0-*~Co55g400cEWEF*XHW9@QN0^!;p(Hu!Y+1uH$=C z1M78%`#M^z!E2(4Z}#WI7f7U+<=RAHAc$%iS^KM(1D2L`hEe4=0>Gk*r9Ha=E6j7u zG`jug7J*+8dn)>!3jI1Z`D8WNYUBjLklDo}*eAlS7zS-u&({TLzSDk3ZlCd14FZsa411`)I54=$ z(Fs}XA=m|gmg=oY64h3*>xV3@Xwn+#)w|75zH+H7U&ep`&4=GB=c>2mGCr>Wr&?U9 z$zOQnKKaV^iX0kSkVSx1DL4zRHMe?8MP@@-)(K?plK}kK0p@0IImAJXxyL<@gwD9#0APlDQ-VEQNQaUJ7&(g*DRipRA9+OD2>Rc7?}U8z^0v&P0>e)ErRuJH?DTPY z==774%8$s~ee@)20!z;brYlGk3r)2t7Fsryqkt9<1-k$iQ{c7^Csb+CS*vQM1`&EV zuC}wnFB{es)(a~`1UFMy3!8Pvw42~wX$8fl*>?2VXsartbDLnYIvsP&Bse-R!&Whx zKBOnJ<(2}V474=yU{zZu9Q93WgX*|j2AN~YEVzc9dPP=HHNGcl+U44PQ{jo}M8Te! zbfW&v*S)T42iS}8qyd4b?C;_ECp4(*4?zWsii}XKLwm z*?Ji0zvEUTkd;MJpn1LoWBQIM43L@NYU^O2(=U@r!*pajw88sbJ$JsZ32=M|L0_z5 z96W6Y0asT4LhSbh0tD)NQE;5?FOISS9G$G^!)CC3A?&2}GkXK^OBNgO9PoXdc*ALl zj%^W6dWPv_S|D7!KdAvzR8TQYTvzQo?=c06dCzoen}&(~eIo8=R6GL=3gYve_*_~2 z&E2xK-1bexD`ZTzp9CKgz&4&Mgmfn^IButc>60~xR&-cAbr9pKZx^N2L5 zq9Ymr6a9U^*!55g?9CHlqnjxMFl>B$65!H=e7l3~fmMJRW8;%=a?WCsanFDYj>b6V z@BHOo`YS*C2JniB=~qAhDS7aL`&3(q34R%s;P4LCnbo|qz$Jn9kN?O|0&sfQ8_r>8 zXGg&T-lrOpY6V0>({@Hy_@Sf6r874R+YriEKld3qv#};OP(ZuAaudF+B}Y!)El+;z zZ_3dJ-X~83O#08i`Fpa6`+8(dz}iv zvvs(F5h)>wWlJzY9s(98jvrHSHK$sH37I>3zgGM|^LxK5^VeUMH2vN9f}DQfArzEe zK&-Q;F-Z}LP=P|=WIKA1uzd(0yCYR3?M$ATxJ^xuOEzCZp|Oo?Z^_t5QIq^O{4u4# zS+FB>gOec_@q5qkUDPj%*N-})}c*d7vB`P(ytFbKSg0XGmq{zN)>>>a;;@g<6gtTCNT9fD)+Ay?#FvpB zQ`_UYcY;W7!2mgL0sPv3q_K|KsWCcQ(re36(3(DiZIZaAHYc_s+22@Rm5tkLvUcsd zyzc|=mXiR4uiUsUK3>nFGTWWBeH;aysUm=eR#yscQZ_f&5s$+EBl&Ol$SmpV^tZqk z`|^l`35K#gPj!6zfh`j0Oj+GyJ+{|Un412mX9kRLsx!~8*#-CmuqO)ulkr0=L&*Td zrR_krk!N%oUDZM=7DtWb2J*O5$0rc$lSzak6Jq`WP9Wo$@e%jG zI&R-gTn?>nCZ#KsB}iyc+x_}>zj=c}DJvuF}WigL-w%uxLELTImq#C0H z6lvCQk6Ow`GYl&-_>)-cI`kg)n({UpgA(A1yE-7NTi?^E;{8`dL(gjYMB1IurZ%aBy}*W|k3Dw`XnvE!S3!20s%MSo=00 zGd?u5nzS~Mcg#0Lkes81hj8#+{I6$QY|PpFrll#gm3#J{pMKm1??#{KkALUa=ld|_o>wkxQ@0@=@`P_ZnLD>?pUbCvD|ZI9f^7u4tCoo(@B)M)^Or7sy*V={V~D${8K+H-%qfCEk(V%Ju zShZA;%LvH5#kib=V~OE=uBSZd?3Cs9)(+xcRKIY)7%<$#dtYk#s7?a_gkk)n-BAAe zR7`#>1IJ;q3fc3svfORT)w3}CCl1Tb9*pqlf(j!}73=bLA3Zm#L5cyPql%NM5QR2b z*9ma0WqJ}6qBv!k#2Tu@?>7|$A<>c@kx@cPhwh`4PO5n-MzK%qyMiO-W@z&NcOaPV*sR1Hxey(Gyv-Bv=v{kt;?3lw$U~q`+(-N)#(|a zKIv(z9!(SfzmpTTlDPM8H<3DT>MDAjy&M2!tXL z!AL8KtwC&YWOd3gSX~8~(wT%NxP?O6RLm^1D4&jNU|6e@LE)q7-qt|5g1{Kqs+9U3 zf*w&FITuwkf>BY+8-biuitVxHJ!DW2sM59I+qO9di#TT%EO^@)sBrAHwr)lfExF$v z0(z;z*lK1iF5_L{bA#Gi@|903IuLtRN~2%`@6k+J0ccDA!CzQf&o-X$%Oh z=&T=@(8DnNOr>4B|6I!qv|v;;Bqf@bY5V%kS{DP}=@X77d5ICL4J`{cv{M8nwBw;A zuq-~``pIx`Ulj_lU|i(DUCWz~{QBE|L^zfcNh2sF&iu-<9i!h3^s-zFO!+o;a-47Z z;So^AB>&C8D<<#+tQyqrpw@=AMu*=5zzX#qns!^!>VKrI_VFM2F?rW}-uH(0yzT{ZKL96v38>*wD%ac~d5V;cb2 z&d#>Bd`+R)rYuk~z#k8`t|XB}-u2*nRG;a8`G5Yevc3V(4Evp0bXyziNNQU$zc?@d z%}@Pp`TqBQP_nPRAPEZi!e-n*T9Dtnu_SlHC#SQ%G%NT%6asI!%X0GYv`#Rr)w;Ux zI*qad(oDQYMuus;CLX}c2e=d@G5`=9=I`PfG`b+X{Z=p_6=QGq1x1h!qL zvq`o2WL?EF1?jcwnw(P`g??vZ_AZSZnoYzpcyFqnmCNVO%3igi&y8(^Nq|HFl0hw$ zTE-9a*(wsK&@r}JY{7P?){<@f$MxYk+d4rt>IjH?1~~GANY$(%WdIm#MJXaSI5G4P;>)}Lvyuq4| z4Opx)=sXbnhfX21gG!8Ep4bAkGu+(T(O{T^Hsl_FKYT`eSc_-Ry&@ORUr-x6IbKx3 z{zFHO1E`qMDT9o~s4Yeza}FTjej&?*>z+)b1Z+3K5yp`@FQaywe%g(>`}Su9LVJT& zptq`l_3hrjUjysgwGg(OEftC8PzDO`x8eWNh%5Q?6xKzem^U$I-7t?EcwWEy>%Suf zyv9TPkjI~CfLL*W8eO*mFg7l=W>@YSJ1#%;u@A`q=Z}6}Zrxr7_>+_pd{$Kx{!rO^ zoDQ5yIZ_80=+b}2*vSy=12jD?T&JD%U`=XlgXeMYq2qGp<_(-{Ok;#*A8{C#ba}HP z^HVul0w~GYdu)6}s#QGaGW>iYDVZGEWM#<|a{#jdh}V#x6f&?$Te4l>1yIqJnMnXC z{XH3FoEFEr2MCpP0pg*6TyoP=0B902XTT=raD@Z2MY*whTeZL#kBpAz<;&mLR%T5q zozlV&*Lf3pMK%M_jD>&L-GpoOwAu)=(rHiGG%62ZS<_tyHiUtf3y3<18$C-F>-%QV zhIaT66oP-(x+0lY4gj;TW7zf@zBo1;4b+D^PTcx(SBpogmD$(LWPNq0F(VoAWPZ7x ziElLSz~^(Ca~xnwES|(ZXe!t#R+K+*Ld)FpG!CGKTsrM2Gb5EDdnut4Yuf+}OQWOO zTAYR5+No`$2#TDt;p?!YeA0!j2dD(QGx1PL=Ep{44+U4=Cjw$M6pY7kkCTZUtW!_f z{yoH~Kk$+FsxDav&$?W1$R1+t96tZR__|;xRzEk(5Qrp7y$CPlO zBo){u7DoFqAM3Rwn`sgm+S=aT2B_vE_N!L6QQ){2z}O0&XHpA+i9}WhS&@w;9K?ed zH%px>6bYz%#_92#2%AAZ<>LFR$koW0<0M>8b0p)JIsM4!n5-@>YaC4WULQafwugyD zwVu$k`@^(s1BX=m<1YH?6p2yQN@*D|G;$v|re|jY^04RMZO8W@ zfF&l0wp9`HZy6+y8vNez_dtd^QD$OTn(-p@GAh#1WK{@zgndOsc4I z&SB%%mXPF3 zaAO&PBAjL^WNVty(h1a{MuORa3N_R5)g_@K!`b|(>>#LE%r8nFf$xjAo{`O^p11(X z>a7}QhD#a-;_2W0W%1y!j@@+%#xZ89`Hs<q(zJ%+3B~b13JCOHdHI}Nt@m^iQdq%v;e21cc2mOLhP1BVQgO&Jia4_On&^8b zr7a5q5^H7IS*pB0aZtkXLlWbpkk$&Gr)g_+aqdY4x{R(3gL}vKObZ?bA6>R^^;K6* z*L-bVMw+YgL%6p$KKaY?O`O+#B_y@g76J+c2TL%x_{_gJ4}j2V%I81-tQ1iRx(8L` zIwzl?YSms@mh0_=)MC^QO3HGGsvEvPj<4Wk$_AO2Kv2BAotwYkhWnlarRFu-dFluc%suZ}Xgnw`F~1SmAD71p?~c7qgjCW&le3ACzbfO{3F zWQ&_`rl=_6#}BMtn5z_QlOzPnJfJAG&z4?R`~eP)jTV)uM39Yag#s#w)XSlmvyOJg z{a!dQiM?FZ`>xsp-1qoAYN1loOM?y-%XgGIPdx!;iUnqB8trnufoe9YfSewr6;MuW zQ~}MHw&S=q@uyu&VQ=_02vjCr7~1wXn6OUwjuG$#EWOZE{ewWAj`4w^CTfP|M&LW8 z(-$K)m(eQnd{-HzIt2@Bhoixxk?tPZTd{C3-G<4SVJ^8APzeX@VaEb2v|({E?84B9 zJt*znNLCr2XcnMp4KYk->pzLL`gS_xpm=1CP@*Yx&VbP|Oag~2E+#mxvN%j@k{t#% z9Drci7kmxbGP}J9ewlVL`TMJApX`ldQU`Mwz-n!?$2jvHU_($IG`q$2!m94EU zxrIcN2~P$IEY~xIYdJ9C(RY4WJ7(G~YRqs-U`;kQm*t~B_>;;E*?%zcSzB8}qPdID z+|cpnI>pZO2G`Hm@Mo-e6I3nDo|J$5FaM?d#xMN``NL0tSvEJpGR%)w&5W*o6q&AJWMpYZ#l zw%VvrJRGPbCVsNEC*mTi#-0VO2KylT(-yfYZrsH4y?ptiGOsxNrjX0X`1phzIDAwl zrst4!XBCL50Vu2^fv$408Bvm;qlGE1VI%Bl*cUtx+E2Af4sEI}jCrPj;d;Z4jUXI? zTHoohAC!9i-(L@0eXABio_7zRP!oV=3o$d9ZWVu55_on5=|+&amqzl~Q$`Aak_9sW zF%QihmTR{z$;$GQPV!9SUNM#k-GWR3MEUDK^H*f%P*Hw5`(yHp|M6F~h{8e>V`;{X z8LU`{a;s9E*GFgbpPKS91 z<1rLn0hXu3maJ_6U@LTGEYXq^Gh`}_C;+v&R{>~Ml^FmjrA!83M@H@O?Y&j``b+2K zzJp1*wgoVy*_TI8pO7tp9uvikYR_(#0S+QI43oy@CJ_sBAdJgF0EjJd7ShK0EM&5V z71`p%)ShaUQAbXjxS4la@o;{I@xg3uZCe&=-|UING9uj}@xsx9XWzuL%2tl+RJzc& z6Enr=FM1mP1V;ZIpco};7)ntvKw@m;#P#$Q0yC4SeIp^EF(ijS094GP2oT5bY5=2( z$p5^Q8Qze^^DUzgF@>T^7QbJCUE8ECRLCM^UZ3#?9(`200L(U#*MzZx>{U9l3Hz2G znZ?fofT?ZRra+#%a9(`GTQ6_CEbo2n0lCnqASUKn#gyUpfyW+0p&%}2E}oa?0sN=a zMfd;!h>47@Uo!fNg*jyh-$a3eNpeXJ4~R<#=RjXwD2`z(nV|tX zRO7p&gm=gBz1Kn*IWYcXe;hUl$|9<~NHkV^V2CX^W$5QdS42e?2MUjOimF@8K#ySG zv_a!Q?Nmbxh(&*o62<{_*)c&|bS}~8`f$MV8cqo^RcM38X+r9nsxd?RXq0U9-R_`5 z;|^dp$3*WYWVb~nes%?$V|imwZeCxLThBcwMK0KQD5n=jfRNWDgU`FT)t2SlRjD>S z1T|IZ0@Rw##Q{Quaun6HYbzmna*V;n{(tAHfm?9BHP%M zRV1ne+kWBIuSpHbe*n~**xP4+^@f!3y=6E(>I%txQAU9{kHAv8wzta(Y!f9C-X1n& zDo!CtPeoIet$~f2bAiaCN?IVRs9hDWg31j3FKli}37_o*MOj}5;yg3231%WN{o_88 z12mU@cXgMk&E|E;x@<@jV$U-%wG;783Mh04mxm zdpaJr`pu`sN#~?;;D{tkBhn<@R`bxfL`j%9mPMd|nqj5DyvXsXwEXKIen1ivhf#f< zlH1K$*@i>)jy@tIsL+lT;AdqRbkf663a{owDE+NqU z(M(K65S%8GeK~_uZ>gRTo~B4$KiolPd2Q-H+P*BR|2 zK2Nf!>ODs%%Vi5G07V%c%g%A@i9D+1C0|B&+LA=|Z)c~k^zSNLb3-F)ZRC`>K4U5h z?%IUXB;1afoYyl`2YF%|tZ-r+TTo)2wSz{~I~r3SSn!IY*(=*y2uwOM4zSi&(8{-V zO|)uG=h*9-cB~cx5sLKkzOeN)p)4L>&mop@m3d?v|BO(#7HZ?lQe*YJ*A8@@P*jR+ zt}ekK{5_pAg1!X6VwzYOc8pe9L)VlESn+K%HCeNrc4p6TI$u1dv~&fra4!05f-rI8 z0(C-*>NNQ#iPDkI=7_64Nk^Y6ld?jwpnxC0fPpRu<3K{vYk+;8&Lx+W*Ag~DYm%!d`-Im*SV)axM%26 zHfSAaURh>C%+MVMqqJ3c-!t#y&WW=nv=>+bSl1+;``8c$Y;yHJDClH?H=_${l!&-^ifqGQSusG-nBttJZm)*B7o3k#LQ2(;5kUN$v3 z&0(!S^`0M8ov!@{lh@~;e_m}ZL97D@7L^gCli=+21y*d_fP4uveUw%1{IvX)zxChC z0}tIV|Nh_qZ*uDvs`K!r<-JX5pvd-vhYsNr@+K~X4It<|)~LzXp8kqF{J{NkdwE4c z*}IM)7HZY8w*m#f8_fo;rLDyzqd!$ejPy0cS#yrd+zQEF0w-Y+X{e0b0Fy z=A2yn!%xZCi&tbKpOQn91!b(HU?(#G3MkJ|U)@zrnGO;+f=rw)*o7b1TSxp*Ea7_c zGDE$@bVc_Qr~Q$^S=}xxfX<{+bzO4RoBx_hiy}1!<@`Q^E6~1OwSpWfVWR zk)V+Q%c-zAg7LUc?l0=6&@Zm8Zpe0}s&?QR4LdCmZo;&dz8~2M5DeGL>iUWHt*f@cGNvM6+A_!tBQpZBMdN2v$Qu@k`5x6=v_MTb7vyG3T=>Pias$9HqK~`2)lu0sDD#^maf=nYu%;gLE6UyiKe!;Q8Iok>2_CKTf68tqfN8~#@Uax@_-cfLWBUtsV z7+4gwX6%qh!prr59g+j{N96joE7HRH z4p0y&#Iy24AO4ukADl)u>dTW4J|gGec}|`Nz?6!owXo82Oh<)uL-mg-j}jh%GE{UJ z38(#{usAV+XMp&!(`#r8Ypq^a+epCeH$L;9_xWI(``IYDU|`$nII) zt1DB8LhmdjsQ@}-#Xg4zxmpy}SioZuEY$y~0Y(kJq?cmWh0mqb0Aucy4l_xRK}{bK z=}>WS6vgJ5i-{THVg^aYY!^`9=Czh#O`qw77O+;+uFP>3brl!(jo>?hs!rPsDcUF+20Z=RCq|*Qx7|ZDWiY2)ZNvH42?DV{}0Yp(d z_QvI9dFrXhq*utp7B(b>{IZlELt!%}7caep``C-PMsb~WQW25av6KI-dm0#Q6*V3NYJnyOhQT!aibw-P1|z%8XGWk|7>T4t(+#7~ zj!wk9+*U*_&=om}DB-o#x{#0`Jas@u09-UnV{#b=>fn`E<eUULID?3QKJwd zo?{nPrsDjR99W!2z?ITxLWkofQUL9G+KyDaab3!&$ff|m+;ifHoB%-4+S!rn&K3+* zOC9j|C@T$li4`ZLp3X=Yi6q78T^MUY(jVIPt7w6Qw$kofwgDMi@0jHTn=SlcPmVu2 zi*+@Lby365>I!(>``|pTnL?GmQgj2{7dJC1GIat;vLhR{Z^(UfqcSy*!0f<`Owv}- z=-tdpdHtsBB0xJbs81gi3R?#!QyqS5EN*utN}0dVD&3B&0!R1OvREGuQ#@b8f9cSQ7A9Y;6x_? zS-?tcAaAE^853i4y?RKxmNqtY(jO_~J$;R_Yixz2Q>RHKQ-R;bz+T@6FewE9pw{eY zRWzf4NZ+(=6UanWl7J1hGa?~zx8GA1l~ThMz$dups$NZ~;J>+xaTVhA6%ZkCM&=ps zLf1}KjNyAzNyCIq#0=vmrrIZI1-MjSg}`Co2tmh?;8m+t6=bK@6d4!19_neRXnQ#Z3#PXEjpDT8fJ?(`0jnR!_`Sf6cT;-Y=s!6_ae*QP3}9$r7~Wx-p}%eSH#X z1kXL{(D3|WllrPRW&nYN0&xL=fP#X4{AOiQkzuBld`E`_nAR?BXw+7Kz%q6tT_nCo zh2MinBgwFJ+(FSq24G3xn+je`r==R&l4C2l+8)XX)U|8{H)?HjjYgIe6;n)7mPO*d zh=gGbi3=XSVP`2YW!v>a14_kIz}{$jMeRQ-8fzyPMlB-*m6Tb-)*;8Rmm?;UxmLq` zQ@>AUqSXM403L$Ap6A+%q*&2$F|21M%=$fX%Vd(b^|)i2aJa8f=bFW|-{u%#T`VI_ z^n#)Z%ir!$qDuJYlFvypcP#rsV=KFF7Y-i$79VD&uCZ;7z%W~MfBx_O10B)5{~&;S z{@kmoZ_`BFF*7$WH*YQ}h>_1F@cNVn+m*c?fJiaf-7Ra&@O}5(C5H|jc*ED8J9kb- zM@QxQ_3NrhRRYj3&_oS_I|S*uw+u5Yrq|xqvF%Mc_3-=TpZ}{v@+<%07v&WcQzoY; zB%LqHGuN)m_uY3C;CEZsN;037k3W2u{03sJGv^XWIQpt%<0Gcnf=yv_w6_1S4Z}+# zNjBPe{Z?0&8>=WRZX%&&#lEJA9d!-MyH#1=JumJ4D=Gke_rX~iFQyTzWTc3D#5N?d z8QYX?!2K^Ed8?x6=XV>r*G3Qz@Or8M-WaYR>;cj^<7PbSuo&K!3Y$ONY3iv_B})OUHWrpSj4qazbP^~ zmQi9gt=u7)?KnfAD)N@~LG)DaI}zkXG2-Mp!>2@}b&$qAX7odbB4SNplM zxhdr`0L4D1tM&C6aoXAH)~;;qRFFjPNQKY1)3kQeB=IUMqKr_(`gH96j;Y?NDID;1 z93Jw|{;7P&$Lj|=?AOct(;mFWWHKx1Y!S(KN%bxhnS?ZJ4F#x~jFUB;MNwLdW!;|o z=u$3YhNQrj-uLhW64Y99@8U6e?+4xq0HJ}9v<;gd*I4R@Kk`Ajc6&*#Ubvz0Upir) zG*3U5LSc{Vm8@$HqVmm@+7Rov+v-UY=fWv|oR*o2CzRRFw)kqND*xht{J%?j1b{5| zMH~hE@$nRjvYza0H;uj;d;zDqW#M<~_kfwNL1GaDzdwY~%pJu7(*NouuJSBMNfvSucyM`Z^9 zSiM=16ztZO+ncft5VvKA8L$q?zh}~(3Zp9{nyVy>m=B*N?U)= zB|dbLU&|EZ7+;bVmCPg+d^huU4EU^hsb{A9YSBSi@;Tq`jU}ZH(5u}k zORo`A23CXjvfY=R-I|_X2m2}L23io_+uqUh;&k_9t%|kR1#lF~fg|&Rf2t-i_xh!a z*W@xl=k?99OaNdXK`~>pFe>9ylXCarL-Ms}Uz0to-|@+k+_SJKuUt4UDLmubtD740 z_^}=U$SDBwWo=(Ajf|nF>dO55C~W1ljEtA0g8b#mP2{RE_!I1j)$Ki*nga+&n?e?< zOQtD+Eo}*;zFSjGR3TH)b)3N7SjW1o<9TLLOidRHI%QCFm=IzdfW3?f8Jl)dxX9re z7}L{c(Fb?@jt(+Xkj#r~5r}%D%xBZEvuyn*kk|+K7T2O}U#Ex0Q*k3DVr?hef@_t! z?jxPb9fZo%CHpMy{JDtxTR-+Ot=<@AS(4j6P|4Wma34b|kp1m`<|C~VMmX#>55uTB zVZf|GrNRcs>LRUpphSNvB06MrkIf%?XncHXlL^=IW$p}vuiyd#x<#7gRIvAO&TV`rYyj5 zpMT{W^3#tWlOMiO6Bow(SMEJ5^9>|!(xbQBoN%G{DqurnO1}T`AH?Pj<+wMB$^={MVnF&c(urpz?U&{6 z{N*2!|I4raflN#uP*y_y>RD7MU0Fi)Xp~c!U{pro>|)s5WALaH@yjAOY}Y&TrI)TU z3zjDyIF9?~m}Hk%gzxWfElcO@H&HbasoeE|#HPljm#a&8<7rvBaZ5UIlJ9!>Ba$hV zOmBFzs|=2nDw5eF@8i2E@0C?QFd|o^x0>>UXZKi_7)3(~^Dx*c4 zd6e~sf2&ST!o+lRI`O(DX91i|Jt#;W_vhH`A$j-FqjD8hq$S*!e1WXBo;0&?Sczo` zvg48;N1&PoFb1O-OROq`g_GZSzv%6lN5wgPC)GrNgFqXOvVQj?^3zW^I>m{Mx}Sux zweg5N1t*$k?|i)}_aWG*0T5j%J1W9S#6PYyX(RNkNvkVw`(enGwpB{@>r#Z8DC%@P zowyPWf3VaSvEY>gMixY{h8d7zJ81h-R%j3mCfB)EU$2G= z*VVP#sA9ziHcOdfTCvlbo!T=Uy2uK*>K&PYyl(**6%PhD74sqn6`4jj69k2v9OI=t zWe~O7I!_Eiu5Xz}w(Zb2qT{K!Y4czp#cpHbP@K@i>+H6>gQTX@ZD{~aky(yMR_%t6 z(*Sosh`$_L8jxrUoM(WKXsV&^2R<2_43Q?@ZgsTM#lV4sA^4tFyP+T*^-$QhqztOQ z(Q4_n+Uh^z$&{{HmZj4OSgO^!25Nm)gZtEfa!ms2lUZg6`k@7)$UtD=ti#ti^^h#K zWZY<6#fGEfdmYOVivUcUDKfz{m9=mHPH}B8kRJjyCh#Q1O)KVsc^?BMGnLO#KrDbQ z3X;A8Ly1(@w$cRJO6g#onbyUGijO*>85h5w-D9vT^UR6aW-@sh=g4>|Nxv|y0;on4 z(zO5a{8+gqP)cx$Nrky)lXz+h8k+Sx7y{s02A5?Ha@}wh=&Bxwm|^d2AYmmcEwE7H1~q$!bHsxV|R4 zds}kv(M2gBS=>NjhKvV-7Gb|CnZ-E+%yL~PT?OlDudl2C#6luL;49u`D-gjWGOc2= z2;l7QqX%`+3R}~ZJ?HXwXGB=fR7pQ_F z0J-|UvFnbuiW79y{jTgrPuqD2wyy)k8v!`CFgF1(U`>DCqMSoFWn*#+IJv`kc)#Bj z8G`U;LYfS97nSK`UZ)Hag07yiRT0?b+d_22q>k8yuH9$U{@dExlv{|`$|$OmIYvF0 znVA^?rQ@m>w+C=_XKPD3t-7{q(nhTTz`J;TMV8jqWOJvi38!{e#AAa!>_tU#76X(O zgj#kLwYSl)TCm92?_wcqV4a6U6VB`qY!Z2%3_JfjXR z*Ho>^>3S(`X=4$LjK8Puxm)(id(wpeJACq}oIJRQwOFM$ml}$}>2^j1x_8=jxp?V@ zYDsF#ecv!+jn8UIKkX|hPW!@Q7X5e@z*a7e0#wq`1inW>cOXBd5#uvGoIxfWB1E*FTWxU6d*^C10?~9Fs?fR z+tFzQutr|tIBmqpNr0YBX|p9Z=F9P!yfg{cv0c%3t=xo>Wk}#&FU%AG%rtd+eI3A1 zob6(|&as}-Nd=mFzL|d7Xpu>jRHiv&D;BQR{{=D2K#t? zCJQ;>27pPcPZ(Wrm^OGo!ds57&h0omBZmHIog1O36jpOHSjg8nbpq&NOEf!O3?`V53nZd44$@1ukI0x^S zudJ`j4?g~GIeqs%a`F5N*aS5hjb)XVegM_FgJYiD+^Mm*Nj7R-*`@jqK6<0-%abSP z<*wtWG*N3;rsP=|y@{|bAAaglc@?X?e?K;NuOc^Vdol?_oy|V3{rJl+W==0qsmxYX>MS{?y4Z3Q^-qVa$2XfHBfzJ zW;_ZfSn^B@O>J*oW@qN*G2E-W=BFeD!}iI~d`fPv-hxv=kaF#+90zi}1w=kGTTZRQ@sgy|kAZ|umk zU)zWxeCd(VGOUVF`vu?egPr!K!)nw0z#k4gDPS;~m7E-r7&3@R5s zfs(!>D-1$eIde^dUuQcPzPp18$5yQ@*FX1p09GBj1Q4PacI95SW^v7O3B#Da=n_PO zBlp^}jL+LB-YrL-ct8#xnv#Dq_ZK8xD9Q$^@=daFV8oBf+j}U0U?;K|L2LsQ8nN&| z!2{is;#x*YWMg<3O%5g&f#X=+A0uk3AcC^0Jk|dSlQ|nPQ<~mJ@ts(8-a)4A|NJMo_ZNWXkvT zH9UWg7gimXz<>ujZO}85!+39XEHo2!3UK-ccnOp#WE?ozg;ju}yv~eeR%ojRwXn1$ z#WTr@+7ZvPe_Rc|dbqdrAG{WRcdKQRM7GlqeBy?RTTLx}y)AywzN?^WFH}tvChVz5 zP@Osk2*PU!HW-*_TUXrENn)m@E}{23VkYo>SrujLvVuld1X}|M07(Wc4UHz01?}|j zPD)vI23$10l7TLDYiKW3Xx$I3K3QM{_X(zjk!E6OlFFd1pcw^b9Wm>LUqetsMbZi2 zQOhoo(CM~had?(NpzAyc3?qy8S!V?J$|#N_m@H)uAjue!_{a=`+V~yGq_)4=#4%e7Txu}dxTfA|^0uN?r!hm@l8vn_kMVcOi&xyP>U+PD%53G%hw0sNz6h?)s zZwLJRS3KS<3B98Q$T6%G38UKD{&RLL!1d;z9f5YdZ=BdSsfp5^Rac6&zh1DNY#D9M zjNKVd667Tlf)(R7{(kD7d*wSlIKk~I{45jVqm$!0rSPpB+Tz?aY)n?DBS68S0JPt? z0}%+IWaY{Ce?$|jrIjs!u6g;5XP%db4}4Tod_6%3BnS77=H=JE_DwnX*kedg$HZ^8 zWPG%w$vu;eE|Q2wtEsk&wwDvkl1Nle9$L^s&r26?DX>M6-|6vDZTBe^i!wVshCQEF z=3y5A5M>a00JHi?IFhhQ)U|1BuSoz9PN%lvT$m`at$BNU!!TG7TTmP8%C#HVb4j(U zZ1>_dkr~StKepwN?WoLAGF@H6xFa)+cA|~%B#VoheieY~Z307NwQ_2qjo%KsP8;n|FD9*5Lw$}~iUH3mCcOO5BI3C3%#5e4?sQYdC(raH*k^e7$ z_3QG(@BgSAK6X%UtS-TicC`)B6&Vl*$f%({C7Itb+~axdvvRAc`zW5GJOSd)W?TQ` zu$c}(m*y@7v6IStj^lhXSywjpI+8*xPEq-Zae(gtvO3sbqoon7jXGYRP*9BRY8=Eu zox0_S|4p95G?l)c@C zR4O&uYF4F--+%D2W3pFmN_^du(bS}@14QehxQElj^v{mE`PC}(8$f9h)?o!9IkJvAT+$mv)=5T_v-$fiINkg6xQ<$PI zm9iUc5l6Kq13M_e2`oU&_|Ob@8D!yPDLbaPL;#Fysg2?n+oh?mOkkU=R_a($yMb-t zpa1&PQozaNa-O!55Twgt-IKAO0obLQhWN-9fbjcH->tfVn*fPp03NFifbs3Jf;W@J zoPt9Rp6&L^4vGeWY*sGG2=bP@j~rB{Td^=9#};N~bR?~;`sLLPS=p`WFoBC#mNaG~ zQ~sfQACRrp6@2D|eByJT({;R6-i95F$+erDG#S%j1O&rccz!JQO&vL*8l?nmXQrm* z=E`-MLIGq9Hf^h3McmWF_ZDPtYdHL(Tq$Ee;~8Z*#W0QMn$eCPw(qgP%D9S?u32EN zw~`vaP{x7`$40H8LkN7>q^;dmWyQ8oAmQ^!dPY8kOg!d#S}5^Y{A}nn@K`LV?ajQe z^htd3{N3E#5jl7MtidF5X8%&pn61y+&aG@!E|NcIV7=wT6jQ=sTh1_UvsB`65ZKR;n72l3tHUz?)A%jYsecv?%$|8F6omC>)*K2O{wDf0gq)jnA zq6*UxTr=ll0(kEZAT6{>2R&`Rke2h+tjuGhlWP9|c=`ni&fk!y?wXMJ?6f+aJUhxL z?uL!i09qd;v+~XL6*)b7P@cPR37asG5hM=t*%%y6Pij2`r7*Tl9cL=osG%GzCgk{m zc^N%$L_YJ%C0V*~P110(E4Mb}4=!AgfBjcKCg}$c%Qd|Am0K%PI(S6Zr{s*_^7-6jC1HEhh1laoVxK*j;AvB3PuJD-xdV=zGFOd4562V@GBfY&xE(jGl3OF-gBQ7L&cQZ54KbvUXFPMR$h1X7bY_X!xp%6*T^@Bhvp$Sg$x-HiMS zoYZ>(WPK>yvq1@h3p}5H+CgxEs@X@Sugsj!)Bw)3V2smjV<>5bt*NaGUDc0xyAQL! z9c7$EdUs~oMy#wTaSRmHGQd_i{4X?9ju6v{)u=Ve6G4loI3?Sl{qR#aGXg(3<0I%S%9?XYpWgu z?iL*Ig!ERe`@v6_S5>x1`Ad2lHaG=U-)os`(uKbGUwOp zn~6Hgc4J_y!ot1=3)IozttNAh=R>^#{T|;p0 zGWsP9(3A;D5%zdobz_1?R|Cje-2~UXk5L;c6J}+cS)C#;=Glo^W>|pH9SbygWi^vk zF*|O~w)9zFFw5=|BN}-|(ZAHhh?rjn029M5MIs&tc$ovZ9WN9HfTU|R zniP}^jjo7iTm4>t(D!mph2D^r5cyy?+BVkza(IbhrP_fjyhnjpkjumh3OGkaDJRNm z1G!^jie6SYU~0V`$FOBEd;@qjNKV6W5MwC!&2``8Gro1(kYS*h`^hT%8iM)xg+=*4 zI#zDql(~fiZv?Pl4+sFa$r$bSCIhY!eaUA!V? z07pkB^01#sl92J!X6+$?BkPF_S~8JLQfQ{;9Y&n7TdqhAF-RG4(u)_C6iA($sA?-B z?YkFrC2GUvggyd;iBw*i)aOB>%0!XLb*!D#fff}c9t5swo4ra!RyQ{l>~B=-+Ey$I z2=vuv6R4U5AhU;aXc7qP7;vi7VS&%n&+u(AS0`cdej&~=V(y|7XxX|_Z?xo@=bl$P zLfb|L1$D4|-DiPH9`L%4pE@PG+v{rE*e3e-|NcLaBZsF@C|pzhuNoOXearYDW0y%C zZI}~{J{q?34%%G_WIK^o;LvpV!EoOYl9XCu=TM7u%lEg>A$OdcI7=Jl?~NCTwdFh3pbYK!quBnuQp6uR$$M|HAQG&*Bic} zEwWz&H|qLO@%w#DQy#AKX9S@CDL&@Sbg|6O0emEUExfjIUq%5Ug_PMy=Zw%j_Itvi z|7=U88Y=Unfa2I#G(!v}QW$uL)pLfA+*& zTAyno+t# zumVsNK7J>qQY5K_qY@}SY*Ieekt$+t>Y?j6M>Gn=bawv}VkcV&x4u=gb z%+JX7#M!@&_Z*Qk><2@t8N3{}QLENV^X$K=-T z7SmAfvjgNN^LV_ zT+JbdHCxc+@H57?9ry(L%Ova+_d2@(2ug<77oAqq6pusWpLeidNE*>XofbM#Kt_JY z^XN94W?C&7_jrG^-IVXP<9iao3J2hh41%>gKpzV>MFQyqtq74jE0xjDBto$6G}va6 zi8J_9TWc(Ev>%)b_UTyd2eV8783A8`ZIuXZ^>{cfX~6t)hSd?Pw0(yYiN5E~o1wfc zeeWN>c1?b=7)TBX@!q8iGF7ceVf2Ljz(emqu;E}aP643VkS;1k`CdyCjvWLnY^6K1 zX(r8l@YuL)v4WTE%3>)djTj8|CV;I(O2)A%4~+u|D`r(VIguWfiR1UnSY=Iq_TWLu zAsI}cdPrVdUY39R*{9V3Jvx6-5;+n)5tJZNT|9c1ki1S^Ez?F7s0LM_6GeI&m~rYE z$B*`K{%MY@#swtO@7 zs|E0DyM>A-4Ezi#05JCetNL2OXuw&n;`cY5amhOXxwb3f71K%|Wd&78;pKY8Idx%- zSoI4%Who;rFs*82R5@b7az`uT8tCKsDjsIr z!)PJ6X4pp7?gc8o+w+aajcdislXPZ@xYgK-nToGx^qTmeCTLML_d*-BwxTRKoxbqzh8K@&}C2f>+XiVyd6iMQC+mT1 zFkVAElT%x%O^4A|;CuT9*i}s|73z$eRwE~3EBFdn5nxE#No)~dquNjr^GnP`KqjPt zZ&*&Q>)3T+gP-^N&}QZG{6=zPT6G*<&y5?#BnVh}%9eLT@+>)(oOIZ_L*m+7ktd^^C7`~m%>Lfmp z8a-WVl8|B2L~*fR(S29m+tvF*eJeiwomy2|NW=rH$yfo9qCh-b{P?;~SGQ1`dQAYV zsL`jbL4g?Gg0({?ildY8dg_}9WYPDqm3tgT(sHY<8dz)@Qe7N^ik5Lj(d}d`KI}ZO z1($0#mSkb!mYg_oK;HANC*|VB%W~g?4@%hDMO>NJRxMZO6Auf{uIE~YpY>Z2o6@4w zu9XMzBW+qS_C&()b;V&5Tbt)?HD+ZPw@19Aa9C2+HO%1!8ylMdFWSmz;Myw|iwe*& zR^=ch#(ng?4ZP<1@~T`z@wS1a(~o3CLOWc6G6TujzLr4KUaQ{~0Rn30dUt@)`g{4# zkNwwbQ<6LE$DdXUi$x3$=}1yU9ZzZ<`9z9R5%GqZ97s(jtnCUXeB%G|C>|f1IR@~E zF)I8<4nReBPk#H8pON*O>w0f^T?7u|wx~t%b;mN$w20-1#vA+@3#8d>LMHGGytEPe z?$iM;0Fls^T-?_2QbA)5f-*@2skx*XuClqkjrbjfp`6J4R9@mfr_=$+Ms1qHAGqG-_>a6{`ZE92w86?o=XC1n69sokm3_0ZPqHBxGf!E)5i8 zM^N1E*7~xB!gvzvqH*rF96b22tOBf|-WOSE?>Kx+4lJfn!0yV*F3veWf+CphWv`IoZsS4jw zR^7qb<5IHI@d%7o8aoP%t(3PVP398y$wI`UxIa7F4H=t6UMf|5Uq>qS4O!bjPK0a9 z<>T0w6&cN;@Q!@9)~(4%DhF^8=jI!b`upGgB)}j~&Tj#z#&e1RJR0$fvb9~7VxIb} z+}m{p`U%v(^2%%Sz9%1(t-UgUtc(tL@YBedW{ye^`SbG9I($n@eKEBdOQlgWaTflA z1C^-9TF3gx;`##B5@9z2&lOo9V&6Kz(Uvk$ao^b5hc(a zW24H-RY?>|zjWSy0>SH#?>!AHdki!oY_uEEi3gyQ?5}LRG4Kq-L2hZCmh*#CLs8i%B_kG{%`}#FFcZTAl!|$_+twrz{s8Z-W z(`&*w6oJmBamcdi9sKIsg?yNso9k0pxcDMmxRJlr=;PQmESOcrH*Cy>{^dPcHLU;03yd!`oQ`!VUd)Vv9$bzudLF_34Uk4uxR zm*R|E*+$SNN!jH!Y;DU(AtxNL(T}H*q$BuEW)RTMir1(bgqy5fTpu4@lB^di-pt^P zj+)eb3hj-vi@#S!g)T2MnFQ`fTY7Np{jey>xfAN}*q_a|CI+dMu9*s0kgk4D$qfu} z1b~Q1#9kGFuQR4&SlOP*6G-5D3R`EfHZpL=K=$Fdj>oFF_6`DCM{akqI8fys$+o7D6|=oll?ug9Da5Ix{z3&JO{;KB!Kp3<&`I&8pt%ZI+x^dRxU7ow zO)DYmj|rQ>^E?u6 z;h0|)W)F=XlP11ls7YMh4z3_OEt8HZ_==F{LjGrUYzxpILdf>^>(n)A8CJlPo3m zT>4hmC2m^-4Xa4mZJ`-0PX-8|vmcmtM=hLKmXaofh9_l&?vrNC^_4wl!UNSfV*td~ zQ(Tj_8j-F}pb+<~Ps%#%AB9HEV6B*`WD-o`6fP#lk@&J>3QMm2Zy-o6rYYeLc9a-@ z>O{;0vBj%>Ea!-AHSmp=-K=_UR_t99#Lx^lP$mXTl^Qd;`+U14T?PIC@G*kXvd{N_ zHynm}U@q5AMD-opZfUNOZR-+7@r7yijqZzqQQsVh3&SDc7yX-H?2YT!6jUKF%4bh- zl+|iZX4B8bdtQ6#dC|xuFbM(eLj(q}g{6aM@G^pa(-v#)WCuRv#?6~@^27;kRoL9z zl&Psn?DLFa!&sogU;vQ-yIBjXYpbYi-yYak#s$h=fhmD`CcE{vjA-J8LSH;#MZ5zA^rt2!Wp-*x+x*t{syeCc z==`+Yb@Tu}y9Ha(HvoFdvk3{#Z+BZY^SGaw;1M9^^hUPBkm=1fLALPGzV9I^Q6c?A zQrkH@h>2Q^I~2F^QQ+(h*s+WOnT$3&MhC6c^^Jf#nHHQji1RK2z?vK%#lJ&M;_65y zX@2k?EV;ytv@tihyDzc2{UqhVWs$^q07<8ew(KW1D#(NSm zKy8kpuW@7_gVGkmLp#0v&p?82zpeb!f>!&FK&-wJ>$h%N+gs!CJsFCtqsUp)R#B`o zPM5{ne{kVJ`HMgCQ3X=!t*TsHy(Zsy^R~PtZNizuUy+uCfQ_ZOpD2fkBrI-=U1^-c|CCjkCSdvcD5RlV<%itRX@MG z>C1uHv=)|=82|$KZnn>HpY65+DI#WJQU2<+B^^q@Sm?y!9QGNfQf?sb-o9_& za&2RO~KC^**W+a}&vj9-Fvo5iGS~bfm0FvUWZyDhJ=ViB2S9yvmZ0U(P053X& zq6^!VMSLZ)yj7PCfd6c7zjFP8Jb3B>1vSYwT^yS%fQbxyOSw_RGq_)wG5OLn zpOdwnZJc*TX6I&PYYjjoI|}-3#K8@D_`wHccc-jH!9CaoP8`*CSM2F3{6ckeSJ|NS zb^Mb9D$<#>GT257d9g0h6iQc3Se?c6`qPSfLYzlaW)Bf#VtcuQP;+qGSKRjeoEp zkaZSO(CS32`vGHX=m<^b9R*Rt&-9}6k)gBHms(1`L@Wyt+g{|{@#pXyql!xyo!FZL zT=sM{QKaL;NwZz&XCJ)>sBuq`_h|$WFTe1t9PL#kc5Pc88ZXMno;U<#dPaWZQ-2~a z%}mS5u?hM9ryi4AE35L+MFgkW9I7PS^2mufIlEkw^Q&8$oIY`E3LsPl@7)o&1gUJU zqdNPtOt*ab(0vE6=&N$F>B<(-Y>GxB+2Mpa;Aa4oNQF!*fI+~c5GxyGJ}@8#Cp?kK z!k%v?I!rosggOHj7@NZ6geJ574!|1(Ni`V8d+$CWy8ybjcU#gZkpAn*)Xcbyp}Nyw zI4Ze^en>dru8UwViQp;(5Hy(^lMQ@EgOeR#SRb6p%HhQX9G!=K>q{#&Cm(z4h~xm$ z{l?2T1)#lrU^XMCiV1BA+HLh@wcgi&WCFqE`71Dd{ViESH8xT71o##AgqwBkpcqmYcWM#Krx8VsS(s_s`3#&uwU*_N97RzIJ;>4mMDE zY9-}!H(K&Tr!umQn_t4JP36aB;`IGU9P;vSzVSRNyPo{kj~pw=UvZ#ZlVASfPsRyfwQD`~13 zm?|Wx_;mVhvdFC+Fp}qv(tgzjnm#UDeHP<%ICj_qrVKg^d&tqi(M*7I2g4@VuEJzT zuXAHnZlOYSa4w@Qfef@M+RMG!>l>k7{+%>((wr%nP8Ja>mA)+^m^Kj3rs`_7j@Olr zTOdUpXMDiW(dwT#3edTn8b?sZ+INlh*~{NIvfa4p`(f& zGa#gj0E~c+w!kr9CVLCPOw0xj$)vef-XA86JZFMjdCmgKX zz~i)^qy_PeE{&PK=x8z*=|-{GK%FnHrI=0rXzz3?Ag=)xREJYq`@s-kl40wcf)KX# zN7u1^?(RO_znj=H~4>178 zo$bHQ@Vnl|BWha~d%ljdub3CbL>BNIh`U=TFpMTGehVm0r*hhWD%i(dS0IakHHBcg z_k-cn3#0!Dg8|dVe1l2o`63osRBw)eXvC7S?Tp8d9asCv_N=+Nc{BAX7~XSFfr|bB zRM^kPGp&vWu;#sBvO?e~0+K6eUs@9ga0ob~`z z`U|JAZj+L%v*T$c@cCIXsqE zb_4e;h0Vk1F$Jd^YyrgH$fOJ-nRaO6&{278{;;g0a8Tae)a!7&OYaYd!o*C&(9x(ZAYz-n|25N~v!Tx~BZ z;5*vAhJJUTY%DYJR;ROe`|6iki0^zP(?$FvpD)OXqle_;AMlklD#`$rXyy10b48XBE6utsc+lG`jXb)1GSB&C&2A(|T{f zS!I3M{jfh`HyXB%U87=veaGr*xx+mj3A&pzw0e4CT4~v?O8?E@)93IUxh}Yt+W0xO zQyJG#tbcR241lw&Ynu~h<0{A;+G0V%dox@0MJ-Uwl9VBnHh44;2 z;5)&rZ`CsR`h(#O{Y%(qD;*0-flgIxv`E+OslS}f%}QpxCnx9cmG{2;F#xM|xv{h= zu|!XP_1AwH33tnge~SST`YH`!*xFX{OZ^pnPamIY+S|B3IR_noN1>z@aAGH?w~C0+^AL9lSU6D2$H%TdnK)x`;(mh;!LSJ29G25N%?Fg)m=s05arr9^M;6?vPVv z=gxLta>=^POmR&oWEJ)yMB#n{=R{phPM+=nl!znVFUIzyi~Cw@IFgE+!o=oYO$zwF zY!3Uom5>4|PAS`}ubN(L%}bG|4p7}=fhkGgJ1~VC&qz|l zYypx@6ebMx6&P^{RF_8Zmm+dH1GJNr)e(S8T|Ol;dV0zl3be47v|xy9bng^YHU&xJ zqq8Qj%YrPmSO`V&6~61};sMWjrAm%q8yn% zAy-kD&%us1TXhB4M+zB$RrNtDb{9U4Et0ewW#qG6>dFD+Wp|FouWUb5NeWl}wE9ih zsg(7D1TdMO)M1aioz5UuFhO1yzNW0=_Tn}qiR&zljHqoZ7E16pHEn~;!$zwv*>~CT zJ;=Zs2E7A{uyf~codNh{oskTu3PlyyC+*Nc z&g$sV)s-CpGBENm=2HibN@HtBQnlMMl3S25*CE{j;s}aIsMl9MA<3zPcG3DQ*q+arQZT^$6s z#h7b#u~ITMJ|gD}Svfv2u1+#{XaPVAj0T+N`g4CGYfXSf2(GSGkXEm@<(^mp6$=1t zA)QiAtIW?VUy=?C$HG)e9+{@jhA+=v+?Id!>Z+s>Q2zE`|DfE}T$kk3oc!xQ{*0Vl zn1Ka z;GlN9ak&kH-q_xj3ws;#LUmnwjhZ}`n~~dNJ*fc&S;Tu%2^cMBRz>XloMx2HNowLQ z1Y;Ap!F4#b%Th$3bu5Ew&oqM4-5V00nAc>~jaPLfa(=8J-&||S9zYrD>3ncuQl8nU z%8yTs;-0&bsrqscs!)F$&vy}kjbd3`pSafF!I!}cgJu`Vw zCrqJ=M;2CKz=vq8xW`1%w#q4(VVN=dGdzn|k&uiP6B-z`I|QCg)!KAQnn{CXS+Jr= zG4c-9ZY*IEKu)kSX3tT!6-OOYR8j@#Lr>W~w0$vc>!V1n0U`+W@VR%Wo5lO#7!4>- zTfs#Ekp{(v2{t*R6l>2l`YRn}g!T0~#CkTF)?$RwWFlM1v{4egOX_R+AFESw+qxI1 zT{X}S?Lg$?IYyfRn@+<*5YZrzl`G;|?W!m!?UZ@Nv`~m4^V0?YBuTT^D>4=FiNCuaOWgWO$y@55ZSnXUCzV*ed6|p zymxU{rr;+%tP=w4_m7UqOB*|~jAW*iaIK~r1&X_x+$CJYiq;9IoVeFCfDzj~M#iS3 zh$?(}ZAq#dYXDEo^g7zww%P{=33(OwrEGi)-oK5wfP%yo_;}hx1)P~k;sv#4TcshC zy+Q_tZ>N-s88Acp-1AK^OHifJ?HM*uw{NG~dg|{8x}_9=?3q?1yl=Z)L-O9#>0pe% z_pB& zVkmJx(-(+k`l@)eUGtu8cixAX4fcoYMeD>4ju2H=H8fzt+ZwBR?|-9bd+(+ z^}#>M;3JztLH(ewV8rImp89)@;q4?IvniJNI%!KntKCVr?1od z6PLGg++n{4n7kv->x$*C*UsC27~siKpJ)aYanj|sFMnDZ z&8j33=-k}8F8|9f{yVH2YB07`2dDr5snwviE}lsysR?)@)>nj@U(b;Ycsns#Te zZ^-e*QP_$d#191k%G7^sY0F@l`fg-@;Wmt>$#&v3)HOdz+bPcrqj@RJj=@F*vM^qh z-D(>E8i623rp893TyJ7;)FkC)5gRvEhss0lki-5+0d%P%p4~2U;0+4CuoIhGEjhk0 zg*6qEM!zNpCdN>#3}mnF%k(G;w}}1jSr}E;yC0-sH=2kYT-imDY^&B)-6q{DA%S_s z&pp^yF9bN(lPpE)V}Zt6&2C$#@y3z~?R+4+(g^_qG6wKX{G=>i?6-C&BmKH#e_{sr z1YuGqW7C%RQN-3M=lDDwEP=oA{V1|~1I)>ci3j^rYi$cV(et^IoV$JlwgdS}-0b;M4!I!)}l#RNzQP#rj;n|X8iv<-QPN(zoTfh4S0QhCw zallv%c_;iPpZ(_M8a^NYb^u_*ZjFwQ$;3no*HOkAL4gBy@Y2QW3iPG0zEepSEDJI} zKPQdlPzQ6}f8vO2V=Zy80~=+Vsw~Q4L-X4=NedV{VD~6b0FXf@1XMV2~UcU@Z#BhvyXT2d`wG@OxB6 zc7|G8tWZP}(hMS3Ds_4B!Y%p01E=IQIN1N!XTC1~;YU9#>+5UMTiulyDhtTKq^^_- z7#|?)h1{5oPL!}{uL+=9B(b5)mq?TD$u=rWWh~y)_ueBZR2A4BQh>3XT%3`bUqi67 z1tXb7<#G$v!VQ^NJS>IDc`*Z~P?b#7P&sJnq(n~kacza4(*zkHytcI=8{1`dJnvbU zHq0!xonaG)4lB1tRE|k1nI19Muuhn>H@a1sN=>P7db_+M2Pd*}>6uT-`TO3DDn(Of z7Zzm#=<&^O{t2vi#Z(4+O)1~r#iq{6z5hS<{sY>QEV~W^PeeTL-}nFL&!0ZaXH|8X zuJ#7q0GhBQMPLAsqLC;Hlt!bGw3f&MEd813jdqydugyPQnQFn$Pn#gb}NNxGtApx@I^eoNsQwj#jV>GpI2|d{u45)J zCeRhfCY%LgQ^jp>?$)I}rpS9-0~wlV(u3Ov+t{E7wyU2FBpm~W#5~s;AS3*(`bVw_ z&R9mmb)#j^7VIH7V?Zn7-94Stam>5OL>(bhb+5W5r`OU5`ix8CThph4yn$_Iq1iU9 z>9M11xv?!T3E4@>i%ozPGK9!P8u>=oBZW-h5a$?;N6Ly)kcHVbj*(C5JnkzMsD17B zG1f_z(fKN<8Cd2Ozej=Y(69uUeP_2A+L$o|*_dGmnQ}=3aIy0d!Scb-bbDb8#F9tf z2FVO67^sl3Wb_NfluQN287A0Hu~=eB%9^r47TeNm`Jx}O$;SE|;&GGhXSR%XkJr$G zW6N?+f&dgmrY~1R)-cKEJoL5wx3ZS-*^vby9XD;5D1i~)9AmwY*hV{Ux-T*yRjyG# z>N+&mXJ)WZ!_;D+%+}BhL=D5nK2x$BZP}IXUV&KQ{cs}6t=%0pm~}K`%iuAAXGpCx z!+Nk>D&H`D2$*sGI(9BH$O~9DR9e6hnRFzczCHn6l!YM{tkF-3Mae81TTxWqYXW<%@8=OdkkFa{RT1kXVq%4+ zLuxQ#I~iv9`3vV140x}D44(+xN!$xj!to@Q~+y0l)uvTH+%ij{hquh_k`YP^m=sNTq|5B z8Dy&?_EjHyEbrNfkehCubod=xie^}6{sb^13ykMTr`L4=SVA}$bWLfRuJ^e5InRCi zGul1v9n9^&`pq}xKSRQfz&{zFiwL%#Mo@lrrzS_4xPn@Ny*}#hh1iqHT4nha^=1^H zf*q!B(#IHaQs(CtrMk0enpQ}li3qOH(U>;FXsZw;3LV3U4Q;s~10mWDf+-R6kc<(R z>=-|^_QWJiX|G4V?LtO&?l8~>9SPD+6{qu+ac3Bkq1kU7^Vz}3w+sPS*SmI)jmOj; zP*R}PGmNF!B#|q&d{__&?gOw~kjl}q^iQ)RVNThWjxFObUvS0)O<<1s2cX5G8nW0it)|aS(ch+ zl*upwzhR;h&}(B2H56P7Cg3;sxEMehYJe(Ws(YjHmke9NBoZQRugKpwbK0><7+3W~ zd7j_vFwKE6H*O>U>->zmnd`-s39Qf1?#sVYxAOF$cl-+7w;z)d* ze|$xL`tSZ7B-8<>B5-zHuEjoVe?oE@?gvB68&}zY6u_q#cn1E}kNt0cSpKWO`qw1r zvdq4V_#!P0?48_vQ`7;fx3Nd1r0aC#sS6in!161c?{-3TZfbJEC(}AED@z5b)S5`V z#^lYr74=W3??zhyNJ`cg;m5lLB#|81I%sM9L@=coAE{q@emyJuxSu3^Unb$(@Bt3s zqvuwWIB!zk-aL{V{MdkwB>rlVsbI>zn)10l@U+nK{HbH3{e7zW}t!QUC(u z*6y;D*#`haPzedO5i1gsYA0Bh*av8HwC~H}LPq*p0ydOF(a~<{oho7(ZQg+MQD_~& zPqKg{1;G#i9PtpqJmy>sdoRIfmN$-dTlGxyC~7R}{$}=YO}vHX_ndRoGaETW(Ta3> zehOa3HBm>&05=wBQz;E=V`g8a9-e0tm|R9fJl_sM@@7YqWU+Xt%sn=Nf@uawH-xR| zYAN!;u%ac`Ne|!^u9?ZufGkz|xIox;w~sI`T>#(!K(l$oZ2%1^mC_@@VW3hCBoaCC zti%w%E|iKg3fXNHG2xAU*xiBr@E6XAgU_>B)(VpTpZUZ`5f-)(w`64n$@won`!V^| zSHC5D?Jca;9>B7^6!FJ*r+WTT6L%q^5;@A_S7!Cy_Wv*fum(r;#^RcT12S`!!cWqz)pwxSMz zvsSOl>ZuigXF2%v0g@Z{Y+2%13fMn8?V9?aft4OH2|_XKeA^($O~utO9U$JP{bDC+ zwLz1_6MWHXMV1k}(@&(wtW5Cb@}Q45gW`hHhu4?aq=QVG>>f*QoRUlBqBMZs_F1xb z+Bgw?IIEoe4vbi@)0PYt`nR?YhS1@>RDMy3!JjOB=dK7%!WBLhvQE$AfMQn65JVM!bKv4e-{B1m=t1;=Z+ z))fZt-dLaQm>t8&EK25JxU)*NO|n~QJ}YznP|KU>2+;LssbXPyQM$VaT5?H2Q;rWa zn|*5K#8``uF~R1VNE(f@SZpMPm5cK7TgS3_ZyQ;oK%SllNHKR_ZomGzEMx=u_&hS1 z=bx3kjhZ^AxzGf|H*aksRls?(2AnP-AO!kmy5XEL$)D6 z_8|ZQGs1Z7jXn9p-~ETgYc%B;4&1`>iaeTv6M&3*mg4gDSLJ17T7Mmz>REj5InRKs z%HrXMMhDu_a9gMTuhu&94>1nkznGLC2k>xzXIHK^8}b=|DUYnq%lmy$b9+FYB@2jq z)-Je?Z-YqDIjY)Fqrk3X6ReYRobveh)Fg4)Q$!rTmmFea+Jm!G8#krx@5pisz-1Sp z2SD0Wa7ajI8Qa$0It?8IUKs+52`=Iqti+5kdSJwfgTMqKp6#$jV8XB$4CR=aIHQT} zYe~v0SKrnw9y``WqU&SZHl2Y&m(CULk0rs}Gzrczlb49Onx#{%58r6Zm{LR2|G#=Qw=PU3ZR~85}kv%vBDI>BTbqExr`9UTI%L^H#s7)e! zt6SIZMB2sBG4@Dxc!Gomxk~A_4_L2@C5*VgLN2QT=O`R&CX~8fJ$5#Vnar`aIZ!65 z$y91~pN=K7rrN#Cu>tu|os39RgDwM`Grf1n1$&Aa%;@2(8}IcRpA)$0O2yGa%Je3_m)j z0!H?`!kO<>AXBX7R%k)Mz}F74&prRRGJnWg86p7r<~P3~%d4m4+=dZ{cV~3W0;^pX zeIMBu%^heUxy^t#$M&zpc*=AHvvMwqnkF|03s#)x=F+E?BLoZ`BQfV9!b=qb^5 zGFu)23tTJ90AKd^`|`qz&&V5Bugb62TXGc{{U?jaj(1zKfPMR;b0v8lfyXWEXQ#?3 z1@O5}JN==Q7m8YP8-^)m0Wh1N&E%BLsZWXE3WDKGu7HH#4s1EuO-Tiu7{s;)BehY5 zY(c>U0#giF#~M7wwLFn+>8Ynj?Xhluto{R^O#yb0T8j*_3jmbK(qh-OUT8YTa!;Tj zJ4exTjNQ^TY;C4?^U!%9hBl#Lbc>XEWdWh70*4tt?m8?*CF_iTXk&T+ z+oB{4=ZMi46iooAUW>hsNYveVQ0GJUn3y#s#xex6EX^6;oc2>Y5sFOaX>=}QJFIZH zo!_d*NTKY&G>=Hof8%vgt5D~Vr*?eM50p8=vi;EN1Cik%j!iK5#vaCEX5a0@51p{9 z!bs!FH{DkywEMFui|1Wra~UbmmE`w&xY3w7G68F6!74LO&U^lR;vmyE8CP~qe`s{a z_%|SM1i2X3Y$&&p1g9or2R`;+`G5U26`#yz(-=!vpE;9a?dAaUJ)s@y0=-9HnJ65) z+dEtGSN{5chk1b@I>&O-P#rGaq@5$kJ0=kCsJIe%tDIsk!-xfDPjb{q_( zjQt#84t(vgR4M?*=%*);h^5wV*2QZrS)MCuY_i`ROO?;BJqEayRF?M(S61YkH}~b< zc1^zcu`{xD)Yp5A$CuUrt`A^0>mBJbhDgARUdU@_IxT7Ij%BWpky>LYmsS_#&3iji zOcybKTDq5Z{Em1&_WmwFD4dApS=&c7wF8{*WQj*FQ?NIi0xqeV`=R&m|#+HbgZ9mz^~e@DLc^>3&&3&-Zd#+t01It`#N zCAaQg#dA24oz8tZeR)w?`8V%uDJYvSaQgX{Jc0SwZb$+kWT#h`?R`g97nfvxV@VoU z?;!@ek0feW!LMYjAZO34OTE?5>KZQfh0=nOIc{FRAxjJMa(f&5F8tJ7A4wPZxa*fL z%30WfZNz|VR5lp(kdR5M(0vo2?fFx4SbG?U@`4;3>`5HS%t~iqbOk-L*YSB~F>kn^ zkh$CLbaef9x;+KK$<*uhhw5i*!dtgYyMN;!t!7nDZCu260>~{=LlyT;cK`UHi2Luu z5uWfPCx+H|qVk<;x=&;lWSX&@eeZ*RPZ(0s`DF$`o1QqLU)d8+Gon0BWR63-o6{aU zQ?-amX6XS3bdms_d_J)B=E)6Au0i!3ut`<`B%A?q`?(A2nzdO;xblDg*rO_7cy4(~ z#t5KNZ(Nf<@!5~bH~#U@DH~@2AcO$XW*3IX9z84lRvnp?p=`lmBnvQ}jU5T$#Jzpv zx}2r6v9codSH1<1DyXu*V%LngL}%_kKzvAyE97)&dWkn?T>$(Xfbx-_}eaDd8;5IuD_SfNhd}6epgb=sIm^6 zk4ufLr|gk{;CzsAIii=Hs z8wNIkxwM)KQj%jh0d-`@UU~JNd>L7>^-fg|MptEw>{*P|aTTmK-DY&Ej|OTS)iuR9 zaHAxM#`eHt0x@`RX?{V@pFbndT+B&4zbxT_Mt#AHz zt*%jE9R#s#$*4;oOUl$ibqEZIRJx8dFh35P*qnB|svQ#qBbhIWf~%2!6tiTsAqkd6 z*lY6~Q{tsraAiM?qzg}HMEpU^PvW|6SgPULj(;(0cN7G``>M67T;Jc4m6fEns_qX0 z1?P$gRv2t_;4si(p`Mx1vS&xYk#?pcxJI$^v4z+owhvhXerQC%2V;}5b>og|<0L2? zN!>o}f)y&*Vub#2A9!Oi?W;}b!zSd}$!<)i9&21F?ISIfaV?rbQB4Jrv}2Lxu`wob zIHYk61XwOpDjsTRT!wOXvHv(~%8AU44!Nz5hS~Rt8fZb-F}M$sgGr z6nEx1ST5ihT^CKea(}YrFbUh0P_!E)&gJ_j_FF9ySG_dTsnByHaAk8a8~nb`n{H=GD(_Ebv*-{+122m z-EegcTJe6CUSWxhFQ5GQM|FP3Y?)MG?G?4AdcD2|>k%MFtvW4# za7>9z^nM=EdUa>m_R-I?9R+!Kwj6C*mYC4j$k2*PuK8J0+UOa(fX`~@SG=cMttzvN z%;hi@Qx?eCN1v3>fBbp*d;k1j$xmOuDgXI%kE_^kh~S_EaQm|`+V^)4r3OE$oQY%I zdhpNMvObsBEcpQT&&T>2YiXrtz8hZ_0%JFvmI_CHGS@Qgex-6G9oVW4f=)-13BJ@0 z_jL|v`Em4qe%}mu6;TCjrMJvBZ!qq6qzh+~I=-Ec6L4HYTc+nufHgg@$u`V@WF~>F zz`D4Tq?32h07OR~Y{AH|{0FhICa<}I z*_kmEQ?^U6d`zD-X~5f<7wQN*&RDgBhrI@3l9E=vkkJ;j@8feVfR3J(xEQOvOQ_X^ zj@6!IOcW?UIRv<}0H13Y;2awjb>N4w^sk&N0T4WduiH_v`C$)!CM84QXRz4?OLASr zQK?u4faZNU1Sr_?O($qp!cg~%U?PE zHWoReUHc@2ATTs@X^XHNn2@g$$l1Jt@JsZ3Ghr-OP$ z&YVJ$|Iu@DfBQ(DeR5GMRoHf{mqZ-?DF9Y4q4IasooPji@r;&K)mhT#(QPpp>$e+DxB#E0?~)-F$-w{tR;MTPr&pv8OH`>H zVW9)P4wG_-%t6Mf%Ryrx755m~{k~KVUl;%0Kz{tk|E#o@&dD49^6Qd?(MtE1N&eyg`)>j?o0ltJ`hM2ps1wW#mImdT^*7^Cp=JfaCEv1~2-MLTqJuX!jsYpg z)UeR(E3#byj8MWc-D&y=Xzy2na>rBZ6pWaG#Ah_CiTkf1qvIr!x^eOM1MRpG$Vbo5 ztFdN@59yzAfLAjAw7l@#^Ahg7ERD=rX$)UMW?&n}X(T`Lg)hpe1puelmbdmQa;h_w z|LmogU|ax(jT!)TVAK&TXGf+UoXN5{%W^w7yY;tTk?coa z01%QACymS&{!S)}O0^}`dI+#8UQA221ZSId$e06#VhJ08BMU3*xc0>DD+jMfo_MfFDAq6s&m2;jcS&SPM^(b3^lofu}{0YZ@(_3Eu_0C_?wBXiein=%nC`5TxnRNBqYia2WrJufb*)F-RHwi>}t7MdEmoWyv z)DVj&jCk_Uu&8`xzy<2K^!rE-3|Zc605)ZQQIsCRwU!sMDS~e@{VIlyYoquw0fJu7 z0eCkyLb;&{%tnz|ei%+V_c3cnIzG$LT&s1aEeCCrsJCO!id; ziA1zKD$uglxOwKmG^wLADWZdghVi816tl@CF+hpgJDtg1X+AgY{~IxdI1{4zKAQnz z38=3eK4(&{Xs$u5CXT(Hz)Z>rcvj|uWfg_;!8j&hn;7tI_Vr1bWEh+Pb_`e>sHPp) z2Ip1>37q5Oy%WMqNvC7;rV&87d5HhsF?qR!8L($dXll6y|APJCcTqy0*!#Crcc+uZ&sOFq#N5 zWmEBqZRQ$JCC$H+95*sK88E>nr4a;mC|(Xj%Yc|c6BBT3rb1n?#ib>^_dNhu3jWc~ zjLmb1+pd8Vf~A(Sh}sJVox1U1-ZgQbWMnZRbhy6_z^0=Cl$Ow0?Jg(E2wPWr;;9GW z1jLGP?OExNAPgswMmN;F%7+mzcBH416QK>g`d}bn|lw-I7ef9Z=U>Kj|i-KQ19wH z0af1#*y3aJm063i7^s0%yTWaNj1E=;Qe}ekpP&Z2b~{%1T)|d*;qfFTy0(K)c^sAkn9$7(Jl4vfy0I(-aar**JWr4q1N&K$yc?TUzy1bMD?| z9p_8RA^?Ef0FRT15mNb>>HsAYIrTf3-0D*X0N0Stz@Odg$d7#SN%_Xho3gr^gAYQD z%9uR<{GwdF4WQ$2Ag435{1n!a44NsQtCVMTT-HGo$IaS>1L9rmRN-**nabs+~|_^2ai*V2-Y z15|4gl#9s$Vi8)y*w6qNW9+fL0d-{uBxAvL3{-c^SI0F_|1pLK!!oiM;ydOFDUeS) z$a$vv?#jYN0?TiT)NaV2wSw5BB;l}vIOw+U!TJGW9h>~~DM+qW9ib-En8ae|z!7X+ z8{4AI+;-YGzzQ-SWoqyX+kvUAi?1n zT_^gPS;QuojPPslerf=+jF24{$1Qx8)g<)Qu(p;Q`PfU($@R@GZ60xI?UX!m{(>CT z4&-0`=9lG>bLZt7Z@r?ebgonZ9#Nxh z1pBbJwWn-2`eJ0+v%_N&bEX17vNNDQa7z=fVIwBTm5$slZA%$R5X#7KpQAbon?GE9 za!pxz@dR07ZPkCP?A@14DX$6rgGvQsQv%@Elv=H>Li6fdQ4gBkKd~Q@xy5A2K+Dp{ z8h7wu^C>1inIPucqCC#XCV|9i3UXiX!N;x~>>^oOP|#6*puluw{h%EmN(NSxDRgGZ zSN1h?IFk%cX#aLjWG=<{Wiw};f>JZ>Yv1*|=oI19Nq5YK7)(SX-0An&_gbk{d-c(O z-I;&OyBT1!*JhpaePl5j^_q+@5sRMbmX*)vHH&=f{!NMBcwK_VvD~?NM`D#NfFs|O zpLugr?(9}131j*qfQtkGi!P|TOpX|e6v%|^?h!xrM$mg~&qGh4~-C81{RG>a?7nQ?F~mn!sb zR|D!Me$Eyz%5Zy2=74}xdx&kP*{ZdO+dH+8QGJ}DX3by-kuC7Dq1<`rzN7~oWK+H> z-a3NrvFY-2e`_C^R1X=MwzTn?Zlxh*ApUN(DW?)y4bsK$Ne;mswP-j6&SQf)UoHTp z*_Dqya$dT3cL6xTp&YXuz*WIjcFO4W30PoLPmQHL>cNT4$y_=qU;FmUy1|~gcv1GM z75V5#u3!Ub%GJ$109jc%_Xq$l&wvx8)T&4*DecLkj-7*ZcL0J7vB@W#xXE6!4sO_$ zLh|zj+rKA&fCH4Eb}<$pSaUUPl9<7uR!g7~ot@SL&HLsUd(p zghSDJRN)!@v)J^B>4-2d0zL7>-^6S&Irr`6`@=RT$gC*pw+Sv(s?O zayY&qHUCKV$F3>K#$!KDXXX4So)V7^GOoR{cPJl(gFuoSMnbQVMqL=`ts6}`o%5n= z(_q)m1ju2VasA&ULoF%*OlRGbC|C?NYfhjfhxs>P@L@Wxn+y!zn_>VWhIQm5qX03` zIZnMP0$5!YI!D0BQXK8X7gumb0U1jjW=AbLr3c80-#yrt^QY5#-MlsiF`gHg&UO}P zAX74%@N73iPv;cp;Mg%vJX^#wQ%jID#xhb<@ThDvb`)cIjL%FO*_32ng;paA^FDME zI*7a{I{wNMqr+mm04iwbnQPaf4aT}LE9Rv_$RjOF>LT!RLZcDp1ZHd*6tm>dwOV1S zjWskK2!~p-o5J@FRVyNw%T7T;*J!)Y4~RM!5`=c1yc40B#qUz=cQJnj}0$8)Y!OW}r-&x?s z{G0!E-}U)Bw{K3~9|1ej?`DtLl0-KG2O_7*F{M@ptO_UM+1e@7on99o&)mW?)<9YT ziAZog0*rb{nC$}y*xlKK<6e6$*J}1+l!2M}Ii7 z35`I3GA3kVuCY4?+%$Syz5@1fDZmfq+{%*GhVzhxMQt>Z1H)9Z^UJWFB8d*0xQUj& zGqW~CCi8Lv)J(8ft25;oK;4bjQG|=xwWBO#*PYJ!$asd+WU{j1I$gE<6j{zu%PbkQ z^UttzotfmdYmJ!!&D;}fO?_9#?B@|!PP?rPUd)?*e`sS1G3<5!_ilk^fvQ;`>pPYT zeuqQ-_&7C+x|#@yS=JtJOH1rA-zbF6XRXNug62xOb~G8HY-PtVnZ3BDW5DuDlbrLF zwHNdpokN4c*s#iV1mRaCJq1X5cs-W&q}3j4x4$$J^$pmQap-H}IK{P>iEA()gOA#% zjyeHrF+&Ovk+MeX$o9wsy zQf-Z-fi;-U!*A#XGKVDi{!v{PO7qefP!xPl2AFGA_~sYR3IHI0(nFT5AyF?S_(Y!S zJvI7cP3ZOdq`&(LIQIa!ol%9n??s~ z*eCc3ztZ0lceIVg4*UcvfSRiC(A2& zBo6uj`~kX==>%VNud%P|c6D`Cy8)H}gq}WqMq*58U|dhFt;-_fupz+JyNC}*;~u`N zD;fBromNkF4-O@r#opGbW51|Md0|EESEq#pMo5-y2Y`M?`rWRy@N9PhVmf0_8${68 z11ldG%-{E9WmEgO-%bh$nXMzacl5+&IUU>N$y`t~a_0HS`p_46>ej$~l`H%e(a z*!Q$NDv>V8#<(qMoV(t~z2$+>BS`OCa1Qv8By4vkUK>Tvoe{3NYiQpNyAo0d1e++E zuBkXIjQkwXat3=eL@gMaJkFQRl{BDk^=Y`VDPlOY*i46eds1%#Xsp$w4xpjmElcy# zihS|;4f(V;FD<_$iSoR>xX_UK%vk=@KlVupVo5pU4NSnN4wIEY#eXuTIk|B8NY1tz zGN!Hu*&DD?)be^G*pP7kj9jm@q?%b$9WyWIXg82}EGO=hXJI_x6u2B)fC!E$yKz;V zd5HM{Lw**Y`}mVe{U#uipwYA$NCGp8hcJ-XKa^tYO^IRCWM{;DXiD`u2v%yo>ApmF zh;4vB2!|nin#`%#^=$%V!@kk%wrc?vnN}XzW={&}M9c}!VJEb#5jb7rFMUd4kDr&= zQc0ZUvc87}b1%yu)bZW&nmjxn9>0&r)6}lJ^1zF2`TaWBI(&8D$)lZ^JkmmP$Lfvx zv${}GQYf5FWSK??QBEsLK}`T;$DV_)Ip2BD{)0GX6I^0hB(p*3djVWgV(-CoysNx0 zdY?U~(fcuxvneeItqW_6OP`ZFckjv1{l=^EKV!c? zpG(SV3Z1i@8SlGN$jHBH)RB=l-_ZmRKbNK!)d)d(OaYTjE@zTigRWF7$5O!_&qfz4 zvm%>HHA*7gLd#xtT*G`NTa%hrJ@{1=6=o@OlmhilO^C9g`Mk(nrB)1$ zAfD8*YU26U5EONAu55~3vv5DSmJ|Z|d?sTwu!6pL_cl#>*Nsg|gmntrE`Cll*F&2e zvL!GRjYluqTcf5Ba$=3B?-TeFt+j~7rDc?!XIThhq4cRub=()dl5%=hrEgziy z`FDJ9tnjQ^Dyy;xqrfImjD}h~>1rbZwF_R%GieMVvQ>(EIIW8TCI%_d4x$F0+ zz2!==oYW5MDiE%kWB`S_LuIBsb!J{(yS^=@dCY69+;{FB%K0-nEm`Zc?9<81QLBpt zuIcK$jR3z4J9Y64fCYe51mvp}2#Azj|0i4)9#yXFY zA@69}zjjki@HqhFPsO$L)T0Kd`juo(k2N_+Rwf$=Xc;2sX~Hu$ZRA__G2RCN(6MFI zWWtfPNx76n%GHF9OJAQ!1SU?Yr=biTqdTWWd_S}r#imhBdYq8E_i7pk$ zu`D{z_<~glj-0-{q9y4}9;C7ab`bl;N>c9}%I4m-eD5beBloZE$aX3(w{Gt1{Wf7k z-7(`0vH@dSeen4CGjeNl8$hKeo7?v=#+ZYM=`Nmo1aqJ)o4bcvR^G$BC?MIA10fFJ1m2KEAg+#&ELp5A>#GHMdEvZVKWNIIUI3cxWhLh< z%4z>twuUuXxb&o4Dq(@o6=dheP1#3Awp1os5R=!p_TTyDo1P@o2_2ULfRUwATs2l=q@FVWJx&-n(TYrSQ=&H2_dK=W}E`R~c!aGl}Plrt6NTrA*!bXh89BqoHH6smKBXP&wPYe`(fl=)DnC56q^rGbuxQcmEy{l2UY+sLAgGM7GqW%EeFqm@L2$KacNt`|Vru^@FaKEson=IXI|D3`RN5^Tq?!5gQLj@BL^ug@xe;kb`~+BS+kTtK&y$)^tEk{Jb)GNK6R@Em8NOBq-_F7*a%ty5Ii zuYiqj*+!w!kMP|0e`U@BL9-(5JZAlp2PFw2cKMWD6)~-h9$Ez4MW8{%WHCVfl>K7L zoeXdvy*^>D&9Gir4m&r$pgsY=J7PxB5q{&1*X7{wK=$_cwe*$RE$bWSw9NJ5`3q7k z6)dC6f-v^8kx=`re$Rsdl$Ni><0r)4$*hbz70wF6`?mXL#L|j%uoyUdmQ~`~E}o8M zf^|AAX(Hj%?QkDFkP`MJAA8rQzVJPA?e>nmb9Yz%+qZAaUwY!AHi*dL&vGh|^Mi~W zV$)|3Uq=91NSg8#YEBXaNdXw@w(GLJy(c?JRP{0b?RHOt^k%!GrF*XWOh#canX;|Z zUB_r&4NM0xWj$K0D#KLujV6|iHE~28u6!n`%zAdsi`i1YvF+SPc5Q(jhw+TtNa!)U zPZmj|R@c2dfq*fMXT~+5;2yrKNnvO5DwxE>Iaso^kV_+hhvXBke|2d==HN?YQpd6n zpNEX23<7`Z%XGQ`0g5Hn+w$DFvbYpn2%MR&nA6hU2%L&E-ORi*Kht0ItRUh8d}20 z>eG=Wq@We%BJ;yuNOofavBD7cB#9(11Ng2=sMM-WDI(c?{`@ik)E2;Vf)hRfW6XaA z&0?x8M$NWLCy@EMle@8)R5{I;^ zjza94b-5!osU9B7#_4nNv1gtK2%nT+`SLHz-JJvZ7va|>8^m-ifAXU*DkJdjjr(#B z@i2Qr(?+r^b!-1V=2S)61i7SpjsaH=DA2`jiar_u$aiWlyz3=Zs7X z;-VK87v+_!FB=9htZ_D%*0q+wbvF-dsx!;dda@W>{ejvMvh$nGV+9wJmn*3-McNi46+{%f+i zJOGeA;5<$N&HSP!8!5o=@po}ihjq;+Hxr`Z|_!RZt1LC>-S}_^9m4KWV?V! zSC01pY`re+BN)#++j0s9JO1b+GAy5y4H)>M4CE7YRY{#$msGARL9!%`LLhZ4z<2Jx zDbHP4$BI9cxiTDyEdW>>3-Yy{8o;lZoJ)*l8D2>Wh;tH-$?3BfFkU0Md*=WPETO`l zfAYJ(s2REuj5oXMxY($M{SGn}O(~>-x()g;W-S%lV=D&F(oDHgx8V?unpN#y6=KoX zVd&LpVpS1Erc<_$Y-Fcz+CEboWfvLI%7D~JLtF16qZz|@j$woy)@5^7QxCz{?4grP z%Mgon502*|GMz~;4xq&+;}TYmfEk=YIGQOS%@iEG)^g<+Zyre29m>CX5l$%3dN)y! zU#e%2IdEjH3|Bl1R(yLQ$`| zSEcywf_9*YxxSnlZE6=q1SUVK_E0KELgU-@~d!Kscn`o_n==0uP#s~cRXWnndBeL~NmJM5B3 zFixF6wof+oZ%F2hHDji%V}Npg!syUs5O}1p@umhzDL3#v@F3odEhB@}*ENv(eaJxm z>mGhEWq-O;=-lWyi2<*N1hM%l>$6;wVRfuysO1UFVur?+?0(m$Wb^yKDC0~@9v%;m zhsVGE@p{phYdK#&zVFCK4yOTHR2md9i1?4O4WKM)W16ej1k+d<8ot$@ab`LkzQ0Fw z6;TjA0itH^Pv18K)J1@fG8m@R4)a-#fn$A|8P+HSPnmAZ9EUjm41>USYBi-83<$bfp1+`bb|3!9 zjk}u&Oou8^A8O-`m;xXyJ!DCB0?9j;|LDaF`a1@sMFd2(X45oZV1lkU&=Mi8m?HcfGQaL_ zZX;kcjXmg#tswZ`C}-vD^1Omj6q4UXfX8wb4(l8ebMaJGfhID}_I3~C)XIvkHTnlp zV}Q{5>y9lUbKQs`Xy>y97>yHQbp@T1dUlQzF_|8e1hI`j?C(r>U2g(}&8Co)u^##| zGugE)jZ7>u*84qw((N#2yY!B2*I(Brt)fy~6_xj+H91{}3Zi<3sb#L)J<*9Xx*vaH ztA2Nf&UyK*n400tnEiGjeN-avs?TZ?_AzbbqNc(z-{q*Bfv@v2OARL6PpjEifR&|f zD*46A3<9nrbFY!cB!g^fUYc^zK-Yl*F->W>XJtctWpfSSzhn>uiW+}ON*>_z zGU7EF-Nv20nkH3E*}R8&Jyc+ctr23j^J=~4z{duFn~O=U)|Mk&@9JDh?jAJd(%F)1 z*JnexWAgx@ucCV)igG(bj{_a#hB zHVkd)rW>kFQC1f3eU0jg*&bDmEe7SJ? zEMlL6>gB=-R2~W_F+2421$LnwRuz4S5L{E!yS?1eZ4;>VD4?+ zm&GF9mtB^-`@2#A0M{R~sn`%>+mU+1Bz6`6-Z$#Im{$dWxfx}%HvIvfF@VQzQ_DID z%o6l z+cBI%H0)kjpl)-FdrnVd*$>+Bp#!iU3}Gj2dZ&2N$=^H9L^L+qOunONVHlot0B7GY z^9$#J-_CyaUFUzm>78C`_^wSP+R#pZ1i(hOt$@#3AuF!~U^@E7SERS!ljoj$T)N-> z8QE{ZK(~)zU{c6<0mSf6Ni97mwUH->$8bR0jx;+JsUs^LYt`lYop+?PcvebR9+Un3 z+w%Ios+^r)mFjU@K2pNe?T+MPEG=``5LRH!kK4!6t!&G=rA7R%rklVUuf8EKeD9B_ zgAt~)S_;LiOk9k90jcU2&MZlitvulbg~wY!$XjrZ+HwG(hIQ;0PMwz4@d2`tMl*;` z%Q`RPFO0-U;g$tJUEtXaH3b$Ph?`~8s`B#IppU~+Z$=)?KMrUj>ScWYaz+IysHd3kKMIb?pu$Q~g> zv@oYYVmaBY$`d5+KOYl^tjfka8#bmwW8u(jNz{xl;wZ?&95Na5tG08eIJ!) z+741nMyFh_nd~hE$i^~2_A8F8 z5VH*AwCYL-tPnCcG-TU{><)s>mAxCOkE4zmjVtNHPET%JcwSyBJjP-?c?nL66CcZ0 z+Hrke-zD$w5fvxIn8kHwIutopur}1D!&6%knmlpzI}HSNeY@okDnn#rp9BTe8FQF*@VgNYMn#YTtrLYsZuqX^%3;@US8lN95$aU&mCK z+GvEG1gcIZ!-8-snr>J`&P1U79s0aj` zbZncsp6E{`&`yvk5_gZZj~*(6KZNDUHIE5A%qJTHw zOC|-&Yxp~MSF2U4vb(*7J+Lg_{ka$AAOGUl<=2r|TF2h~5d^Cl?8_IBINL-bjsXzM zIvg7SQum1f9)I55+mb^Bqyz!UvKVP1&*&fVGYrH>NM5oj1A#3TgRn6LHHn6O!-VJ$ zsHGXI55d5V9YK5juI^c!+j;nO)V89|7eNJg&W31Eb zYmmgQ&-{K$8P$=L+&-*n>0lojEtU&D_sB*0*wc@TkMon2;9wji?gB9ADN`$zNgLg$ zY+kzy9#tzE^hbgoWKgIUl-N1V-x2wWo})fQ>sANB1avZ*+u2du(otPOth=aFV$bMz*p3~VxraO2NQj`=sL9{?F{QNI(NjT3J&wC=ErQ;!@V%#Qa>L`#s zz+CBDzek5JG!0KwqfWc?S{7_*m~Q&4Llcl2K+jZY7P6|ig@mgq`D3@WARI`e1|THU zB{vZBe1Nr`k}?wUWDbt|p@O&sVt4o3%q^SJRDvmV!hDmMVDg=n0QAGlrB&Ik)TD(Z z`IYkpskX-e*3+`JJ&QIQLab24C8)=W{hj;eBejM!x!U^N!jVY7`f8>o&_ zfaG!l3H7dLbo4GQInv7w0ahhsu8@+&yeoT^wiL5zsgH)re4>E5hcWCBgBm$V{3f+Q z)JQ>QvgC#e!V++fV`2?c1}tQWCEa#*ZVr4y6H&<2YTJ39Z9K##3m86j42>ltZA`0w z#Sms>n=lN?uoLYf$qw)%f|Zy%1oc@y%E}s+H)hz)5Z}}qx>^}BauQm#q8OT+)bc^q zeZ_c;5No*jqx}QM8Q8_9lv3Ced|SGjp#EPEped_nJS4syZP>M2ZOLzb``hyG{=}b@ zFMs`8LLL-V1>1<>c3?YReDOIs0?7I0mtU2~pL_yf8tnftRNc%T?k5fqHl9M_y%TDg zVFPh+;B>X=M!VCLPGg|WGv>+|S6p8*4v;d8AuKGwu5QRX*KSG{ww`QbHooGXM><(5 z6-uo=f}PFC<>k|?LqZJM#5e_Nhq)%$)F+$8T#KjV;NVa^T+7=0oNR5~!L#3?dT+EN^8ps*C3|=owiX?Ji43or;YX6_Vo?MwX^zgw)y;;y1jBlIsVH-8PYO#w z`IBk6bUI_jszZPxU7VXV8KAKX8`1&jw15n&raQza0jmy>*`cs7+gRiSWH0~%VZp7h z`m(sPpo=mH`*Q7DugVac#f$&Z7bKBQtE0sQNA0Wi-KvagN3wDDG%^~#tgNod=RcN` zd2C7}Y&0xs%x)dYA`t2$Y<@|HBBeD_@5$`RzU zP6RKL*-*zmD;jbi*WB;Mr7^VS1C&QhBdbFP(uWfV14Yz+gmE~6(OplDwIwbA8s8cb zHXrTa`)jp*IJZ3s;0P`%#nb3!XaL2Hof)EhN_S`1Hys{WUp>ZHoGE3cSE(rNf9v=S z$>Q~WQhJBCB{SUD*1F>~vVeuWWYX0Mg_IgsswNrDZO4>{goXpC&x&)6C5yYYU3qiTZ z&-TCgXTK;v_CueSA9`v7n~Uip!}5gV!(EwQUNadTIzQMvN4xjsr+)oqIeY0*d3G)j z;|zrV=s

      QI$XUnHQvTYall^@5wOkXs0uZGt$XT>wJ6v4+X1ifE#fhT>D=Yn4K^_ zMZ3JkY!*4PH*`&#U;2bpAA(m8kB7(qs>fGXMVL2yv0@q?gc{RYpoN+$p+8A*xlt*d zJMEsvgKQ&%+q{1O)-1~@ocsw+u&E|sR2VT;3}|IoS0bhq@{mdYkN|RtrD}03K$Gsd<$KfWeZTYNaZ3bMx}pV~@#& z^XIS+WG3IG=d_HgNSAA(TVw&J2-q@Um)ZB&O-yx=0#h!iLhn3BU;r_)f;*j#j#$Ei zTzntTH=ZeXj6~iEYEewPQaM)LBmSF7G5)UGH7(5x?7n>Vyu{9*20%2DuYU6_?5|z< zhlj@it~TJaATUJ+yM%q9F$xtJW6&RS4B$aYfmZbZL2gAFeU{ZD91lVb1RdWbr?}r# zTU`Z|TwC^Pk|U<)6(!u?+Op$?u;k)OHIeGT^7i8nH$K~!D z-ETOmMutyU6e5=+BoM3zS)hdZ;Q{a$bsoj63zgxbf`>6SD8q1xHI67 zgeTcVnv8@GInj{P=^Rd*GDIMzW4juPOy;v=-|tL*m@K*pgDdJzDb~+Z04g;5ziBic zRauzwMBlchXBm(w+cDq|L8?H@vcgH-oC?4zKxs7O$YP?Q;%mxu<=1h$#`vf;V5W`r$NhAD0Y*{33whM4H-Hq6|iDL8qb#&ch#12l(7TdWa2{=CCG5t{gPGk^ur&9dxA>MRSn7!%{(;P!QlsJ2BPL8++_>I_-w7%s2%+J#DbW zzxxVu2U?OzKYlcHOyWn0iP%Fu-E4%7oTlU%wj7$PY z`=)m>tY&er&~A<w8d{_B)fcB_HNykONBU$!%&u&=VfQulG`xQkCd0ChwtCHe@E;6FJ5>` zYC~ix=H`I71K5H=FRTx=(-?z;9_xg$IQ?N8U=Iu^j8}SbP0pNMmoXfj95Q<>6)Y_+ ztLXVhu3Xj*YkN0dksLDzcu$wYkg2qsUoFXaF{|2D{noMU0c05fN#6lr7YArlD3)Yy zsU*WfAkBliQrR^_iVdI#2ieE?=aK~}uPjRi;9f{AD+-OTlqK7N*&Uh%8_f;l*t<#( zRWZ$E9@MaT#6CBIlZbJSvF$Ys zMl2n-fLIiH_*%|4=r-{l%nv#Ofe}k|VC3%tY|J7hdf}1Fl2}}k-tBkr9DhlkfAQne zsl0=+$!O_b4TgA>^-OT39q~dH0*#4rgvL%%YGFYNV?3WhU2^%1)s#_? z{_u~;BkTL}qsMQ{wboD#GrLt%UmzB||7~0q2IPEGtM3}CFu}yFrLc)#lSOtFJoK$E z&CO=CT$K7BeF$DXJRTl@5XYC70=e7_r93uW#zHI19-0k*vgc3A$bv}wN~{KsOoYha z@57XW$PD9Zs%yocCoC%aTEwo1z^+*hslY}pjxz=4JS%P<+A`<~*mcsOnp}^5*6IX} zeRopsL$In+tIEB*cknYZ)SbR&yV=pRR;eq4>B>`AS<)@&E7NCQX=ZPasMZH=B5nON&O$s zNJHe(X)TLm^B4kLO$12ycK5Wq8yQ!91cok>Sh-wAO9rdWt~Q-nDCIE*2|2{S`Fwx= zmw#FQ(Lep?@Y%+AHhlw5;9z-IGG;p0_D5A^=fq-n0;Dut+QLQp0NBUc$cu4PqC62nolS|WeX(O*m%QYVwf5r}0Hc)`qT<_v)?Sqx^n zpwgdn9P3vqSSs4}E!6IrqLm2|;Oi?0Wj?FCG40f9%6E)iied`Gb_}ezvO+E1?@dC1 z>nOBA&4XaogZgp56Cg`VszWpPw6maUc-bU?7~qjIAp}^p`(0p5&*G+JOl?+Z{Lis= ze)MLTmZmY&*tccD+ELfla;T(zM$}FtD5d6k7^omNJC<{8jG8^2+kJLI921;|Z5Z(K z#x@DT>o=Xw$^MFaNz>)jB>iu3X3i5Sx>$n}_;bn*chp0G^({ zG%x!Aqv8Naj;dWbsD%m+4avNLP3w#R*8s36!|!%54tWpuCywi9H+X=0^|oP(Hfg&! zJ_MLy>qZ#I5*bV5k?wPeVH|N^S2g((+C|dDDg?Yz0EL)n^;m*NFcQEEt3<}3nePO0 z*io4!%!9tUzL9o4c9qSQ!5EVHN#T8M*;nz+wt`Ey5-p3xmV>iGa- z8ZdXBmXWetvIIL(Yd0kW5Ru&m$Evq6Hl33x&k_eX79>qMBS4)DOCcm$}S5z|yuh zt)OiuC`o|4*4@`Gxfl&imV^MXy0HeS6U9y*Ju|(!z?=J9V6Iq;_v%ep$M>zJ-;7 zbTH3zhy%$0_5%QcPFexu{%D}~&6Jay#0SX)Ty~vKLpxxbh8IRZnw=F5W6RZ~lSH;I zG=7lEzhJ+4{f+B#?dDDS_x}8!lMmAIp#!kqOQ_WTV)jiFO6!T&qGKitIWgcCq>9cx zo8gHZHplW{JxilB`=b%Vn|10Ww1j4N%J#BV$TRPmZl)3KYeLv_#5|Qu#Ak^xG z%W`~hN5a+)zJE`C;pRKCFwDpTGh^w2b^wWwQgRH(soELK`s%t|-QJfR3`DI4U}V1{ zXV=qm29D!lvm=%J_hcCvgT?uIxxcd`N6nhNe%O;IA9(~DgD+<8jVA{(veIWMxszuv=`O_hA=Owr4$^QnlxdgW1XxVZQhss z!h+<=bGk7lV3Y@MCs6NJt8Xj#>}_z$ofsIf=Nox9YH}eaP;F@q})63+X(vuLBrN zYJ4@M{v{mXO-3zabYf#{0<_Hp6)tz|iNN7RJSs77ViwqjYXLjm>BP0|nRB z$;!|E@>Til2EGTN$=$oyoRI;#zE_hfjM@vuJic4x-qwBj1a;6ttz;KdV-r|_%aIj0 zsbyqEm`QCNRbgbAK}(o+y4dImrV^lHaH0+;!8|SN@U){z+uk?x0OfH0_v zv?bpEBYeQsc{gAcy*3qjkMwkc6Q7IxlL*L?Fr0|qn{S%^W5w+wwz;P3g9$r|=Vnar zB4}Vq-Oby#WNUj1U`S7n;GDm6?Yag>k3IT`l#z`4*vCF5&p!JR&3aG8x<$dMNMxRY z0uP>pU#I04*i#M<4zZ2G7eJ75fCOEmQB|OdpKaqa$4AE+7_&@{=S^pFGB-abXErV= z`|Ir4(=v~wTDcG?V3X2LdFGCj0GfLJp580LEOsx{5;50P<`!aSJ+Bdlr_eg~=z3E& zHqI!>RY&Iha4#hrr)1duosXdmmo$l#p6BY?-B8DLTfn|eUpOA`n(c`rkj`-Gl8r(WMQ6j6W=dv(2S zm{(+}u&k<&YYPTB>)sn%s>IU#$8$8vaFm1BTdEDh`_gU3-uH3MUUTI?!F`G{gJ zE6+ZCMfUO8db=;L-rCgX9NmKfX%IlSdXkREOq+Hwdt)*gYS6`Y?{0j`98~ZqFdcne zD=-{&?9;V5(Xg^^y#<>IicS*R&IEIsne$@1qxlnXguae4slsWa1J?pM{C+1Ym$R_} z8Bv@I5oDpwwucI$tH^&~m~|}cbF>kPuSs=++G)gK?3&2mFO+jq#O9np z+`4}RKr-b?uhP|ug-n(r?RZMOFUJ>JD!=37dhy(HNI>)v$Hfv_TFtWRI1=2WzDOaJ zQ2j3joXFW?327mT@u3tm0aA8prF;u)rk9e|sH+5r6u`g+0Qh1dgU{q890bY~91ZK* zSc`1kgUYeAyDeR()mlfB3o-T}8}c5QJn^IeyV?S%MOH0!4G9eOhasz|m4&7a8!=7| z#FHd!+`4yLHQ^|}U&B61Qb^B>hljt5y)R0z zXgNIX2cD7Yz7b5cz%kj6S=i}3JKeWy(nf+uIpwrrc6ri1v2*H(V7F0nS3Ae#3T>M{ z^U?dSLHywHp)DbN&{>;;K2a9+y|bmp@0tQq&SaN6*`;K1OdPsMC&LIv8f$4bTctMJ zzb74jqH=^8y0RZkQkWBmd2-$M#i_nSbghBXzG-l3t)}eV`IhXr@2U`9tPAkrxGg(a z>{|dad}Ns~6tEbvP(wV~SGKlfABgU_awID-u3ot-#{iW!@7xhN7|ZEYAbFho>YZb` zurkyI_uPC5nL2BFbYg(5jaj1WnkU( z&QV1cmzGuJ_3f*-q=m)5g^X^4tylpzk6`SdT)Zr+@vhRDIeLTD6*=e}NUDg;=faw# zunBGUyYlSHSqaz*RU+`xINmhM#-WHQ8>$1aZK;rl1JRZnuMecSmKFz&>iKhP^6S?( zwSz=0NXy$*Ea=@`WDN!iuCOcMeQa1?c=iQB{zaZSyCnBszbQ>vhZb8#BU=#1XNS1A zAD$bkb4D>!=18ciq@wfywlc`_1Os;0z?H5QvC-z$Axy`Bmb3d%3ZEDqNfqb0IVekU zyDsI{zNF??<(2p;IS*X%6bx|!^Yq_&DJ#S6Yw|1CE=d{L={7|hlgkpokdXp?0YmZH zuYW~0QlFDWWQ|lb(=jluI(XcAkYUdFSv7XU-nLRvwFNf5Kfrj!LeVn6cxVJqjfkKp z6Ru;#X0Yo-#X2p>OR8}JMv_`uh5=4cFQv~lOksP(JPWZYv9^8ez5g}X=8i1YUr{Po zbLAdEKi96}(1Ov{u?sA-Q`-+O6=m?bkI2L0;qmbJgFCizu&-FB>9G~PR{y}RSJ$x& z2$9H#h!{vgI1POL;Qa^CqhmJMoc!DRLxC-q3q$8!@16Ke&U+^V4Tum#q!n8lWOjmJ z;vWSQ@{5-B*-}0ucunS151Hs)y^ealF8ctS=1OICvR`=N1^N8vzf0LZQ7PbTc_2Y3 z2HkBkthyaJ1en4^Nf$v0OEC6!;M43M%Fgbdmi1B3!vqB*Sz21ezX#gUX?<-)7B5|f zZ<5oFP1oOfTYmo4Zy@orEMG?8@Z9sCkaL&L0Zc1O7J;d20l7@hXmBxL$>OsN;F!!~ zX$G&Co%vY8ba1e*g6{M4Wz~Y&#dYy|a+#Et$X(c2k{kDSw50D>0Pg(g;=GRCJj=!K zY#N<`tS`+Yke%0->zli#^I#w6F5w#J9MHRB_bHa$P?UX$%zPX7OMzdqJ;(@PSy=*m zB%9TkXA}VlqR&_XETQTIHHYFzGNu6Bm81qAia<~o<3*4xK39|il8U={Rt@++hmDqD zPhjl(1X2QOhB-38>nthc=~;r6fX_(b)`w5@x7!;-U|(zwGZE!ePv4}ZGvC?DQhee#y9rT z*PxreziOHVk)EC>6TK_jG1II!Pgy`ptP{g#V^Wmsf$Mn$o088PO`kqMEP`3_cxw90 zT+zAZE8q%HI&Hu+FAx!uky3(sHP) z#LnHJ)BtR;YQ)94*#Vt?GfTcCOv@Pdp@F!rjB!7;Sd<20t2z?SKGx^}Ks1$~Qtm*3 zF0wOWJ+#w%A)QplphP}AZ35;!ySpo%gAvZ>N{&$yZa15bDY#xJ0?h2fZWdi>wtNN5hWHcD7^ZEfZ}u3Y1s5tq zt576Jh@az#?Xb=c*clP_E|ZGGHc)4+qoU{(tmU|;Q@(bm93T!^Divi5KqMPDV3JBA zOTgZjqoaM;Q;f;TtkX8Y$emzY)>kh`t$8GE#K0`)jbYwizj+nUKZE^*rHTn%-wni= zRm=gNHklYpA-gP<{vLp_l3pXr9UCkqtPLcNIX=Rle6fT*Z=_6GM;XK;WdYLGvumL! z<2YqX3t8SPk=~qR{T?yR5kdn#M$OX2YFqMe#(iuU;)fp`|0g;=)C{cIe}@mSGbY3- z3s8k&IN5|8C!8{@Y&PKCH2dg8(f5i(4)1Ixc9sDabsl-}TB0naGyDGNXLX!pQbQhf zL5gbbLuGflItj<)u6PwLyo@vx$WC@*+WBp##s!B=+Q5}}u#lf$^yDhCkoWrz9GThj&Sha3(^IN5 zJ4f(3Y4FG}iFrz6<)~EaT?y)&K&O$-=r*uH6y(-!O%dOX)nysCfilB@T{wSH+uw!& zD<}e9L*|lbJ(=>k@)gM}txN6bQ08x6m;BtEq)LmjaOS+!kd1u=nb50yRUp=F{XVwh z7AGT)&F&3SSy`Ni(SV~nhLefh3GTZmaTqS@DjAZiqpYi5kWlA|wcH1LFdku7PG`AM z26B9SBpHBt6w!x^E3Ik`4sc3R!clyJvdlCg*vySXz64!ZKB+*Tm14TG0ItV&|9fjjK#=3fa&5DxY>{@ll(OW0`s*v6d90~iaiLAZ*XhU(mE22@4d9i4|RGBvHeZJn1fTz3Y~ zZtg7R&C)420UpqQWO^}YLKx{$%zjpk!>VHM6we&=#6#x%k3X^@O?<~)%$j0MlrdJI zLr%jS4y1EX5y_X}fdjm9ZT|lQU_Tw}phfhnh?ziukszds2spk5zba0uqS1~9zm$v~ zzWA6tJRTkok3ab1<%K|A+zqXu^0X_cO!jtD{xdD(ah0PRC~L*Bnl^<}w_Yh77gmFJ(T$X8$8lw&wGue7@IiE>`r zL0^-0yq7unWz2ftxN}n~NV2tUATlDWU_748!T!i-P!UM-*!_?Gmw5I)2uxX)H@55} zJ_~m4;=UP-6!;pn2HH}dqVPrddzE@kHLDnmviz%@PXTz#>R4_gfWN^r7#-RdV z3J`?^!-lFu8Fh2Z14t_X1&4#lOX^F}pD}TQJ*5*)x`aml zg(FrFeg;e$|1LGK7#x!^_8`k@!i@6dJ;AEq3dD+<*i6a~#ehds0zjy&HT59_^Gw<7 z#Z@rk-rkiA2nlmMb?+!0U$pwf;@lVVt&nFnbAK}pqT zifhB4_&9F5A$p=x94+|oj+@fPQaT@}FkJ^@8K7o5~kguxD$q@j>6oBze zHc(zFakVLF5+1ZeBIeqV%t?#|fqlxkz-|*6rff@G_s+4- zJ63y;Nt%KE1D=Uk*p#wT{)KBzyC71y++o*OPfDeNvPE|fca?oe0d*Q!uH7W|yks_q zy{4JaQ_yhNo4+I1KV}CK#~i7Q;0R(2v&g=jUP0#OxGJ5y z`*N?}mQAa1v;-$S4M&gJiZPx;hRz>Aq-}iPCJc85uPxGuHM5e(@1DySWjB2cCVh*=C=%$d852eF2>d4OF9jV>9 zE-eNSO=M9?DaPlwurU=s`u%c@jMbUYpRNh@6h*-oIxTk^by>jtqVXG&zKi+r!lyqc z=N@}PuD$(^bg_}rC^`)GNPETa!w#HoWS&Bb`PQnkk1^ia*_Gp3QwA`+C5-*^n19tb zzYR~LAWxT_4{dmA9nf}LhCIfl6ZlnQZ+3Yr`j)M6~unuRLETOc`-m^m=H;&JK*Mb}Z3}LJL%a<=J z%RPH1X59%~vE-0RK9)sh;g4{v*g-0=BG!5A z(*z1?*xy(_a`Dndc?%#`8`tvarOWc>ja_9Myxi`}8p~R!H`%JoTB@w9v3tnG-`?Lx zVs5DAFbwd_{^Hm!jOKYz&u2hgAbchc|6u@sh~+~JKp4yuU}69__Dw0LYF6Pq9R{_@ zga%_Q2P6}o$a98}f{4wa$)b z@FnYRLzx9>jL##NE+}(`<%)HRyiYnvn)yZ6{n_=?@`GRcqMX@SL$GZ$zKlS-@rUhf zoXlA*b+w6TQ`umA?TKES1yjj}@~i-5R2DcXS+faiSGzxk%6^I@LtLxD6eW}=`6){^ znn(i3w3)!9+*lWeJ7X{8#99g`%q(+OcV_+2PtpnwnU?=*qi6t2S?74f$gB*t^B_NSaM0Cilx!J3eBB65(>o6US_}xZB-x|^_92a!2tW7X zf0l|#$>fsC)G@kOW7Tg;0jwxxnpis-fVN~g4YBt6^4yav(z^#xdAovtXXL_Z{C>~T za=vffJ(Mig%lCfzl>F+~0ZMcd3Yf6mu3I;qL7T0iez!-JBrgfKeXKx7KIzC?*LPsE zvT}$7c>f5#@d(!nAZqWZDWyV5o;8qx3 z8*yJOWQB$4CP)C$86qmhy(VGb+x?CVu+9_n3B;Hf3#{uQ0Y`7FfH7zA0030dXF2#l z6AYXnUDosgWK85l7FXr~>{qosJ0H*L#Gy{^nA%ne2XQ0fv7oIC#1TvGRCoiR5F1=^ z{)lnC$!^mUUo!hb$H>UwIrR~5G;v?W`6TA(K*9A9fUgSnAeNBQO3*g4T$~^h*-Tt( z1;iOK_<(K3G(*F3Ww{>%sZPC*YaDAQ#3j71-WkDO_4WEVug7e_<vYsYfr0--qqR{x$aS{E?WU{VpKpPL$H@t*Kg!_qXm#uUo@+=Jnpw zshrw455rhT{FTiZATbx8m&*R3Xq2w@%vTIR6K!5xnTatk(0g`mN7NBEh%ENAUaz9# z#TM5nmA=MzMYozi4{+dtZkH8 zu$h$y4^!4BCj!(7jag*s9L`*iSat}FLtsB2WmM$EIm9^1fzid`p&d)Y$l)}XG$z$r zY~4Dp`TG5Bx&GC!%JXpA>M&eY7^U+|MeUftiMasdH^4$G=jVVvkL1efHMw?tPZoB z>Ku2C@m0|#S5fv3HxOh+17sV07^QBzDcwu~K$NQ+->us_G7m@aQDlf$9-WtiqoG>I z^2(~bac>J7R!8y+MR`V=+R;ZHr9mh+fYa>z*hCYa{KSQ{{LI_CK+qHN0x}&=c|o51 z#N#rzu_E8TQI}^QTUDUXgAva?d08GkcSi31(|;-V@jOY3)h-xB{mHCyxCsxCEeIq_ z3MkuHXVVfOL*lf1+F{Vg`-gO_k|8b`A6qU+@!SFo zt*f={onBXV8~c(7Q}W8s{7qShW4pd|N*y21w3C$e)uJrtvhuzkkT+ud zK`;f|4yntlc0s`PYxqauJeE+}k z$CWkkg)e+w{_Fqxzm?bDc@4pSRW1O0x_J2!Ie+%7(3|V@9Ds0#2qe-PVDR3|{fsow zGGIuck_*goXR>*1S^nb3J}x(|UX{{ZQ9k*R%kuNT`Id?rzXnj}Q-!>&QCF+)tCm$A zNx1z6l7T}5@~~5&>HcL}p;OC*J|4?p$Tna=!~09YckytZCidKc{(fjmvEUaFSnIRP zmfnTwGTH2owM>gr&+Jx3J)Z%_r-bt?FD|Q~^-;Yk)z(0&?Y^?bsbw=(Sy0$gs!S=N*!406(I;I%Ei)=A+x0Ej z6D8Ke-ywiSkcQnp&03y`RKoWbYM*`W!QVZ2M9)fpwzko#;?015&g9vV?J^;`MWsv5 zjDKlOtj1~tBne;;=(5BBO8T%v8v%+?%MxAfC}-wmT+5=U$yUgu6fC9xn+AZS4V5rQ z{V;|(+Eu`!KQ?0CJRi%$jvGjZr+V=3;m@b?DuDf~-@LC~vDZpTW&Q|&ol+hN`mrZ> zc3QGNSCFf>TL5v8JWm)Q_);ORWpbWJ*%N@eh@YrOSI%c)lLUafkG0iSjih#cB-J|O zp|NyRSTnf60N_KV%{U`ameUyLCQFgukxF4LWs(YZvYMuazrD;*iW%4(B=%`Ea+y$> zKbdky%a@l*IoK>0-#O4qihOEdbe0h9Qw*Ks&E`lPYnD0&_|h)cd>AHF_}k0GwA*@u z_8RxngPm~6wxX~*)(o}vM!0TDycpeFJPY{ly@A;SNO&rh(|XU{V5nVN30#d?nc&2< zG`8OlRI}HMC3Rl3asLS?f!MYy5rnJ^Oh?r2hIroqaj%QmHAx*TpzBJifDIa}P<*IW zAWWDSSiT4lt=SpM;$i{!4Eu=p^H1oQvS{|=(De_S*6g;GZ5oTgwjo9uCk#V0nPj}w zM?C7{`S-PinsFL$JAt1w*rymvW&oBonr+<|UBq< zS!L!?lZ?zWx)tp77e}nyYBn%GnRw|aXhdOpE&^()ok0SIpBwUht$kcqN-K3#O#Zkw zX(XjhqJptyr~)8Ga)O?kQG8tdu4J)z#<7+p2LKZU#;#P>R-t16 zHE+E2maHrLYCLo4G3sQ(a3P)XBbdY70Hrvupm63@Lm?z z7+|p{-~i_e$jaq3Bf*Shm@dO9#NzUMl3m)sf`TJB=qa!gbm{=92I_eA;z`Yr^&o!Wq7;IcKnU`YF)2wPh>Mb?K_yn-IB;Xh> zVy;z=mgFs*=iG7?S=F`y69Y$`-UhPZ$1Rp|j-*67FXmVgAJ1ZbBypejZym~&%gZvL z4YLlH6O|5%5ygD<45Wlj@=~)7qkb&+-`SFHy_J?u zX$9v$E7=XqzlAaagrdCPM_?Hm<_ISatz$v*Fo=M1TUO{flg&jlu@A-DKlI0szwuAx zljRNhJNs|R!{ftqG%0<8eI;NEb{?TAk&{TD#R?rq!IlP(u3-*YGQ|6S%nGcVzfZEe z#Rl(@4%RGNWGas^Wr7E`e2Y$U5P^EQ(L{p!EC?!+Nl5{)&~j-Nr1m6*J&_=iGKGRE zTZ?1c?p8I}T$-QP03g!1A#g=N$$(tgw*g|ckyXBb=a#(r=IgSJjB*MN{~!In&tbn# zNf-P1lh1!tKJ}?jVZTdjph19ofsJsMkv&Sa83hqCyqV7ESK8{bT*-|~HwT(0CTim*SL!N%_1-ZFZlbiSU*$$2?9P8 zN3PUcT0Y32H;sf&oMl!xC&8s20+ufBb1({w7ME{?cSnk|ddeu^Sg}Nk;8ffKYN6Fl zW$7iae{30tS%QvC8Yzp)N8&TDnfn^Xr3L?o46W{PY*Jixjo z?8WSI*zR^UfIB*_Xh6&|A)cd(^HHwh%9W>Nd+WXwmgeQ+`LlS=Z_C?ny)7TP@}xX_ z`Me5vPndoBLpYg_Qy?i~Mox7!qb3ZK6)>68&V&VIf-l3QjP#dgeRa-9N_7|pf`w;e zcKruBsg3UzP7~A-k19%J8=pRE2xOTdj!gb-?t}Itm;mKwts3vgnQ4a|0YfS-9#{eV znfp?9<%xv&dmjX^DtI1R0u_s$3|Q1Yyf=_#Ovk&s5k7b@;AP;eZ2JiGk_Sy=G)e}z zCacG_U9u;i2xUSN;JjtGJoRlUCXQ#rK#75M8h){Av|;X%>B(DiG3Pq%p$6fk5>elW zU>X^Xe5v1s?W5kTo6vPR0{GM$c2)N(kEC`7Ys~@f(#JE5$8$gm%2!Ib+HPTiMrVHoh0P$y3%lM$xQmv@LFacZ8();KhGxkdXd`W7O--(NshOtDD zU_t;u#ABH@_A-i-uL3Mjxdw1(-l9@aDfYWUxs_Ep0@Q{z$dS>H~Jkb9Bro;+()32Z+xM z1CL;yCtbXk>h`jONq@@g3{>EK)Q_u96hChO zv`9jT;5^H*N1B`oaecgx43Z+8XZ5zPwsSn@GxarrK@tZm3`5rdtJEX(+(6eyQia*$ zO77rZNfsGP-Pt{JeqmABS?nsvV2_tsx9I}HVM~~&=cpd~0@7=%8qH)a4 zxMYw-Y3|o?ZE1{sS6Nt5^9VKsp|%=h5w0DIvbzd8_BHuJIh=fYPLm^t$Ge6>=epCX z8xhM;^_0;%;rifwgYiHRz*5Sp>lz@)buI8Tv%!QjhJWJh&GMyY9l#(;j@Ybb zI71DV6B!lb#D*s_nzNfrw7pGg!zY`80WYHWhc@8#?WQcQGn2UxWpkuqKECy}ufYg) zB!@+saT@@026C|7m3g4+nNb(UF)15Kte%XIh0~QV33RuRmMSLS5i*b`TC$6)YB-0;w04g6 z#SO{Z?3>o4I9JDGn^ZVpG5{#WP7Mh;t~LO=0Evb{cVIb|7nT4*;j;i=@+@nMb;Zx6 zbYoaOU6e1Be0luJqf$JzDv~S7K{JpTHK95UIVDx4;k)C3QcdYBbg^-E0EE5z?W^jn ztzeT_PZeY%g-qkA%gDOqWz<7v^2Qx;oBPUkA|ooCKa1z}b;%Zx@t7;i#uKL{Rh-v_ zPe&qZ*KQmblc@^<0?mKo1pqTE^7gNOU264)_;`*7$Z8b)n8fg>i}%gpeM4+)4l+Y5 z82-WZF(t`nS2lm~U&!Spyve-cu>l*w z(!)=dPRmBRi1*#s_eG!m+k0>Qu1XUh9{=kfT(>b>i>v{z1<@lt7YQTLa?AAgLmO{R zyA;2l$85sQ9L_X)ocItj1+7FT%#A33jDV}?Fsv7w2&Awy0WAO$1vtE_rNI)b(8wbY zxKT0b8Ro`BPYmZN7fZHOBdxD9ASLib@XF{>)s>xe>&Dyi)!+Q8YJm_4`OGIiE-yU& zs2n3H^_eezuRQYDP_=k&>Xn=B@oN{Cos%&xat){?SB#A-azC$zT2jr=_u54e`WXy)#; zvuV@-YE}e3VpB$4M2&_n%SV4}1{UZ3{@(ti>!7X+_aqC`k(ovg(Q7m7IQq`-bfhx? zsXJqnteb#)=DMSfk>;GUV@R76=-8^LzP*wNY&YZJ>F+1yph&vT&&4(H@AXDH&f`&5 zK_RkV`n2ION10XZY|ReXWCW32MetaGnGwal``Q(=kfzR%2k>g7;?`UP`S~n-W!SmY zShf!xWlga|I7`t6?8t`q`v8CH0L#vwDN7rm2ulJpMbC8P1h|uP3v;qj}p*An8nN-Y5E3c4KtHslyst2uC-fFnAyXYG0cHuBIh~flOt!oXIC5 z=Tft3VmB=@bmDhz+>n*_Ed>aCpwTfHyz>CAKKkToWGX8Fnp`Pjf-<4g>Qv?KPE}sG zd{IhpMkH5|>u=nXz2mOZ$zx(kd$fzs_mwW6hEX44kz;SbV#gv6sndYX0uFBiKw1%q zbqg8VI1M5kx_$`Y2^R0%d_j&|ZK*rEQh|f@M?U%|z{n7803^FF#7nj`@ z@obs^XL@869aiLGzNk)pzA&fR)L6MFxhGCZ98Rt}RxatRA`*48ajkRWI98M&8|~!_ zvW~y2*KWu`5TnTkaAi<^7sj$mHkk_Sxmw5E#AoBql5h*^xYXYYGz->c?K3tyQiE4u zqy_+szH!f!>-XF8i$hRizM<~8XKZ#%4RyfP;QOV((_@Q$SCtMM_g>2 zLv|yH>1JO!uF0*9Enaa!{=v;1`CGWI z|K#jb@~O+u$=+LU$GO zL;LVJdHlt5AJ;##2Q{*O?2UgqDHr_n8_%66J^YE)Cls{$FYkUu{`~3Z0A8gg=lTmb ze@*_{*30tn_<$TneA2Kw_-_khIg_$GTe4&}X)!Xf?iAqq035UBJ)v!^!ebJcPBN)c z$&PcPYx47uXS&%X&;MIcrcJ_*4qAD_Q*{i;0m)Kgl<#rN@gcwL+aO$4cb z;?Mqjcf{$d*{$E{PJ{-h`DsU594fD(lgi(ve)t0_8oZ#*Sr^MQ8g? z2lcK9)*3Kv>SsiN)vWD!Z#(kdKRak1@fCl0Z3Yv2cu-U;=msXUK1Jnu0W&rwFR2!>h*=n?<*}^*O z0J!e-WnqCG3I|A#2MWLum~Ic)FL#V}?DXDw9YGiv!t3u-{?K0(;Hwj~piiTYM7v z1ndaQKoEM7X1~4PK56&0nM|O`h8V%g>Bj5KT=(Q$5=m3o_QzaI^$N`6P#RuS>Oj2D7S3vR zh#9RAi=^$xWG<0aha|v)s=)xUiyaqCl45rKu4$1Br>2kuY6}oy*c}-ZHoGjlM^$<8 zB3m`5<&l-L+}f^4a-k#z%!Vq!g`L`=ytDO9DLAL4c={PB&m>LE22KVI3<3s!}l9`BJ@PUT)!^ct)~2wUq6&*zUK$z?O*GrklO(c}b%=YGYh)NqzSf7{s*Ps`n-3jpf2pTFxhG znz0(OMYHeeyruSpvU%L`q%lEnkdr+OZ-~nzBW@m`(x`Y*&aYmUN9I=~d+AAh@4j4E z7|WAcAK#IYzx;Mg1Cf90BLJYrcV!sEJwN^fvi9s}C4iypAS=AzX-Vq-4Jp7#2FNJC za%Ue-?ofJgW}nW*MFA9Eo74KvD4&RSLILt&=+K*An*I3PK0AH$#EFz zX_!{w*y40EVtrM9v$mx`*7q-7)XzQyus%445fF}86~Q#f6`3goGHj*U)vBy- z=Yzq(ir65L9~8a*Zg#l-Bq#HA&b!_hX*oq8)a0-%6~_u=^Y^oCC-XbUzI9q|KsFL} zXILi4pqh-N?faYZ$~V6$_wU^UAkv02-I6(Ega6GR{b3{pQt~~2^0I<75fDX& z6IojXh)hRCcfx>**j>>zt5B`g*P`#m^1cjwA~L6{m1C(KHROpWu_rehdJck6WRp=> zB%8~^cUh7@_aFT4rP2CJ^3AvIsi-`=NKwOScXv2vM%+uEhtNAi%tuV^={DO<{b%Trkm zN22mOPbA_BhDN`}V9ut)onw7<0}i>$cCfOyHn$zf6o#H*Z&?OcsMQj-RMx&FoJlw< z*+~Y}{U|5RgULx%+4IHglvf7;>n7o%@n}Kv(Q*H9V z!S_<%hI7-z8_tXjO89^skO$WMyU+Jql@3M+#rp%>)L}A=PSl%l7Q_;h9I&?3bxm?! zLAt1E22bK!@SPn6E$~NADxFDbV*r+>`Z2>;Aqbh$GD1ho!#M8B#H7!SQ^(++4hg{W z{2tj%hkxtaT2a-g}Grybz}p4 zX23!QTuU3V1-lROi41Xm>Xmna_RP-%JOZHIj*GI>wCNYScMcuZtr}pQQ&#k!coq<+ zKi|PK9QjP9z^0A@?UYWCiwWug*THe4`5Fv5u%APm3uDfv0{{uxVX;HXmlLf4R})2C zD@@)ikdD=TaImAD8D;cEbvQ+cyTP>7z*RoD?SXanF{Fl&T~APh+p_Sf-8S_#!*H_6CGxRGCEtS*~% zaShN`up~K%eee?SA36Zb_oub*Qwp&&!*UXtGVD)+Q(^Q=naM&*#J-wJ5k}NlQ$ruV zt9!Qo{()|V=JlBj3ny+6Z9miRIq?~L4X({RnbZ1G0>YgF+C2|2pxuj0sh9x*3rB_J zD0=yhw2*P3mQbbFmIfS(J8%~2othlbdBmir{AOV$qX~HyT2!QcPnzav?i{$&J68lZf=4ZO+N&hohWJMsj#>rZmW*W zTSY3{_oR?3$ja)nY~J3+y%Yg9rDf~zj-0#vC>Cj58bGJJLl`zVhhcXM1{PZuK#(@F zfSJWpDqL9TugMYss=x(;4@5rRIL7@1K-pusmpMt}vmVYJu)ch5LH3Z@_~ol#k@WQt z&hdd{Y5d}^$pD+$4_!VlSqhjU%aQBv$U8vk zKYHn`c7b*(@*Vo6KI`Iy``pN@;d9@#JMmpYF=RxU0-4wx1mUaJ#wPkRUmd zODl1CoGc`6R#a%DHi=PD6v-~h!lesx?M^5^`^sxNw%-R}=#x)BVx6Fo&Og_(-a;FU zCh;^X8VjOYi`!D>39f+bc28Y+qgzxTNt&54x_>X%9RGH$>2IRiyMjo zyCMtZzW)L6!{a+2WK!|?J9}@-m+M>l^PBA>`DFRDGOk!U7`^^p2TKMCV42Sy0>Jv; zYAIn=A)Sri|$%$TeF&==(4E5O$>jPyT@!#|rSQ3{(@EI_WOy-nf!lzD+EWT&+fdyS0*OYe}piC@#%RDEey*piyvmlh| zS{PaY)|4qmaf`VqnIyeKW!rfcKnpl1bEtedazvZ zBne|>JU#4gucq$Bk1?=fR!ss(H$uR1>(X<0JCtY)#6VNoX)pD7k& zngDmi=(y=~bB*vgW-8(uQ6D`53{$)qHt_8NR?f+8ze_iL+Z`NH$7a__K*B&{p2-q@2^kdRX=d07BR zd(;Gw1RyTO5??Wi*}HhaR_=ltm7{oN+so4}Z4aGkNC^n3UW;#tO}>{7p600_h6 z1A%$W>zI>3d;)uxq+YK9^9tD%?hWVg45)jId!RiVY2ydX6`X@*sMJ&@xXHP~N~J!6 z2rp!;lhReh(rKRp<^b!GDNk+7kY$NjYh>h+u{6MVWYYLuETz>j1kV(-@&S6`o>ezf zJ8$~hB!CROxpD^IJvI^|IRB8><;5m|GGiexG_gUu3*af?;M%%+Jxthh-{g380a_95 z?chCJE|gjcM<%f_M!dd(ee>?U+tL{|u_qx0Zge$KG4vfR%^c$X69BSwpTmAjjp$e! zF|@89j2E5@MSEI+GLl54^{b>E_@@ zLXP@-^Zo70A&g94t{wFiVc*{dm~`nhKoX$q*a-6Ff)w&`X=9OZ-`|t2Ka^MRybdEf zFW2{)a9T1_gcIY8`;vy!RxV}b%*Kj*^>$Mh09de7pfFp32@UK(E|lWP6u{680sb_B zWDhpwv3N-?mQB}%$-O$JgpzGWnT=!VABFG|G^DKx4DDF*bMsO~#&SID$m*FD*{L3> zK?sKco^oXvu%s-kF3F&sl~|z+;3F+DcD$j61K#Jb1ONuXL(m6=M3Mlj!b(k2rIPg6 zZ6`3992y(aDwCtW8uvUhE$(nvfs7NxvFJq!SEsePezS!ymR%c+<=iVVkvHZ%nzA0yONlT-*YldG404fP%c)r_^Lu5?OEtl}D zTB_gWIgZWFi3--zxgRia!Lw!Ap3f}Ecqs4pVVC%Xt)coXYzgehq(!zkk=Q#EE|#$+ zhNboJ_~0H_@R748$AH5PXWmKtpKc9kgD+k6uf+Ri0US(E@i}2U@$ck z^oEv!GD(wJ7PeSN`TahOuVRAT83ay$7g!-z2Ht!{(`OS_Mday3`ao0vBht*7JtD@F z>IB)W{Nx&}9U}-~_D54z*91VpGO=E-BX7U)irl?@TXwg15E%8P0^o{zS`}pNpMK)9 z{OBL~KH0eZv|M`pirxnuc%F}-Q&I)llauc;-3v__BbhuAm=#@j6twcY`TSbgQ>ckU z&7}bxdX_6KudFCo#WCt3pkq+WpB3a{&;sW?md#0VX_o3d62U{LFG&^6ink#=Ka$&jxMDbIoeDqion7NjI&3)der zpd?EOvhe>@uMB}J!KnuIt#IFt=jrDgy*>a#_(BRi8sK1TOZT*+8-TCvY8{D2qxVHY z`SxK&pH(#V(it;$!_HU(EehE%@c&m|`Kpon!1*?}x0TJ(#{AF{8UR^GNMK5MS%YDw zxm@dTt9PkdNHGO(G~m=uj4}m?oTyWu5w(vx`vtmYO?hAtfvUDl&j3f(a}P|3Wt4-~ z4uF9Hs6*3)6raPMKJt)vc0nBKWS)*Yz|xXMiks z0&FpX$6u&;vd;U!1lvwvZ`-W(d-v{{_{9Q03f{~DP!^b*#3m2891nt54}w(h0>B

      P6euA|c&csQsd%}<6KzcF5u;Zl>%x(iLV97F8x3Smk zur{L5JD-WG3?2$>^E{kaoM(YLTbLI?%!FXngu-<+0jk7l!xQHDv7`Cfm9#A7kh)*a z$ziRIHz$QvQX2FV^aWDWs&`~s2HL5*Ug^PR!~sfSDGhwpt0G`S zMkWE2J}YRP7~(yastqw`vXbnxPpPl^cZ+j583G*Y!1tg;$Z8yOogMcy6N5N_BH|raHNV_g4}SQ*^tt8m?xeSRo@u@qgYCty$ILX@0+s65%$JFL47gZ*_o(N zfqejZ$_^!XJd_TAPL>NMlk6r)_Ha>IRNN=XG30#_2-7Ak?E%2THUQHMz{8}Bx??TR zuUD%IIHmxUQmmc;61@CnMqf28IWT~ke#(BqgBwODBGb%BXjvPE z$z<4F>T5_a*^pG^5et81eobWWhAaY9n&-p=kkd?;Wp(Y69DL&|+OcPK?krH=rldTe z>jhVh+U-MtPkt8Jyp(3P7*wxgv7B26u#w@;T#+TG0fU^7qZS;!J{B&FM=G9@U)%QO z7@4-uK5{`8PA$patsBxDXXR`nIROTFux6H9Pcoa=P7WiMD`sFgfkdZ^^U}QYhLqsA zwUNoVzjal5Rlvd@5jYpLxKLmId!q~Dzuh*#O2iTniM%0%ZmWA z*kw5lU*=f)ZbmZslFTC$Lj5Op8KSfF_8T{)IkzhD#nZSh7*swAIwx}%OE7+OLOjO!WyTR>=HNa+x4K)BB6Xo`yXR7#kYr)EJvzg~jif1BLcb4!an`SYN*^MQ4t>Y80Ie*b0|vT#WOWnqz^ywtFm( z%c8`ZW2rp4B*Q0Plz-=$&&t8heHp`Hk1v&_zi>vj>VN@}JxXK>GHz65Ts@Heyx{08?>#y^ zlH*EME?hXLLGAs!`|{{xk6UI|AJ^PQ<~lp+AV}az^^;hp!_q`12$whHkN@}|k^la$ z|Fl#HVh#FwE#>(|WcqXJt7QRpt*x!7=snNJbF-|Ffi1y2zQ%b)kc-+O|G;{Q)~xz-BXfNOsCd6x!t0sxJmqvbGYw+IfSTsR zA~RC*lk-R8VD9(b%@yobPu9w8+3|zN?7h9$p{x)D*g7BC9h1R7n;nj36#|2aU5OZ@ zVnZv(CJt1je&!k(Sabd*)DH9MyI4c6GLBft5?ZiQ*;I;=_{y4z#SL&a()mSf0q-H8 z>zM1H{@jR3?j+(9f?S~~;o@gDcRLD*4PE{_uInR~G`doyTwKc!{Sdx-EGySPVD|uKbpWtaSJ@?Vr-L{O z$kbAP1!Fv?Li!DWCj{&eLEz31<2Ws;^+o{qJsDB$9Wm;d$Qyv50sxckgCp%+%5Jfo zlVhF2h*2nXjKu$NggG>ZEry-y4}AcLZK21k8gv+^9EB7yAsFNNY_=svqC=Y_kQ4%& z>89fnr%?aEH2N6#0?8$O1@c+8orL}5_m9X<#hy+;luTLeM6A?62cQtFgrP~%`)(G0Z_$re+M zW7zg?TftL5U(o$v0Kl}_tV;@?B^#>``^&wCYcGx%pGIsHlEJKtO*=I+DKQ!v{ll1Q z$~`P0{MSCl(Z(P%wd!_reOH92iJci>X|@Yk1a!$%BO-DH-6&&eQZ^IgYtpf%7CW5D ze1_r7W@!V~NUzzon~Kb^w<1x-=uc$%Nf&?lwKt>(WckeLOS0J7mt5~yzPWWESF1hw z+-EY5-$|t5MjY?6tm*ByHch^LU&irl;`C~ zp2|tT>&Pa~f3splLQ4R@nk|4=Lr=>2xSW0BoV@e;8%AkWx4XL7dhCKjZ%(9eHF>TM> zs2{5qM*CV{&OH5`j8ZxA8vwhy$MPtyF;-aAx?Q|r+PcyJH;$$I_}2Ey;VkK&6op#76O}hsSD6@<}qg5|X-pU&@Q~xRtS7Lk6I*c3O6^SrsWP$`S<_ z{OzMUvNqUAa#?Lp8^F97yO!?E%;Q_1YgA~L0P@CQfx@>b20r%Q{HCriw_a)#b% z=Ac3$6#E;D6$s?~yNT<)Ih+HSS(5XyfqeNJ-$2I2lQRG?gKi0%5ld4={>>{TX*dO0 zU&C3jvHC#aFK=9srQ?nav55rXoU9<@K|t~_QIKBNk=@N5WQ>Ng)y3vC&Pg4}Vq5Ae_;&g*Vbi@wb;sjz>Dl==^8WS zXs3)wlZK9jBj*4lcH``H9L{vGdH;^6P(VA%OK2Gyp#`Xd30UpeZ1BXHoB^~S9)Ix1 zzj*dX^=}HVM@*?w%rGW4d*{s%O@-L2WPCiTK6^}PsNAmFaa3315`=$-N z*u6ex9kUpc8-Yy@7~sT+7BkSCB%0pmV+vNiS0HNjI%n7wCmG`>gVsn_XO?9Zoihsd zqu(11B9mYsU_t<>icD@70M+)^E&{N=+`f4g+1-j95%lQ~ZSWc>bAc`0Pp!<$PyX3I zEg$>*mn26}V=z$hTY?>Q%K1mNe4LY=4OO(9nk~vkNKCY^`1`1Au-$IkGQxrG6Q?&e z;KT#KIj+k2OPBR^0v8Nu7`(6q(6F!oz8xJYAjNyhVZUeT#pS1-mlvOVS-$+ux0KP9 z#CfCg*LlD{=D5Hd|fWTrzn$!s_Q%b=TcKxGv)mTf} zd$_k$f|@U)tcEs%7>?sH1%45%3@9yudu}0sY7I@cUpsPYz+&b_mW(X~M@{%5fd!6S zizY?+qba+`?rGY1*EByMK*Lg&z6Bb?7JR-;DD(4kQYS->YO- z^Qij3-n3pHk4RwM0I){HJq)6Cc5N+C??-^EB)ZtJp%iAJY zA`iMj54aX5?1MAC_u1b?zn=xUemnM+-ZM4XaFgjYK+&OZm{5qqM>?OP&qZF+^crSC zL|xY=4QNt){2eM<(v#n6aN88GN+o zTtl4miI{mmrzP2mWFw9NuvRcX2@-K0`9p$6fp!q37FIr&lv=$fg#;4q`6T8qu60b{ zLZw^2V-5F7OeI*&U5om4=a@J-T`x9TdUpV&ol zq--{VtE7q%eq-!P5{8elO#q10QaP?^fU<02!E$VZPsEr>pa@};3Ynw|^p65hflH1% z<$;uh5;sgxUs2Wo34oZ+SK1lJ`WKF6Idi^i2Sx&0TIMbah~@J+O{BEiP2CR_Fk+Y6 z6ca6N1!vuu0k>-yuROJ(ahh^&MYgwh0FVN*#T*%r9gVvj3fgmD#s0@ggkTu$Yk97$ zdseQHml0xiUH}0ylkjp?)`d+Em~c|osOxI!JMFS2xIPF8ya$dCu?Cjdy7wtsG>iJH z-3(6(wA$ZJ{*Lygh;$XPx5S>&lna?1Bl^~ewLjS$^b%%w51CXCI+MTcM(Iqm6gF34 zt{z`T!S0>Cefjo3`P*`Np&+}&xyN0p0G+C~Ie}`jbK`9}x3VU?`-ifB_p0mwREPy> zrIRjWf?rw7XeMVLS&IO4NuLBha5Ym7Vzk6>- zig6=mclz`hxp8e%viVh6S)Ipw0J0V5ls-u|R5F>77#423f$YYhip>#@BAh(QlvI$< zEltZGLc_ndV`d*hqbgtc&TKG!jXTool$}F zEK&{EYrZU(11(1b&O+L5bOJfj|jm4o9 zgSw2D(z4!*Yso>}rM?Cn_R>@0=kQG7Fn#{nmt=2epxKi#0IUQ><~?kPDT?%A^IR%P z>u8MMw~#$Pguw*h<~0ELCFJ>~RY{eK(&AHqgR!-DD4n~v^mlR5qGjdm*w1FMW22t*s=-titg9FCo;< zf-EhV8XFT_ghmg;jrdpu7{#$}nqi@R5CY);zdbPY)Uo=hOP^O!bqcIg(`vKdm~ZE!a$or*Gt;nSC^%PN2>*%hvp08Zdhw z01EwV02-dmyiHy+4Q9gkWLQLikm+`2eox&G0y zM!hcAuit>99mwv^mfXE{NB4D>ClFL33yEM3gSj38oki@o|Ng)Ir{t60`-3q5NRVJ` zBQ{k&pI5D`=(-|+A=0?w-@HElj%=predceOXkHP-Y9Q&gxU{D1t9zUGWaHdf9Uc{y zM=%gw7fT2E8Gd)MSk~A0y)O2k75E@5i~7W;KP7Kny(LFA_&G<%0NA!w%V}|c5$-|S zvaTu!GP<@Cp{M#iivYMdR;^}3wzjra?D)IB@Lh8A`kQhJz}ouCg1mDJAQqw>(9|&9;?Ve#|v6ENK)%nUY8fMtZs^WN& zZPn`bb)HmlEgc3a1o2{?vf{}c2sLOjJ5(Lu6$5AjVFdtM3v(r13mwb@K1-Imu`5@r z(^t{?$Zd|moY9PruAmwcinT^Vs*R@PN+tM1BlV~WHVlV7_@+llh_oYnx{_w094iLL;WmEtm5uS%fwa}ld@CoVb8#N z_eMGgN()Kpws|84oM8E{J02o2U&JjrGQgarN(e!i4E$tjAh9V`$Tghsm1&dD$FyS~ zs|}Lbgo!%rs060iE0Kl5$ z9>MqvAQQ}<9QR$RHvy0UOG%7l3MBY_*pMt)qj--qkX|@~T?Z(J`J8s*Du*&4Q!~c? z3M13K5HakK;^z_??JC%LHXdV)FhC-~jU+1rQPxoxYcGSb>moiG_Pc5i(glF_`Gm53 z`?!YAaIA5K&v9~8Ee(^@#rO;mFIyHD_jlU-z%R`Eu?fQc* z?yn=~S1uSZYZNHEjdM*wNp_{gJ&#$-7zD~YEo_(u`nzeX5h4wX_9x< zsEbS)H7aU|EEycEU;0~rS)NICB#X&*y&{q<1HsSCNg>yeO2?7?`TgXyw z?pNi}(`zv5^Kx(RK$hl~43UGbbU8cAuagjQG;2B}pumC64jj1j2n2KvIfb@QP_*WEGhQ;5EiVKltgN z!T03lP7B`=H02N*ZfY$r-x%a&eXE9R<{nIxzbo0|iY#Q~vYkX$6^`cJ+&a$Lmc!Pb zG!FM=v0ITj0EVa1WBJJWMRA{8QlQhRey!U^9br9s-2yVw@#|aX>bt)fmZY4$r@s zkyI^|GQcA`t$ZH0cW=lbJ%>5d!kES625_cZUwunP00yx`YKcRoYBGp@WVGIT^R|53 zzb)Pme?cBAWmII+sCkCwQTnzmHk}U6C%aC~AJg)fj$u5Wm5Yy@gA+59!#fA^8`X~d zu^*E6^%ze8w#YjZiGtUZ;5IzL3-ml{?-1t@bJ6C>Kfh+#u!ES>; zb?2)Sy(;QkQG}hH1OK0oeQEMpf>%HO#y^pV$A|w=21YOi$!Q;zJtD?|^=tsF3?wm9 z1-|L6t>xP9_YnkBvE*51$AiFDXhAn)dc#Q)&!6Z9%>=8CsI4bBA9WUtfFu50!+yAb zu&-<;3f3+!&B^iME*$;3?CN;!e?VK3W!Hh&iHPUj_bxMkno3u`x~sa{ z0M*@Sbh8^k6CgnV1VMlR2pWI`iZj&Ah@7=JT1(QJq0C64W<+r)krYRZ-~c4((C}z) z(YCxvZ@+iX+c4VuoEz`G%&G>!MG;lKRMDN4`QLvpUc`-i&pl_KefHTy(xPF(A6Y{9 zo;DIjWLX`XpOOFk=YLwB{(&FS0I$)gJ5VZ*ps{8eAfu69JHL-$Qwmm1mk&;}#L_>! zUNXLJ-nap0yQB{Og$r=halU4=EoaVOP_TjbJk+j!)ax2*a8oFh#vKjmz%!8XTp;3k zMR~`Q?~?~Fd`9Zud`+GF+qZ52Bx?X5Tb8qD&*}Hyxzo|WYGY$lzUO;BsP~Wwa zEibm(rYQCTQ6~1-pIAbafJ^_)&l`Bdfj zS1E{N>o~q=y{0TK)y+!o6-4L#Pu?dol?9jkwdtl=SNgrKLB+Jdd)fi<57NQsNq=Mt zWqdma0Y#v#F?_+mjR(hp4G1zC+z+Hs$s*1%HW&4@!q^yb%Ai%hGtp;HmgT__K*)Zi zQX&M?`8ayH0eoo6gkT*c17qakb4PgQJpfv@nSwm9Qj?k4vUD*2ck6r|VBTI=_lZnq zsO5soc+a2{Ni*EXx+){c=5uFfZWH0JmMh8_QkG9dy|2E;at$Q6OF1TTYXFz6`40u) zHxC+wV-PzHwQRD8_=!G!8vt@ph_I%aQpWkc0+JB}*FXtBj`C8P%PHVd&XnQfw3bV|}hBw|1Kvlh!E|o|zHt63TKkj2{!@eLRP-;K|ytS*ZcY zZ(%HpNWw1{0-bNWn?0O6FCJnt0%{9M39pY}I{|F*xkVcFV4W7EXma@ZhIBd7adtmD?P`(&f9D0J=O z?OX)YxVIG%ACB}_Z@&L?|M49t;%>yGdTn+dXt zM7@VV(YsA-7Fbvd$bhy1Mupp#r2%kY5m&sP52dqI(-Mj^Fkngalp&z0r&i!VzFlfFSV)d}k$H-NMBGP1J~vIOk7 zS18ZOt=l)0iob^}MQwIQ_O8Ax^F@*CS1(Huz+C``HaEL47Qs$j*`}7xCGmL7(}$?t zVe)WX$(zjHF`Wl|um=Rc#X9<;5628f8uw7%@swik0r(1X1?}EIgIh&Lc!pz1qfMGH z7IK9vADIOoH&Vmbet5Mg?_NemZgpP%#r0Ue{_0(18Yl*fjACg`u5?4G!)EN;rKOou49u0O6~)k%vguUI3Pteu#SC+X;PSIsW$;?QxsM$ zAdM^xb7fsK#-yU_*kEIz^WW)au}N2@lF#WJA?2FwhlOlW0C?0MOWG}U2>Ni;I|ofT zk1YV0`!Z;Dq=x__tOLxtdl{QsAg5r!s!3C@w_~i}ydWU?m&fyRc4t#&!jTGTrefyQ zv|whdu)Hp-`@2#cR@AX3i%LrXGl4^tJ!ACo`gM-khLeoJ%8?v><5l_X-~AGdbx-xM zGG|Z8n|-83Ip#q7dM~l0C4<_z+jS7)!!owkga`W8%V7Nf%fW7fAOF^`$TPDiiLDdBVmHB$FP@iK*nnI8ru@d z?c8&&UwHMm_3yU@-QPNg5ju>qqI-MR*pXBvR#E7THz^@>!6Y3?6;zJi{4S_GrkUdR zzixYGBIAmqG%?_Lt`n?`8`AJdgXV5`q=9k@T9K)w_l~_~Z+}}F^*w+woAS~Nuj=pF zdLEmJ+UC7|V_5DX<4SFM&M-+`aC zzNQPz6$m)C)awBu-}mp)Y_s*6-1B<_ui`0&mZuC0t_k|+NpfEqvnIyOhaH1X-UO_= zrzFt3_j|qMkH)yV|6n&vc6Q4ZGV1YlA?_5V1`biTj<+17&Ryk>cEC zl?CTzgk&@QeF6)OcBDewwC0@q>_Qs&R`I~@ehK#LxrKQJg3|7ti;F9WC5DnOW8Gan zlI=QTs44&i08zt!q5v${XA$#=jFoCFC!;zpqo0)yuC1Ku#s@~%hDN+Xz+ zE4R1hvGZ&4^3^Q><`_Tk5U~}2aeQ41-%|;CYLEBYiH=XM6sbPf0m}pNtZN0+@LZ9OsSiQ z--)<|pJ!~A<8#pl3D$xz3@IAYoN0Cu^q8e#0B z$dmFO*`>1E?#kl)q8uR+#iYW3jRM$+j7`*FW3)_^d^46WVomfqEn5@)aLnp{s~z8Q z09KZU-fikBlo5N03-D86QhyvTYHl@6)_9&w2t5uMamPKGOmFP>80A+pvG#EdM%{kE z=@@$kP^D#pY39Zovn^5(%Zapka^FNy*jF<3P1zeIa=qtC4U6-1IV&57b@}wINanHF zR;w^VM_nm~$Ep0t`}twY$h{tgOrm z?5SM2epfE-9LPIQt;q>EU;6{Lr7lSoKo7G^&uw+&W9uE6ug*(QnKc84qdHeMfjv4Q zosP_{9n&ri1Z)aw7g?5^jwk7& z8=HGl$dDz~m42fwt)MAkb0o+59W3OsBva4G#@8D^6Fnk(HWXKnm{sF+)>f;&T;1B0 zRb&YJcqzhb13DJS_zsYn^b0cp)3Ax|z~E&l7KuzS?kh`Mo@ppGy2S28Y@N+gN1Si1 z7|HR9Cv^aegUxGlu0}CKWTEivZs8smqCF|@HUOZ(5KzktNdLiTS(1ZI$#O$&b)=4L z;|##EE4LbQGib@RA+ihQNRG*zlw$*MB$>>wNtdPR47+3famUwsa=wz)4VyXE2Up7S z;tMZJ*rkyzTZajDF@obfd+LZ{dAGTWm;CPo+80)KBy7U3Mslnb(UVpiVlgL_KgrJ(BMuQ*P1 zu#z#L;jsSb_jSQwrLfWBkm7;t5;xh4&BHA;9~OeZ*58&3L?yeUQAR9{? z(oTeYwkOt4;9QYhy?RxidiuRi|07brWgbB($AV((WM8FhFP@vhA%~2bBg|a0q>-9g z$Id<~f9g+uT>j@@{Wa~5%kOP88U{GvfBZMcu-R(MYp-3Fdc>_z$D`;X+8{?%`40_2bhGYa-HuGU~Z(EumKu3~%8E^%U|>b=3pKsFIA z!Y9Z=HdfjxirS^@AlTzGi7hG1gSeP>%*AI)rMznRFcI16^pw42Nf=Md3q2Jcj`Vt( z0OJ@G$7~!U=0CUF9RQU>Br|7Zer`^-cB~Y8x`gfU=t!?Aj4b(h=k^_W;nH<^;N%Ao z+;iL_wVuYaKNwW zRK+e47>w7tEfR0CpC@kgy$PF=83FH!KxY>Kv=jj*Vq%A?iI*9(v*=^$xRU`x|C95Eoh<_cxO^2F zM-0UEN&P2A5xAaC4@fG&8b6cB0=uQd&%LwJkZS;p61dxQ1OQlK4#1#XDQG;?rRGqK z=!>O+1ZFX}jsRrO;P;g(e087I3ImlGVOcLh_cg>-#ZndP3u`qt0r?>Sj&OkS#8}i2 z$ITbu!yjd36j;Lpu7xVDtB6Q1@(`V&c9X4WgglpVY zfQ{MON;M<%l|^M_Zo{s!t7$w8@pFXz14GzE=#%vnJZy!1?aW8f_S)QxG`g&g$;zReM~E0La;y zF@a(2HTtp}voghGh;(&m3G+x}5FgJblegwAqtHOZ1fW>I8)$ZN5pl*y9U9}lUCeBVUidKZxSEfH_ z6-{1Z%ySCJbC9|OvJ{Lbn3~$ZH{buc|M<=;A*3PaKc=%PV`t5u09)>FWk?0yy#i#3 z=W6Mb*JmF*E7x+&TL(y`j$h&&!<0>txQuS>vO%7twmKL;YugA?`rvfpG;vPJK9JGN z&%OZk-j`iCIS&F{+C4awY<&k4lmdJ?*=oj8?*Sai*5$RvKvvflrE}O*6u;9O$b+l1 z(yk8yLI99~V-n`)WV7Cu=HafaEYE0bp4 z8wtBoR=vqTi8r1TKgSOISDbo{K}16 z^54GlqP+j&qw-VlUDtUTVBAa>E!MI*&#@a4vaE>y`^KoU?un)o^-sV4tbBPGY8S+( zPAtpMoj#$p{o))K^Fuv#(h0=AV=d%-0}mCCPOKd1 zt$L(EdJ0mB3v`ny#^?mVQm<(Ieq}Q$8^FLUf<*Lzwl+7E<;1eNBlsh`+dJ@WhnlQP zzl|k=WU~+qQU(vTtrRqg<=nZ49#pFNF$+wcJ zlygjnLf*Q5QP6rA-3z+#+#b7mQ3DOZc4s(L=0@z^)1ufgo&z;f8qFpG+1li@F7c)v z;}g3d<;~3lURVDpYylH(_i z%c)bRb)1!j*ljB)l9uaDA1N@zxozc;nK59Smh0N@$hJz9y>8lI;y@dF-UKVP8sfh5 zP6w6KWrEXxrvR_#K)%G;x;NCy`a=%t`-kOay)aUsybQ1|($3U@GJx_(#?FjdQUZ8I z(RVGC2FTOet|L4t;X4wYmla+sK${9;l;Vk;?6$D3hKZH~YiTPrg|m4p*`y8_*+a!x z9-KWPFTJ{nxy~w`oIQ)kfU5zi>IBs&1)EiBGT7tiYGpeZG40s7Re!u?ZD2Jc^5osrQXFD-!PT|^Jf zUR&8q?NLWTc*ZOdV!bxv&m5lN>_S%B02Fuk>k8WBb0jJRQa^Ga5;|sSFbLg?hzS@aGF0ihKj7|q07r>|t}J8aI-`#fsV19Y z2imM6wP~1Bc`|Cp7q+Q1oB5P#=kZyFfK*khumggIyXWS81)jOA(9B4a%oQ`4=9;H?K2 zedhsKiHtKqlK!o+@6-mTY=<=EAO=*80jm@RnPhBY2S%kv-j_5Z&Z$ zhC}56c$&{)Lx7Q*J1KLE3v$%DCVTLCG5}KMVtlT@D{}y+8U$SKZmGjwDVAZFX5ow; z$tq}g8L|T1z4AM&Nx+0Wb4*l*@6*EGF|DnhqAc3EbUfP`mF6OxBp2ou-E$Eq=IH=MN3W-Wc*h5y(Jpp; z{gG#qiKF8NdFJp)P660^{`NKPytA^hF7JHwG5O-P%c63jMD*b(wvi272VyFwv_<4-&$O=JyfFcz=12>`-S&-!xPTa!;-zbyatPyT=$ zCpe}hD6vw2|N1}v*ODOn`}nEzQs^Ga1EU!{x!0h8Qk*+o_Iw5xEn96@;wxLocYZ@!`Xa9Eg)3WwwYPwVUE0++ z1*Ld+W15L+cBN38?^tCn`ytMnJ6%xoYm}kRw%Yx+Y$1SJLc)qVGdsJxs+)0e(2|3_ zeFd+`%Id4OMySDc=t?R_toIPxdq=9<5y|}giu`Z?oBsxZ#H{K;_2A!7!-L?Je#U`P z=^q9UsZe|Rhwqs#aS}=WI}_j?u`~h!(Dv3gf~T5XxNuQRa$b7=MLG4r1=SPLvdALK z2D>^86(n6&R#pHkZK+-s3yG@L83kKdMprD(DzK4ufg9j{xz~N{`@T;uU%o7NcbeKA zjq~B);6NEwGXTvFsqwUbpn><lbkr;)E@&NbWc;3 zJfB?=fpHbrwYan-x7a~a#;&lIF^yvDv`3Ju(;LD6>=<~J`o8)cJcB^ts}lIz+1VcZ z%&8Af_D0T?rShK6t}n}l<5f90Y)J>nyWjfsm*smu_}z9cE$K@cO6KoHPN#3+^~MRv=i zNI&O*G8?=}`JR5y6vHY7twnh>wvjoUO2F5gKl>(a6 zz*)-BO0UDak2x_7XpP@>oQ0<>C z68j8GD%Fy*sRr;}31SgU({sc&W)vN#wv(4J*^7K8wsNf`qt8B@BPa);6XR0vmgTU~ zko98#T1E$ge6a!=1SiNkBcLATa6zOfPDDF(h*+EU5Ng0e}w$<@W&q&(`u9 zm$nBz_=b7JPE`fp2>8UXZ%u-1Wl>@KkN_CIBVWzP`r-_Ln1O;AF|L(mbeyjXrASLM z@#XT+BPS434R!9c8$E!m>{JR+2f-#;Y{e{X4b}kGHy);Ra6@eXb}S=Xg?}2s^!&Tu z{&i{X9wLU!O9&vRRLv^GZ5Ht)yD1{)E=K@9q>DJS5KFC^mmL5`*;)>9)ClA4DKg(D z%PG#t>hU?*-)-sItCXs$J4l_YBA#Ry&#>F*YP_1yCo)$nskX9*aTx$0J3MMCpwH<= zV^UywIKdv*33G9wrn-PNjQx8beNevm+}G5eaAk00^InRB23I1>v=`s#ThZ z1IYr&~+3(T+v2+Y@nd)OKTMU?rJ2 z3)rLlN@C^B)B@Yz-_cTCuF1yXQ1^3|(5jR`Vm?l+!uI^itb)ZsF{{;0N%+=~P?$cx z^E9x$Nr%8Ol;t+gF($;UhUbD!naaXAKPX92uwe4~m{^~(DcskkFxc3Ia{gc}_fq%M z%!cPOKosbl2+e0?468VhYf^A1Dy;YZM=t`vh~(<^o3g$z0~DE^@@8cJ#j7%#59RnO z7B38TeFS8l9U8*EWMD{+V62-BWHyInF6QKJV<7uLo-=SNPn|s@uWalA?H{RQl}A>t zpe(hVTsT(HYj|aITbAYu5_dhR!V#OpHI#fBdSnlG_JF3}k@r3FpmyOo*xr(u6hut; zMP#8^o9=nmIqvxJH7UV4ZL^gpt}UM{!NB%p4x310*pfy)D@QOw9+2*R041x7OH$m~ zm%*?gCuS)zLHqi63f12w65L!_hdZgk}{U)v;p*M z^g^jDtjM{io{@cI4BL1;H&=qiIFheZBcjuju(K~`9$t}Ep#5&d%Vrig4yzui&;N&(00Fe|%_KE`aI_ox9?6ptrrI@d$$bs_Wo z!mZnqg~2+1`jo_LdHo%`3hnOiYZ+x0`_mydX9?i^WJ?Ns-Nd#32A=y5JnqQ?7lDre z21dI_C&AIK#wE6C))&vZhMQteO7MLBXk-pc;+{=nC4epuXs`PY3{Kp$P~g`$CxRIR z?fQ|ro1&rwo?Dx|<8$!_~Sj+_l72pnraG+JC;Qz?CwomNwO=*R*^);d-_{K17d1V z9GmCVuTd~Awu~(AOU06%KN6=NNV=aY?Zg5(hJy&)*mbrKAE8<-YNtW&ugykXZefpM zEA#>OBxY&*s<9M}$Adu9P&*mL`lo;(-diLLj#{Hn8{4Bk)3Uaqm#s z2)XqBHBeHziDkjZd%rgpK$j{1QA=ONQ`TE=5J>~ROXRZfEHlYEP>6qOxJQm1=lka7 zre^gyH>yPht_urDavn%D7|Ft1O+f|fUlEi{ufz5~yMGd^$?}Sr%~!BDQ1Ei{j6DS{ z7(6}s=mWBg`~1=i2M91vN?h;AZ~W$OOCSE=PyP6xR<^$+1}tQPz~!~lo zs?=LUEsbl|>r$=FsxL`BDW4#dcK1#c#EJ-@X{jQ|yRX+9XeZ8*mZde3Y>g4$l(Akc zQ3-$p$j-U-8M$$%E-Q!!dH@j`0Ej3hLeR{b5B1@*=3!Sl@NqF-c&=Hp>x6)auO+Cx zL0h_g`q8+LLPo*bD2K5b#-_bh$m`mn6o?PMyjEoQyMcCr+&k)#I3~k3Y*mRY8^lW( z=Wc%pkfsL!Y92AeNUE@hhj{PBQ>(By+cICCmlv;YYuRTLwwxx0Y$`uMEJ#f(GSFZn zk5%SnYv(|&zH$xrtEyxP0+K)cq4&csb>zkCSESzVTJmEUk3pSS2Ko%T1iaz9Hxk5~ zNInNWAF*Lxn%G-1Wj3Mkbbsw1wWtXsUL{b``}swR*XLFHD$B~4DpnPrCG4eYRZ+XL z$GSvgP7OxZ36rIROk#}iT-n*a)#++efhAn~-r<3))C#bPeO;s4RZ?t@Da@};U3`7M z8PBDn)x;2(jgasFco%v~GVw`7VJxMfx2+Y5;VW3n=SROGkC=#ghbXlNzSIQf$zy>5@o>!m~ZSdNq{hu##5d(U!n2JC{uW(&!0f9HjIi*zVISavgCv_i+X2$bMw^!;I4)^t9)q`b4p^e=Tm~oFuUIRy)4)0IbA8 zO>PfQrl`f@O@i(;tKyBFQuhI+#mRUxmc(_)NVBV63NWRPYw8`|dl}3ej5kG*$%f+I zmzEGo`i?}#8>w!bN!qaxhN#m7cmeRBxi2FCDMNre>t~i_gmWBWaToFayPdww6-zQ; z_Y-`uiOGHlgXPbzir3kb)*u9m-IHzDgtf(4%|zZkXiASd7Wgv^o3ItJEMPHrhA>55#dhcdr%OlDW-Wb4{xsbKQv7v|;C^&2w8LR>m^UY`Bj7bLoI zQ%;>aD+h4eYUP41wn}wQ$_sOFe0wqrW8DA}U!Ez;u@g&jguvm|tv#ikKL8+Tdv8<9 zSj-F6f(oiG%^jD+`Yi>#G<&;p90tB;BR5UUPBSxfSh&atB&ztUJ=er#?rhjilWV|d zQYhj7C8=RC@4xU3I8FFYz20Loa|EaLur1qnuF6(1Bb&K(+1x70@|7(K=4a&Li%-a< zZ+%j_0G{UINQKB`P|)`3&aV8EU-}m?JlH%A@5q1gkq_hhvp9DkheNAR4*XCzwFs}T z0MMJuS7aBzyE^%6exqon=qA}=%{*+91A*ko^`4q zBPfsW43JTY=(IXv+{B5cE0Bth^=NE$Tmxr8m5r=f2GtJ`b4tX`YZ|ew#*y^zz)_!D zk+jdImf!f|ezpw1{vv&3aXj{$j9sg{003JPL(HmXRy5XVu#QNUXJ$=*2HBfYj{z1o zD}bi^SKoY1A+sjF1LIsAEZ&%V<)w>S9X(s`scGT5&;R{cCc8?QsGWI(dz>kAuf66ypDm# z1fBVx_=%sA_kYj(;UDa)rUrv^vYygX!D-?4^v~q}?k#OfOUV*t?GE&Nsh6Z$Ft`V5 zP%$&Vc5Fp;x~^ThBI~D4D_F$=8V+6gpoju*Sp;bmkFNm4I?6TlHG)?>e-B`kCP?x9 z%gZYoDCbnzouE)t-t&Qv$XCAhl3cyBryy49dv-dVF(}7?rLdim+1WYWhdF-Ca$mV} zNj~+-PsxRc-yx4*Sd-uV^yg&$;)8PW9FkspbuBR;P#}(!??!CDIrU9o4*5i3Ic+--YB$>u`Cg4>XJ9wV+)xB|YJQ+Luc5Z!5tdvd}^NBxZIZd;# zRO8dJ_tHNG%Eel`S_0@v5#=bf(j)V0P3z3Y(wkhPHvz5gVP#Dve5aXOzD%*M#Csi+ z>;8X#J0Od5jrX7|GWvI+^Si|YasqA&28t8tr!EzPaTiP*i!Ytq7RalvaT>RgX+lt) zIzvIuI%cZP0GKlxDDY9l+Vx_}sYHlp$UvIa^2I)q!QDYuN|mDcSpe5Z{7;Udq9R*nNUJ(+wXJXx9pafpI$r`drvmU;s3Gy* z86sA;c!mj-2OoM=Ub=NvS!|hHUKwsBj8D54%hKu+=0!)ppE_LxF*T9pbOn_8$?`(n zSE-sYkdE_pXe?Q3UlD-P1_C67G7E0U zN@?fQ^m7;P-}hd5-FswwUT^%fISy7fIQ`kliCta3h)h=*jFTU(+n@3v;c5nqaPrHRVOV!DM}3n z;t-3!2FGk2pb%-O%tG`r*^lFVSJ_44Y#`-ABA0IuWoh|@GK6SYW@fW;1DUZUApJ{A zt8(_y$Hc4VrH>6H1ZYuPJ0nLsTXOv5S!7S(q*C-16Tj2PMp2uAK|N5Rx>BhiC)Zcy z4xGCMpx+Oa1GzQI==vRuaMc@0H<b^Z2_}v=#WjJp9i0YZfe@QGY^+O1<~& z1$b=8D(oIgxVS1?l9%$znu^{N!;Z9L4145;R<43E>fx_BTyu~#ka>wUTg8^P)UQgr z4wA!~i4z&SVw{I@Dmv&%C@E+{jV-HRXDWr-0I|yqgpq+fw8%qQ-eQ|?JMf^g&6OAp)W(uwKw@NEs}VW6_>Qf zpmQpxva}TOOti~Wnt8#p$0qE(bX}51-)3RGeY}1AaUJKjvA^^U%uk&>ZPxBv@H;L8 za?DZvJ%jfkWoBFFp*Q(_x zc~?cuZ(a>ljGPIoS?uw>URRk$DxjX278SuGmQzsxnSm2^uRH`UANtTon3O=hty75UR{%N zxg-(%lEZ@|`My8-e!Wrc7ML>DI$OS_8mFc+mU0(*VT#>*qJ0R1t8Y4 zcAHb+Z2*7=?_E27TyAXa>mHjjS$L%P#nLinw@;lujex5oFTV5w0Gb)8!ba#Co$S!#cLTFd08HdyXmKqUBc9SaBs*d}HMFpxAVV zTTql3U=uh&)^af~x9@HscpF+-4^Gk^8Y?lx_YWQ5rNZx_2?e`vo|APxMdbbxL2t~Yo5Vl&oM!61Z^Ss| zZwUaB5k&!Qj=$N*l%+ZuYlRf3QN>0IjDHC3xo(tk;_MP;IrWA7jA@OjP95jAcBZ!H z8QM@6;+Bs;sUBLj5PIixyqLjzvPuIltu zfLn!eao+ivK$Euw-(q$u?GH5pJhND2M+60_Y47&hvE16~$^yl~@yxdYt`y)iQ@@UD zkMlG{+>#GG@o`WqU$mQWaikwgR4(3-;mS(B|QigJP$fSNo0i80t$hXb@H(OoUgo294 zCw-CK#=bHik9Ln_abZ~&k5#0;)sS-!o(J$2$o%pW03{EAU0Lb`uj*Y*upc0X+iUH} z?!mq?kA~a>MiwI=O@SDKb885&D3m(FD@w*3)%ccj}|1baK`1Mmh&xUf{lxK&gitBm;W zOW*jSl;=vawcpipIu9{bLt~OyI+4w#LXIrsBeMq-iRXGtMy4r9;5p}Mx62-U2L4_< z<5EDKYu0IJa&8U>zLpZQ&QrS*YQihj`O8>T8KL+efxP}G(oXJ7)N?B((3QA^8sl7L znTnqV89HYP+;eTwP9(8uXL-KGNL)v3sWBRiCf3Vo#oeP5D586<$pu8p)aAaLC8+_= z%TElz8x03z#;Qw!X&Jj}EL)3Jd8-}Yc>tFF=U#9s&5WcX%GxPo3Rp@ve&3tg+@{Xx zxlE#X6PA_*-6;#j8&g_skF<>}aoq(bTbjEDcWr6LEOFTf-(?^9Dzkmmop|nRpOxM> zzQDYTR7w@8!LfP;fYa9YuIz7YE1mxUMk^PabJu9WQ09=)oXgALZ~*5auSm1auYwv# zKX)YlfZq&Y31HAD+Lf&9?v}?w%L3h=DP&+Y>&X5cAzOF?n`I70c@>CuS(+oh5#ZT! zO}>b%>?*Q}H5k_pGIR@oO*+_A4>oQ~W`02#G|VtoU|bff71=8`wY)8ekE9yIiG?N0 z!H}HHdvGrCzDhxsW{Yy|@?99-dD&@3^773CdH3lWoY4RdP(@yN<+6PAJx@BS?^JNX z1;sYbaAwIM;=-GqttlW#q47-^g>T*6lJfxKF3c3w&tLIN^7N_8a--)<1*dxU`Yk!c z2C-Bu%f$sak)46n#KRZ|Y*B&FY_fv`z`6p?xd10|pxsO0#1iGk?d) zGq*RSTg=J1^(7g=8S$gQjLs;rhzZ7`fU(~N0%nwEF`pD*(F(IgFp_jUBN*}-8bM?_ z>h*?{e9BmPDz>iRr|%qAiZjBoF5=pdmy!;?XBZ)q3}=YhqFETb2g_M(csL(!kR4Kd zzararZ^<|D?22^)XufmS0u_$*{G5b1ugAbGOv_88#1cub$4?*3!IuekN+I`ptrx&mw#jHxhs6i%E~moevX53y;KX{dva><@P2%|6mh zEbq-a3tAAEmPv+gp6VtQ#;)`radt;(9}@iEepRBs_ctUd7v$~Z?c?p^Kkku*ZF}N6 zJol6_l$c|u!pW{vP+CqTGRcW)tP@$+tJnJtZ_+XCTX^QEYN=IP#^ib9?sQ&SY9-DG zalVI@qFEA1ePw`6x2|7C0MLRnY+e3t-@c`R{&m=W)x_`vwbA0hc?OW7bLb;??uQ?F zhy3UN<=;eLP)A_WQ=JWVKTg3Tf;cJzhK>|A}v3eFoGr}YQ{|I zbO-wUtCh0urR`2vL60C!;&N|dc?`fsb{Zrw#Zn{H7>gYvkxctSP6~L9Kw%=L>u4R| ztYnP3Sg9`^rOYRHO$7jB2LR{zeb;Yq$#=i&qJD03e)kj7Z*0p`?|jSz%T+u*)v`@w!Y}e1v&@BTzFX6dg_TxU z*ji7+IvKA4TQiA!ZmEyrjS=8612D~!i^(0N45(Dr!S~Xx!UkZaJ}SpK2_~ZHLEukH zAt{7EG5{;pz~UEYm8n;q zYf|n_?0-A($_`&aVC_2YN{SLM)nzlGXLd;=Gl(TgI=-|Oaj0`jOS9s1Y}3@AhhQ3@ zb|Owh-E_=Um>ge0wquq-JKjSU5{5x$7623@;NCwPDM(Q$P~!~%U~VAIokN}X1P`=~ z)3=~r#kmd3(rckG_5h%FJ{wE3$w1xo%)%&8Mr00av3Jy0P&vp~bbT|0a|4c@X7Z-8e06=h#QYEkD$Q04e7qhYt`#=zi4WI}*6KJLox#w81 zBr_0vBbdgrV(N-fWc&ch&u(v|>m_8+GROiz31x1bzDaPdJaYmd_DG(5=7N0S>Bpq+7ht1cyO=2OeeK3hU96?W zs+?F@kk5Xjju@i^01jY3VuT($7#8vve_!{Aev*?e#hN-pv=$*U|&IuGQ|C7 zBnyzbhqx;nv?NCCQ*;#K0Uma(SdtRf5X%9%0s9!!9M%WzmWC^2i{krw81pP*$sERl zKv7UatX7(nQ7@JqjBgW37h+X}3v*?Fef?NLQ`_;3z00J(mkG4wmG<3FY+jEDE{|+a z%jOLtN!aB+6x~-61#Sb4e+VjjxG!bAVjP2fLB}|8ooy9hO-uDy!aA@nn4SZ;!+4-T z<%s2ju;;uV7Q>82R@U!|oYmG4;N_aLJFqpU8hny=KAl*}boCMt<9yW8*w~dD;(B`Q zChr^j)9zoC-8cvb4p>glmwr#|NEUCc<2w$(@*NXL1LCP{nYO+bg`Gs)hGhFgJbsuK zc;0K6E#o$E^7QZ6I)|l)H^yB zx$H>hD=cEvTzL1>GC0_f zGY>o}2^QU@n|F27?6X50jB*)Z45_nG`%v})jGe^-xq11DJo@m%@`abK$%DAVoTKr_ zp_MM2IKCp!UAiF+09s+YC+8nnm)mV@05H@Apy;(iSr%aQTNF%$QDsK1(P_z<3uomJ znctmTT^PcgtQHJV(Qzh{EmlhKl}oS6|NXOHl3#f8N%?>M#&5_XjPKw3nV)qIw8%HF zU6=pjGruQ)>-`^*bMp@fYudALPFLpFq}j&;1{iqf`Ab>{-_4fgsr3h7tVY_wg6dIO zW|y(#f9p$Mk!?7F%&PrYf8s-UJ}^uy(+jOLLlb}hKR*9eY!0zHq90gaky#jp%G`_u zcs9)1Q-6dt@1&Ie?4S5<>CK;(0GscrTurjrbbsM{-i6G9$SfTAr`N0UnVStYhz)EC zb2!&SFl2qwT-%9k0n7@Ez8tR(~fitiMO3n~_H^i2T$?{cc zEvMtpc^qOKR?j{p$6!>;aOl%+P~+mc@tPu_Yo(jwGMDD!iL$P^$^V51j>(@Ps*lf? zYXud_EwUB0XBr5aK!}ZMoJVGA51ZlQN)7Lylb-h$5OH^Z`)Pn6W)HM0)Hp-#jhSfl ziF~J9l9nQQ$b9*~{Cg7pr5}{HkGGGvkN>#G6E^^+^rH!DLL9YTJOw_?Q3$4h=42e4 z)8S3^vECAg^M5=CMkN!EN7CjpDGe(HttR%_G0U8tA{&7LqKo+<|*~B__H76w4}xckf88Hlx8RHL)0gl#0gs zs@7`Ko>`PLr;p3w3s=WwgVRUoN;#;jMS-kR*h}YAnrKcN`&hEhSHH$rkjdB8&V0W8aiA=NQ3AD`!<^G8GcX0z2=-+%?pbl| z4XuPJ4R!RnYqNvs9>Ml$;OUKo*{6S=e*N3McK)HCrEoQfjT;Rzj^ zjVu+~A~Gly93b$e*B@9l3T;m=5Z6&cOR2;?UEcxh;mCEgB#@2EsunAfFZ;@L>v#H^ zsHOexA)~CI3tn$G23T`>6Uz=_6^tKg8LC(}NoUVl>gQq35lrh0OwvU=!jXBSfP|<1 zeUK$3L6qeX@Zvh-He|td^EF_Ks{$)VoL= zC&pd{STH20z{(cbD3*1pxHspzZ=K)>-sN%b0WQ6T_>7Vw1KbnGW^oyDS}mg*P6Gg9 zhXAu@yo`20tap$k?z8MqwEAMy11J{L=9T2k+A#&C3Pqe_se-s<2Fdxnboy=a3q{0g z0EPh4)kuCA)g@m7h+mjj!T5(Be_FCPuFBUgzkp}m)9!l&$sVZW@LXnPuW=}QdqY{k zdGFk*BmT;1c_M}5$#(0thDhXR^!)8sgxG?e{_@)WzK|~hYzvL)OW+BhE%gfTZ0%@_ z5@Y--Y>M0m*(7ZQs+VVk8eRvx za1P>$ZdD38**Y>C=liiWkWe*uQMN24ZphryGG@Fsz~0aK8L)f3pXz90tz&$XQRG;- zZ)GnH_WG}w%$GMH0ulnG!p zo#jcr%t+gH>Gx}J9_eNV3|!7HElcI@RT*J1U2ldkfEig|U6rsjBZKz7JPhE9 zXz=AbTe3V~m4_Z!QBl6zcehn={Q9V^rB&?SuoLxU4dBUa8HjjPm&R^JPQwW!qCAh! z_DWeTYg<@blk>+;sFRwXU6LG}v3VHB-8--7=H0`22LMZQvoK!O62KG7E-n;eWe0`G zXx>DYa~Z$O!Pz_7*^%1vg3>=p1FqKQfLxE{sL=t6j`xo`xZi@Dn)l_f-iE=Pm7Rkl zIKw3sCZy(70borF8$$`s;n995?|t$KX&g3?t=xlCGt~FRu219u3%Z-YDJ{=P3yXHG zlvhV1c3CpEbWL1lEG@~4VKmCfY|XP2q%tRc0BICr9O4{RI94$nb?i}6!x!Xm&JGMX zwZS56C<%bPx!GB%_L^#pXh26?*9;0W1>T9rWuyMG)Ux;v0A%kzHYZmPI?DE<{!NKsaR9G;;SgfzDIDpu6D&oM@vy?IGJNBfm=@1Tyr`?m9Fz97~b=Ay_yx9jg zpuqDc_C(BX_}(O-^qh06LZRFQC7G~8-3K$D_%a-aq6~lhZ9S~FkGGHiSjVGRJ973~ zN1}`sXOXQN_$i|za890DDGg>~r-A9@qqHl}IOXLf@@5|s$JradV1aJp0$s;CnF7qy z&)D1Vy$AKDGFADxzw-0)kN?p>l;>W)ZQz)n>hAc;Dj{=(&MsLCzGGu?pA*Z?$q)a? zpOYuw^%%gbBm8N~x%1~002+-3&S$f(YGhxfx>p7&1>({MWznP5H4O`IB<%#&y~I(z7ZH zka7B*W5Cs7>#>i^gI(Z8!$^O}@-qq-vy_t!$tbx%<}&vrGGSP{5{8ijTP7M~TKhEa`dmPE%ffZ9_ivp7S{8A)Y4%_CqZpH1?RU^KC+ljP>&=(42NW=A2Q0 zLj8DetQX~WVjIuI^p$LV_>P_9*i%yrY|KA!$l)}mC`bGS8;b0$BxFpqpzBv8P}j8R;m?) zK6DyE%3SyCYZ%fwhlgMeje^W2cV~d;G$Nx`FRCvXl^DzLfn^Dt0UEFQOA8Sh|~_W zns^QXQi_<9wV9$^Jbzr-X61504iP78?rkd2cA|@W%q}VLU-L{8iC|%6wx$4nmw@4H zSt_e%CAst(VuGHmFBGIw%qSq8#dV&XpH*T5@3mfUNu%Av{KcFY_zE6zNc$`e3~e4{ zrJx{*XnA*{3{XC=T&}1>^I;)^Er$KYGCe{JnI~XFb{t}qS;PYr%4Y>1g~7buP#Jr) zQdu^XV7FZSn`|t?i;OyQcqZ8#wb3%Jft1)BVOL9KFb3KjAe)&qLm=RkIM9gi^S&+wJalz2Hf*U61ns8cLP_M9V*B? z(F7+8kfn>h>n{IRJH8_|uv8)6yZ5!p5B!fIRt8Gh20U^2()U}i%p*>wStQPZojPye zO@OhKen0i)Y5LPLpSn3DCZdM(?(8(Mu~%gPhh_*6;jmSgSD$@By1Tcfd3O&+xFn}f zm9TNOWjo4>*B;3VGcufB{ZJk_wx(IT1!StY`7N(5N&uttt-B2gFzb$@ZJ7l~H8)d` zX2%2i-It}}qC9pAz*1OX-wc^uUX*<}8a|w_T)C)||IXFdBoE+Z{oKQnIB88Odf{cHz)H`1r$e76y23hFVSrf-orPVo~)0Jkf`su-^_0 z;9i(hBXT$>O1@Y_mM{;81?N9DFL#f+vJ7W41ZY-;vB(7kV?=4R2XIywsjJ}12zYRv zvwnE4QZR8uAn|4DFL@K7^7mhSQDpZ>ay`p5@;Sr|QjkH2q5(j+S!MqCm_IF`_7p)} zDP;8dGW|$_KGw6xG_<5H}w6qqzajALChO~SF*O--~y&ZsdLz!c(G{%@2Aa0;OJAc41c7l@8W$|44m`D8qyQAdn z!FZmd(I?}QL2oMa?>jb@{wFXxcS=9^V_PpK9O&};iDk&tcw+u}<#jlOJy|Hd`Q|E> z8=inyj%DfWOOkdmO|u=T1MN+HPVX1lzF+yY6ahH4e)J;}zgW=Q~ZyR2Pf?=Id!NkZNRgItYLo zO%15nF^{@c{C}2)egAZDFC-_3IzWS&^<+j{M=9fn0)1PUzFWeTR!>wS7dHsMQT{LCr_T1t(`r)7B}xxpvD>?C1bXs z23F2LC+o+8PIpo6Gcxwy4S*w)f`s~_@R^c92Y)Tw%*wYd4Yb=E zH$=Fj98%{Lzki`B>;G<^jkTXYyKVS8V1~Q$xyIXa9o*e=MIcgs&xK?8FI|x-9adl}9-`PU^5n6Y1t=M6V1skNX zGTy6zQdSn`kf`1tVN6Q;IzgTiY-gtf8;8APCRY-YSnG%bN{Bt0t)2;>BfiS;{Fql1 z?{6V_QY%+gTRIb)2Au*;WX!cYNZyMk2pG308_*@6*@18rdn(~V!>IsP9&?Tf6^!Lj zU-w-1-I3b29Hnc*ymW_sOZE^TQqlDcWz(#Dm|D}Y$6=q~R;Xo`0kx+B!zGy12!~vA zq1tB!dBdS%3ECPfNqrOp&>}xgsu_NvGA6!T-<;n}{%|(2%u!4tfytUwA6zjg612Go zhm-bG;?^7`i)Hth`P_T$$%4T0Rt#Y%NE)BtYaybMta)Wlryyl=9hXUIy)^^swMdbf8E>E#zQ`^P20s{M_?$;oa|% z*UB}?&o65>fbFO$-o`S5mGxzSA|pA;@;EqYo%)s(Pp!-L<<}&{0q>~tp$H?{!+Brs15Cq&XvdKn z(EytobJvn6UG73>B7 z=%s-?odr-;I>hs->E|n9N7yH50dE-XB0zz$KZN10!ypy`hVB6D>qORWwu5KYLcnl1 zY{*F%xvMWeFB?~1k=epAIXZV%2I}`%CMabsD7~MIt$5VPEnZ|#ub zS$2V%W~zCH^I(s{_3X;6PEjsk5MJ8}<-}tr<;^})JulCj*a;(Wq|67Av}=*)BE-be zLb$A}yA&{-9%aCa#1hEr%T2oRnGO zva^#Q+=5mOm%XB#d-NH(@YplvkYoSqcN+5IOV7*AYnSEMfAh0I28%N68mo$WH`ILj zJAdcDR-KZAgO&!`1bxy{IvyN%>-3k5#jOooa-Eah^+k~}SlB_CWs77??e6X>ldA^b zh0JLBGzW+Ky7%9?eOs1}ol^g-*=ouYi*sXLsuWCOH$av%rri%y28`;70&pwCUpapK zIDn)bdFPW^snv@3P6AW01|zp_-jWUipGO~iL`z9_cDIp;TazcBe3#tV_-z+xd#at4 zN3cZpjChlh$RpK;veH79YIXsb@q7fcC=@-yUdwwt4>(wRs$?uF_x_X+q3C;!5NwIar)8>eBIKCcJPoRn{U_4ff{{gC|q zfAp(zbNdhp*9^w_QTgY;@~`C#e!o;IDQm&=Ccb#ul3v8}#VG?Ty~o6{8Lac3jFZ%f z1ER+b8^m*ZIFtD|0eT|`bX$<9^EOGwx?kyg_1s>%=Zi9mhHP*X-(R{ba(_ARxNJ6_ z%vF{cb^uBaoG7!EIU9R|?`Z)H@Ld8hwPERVpYGf_E+_ORpyl+DxF>Nxh;@H?;Ts*r zGUr}V20hwJj+3vAc?cnR3O<{D6(5f37A2y9DM0`$`xIw%col(>u9PMsjv?o%Z=B9P zWi+|x>=gqo$?dkOA1qp_!0vTz%rynp07ex`>_9kFt*IVBr@`LPK#IW1M|}V+2{nLP zBh^646-8|m8BhdsDULqU@SVrqvW;q8rN7V#^qU+!-AWP76x`zQ*mP(wK=;JL8#9-i6Gc2n04 zO9(S_fQ6#IGU76MBzen4jh8yTuKLh?<}se3H^8||jD2BaIIlSNq4olWJ?tpUia_Ns zW;tjg19nJcH$<|LLQ5 za~zH=Z$`F;=sOyH*t ze(d2nRMm{I1H0V0)6Fi8V&f@2EOGr~XxyuFMd@R6t}HA_eSbqPee>&*^x6_<*?yHG zrzPn&3gQDn8NeuXknOBvp|oHm?s{!`@_0@noTI}URRAqTAim5t9-oP27nz!+nPn+- z>QV$iQ$rS@T+GPs&VlRzFd^fnk83Fcz z#JczP4pploH*6v!5U7*K4J;Y<(%xm6<_YMX{%oI3GxhKxb`NFtAN(uH z{PHKI`P3s4yzgO&&#XyOF3Q`-+sE6-AAD4iJSZWcB5?K49VBQ5){0tv!+Tf=j&0%a zo5*!p)$FI|x}Zk!J*75!Bo;&_Zvg;noM5|$1(GtYl5v7AnHZbO zJDFSsoFkLjk>CB~XLQe8ny<;_ORver2QSFEi;v3Hn|Ebn>u3y=q@dLFb21PJ$-`RJ zb+(JfAcoF?(B4M?gnB%adE&}SRgZP5l+5$)0Y=Aj-}%`D^2q*3^_^6VJdE!FKhopQ z)~;;t9Vml{e%I1WN#<*T3SaL7P$uZ}__-5udvjYFSx^4Ozx{2w%Oo$Zso6M^&wcKT zNW>jz!1}qVE zPqE`A#hTftQh}$ydmY0{eJ;;`9qVfPwfjpA<-TV={qwgw_?!kkYlxASDT`~)qq;q* z4r&;W8KC-1n7C(Mi92=Rz(MUy7$sxooWfe#u`x2+MfMMT?+U;WmIITV5|A|oK!{~z z6~s`SpS@B~8x|3$?o-gRIJkyS&<`BUdW$;kuVIV43k|;nB0sJE1 z94Hv4WnR?18pT>BmnSO1Zhkm_g>gp0k}mq(d`4p3BL^LvBX3>m@I3QbU(0p709O10 z&WU?&BQYG~emIs)Z1;zemUj`n@3ySFH_I_SYC5r~Elji`g$$d$!=4;lDM+IOkWK0` zY$EO})s)RfcGG^lt1QEM)>9ygF%m%-0$tvapp~bwp_d5(7O^C=Ba6ppWxfL69$*M< zUm~k`92rfZAMEW)4zb|YQD50b2RANBfLMcF?pbltSG_0`?&lI^zq`&+f<2*!?-?jy zmqnZq1lDYUKoY^A0piY}5aW3fgu!P4+T@eGti#4`Ztt=Yy2a#LE?L8~7%H2o)d6rf zTSQ#h#hhpf`>co97lzcMa_fxzs1R{nqtn-QsU?`OVc8_o&hqRyStVuCFRri09p#T-cGlr zgM4$RsnlDxA3l5j3Dp3YtL2q7^^V6Ml0$%cG%9nrpQqMN$phd2qj09m@`D&-8r#q@ z=gM=7@?B57OWtweQJEk0v^!#|#uPhmqzq8*Z#?rZN#Jbeka=B&0jJP80kDi)v;#O% z-+Shm94u9k2@2$0YYRGKBAkz#lXi8$Gke#uRf&cy&s>%mboA2cT^j? z`Hd%NlC~-qEnV~!9uMSqE+z82*Y|W&`@yHr$VX=yaxCcR=KH0?dD&wo5BK%-;I^EI zZy|HBE>&c)gXSSXRAYnrRHvkoq61VcTkWh@gKb?fFv`!RsZIcwdClYu&pj>4S6`CF zs3#?6*Qmw87Q$LT?&&5LYbQ!85Ao8Vir+)0Y788kRzl!SG$mL<%FNw>t#eE8R&sk% zZw#fCKPwOBvhrphQ6e%`O(A0nmWwRaF%`RiKmDCpmN9a$mFFC8N9=GX!|!(M5`5x| zGW)w<((F-pWZ7jpFKlVf{meCgG)AbG2Ivk%a~;;gWKvqB9dz9LeD~h8#3Jix`~*7b z{BZNj24>^vjOGHnLGzC-tHbWroFdv8DC4;~Y67nOn@v$TM(sY!j6^%K6f>i-GoEEf zE7#-5@FttQQ2^A|j>4fj3+$Fc!BA%7 zvSdPf=6GsD0?!0|OZX0E1G!me$-eYlM$08IB(QrV-J8#m-8$JtNCl?dGc-1i3o^yD zT0#|%&S<$1hlST8ZvL~o3~h*Zmcj1^2wJGiQ>&G94s>Yqoj7(E&Ji7D)opOP3!>!~ z#;DMe0$0-JyRm3=MymfX3=L$@2A)34oO8rD<_zpwaJ0FHw&2&@X(AYL6EK}m)H=+2 zHWzBR{6#pHvz44wvG&*on+)5TT1^G7$tq^6Z9kV&I=;?Tf9z}4$vpEu!fpn}}T?nwWR$GRR9kUbd# zSW^Jk)O#!$Xs3<2!EdD~NF)avT$ zxLY9qCM${T2Kx%{b%00ud?{d@3X3yiTt7P0kq)(7Fw}EwY;4LRUZrnx^ZIrD{lVdp z%+A#0=FJ;&{P-!G!&zIWra_fx>7s!j)CXy+o#M~S*ta*gHW2hSr8YaOS|nfm!sq0v zr=C;>(dO2c+_`;6wQLAzt*ord!w)~AcAvcffK)9fx5(i7IAx;eruw!pQNvN zQ|mkhy3=6MK;qa5y*psYGe9wIVL!btr&&$O6e!8VN->SKlksjL8La>* z6>`dEp%xVxGQKi1``Q@Fo*koi--2{(^7*2#rF8_5u&Kgk43$X}Wb)RuV8r(hEjbH6 zA#8}2l!akSeYs-B)0kjk9&u8i`em-BColklY_HNll)crbtO??dh01~qBYVbV4Rw3N zv7f;GlzVl7s2ZKGz;|Wei7YMVW&g0N$^Aa&gI}IycM7?Ey(9C5Is6_;`8@opT0!yz zL9t)gOk-b06iqMXBs(NP1plF&RT&oU)okK0ix`Bd=hueqR(U$ROhTS2(p`2d9^UN(ENwB3I z{^;Lv+;T1$zWu!A~%V;N(Cmwu2&aJ&uKKZS$QrK91N3xgNNTyd1JNDw1^Z_8! zzsOO}MH}bl;B)r$z1)kkh*g@f(;bWvW5FWg2{L(E8tIP$+1%gI=hLTO6qC1=RXakT zE75t3uP)|PQYHe}*nz)BpO+eN1)M{>D`qn4@AZd$?Qm!%pDY*6Ym7E>3}b6h6*(q2 z9$P9?;M+P$S<@}+N_29 z0}~y-kvZrW#g3JlvS?GVIZ2ZwW*x-D;mvn`s~z8Q09M{NP$J!Av@3+`7?^H@=@`Wnm^|jGR8C2&N%N?qhAZ3Mmo^rcKffkE*;p{zeSByZ3u^nQp-#=hTv1LPdq55W zG#u^T0*dR&4BOU49d+Vr0Ce)T8QHBLNp+?u%>e)jAkM9B8%R0HraEh6nT$au*j_J9Dp1TX!Q(?g_hzC>o68MdDp{dmIykKHup=9HZc4UVla=GRPGn&-^UG2`z96l7ABHMYgEq)k^|8`e ze(`r+mi^qE{P}mUIJ#w`#7;gv)^nHP6dXTuQWt)lB^$~cvw~b+4UR)j-hb}2I;70V z1cjo`FAL&r(=NhD{n&e+vT`?y!Q#5vnp)f7vZEf^R~ch-1?)=UyMP;WqFjh=AMF&~}L8mzQy$HLXPsoW?-lHvTk2#s7@}QiXSqWRPjVnBy^)<|T`bsNnUn zK?d^qS6cEFW;S6UFMj-@lrsPd=T6Gq;hNlT?aKP{oYe7LpG45{1ptnRQBjuZsN(wH zy?)#+6}5Eo#jiappT4mzANk0KI=5K(E9Q7VY%n z8N7UScqo7G`5UT9_Qdg3sU}0Yg^eb`82$7U4@gA|vqM!5+ZeUwllw2o%?8CxF%PqF zg!gvjVDrrvaW7R(4=xpD*UYS>OwiN@P3BXQiohn5@(G&_u>(R3@DUfB%oM~q;>P4s zhuq{i9I#|kWP9wYa3&r*;r3)p3Y}>IMI%s zqTk7EG_R9^W`7WBc8m9mTAYglt?bw%zG?VS z=Z?-Y?}Ijj4xxTW&N}5VvzEpDrH)^@6kwn5HPB?Hk@^Ta-hn-7X18^1IuK5~YlQ}s z(Qz1RMlVq(Hw{eqAW2;p$5J%MAT+=X?_=4Il0CT=T(_(-dYzbr9829eKHBzMC!24X zUuOUKRysBkYbioJbmFy|b@LR^YvF#jI-KopS-8X5V6K^Z)^CkZG6c8$@HL@9g3 za{;0`^VV_4m7S$5jM$t&0-ZWsj&0>eWXw`9s{Mp1q1r62wY#!LdEW}cnFE-(5=358 zsr2SEBGdAvX~xX7;CISIQQ&l3R_44Hr{6RA{4{8l;#tW!@J~yqY@Op7W@qJRe(tYG z@9+P8xx6`$zwtN!Q!R&J>B#*2JOYG@2I3sovUV-Bb1C5R1{y#qfW_=KOU-)So_3`r zQ;Cl{n=L7myKz)kk@j6AeeT}ADK~H2R9mpJxS#-S{pd)}Uwm{7wvi#k`O1<=I`w?s zdwYATM@518g@rj~MNz|vfNZC=Bh}d%dG=c`s-_e*b$EUX$FrP}tO$-68Cj>#oRPW3 zd4NqT>Z4qF?W**t6Nx`8A3SsVBtBPCG3E3~*+MF?48LgY*fCj4mgJ?EFDux_>)PAf zmy-a*-u3P$<~oJbX7OKwkDN>UyIbi3#XtX}Y6}x16pX>vC^q5c z$jzz1F^;Bzwe+sMbi&J|D`7I_)mw?6Sn~pzX1=8?YTqSKoQ6$ecFA|iy;S5_Sy`iW zcYghmju%Ufs---V14X^ACIFg|vV9Vr^Ay9Mohj*i4~{Tb;m(#IZQd{`cVvSOO@g%*^TxfFD+n^l+_=KYAYagisC- zV(Es~&74VGvOLK&>-Pr|5J=09)IXv>+`@CFufaD^`zcTTIchk?CZ_FWGdeeDPkPiz z!Sxhb;s^lhSUHf5%SY11I2ZB*Idhz2SCC4L@*92GJ;F5&5clON>Ky^NLt?*Nlo+4y zv}3I2j3$>uiU}iVs03vJ)S`f~m&wVK7f))EGLz4130%&%k}}33`4XO6c%WTRYuMkL zhyl9*>2k9;e`uhI*&eRRP?Pai#umvE-V*_Esmw-Fs~2o(;F_{{Cd1J{vAQRpT$b&F zMB4kYeC8X^$^YtSen!6jY6)}yNWSaB1-Z3(pu+nHL0e{UPaBAnl?@n=H1QcBSf$3= zpfkX_nT1X7E6_JvscEw?>I70(>#*IBA`)_QtMfAIb)`V&T$Xx|eJPf$bWcGg_?$!h z-Rrk>E$48NWSA*PglAbU`}&Lta&pe7?i76>fKS72sCrkvt_88K>dtW*$;;$`GC zP-nLGYyu6h6`C+0k!&Fwjx{AmJuF}tN9srQxtY}uq>e>9n=i=`HuV?=tce9$!s6-# zp=`p4++yd2-MW1E(PQ$poq=4sQ z03wgAp9m%dOYj8K9al+zHye5qEzC3jPv<9KWLC*n0z6I9=-iEAI&S;in zfGouP%$&>@^GfwxsO4n)Cc9AVN`Glt194UZGkPKWqZ@J~g@e?sOZoIErO`4g(gs*p zEzihut}l09eHNf4GL^`>o`2#=zMt2wl(BP2Iv9@(E9G2yot6O-4oIe~leV|xyu&<+ zY{T!u+2^gZjv0^|vMeyE$Ydu0w$;ikHkefz6qn@lukOmHE^WzoJyw)$Jo|T?os(aC z`I;mP7v(engWOV1-czWJ*BA}ztM#6|)EdZxQB5v25M*F%21!PR-q|fM>9_Gc6n@WY zFd93jnAhw_0|jVC&5nHS&K~ATS(eT{B`e4ly?Wy_a+I{>>{?kqIyb9h^n7z$K6`Xc zHV#8L=&aAq!O_E}+uRku_~tXP*4IzUYp*mU6<18N-8^EM2t$iE0XArJ!ZFO1K1YA- zKrou3a}CWq`OE4?tlNkOrAB4Vvs zTn9*57TSUUHV5Eb)~odmY|>I{NsOK4+qF`pG8@E>CN0{Ts2^HT8jEv8RRhk~HqhFl zm(*)a*c?G6-b-wW0@?y)CBZ0H%Q?L_I+3K_vrFkHvCb-VOheDWx7c;+(w6AdjnnH2 z)&3UAg5sQ`6H8EsPC;U282OB+rAPFdO680u21q?3dx~R{&-qS!BvC4O#OyfrDHtG9 zpcdIR6+R9l_x`LH^DWX$ZW4R0U3lWMVYZH#)F1KnlBHd1Ms6>O94i7&vofp% ziG)};=pabP-?TA8^ZgYR;`h?tPYoOGooas61>m2R`M-4{k5!pm39G( zC(I8`BE|PIq!n0-WB0n#NOAsC%7W5o&-oBq`Hd!`ri9rQ{P!*B)wyBljscwx=rP@u zSl5r014X)CM#`Xz^&XYYph0UOOLGhIW*;dyklLNJG%5w2^d20$EaRnm7gG!yJIMqv zjMMYVJr3$bmcbjpU;9!N*W|DM;(sRFdp%iLoEew=&nzxVS|Z2{ep(`xb{U-3#7Z;8 zk?VTLwbgDmHGtm-&_ocsgY!n=zI59S6>H}lUtFA%#~*)8KKjv*%Ixf{23-W4P98so zeP^W1EizR`VNVCBiev*pC^DnUNPsaxRw%%i!u#s=Llv9mH4}(s0L#*!!-Kk(1Nzz+ zYpCN&rX+*R{ry9gRp1mR$TBkrAPb40+dGFkPbt35#MkoDqRw54tfw94cyL}({$XZr zNjC3Z*A9zJ{LRfR%huMm+@_}2(t?~iwJt}E%ksLCRgVd_yk7Sq0=qB;1(V4$v`)U0 z&!zsbxxmg}$xOQMX&EiGFA?1GJ`>mFo9mC|ka4>+<@ZjsQ0^}^dn4e3FRiYu$oIbI zVVQ%U_VSh6^3F%j$fv)4MQ-eDj(zg!xt$)JPDg>n7r*sQ`NkuU%QNqJ6mIKa+#SwO zQjvAH2afMCJ!j(lz_H;Ne+Tbb?M7?>hjk-$CB}h)E1qq*<9ka5?)gZfIC4zKWWrL2 zQ{Y&pz~FoDZTkMm6j_|D%88{JU9a1icb;R0mH}2Q0K8fTP^wJ`_`Ki?9X5Nf1EHqD zs5dGh^t=fx>;C8TM+L3!y$@r1XadCzDghgu6WEF!`vHRSTmXm$T~-4D zB@l7AX~c~ zOdG_iRX|OXR=L5!vWrv42 zKN(M4$MluRA|q+QZz55Sv0h$TlUH87WIh1xH#^Jcse2YGiD2Xn;j6^DKhDh76tE(T zioRGJnqR^4P4%O24ps-T+%i^;MwYq{wW*0!9drM{e1uO)VSW$xL|JRG`M?R|RVSyC zHZvetMNn1aBS{->Bw98~#eCJhavhS5o*22cOnPX=47$yh=ed zaj^sE7CUdU1ea|8IJH$)BpBc01UNRKq%AjLNw3o;$lO$sUC=cls={kGoR9 zi7)N+WgbD}@$Z2WCCNiHFv6+srf#xXW-s;NT zyPNXF;}^8dhk9B(r2ySoh%dumtvJAu0IBdzmovU*F=DwUdeq8)xH5oQq5@E5Ikfq8X zd(htlO5WL#V}-6P9^H}tMo)^!a%$;cvmv8{Ly4PxY2sQB2BdB8U_v8nBMEg-AF;aw!_jU9V*!^3--G0`~{D4Rs(HtD33d66|5d0H}Oj$Wu84Xx`1 zvK>yy(KbtrT_$Hvt}6%n#`d8+xn7kex1oAdL4+L+%)&2*>^!1+^NBpSbtK=nUX&97 z0X!2vjM(Oc*^w-^ub`@>J_;%nVDu@(N)7x>L0M2)yf)%Bk{+Hbn8BkcAm+mI*+=BT zK_D;Rg`*A!n#-tua3Ehh+Ld{H$0KVs80RiB5*cMS@=}>~5AmmkdH>Iz{iZy!xMT>w zG9x1Lb9L<$;FNs&>T5D{=A6tR1NP2**5Q@eN(B+B{9a8gjhWf}=i<+7eRzG5t+Br;pA3@YDX zI_;uG@Fio}b_+;CD<@3f#_|Er*iCdQa+ovhkV(c@wGhC`3dbxJ?F~xZ3uck|EJnV9 za2(q(wsHU-WRwmGS|O{KkF7k1*GGr65Aceb2|O3+<671bg<6WpQU{j#X>f>fWcM9X z5SURH2ZV^~@MOloLR#9XETDh_sG`p~j*VT!am@3&UD=$qz7G^=}u&7zgE3KPO}7 z(=jfRG`Sbc*fA2hC-HaBIr*PBd3~#F=hvj4rv1uPR^{R2v(oMWD8kcZmY<9!0uCBf zxU#`%jVm4mY!n=JfML7Ul)arj05><~Ti<#?=gY9$l=agm<;1Zy_$qU9`aSQKGW?r* zvn^Ewe-SeF^gVLrS?x;5HMO#OLdy+X^&`1;?NzyZ>n7%XP8I>4lmLj&19)WVhjRD) zwDe4Hp1bg)W^~vdICENVU%v`qs-?Dr2U%oo6^!mF;6dPv%pd}ECr_?Rgdp^Rv+HtW z+e#ie$98Z(3kU}J9xM0h%XE1j!4Ha5-Mzixm>02vS2jK!WmUcBz3)-!g`I=ucwKUj zp?R8{pOFR(z(y|k;$3BeNO?mSSHpW1&i%` zX{O)vrsko%{@>}(o`Q}`8km3e>XvLHNUgSpGGD7oz1^2|J$i5OdF|rJQXtsQfBUa~ zRW6)8C94ZX1K7BpwH(G9cb7}M4Ne2{Rxayoob$<&FOR?GDBa!(lWIiZxA@7+|Bx2JXXt;CvwqqIFzc2|o{l zwk&DmnnJz<$=ecuk&c1|nrw&z6Oop9oG9VvdjKz3&L6rCjUke_BX&U#7|$3;6{w)K zbwK2WMOkAK#feE8uzO}iy;w2LW3qNixCV-T4+#{|UoIIFI@BaUqNQ|u`hFFpp>7j!b&O8=6LNyFHM0qbY4_RpGntY(>g6i?pLF;zsx#;eHG8 z<3MV&d1>OhSLd>F_3pN;%;6gQzLr9+uN34E_5mK08QAIr)|4ed6|In)L? zstHKWCCtC-B9fK;K;uQ0t!meJG9Ut1Mob?c<22~S+Qg)WxTy^wY|u5fR9X#2i4^to z9ge`gO4qS(EU%1j;_V*a&U4A-T`k%9shT+bt{DTlG4 zBY3B&y(j?8U~zSJkx4z&@mYk?=LWnm>}lKC0CQn9V*6`PRV0x}kr_Pqr%Kpp5P&C| z)pC65F?f+^plI}Hl`fPL?y-RTeH`N&^>NQtzKVMph2xB5jEy$IcqF-s(MW@=bYX~( zm#TWLWNmq>BQTP+3ci=R^DHK;as$h*b=AJlevYjmzVI(stPRU=UFzXmJw(-!> zAPqir4!xC1s~f82&t}sM*do1>b6ZR9*iDF_no2S-J7hX=@Uz^;nK(9u1qhZI3*E-; z=Byhhf=4V{Q$`*f#V8lR-KFY3B?gRSnNg0c_?%-;fSaGAV@yy)nPb#b9hp!qSy>EdGY$YE8zl`P1K0A{ zv{y1?=F%{>DF^H80>@MjNr|jl9Axb(rtV^vnqk`#aCp=~Jq|UQ@Hp-OtePu$?@8G=HxN}=xed$H{SPW%xtQW)s0r%K@g=#n5vMCjyU!Qdu5(;z?OQ zc~YMJ=9h8q-$ugWaXEjEox}{pE|)5@xw$3Ru3c3yiZ@0;r~;qm#QG_D_PLid=w6(k zmtlXP;MK@o2kpw?(E-4&2js@h8#04yT3%hp`gy^8tSDCf6?PabGBQ^nHq>l;n%Lyr zS_Cjhu$hfs2nZZoTa~TtJ*gixv<&fG?|f38dh&7k^k=>-gD`!@u?AYSBe4rM5;qQ$ zJt$3hC22x_@(9yJ*x2i}`AuCb{z)_KDVuLRL&k|X?+spiqY}c&&%DN$Uws(~(lW-b zC=aY3le_RE9)I|p?gJZp2je7j$`qSE80ck%oz8ml!t*c4`o}(qIn;4e(i_iR1#C2F zV*#RRwgj#MBjrhXllxC5>s*sG+#htWa+-^};mX*a=>8I=`b@@Jv-J?UZj6xviSZxM zWq$hJ0@c0>taM%V2}3Q5NoRPS0hOMw;_b?G8buoCC^L>pJ0_FxIWmG&k5jZ^DiZODm6MZw%<^J@9+g5? zWeKv`L`!ff>aO?Bd@mWegV@Q71jbU~)hAUML|y5$yShnHqrEb z(>^+g`pUM7F&2#@UuNe4+Kk{6v-Ak?8&EjC7;vD9IM;h&H_#rdIHr$~4tHTaKY>M7tl zPz^I*i7KutAv8u5ZM)+)Did(rSz9C8l)%!?=3W`Fr~XjZ61YR1^Tv8- zU&8^xE&5=Zu(iEI6NIs8mnjJ5l6Y<0rHs!+jTVeX0;6jk`dEyZ16WeZL>lbU$edrD!J>}jU~5x1 ziEV&;voj0w`Db6nhSZaP_|gmVfBNx7`R=S}sb8_RA+^;-`L_VL{=4U|%FjRjh@6>Q z1fYaW0f4mwYHMId3=wsI=H-_)fW3J7ynJkZ#UKU84p^=Lod+QJyPx}_G<#i{U0Rjz zKE4ctIk2bencI{v)#R6c=hMm_c;};!%fpo=op&eZ=H$QsYFp}B0p68!?dN5owjguJ zfK*Cnqjuqh8eT9G0Q@+FMp-l&ZY9@%b8 zta+S|08Z@YF&Ru5YyyAwnd9=q03Hcu@%hXH5V(B#n(XIb$YJF3WSPJ~ZNUNB^^hHb zp`tcTJp^i_~U+@id(0E$Na?L&_}g7uTYCaG`ZWWY+gii`3_w2H`9DP|mNE z@%z3Sznoat63P~gB0Ot~zT^BC^A&lv90R1o{R4EpyL(M;?_QT8z=a1-odF2w%ONhM z)6QYft;^iZfo5@*=4iy3Ny^C_=Ec^2SKjR7qd)LNQu{l9OFJf|mdIgEW>4b8mD$<* zJ+bz>Mi!38j<>_P^v}qNdkiDz^f6--xehX7>=k7br^1YqjD@Pz=@ko}lnJViA~SG_ zJ_~i!d{2Q9%}~Z^aA6=B0gKpyUZ!_stir&tI3ianD6ZU(@8{1!>_8aOw4>OSwk2A| zmI9~NIK_Y#1_>Fhg-cA3md*n<{I+)EwoEIVA81BROAZZm@Lg9J&4OpG3@~)}U>k5^ zWgUr)Bf%7Yaj2y+wgu;1$zoblo^gyXmJbxDagnjo*RCrs=)*ZGD09fl5G^Uej95t0mve4ZvYxDP(`x)v;k_j-TNeF?*}6n8`rH`xLB7tU-ju0KO$& z5@TzUxfI6c>}LWCP9j&P;pw=C>bTLKvm~By9x3~LQgnV8Q1RKDWS24J4tp{IJ=_c( zm%=zEp^AHQJyTE3&+2{9&RY3QtR3A7uxVL1@%chYa>c5odMCr7>0>d_QSofgX8p)% zIH*pTV_iiq%1#_}(P6&hI{m$_lZXyk+;GzDI2sS6>d+3tnE!xY z=RPkV{NOY4zx&_+T`2+ZF>!U4-E{#D-PZ3WU_}6Fc4kHc;q9$$xpnK7EF*|ww?hJA zs&S>A_(JVaNa+J=Hm$Commm4DQ}X;bzA3-@%fFAGPs*t?r%Xd{WWXx#hdNj+r>W5qRyH=bwPbPQ&RyBv+m+hPtgIhfl#Q(e zUCU(FlbNH<42()U*-PZUMnf*ph~wAKoAiD6v#31pjo$kQ2Q2rO5>7MCk|bq%d9riZ zMle3a{uWBUT9${NcuKziqaTy!UU*Ud>97160{KwVa>@Gvv2M2`k3RaSyaK=NV;}tp zo=48WZ?X`aHlCUZ&(lPqfi{y^AYBZx16IV1PYUjg!PXRf<=*FF0gkgWJ>5XYPPfVS zgGn+xWqgj8*dH=hzBWiPT{trQJR`N*p2PhIwsX)QD#Nim2&K{Osn~a_f%QhrsyF&G z{hsOTxc}#|$h!B32dETFxBK=qkch@zTU}`|%iP11$vT-E#wbp-V_>P2QQb>!P{d9% zS?l1Z3~8t3#xB%mn~{WppOD2`>UCl*IinB2XBnp8HRe@@rTp$XbdU8MtD1~*NnCQr zQ-O2}cNfTZ3sc=p^U`{qf%*cBYq;i0g^ZRhs>pZHSJoW6Y92L)nz-xX88t($dF-nI zacYG?fypR>-^*k?;;B3mSq1nr1Ii$f-Go?Z1aQ6p1CwW&9e~SG%nqGR$DU5Kn_dQB zRRzgtR(_mZnvqScAyHjO+$X^J?VUc(A4m`T|I&#WfM3*^?Mrkxlq$e1>hvD&^i=BP z>4zVavu76Mz3+OTvc5ugYQ-~R(urWm5ck2YkUk5`<8tuPjqQ`sSc9vl)$YmKTuF8D z$b4<}?lMe}<@u^KI(4ZQGtvSu*y<5f8%VQ7JIDlfV4VpwShE9P8+I`PQYx{VU{{V1 z`&NoMfO0*_6cJw{dCjh~WyBVld{wUA+?IzfoK|qjA5n0>Cti+zP+o=B4~`IzP@fFr z8sR;yMhE`aK-uCtj-e&sMgxOl~a`^!tcq1&#)YlSx}6% z-w$=3s(&9~UX%eo=PHN+5MOiL*x8;S)^Mck-i#`p7`u=5W2gyD^L--|yd7&_u{+~9 z+2a|2b^rm1Ex31GtYepoBGW)J$uJg7M z)3bGGmWwTt@z0Ya##`t3jsvhdVd6j}2Oy0zQ8v!5n$zmrQ!S4)Sacl*C;OU}G^vq| z;&FIspGnLhT3UK)hfjC@Ng#R;TU)zq0cpPRMOhh^<=ojPB{ygwbJu{=pO>?XiE2;< zo@M3skl8L*=jFXmKP218PVH^)%i&=|!3%azn1eBRY$cE@{k$wz3lcu~pd4*&3DSS! z?c9~>(wtm=?p4`i|9KNrwY^Rd8Th1$W_4wkf z?9>nB#IYHfS(ulL=hl(=+!LQ-j4)sW1Ul!}YT{8?6&uG241K0hHpT`vr1ES*`kT0x znSyF$_1XaHZuc~Zgx4w3+LPI?E#BIL7j$zk!g-G2HrR780$P+TsK8- zZr_r{0u8T+HQsC@xYy{*-CQL3nOMs-N)!lW?RX|q zu%t_Nhqs9L-IfbVt?@1U5S!ztnr^C91n1wawJOHo!CFyru2m~LsT4dbVdHf);Gq1= zYnuoRvT_`Qd;=S6qu-U0*Awhbvbwl}%=5Z*fZDWMU0e?~o%T?Iq=$RSNHGUTqh$;= zUf;2kn2Whc-t2<{mOt|6ep3GN|M)-X&lb2RDY?Nlau5Yk(&iDWJ(7%xx#Nu`cA||u z_|nj^txQl|>~jRO#LDs%grWmJ4iu6x%SjzaF@Qsbt0M!dL#O+b8|(R47Ks2(=zyQ` z{72mGhd$V=a&1o9%>zlp9y-o}D@&oH;A`vSKp9u5AhnhD*}r{lTpKxUDAUo?Akqu; zdPgI35CY#cp<;Z03mLzf>PZ>or~sgwK&ImqE9f_h%;Dia)(usqPn}_E`6O_zLS6SR z6X%-~QpCThdr09`#sG=aVmJaoyxU8ZSt^rVZsOpi0gN_9i4+(tu|Y*4XJAAe>-;Mt zt*x2%z`8&3X$+9{#$CaW)Icsq)Dg5 zfLNWMv1?=RSX4pQ+AL|u!YMY0vgFhzn?ykBjOpR0Y@^t^XeBA*$^p@I5EDy(DZ7F| zATHpU_qqj= zvb4x@>JJoQ)p9z55T>xqu8+YW|l^a^} zaq84*Id=S*eC!8*NEQ}9C%^GqzpITz<`))ZWpzn|-v<1MIua4bjvZI+seUgjXV0CK z=bpa;@Sp?xkar9co7XITGJQ*5Ha9l4%&|68ll2qFu!pr|;Ii5b0?FDUV=GYLDXX6) zOO5M!acx!3K5#}wj0wn{J$pusRT|@7cjfxED*)~0;hUY-Z2Yy`JMfuu3h+PkzW2%V zFFYr=w{|Vba_@&G%5qTYxD*gL@#?|!k2Lc~1xyys> z8Zuee;G;G1Y_O4e*Xlblx*Pp0t5N6dIGwv=}F#I1lPea$YLCn7+8OplHLf zSH^uSOZNg7j~lyKpBs|-Z7mziD!ZqI#7Vb9_Df`%wM-b2*&UB0WyEkFSC$FO2MI91 z@h#?!<(`cRGW8`K*z;A8GGW>-qaYJ~*)qVRVm45nSIVf&&3fiTkX_V=UkZSRRV2OM z(4Hsmq1CfyRt13ky)f41ChWpTmQ)GX)Wf;iXe)y_Z3G{eiLP5aZCO~JQC1Y=B`(P_ zfHPlXkdZ9R!au<`x4R>atJowb6Cge+6*TrJV%{`&JGysjvlz-A;B!R)U{AqTeEj2o z0wB{I{2gi@Wwd;fjch0nQ-&|gj`y^?+DM0E8Hn1n^4yHt5i-qYt4DHo<46;JWLvGx z&da&u$K~$Uo_zC_s~CfpY;ErV2y0uHYA+{C6~qxqUJhV$DZ7$KycIhADR#;3A?H0i zmz71tbF4;b`o%@E?k1|dSKQNgO%te4|g$(tfth||iG&NGm zl%ga8lfU^=&a|9Iee*MPEVG)h)0vkzZCVQPk0PyFAksE+eutLBI@tpyBt+J6Q~m5D z88fXE$n|Y*a}EvrrUR?pSDjRi+B-V&Wc0JKQ4pBlC-<>l?RTyG$Qh<`IHnPqUo%qCEeh(dx`{8bp403gBk z&Ffgab8_*qCu9*ux4ph5`!IkVEUtYxMMpr+84wJykn8PGPR{4WXB~2E?dltiLn&2C z*ffy+1KPfJ;-oZTj7nG-N5}+*0E?Q}Uy&1!y&p*Xp^5{CK;iu&97L7>^MJhP@!pOa zzTv12qa0{m?V#S!pr}}cVPyxRVp%&roLrm7@4M32L`D&r)1@N2uHe3ast1^@?z8J+Nmzh<7`7$e*^mm25j%_#QP&MHrc}-pC===JNs9D1ebHp*ulCmAh-r=6?cGhG*FkpxiftgTdBqTDYqQ?vYzNf~` zNUS9_&&NP4&(b2*n}{@f(St$TWPSMX2(LG#e0K*1iCS97l3)&HLS{YoaSix>fSWrJ zGB(K6^!-`6)PrXXk+2o8zKh1ybaoU?*Ea8|N5HGKQYfPoxZscV?}xG6xntR) zRC;$z>31Z3VWmAMVSraaX=_w*dfiPEITqu@1U$#&GQ=WS$n+ z1h=bMS$4Z??)T)}YEEXnnq1m%OJR0N7IUP^7GxHIN&(p-Z}`?Qp?~=o{<{35fAHUr zH<7WYEix8+_0vExu}wz{B^;2N0;2pS32zzqxwI2hl(HrgSIX=_C@qmU%wg;xtH3*L z7sbEHbP;2`=w`?=JJ#v@w)s$ERGr#*qLX5pW#;H|$!H^kR50H2#tfOrmJ{wPFzRz; zwlWk0Ju;rn3okOjhu;|Zmh~pMqopvk&!Op8@VmN^D?xLmfZBN{QYOBF=Wp z5CtuKb80(-NL!6lzs~e3oP&w?D7%wo2b{;eo{WJ>_LLIM*v6i1-Yo#W){FrGgzJpR z&y%UhOfNHDEHS_W#x;a`Z-LA5$H_>u%^V|YO=ZNf?+7}^R(7Le@A&?#Z=j^IHL-^ z?xTUsW}`m=H|)QbbyLteZ9w3jIR)Q~tmjresH}FxQH>Hf=mg8@C=t+NpsqZ2c(x5AME60sX6NhSfd{@#JB z>2r=#Ln3Lw>Oc+8eb(8n)Ot%AxX0$tq?%^@C4+Q!pk&DgMbsH^6L?Am+j*ow7Qrh8 zy74p1=@0h~Nk;#pWwjGaU^Uj96 z@X|}_YyF8o@lko;fwOu`{BAPM*@f`v@IbaVx8#NAo|6K6iS-kwWRBWbxb}zN@h+L4 zUzC6HPyZ*mb^A5~w2D+KH4VlFy1BWn>w@;aGBXR`>QKvYJe;d>)Rd!U`yTOj-)#!xlCfy=Tz!AK z#PI&Pbnm?ScC4#!2VSM0`$J~zJ^xaF#sz9*XJs)qzxbDaLjJ|S`AvD{#)c(Nrr1~& z_(RL=%1n3x$<Kb&cI&(*88pw+lA0hG@bRkWIAfI~`l zI3}9LOR29)t+lLOcNVTZ0SM3eK7s3c#*$m^FCK4=&E@Xw2mS>x$g)G7t3hrLAl<=%Wm#v_-cDT>5bw3BGg9>^Y~Pa(Y}g@^3Ah}LQxBkCUxBxJ zqb(KOAIG#-&P%C8m=i!DfUcQpUS35Uno!FM{x2mlGvBxlOiD5*Z17$OsxKj<(oavt?DluU`i3+=m$z6o3Xd;~DrR;Cd zx@mi&{;cmhp7Od4_B(DsqyIb9Y9eBoi1d}HEhW|l!f#+=&}Zpv=txyx1Q|5k_jM;9=1oX=Z+QW(oJu(%R*M zKa?{C7!VlV1|qu<#$s=OLo;(<|Lo_b0|fkNn3Kgk3?aaxxL{f^MF3&_Zc{o)+t-mT zrSW15=MxJx=^Slg5Y7WM>uJ}x3a+gMBN-RU7Nn?Gl-14+Nv0sjS7B`OR`l)lI@Us+v2R$&F1$%b6HbVIJfke1&J8M;tv6=#Od#7J9=>~ zoMBLl$he%ZmSwZkLS|%JLBxYWq995I26pFgQxwGBo#6j%gl&tC?V;&E&EG6H;Pksh3mK$S?4>J|0!=q z15B zVn7jUR?&|_)BZ|q?GRvB9V_2Jy{yu%6SWoDj1!!P^Tzc+)?s2w`OcAWBKXv|a6p$r zKZ!AK{m}Hnv@}75z^$x61)CG=b{IK*f&`8>6AGDJUe^b+ib&F$aKDbdudl09v7vV$tdAlSYlc9Jx4c8#()spp0hkF45@P{>iBBnNURi76(FM6mG*gK-5R@`czg*= zCWQ`MG7v`Wd*ZYNF;!;pbU#g5R{C)*=Se}*WXx7_zckP+u@V|QnT$iQlWJN`3r7=B;%gLiCty=77UkgJK-wE!`RW%xC(nG(hg6^HU~gYV zo9jn)%V6W&)L_wWfyFA$Uy{AOT@~?W7r|S%Z^{fZ^RsjFdd_OKqC)Xx4)9qsIKFb_ zvV84pUqdi7E2qw!k!AQF8yg$eMjq?p%*99K7yjzc$v^x5{7*>4H58m$T3V6?09#Ce z&Ci#0bXQi^=)V` zCxa`BO?$+e0eJY1Ihh0Sck1*hS)9$ww_dm+SFT>nJ-;^Hy@vXYh* zK6K%nyz<%==>a%=;pLaK^d@~?DU(WBAPUr58EqP&j{}w@nR?xx|NY?89|hF-cEHU2 zpLt`jE4Hz8^ODy*gbnY)xBZbH`9aD2+Hc5DS7+c$%+6GixM<2Z zzW#N2_q*SzJ}glT%5x-+6{QSi|6X0N2|FKjwx?t1eqxguQ(K2)mAC)=pk6DaS96L~-bH?r|)#_5N zdkSE=;Y~HMQXA~~_kvb$bfmxk_XV$PG#LxzGzK8!sRMw<>)9MsX7ku?xH3(*1|+cr zh?!W|^&4}c$8vpuSIVS}*_jY~NCdkQ8p}@kT#Wff7Ho%+?R|Lw5`#{x`cX{ySQmLd zx9mg`fu)9I#)+p);x=QR$cB#lYQB)s<|||kWe_uYi2|O<#fc0x*P399EQ3 zTM2WmhFC1tq%D)exNg`i`q!0m24K4RCiF@A!=Bo=0ktjxGStYNDl&}&TiFWLhoC+& z6GLR)^*f0&#byx~GAXB|iBYK9Uw)nvFIIwCEE9C;;a&sT+Nf(XkO2y>uRL3ZUy{}P z)8rvQq~4$>Gqsumk3%HeDMr3=_pVAVL{U%XmsbqjVRu9?Et_@w00ymx9~aI&ArB@C z(%IjU`e7gUTbGqZtjnq=bG1bYTXng5XICCRe;hGkfbW}?-~Q@zuz4kU^|f2V=CBl( zFVDaqLacIh)CCZnlUsL=kiajhX#5UrAG>f~1+dm`0W_i`l<%LU>8$S^wE^#B}pwA{PjB^RNuHk^J#4&y<_V+L!Fl}NN5iRVgEv!)N5 z6+?YgE`g14SQ!*p^$vBVId3vq%2Y(!KtQD=iWJ5Num}K;fEeu?dutLiRGEo^C6kk^ z`6Ofw(pO?ks$g#l45>Va?`)Ls_Tor&i{r=`R%yi;lSzr{sJc$ny3hF9;hVlO0ZjwO zO^4B>T0L7+p{HZ5t2uQClVn_tN2qAtu|E?XDDY(R~#|fT;^ix{e*P2;bzi>u`7gjo`BFb<%6@MTS;B_AD!5udUx{ z$T)YJ-L?eSP|EmB1)yFDhAxO1tmf5`r(R8?)0SQ*f{_ljI|aeUj2CL1_3vM~E0lUdCIuT=qtMF$E-eC>sXymDt7AZ1hj@(;aV>R zOPEs>rB0b5s-HmuEh5b9(9<%SF2OWxkj;J~P3$bUFi-9t9KwPRMB)=m z(z$v|Vt}V31gMQ{P5Mv0TW;?i0#wE<@r@Cng4=*6e*csIPQDC~Y76tZIqI z7q;8&wCi$qp(HT?&@yYqSJ$ME&1!xj(C%%O&XKgSvCQ-VlJ?qi&}c|*VOicP$N%zg z{T=ze-};2yy>nZCPDPMYCYqHXxGaj7(s+|e;2}=DHZft&)HaD@Pmu;ZbOE?(%B0ld zWRh7I)%6i`4%NKHx?%dRTu!weVgs*KcSs9CJvQ3G95VK*@3Kb5JhAy2`{R&b(k@ZD z(ZyCj&y0_ZDLC zUb9?@>F#L~Fq09}tO{-HJwu@AKx;Caz)xbO5_G1t15;w6v~-Gm2L##7aV#$_1Ek&} z6Ccz7G;OjJRrRJ~t2C~4ah#41n_4VXb8xmxTDqhl9PY7-ATon&t(Ll^ARNIuW}mgJ zaVR6K_fESlC4dY%x6=8OSovsZf>K%@uSp?AHJymA20XSO8(SbAJ5DKRH3~Y{V z_f50b_+Eml1hD86X%hwfytBO}w{Bch?YAHMiJw%~QWyIx_ge;{1q7AUmufWX0B3so zePr#8MwS#A!GF1P>yA8d_MDtQe?eAPR{=ULI^k#wW_#VPY;N3<8`p2>{zyUcGY^~r z5Y$xwm}Q3*?IzepV7DSa`{Qwo~UgaxW!-w!e3vdS0Aw z)XCz#b@5#ke&<{|as0Rj^0k?wbecz!FU}$u-;q=~)yjuMWvZ1hX4G;bz|O?p?|=2H z3dZCy4!3UHvXV3x^mDx1_?``n`RdBNvc$+1U0RxxJ9l@b(d}AE<1ijK3ejYQ3w-o2 zSJypfx5njOX4Aboc=sODpvL|BNN-dcHw_To58m8Umgr^~HGo9f5TV-sjFxTZH0!b^o)R{@owWoO|O# zyD=uAvF?M(W3J00ANr|z}<&j6%_*j;tFIicFKfW=GnuX-@CJkOK(eGkf1_12DMd-nHIpToJy&1 zI+FQ^8^ZDqEyhnwONw9;*^dMjv^3dIeJ*Prz>bn+^&0bUq#&WP{oxxieu?2{F`>)S zR?T2YM%Qpm{jDUFz=@%c0VhrBv3kf7f?T_SOB$sjy@d6`wins`CzJ%Y4*YlSz2K-t)=-^JHF!ptbAa= z5w$=VlgAD*G`1?cF8TWK`4el9RqW5{$0$9|6Dt+*?QtfK9!R#823f9UINiOh`@GUn z(+S`LO0x88)Z0sD# znbjo#7F}uJIu{lz^4zr>dS48p&d=B6r=C0`Pb_7%9jYdh5iricnEl`*56TB9x{h=8 z0Fab$?^^!E>?X?+@S|a*c*7Z#~#pC$HrQ*et*QJ@1nj_xo}V8%rT< z%WeZfT`{tNiBwKxLO=BQlgg+g#l6#qQIE1Z7a8oaIw*GZOqOFtWf)cInn0eiUJL{! zyTL=|qKFM+x#%krJI5?}V zDHoDI}`we;ii(MHND)Q(IfQEccYRzrwfAX5lvVASV z2X<)8SqbI{8*%6EP1!&|8^#7oG)4iQhh_6w(v-kC^DvG9o_%%wglyf|mC->%Yy1~6 zx20Q`Ol1Y0$2QhWpt=f~=&fTxsfG0`zxF%w<3IFKxpVvW7y$5`&Yn6@DLCLZhRAIa z;+Rp^y)GWVmcHN0gX~aIcsjjw^u$0G0yzYc#_`29!?#Hg(H4_Rf8_F45Nz1H# zbJ``f*J1z^GmF|4)977lqiNG4QlK4R283UAC{j0EKN~qlS`@p)gJniXn$gObBLF+p z3nMLs^ZayNEz6$GnvlCfxry^=-92?U|I^mOF59KU7hBRocbPD9B`7WsiCtMr#sED( zwy~n)PN11!lrnnBU<(Z>WO*JPZn8&W$A;l}li}GLMCv3{7+ytl11n?aXveWdr(u*5 zhD_s%b4x|%Lkh}USI47)FD=B1&0#E4h@=bB(uT@uDV~jP7GTmkGQ6{J#xhPHhHL?f zJ;j`PY74-bzO@K_qNk;>0EC46rki|5(S!b11We%9Um5CboUvY5k;N#}u){oL>BJ zZ6O$KX#)_h zZvtJ)QtD^0&oAnnVW8D%Bk(|y=;){}4?p^_tQ|Wpr%s(x))ko=wOUQDacgT+*#%?) z6I{JGb5Q}_&CLy&pI?xj-94PEsdMk*#RrA`>#{hh`T$)&)*d-I7G_j{qAFvdpq`*vkOE)f+9T%q?KO?7Hq#ldymXgXJuU_-riHNw+?_z0a*>EOwUBSX=0CFSXhud8=K0WNMv8fURL0MD{I9WyaQfW;pmM_3&Bc4pdG9&ye{FJAiMwXg#+iXH zTtl+0)5^+^{qV;z_BZ4=KJ}Gx*V==lBL&jgQTD~FcT_z4zx%)bpXERM>%Ry)>h_H= zw9@cs0!TAan1XicYYM!2<`;=f18uQm8GEkLg9CQGl&N6*8^QZBg4r@a&T6%4Oo+s3 z+Qfgj#6ikaE{VY-d>kY^DjsAA==(j5k{r5dI zfzQ3uH9pedJCi7riJ+3|BF6V#Gxvj>CdETX7J%+VJAXSpwvmEN!QV^ zqZ&g>;)(*7ShuoscDn8Y(8=aA`dU1+vVWE~YA5B$>^-#->AwW7i405nsh`B&OnK@H zF-e{AR5+jCUqq5Pz$d8pl#XY>+VF}$xO9e+m z+gIqbl0eQqdSMZJCw!v)qn<3`d^_81fFebe{n*{B%gIx7(ywE`WOqu><|{ih(q^<< z2>@@F-ywF2m>|f(P9e!&K)f(lRZYT$A{#SRJHUkVPgma z>13p969Q%Sj7+P`H#Rb#Q$C*?m(da+E+P&{0AzLXELhp1J_KOFY~I(hOafDtB0+jY zIT!=7-LBl&l-v6^G1eK`+&w~)eja~j5xaH}PqFJE#v1rqewfqliT&PClj%O2gWr`2IpG5=94hdbqa;QyG{&n}(D6@_o=Uic zQRtZZrezp;*3mrc zMkF`_C9TmcNu!xHYmGE(G+eWW(nuq-NI)ZsB0*B5;K3$90PRrK-PK)Pm1Q!s(nn;5 zkNDxf_y5h_=e{2im6g>1G$c{AI$w2mxc~oq@4kD_J!hYN_8CC=-a&&ITNct0_58!+ zL$4on${uLz@_PEN62ZBQy+d}W?>Zue!;wH{!M$m)!p%464eWeSnj3&reZPMs`EbOB z1xYTq#rQ`zjrYy*fdjBi$lCM)oO>GajIspCmQT@W<1ww(;FbCzLkOazAK-xGFgiRU0v{#y=AQ5zmB2;a(>p>&?u_qeIocN zjLx1$th$Hd(msYqhs?p6KgkTAD1M&U1aa(FYRGdVA0N*V{8`5FsWH?_d%U*JB^O9)Z!xqE@}q;SzBs;wxY3CWfKK%)?FGgQT{JqehV)=_Z)m0?1`Ca zr`02d1n)CNBbFT-$8@SeXZ0<-_Qo|l`-$gp|LxmI_$?Hq4L(6*ySGU|sqSdJ1WM$j znM1&UiQ5db7!00r5@+?T^Gb-|+ufCIr+3p8HD7v63I0=EcFRf#VcINVj1P|ybYbQ{ zleMxOKgc>;ctS&QmpWtK$(*f8Z1C^w~-=sm+XY{SbDGg%asaQ^x_oNbu3)vV}YIQV2Nz=T^C!(%H zBwr(zls;Yc({{OZY(zIUT^$)G1s@!PT{_J5{h|e-x9>I3sqUb(QpC+$izbM#y<6vt zNXv>FOpK0ie~->K=UapKt<5nV65}Pxc@sw7MT>Z1e$3XA(<@M?lPEWX1S&M}b9ox% z^&6b`1-yQhKxih1r;g7v)6sWq9-{dY-mmC+#Zy*#^`XaJzy;5-RNBoN%GTO8V%J?G zFzFN2-P$dpF@N4R`P>}W!|n#bi7@sE{CfEbG}NgnUBCp#p|-J4r{m9G#Qo@@Qo{f5 zul^c-@#lY$RRfW9=P)0ZclnM6frG4vZ7vS5l7rp# zT-QH`4LD)L1Y&)q#O(09)}1DhfHk1ZQ-&<;o`GoL@}t%CL5(t$ zElkA|=3IvY^>%%BJQfKYyuN8{>GKq*r{a-7tUO=`g}npeO$Vk0ZHs+JH}6~LG1qO- z0xhrWg8aVQtAx1?KF>2<58s#@rWw{Z)dgc48=z&GV+11e4!P?Dx=$wf&hxZ7o|Pfe z9HFH0L~GUV%0mw(WWRq1UIq+g0~FMXIvv7HA<4{X#+>s309!z$zkoLgI5mC}skMO1 z=0)6e5uH2aK5yVPiCtE;GV_+pMw@n)V+2_Vkyc5-i1LHI#J~apsM?LZK?!Wf1x15N z5!{0x&@HU|bD$>?1mC7rX3m*!8ejdO(Z(QPw@VEHWlP9f^$<=B6;jpr^*~Rq7|bDETxh>lb)5%&fmaEdf9RveZ~6o=nhJ zX`4>hjT<*yLjl;&W0IXbHiNyTJGfQsTj{RT|LPm_%RL+4C?xi7$~-|&VD;rq%AQg7Vfu)Rm0vAM8N1xFvf7DwKzudIQam9oK>6(|6C4`K zAeK!K$l!eKM^WBynl7)B$?9YmiDb|w=%o(MZR-*Zg6|z;{iGT1)XF^qQd#b$eJiQ8 z_QrgFmUgDoklvrrxG;Th>1L`_(L*ZRMkneNbHg#8ze8y zH7R$tQX>84zz&j9uHY=_*6rK#0UR^kScATcCH#K>V2}3<*zX02IzM3VIxlR1cpm`f zLB&TuutD#);{yj^m1x`}2V#{yTa>M!qlF=xJ`OS{?I2s(^BiEMN#61O12j_sc&G1Z zo~mg#%?>%W`kUuiSpy9Tb4K`gF~6MSEA1X1Cwe=`(Rh^kyNT&(tQAX0r3p%O;>hP? z*xK5+`rR2CnjlqgnKrITVXSnYD@eY202|;^xKRfoOMqV*~Y40~6_CE3bO% z`VxlDKdFi?V=bhJMBjh)Wg`Bn?@i;@PE{4a1XkkM*e5^|?_ir>(}gUZy*e_?P9}*K zr=+Hu$e>S$O1_oCrrYvF1sIM zCO67+Z}B?fmf0EQSPl=Rus|bdftK2D(?}@@Q%!q?=jwLCMuW6MB~cUvjwqWIa_#4x zFtp30n}h8;f$B7!Xo+s>b*2{)@&e#NnVKYa=v~y?AxwiAPl8zYQW1Q7BIP#1fT_g-BnV=}EavT-vK8KdS#vE5H1%ZqP?vQ~Dp%FilHpFnnfk#jAACLQULZ4S)( zGFaViXR*nrI7i2|CgupAWg_O94k$Ab4_r{wTi8DLi4RaoIbM#tPRu%7C{t7AHo9X5R z*~S;1eu4n(B${;CzqPXqP9^*wKK2m|jm+Xpzy53Ze75iCL-2>t4sIocZUUdUf|FMfDd3o-I{O4RuM}l z5b<+NeAf&jC`NZ0SE2>?ox@{{{jl4(jCIp@b}bT6`K?ng214?Vw(bqsEd4-(D{$T% zRmwA`Y(QJq1!}_zyIs`LoOK~#$3Pflf=r_$m;bp3~|jGo5UOuL#7YdMgx|TT0*qR;GbhrtTJ0_0>^Z|LQ%W!PNRPSEV=T$BZ05Rgg+do-JUPR zk)sWgla?^XOUFSR0k{nVrJ1#*gR5sC5mRHmSyr!W8B8&3HFhcw6R4?Dn>YsgXaS4B z^8)RuV06PSyKYQ}VBR}zu|ej~G35;OMW7|&^@G~~@Zr42zzqx7FTwbm_LcjM{mu3V zf57ev+G@iwY}E7Au?2Gn(V+(r@xYC*tFeAW9AbJw2D=FJb04`Exjb{=5NLVh%KzMAN>g zwJnC1Bo_oy<#H;`$zg*}(L{jRDciGe{0OiqrQUeUdKi#UDyG_SqF&ud_Mc7|)H zfh%v`#EFx~!E^~~OfcPBT;h8s2#jqZ&A`QMNl?QjZL8hgUEHUw7ofkjwP6e}G0MY{ zKrcx@2TVk#3)aC&e*V(Z5_b0YtOR*zWYqMq)Cp17Csw@JsA<^E_v_PiPv4ONdD_I^fP$ftL1R$H7F=+?aTXmDfP{J%uAZ2fVpZ5@U ztaD!5>|_o-e!sL-!cZn*eoZLNtL;RrEL4C{msuw6&hQF7i#h5l#jonT5gV_B5>xU` z3?%J4P3B|-$(}mBi{b1U13F2Q)8@skZ|-3zzk`csE}70=hUci3f^xrj#PpL?oun?U z?S?B$wMH+tM?|q#u2>aC$f}U~HdeCX+A9?&S80RChm+_u6DTnWA<2hyG{x(7Agt`% zouy3!{_Ff(Jdrd%Vsx^A&83#bq<-eyw15HBF2&y3Zy>c zMPuoQ9ZA5ib__)7XdHrhn$Jb7*-W*eHQhE6hxx|z8za150jF}SqfM;dLZM`REb~El{8{&!i}kQ0JKdzV3Y@P5Q8#ioBPrRv?>G>;<9;aZWiRS_X47X zf1r(Ldwk4&t{8vGmE26yCgY10R0w0&dfpY4;i!DU4&aQM6X6c^bi6 z%sfiyPgzLU=>WFyd!35Z=Zq=V4k)%YE`S6VngXI!I&P@^D6dgn`&v6SL{muv_B2VA z&D*EZ*&;wCfLHoY5+!VwY6P^l5lUrn_1mvv{^S{i`95{fiU#F**0z|}cl^v5bV5$Z zcY+ywiL&=gMKpM=U0y?_9Y;7(z}QFuH}2lE_b9uT<;K%)I(l%mrDs4xCG@@Ty1j^= ztBxM)T- zGeNN}eD+7qanq@w$!v~v$ew?C4o^Hi&D&i!CRKy?P@)60x?IFuw7~aOF_j)eI=_uO zch~T-nUfgqF&ln)6F>A5KZeHA7LtWgq@rc~?j2@~7_5GBGDdKS+1*&rg4~n!3hpuA zxs}XWi{6p3AqzT0#7h|G@w7%m1B?SLj_G3WGq=cY16(V&1^1cTQX&YvqEE z!1;6z{t*C7lx8(s=sM=9oDe5k?m5c5Lzp$PO-T3C_RR@X03o|9YJSUDRWSOt(^?DJ<|fQjje*)h z38eHE1aQd-Fy~cwEI^qb(CxYGeAjmXxSRQdGR2-_=C*w6^nxH*bQv-S3CN}k2#i@H zkwLzzAAl=C_P_6h-SxF?9osy6CRXg$SJuq4Yds7^9rPy$s5dB4@q;ojFLY31TIWC) zs|@Puy&x+W%q{*s$@A5N`@li$;tfz!%ZAP-J&YuoIAEq$%z`-WoixOvrjtQnFy{IP z8rwyVmXK9YTG>j_c`W1tOw+&#*4hE*AP}wh2JEb!V_%ydl(F_AuB2!X-0?|$ zTCK;w@CA-R0`JGefT;n<5U|z;Y#(E1_4^pK>2@VVM*?5C#9lZQ!ciS0KLETDXw$9V zzlHm^uc0t;*1F)?SO?Cnz#;vUxVrwSj8M-?0^=L&8_4D|_@N*9(Sz$6#L8lBh`plH zz`;ET94!{NO&I>h_3L&mBO}B3@JC<3vH26mveFtC$RnLBts9jOiv4FmR=;m-EM0^2 zssxtlZ~AQMbh*+$$8gkh)@uZ!?MUB|BQZNWg_9@F84KZ!*Wa@FJU%vRC9}z7l%Jcj zc_iOb*Po*AGtB^Od}6{F4fSTzvf29trBZzFa)|&~r+4I8IRGmht{Y&M&E~MOyh31X z8TaokS=Y8C=ULc53@16D^J$&$?v>15O;1hZ$tN!I`d-Hr6H!xHCb*hy1KHJlLjIjM z*du~j5gKTi1t7xr0-zoQt^PE+Ru2O}9{l^@JqK*ZBR?Mn1pU7Mj`6ZCmi&8z{_FX3 z=kUUF&*Rn0uQM_H*1Li%?N>#DSbzKP{2lyzf8*aaofrgjdocG7Sy#bU7uXla&U5P~ z6ms@8t<*d)Cn|Vq<8|eZYEVVw?6=Z?sfTkj^SFJiRvVM_BeJob{s${|C7)83mX6?5l3C~BI-&~>tz_g9Ahl%an7}vzONFv+NX`5%norZdj$V8*s8>t z@MfZfWAo7`p2P(Ah!aXH~QMthSYbiva}#L8ZkfB7^`)KN6^x z^&(bIX$_TVR+`diM9A28vQe#O&t8{I#jVS3qt-G1#{3PxYje#l7iVuYFD#+ZcOYV~ z=NOB&_6L4V*ZFQn(F{6pyN=$T`LQMrZ;ZLVlQA9y4EoX?Aj66c-1~U>roUw(_TFIi zdO=g7;2Hae4PQL((9R9)wyU`a(v06Df$`^ceBc1A8VyiJ?3A#}u8OuOCsrkA8sAvd zl_~U9;@Wp@#cQJD^1)U+A**2(MYqbyk|#=EQ-sARDaVDjU2P)I30m*EO-Y8a!0d9P z=O#>+D7M;NR=FT9_SSHsz6f94|M=Pj7kSN3FayNJy<3DjkSA#rw>P(Fc)AWiqmesv za>!cGM^Y~EG~z=?T31B=6QYRbF*7@c#_bA{W0R=f+lQASkkF{oKvroqiK-J-9!ohE zk=STcBRLum{w|y4G^@d51ZDao9*r`MqQW+b0NSS9sN1BB1le1O)v5c05Noxvjis^# zL565NgvKXnjE$FTH2gf#cNs)Sq4aD~s-swo0GPBId;&5Netv@JMNCeu^eL28B8Z`K z!1=jxymfuSbyQFXI~tGYXu|cEd#GE|>ZBTLb%E}%ZeCDH>G-gt1yzt~X{NYP4TNl6Clb^t~^)CL6Cr{$8>bg56 zj7Y4InVf9`l-dk_`zwEpJ%Ty)XcptVwger|AsIdzy35~r8>7Q{+~WpUW^g#tQt>{= zgfMBW+Q#Kt8;|9?CZ!)?;QaMhS5X*F;q(b+r4>Xr67U%q6gegWGrdU6x@3exX^wFQ zxrrp!?rz}}=Tbhmh#2QuSS?pMZ`5~b+qAMA0HRHOyUu4DVpgFOG2^Z*Or6>8n_DH! zPLIRnm25^i!?#@{7?#MQy21IHZey$5H4wCESrcwL4P~9UjySiVL9Y-5$zW~0Xac-ly^b@a)@kAWdWcQ=fBT#NIezh%{yqGE z{?^~bum6)@g&Qf?Y(m>v&p%A|YVS!J&=E3vuxkbvFsTNtkU(F_0a#A6$^1XSN<~Gr zZucFS-}U_f{DGaZ#~)&0|DY>fBq)(kmlf{QPD4qMuLM2A?mdp1;$hI#&BCd^1I@yL z!yf88v1@5=#TYPjw02-Dd2>3t0UI_GcOXuafK1Dhq+N4l+r~zsGZ=FvUhzoCI%PU% z8x}}tRchTz52hPriCmWgORQ{e5<}@dv7qR=Z472B`)@CE*eYdLlttTc_vRCn?iuVzrU*L0QRet%pt8 z9tpJ{Ix4U+(bx(!*14=CML=T60b6>h{H(cD2%{<4-UQM~2Vf=XmAS5&T?2{ZWKeI0-!F1ZqRYsvSIG;J9Kz;L>6{4jOFdhVHL zT(`mZGwTY2Qsg5nnf|~5?Ha4(Kw~BVuMUD(&#@34`|jPK#X%=Krk-wH`6f=DI*a3% zp0t2Qb6G%4GU*wsP7EYoJR4P&wb9u-sxNQj1i&r>&gv##$3_$ zZfzB@va*7Og$3Nac@<-0Q+Vd-XYkC2p0UprOU1;~mCa}7U;hM3>6vD^zv{eVfteq| zYunx3G5@8@Jt9dTCd0j2=Mq36)>yH)Y4&boW7EJdbv2Y#)BT(~_XIN848FpBx=Ei! zpwj5*Fu|iqT)(wo_Cn{CT~T?W$_uAwW-v)0OC=@u78ePmtYUmLkKJl3V6+8gvg)#| zWL2{PS1QOv9sSG?J^LIJnty0Ml1eize)kVSh6ID$PyfId@nb*wgIHX=VZfhCotN+4 z#{Sk8b{cI9IuS7H28RnioV^)u>9{G+4(==c<6gP$9i|% zP?$|~0LKBT6t44X&uojNHO`#7fPeF^oZ^1a#zw#^i#lQOV z&MpV%c0f=9yQNBya0t4O;)s@%KLA?$N5;W{h>?hE&S9EH0nj!G>;}02S3+xb`2jE< zI$)AMYzzzp?zt|EV%aF+qU51;b`%_|ilHBI!K~(6`vE}lK>%xTF9Q+g2mkgjgLU<; z!$S~QcWv#<=DTV^H)ey;vFqyj2dr5H_9q-jwK%B)-}X#Z(;VuK1-hMKH(#XnrX;m> z_ZFxaU;~3jTIOe1sjy>#wi>O21XI7`k|e6!5L-H1h}-_9l030(l-N^+L#@^gl2A?a zJ9Kw)4)k11LsuXs=aWjBhlgSqCdg9ZXV8N%W=@heWo?so5^l~_YeL%O3&mWgJ8MwG zGsMLptMNIj{IrYg5MwHWm^CKd6*I~=Z#8|!8;oc8xuJH*1n#Bv7vnxHp?NRVHlcbA zb4DFu34TTVl-ZxLk#U@wKW+l#S8rXzCtvuO^A!d#gzqGA`lh87vE-3N^5qMu%uZmA zl2xiAv3cEfK1N^uw~{1Xm(s3qJ?4`sivucJCXHXl zb+G+Ag0tu5t(3dMd2^C>cVcu1UwyTNR4&0dK}jy_tL&Kj@>>}T$|i*OR58RDm*7CG)#6h5sHiD7B#|)8CLp}UNmBjyCewTtha4mYd`7*K#^9O{5O}N zbbe~Yb5%ZvvJGKd2LhPdZ6`BfK93|ntZSfSB${MM-^q~}NUpWfbGb+BSnoU8jsu-b zSL+ufJ$r^%xTLmk5+Pmx9a&6gtBk?!2fovwaa{-pen#jhtMdJIeBc1AELU)&8=#kb zKxIy3)!{Y>NTfL<)s1f`9d|k^CS=MDNT_$952LpxO%Ew-8GAXj>Jv~CN*i(@m7KUJ z&m$m93@vLd&){ALCZT<}TSspB8qz~FEc{(+Y{F>H8@nsWh{=^nV0bEHZBHAUMJ{}P zCV>wLGj6Xi;OF9>~M%q`scmW75PlmI{)nPd=hJwd7YS^U^aFeNsdoa z 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%0A_;0@OK%K(-LW>-%Mk6!@*MM3J=v0>lK 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

      aAT1NY+ac+6vx$+cERHZGrIsW`Ef zE}BIgJ2A%xB*PzGNsF=5Mr9zyF<`E4`yuR#4g^Aw$BWUI)+b0Gn*_BJgRyFgj#lRK zjtQG=Lp{r}%w{BDVRq=87{7(z5o>CpK-qtjs`k%Y!>A&Kkn@#f!-FN$XK(W-U#57(_*IWzDB)NlWAEbcYQ#wu@{> zsIVsjK}rHd@*pN0!kmALjKlZ*qljFXpX+L&MHs^OD-~hL84=T_vL|rgW10S^Q07r5 z2i#pH(mJ{Owe(ogE|La&sOL^?q|XTb&%eT-mTVLKjF-<5UD}>5F8E>`gpevP-N~X} z4s;UR6OwG=h%o*(QeyBYCG%yoo$42!xSN~E-yX&Bqb)%MKcV{dF7L*Okr=Lq9_bxpH%(Ef<0O%EBPURP$>i9h!eUWQTzJLi zZG@4aVwFDzyz4uYF@}#*Se7l}=B+J#EtaUlm3_GDcM#b2xM5F8GCO<_KxoQdqLnmvRq%C_ zB7N~%M?S*kW`%pxkP$sBg|sytp62;Vg|~GO(iPZ{a=S9A1%st@vx+<_UmVNV6V)a@ z?O8h%<76{~hlXG@CY*1<@JJo)H3s(*I^0Gc4enaS&3gJV5LZ&+Rlc{z(M4S-;fV`g7sENbc?)iW z*@XMD)3Q(Q6m*u$37ASX%ylAIp;-7-nz=J-6bv#SYrK$-(p`TCm5Xh%B0~_ECoKBY z=o7XzMOj9bZGUFCcWZ4dy4!9A4#dz3r8x@??2B{pJ_q|{r`@xN?+eZVO?Otqd+cbH zy19kcHqp|{=u$EKkdiW3bbCbYU?`4a4jMRS~;7^6u+H~olK+flm zWr7y`c_ynwYw34*Ta33{3|b9uy4u&g8Z-5Q)VU&Y; zzU{9K?S!BXYy8ibg5UIa2rEdGS7;V|Q{Pvv%oaVVrU?P5xKwdgW1tjnJc zOGXwuc2KxLv3Me}+-SEI4bL#$vrA2t5+TYc8(RTwvWl*$5K%KE^{ZyCrYYT+Yn)_A)pRHQt!~0G;}#injT=mP*qhz z_jPiSAkxi^boEe}A)Wfw<=9Flo7yqB`Of*^TqST$+Vtd{j7q84@s2^}^Zo)KQA9wh zsQ4!q>&}rSrY>Uy6H@PeK&i~RA)1MP6p|gxKZTazTd5|jjd6avryufy@W!F>86Ph; zV6s}8V~JRckkdtzCfXcmyb;mIWdkdYhr$J!*~|AUCl}eEWz)`Ch1}YZAb1*vI{y+* z%h5paVl%R)t1Q!Z@j>t?$4@Ki4WyGxiKq0u@54ox5Kj$t82NMWEkuM^pcEDO<5Kf->>4`tr5DD7#piO%t$#Mi>h(zo5M!M?{ zr`Z)L^$kaeSg;7}dNQ)-pUA-Lw*0QJ<~;mfheI67pGh@k#<2P1b5VLr`N=3uyE^#~ z3M-SY8Y}*Cq*p-*=nd4rt9Yw53uL{qp{aaK*b!|mE)Jg1=8cR?0JJ%LeEWIba@$_n z>B=b|Mc~sB9z`D@BE@D&hz@KzcqAAeKpE4o07>K-Ov_BM9xZn4<22dBP1_;#E9E!MpCqe)OE{Be@f-@4d_il4uK`p2lr zVG6{Y2?b@!@?!Lbg6VcrBbqS9 z66{vSe4KMmNfos;Gr#D%(^n6r`kmpde%2?{VVTCwXw^u-Vs*?7RAqc>6~mCwsqbKk zlp(mUNgmBj!6f}008yh@Y-T~_6)8Q<34nA0Lprs;c`YT%u}{~LLa{$p()mVOq~{$L zXSZf@L)-OMr`EmHL;ci&L(L49{h(Jf!x?5q1dEYaWg^~rk{piz2Riuqj8YoDUd~NS zWr56xE;LNVtvqM6eSBNBS~efjo8APEw`h?zN+ypB3A{Nw4j#{-Do39Atq-!+KR8~m zmw5iebcq=1jQOAAm!ep_%?!*;JRlGjpvxzqW|Hx>eT%KZxT(G;mfd`+j$(rg^-|5X z3oBtCs$5O+6WbrdQR}=$svQ#l&>mhGjKe=!YV}>z-{EC`gWK;W9;^ zMH7|58|VN<^+w&q24qoqM|G29kV0hP0_G*M;n-E&*#mS_!1QY>1WQ4`w+Fg>7&7NmqCXnvc;G|dQ zJth*fR2hTIn#DyWQioo`=W`tO`1fUC!E4~y?(1D&&CT?}li&y8$i_1Z;{d2j?k5%E zg^0+rm7SCJ1|g3P{(T@HOd-{rCDs*|k&Y_Bg1#c5xp$A8YMOa9U{!i6ea%6fB& z8;t6$1Rt^l9&c8<5sdC1C%e@OZ`hB$sy@ix*IN%o1}CimBd@(>rOej ziS+(TQ#yxIfZ?j+8@ghvOQfK}3pm80)|ovsLy=ENNr{Tp#MlT(aK2YHb@KsYTK3(3{O0IKaV(a+Zh|BMB}YSK2Cajlp&^8 zA-y5(^RR5umswWX^G)KE^Y2ovrsH$J zal#>(Ppz}-?P0^pwf$)5A^j)si$b`&(TNkog_Q5-Y>HTqy9wi~s_Vid!|k%DYr>-7ra#}#NVhCpF$(ONTsBbL%t01?b%8BNvEF`8T5xA(BiR+RV zMT72V%dQCv(eO-!E^9ehk5#f!}Y2c3ANV{tKRY?Fz~^ zSNO-P&6l7z^NgaJ5D6Y7x%+a>l(Q@$oImrW9`p)@+`5Km=Ll{6rGN}KgpIEuM0b&IAFd;%;l(7I_f`#&^MmIF|2EhVEswAO z>P*;=!-Pp$fk_TCUj|g|=laA{Ra22^x!S}Ug~5JXf?Z3 zEdVtd9!^aQJI%y@RYvX3f>lzeN@69?5lO7BRnHU|E%O&lqBv9~=&P&PSrX$rp;MVJ zewGcC5R+$aBB^qAG891sKLh!SwNelJ3Wf({+vQ5VhbM+oY*^`SM;t786ZxzDo-apG zWID|e&(?iw|JAC~4Xo7Yl^dL|BD?W}rz^m;ZxzAD>=7$i37YQoTGC;xL!X{i%Pe7Z zAK+HtaL>K-(1!F`)pY)^|7x}C0X zyab*r?QYH{pn`WDOZaEfA{FTP*OB*0%YOZkRm@NI=(4%FRoH=7?83e)FNXboMl1-9|L})WG8$NTa z^II+9tN!YBd|{3f!)9y8(Fqg!-x+i5o>AQ^c+V||%rIlOkJ8S4OQn32Fq8XVnYSnM zr4cc{QPtsuQQTTZ`Wm;|&xH`VOj8!|c7~8^Q)p|Ef=J~Wlq+gHK{;K5cM&-~g}=Ik zr%K|$<*5%NN$pyK8Y0guzA2)|N&O>M#|Lv4BOAea0!BWhektrYtx=$}-8r1DzrW4v z%SMRG*OL~nFEkV*%u7Lp$a*LYN-^YbOsi|%%T>QE2l?U;fA_OVb9boeMPwJdX$opo z=5D|i?dCj(TJ0@nE32});1p15Ke5nW2zlsIym6&1O#Ka(>I|&zTIlfH!jB4q7o4MI zNH<%VhpSFholDnE2!YmzE{5l{0!Smcoq4kR-R#>R1QKIK7OKTveGDDlaMic}-ZPQ% zokvN8Zu$zXn(+A+DG*}-zwy`;uw>LwMNK_?vSMhIC%6jY8ZwItm-I*H_QxQI9NDxGQ78(9G$eqAg(Oj7HLJ<-H zHOdw4?v65~yt>uSag?hcg}#$iolKSXJDN26V@=b0EGDmRXp-cP%m2rQ@8MP3j273Z^Zh3=3v>#pWt!U1g;Z^8DcA(GI3DCY)_sgpZU z3%F$VGM(rAha$N5W#fjy@d%FmEIAwo3$ewF4f85c_fd>WmF97A@En7yE~+%^85H30 z!eu`<7YaCc`*^A9Y%Z2gw9Im+t?1ap*do__yj)qYI4g`jOf(hH*6~4akk9IUbMcl; z;2`%iY~;IWrW)zkxV!J{n}6s3M%$-^F8-FR7?f;Cq!--V#b^f7iP=Oe0sJZ}+g$Ar zd+cp&3*_mpfrw8?0D#2F%gW1lFunJZK>76x=bNLQyQ7!EKGzZ@I;2{~bC{QPg=>-P zw!S-*6$7pOm;7Z~KByI%+Pyp*_o|EJLov*{F*`o*4xN&E8;JalA6{5+o-KRFsHtCF zU+2@9u_CUzU(N^dCtN9lGBDncD>s5CYvF5h7j&X{GTQ^rGWgowNL{+|etxQv1N1U7 z(}WWP4Zm(OY}`rVX-i$Fl02yimfHg2WEA?d+V&=F=hzpvZ#o~j4|!b$&Y!zp0xQ3v zjfj>BQ#(XN&t^qVCd0R-ge%7Qq)8#E(sNW1@7QK7bYT!x#xPdk_-yx z-o0gL2gIpK*%m9u%PlBr<|r(QKGd@kSO`Jm1KmB52P1`(4SYQq&JNp}_aF7?=FPEi zg;`bMWYvw81;IWnecm<@H9M(eiRX*G-bUzJ#~B6hmi~jV1@OkA-f%ltST8RghX}i@ z-q@Mp+9U!cU*Zkr!Z`kG{{1X2KqX(l4Y!%x*l@T=t7jn+m{GHewsSX20G5$Rvfi)Y zSU&D#ynF)f8NfPgb8F(CGjry)gSekDsuIHs;}fp8o*0tP&Iv(Smc$$3zW0GZR!Y{c zj}OD1K-8lfNszm2H%-i;kNk{7HxM?31lDr7qJ&sI54e;)unY&FleIClSW%majr{fN z@cz7M2arnhkj*3TC+o$>2ZM9X@rLwyKULGF{+JA%vA?8Bi6-A3`=lQrpmK*wEGi}V zg*B(+vY%0956!2ddCvr|;~r;CRm^u%F6+UK%j<&j@|4jV^4#@EX4XT>5*6OJX)96F zPHPjDc}BhGcN(JL6IX$7sP8gB!F@jVnXTd8uJ*zLVk=RN@|;+e~P ze9rZ#(VNE^P{v$-3Kn?$U2@D#{o@RvdjqfK`iPc#a^m{F;2p7S$ai6>8&tZBMcDRY z&AStp6i-FbGjxXK$<41o{+UQMCLHO0^CeVZ&;;qU&tI=56N%yo`d zmp+OR(`=!;^Ht&lTEXWSc)58m_IgA3VTXT#?l%6=`JCWt<{?2#_5QiY;6g!CHsa~@ zateHKFLHa~OmrUod>yrUcR$ry?i)6gxT^QL82xpee)=Jk^$toW2v$oP)O}0Pg@l## zcz4JQF%@{jSbbTz=+PJ+4AXhs`*XkIy2Y9qq$#fx=)tHX434~G*L`4Fvcc^S6!Sci z(Jdhah1~SQvm3Mb)o}`w`38-U!`h}Jw%VVHO!^(WQh5=*MZ;3%Jb>{coV>B2s8qa- zmbIo9XaX|bh1@u-fP(66Er>vdBfKc%NZb?{HmkxxRgxVWaqXuyar)yOwY3F872>>) zIko*yNx7>>7**%9er_eTi{IU{KP>o%YN~|Ndtp8dSY(g%p}q(Ej*L zirfJge5&0wGGZr=qMDEW%czF*$h&R$J!$0=)1F&U_W)kn@b#a-+A9a@~rBeix05wO!FW`;jnnwO-FV&s2Xg<%YfGbzo9Z#hWcvSZ{Fw`k@DY zRh14K24Z(!{xOpGu$-4!?Cr))w`2M#ahy4?+h=&#JRK(7y2tfM^K^82M86gve>I4C z=_I--K70%~P!DrtX(BhYoUW$Gx)Pki$LZsFw8Pc(eMKQLn!@2M)hESn@b5!?oTKg$ zbE|ys*seOCeNFEjTR#>4m%N>5D@cp=w6XS$MVK=OhiIZN{;%WG>THnCR%rrSavn-q ziLUzy&K~&=D9VF;b*_>j&i}ugv#Ge)($Oq*5K%>$MI9OPJ!8wgB z#~gEuYR=YE{);EZ$*hbstJmC%7oE0!o(^q7pZ*1Je4YEy%8WbqnIp$@9984V3^x{L zjD>~EaGrCB5@X(z$b%h5?+cf;y{^=3+U-Wd9N{@_xNwtLp1DqdS0t32lSDL47 zN%sW>7md7o9O*nR7#H3PJc@KlR~sLrm1f5Mwm&p%DJrRxXt{ju=?M6p;5)B%-)q74 z!yM}$9S_^6Nc_;!h85n&R$QKUbFPm&58IvI+l5svE&i#3;kY&*yzE!r%LwOP6P_0j zG_K8;!!SzaoVGKynIQ`69*pu?+!0E6CGcmdn$|rM0@ujOB994z6UNIGlu)xePuHs3 ztNAjICsC`#5J8(vF@&EBfK|sSxo)6K$HUqpilDypw-G2Qo%`*|zWaL&o!f^Fyf+

      tTzA$P{M6`0U?qQVhM69QX_oPD-*%zp7Ow!R;_m4mhS#t0{Y?m zC>8kfBFGI4VDRT)@U-y7R&2;Cth_d@S}3F|^8y`gs9MLz$|aR?vz}_E?i%&5^75(X z#!<|?AV0e|o^hYRZ~A&XuMM;|3wo?RBNPV6J=HH_ zwaZW?(rDPK@gaek%(q4i1>KxMPak3_bCWxem2<_dwVG)0cy-#OKQ?7ND;3TsS4J(b z2(a5EKFwpbM*EI=#V}z%gS2Pu2PFRR+T?13ny?+-^Qs@b;`4) zqRZGU?wSPY_4f4uxC9~HY`(_pxad(LwtPbGTlMP{@`}dv00rrJ!7^YH1<38U#hK7oNxzf&D}tUEL9xN+*W0{yOax4Q+0QWE70!7@pw&Q)twsZcdY3(+aurY* zD{6^C#R(C+LfkoTm3YZ8aTO08mt>L?Rkj#8CuZ(`ToOe7;aK^uhI$F;>h^Gxh}pS? zRY@8@H9CX=Cd7vGb2y-Gg8*4pG}u};F+7L|?mdnd-Z(|Ve#^aqfDb;9&cyZP_*dq~ zxo?g_yn7UHR3Pz)ot7%r zHw_+mNIeOXXBP;TBL&%lpa9*jx`!j*SciY zB>=kafGAGzP-@Y=-m=(r_yGR?-~aFM(Ou$P4uJEV$&`&_AWm=vjkSqo3V) zV9B~sS9 z?Y8hN4mY?oa}l3?;9flZx%(v7(^Jnqizl9b0|$?NiU7bFoPX-@#@Xb|8uIyx+JCVMfp2qfT8rghrS8SRsu1cte)%!ZWj4i;Bdu|l9TS2nB? zU#=2Qo*ErNo%B?`W`3=S+4GA8vXN|E;&9-K@NzapFR!;nAYm%cdA4?r)-l+yomX(OUOM;M&yyfItJN0%NvkGGtL93!l7qLH9Gz;_hEM; zw|g>YvS>hb-c634=6O)wUk z*`6FuB0YqHELQl6tkcXHM)cj>{FFj|Gp4_i3lgqCNy6TM1Ov#ttcwsj=%N`M?{eR{ zD!MM0qPqG zE!sQG!;5YqJU-9cz7Hko8+$Zz1x^M4J0uG*U*_T`TwsCEWiLtgmRuvyd3}AAct#WN zN7E2?uJFr!7k=mmh!eJR&a1;o*kIbONfD=~rw`Gue@p}T?d!c}yKT4aw%xYdcH3^- zZM$u^?Y7;v+jiS-+ikmTx2rV9;T8$F`VL`E|BRifu6FWugHfkWof;b$82AQ#{2O%R zyXfZ-p@d`DZrg3UZMW^V-L~6y+iu%!yKT4aw%xYdcH3^-?HY}+q(#D#PSeL1==V>X h&E^lTguZRob#Pir!>@+xw*M(pyPJC-F};{ z>qB_0ykh0R{{4u?6VOnG-KJsF=FLdO>UAg<3m83d9MCj4Z8jcfLsNcr^L$kwXvm?)IXXX05 znZ|4DdeJ<*dXJK>t2?N3xzWvk)P1?Va-W*NU1t3qZXf#BuQ%#o)C9qS00(q-o)!IW^zboOYr(Utg8+2Xj-*fSsDs9`222Ud5qjg z*BpFcFE`ux044anb`-%+F2d^@&!d-(cC+(&Tt2o3?_125;9$Gxc3mDEg`6~;4u{JQ zyGw`D?ojRNu-jC-+iebXwhhAT@#FBpBZ$UgmG@$`nf1MT^)OmnThOT3SkL;liAJNW zdI^z81cQTv7#|;3&(_w~#^){?@563Kp-_O&=flXz2s|DShK7c4?AS4N?z(mBaOB7l zc)eb9cXz8}e;2$s*k_y@5;8U*xg8K99_m3KTpVio6FeM?lmOpkxVqG<13$6ao|) z+)*Hq6#2;%c@2W+h1<8|&%b#W0l8fHXsm3f}gtm-FV=>hhV`{RZJS? z)BpTQ+;;md%f^=gu-E6U0Imi4Pd)V%ve~Qx{AZti7Jk1U!C(-F4joe0_=7+A0~|ei z6#w>b|AwZfCcO8(@5PtC^d$xQ*Is)q{^oD~2A5rSnL6)+3ogLD_uh-Ht}Y~#Nem1O zVDH|&N?7#t^xz{O`3M4m0De@(dd708j6@=#1eZKht>A0)d9AEmM8L}@m&#x5aKQ5(W^}%>%U0HK_W&3MbbnZojrhJ@E zrzi^li^|J2#Q5t3^cCQXW>0NPf&FXc)hljikb~cWp^%^8?^Yu}P0ey7mQyqWm1<;i zd3^V4U%`7n^kMW5ufh+${uQj*u#qp%joW|reV7^>g^QY)R*qs**hh`tLvZ$BhJ(3~ zbwZ=YUnWFD^N}m%-a1l<2|H32*#RCz*tAvDcY0>o&qMK^O(2C&`JQk zt~G@DLI8)-LCm^?C>8T?CMKchqpW{P(JW3|33;OXVwPHUwv1M{jwUDI<@Ey;3_0$z zHyE__CV3*2$3aqAc88PT&3l#dIDY&TF23+$TzkVM{F~3=^$x>@H*Zn|{MaC<}*2X4JZ7hKZ2yA(ghn% zrGbfb8IfGs$kXTW{H|S?n4QDe#3^#~WeS}H z5^+BFe3}~eW_ZchPfef1=*Sd2?A(2Qq&jvVB^A?(;qy8$us)1UH|Xf>o`z0=>)^hg4maF63IKN*>AW4WNDPb9Nz9%~VdrBL zm^u}Q+vg@7K`KTMOY^Cs>BbYP-}Mj94Nh`Ujlj;>z4Q#BZ61I8aRtBv)Kd2B*@J)h zhksDNfA@EPSM3w?UBF!Enx~(B8Xx=E$CO#0&*#-XDe^6x{-;0vY4x|zL~`yAe((d_ zbI(1h4kBQreD<@S#gk7yseW7AWWQC1)0MLU=KAN?&Y%?3YWt zj#8oY$1(t3lb)}B$r5m+tER~h=ZGykpMH_F#0KoR*&A>JNIH{A&NEUZN~ri2Y-wg9(zP_xrLIU!H<*AJ`qi!FW|+x_7)5e`7xK$a6H+H zNTH1?9nrTKC!LWb@Y|KZ$&-tTP#ceCby7Y$`hyPTge_}^i&mVbLS>Z8C2F`)eqtDG zZo%cD0Fp%?_Qt#zwe?Y>?SeNo4SOL<-aezabK&ou6dMUTJq7T+#Z5=}Uf@X#qq&7ZVKt`Olh3+fy( z z&Lt3gvyb}2%#|o&+b?&(14h# zOK}{JL=mJ33E&;n(5DwtaNFF7M$5>~CgBb^ zFh9pOT;<0MpQWkb#_(VZ>6kpS5egSRTT?gdrL%qb3i}6|E1JD>*Q)SWBb3!D0_Is# zEH00`zA=Cma8M$dB)Ud8cL80|#y4!(pg{N5TW`gdEn8GnjST2eD5Q>&XdBVQCnhG8 zM*rM%&*3+I<2UeEfAv?`y?eJ398$#5D*{ErG{5-8FJkT5wJHQu?k7S;qJD0^`DP^m zT3T8_rypkMthPA+a|Q2ON9@_0TMP29ariHa5QX2wL=*b@x543c zqO-3Zw$&OAzc7moHS|0w8oR@$oTP1SZY0yByE@&Zw0Q4CnRR1x@KM%m?8d@kobQC~ z%>7O`pOr$Or9EIin*sKv}kv$S>DIC4j z)!M#!^X3Xj-g)Pp>RYHBt9<7>->Ke`$9?KkpQ;=$z+PKq+ne9~X0>0ehtp9{_1kKn zt}YS7V=6PaQO@BY2t#mv|!F2CjqeD~{L z!)9t;t5>bX-~Qi^hBmx4h%0apN1`h$kO?4BsM8TcqV6@$eERn3u?(QXVtuJjUW#Y-nr36?ACYH6IQU z*pJLQkn#5+ke;VNnNym4s#HWQFCmvD9F7(cc1nmPu%XFe`T)uXU~8I+?3ty8KSO>w zOc323^1((;aDOUHx@QBa2U-)3z>0uim2kTkgPU4W9*NQ4Kdm0Tu39prDu?#x1i^%`xfzfOIrb;_QpzOR*+US0$IA7$aF4|@vmiiSs>?>#^Bc53xGOpj0D zb6@*U{NQ_cKPQL|ZS25F?Vj$T9A_ieOJl>b$LZ;>r85fzQ8vh+Kc#kDU~Di_CTVf8o&^WI zbZnRC#7-`zSf7mY$Jl)Z#7Bxqq}gV4i06x?%JWnq-*{%3?6!G*FJ9PtQq2fH9VdM{ zaH|K=b3Ok|$JPsidMf2i*KYJ&XA(YVd+pcC%P+41{*SPD?IAh|?P`{(24hmvH$L_E zIC=O8uDJFd{MH9Pg5Um=k78hOSV2WzC%sZO9Aug4LpXKpIDYAWe*n9m+e=WB$SMae zz3z7GdHzLw>?6O1kN)yURA^_=w2#&%ZYs#6e!yk(z@&x4=4xgI8A|MYaXgbn<%0vkwOB=nl|fY&no=4G5@t z36Keb_b!5FlP86C=Pb4~pLynHDptg)!x?JRnwpRnr8D-tt*bD3VwS#*3}#QH(Xqjg zi>^8!z3p9i{+WAlU?2V<-I-k0X_)UxB>$ zaCi$HzulM^J&CEwaSE3bx@ZZx@^%dRJ&*{}v5jqTgy}<}B_@8BsnH~o2V<4wjG4?r=X8-$^V46G%NLB9&ZYn~xz#1w?T?Ft z@}<<_m8^GdJDiQx@>)4_c@6M?gvD-mD4=)SoCHdzqFm zYKq$a75LzXKcXCO59~gQ;^)7L#kqNW{Ij1ze0oBiGe0qfYu|J&ZvWX|#SOPzg}cA` zP5kg1UsWLE5I#R|Xr1Cf6%VRTjbB1S)1sBr3OEs?mYSQu^HVbf!yqo|Y{6x1E<80J zz_F+oiL7YPG2}u2fhOnjQ?}tyyo{5nJUTo!kbcL;W*2FyvI%k&HpH*FbOtfu@FS55 zXI}-wIt@QVp^+dJ6{T>Ck@gx%!*&U2oVEbc)uirNiz{1Q?<-i^rorfcsfzCQKH}z2BHsR41PojO{A&l?bjlC~Ejd0kD zeNzei^aVYbo|;1|t$?GcII@`{f)r@^9Ix%=8<9z5=_0S=f~UoYENQIlLI%$~0SKrt(kM5Se5Z={ORD!;ArKONXsdj8iUc3ygU4e)=2rC5@% zJ!-|EW=PO{=KhB;IWdEg`53sz zta5Sc53I{UYpWtB}}D-G>=4N7E46~(4a4wN?%*@G8352 zQI}7H({Ic=jSnTQAU&>L94v zF_A2imU2Q*C6ohqguapy`y_n95KbODi5~g`F1olA$LT>&jz=&ai6TP~Psd{vFj?pn zE=Bq?=)-26oe1!6e}InJU|uD3TbRnwKT(3yb`9pHi4t(+t z{z3tT-R^?d?SsqVMKL%;V7J4UStJO~kjj?aNoAx7(vsswW`#;pwSdc*ACTd8nRQD! zKv2zL-wYk5GEn= z8#b~@ihxldcZR}8CQwWCrH)Xi8vzQPL_CR^V^Q?14P#(a7Z&D$!~&_KR*m$}EV^5I z=%^j1eDcuW9x#zq|(cKf>ZA$hh4t z;{P;;wQhq=K9ZW38grA&t+eG4`WmMTbQ%^6a==gU@AEs+-_wgibW%BC=cwIhO4LNj zQ49Ec3GxLxTJxk}9CkW}3Ccc#f63R1oV^=%I&1COIo@-gKu>^|bi%y4X!kNfG~l$8 z;t|KLPENk4GH%Kgf%$X-r=lqghW)sHRVUtHb7R-66VK0hu}A@yFUFB6@Se7!dM*(t zCkXx%**yAvHfsEKG#Be4FdB?m*)M{lrH52as~^*o5#%!kWsQvPBbY`CYF{CcBAt?k zKkPCRqUqwOEh0S~hZZPf=ZlkYxm~cibToInk;`f-J##Lbgulau8Ja3bpPodx&57=- zH>u=mvy%yUN#Sf++l$HPMlm;$!j@G{c$(K#)C=1so1&HC=C}BP#eH40VZ)Xd=zKRt zEyK1B8hKzUk60zG*7mnkibjzul+o!YHC6N66-^&2N3n=Ae0ot5!KLUoD5!8u<@hy4 z%Boev|79tSU(NDLIHg}JOUrA3|066ZQUnrgA|URSfnJtW!Uo_sQM;a^X5H_zt58P? zee8A;{G3iq(b2ann#ToK-30q1-yt27B;Q_Ce0rLKAwdw3NEO-*@Z0@#wCdE@>3A&^ z;7P}nrk`~N;qmrT>U6_dBtMfHr{$1AN}P!FB@~Jpt&K8;h4>h#*_u7WN#K|G{Ns@X zP7?UN6bxHC+we2%?U+p3v2!+zqfs9z72d0yBywle{mJy;a8k!1YRXw^#Y?D*+L%SN zIQaaX!#=Fq*o+tM8$+naje*sDv__oDd792-sJ&-#-F26sB^+kQb;3jIu^#yF4N)b;_z!V*(0aM@xD)f21!2q%p>>WXRhClpCPUHcYptBeErTx zP%P%r-Q9(|@BU#WbEZtnl4NT#sY+5ONLmC5;gm^Pvdx-kDHEt%Q>E$)R z{}GmEt)%j~OtZ5F9d3j<7-cyQ8RW5|%$C)0inNI2k{3XU>1DJNS0w8sDQv_d3p}rt zg2Ri6Od4JG3_>2EWip`8lv;Zc$r8EfLPDigaN0bICn-q8jy^}B;)Bl{M$y+o2k2%v zaxsK#)co}rwfekT1Vs{^rHjJP%WT^c{G=}I)Uw42D2ru4q44y$q;RlfpecwqtqSp+ zAijB=)Kt>V>lKhJlB<^c!q7xx#WT|sVfqVtSNm}Exdk+L1hM0qK@1M{K`*g&Sf5xd zVdSWn9!uV7KE4QFnY2$Ki}}R@G=kXlsTAfTMFhGC`ndw!Ap)D-iLl43ghP&?-My|E z1FzeLxw$DcHPiV@3nu6b!rk7F)?3Qx*guZ>Q&Z?76_jVYttaQdrZtSa_D_;3%2NQ@ z)f@_q^v)joOFAZl=;&h|^R^|9XiLCt817M8c_8FemV?u`bjY1)#_1VY@U2h<{eC9YH|jD_U9kRSHAoO%+Ai@eeZjp%A51pV~?r) zH>0DY3fN`#tT>7#p_&8&NHVn_XTX0A*kAeb8sPs3OIC8_NZu@6D1i)ut`KqrkPc@X z$g(4m&(N8h<*&Q~TcK!~R|{8XH=gsg1jfq+<9toxy8YuZFJCDk2q@C70gO+pF^5 zv*D1*##H+~{mdkyC#TWc8bFJdrZb#cGO3ca10nQvw%~7nxYGc8wt<_x{EpYRB1Wnv zJ4ath(2JHOq|Et+lt4zK>bt;^`&%@vFI#Yc|z@+#D^tTt*zx4*cea ze^yywKEDecbX5P$+it<1{oTKka-y@`oaHMi82ihv%$wVkc#ak#MH4`Qyo7VcsWw)7P1Ge>Ht zfOx))EH(6GQR)h`(IM-1h{kX5&XUSuE|nuSq+?%X5v#&>{OpzxrV}MRGaJPI`3UK& zx^)&BP&(n}Fe1?mfz?OL#7SOy0CV$E_=7D-ERNy$$x(Fow&AG<_mB=x$--cm8H=Dy z3&$o-Ro3aRcIHvC$?}6vxLA*_jxKWiP9)zlsqMwFN zV99yZ*TMF8V#l^&yzi&4H4dkM5^BfF$Z6%#mwY<{@RBFTD%ScJl7P)RroJ@NvL!>O zoGV#4U&(T|%ND+-`M>n?BLV!g$)$0+@>0%ebdB1&ob5GN$|2HdLdcnlvF56<%sO1u zd+h`x5BX%fgsA9w1c(GBJ2g%LX$pX}BcNuxMrj#5JkI^TJnTK~GTDuW#!3#5S_$2X` zJB>m2A{?F&BAy=Z>!n5-BY@7Kn2)MFFd3dSoibL35) zI&~h#Ws>D#AN^oElnbA$QpXl^xN0bbW1cM1(GnaK zaNax#Icna)Ru^KEF$4>>OP^4{(;=LuFl_4SrU13WLF%Z8m|9YCN&i|wvsL}g6NbJR zN1p9_{DFtjmb(ZCAKZx+g7d@o-mj>cH($4vz#dlTOifLx{P|(}IYgru2d~^i5}!%> zWVz;f=bfjLs0m=paRT6DV`It^5Pn~Tf}A5%kR(l$>qx@3XP$XRSrC$pZ8a^X{{H?- zBDPnhXiMATwTV|Rzr3n|-zbjuT+*r5UT39pE}8dUN~ui;&}e(@?=yBpNq$z2ky?;g zb+r2*UOb2ey#ujq z8pjFt>!`^2-2Fwq8G`*xF>>z-$HYsw_l2>~wEwg%gFE9M#WSSC2HjtUO9;Pd>#vnNknHznZ+iM zCLPt<9Yj-Wi;B@tkjEd7&STxs2B`>2bbYio^JR3#c98~Z?;%CyrJ#w$DWKXwwoIkHSlXFZ=q{4Ltht1@ zWuM3O^uHuF+$yssuy*YReDUFj@U8vF)Pn89-A#&`k|KaCX_2iI#sb!o6JOT3U07I9 zfG*!wc1>~Owzsz{OF)E&oG(H{gn~GAC0nOh3nDCJ9bKuD_yy#+S7n7fZE3q$a}{1I zuS|Kx0sm}(vC)+2a=Ee&+i%$_3I0>>Gh}{qgm6Jd*%xWC1L>rz|;0pcF-4 zvyt0&CP7egD+-Cspw@DHI&iR zgkF_cO$5~mS_BWyr185(1FTqxr?}@^`!Te-A8&bIH=cNW7upC)UOIC%$&VAVp>v>v zg2jfApP)2DN~)Yz{((!bJdfOX4%rJ+$Rr%(t5a}z3F`gyEoibRco9=4BXEcLzDS?7 zcQqpv4v`uuBTiwtX~TMGQlx<*h)Vyh0ROIc|>Q*AiGYLfK^O%_6wezKA8tY1N__v+-E;P?5 zinC!fwRmuHdII^tS`;680%Z!`kT*zrhmLh)x|;%F(Z)MEIx2l~>(;Fbysgy9QiR)I zX_Y(4x+z68{@Su`-8#JLrHN}DVp zni{zZAEDesOCZI8-7b0QsS!tbo8x0gu{sz)nSvn2K`p6^Z9J#hL9L7q#xyA*0pOC# z*jQE|FAJ#1TDme#sEHcCBw3U62my!WNF#4g@QV@9<3%Sa94CU#6b3_cIIo%1N5GE* zv0h9j6Yxo{em%uHX8BAu6~dX5S*F78tJSZdB95}4!<#G&24wgr1$ zJOP)_fuZ4k%uX(#In>FgkI_*&i)effM~+M(91NkgJqx=li6%Os*KQnAt2doIH3^%? zt)f_p6i8lz^%OySpsSBmj!(^W?(OP8_E?nu4j(#)&R2r4IoL++m6j9z5wod0*1zd8 zG_9Y;vtNIl!X$?%!8=8Nh>KQ}o6j4d169%;3x(yjo0OeqQ=fb)gQ?W zn6V6@_?Ija=tsaso<^4}jK;}AnYakZ&3c-!S4J-#f{8)~V~GSdH`}q8&!S9+ry#t8 zpxfpQspMbzQd*Me@HgvAfhe;FDt~`s z(ShT!Jh}sEbbEEIZl|-j7{+w29Sd33n+`<}t(KgMV$qbwujZQyeO1?P)~9x+?bk=k+*gr z9T&%_8xse}hm)2$|CY@-^!)=EqhnU)q{(Ec=8gbn=c3fS9m>Cv^jvqO2 zoV-7s@O19V0_QG?kl}N=U3HXBHL2#Z{!=FJKSSZ~CpDJ)v;RP-y$hk_Ebihtt5@|P z*uNeN8Tx6a=heAFyGR6%X!!Ciz<=b(5nO-$^=kRU{rmT;uTW`(9j}4? z%PTJ%@XtnjuLr1G8 zYxk%buw??X&ru-VLz+g#)Z0`lU#I5BDCvd>HS@isA`1C=YV3Jxm3{>_ClfIR#1YA% zQ*gp7N!-QCC-}I@`)dT8l2{e=5!hItfK2b#%xD{aOGglmJVuM7m4Fnm%QnpfeqCkF zT$Bl3kqiz;?L4MHtv`=GkCPS%?G~svL*f!#yREx8lAa8N9!X?+v z4(;g}#9}N0pVyCEA&>dUEXGF;!s+rV$Fj-NhLlApNO~rXQ%9$GFAC-yX)H=PyF+s3B(a{>#L3a)m?s64$t2O= z-bSk?g2b3pMc7E}e5vHbvkxAFKj6Y(vkNaw=}K@m2>??VNyz6U-`N1285`DZQP1?w zTdqJC#w39<94m8}P-<~Q zN~55Q*UGt0;Wn3s(a~1&J&wWQWo2Ax@WZRBhOJN6pgD0kjc`5W_Vg7t-ii)vRMKe zoi<}?yvr7V(?QLU{{?LA$P!d#SwpWqL!iv@xDqw#1gV5L`E?(3I@yZ(2=e8O0%*G} zMF($~Kwm~DNoA+KL;;XNlI_{-aHENQzr@r_s%5)GiV!$u9oD?eq#}T7;y6}w19Sz< zA_u0aF?P8L`s9XBkq+_mc&`Sv)~&RCmfZbVCXcDCL*|_-`l6X9x*YOEPB=VW1WG~tOmYp(VHb=ogs)@g6CsSx@mt6X!YUax5BDha4 zMBoZGlhzU|p#`xtowIzOvKY%kY6cUF)9{gkYwvPk{CE;=O&+Z33?c3;W6ioQ?0WVT z`d3pxIg0q*|Mj=z$NSZ@y#4*Zi2TGM#G`ZYkV451^rD=nvztP!Fg?jZP+j}B-Zxa= zE}n}o!sSQyLi0_bY~O%DiFMp^2p^(vq`9>TJ=D~_p=LPUjrn-FuB=o0lTh>qmS7|Q z*=u0`(#tFAv|Wkko;z_2$L_lWsiRLIK}X|}2x*4SF05%4&Xg+ ze+%C8u}`aA1qzr*WWiX6Q?GWUg^`npj*kl5W79R)($o&9?Q)!=8_d;&q-#l9W4pru z^~WE50`LF%4-+U$mOI)rD9y)Mr*nU$$JGEDG)*1tGe&O=W_~ zRJiq$(x+X@$=K=ZM}&Zy$d2&dMHR-mn9UIQlduQDa|odG)@|LhmAu>T2CI|Zec=F7SY#}urWERe;rT?t3KusO=VK#-;om?Mo7 zXLAL}Q%hz@$#?J8pcViTiRD%47YP0`E4L(>_Q|YsSBu25lRk16rg#p44sPCqK8tee zl73Q4gIPt|=%&~G3^uO01S8|e)WR^DP$Q(A{C;Zr;&`SHBa=>1Y2f>o$RZBQzSvke^=T!{|+_baaf`Kw=E65ub> z>}$ZS9`sK>|1`e&d%uqECMP)>PGMF@5ct3@R84c8?)c|G!DWfp2^r2k!cRXmuO8+0~MVc?z>|4_Y=~fV?||$O1K5$wHZ1fIWEx9p!_( ze;#{c5`ai;->E5~Big)h{gPHWUlJP1hIUGV6ip3DgFKxnsJ2_Ah2doz#|pAa6x+3A zyeEsd7b|I{sI30(HR|)@R?b^}PKT4qaif1j;~4d5B)WtOY-Ab!B!S<#_`*(C&h{FO zqWtu;4ER{lS*~eV$rss(rfn46x6-}OrmjD#^2%uVX1r`Y*k_`P_~FO@m}+(w!9W1M z)()hTr^tO~&`#>XCetNNLD5R>Japj&=vloU{`OT$>l#0_6Eou@SXhkF3ZBRMwS8E< zrGpxp2ZxV`aN^V{a=l66S#bN-0fc=XXr3UR-**_YbaR>7-@knPukn@7ejVvV5*^g$ zM)L~_yd+n}baJA@a2QkB~m0V0!V3$Zgq3P0nB8X04Y?T@*PR9fy)`K$8^7PEtCg z9Z*&@i!@u5roW`+J!;=b2j&sq_*FL+?v4o(`Qc4?{Fz0p-`s*r zNMVfcn#F-{K8opa3L-}rJgGf!W?3HB@MN-+!}&jJvbV&&*Mq%sn7;z$l>**#Ew5CN#JMB6y3ciq~3^?uAo*Lk%C!7Jvpt^KxsKl_cZVqta+?X7e)r6TAb zd;F2t>a)~0fE>Au35JV`*y#e0KdP#55N53 zU%(yTyBFIo+>T%U@XsmkdvyQvIPuJ#b~#en%m!LG*Hd^6Q;h*`Z?(cbP(o4 z_70>R8ES(WAwMX9d}#Is@I>nkNRU4+wFmKFdLEvn6Rk~U^j>le<_oJ4e%tS0V&^O{ zm%=j1!TYWIdr`1gP8xp*J1nZ596ZgcOlk4h*IbI7}|0To@#Hw zi;u^Ujo5MMnFwri6L`apUflZT8*y+?2cCcG1r%IuC`TTJBR8$mJ7h{w&Sk*R_GLZW z4zEL5O_%og5TX_E;6z&a3+xU}(MLjEdFX@i+RMu{DEY|bpkOHYKgN_7piigLmFKsj zb2MYgE2Dk%mptFbHBe#Eb)>Sq7aem``2=Z*G##)JOl9KKYMs>Z zL%8M*x1qhK8@qPy!?ka`6~~Sq#}9sZANCwLPBzMp?|$nJ1^9Yo6eH8kq-n}%iN`Be zk2RQ8n;0HjrO7)r^3C?3%CllC#>tTvvFKifC-p%JI#MOA1DN0aByt4vwqN@lv~1mk z$+;|YU%m?mpPz<(KC1ZpQX-2|M+n(B-wbqzV88bVYJJ$TPyG#_A&*PGau4!jhcWZM zUqc||$Nf1QqEiLrX3|*QNA8`1B6@5F`eS=hSi2VIZ{3O@h0$ZrJqLGa6*6&xRCZjo zmC+eBwQ!0y5#nkIhJIVzLMuI%#R`S~1Td5t`~F}cVk5lA)|gQZSOl7W+?<>mAH zDk*#ayB0}tkV>X1+I=Gm!4d*zYx2L+8vVuQdpvT=utUfez|;^qAS5MGSO$F?R4d#UrGNCmwp?|2>H=|=9k-N>AJ9)q{N z2a(h)*00}=2mbjh@U7{>(8X8bx|{lOj7HGjXHLSAvcvE6qA59t_+%2%1=3idZoUU6 zCg%CO?Q&e89mX6jqICQ)(z%?PK`UMVI6b>Adk)*_lkEz+RpiemQe-;``q_dkZeB*v zX{3c%BKXYqus}Z%Pmta-CM(ryy6V^($NZ0Vv9$GC4&HiRO2bMpKut7QLjbCqc$G^; zaP)`&f?Q;bz9A^~TUxrq1Xi_NQC zh|QNZzW?fN0A)kNdRYx2JgJm{Kqmp!t3X`S-SCmacS?R=Er*$+1B>M-u4oUS*XzRF zlTkPwhBn&jA$aEsn9Ip^bZl&~Ba$nt(9zXvhOuG&Y8*Ur0%dpMo_9f6jqcS_KpIxlCqqC?+S-?8zZTi(q7K1TlX*HaO<7 zvCT^g&5l_<_zboBIFWqULQVnQ>-+4=u^e(~*wF06qf>ch-$>|auDrC5SdLpOT1Po? zrJv}fin5@W^|R`4=Ta(z(FEtpJHg5hyJhFDaNXM9wV+@7u{8+&tz6TrQ@sXx^3iW% zX8&XGdyNHO=y`&J*5O_E?L;w>#vL`Qu3=F6&nj!=wJEn{g5d^i#&(0QD&!uh7wXEdeY^3$q{$2muI%lQ7>(8@}u>k&b z{qA)ALqCm=z`FiQzKYs&Pe);$i{Pj)=LGm?Gx%z^WwO+tNwGKypc*v|s{1PUiLdW` z+;rPj2(@-AM{eyPv958p4|%%n7rf~je0=j4RJ!48$)T1IbWp322%Lm;{9*>OMn-@j z^|PYE(mN>;JVv}a)NItK)SuriZhIw>)Mr2UX*}}q<9Ldiew-SZQ>YbLU5d|HF6PkQ z-noJqX@*h?r9;6JZCQ;2t*bFPItlm2O~|H);0ZQSn%4MHK1SEeHH?+nbSj z=IijUe?1moxDz(H2K^f(&JfRyA^b#++Fl44T?~x^sQlRDq*szy$i(0bva>lt zD7JOtjsRjnoxhW19Hte~$LGB^T|_5+8qRd}Z${N&)gG^hlnb-Dd3+Nm6Q&f5T+GsbcWFnKsDrD5^Jp_HP z--}G9h+`+F@xcpQ@bp*`W7A1&EF{!5BrE1xQgf0(P1;8$TuJ%_nOSQsdLn@b0``&# z^K8a+Bl_t~=e*Ri5}k9V<4(7KrDJOEak}fA4Y;078`Oe+y+tTxnGmb%=e6O?FBSA( zJxYh4iJ7FD$m8>9h^I;jdTH|C{%crw`HecTtU^)~g9 z=Qw!qXmui%&^3~JPBD)-K8d`_+P+7^;D4!mY+29eAZhCPzBfDDnN8CvEj z1=<3p$mCC@%J4fxAePa@_uA`oV!-c2BCq42(HO!`8Y%_WiGQC@%V>X8tfZ=0e7a65 z{h+ol)qkH=sny}v*j1weHpd{>&NUhy%k0*!tp>h&Jc@TqW+qCBu` z6isZacr>m;Wktx^&54H6h9CXtN7ea~C{4Cqdg-MrYQ$$#8c`uDU8j*|TCcg*Zd*xv zKhw1v-T$Quo->{IN(rzB2xeAh+!HOdoquAu*txY`FSXtiR$WrCnI(m(3Zk!ZrRR7OD5QzHtY>|AqfVkd%Zdrpsk*-MJ&1lgWZxU>SC zE*F|ei}|$-HGEPbMQVTS6y;J1LG2iV<#~)fc!ac#&_V@hp0%(I>_Fl2ZAia316Mo; zPb#HWauTyX7M;f-I)1$_QZ%tyWQ#EZ4C$Hd0-d!nxXTV?%2^ecU(!mXY@9~oHCjH$ z6J@X}==VF&<+EewLLQwSBX53`fInL_pnjFs7%;3-YYx{AirQ_B%8I~XTN#jEN;w+< zsvoSi$1K^VEj?H5Ye3~xICm59oh}=WPNwj$-+KX_&az5P{r4}Xcz_SFBn7Xj^wC>!&} zI9&?p`nG$y{96NRlS6+Fg+E(vC zdhx{<5sgOG(rmZgcAHwDLC%qmCuv(HBchn8*7YPmw{%+Rgp%)jZf;H;C)ojIp$7ps zIaYF=NTxtBb*00fIB`OmzjD4rQp930^;?oqH7df3KJv&T*uH(c8Vpi?;~j6twRhg3 zmcJ{Kd-l?iw!~C7Uzpau9Yx7^-_(n8YcnP$=Fr?tic6DaH}Yt@WG!-~^AOvz75b^Y zNI!ia+^I1%yUS{}tk2VlS(iuo0g7dtvGy&`4e&-y9+~(gGhr9#e5RAo)&{NXGI)2q z6UqKz*!L{LGdTy>$rqpnW#MiDIH#0pBTYXQs7~6a+ESV8YQSsKmGO+e2_Vk(3$DI?}pi%GA_sSaEQlsYA=+FpH#& z5}ATZw$_l!Q6~VE*>SI;CjU|Zpb_ZHZx01%N6@3FnU%EEl}vll@aGeGeCEM%ym(}u zekcv?Jt4$$IySQp9f;)db0Fdz`3!cchlY2;i zmvJKCFJn!{&%uKS)pQ*=0DFveNU_7xljNs%EXEGUOs@`|seM&Qt9N@Bw zk92U!6eys6@4fe;ySrOyHUjL@+2uSDA_DxDpb)2){1*OGG$Iiul3h@)SzlyzAc-Hh zC@Coutm`i=#*m^=Awh*9e;ju;0E^PX95vmMk8epiU&@>JANFa$DX6f z?xTrbP_O2iZ~^N&gNSE+Nav$iD5O+s<1(G!Imv0G3CROA@p~>;R)8z?fH?JLY#ZS0 zxeTRKC*d8L=gWuy3n!s9)3F<9fmWjSpNaP@k`IKYGS4ftPoJKx(b z#7Ox#%etb0B*SOAm{;i;3c9WYj>qOul!6F4kEB}GjI<3F#ib%t^u~S1Do17$xO?v; zCg_Az{ioU~@Do{T2ebL@rQhS)^_{q4O}m=IP*DQ3rBNjHW#4ENfBV(FSV-hB&>lpY zV`@H;Ml6%3-$YaIB~5=#K48Us(h&$|0|;5 zucYyZWu>KP4AFue4?X-m{8vAN+ut#)gv1-)_(mK$bO_c%)IY$sZQIlmYhrQ=KnwUv ze(xPSb|~N$%|n3w&2N6Q`j&gkl51iq$bQjMEGLzK_=OishM;iN#nQ40<42p3u3e=3X0{EMaDBS z9Tu|S2_1bUmjdMS!N*ai5YkA?XvMOTrkG&kaEvKOG(Eet782CJ+we%|FuC~{Hgz?@ zw|Og(<}jwC6DXB)Ds^*KtP1)I1gso3Nz*JTl<;k!fJ2H#A_Dv#REL#Uj5>G5y-VSG1&Q|HKH4LhTC_v(9jV6t4pmi zsjwj*hx_@D!Vx{F0J74o`0rCRkZz3~h4a*%$X@(^QEuM6B28Fd&P4#catolK8jfjw zo}EwN-sgAH9c?Smw3}#-dc$Twlrwr!5dXrLdj~20JpW0kJT}UhleZsYZqZY zn+29FEvL4KDSNsifG;1b$Y471-~;%;b(dm&90ojK8GxLl2-sz zDv{Q47#@6~0DQI_=HmNN&S)xorDmf>uk*XidPNBW$!X}pPFg7o1p65Rc{5sRN%e0I zBA5Z@?|1=w9{oIpND57C#zoRlnUcg;IaTD6gfivQMSj`H?bESL-$kKh6Z=gqb}sWA zq?BatgJk!&FYUNi2aTrl_~Cv!sY|-4=~x7}soa~}v~z&ovjqWd#ot=P?Pqt*8Yt50 z&ev?}IS$Vx@W8d|f!4n6(7#PeUYhR1? z9j$PXlF?5dtz1X?!l`7 z?JGSxL#JyDm@>3V&#JdVyWo1PI{6i>ZH~ewsgennLGtGwYR}D1I`Hgn&_$;{LEa}# zenk?oNjRw_FiV$J0td8uGFZrp(BoSv%|KV{UU5$`!hbuES%^{q(CNo3b@X;%BQ2V( zk9`Kukmr9f8CTcv*hF0DhStp^<8-#S`(3P8iO;|*7mfTs!spA|mW-9c-4~QKp;bV< zSQk@owat^q=M~t)bX?XJO{w`dqyD;vT6tiN_zIO@r%>zGCG{GUx$;l-*xKXj&#%2# z?X}JhY_!IkbYuI@u|?dvt#=t^)u_*0bj=Nj-uD+c8j-w2YtUjJ!p%24kJ0fK{Nr6o zJaS|P9ZdoJ>um<7-rL)YpZmF=Q@=&S7tUQQW2?x@S3j<$kyY%Ndk*%+J!+QvPbf^B zbFpRT;W+*cas2*ssFOgeD=`Or9}`qXg2Dy^Nj5W~jZ&q#ql$Z&-yl zUbN1L@UcNn`InC2^fsYq#w@)NX1=TOWRP&)Y{vXOCuTLw;d3;yk&{sKj^Lh*&Xax9g2&Opm5Ol9xD zk>jL~=&+nWIzeB+U_&!Y1Y()Aj-Fe9#INW@$w*c-e)9oxC!T=TyAj{n{t-NN^eKEG zbOPz*5v&eTOXf33IyPClaF!Z=G;2c`LiuR$QxF8H`L{^AUOvmLq%}Z6(K@l5k@wyJ zPeCm1qae|BhnjETX~_F8_&zKF1pP~u%?#wgW~KZ?~bgqdCC$JcoWPf1_^$3dHE?m=P$5niR>tMoS0>1vZOy<$a6RI@Mn_wGG= z)nBn#Tu~(QU{l8qA{PyytFsk40pCT_vn4ExX|vSyWjsj^C zO;R?@WU#v30nczdM&d=39(w_f`Ta)bkNSIn}zES^0WA47;ft4ewto#xyV5L*dgO}ivR)2z~7BaU0 z|4hX*u!H>O4z$;7lZc#i%-H;6U+Tj$Rm75iAA-1pmd_}8-5)fYqz3#xC@iVr!h8@!=NvV!gvZJCl}xtJpx-Yk6vvK@r$oR zgnW6K0w_Sxmu$aTkAu{TO{M>J_;px{$*ht$$8Q`Z6Rd4FGSwy zg+0>-U+)D-QVULI638!{fGu_$?YV<+W=7zpQ`n(Xps}rdEt}!)*rpQMmB{^jd)LF; zKY%7W@3xf25kf*Ony#^pB*j5Ym-^b&I;~kgLl~x&rWw{mELT#3L{0wUds*alCFQh4 z5#`FVpo@`9$GJi$t9DvVX}%J=*wy4kv(KpjKg4eV#YYd#EZ4eg!ZPc@zWTG4)6tjt zQ7sa(DkbV1r)pQ7hF){Hw(MXmsnkmKwWu9ktG0vw-yz)OgA(bNG!W6j+m~Btm0#Uo(dK+VF-gT^zi#c;LW{nvf-D$ZA63 zJd&`mIY$stS3lajhLI(W@Si{U2C~^b_`qAPfZH{sK>u|+Rw0>t1OD+}@5FSxfY)u^ zfIs}{*Q2S!i==-L`KfV&vIEYcb?TZjJ2X9Y+-N*A=eX9n9-b@Th)^nm3pVv2F_D1# z$Ya>>b8p3oNA^LRpGEiUUr+wC4A(;mv=Qv*3GNQkL2h1C9@XcP{O|;~5UC9xwc4^D zJ>7lSJu`-9PmIIS*}J4YtP*qw;dQzQh;Eb%Lha1+fDp8%Avh>-&>W(ZEdZO#hcc}P zZFT`AnN4|e7h>(}(R%4MuoaxJ(UIpO%_5QO2rbDYm2AS>2E zxm?T7)D3kDeYKTzcCBW=`M1^pF7%q~)D9MXB}rmA5A+7SPu;zjOCW0qtB3?QX5mI`!u~gfrgnHKdtmW0@A5$_2pIs`M`(=Ac3Dv5D2G!q+{xh#rE-&pP6;2R_ z-^jYJ9H-J6K&?(!eZ}0y@nRjP*EyMt`2dDRtnOnmBBB`EY!!vWux6|)Sbb4bRjeWy<|)da|qZwRH8Mzk0c2JE=gd1?!*Z0d*%@4qVxFj-~Row zh!puw*{Q*{_Rvb5#zIaO8W90PYb8rZYIBbY$>hU9Uzmb6L*9Jq1oUlJK@ShY-WEji ziuLG8lyLF&-PD3h$Rs4}w1jsNHwBVEvZc;HLmArZXr6 zT}TIbPp1JTt;!300wYn)B6>VqDo?a5RYXl2uW^Nh-IQiS@Gc1ELEoQsR08#!n@|c^T zFC9*RSd>%iwaOBnHiLe&`nWpY0(;pe`;`DN&ylg+dnGXYBG1pM@ga~S2@-XwgBj4E zjuZSa?_mT0*eU`^)!k+ZEK{M<%UEdw;*Ts2zY%x8Qn}#mzlm~AB0)skx2s7w!u?)L zfbh5U&{56sa zvb$jSv?Dcs3h}uKUcm#ctrOW$-phK(TDlBb56cEdXx zM=n9Ybh^<^O*k|&f<4cF1RNR6~ni)|j*O2WJAtqy6 ztFZ=@Hm)p*vZlf+4gLxZ1*tNNIlLJ9>;YR&(Q+n_EQt=FLdj%y@idf*C(tEf>Jiafwme5lWXrCSdF~fj;W`2K_geQYE2Ick3EN{p8hVPkr);w{lR7eA-Q?O(1LPI z!bT3eRHQ&FVU9v3lZ*>Th3~{7nE2{9u7v8e}k8v>ewQ*{x!J3sUuFn9jBimdUO#*iI|y*!@Icyq5f7r zPa37RVQ9%T91D{uh3FWZ9L4CGVWeq^tfj#6(|Yi!y!NDl7G^Op5JteYh!^fZ2$w6! z)GW)sl8nsiZ`4)jF|g##!Ydl)XALQ=9O@Ogtyn-X}kxVh?-e8yannmPY=YF03% z@$k)dOAkAJxnQUTw_h-T|9I>e9q0-8`A+`VjT^CRG=lH%9zWyxLu~>4;1mBy1mkw zuoV~VxL65<+9L7zG9N`|mn(%sTN(nbtl$PIoBu0IZIn*6y=+S3HJF@g@3IuIiq>t> zKX$ib7u4TQ4|PGZ2&--*7fS`R`8?q8SD`KJ0XBaCXju;&`!*YTC$QmXm7;~w`(eN_ zuQl-qvA`V zK(80GhokTb;E9kVLUaxFou6e<#Ey{sga5SOo zhWEi0aG|HG8G9dm0cm!2|3D{BjZL6%XeTzk;RzCk6oFK1+5+JtuajRo+P->qpWpeuU|v!JONw=4{4TGwpDOp z4);FteYiTWM`Ch6UrY+Q60HqdAvQ04An;>8&t1GKH2ZNJ8V@IU0^zq#b=zrp_{q*_tqAloATECy$Z{6NUhpt=A%-uH; z!Md&xuHDe3CU4!pe-hW8*U5KHL3-)15)koB0Y5%PtNdHTTp8Q6(>rZ7~46?hb}B%W4|7wy^Dp!`aTXV*=w zx@^)i0_?#dVEiHA(mw!B+(}wt8-e^AK>LMMa!AXB27x303GDbk(8eC%w#(T_3*?(u z5xn1F+;d^SVL>b$0y=p9^8)N|r}jgC+~Cc?i=P0_{|JS^DPZd_1J8Vn7RHSo;A2`;J5qn@wQr ztv8}DHjQF535|jz-R48?}b}KYn=f zS(Ni9sp-4vBwmGb@)TS>o8cl*=QgiKC=!RG*@3Iqc&KH&@$h2{ICUTi0 zS_I{TpF?b5h|~+W`&n^awS1y{Oi|UDM>pBhT$c`E@_fQ(2p~Zs@To6k1k6 z9~(s~KTY97;FsL~97M-jHsaP_z6g^~K7_ev9^ku3D8W?Fjg$=nA(@h{!eTA@Qz)Nk zK}X+NaQIS$zGHeJ1>smyzVf5 zYR4d=CcrPIa>~;9@hi2{63;#@+lk2-P9^*pUbhMV__YVHr)LZPKR$adHGoS7J?QKi z#6u4}i07Z(Nx(Pq-MsB>Z&PVPZn)tFm6=v39|=>IKn4MM(fZ~0O6f!XD@#R-wHX6O zuN_AOa7DT3RqCTcmFP9ja9Yanb{IlJfVPx2_Rqb@!MTg$g%k`G8O+ie9KDa7hV;*l z-{HQ!{QF^G`)?YQP(MLr!+U{KcLBXu8KCTr0AmmG{61jn2~rc!z^Ev{3RE;t^4Rr1 z&EsfQkZ#5NJ_;LJ&7mQ{3LdEO{fn=mqBO&zs4PBTf5oUAtGuMJ%#{GXUQ;O&RGK&_ z6QgMb28*NvTF3z#R+&Z({sfNhIe>LrH{qgdUq_(ND)7kX$~b;-KOVX34t7qDia<$_ zUoRB07@0`pj{A0^{XMs$+mS=Sk;gB;?`ljZgH)RNIF10`_~zHE`zO-Wdp*7IXmLvV zD0V-z7hyKAi*(4gpML{(fBV}gZrOqK(P>2g-{U;tAj08cw7C}0)znPEGK4Y7F>~Yr zOgz7j+U8$YeDSu}0)a9QJ1L~Or=LZO%LhL_x?#7U-^hEabXzfvM;|_t~YAMQ4u z>1YY-FW;;j!BhM8z|q-?B6<8gX)P});#^F_3u9DfE`2>51fb(Pzk)P@RV`MoLD6ct zl1b^Pfoja{m4pngvxGOvr*j{*^>Ngd@52@aOAhk+YE zM<68d$4?s8ht1UJt!EWFO0(!IBiKPXdTGfhKSG1{`H>}0I}^ayS8DR!<2Z4A93A|f zu*s}UtF;YtMuc5F8dJx&c6Ab<$%#wKT~ZEi=V9gW%agiEX9;EwW0HzYsvVzNz=PEE zf9j1_!j(QnhvWhVyIT>@1?W7@qqEzsj@`1gA7fKv(Hw|j>yz*M33K#mf~et)7p-=?zl;XkrpMwTomfr zDR?j5fxYDG1mF_MIka|M0N=D1X^$86xh~Y-y0NUGbW9t;zECQu*|3L6yKHZ<*$Ja*Y&_42;D$C# zO;PAlfRqyniOpnfMVO?J)m=C`KZZ_0zv8!duvnx)67C=sN0{e!{X3$1hN z`_SiT5xBy%mQTuxGpM}9dw!0;Xnmac4zHhve%}Xqy#loGDns~mT|z73knt>)cWtZA z)2VUl!=iz$-!*Mh+eVGr?QF`+TH+9udNt1XT*~G#Pm?r7+g{{hm?or6d7}*=&`~9+ zqKN{MnUdk)<9^BJH^$CcE*6y#Ef7q^d`qRX>KZ3TrV!U#5YQqhXBOc}oIu&O7BjOY ztlnTGH|yRogkSoLkKtec^dCfv9UrKj#jQ}Q@^&c6ZIz3Fv0 zJZ48zVLe{ICV(IAKZ^N66wMnq;}<{ri^g+_Ux?2WBYhHF-H$>n0k0>B)udH^`wxE? zU-|r(aO}j$van3!V^hy8aTdjr;h2|?@aCC(7z?pBcmnNs=YRu8vKoFkc0?^U(n|T2 zJG2`Gmm6A+9fj13#=%(PbL%OBeeoEtxCna_&CLECY7JkPyQCtbiah_obH^#fL}=PD zc6b_k|0;BE8$?^L4YTt(B#J2%9drs$C!o)g64|f@PC5ncxj4$R<0$nGa!~L-3!_+Y z=P=@RBSoPg`Q7C?bW>xMMa<=SBnOZ1IWqPN&WooOuzj#u0pNHfjUVT7w&Exj zk0X;xVPO4Qw9ta>Chg~-FzelQ7==Ipt9#opQ)Ztv(-{khO9DUvb;(96+PpY#CFQZC z4wrr?px)o#uK-;@UXFk6x#v`3LZN>oKfX*{loaEV2K+|>_EuTK-vbKR4Tr66M(L=n z#sP|}xA=VHAKl~=wG5S`G(lYuMFa%QfEOjPk%NJl8chgpLCrJbutSNL%M$W9K*d9*pgD6uW#Ikz$+ zMd;Yr2F2J>1@=;G;jM6!uS||-;2b9hACOL%hkJGup{;9h^pU+NcCCl+{BAn339vgO zu*XT2(LZr?_aWFNj8eG#cJ4pM>&j~9nS}CJ=u@ZQ3;N);6_KaKl_(cYpw|?gBmbpK zhNIS@sQ^?p2xUw-&w|p~PsKn!wdLM@ReI(#j~-pJ@A0Fv>Qh_3@Z<^n*cM9()oQdk zYu9Ns{K>HiWXc*wMkf)8C$SJu!@;pMKj*}u!zXdg8?M6uuiP_W1Of|(|BiPU4n}d< zHY(y56Tu)w09~~Ep`jtg>Hj!TK1=+A@}p)ASc8+%Dl|wXpOVRo8;YdO6b8D%k;{^! zjv#5CPa1YH^_A)@k!qHc6kYv;k2{1G&9bIYIEmGq07F3ODx$~;A2og#4JyhMXsRv}Dr(*DG}_Wig5Y%Jl}nG@pwn*N z)glunzmv>#uAd3o}>vmO3^~nnKUAa1tZ3qTBXFtdMQ8z z^s@xAndv#D0eI|f@E7QajZDJR+=?7E6l=XIos>{v=VK_x7c2GB%n2A)yzJ8W3G+PT zNVSHjeRvaWeQRMI86P=G%ViAy-d=1h<`L%$dMf0@=fC)6{Pm~)1|7ZK4b3ha!LmSy zu8l7~S2mnXcDobJ)QBfY>jbF5mHnOYd7P&8W5;#vtvEtUWP0id9jL>U5qV{P+MIUe zXP)PEWp=8Q0%!}Z(SGDeiTPG_qp8V_x!TeUZOsL6E{-Gn#5bXxe>t7QA(ZG7D2uatah}4(K`JthghuVpYd8C+wq$jx ztOES9>5{CP=Js=-8|6^HTYMYE$~cse%c)p~K9e)e*gbve3VBpC(0_^cU+H2dG69ts z{L|4o4*F3%1ms9OgC;5zL2BMH0{>Gp^YD|d(d@>IXouaPJY|8NC!c&$ts^00ND>pu zl7^z;i$*Wtt^y&Nn-%EG3Rl+3aRT&0`AEi1(fnnhp^=dhB}Am2vO3)>HTp4$nn`w~MF_q0Mk{1wA-yx~1YC6AEynS6@o z7?l!POemi){WY55V}q&aS&=!KVKL|>W2UfSQIxCJixMbRp}SJwsHct3ro3W+Umv+6 z<=Kc0uKp&hrUvZkBnM33SD6&eXVGgUY2@(3n3|ZVNNGo57Cm$vddSfh=o~HSc_YM@ zFFH)~b^GRZm^k#53fq%UN5GA6If-EA5S{dE)HO?UlZgK1hhd9~Ca6_rTiamqgT|{U zv19C-NnkE7%lO%`p~a`TVG#`0C>LmMI{X-T$8S+!>PQ_X_ZSXiK3YQZ#D0VV9yAHX zadHMZPrC~HZ0!vqPcmP!9pr5#75h(Vj538vE;7e~#M)DX&r2rHR2;ToJ3*Ysr6l`i z7T$m?rX8RVkQuS%8ZoIOTPzz3YMbv@npbEauk-9WhevFQ;6;sYm%8zV_@X{Ai2ba7+DoX|%*%>)+DG_$YiUoRaD@I5 zx<^u(3+FFUJ|a9M+*6dYAK4_Y8XjA*-0ZWO6>ASu)3#}q@J2PZMU%EbUuor9Kf1<92kH!KQYE3oFR(Dwg_(%h>l8Oo+}R;#90FtuGpS?T871M}JR zQpvPVmaYweN|P)fPd}3M$SZBLG?(H;6w?I44efkr4*WKsT}{U?nITlR8cs)&sEOl4 zTA{#BR;1=E+M-OnlEx~P)TDjI-+MhSy!_lp(4 z7eR302S0%0Cypc9z7LnJUxg3cdNV%xEAU58{XK?<~K(mUh_*q*Kso73I85$nAd;(Ice7TunrdpiEswva^kJ4xh=_2Zzi`&bFZ3*8}vn z05eT$0rPxQ8}yJLjyQcNw504RG?N;jq>Lt=5J|?=>{{b3RyBQjd&*a;*;E2H)xr4N zYd_%p-?qUS_Cgt;%X>tIKvIGK@XWFM3HUQ?NcsT}e3lRXZs-mVd3rJg`#wWuCI%OG}A$7RiKx&C8p!nIMx99it=gB8IWgGJw($QT7Sy|LQHIX)sm+fZviWMo-9+I zWG@nnbfA^&=YuC9Tr*xUuYqIWyY|5ZBBIA!(?QOc5JzyacTqE`**< z;OF0Pq0(yJch5n5{npI{=dzJ!KN(e%K8%;6!xivh&Cme6Z@L+&uY3V>U-&XE<^8Yw z)nCIm?)dgHr>&Hbvj{f`z!YBl$gBH(O&AU|Q!_5`IVCoq){0A#zU7q3I7DaJcv=Rw zMw%ytMVj)UKq$nYgh~|(nPe42d14ZI^8H?4hTjf&!hW>-9hlh9#%>-&(bb|}m4|+U zj7(f{78@1U8wFRmx^~SyD<#T2)a}Ic+`AQVFFQ*$DstgG=o*#Cn*`m7Ss6YONQ_~ownUgUff7aK@_en1Z)BHi+LUCP9gRe zasJB$uWY`oQZm2)sw)PUFe_u+OC3up2N(YlX`xNP@$VAo=h$GY42xmrISPTxmOO<;Gno%ab9?D# z5Qo(hR0yW!cPMGfPgvV-m9}Zru4myRv&t);EwfV8vzAnYOh(AbJ9P9097@`XbW?gx zO+5!zt;Sn^`e!jdazdGo@>xeAfO3^17HUC~61m8Aw>5|1^SP-}I}EK|GCUHHR;}NH zK)AJ1hjP)7q=x0ERXUSyI))Es3fQW9&`iMGxqmObv>aNfc0V=~$34dvaNCCVN}?pi zv#I>~Mkn0={kze-V%Oa*D3*;jiulp z?gpl2k(-HfKj|epk#i~5ffiFfS;87m0n>SL+~rY_=o{%|vNrBKHJ8L9?4%8fIkqze z68r&D2X^G9C#m72P~^R`C5k0dOk0}0e4Y~hGNc0vWwo@SxN=j+ZSOgajw<%8lu00b9@DEY5fAZKob_}=T!2{FS zHqcBV5ki93I5C${5kHbwU(TCL7&A;|6|t?f7L4_IjkS11pnO**a#6DnQ!q&O&a2mV zVm_Hwf+YG1(Eg_0w`5y=(y&H@x38~PeSQ?>Y(V*?mb1C8;V`WMealG;Th*zlCSRG{ zp_%bguYfZu+`sDE7Wk7_$K(H7#lstpSnhx1*J$EUTQ8)cPd-ZSo{C~-)<|=(>+g;8 zpZY^1@<23snP?>zz~m#`M!_o}FIv9L%3Yv!kdGQxf&^f|;Oh07XE5UM?Wm-Dw&L+^ z=JP0FWqdaR_u9VkQe*L7cJj2-g=(syZoZ@}ZGErXQz6kcU0XH)!p$w}W0kA%GK*$R z>tE6=W`vN`sX#P3KA*(Mx9`L4$vGT*_9&goC7eIhp%$muGoQkn%WXnLqtXL~mu~T* zl*+@;cb=moEJHKewRSZ+$ipAb=CFETT}>!vRnvFS!8(&`Lr>Q_`X+p&pQbQ6KZ65w zmbNx&xTL47B9o+nB(Hxi&+jsM+H@3ct({0kvnZBiK?su%)V*p2uL8l_Ma?hB3TdQt zvg}U_=?u!GHH>&=3Mp#uI|B~mzrwocen?A$Yl zp!-{p7qFK>NVBy_YbZ^BOqkSMf{t~0Hlb_0cA<3am3aFy!P^Qsm3%v;v%rtz1m|l? zop|pRs};arLajW?=h{bF@a8QB*a@}rtJiO!F_Oc{`D%i^B};48TvHa{5gO=%!B$Ms zA`pkIjUS6T677B4K#Tc)me%Jmwf+}rO}uGqA6B;q)%mYXu{2bpXbl9wN~Io*R|4mk z1KQ_u-YYE}mTC7=)a0w$*j|$+s8Qaa)^R8s>pkn{F&6i4ol>NAJpPFBqQxQ*dsMREaA?WWRX}&4|;Nvjybaw;OT%qjxKAUIDj88b@Z_!o(Me{TD$JA2Guoz5@l*v!3ka7Na3-7RXx@^kf$;u>#Hd zH(b62A@Y-Ltzq10oveNly*OhTx&OMT^;1L9q_jYP|6Gj;qyGo|#r=jIiu+7a-yJrV)8Bm!!Wul1yyj>c)tr^9c2}7F-1(A-< zVL_A0W<@n=tXNf2lveMsW)nk}Jk%*5bj0&#&aOJTkitLGF?-wgK3qf1dXfP9g(ps^ z?3V{7A}Ypznre2IPRb{a&Z>45?S7u%pDh?OZF8*5Y|NOa(eC%CS-BFsA0_vF=dLka zNbncob7D53CT__+4^Bp@&1WjWdvrRkw0og(uG!GZW0TlDwuo1=ob9-3#N{?BF9(Fr z7R1lW%0I{JTbVHRDnVaEjTlEL2dBeI$XK>6YK{#nLd+QK%CT!vI-0F|tdYOiNL5^+ zgDN+JZu$}}=dYwbR*^b7D!h7SPC(hRG+x<1{SLVE(CUThEdY+nOob-X0G>pk)Rh}slPhn!l7+6NT zT0#NUm{`LVZ&*m?sb#%tBWSj6oSK-!U{4#hU9Zs?R-{cOgO}0aBnm`QIJDCN9G#xV zgU{`UlP`LBs2fuU4q$zE6GjilaPW8xmuziQW`Avwh=*yOCo>fTbT~^|2yxiv=|r<} zTX$EtakrY65eT;s$j}L@QTskZM{Q5vW;Av6)1Rxt8Q9A? z<k%!GciLGfB#i$)C}BDKXk}sdv*E;(x&-e#zP0kQ4Jr} z6jdno_=ZIAn6K=CgHxzDQ>%DTGY+*HW?skgaaX$@Z!Hgd=F|%Hi3(Q&*p((d)>{JB zy=vpO8(9l0Sq$}ct*0zccmMk1R;t62<6-(WDxAD#hALWd@n!RMm{B__tg+@;i?g>t zU4?LJRdBbCQx8*C(P>&}fLedtn1JO98yPVrje@K~C+9f*s%9#;zNf{Q*j2fg85&YH zW&x|{AQc&;8G=VISLPp8s2t4zH#K`$_-(yZ6+9B<)1bX;+vi6@=@|7qJBhxwl@7=@ zHx|hYJDdE0YGgWp~c3>fzGyvZ^ zul7c!z>p{hnSMX=#6HY+Qgbc%kR%n33uRrlu z_>ceiEV=F+TAG^?2nNwY`sC2@5u`IYf_)F}x#!+x?cwr=39=Iex&#u5B>H=LAxpg5 z=)85iGdP(};9@#q?ZLIs0&7VDkp?37?vEa&uXfs;R?g$e&BMkHIZD855@#X>L2eP{ zya$P?X{3dF0D?e$zxTS~a8Ra_U#3k9EsE*04zQjAX$aqgF0yqOG%xzEU+&)71Xm$Un3az%~N@ z`tvG(*J#+M1CulE)2rVrDXH~!sV~(Tx8-UZT9cG)riEKcnJhqS3Re*ZrgEp5Ghr)$ zY&m=_z!$ALI7sgAa%d?!VVhP%iySd#&5|upz`yQYM!Mz9oZ|Xb(lz1pGc$DhnlpAS zC!aM3#b#I)nrW$2^86SF84*3^Z`B`6g-EL`(4rZWvb2@k>qo}nTQ{q}`Lbj9UzqgG zFdb~Nu*p=mtnzj19xoyURyV=KQTtFznA?naS~TtmWyNoc2is|M)*7`-x7vz-jn6)h zq24!`PIBEeo2tD}P1ul>z623JJIV!HhUlCO(81Y6fLy?1ca0+x%fqXA)S}%}vsrYs z8`I0Dr>5{v|NM{exjdwLD9ETuOOmms0Kt|*E0fJtG^N`3S*dR@9YG?#s6w*>-hlFj zM5*1|2v~*m1YdlbT5_KCDyaIZgsBuv(o9jF=kTk{H0(=0`1>~~YobJr95!km6eczv zQ*LTSnF6ao?mg!rhhGv9mb4T(m4>0Ee-H^$76o4S*t3UVBh_QqGAa^BXe&KGPfe$p zLWs1`{H#jPQ0`l$^4bSIHbkc9mGz;M*2z_KS5Xe>io$7f8k&v>V9~~<#@S+HN=N#) z-Db{`grU9ZEA(MefDTU^X|L^OyBf+s*^I%i1y*r#XU$^`E&goAMk6y?{iS0`y|fy| zq+$WomnBL@wR7qw7%th3ni-Q=0SHO8rM~kp^hk2anT>x}h1rV7>h;^TrRP>n7i9s} zUD!Ov8vjf8RkvwNj@RgC@?E(Wp6vsuFDpi(m}9sST4}cB(iyeZ`KlvSz_b$cUQqWo(bht{tmWfxX325TvZ9AXN+$W#~srkoGk;?TMz%SZ2g@G<}11f?^ zDq-^PnypGPsXl7roR#EFuU(GOcs9M_cd(wZRH<*HtOoVJ&$hg*iC3r9@};9l8ew*d zZgFr36_zidWRtw@KFnqo(CMx&jiH+_N;46^_R48e6%lgX$9Fx2Kua5jHeP_{u0fMa zGw!9CgHjsV>oFX06^E^PF|863YV;GCvFpr~aPq-J7`piaB<3S{@}Xzo3pmm5cEOp~ zRJO+qk4Y!~e+!Qn=$Vwf$1D@r=;f`BAjdc@%ZGAeo85 z?XjzChoD2S-jCt+iqnkY@L;zB2Xk- zd-d6Ly2}VG!a?{ z9;2D*hThQ!P0}Sq6Gm98R3bTr(5gPfs38un>O|`31oDe<(?BZ zE0rt#b8`9!5*&y<9cyWZJ1QFca}RtU$B!Px)mL1NA<_}Dv6X|=E(@ZNBJsHW$mLV& zep7S1`FRFght0HS8dMk_YU`|97MDgEhdOde=oJrs@2%(KfroZusHX{mkRO}Q@51q^ zF*r3NR=ZFzw1^@*St6N0jy$qTe8!8d8tlLm&!1ERW1z1ao7S#g)^5@+b{?Ch^Yq2h z6Bv$8(GlsxL?TY0O<`-Fhd^3XD@Pe&S-JvJnMWW~-=(9M3Whnalh?P?lE`KAis!e- zljPl9u=kK>r*%+{QZq?OW<-zbR5BCM>&YWCpMplqWN~~3B@tA93J1T;+$p0b)YBc=Q7W1{M{QQ#GnpR@*(8GwG+KVLpNQrl%SsJu%UeC;3W9F^V z&D1KIM9wIuuxS+-TA?9mDzWo53EV0mg39qK^|@wH%UZeCDXUk7i`u4FTnNhIP?s|1 zCK*GYE|2=G8vlegb?Z@ni!|(+B z=-U)Rbbkzig05!UTIUOpNxE2F)_Be5)bLwB*n?B!bF?;`ICg46g$dRddHxs$TqK`C zP?CeC2;_O;n1j^FTk+w)_+=#L7I6R9pHOKfdWU=Ap~)-tmw0;5P!aJ3Hw90xqH^rQ zD-vjJY%_7J7P1m&nlm~W+izlW4$1k1(e~sUTUKv^v$+j?REIWzx*rw%cnn$ zuYBpt$fVPXH?KlnRqJ2Ymtd^%TWzDtD_VAB<%|l3)D8q)%~GyX&9&}d3T!^dy2U3D zO6)@}7{Ppd5oxc6c`8`RfCI-C7I5(KdvW-_@4?M?amnrP!=@{5Q48u=sdCjdtuCZ3 z)69I@#q-NtyG_T>G#s#ww4fV1MP5a9x^5&PM8^2 zJDQOC(!=n7;6`p+fMazxaxb2wMORpMhn4QU?0)su0)H20spu@G=$EQVLxQCZYfYwt zwP=V^t;N=W+hECBVRPrBCw`>SE->P3i@B7m-C9;SH%JbgQK>Q8=~bh2 zRtgoXFG_3Cj7)GUqqSyKy|t?ij?OMT{q!NY32aWgQH7(&o}qaihKr67NueNg$-d_v z!`#Uexbd<};d6Qj;uleq^~ z%CtgeWG+BiH1jl?JKE4p!7)Z^KteZN%>m-POM!iX$CW9FbRR3*(jtkCM3sk_8ycUj zDdbZiu#aE~6;c(-<@!#C z>U3x8aN`)Q28^qN!vYE;U(>cS-*Hn8C2tR+6y7a-j@#i(g-q()0 z2R}opKc=ykT~23UOJ$My-m|cEHBo8sQPW=lPSR07M=(AziGuu|j6f}Vpa69FomK+> z6%VqkE-Ewj)bf7UjNp&B1uqA=aTTa0$7NQu+8(xX4CMw z`{1bQnHIgK8uEsBBXQZy@a_Bpel9EP#&#fca2(lp+{*rtRxe7zAnh(cO5}K*9nCnI z^Pp$-5ElJ?s`=NgU5oCnE()1$m31&fppGXq6jTIJavVj|`(HmPLjIPN0}_fjU&z3z z%uqUgS^xQo5q$YiKT4kh!L;*20%so2Jn)Qiu;wU4zWVrMCe%0?+z*bbz)Aj?Ij#K*$t;qgvop_Sl^Q!C@U^N`jlvQzHfvlqYg{`afCX<1XE zwM#n~>0xmi?W0_y#guFMcOxBNuW-x8-Wu+|E-#aDJyDTL*ik;kXBQrr^aa~hgq)p9 z1KBtv^Cj$>h#_9m)M{N~mg~x2k;9YU`vL+Ks#|Y*n{ipK8p7B}>uUUrHA27|(E3sh z|4haI-dm9Vj~}Q!M>X~W^fQ2eV=%6Qf9b>wiu|a*4~|vOG8;Ml%_lAT8a1ZM5=uv} zxhl+>>Gc)R8&(9(AGr>iZ|R!4mB_ogj`|_chT(X5IA~n#g38P|NdM z4qDC9{42DdB}R0dPSbzYD4j+VCMr}%xdDvV`80VAz9o8c?o}%2_2#(6XXT#g=U$I#E~ZL0`6v7P^6-Yl7cv$ zFdRkF??0{sR;07| zoYQlQI6g6p7f;1;G?L@H&{PPlZmq^DQ`} zO-sg<`dyc4&feF7rhoWNME}>{kybHs0adigs)Snxl2v>@8!%{W1yn9whwS=UU#A9? zYXpY>hK*?b%^R1TY2imLty2NY8YiaF%<>M3)`{l9WmpkghNRLe!a-TwLZw&<%B(ne zb0sUKky~|C6SXuWhrZ32t*hQy*`!Tu=5_U2>&|+%G7Rg~c*knIDrc)nHw@@Lttcd; zus{7GY;S!NvdJvchYp~>w-@fkXK~QK1uc9*k;Mc?CKoXu%i|(aLL_<6yQT|m$tjFJ zzYimeS!(;PCEC4JwqLjv_uTb3rs$KfN%EyKK~vV0C0L20P$F@ZMIP;JpCZHUjJ5J!{CDJHLb>qeIpCSP<|>a zCe<8Mt3XLet{Y1onVvUXj@C8($lXh;k9A+FM%R8X|E;gEed#r{CEF|bUQseFAVO6T zqpJPuwSu6kn4%KDZ?PaU8Sr&$;lF+(e>+iIipAmz8opMI_cghE-HM!P(9V(&(F*mQ z&W7=&XEbaY2;l00dHSDnKr0hlXfY1NKm0ln&zCf{%J z`NG#rVnQW2)GT>ZSvIr&TEfOw;}bCYph1V9MzSs`ud37bT#9t?vdzeq{=m)|YOIH` zw#%zDdwGX9+;AiM`v=sqc`x~IamY^V*f{)t^sl-A5B%^>6y_&z@2pI8@MGBSL2yF= z@zgPBi+O5n5zI}^!b<=wfZy%`Oiu4bTZg#@r&82NMNr*LfA#Y?{M?J^dgljW_XhA# z(T&J=zKYAqV>lY~unm+l@2oYqxbc8Ohp22+=UI+Vu1K76hN;I{0;QVWD zhu2nuQ_CPRK7lz7LRsU|rjm2HmT6ViVE*Z!eJ8&9&ATxB{2ZEXF3b}|eIB>bF@y?K z6EMmOoD~q;bwnu~H2z&C*edPAPfpkCGBkrS?=>+F3=EOOCtu&!tHmV zn2e!dhJ2PR?Z>2VO1c>_!Eaei;}<^ofrkCVjw(H(RfL4raPrksjviI>%|e@s;#~!= zem#l+{ST4xQT+Y?`+@@YOV*IbpNhll6d|Cij{=#pWi}gTxrJMkNB3g;jc-@)L+KG( zt!Agy@%goO$ntHP31+%E*q2$#%9tuumL04u&b9sO^WU*Z8>EtEGCX~$)uSdkRo=C! zb(hUBNv$erq;(^X)%fg_4h;BX=x%l4n@=Zcd3WLNy>UD>cM-O=j^nz%Ni@5&Rm|r{ zv$TJ;p{z7ig9WOw7%hK71+48Ra91ri^?n8POC^)7(T%hsJZ{34!W#PC4DH<%D&?{% z#7ZXJSHqIjDFr_k9R5nhdSSP}kQ0ONsyK@1NMSI%+fy=ZCz zqBG>m-Mx6``Q4aJ+Ylw7b`WG^Yqw)?T?nU+jG%AGkI|V2N%i>1fUvO^O9;1gVq$hT z6;(IJ$%$8rE}4PLNM%cCvyb43zxg$ET>M5f!-uZpg~~C~-gdQmmPSg)>;QZjp1BBi zJ~xTUXeZvr{jtbA_CNCoLg6-akWLxgaG?U@^H+Dkz9o*Gn$D5Z)jY*e3} zLXjGJIZCS_;54X584Se)g+qw{dlB+#h~)`y9w(_QCvp>M=nE7ULgT0rLxJLKM?pdW zC4WvZC=(SZi8JN|ld@V%RjjH^&X^5cp&`wVWKL@_o0QgDPY=HK&2OO^39%I5%;33d zzcIhdx&`iKGhIS?spfBjvZaz6Lrq(P|4s_4#RCuHWFU&s1IKWDbOyihjvFvd3+-4s zOWMti)_{hov|X9+TE*{E3)sN?_(|TWXgI_x%g`&v{EXt2%70|mpcVMQm^_7BnY z#L`HUuJh9Zv)k?X?_Pw;iO1qg7VEZtE1E~fh*qN%=q4~*>tdT!PO|kHJb5BOCUX+^ z>={Qimcj?${U-d`-+vZ)TF@6>9K?gU)!3WbfbGp=xVVkJ9bXm`QJ}v$Z-#-Jd3yMV zt*BQ84a{#v_lRYp8=#KbF>bzFYoZrB@u6f6&ygCBkH73m%SSaY={_het!F z(_{mabgYXtrzY%>rPuv_^@ktnRHDL?tbtw z*hoc4#>Cd-gcDeOAvt*<2?ojJJ6md{blo`C=sk(>!1@1+zwJxonhFM zra+LzStyX~ZLKKMfZ(XmgmsVF_ zm1Lb%gqDiWPpDP)(X3dS<>l!Dst$6qSlY17 zqCX4)Dok9-5x|~F_UpNmcyZSO4Abv%)%qa*?KA&Dzn%j@nytaY1aYE?6loJ4E3HS` zwGo#GQuxa|@5lK)I^K7UP341vnf$B_BX7Nx0l-=gRRtN>TD=Z@DKUk2dOFZu*3EUGjOWoRR*Y7mc3@u4YMc6YtZlQiDX&=a zG(*dJ=^gRZzB$D6VPxV-q^W@|oII(LcTJ_|5w&MAxP|}~oJAH%#EM>0Ds(=g6*CJb zXgPQ=dh7&3ZDHb58i`m$T~pUhM?1B4S9=h?mNsM)QT1XDB?yiLR9m4M0Z`D5+R#X-Afb-&63bn({pcw+Y{bx-MoUwC028Alj{m)x?Xove?g z)w*0ReDH%mt3LIbZ+&SbIBNGbdN+;st#t0`9P!IS22XRnmFigg4E4oU?*z4!DWHa4 zL1m)VlKa)l3C#pci&N%rPaufvFFPOWdjmMOa|C{87OMyQaDHbWF1v6u4n6ZM_8wZm ziG@5J@5RbRmDr$3?V@W++W2gizpIS`saH^}%3Bm&BVe}by;3yEN)v>%Mt%&fQmIOR zu&9&T_;;8StOQu?g%~z^4&(bLvsk}s0Gm3>cTkla*(4TYF|^taVk+N< zt5=6`^G2DZ7(gyp#2qgdabzxl4_{kAf0Kq6CxQD97BE9Aq1~sUBcNk@zY~|P_Lxpz zvrQ~VYb9#Oz?>N>R2{SkM{;SD+!WpmC8Q~tj*}`~6KugP_BOQ1+R1@^gn3$YK&g6?lOU>ECaFya%h(wSmZNbd( z5pu}=C5@lfpiJiN2=;A(HlG#Ja5)BR{#5n_M)d%eb;_n8y{6m1P{o_rP~u zkoe3ROG5q=YHcAyUrx}4jT<+pa9dqRC89{ztYN5IVxSVWp;sV(X=ROV=4@Lmcj#Ln zU)vWd+jKJtcF;`o_2UXH_i_TXC&>_mxvG@0o5;;AV9=Ai(#^!adTB97z42w7++l@%+* zpnN`bZ42IeSqSYx(|K=H!7wb#hQO2X-XF{^;HSIV)iZ=O2NejHO2FAmi%q&)k(NZe zS z#nhXfIu5?@9Nu`-TX5S@2%TZ`{+f1LE%{tQw$iqzu?SwxQh(pmY4xWo)oW-51yg%H zbF+D1jhe&5TdyDq$lu=2cE^z*(mm&ieTm+zJydkwBRVzyVlUUuA1ydk}ln=_l$Ob1Q8SiL0V|K^CEF{nt4iA}p>XT2-N;g?y>4yYYVXxpIWkggSE^$6 z30cf%&tyBk`S2u$T5WjXk;f_G-B{ZZpsz{%A8rx^B_uszTzkV!xaQVd@%(rG4R<}d z2OIi3aQiiz@chXLV#J!&z0DBsR3PZVKi~NrCT1h(ln_#vrdD)IlW~w$+hPg&a$Gii zYmXOi-l`i;Kbuh}iA>8k6}!OGUrxhP&QDYZiV0DdKasu-E4huxtZibYwEl>@OL;fRo>^6XgK zAHd-Q$LPe;Xa!`*n+KH1S1!{0rsJ};t(hPkfWsZYO*h=Gu4!-YLF-@tCmfI53wO6$ zjo5JK9GZJK!`3p2j{n`Q=3@%2V^Iq&<}~Rp)_*lW!+hDpmtBh0bU;h#q@Umo*IcCD z^?_Zx5!F&~tXe~pF@h7{{#TrEhOoP@7w`PXU#mWxwzN%_nB;Z8&twU_lI2V@_)b^q z0logaA+-Q3(@JbwZF0Mskjx6!7}}GWT0})sR452@!j+{h8|gdb#4^&|TX6{o`misL zr=Q-53~3x&Hi<`{n!pcsjbO*xel$t6gfm7*Ka2^2dNmVbgxbB+7sAGiFNeh7iv!zc zB}ucUy&FN#tpZk4AuReXG7$S9kTd&5VyXN+ZoyYS`RB-_(s;v_TX5$SNAaB(CKaZ}(q**h88|&fJoMB!TFISX zw{;K$twDIn9AwGyN7+G6P*HqlbPjWiY3w=WKr|gjQ`lk5q$NHr7P8nKO{1IJ-Wu-2 z=N2a5o^ukHJn(u-==3`YwhpYZw0j*!x)+eGq5rl-+1Fi0WN zg?6Wdyx`q%H}#-raeUczYTKt!D&XYYNp_-BNMsTwCt0KQ)tzhgk6KNucHi>zmR~_@ zu(|q*w93Dh^KI#IT8$Q0cOk8MeT#4PIlbs_8NjNxRSgHabxmP>?V4VxN4auXRjb#n z$t)F+ftjzUTxm1ozQ%p5bw`m(p_v2r!Ke0MY-?jvl_-=5EP=q_i&!z|~p>OSDm|Ev zza`(%Xu*w8Q*)J$QUchTd1_9?<8}8Ro4|ac&`{{CM8_!LuC*v?0bQ)=FqNm9Zo)5o z-~*_2h%apyGXtfXHEyTX<-|Wf>cYfW0^Kb-o;|Vvr@skBI!McTvDEEw`&x0u#apmt zQx8s_IE5!3d=zU4yn{Q2m7>-hbfTl+#k&4B%*V4hH6Np2(1(yef$MskaQ;viiuoeq z>_d5134XS7SF@iAsU6?mJ%Wk(6dpR9#!p>nQ|s$WUH8*cxU?;VU9kjyn4QDsQWK)> zX{_%8+RA=4BR@!s(r2r+S~X*}HqBhWz@)5nbH+OAExDTZuC(JhX!lZHkwwhUR_i}q zDbmbwdNRl^F2GZYAXiQzpOM%I5Bj^C3Ghj*Ueis0ZN~Ui94;3fx(PR2z9KfC*N<@P zc7(%T?Av!Ij|JZQmXG4qC}Jkg&qvhE(8;h^yCLji4t8G^o4Hw5)0r9*dZ%99!w=m4svFEwn~Lts3T8vSlziHjmfed;|7A z_Y9uja~!u`vkhN=co#+p{^?W_C*~5EN@dlcQy^zb51BltIsCZb^*56`D5-4xhm2RP%z95ymNkgSQ z)T5V6%f~FVW$pS>wES1ZX{*fXx?DQvS{aeB=|mEad>nd_jn&@^S0=|nnL>L=$MXjh zq+7_<+r3CfIS6eDoVT_UtIzYo;Y(m-{1~QoCJ{*WQRCl?SF2=m1x!$5%*P{Y6)6FI z8EBDMin^g_hGjfDI)mRvHA=^7H_0vY{oOyrV#-KGYmw3owe(uRHjk~t@Z!#=@%2ZZ$L*JGKu3E}sm3zEPR^z=zLa~|LO93K1LS1T5S zUc)JNHzH)1IZRZUo{drumcQYpqeEvs}OHk%Q_rfJIs5>T}S)Y`GO5?%`Rw~~Um zq|Nv_cwj&N^iTc>fBmVf7S3+w@(ujw!eRV%B zyPzNQlP55?XA&1~-3CV~h2;1?>^poAi?fq-+Gf<`O!2|_NDmK)GWk>%0TglTb(i7P z#0(;{9N*N)C4=qJxfq_L;;@j)VJ(lnu)hU&9h}0k>9n%)ZG5jssl=`I`Ea|t4PTm^ zC4Onh^1&|mHBsnl%0g_nxe#{R&52#cY+>UO&4?f64=^l!^|7qA)3j|pm3lViWyRsw zYp}KDTs8cjt`3xAkHM9nqrlYB+0ufGF24kiKlB)87U%c^QZ(1xl*9|jrSoWQ*AWOO zaA0p1qa!h7Xws!J8q#wk`0y{@f>*0ZTI4RIF;A_~>vkeaia?f1?CxquXM2lU#5@r2 zSB@{&@WT7p@fHb!23S@H;gV7h^jJxo*J=+(<*bI<{L(AdI!%{dtp)&=3K(rE$ZJb4 zpw-pex$ay{o)(SpiSgH>kmgg|E?o)lWnFHkPb3KyS(2Ox#n7xNZs$ z4!&$t3tBune*3+*(){;g&%P6wjV09mMix?PQJ!ivjTH)LT;sCqu7{giTS>EHX^X7P z&o>%?CT>?I?o=$8dZA$c{p1h74qJ5+aiz_*3NqUa8UQc>-Fjx!@Zd%&W&sd8`=45$ zK!dSnfJ)S5EG?Qzjqjytn%Y{IgL)u0dLWXq)S&(KWaT@ zc}Age)IvuvoVGA!xS7b!@`b$8{=1hIhri63WY{W8ww-PHz2Eo%o_X+Yj2$b|UtU(G zq%0WTO{x0ei75p9Er>6a;R`Jw&?Ft+g~Pi77#o=<$R<_%eSi*=4RpA?_r1S@SF3pF zbjbu;;R|Rg#eg$SFT9f;eoFY}CO?WapIa!bYPEaodvtNEG0@k6@-o0!QnVT%&{jHV znUK(yngC0#w)9nL%kES8GJ$o8wV|zGp_u!m2)#4hx=Q_)c2OL>I?sls)`SIz){Sbe zTOI$krpJ;SDx9=tM)KPpTtzyt7c+Bn`1Z5A@$l{wh-HmrR;6;SP^r1N)Q$d_Ef-&` zZfYjVHLkB&cR@{MmcO%QMXMfbEVEZVr=AXtN9HO3CmMDr+=@hW4ps^QHCfGsdjr_5 zi9l9E>6Ofm;$*I*im$v+YqF3@D(D7pUr#Gkp2=ok79#j^N@F@gQ!{QQB5w)MRrSJN(VV=%eF(`?j?>_QGR4zl^o#pAT0cjKeQJjFTsiVmg{vns^)O z-tEI7tm!Hv?3RUsisbL-5z@Ta+SNjZvkgwYfS&Fyv^d#6Xu0=v4IxOayp0N7D;+2U zbi8&4T-e;xgtTz~DGy%PtKoBtqj-ONFFrpqhp+kP@Q(gwT(riG6Z8?KGB&ik99Si* z^oj7&jd?+`8doY)#t#lP;n`C~tnc;WgBL|A-Cku))t5)~oxUBKwAgPmi{BD&$Oe?w&nMykPl)FSyQ zoY=haQna^s;MFSY)~`cHR}bQ`sLFwp&J>i?_R$F_n!X{ujbkgJbrz*#%@||}cmrq+ zw5V;VTv~PPTrr1C-dF*wA<)+ehWdl*wd^IpY#v|5>{@}Kt#F_EbG0SlQm@UU{+j0Y zY%x;-daGTm<7zDj&7>&QBqQruRuqF)HZN~eR7CAL7VK8Lp8?TFjvv8;U%P`2+XNC> zwzI4U14Dzd9G%ObAMlc1Y*Q(n4RE$K1a(vMgjK(#ZMeMDQd3o6T^6|_wKqGEhnnN9 z@BiP}|LlXvXKBHbMieczwX>Ul7f_(XUm{OtP8~JcLs20{qZz5(?MBvBalC3qDqyX$ z8ktRL+LrdO?kzq8i^H$9sa_X4dv2xPp<5MjRSm!LZ5~tk7!PHfV>2ue+0;f{c-POq z8-Y+ejy-WV4nOk<`a7GkP;%fq-@TJhokgDJUMg3jgEok*YrB-Qw#^tMvACEw}_k8_u$%VFCuNbi1nS^?sck#bY%I{vP_x^c}WTB*sy&7 z^DSj;_XY8h6VKoe`&Q#)Pfj9cPs1J~L*Wgh)oq7M*4Z#ECzX3&eFNXwi4Sx6cejh*h-uEy$ zIe|`c_woWoyXfj^Roc>${4plCYWO&+cDhWa36tY%_BSgZKq{M5YurA4^y%8W;q18i z(}R5Nxm7c|uJhCYZ_UHj{ajAjRBobG>r#L9T8prD(5v-sZFSeFal9IW$+kp5DHyY% zvLC34(_iv5qy^90j6(Z5EY9quvpub-5X%ZcP5gZA1w_!u1UtLRR;elOy&?cBG>(oc zXKo1i+L(2Nz0sD`NI!$+TkFWKh%f@vQ}=ugO>LcM>FmY$k-gaQ`rD9Ln5Fy3kB**x zoY?nb1By;l5k1j>bZxc%6)t79=Qd&>` zF_opVe*pSbpF(oy19;>c|A>uidf;>0@W{al(2tD*51NV=Rmy}+zKC?mg*W(P)as4& z*1FpbZD^2`9~Cq`1l`w+d}}j$3HCu!LE-Qr_{+x;3i!y|r|2K>(@9LFj_=b!N~TC9 zufy-c+Erfk_6IOcW$l=@fZx9KX8hSBkKkfj`sbb3gzv{@aL3pjHabK2g`OS-{E}Er zg!xRN14p&XkX_S(H?1ktiikst?ZGl+{CD|7DVH?w2Ot1rGqiZ!d}l@}FBL4B4HciR ziPOp=Si*(FJm0uS<63$(_M=r`q-|gu{bqK>aYwCd1qM`)1bv_ zVBK2eL+CA=kF?v!fy|^}1%N zG}lswH^0kKF@`9wS| zehjw-anl=nRI+So|-&@R4k8Q2o94Hvg6tLGDIyE~U|ADk+r} zeQGseYoDe4Rm|L4jjc}Ws@byaCD)#|1caABRNZlC0P^)t##h8PnGs1EWNaZoXP~xTn^9fKY=T@xsalu?|a>q zm`oP%BK?EAr(&uO@q!Iqq6id=C^owh9&%zKlSPC){fSrvYg>9$`i_#*3vVchuf(P? z5OLvMUG4BH)5M??4`esO?Q-JSk^NY;W*z2cr_{O=3sIdGe;3YgnO199XjnlKR+?og zF8oLVzhQYPD#1^1u|Ul#4IM04-Yi-JO?l~cYxdRLtL`GF1^MOosk=BD36teFSbmRX zcQE&9wWk?cvaT=F@>NnStp?gGRarwt%dG4>Lx--VTk1JagWJ}zmVE5iYcIjn;TPbE z#Ay1vaq&ePIrvUu|40(gO(c;hmDT#l|M7{xL}YRjm%ibh2(`5u*EOH50>Ud6eHo== zZMOuVw!-;KQYFYW>`KS3giuz!dN4q_vMw+TfVbI9JwjK)N7cc|7*ii`cYbSgnAz z^T;XmY&Z{FH?BdhRKUK8IgHXVo74RSOgpaF(MrwSj!!=QJpTNqYjE(fD00pyQj0|l z_lI#2DI+`j@%WQ_lp^6bU*%j(vSxdb#W`m1saCsc z=m>S7zinWtB`&Ya?JJ8d20 zUiF{l^<24Fwt*b>mS6mR1j4Px?_c_Ttl4@w-u~-amx+;iu8wHwc3*HfDEPmW5tJIbD9$jp*(hSh1d+ot^mN7r&@}4-5?8)1Uq{ z&bCBI#+%_z++U~F^_Qx(iB9Qet?OQ<8YSJrbVMwR>fMeXfKULc}Y<^^<3<0 zluor&Ol1q~muNOxjV7%jNbr646+cac@R6aB#7mt&GU!rE#-qeJEy#Slnr#R|xQ#1P4G~vK_5~K07S{P;c znqR=)@I`1kuOA5qP4R>Sd*=%9=n<^%3}U#)j)1d4EPmq#tANazEftva4WyKD*&E-9 zXYTnrQt^3Qb^Fg@|1%F^hT!0G`*F*Mehaa=8N?Q5=+y1Q6>oYsHeGxz9{tw8!$xlU zx_5pEqlb6nnS1ZRMK`?-J;Uqq!u{XEjX(G6IJM^z-1*P{7y4`lmtK7{0)Y^od-6eC zck^3`TLnD#)Wf*_o$tf3!+Y_?fBGxjbn}}quzou}|M}08Hy_7GKJpRe%i6YWo2qFn z7Q>-Khj8homtw<)4HzCC#wR}U2_%!r(?2gv-CwJ1sygnU`swU(5~k&%9QV4?@?9=! z`RpP4_8h>Cm%fVvHjI|;LClOEhes>I*G!tm_}OQY^W%!zYYI1`m`TCo z^i0VHQ#G&h@Gql^;(>S%|Wku|v9U3wIm}GY zVEu;m_;D>uwbtd&W0|N`P1)Ff?WSu~DCSq6{3=@MV7zSYrRZwzQrEa}=tAU6c|39C ziOTVkN9DRr*CFf;<~~eB zCe*&}aJS0kbMdN+acJrwE?Ipkd@e8cj_<>%`IA-Kpy6xLDq4FjCRc&J7O<N|x+SjRQ6Gf`h!RZXRDJ*T+6UpP?A~4hjZ00#W7oW#oeNwCDwUx2e z&DK5LV=3Q;Zn%f#uwVbXZ=#sbqOE5L&28Pd=*G7q&?f0b+K|s?vGKC&urM_Shs%Y| z!8N#of?@l$Z^n~%ehxRj=hsL(>$v{iAHlOf{0apF1z2Prk-14)J1JR68MnRj130+n zITiJj&1EpSYJ-wb(dYsqi}M&*y&kvoI-mZhf5N~2`@iGvyYE&&|Mb&OS91F_H#g(w zfBxs;C3x-Fu>+%{qxjH=K7_yh+rI@)<9yU=DXgVCYF?yXd7(oC-8ei+Cu%ZBOVx>h zCuJR_sE|@2M@M!6UWq}X1uQvnWQo)1F%%%jKH)FSSCI*Qw`Ux!aT_5^-@+ZJ@VviRiv&!Rvd z&}X0Bg{{M_=yTI|Tox@}S84Cl`4SGf<8V{quyg!A@bJU9@uoMaXg!I~cYFQl^3NNK zr)y@?BmI?k+MW}ovn0ae|7Y(l!0fn=wBfh=GR@rK(TqmSOlFEPapE|(D9T`1>KR@|rq)AJ;eBI^f8SfGN>lGWWutD#_;^O5OqcPNAQ!?eNv}hYeW9XHXjiy;tPc2GD9l{v`S=n>P{^xKaR?tO4OVcX< ztluHCT5^O95ir=9G4K#+Zj)PXLn$^6Gn*4Dq>C;;>Sr!Qq$x_;^Cb2i&S6*6C74+I zUg&GiLWF?DG`Q@fORW5Md5FEG{rru71Y08Twbf(H=fiUa6ZafVU|07j+-_GDm7@zy z&ZR4@-SIbF6H!72r_wEpx*vSvE%?e?Uxv~C!?0EvdkM@AY<&WUcWzZr$;7rt?m+i* z8xagg(LQGpy#6qDK6xK{5A4R{H~$(NUh#U&n70^dy5B?FHwkAYuXIimr~KF7{{)>~ z^UyhSE?GQ{ND|e-YhVuU--+h-4&-QC&g1jG}KtTwCJaX|d&?JG@J`3w!bp@V!aw}Y=9P*@$ zK6&6M4oqgSXEXsH=P$|-^+VRe#^*+{W#}B7HshVxIJ5}K%xVORL>&>B2gy3uVjdhG z)8&+itrJ*S+^TEL*-D58Qu07A#nR z`|i6R?|j!g?R{3SSxp0nxUd`kBDDVf2livZ{Q39?(jHig`0;s16! z7R6-)B;*ue>ZU2&B;NDFvbKgclK8p^zgyV8koOYWxTOU*lNI3i__1N$28<`i3Ah5{ z`z?pJAVWaDZr*zG^veWPkL-C^Y|9#admU-8E-y-SzBpqauW`E>I`( z-ULX~XRBa}CU0FZoNP_``8w~ZVh4L4t){QTIYykx$jYs@#;i?=-B;((BqtmvjlM6Z zVIa?`HsV+~v=tYfyAXxc2uifC+Z#rdKuaS$*Zl=N8(E7-GYuG}J}IO}&~xvDXj-!t z4a*nN0SmNUNNR;1uM#$#n9M|5U09^B^aMQE(>;XZo>8n>&`JWL0GaN<%AZqt{Zl`c zn-mOX=OWWJTvInkns;n$82MaQBoBM&uRp^-eECO6i;|rtGRXviQ4u-%jsI@?{uglW zRqr4NVG@tt@<*(>;Bo=<>hX%-bI4Vw8p!3Y0zeJoXN9Q@P zXFJ~b_7CDaU->Z3zTh>u`s%Ck;DZn1H^2Ff_&a#;AO;5q#dWg9&a@6wIO%j6S+YEi zP3Oq5CB}qv%vio!+i9y-0*mn^W24-fA(R;-pM;e@8zRbz4HmbE*lBJh-ab`_{Ny-M zd0w*Sib$j~=-xYy@qr@FyLujsj^Y03BLHPZ=fUWMSF7#PFdVV zcyky{o<{N!nAkj?K#+t#TMg_#8z0rt5b7e~(S}p!o<-v$hqO6}0~4E2Pc#m(a6pir zO-83}Gz1#**tP9xj1V)sa`8OOr!knOK5A%cglpF07>JkfhwNeeQ}Ys;4z;?+rUCgE z0{$mFO6OSG|NZwrfK)1tPks7RUSe*UwcVfl*X2nK_=>WVAz zm4E$;*ypJypTv{&*V@{K#~*tPm%aKjeCl65C4>YEi;FJ05W~X>T=|+SuzAZf_^)nG z;pcS7l?QAkC+P&zr}jOCbC;b%mDm*IZCuq z0mF$Q1U*5FCPpiK4C>7k%Er1E_48EpvIT{Dtr`+#TE~>D3a$J!Q-It$u!&0Gm(IuX z$#uGagS2@a69t1Nw=Sxtjc?rtzmY+-V-Y$#Cy`H0z(-oTNM7X%;IZL4+&i`iqglF+ zAPL|35#$p@7Z8YzZ+(`yU+SwfSBp9gItvF<)pU;F(DWJrUwe`YYC^Z}SHm~2d!_C0|N6UMPQa1J{%0OV=YlmtacVXD(P>JkTYglV7F4ggONFJDL_dNRAk&cb%$c^K-!&yP_?lUX;!x8i zD^|coR*63n#lCF^5Qzj)*HlmUl7Jpd;F+Vd$S)AW$}T_Z!eJUe1(aysjT80qi$C0k zb5}1CilpDAi3MG$Y*FOGX(le;j3 zlkv#m!?@%2JH+u4A7geLIK#fY`H}^W;xZu zn%S$xcL#?Lp)uTmWHyQYL;JCT{xLOkaQGl%q>c09typFfGe{8J{_JgHJLdO!@*f&G zC^-AJ`Znz8-;HqsJm&HP-XMWh7J6YFNLCz>dX?%@M6^@BqAis4fO=qtWs_ zd@pTOOlh)+xoPiNQJBLP8HW9P^&zY+vV_JD4ULngRtJ~g1DEN>#FkxXAqBiZPPJ!9 zd+(fZVNE>&qQ^vxoPIYS37{t#ge#mU%gKY$;S`;pCvcoVB7ziIOv&y&WGN&t=jG=S z=zHPu77=g}XHRB#3(+PdVo6|n1V=m>C%{O@i7qhk$3Hwr{PhN+fh-F}Lq+7tF`CqR zH4#_OcV5ip<*Hv3Lc8ZaVm|-Cvrmc|5)3#KLwy9kGK~UT6^4kPCrT@w6k0Fu%i2F{ z_?Ey-5I=8G;|!A498M9vBlEJ$YfmJ`6`gF_V9za+$xOL+*6OFdFRd)RCCh0$S!!-8 z?!n353tpRO6<#RDg^>tsJ#Lqx_BEM5$dGFW!u2!`2*5)vZMgH{+tAX{jv_sqL;VTN zhIP7(fKAv$H}_WMISc$mXPy*754Q$hdHy|H0Fvpw68=~ zPf?_{K76E?tfK+sNI_ZGSs<=|CXBWOc8|sI$HD+Yb6U`K3=ps8@GJXx`u3s#zh=b6 zakST5aRt8ljc?-J?|PST==}N5e@3LP4p+VQwfMpJe;_p7V>K)37PncmX43Y-$_3y%N`YVroO+@Pq(w_yqvGjz!^OO6Zs5sE0 zdmj;RxA#0}pXbqikBZkKX?YLreF%=zigxeLyKP{9;=p6at<6_`EkOdP)aD%rvM#ea zQpbAL9pQswf6eh8Wi8inR7aB_S|lJCBalmy^D*e-QkcY_KD3*hc6k)(y+IDkY$}FZ zx`WtRoJ7XoicFxD9C|cXym?tNb0SGjGcUcSNn`dP9g8E})`$#q{zOj?}k=~LxbIsKJyMEl&uMCW`_9RBiu{4$=t>joU$y$$S(u*&ut zV%eB1IIi2t=E_e{vlqarOVwYHtM7T5)d8|EG}D~o(~$J15|XCFvSVRa$VUTc#JHH28@kQU}Q2*Lb8A# z?ij%Q7B3$799@Uoz*ZWMn~$c@PWR<|p5ElXa^m9iwU?A0x%$2HB5E~`xViVf`|#;c zeG30Vw9MSOb8yQow}>#Vv(7#XO^uBrY1%pGoP(L<&^?v-H3svsv2k?G>ca5Qu(-L? zPdkks>U`XM>#g|w=RPNn{hsUIi~pO=8F^wgO=-5yia$;bI^+w>ed$jmO;ZkE{*C$f zB^^t#?dY@i@i=^QZu4C19@uS1{gj&nWKlcHMsuLBQ}|T8t)Ob0?`!;yDzc)+_R^{A zcwg}fXcfgk)Ej{^5+pShS718tK^69xTOP+fzyCfiecMN|c->ie@P=Pt_fz-b;%oj1i%&Th z_x|qtBAFla-D_TUnRqU&`Lniq?Z5mR>KahYn!Y+<64_!-ZAJ?cM46p) z{$&WdefZtiKZZLt6>vu=MgEc_nAILdOO*U%$u!1E(B!FKC+Hclb9Zr@4--kEVVhhy zy*YwYT@j4ep2YG+;jS|w;R)C9YsK9kuXb;>CG-Gpy!j?U!#Fki8~*Ya`~97F-z8pO zap^0>>s#OUwu)o?;ZJ|G-#`55Bly4Bs@EilHZ5mesV!f&?lLron}zv$bnGbZ+IFWM zpYA6I>e9}o*gLqFc;c*h&g@)0cj~{;%1ZNv}}vClO~mb_na%qbw{A=E~1WJ+59#=1)S1WAa2$WbqpHoBZ4kIlpe%H zAMHcOs%!8geULncMMwB^aq9xs=eHYDwhyhQKCim>lew=;! zT!Cu(@fM|q49jCm&P^7|yT9~f{QCcV5ObGrz$q8M77JFLhMRu)WxVT4KgC_45LTUg zDQ^7k=kd`W-HN}_>+B_~F?-P}{Or^3z#BjDEdrW@V!xk#@-6t_4{jAs+qT&Y@!;>j zjqCp7CgA^k&VGzm58LZ*tsg{5NxbAX6)KdeV?ADV5f#8?SkIqJ{}F$#`^75PVh&~N z$&?Goc&sp~^~C09v4TJ|N@E~78NulOO*8GwM93_iN<*&0>PaBu76j>k7k1 zio#p|y$82^ZVtj+7;8H4c36i_N=H9VE9@mLymGc#n|C*gLQnuU`9VY?!+Njgcl1n#oZ&974&FHLJT;V}9FwJ9RSe z$+7oyNZXHRTdR6IRqLoB-(`D{X0aQc3nd=X_Mm^I(mRR4}Joc0dK zODGA4E%!*#^dOT?34zE}tAul#!Csd|YDV3}5X>~uLVk@p($s^kCid(*gxM|iFvtncuY#m4KJ zBX-@oF7c-{W$X89E5QC9aK^xrg$=Kh<-IQsnWAH%)B{SLN1a5Hk* zG(Pc*yK&o3zJ~FE9{TQ9Jp9*R;*x7Wh|xZ}*5o7(?RZ8!l%BoYaCFaB;{Nww)6jw*QYLQdkJldvk{f_q!q?1-|J#Al2mOu^2tq(@)Bg?I0%6& zeH(6~>-{8{-SByd$|K7xPvF|t+Kd)*s-}uUjEH+2A?IpSORKC8O#K`uM}2~xEeFfb zBZuy$r#E5iwr!Yk-pjD^b+5&eSH22sUhxXdUb9ZDf-M#b;+4nlOcDY!+B?vDm;}Y% z=P)sR1cweD!0>=+*S~4wCM;jR3~zYj8}ZxU{6-w3L=XQR?|eJ?0M5p~efx0Z z-~J|!_2##{S(s~^Hf=(RBsfo=x4+{ZLO}faPk$!Az!h}wp$KwCIK)LU5#C6q3_%@@Yl?eK+i(MvLKw)iv3cd%~xyo z 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 {

      );gREyEzBGi}~9HzcjfjROY1>p1YFU9xDvp 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≧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

    ; }; -const SpaceSetupPrivateScope = ({ space, onFinished }) => { +const SpaceSetupPrivateScope = ({ space, justCreatedOpts, onFinished }) => { return

    { _t("Who are you working with?") }

    - { _t("Make sure the right people have access to %(name)s", { name: space.name }) } + { _t("Make sure the right people have access to %(name)s", { + name: justCreatedOpts?.createOpts?.name || space.name, + }) }
    { { _t("Make sure the right people have access. You can invite more later.") }
    +
    + { error &&
    { error }
    } { fields } @@ -703,6 +716,7 @@ export default class SpaceRoomView extends React.PureComponent { case Phase.PrivateScope: return { this.setState({ phase: invite ? Phase.PrivateInvite : Phase.PrivateCreateRooms }); }} diff --git a/src/components/views/beta/BetaCard.tsx b/src/components/views/beta/BetaCard.tsx index a7f1ca14df..33b1fef9e6 100644 --- a/src/components/views/beta/BetaCard.tsx +++ b/src/components/views/beta/BetaCard.tsx @@ -56,7 +56,7 @@ const BetaCard = ({ title: titleOverride, featureId }: IProps) => { { value ? _t("Leave the beta") : _t("Join the beta") } { disclaimer &&
    - { typeof disclaimer === "string" ? _t(disclaimer) : disclaimer() } + { disclaimer(value) }
    }
    diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index ab2614af95..6c10e9ecd4 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -786,7 +786,10 @@ "Change notification settings": "Change notification settings", "Spaces": "Spaces", "Spaces are a new way to group people and rooms for fun, work, yourself or anything in between.": "Spaces are a new way to group people and rooms for fun, work, yourself or anything in between.", - "%(brand)s will reload with Spaces enabled, and communities and custom tags disabled. You can leave the beta at anytime. Certain features will require a compatible homeserver. Beta only available for Web, Desktop, and Android.": "%(brand)s will reload with Spaces enabled, and communities and custom tags disabled. You can leave the beta at anytime. Certain features will require a compatible homeserver. Beta only available for Web, Desktop, and Android.", + "%(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "%(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.", + "Beta available for web, desktop and Android. Thank you for trying the beta.": "Beta available for web, desktop and Android. Thank you for trying the beta.", + "%(brand)s will reload with Spaces enabled, communities and custom tags hidden.": "%(brand)s will reload with Spaces enabled, communities and custom tags hidden.", + "Beta available for web, desktop and Android. Some features may be unavailable on your homeserver.": "Beta available for web, desktop and Android. Some features may be unavailable on your homeserver.", "Show options to enable 'Do not disturb' mode": "Show options to enable 'Do not disturb' mode", "Send and receive voice messages (in development)": "Send and receive voice messages (in development)", "Render LaTeX maths in messages": "Render LaTeX maths in messages", @@ -2683,6 +2686,7 @@ "Inviting...": "Inviting...", "Invite your teammates": "Invite your teammates", "Make sure the right people have access. You can invite more later.": "Make sure the right people have access. You can invite more later.", + "This is an experimental feature. For now, new users receiving an invite will have to open the invite on to actually join.": "This is an experimental feature. For now, new users receiving an invite will have to open the invite on to actually join.", "Invite by username": "Invite by username", "What are some things you want to discuss in %(spaceName)s?": "What are some things you want to discuss in %(spaceName)s?", "Let's create a room for each of them.": "Let's create a room for each of them.", diff --git a/src/settings/Settings.ts b/src/settings/Settings.tsx similarity index 96% rename from src/settings/Settings.ts rename to src/settings/Settings.tsx index 99f0ebecbb..907fc33a73 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.tsx @@ -16,7 +16,7 @@ limitations under the License. */ import { MatrixClient } from 'matrix-js-sdk/src/client'; -import type { ReactNode } from "react"; +import React, { ReactNode } from "react"; import { _t, _td } from '../languageHandler'; import { @@ -123,7 +123,7 @@ export interface ISetting { betaInfo?: { title: string; // _td caption: string; // _td - disclaimer?: (() => ReactNode) | string; // _td + disclaimer?: (enabled: boolean) => ReactNode; image: string; // require(...) }; } @@ -138,11 +138,25 @@ export const SETTINGS: {[setting: string]: ISetting} = { title: _td("Spaces"), caption: _td("Spaces are a new way to group people and rooms for fun, " + "work, yourself or anything in between."), - disclaimer: () => _t("%(brand)s will reload with Spaces enabled, " + - "and communities and custom tags disabled. " + - "You can leave the beta at anytime. " + - "Certain features will require a compatible homeserver. " + - "Beta only available for Web, Desktop, and Android.", { brand: SdkConfig.get().brand }), + disclaimer: (enabled) => { + if (enabled) { + return <> +

    { _t("%(brand)s will reload with Spaces disabled. " + + "Communities and custom tags will be visible again.", { + brand: SdkConfig.get().brand, + }) }

    +

    { _t("Beta available for web, desktop and Android. Thank you for trying the beta.") }

    + ; + } + + return <> +

    { _t("%(brand)s will reload with Spaces enabled, communities and custom tags hidden.", { + brand: SdkConfig.get().brand, + }) }

    +

    { _t("Beta available for web, desktop and Android. " + + "Some features may be unavailable on your homeserver.") }

    + ; + }, image: require("../../res/img/betas/spaces.png"), }, }, From efb9b7190072cbc1f82693d3e06bd2039cce4859 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 28 Apr 2021 23:18:42 +0100 Subject: [PATCH 0124/1449] Make the text filter search all spaces instead of just the selected one --- src/stores/room-list/RoomListStore.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/stores/room-list/RoomListStore.ts b/src/stores/room-list/RoomListStore.ts index caab46a0c2..6e9216423a 100644 --- a/src/stores/room-list/RoomListStore.ts +++ b/src/stores/room-list/RoomListStore.ts @@ -601,7 +601,11 @@ export class RoomListStoreClass extends AsyncStoreWithClient { let rooms = this.matrixClient.getVisibleRooms().filter(r => VisibilityProvider.instance.isRoomVisible(r)); - if (this.prefilterConditions.length > 0) { + // if spaces are enabled only consider the prefilter conditions when there are no runtime conditions + // for the search all spaces feature + if (this.prefilterConditions.length > 0 + && (!SettingsStore.getValue("feature_spaces") || !this.filterConditions.length) + ) { rooms = rooms.filter(r => { for (const filter of this.prefilterConditions) { if (!filter.isVisible(r)) { @@ -675,6 +679,10 @@ export class RoomListStoreClass extends AsyncStoreWithClient { if (this.algorithm) { this.algorithm.addFilterCondition(filter); } + // Runtime filters with spaces disable prefiltering for the search all spaces effect + if (SettingsStore.getValue("feature_spaces")) { + promise = this.recalculatePrefiltering(); + } } promise.then(() => this.updateFn.trigger()); } @@ -698,6 +706,10 @@ export class RoomListStoreClass extends AsyncStoreWithClient { if (this.algorithm) { this.algorithm.removeFilterCondition(filter); + // Runtime filters with spaces disable prefiltering for the search all spaces effect + if (SettingsStore.getValue("feature_spaces")) { + promise = this.recalculatePrefiltering(); + } } } idx = this.prefilterConditions.indexOf(filter); From bed52319bcc46c67df9c6d561908faec5a939ffb Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 28 Apr 2021 23:39:24 +0100 Subject: [PATCH 0125/1449] Sort rooms in the add existing to space dialog based on recency --- .../dialogs/AddExistingToSpaceDialog.tsx | 7 +- .../algorithms/tag-sorting/RecentAlgorithm.ts | 140 +++++++++--------- 2 files changed, 77 insertions(+), 70 deletions(-) diff --git a/src/components/views/dialogs/AddExistingToSpaceDialog.tsx b/src/components/views/dialogs/AddExistingToSpaceDialog.tsx index 1f45a76008..2253b525e0 100644 --- a/src/components/views/dialogs/AddExistingToSpaceDialog.tsx +++ b/src/components/views/dialogs/AddExistingToSpaceDialog.tsx @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {useContext, useState} from "react"; +import React, {useContext, useMemo, useState} from "react"; import classNames from "classnames"; import {Room} from "matrix-js-sdk/src/models/room"; import {MatrixClient} from "matrix-js-sdk/src/client"; @@ -34,6 +34,7 @@ import DMRoomMap from "../../../utils/DMRoomMap"; import {calculateRoomVia} from "../../../utils/permalinks/Permalinks"; import StyledCheckbox from "../elements/StyledCheckbox"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; +import {sortRooms} from "../../../stores/room-list/algorithms/tag-sorting/RecentAlgorithm"; interface IProps extends IDialogProps { matrixClient: MatrixClient; @@ -57,6 +58,8 @@ interface IAddExistingToSpaceProps { export const AddExistingToSpace: React.FC = ({ space, selected, onChange }) => { const cli = useContext(MatrixClientContext); + const visibleRooms = useMemo(() => sortRooms(cli.getVisibleRooms()), [cli]); + const [query, setQuery] = useState(""); const lcQuery = query.toLowerCase(); @@ -65,7 +68,7 @@ export const AddExistingToSpace: React.FC = ({ space, const existingRoomsSet = new Set(SpaceStore.instance.getChildRooms(space.roomId)); const joinRule = space.getJoinRule(); - const [spaces, rooms, dms] = cli.getVisibleRooms().reduce((arr, room) => { + const [spaces, rooms, dms] = visibleRooms.reduce((arr, room) => { if (room.getMyMembership() !== "join") return arr; if (!room.name.toLowerCase().includes(lcQuery)) return arr; diff --git a/src/stores/room-list/algorithms/tag-sorting/RecentAlgorithm.ts b/src/stores/room-list/algorithms/tag-sorting/RecentAlgorithm.ts index 7c8c879cf6..49cfd9e520 100644 --- a/src/stores/room-list/algorithms/tag-sorting/RecentAlgorithm.ts +++ b/src/stores/room-list/algorithms/tag-sorting/RecentAlgorithm.ts @@ -21,79 +21,83 @@ import { MatrixClientPeg } from "../../../../MatrixClientPeg"; import * as Unread from "../../../../Unread"; import { EffectiveMembership, getEffectiveMembership } from "../../../../utils/membership"; +export const sortRooms = (rooms: Room[]): Room[] => { + // We cache the timestamp lookup to avoid iterating forever on the timeline + // of events. This cache only survives a single sort though. + // We wouldn't need this if `.sort()` didn't constantly try and compare all + // of the rooms to each other. + + // TODO: We could probably improve the sorting algorithm here by finding changes. + // See https://github.com/vector-im/element-web/issues/14459 + // For example, if we spent a little bit of time to determine which elements have + // actually changed (probably needs to be done higher up?) then we could do an + // insertion sort or similar on the limited set of changes. + + // TODO: Don't assume we're using the same client as the peg + // See https://github.com/vector-im/element-web/issues/14458 + let myUserId = ''; + if (MatrixClientPeg.get()) { + myUserId = MatrixClientPeg.get().getUserId(); + } + + const tsCache: { [roomId: string]: number } = {}; + const getLastTs = (r: Room) => { + if (tsCache[r.roomId]) { + return tsCache[r.roomId]; + } + + const ts = (() => { + // Apparently we can have rooms without timelines, at least under testing + // environments. Just return MAX_INT when this happens. + if (!r || !r.timeline) { + return Number.MAX_SAFE_INTEGER; + } + + // If the room hasn't been joined yet, it probably won't have a timeline to + // parse. We'll still fall back to the timeline if this fails, but chances + // are we'll at least have our own membership event to go off of. + const effectiveMembership = getEffectiveMembership(r.getMyMembership()); + if (effectiveMembership !== EffectiveMembership.Join) { + const membershipEvent = r.currentState.getStateEvents("m.room.member", myUserId); + if (membershipEvent && !Array.isArray(membershipEvent)) { + return membershipEvent.getTs(); + } + } + + for (let i = r.timeline.length - 1; i >= 0; --i) { + const ev = r.timeline[i]; + if (!ev.getTs()) continue; // skip events that don't have timestamps (tests only?) + + if (ev.getSender() === myUserId || Unread.eventTriggersUnreadCount(ev)) { + return ev.getTs(); + } + } + + // we might only have events that don't trigger the unread indicator, + // in which case use the oldest event even if normally it wouldn't count. + // This is better than just assuming the last event was forever ago. + if (r.timeline.length && r.timeline[0].getTs()) { + return r.timeline[0].getTs(); + } else { + return Number.MAX_SAFE_INTEGER; + } + })(); + + tsCache[r.roomId] = ts; + return ts; + }; + + return rooms.sort((a, b) => { + return getLastTs(b) - getLastTs(a); + }); +}; + /** * Sorts rooms according to the last event's timestamp in each room that seems * useful to the user. */ export class RecentAlgorithm implements IAlgorithm { public async sortRooms(rooms: Room[], tagId: TagID): Promise { - // We cache the timestamp lookup to avoid iterating forever on the timeline - // of events. This cache only survives a single sort though. - // We wouldn't need this if `.sort()` didn't constantly try and compare all - // of the rooms to each other. - - // TODO: We could probably improve the sorting algorithm here by finding changes. - // See https://github.com/vector-im/element-web/issues/14459 - // For example, if we spent a little bit of time to determine which elements have - // actually changed (probably needs to be done higher up?) then we could do an - // insertion sort or similar on the limited set of changes. - - // TODO: Don't assume we're using the same client as the peg - // See https://github.com/vector-im/element-web/issues/14458 - let myUserId = ''; - if (MatrixClientPeg.get()) { - myUserId = MatrixClientPeg.get().getUserId(); - } - - const tsCache: { [roomId: string]: number } = {}; - const getLastTs = (r: Room) => { - if (tsCache[r.roomId]) { - return tsCache[r.roomId]; - } - - const ts = (() => { - // Apparently we can have rooms without timelines, at least under testing - // environments. Just return MAX_INT when this happens. - if (!r || !r.timeline) { - return Number.MAX_SAFE_INTEGER; - } - - // If the room hasn't been joined yet, it probably won't have a timeline to - // parse. We'll still fall back to the timeline if this fails, but chances - // are we'll at least have our own membership event to go off of. - const effectiveMembership = getEffectiveMembership(r.getMyMembership()); - if (effectiveMembership !== EffectiveMembership.Join) { - const membershipEvent = r.currentState.getStateEvents("m.room.member", myUserId); - if (membershipEvent && !Array.isArray(membershipEvent)) { - return membershipEvent.getTs(); - } - } - - for (let i = r.timeline.length - 1; i >= 0; --i) { - const ev = r.timeline[i]; - if (!ev.getTs()) continue; // skip events that don't have timestamps (tests only?) - - if (ev.getSender() === myUserId || Unread.eventTriggersUnreadCount(ev)) { - return ev.getTs(); - } - } - - // we might only have events that don't trigger the unread indicator, - // in which case use the oldest event even if normally it wouldn't count. - // This is better than just assuming the last event was forever ago. - if (r.timeline.length && r.timeline[0].getTs()) { - return r.timeline[0].getTs(); - } else { - return Number.MAX_SAFE_INTEGER; - } - })(); - - tsCache[r.roomId] = ts; - return ts; - }; - - return rooms.sort((a, b) => { - return getLastTs(b) - getLastTs(a); - }); + return sortRooms(rooms); } } From e390c3c732d43fce284bfe4cdf6741d92f2da1cf Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 29 Apr 2021 09:37:21 +0100 Subject: [PATCH 0126/1449] Inhibit sending RR when context switching to a room --- src/components/structures/RoomView.tsx | 5 +++++ src/components/structures/TimelinePanel.js | 6 +++++- src/stores/RoomViewStore.tsx | 12 +++++++++++- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index 7168b7d139..5108643673 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -190,6 +190,9 @@ export interface IState { rejectError?: Error; hasPinnedWidgets?: boolean; dragCounter: number; + // whether or not a spaces context switch brought us here, + // if it did we don't want the room to be marked as read as soon as it is loaded. + wasContextSwitch?: boolean; } @replaceableComponent("structures.RoomView") @@ -326,6 +329,7 @@ export default class RoomView extends React.Component { shouldPeek: this.state.matrixClientIsReady && RoomViewStore.shouldPeek(), showingPinned: SettingsStore.getValue("PinnedEvents.isOpen", roomId), showReadReceipts: SettingsStore.getValue("showReadReceipts", roomId), + wasContextSwitch: RoomViewStore.getWasContextSwitch(), }; if (!initial && this.state.shouldPeek && !newState.shouldPeek) { @@ -2014,6 +2018,7 @@ export default class RoomView extends React.Component { timelineSet={this.state.room.getUnfilteredTimelineSet()} showReadReceipts={this.state.showReadReceipts} manageReadReceipts={!this.state.isPeeking} + sendReadReceiptOnLoad={!this.state.wasContextSwitch} manageReadMarkers={!this.state.isPeeking} hidden={hideMessagePanel} highlightedEventId={highlightedEventId} diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index 12f5d6e890..755a4e7784 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -68,6 +68,7 @@ class TimelinePanel extends React.Component { showReadReceipts: PropTypes.bool, // Enable managing RRs and RMs. These require the timelineSet to have a room. manageReadReceipts: PropTypes.bool, + sendReadReceiptOnLoad: PropTypes.bool, manageReadMarkers: PropTypes.bool, // true to give the component a 'display: none' style. @@ -126,6 +127,7 @@ class TimelinePanel extends React.Component { // event tile heights. (See _unpaginateEvents) timelineCap: Number.MAX_VALUE, className: 'mx_RoomView_messagePanel', + sendReadReceiptOnLoad: true, }; constructor(props) { @@ -1049,7 +1051,9 @@ class TimelinePanel extends React.Component { this._messagePanel.current.scrollToBottom(); } - this.sendReadReceipt(); + if (this.props.sendReadReceiptOnLoad) { + this.sendReadReceipt(); + } }); }; diff --git a/src/stores/RoomViewStore.tsx b/src/stores/RoomViewStore.tsx index a5bdb7ef33..fe2e0a66b2 100644 --- a/src/stores/RoomViewStore.tsx +++ b/src/stores/RoomViewStore.tsx @@ -62,6 +62,8 @@ const INITIAL_STATE = { shouldPeek: false, viaServers: [], + + wasContextSwitch: false, }; /** @@ -116,6 +118,7 @@ class RoomViewStore extends Store { roomId: null, roomAlias: null, viaServers: [], + wasContextSwitch: false, }); break; case 'view_room_error': @@ -195,6 +198,7 @@ class RoomViewStore extends Store { // pull the user out of Room Settings isEditingSettings: false, viaServers: payload.via_servers, + wasContextSwitch: payload.context_switch, }; // Allow being given an event to be replied to when switching rooms but sanity check its for this room @@ -231,6 +235,7 @@ class RoomViewStore extends Store { roomLoading: true, roomLoadError: null, viaServers: payload.via_servers, + wasContextSwitch: payload.context_switch, }); try { const result = await MatrixClientPeg.get().getRoomIdForAlias(payload.room_alias); @@ -256,6 +261,8 @@ class RoomViewStore extends Store { room_alias: payload.room_alias, auto_join: payload.auto_join, oob_data: payload.oob_data, + viaServers: payload.via_servers, + wasContextSwitch: payload.context_switch, }); } } @@ -266,7 +273,6 @@ class RoomViewStore extends Store { roomAlias: payload.room_alias, roomLoading: false, roomLoadError: payload.err, - viaServers: [], }); } @@ -426,6 +432,10 @@ class RoomViewStore extends Store { public shouldPeek() { return this.state.shouldPeek; } + + public getWasContextSwitch() { + return this.state.wasContextSwitch; + } } let singletonRoomViewStore = null; From 7552801103f8ed8a2c1d11673cc6fc10f3e8686f Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 29 Apr 2021 09:48:23 +0100 Subject: [PATCH 0127/1449] Room List respect the prefilter for new rooms --- src/stores/room-list/RoomListStore.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/stores/room-list/RoomListStore.ts b/src/stores/room-list/RoomListStore.ts index caab46a0c2..2ed3a2718d 100644 --- a/src/stores/room-list/RoomListStore.ts +++ b/src/stores/room-list/RoomListStore.ts @@ -426,6 +426,10 @@ export class RoomListStoreClass extends AsyncStoreWithClient { return; // don't do anything on rooms that aren't visible } + if (cause === RoomUpdateCause.NewRoom && !this.prefilterConditions.every(c => c.isVisible(room))) { + return; // don't do anything on new rooms which ought not to be shown + } + const shouldUpdate = await this.algorithm.handleRoomUpdate(room, cause); if (shouldUpdate) { if (SettingsStore.getValue("advancedRoomListLogging")) { From 036bc50b5dcb9370135f3e371868669640129605 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 29 Apr 2021 12:29:22 +0100 Subject: [PATCH 0128/1449] Disable groups routes when spaces is enabled to avoid confusion --- src/components/structures/MatrixChat.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index 3da5d3b6dc..43b1d57ca9 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -1686,6 +1686,10 @@ export default class MatrixChat extends React.PureComponent { const type = screen === "start_sso" ? "sso" : "cas"; PlatformPeg.get().startSingleSignOn(cli, type, this.getFragmentAfterLogin()); } else if (screen === 'groups') { + if (SettingsStore.getValue("feature_spaces")) { + dis.dispatch({ action: "view_home_page" }); + return; + } dis.dispatch({ action: 'view_my_groups', }); @@ -1769,6 +1773,11 @@ export default class MatrixChat extends React.PureComponent { subAction: params.action, }); } else if (screen.indexOf('group/') === 0) { + if (SettingsStore.getValue("feature_spaces")) { + dis.dispatch({ action: "view_home_page" }); + return; + } + const groupId = screen.substring(6); // TODO: Check valid group ID From 286463606c14258975d9355c6b53b920de93a935 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 29 Apr 2021 13:52:48 +0100 Subject: [PATCH 0129/1449] Spaces fix edge cases around automatic space switching around room navigation --- src/stores/SpaceStore.tsx | 49 +++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/src/stores/SpaceStore.tsx b/src/stores/SpaceStore.tsx index ec6227e45e..8e86253f75 100644 --- a/src/stores/SpaceStore.tsx +++ b/src/stores/SpaceStore.tsx @@ -410,6 +410,22 @@ export class SpaceStoreClass extends AsyncStoreWithClient { }); }, 100, {trailing: true, leading: true}); + private switchToRelatedSpace = (roomId: string) => { + if (this.suggestedRooms.find(r => r.room_id === roomId)) return; + + let parent = this.getCanonicalParent(roomId); + if (!parent) { + parent = this.rootSpaces.find(s => this.spaceFilteredRooms.get(s.roomId)?.has(roomId)); + } + if (!parent) { + const parents = Array.from(this.parentMap.get(roomId) || []); + parent = parents.find(p => this.matrixClient.getRoom(p)); + } + + // don't trigger a context switch when we are switching a space to match the chosen room + this.setActiveSpace(parent || null, false); + }; + private onRoom = (room: Room, newMembership?: string, oldMembership?: string) => { const membership = newMembership || room.getMyMembership(); @@ -424,6 +440,11 @@ export class SpaceStoreClass extends AsyncStoreWithClient { if (numSuggestedRooms !== this._suggestedRooms.length) { this.emit(SUGGESTED_ROOMS, this._suggestedRooms); } + + // if the room currently being viewed was just joined then switch to its related space + if (newMembership === "join" && room.roomId === RoomViewStore.getRoomId()) { + this.switchToRelatedSpace(room.roomId); + } } return; } @@ -442,7 +463,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient { if (membership === "join" && room.roomId === RoomViewStore.getRoomId()) { // if the user was looking at the space and then joined: select that space - this.setActiveSpace(room); + this.setActiveSpace(room, false); } }; @@ -542,10 +563,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient { // restore selected state from last session if any and still valid const lastSpaceId = window.localStorage.getItem(ACTIVE_SPACE_LS_KEY); if (lastSpaceId) { - const space = this.rootSpaces.find(s => s.roomId === lastSpaceId); - if (space) { - this.setActiveSpace(space); - } + this.setActiveSpace(this.matrixClient.getRoom(lastSpaceId)); } } @@ -553,27 +571,18 @@ export class SpaceStoreClass extends AsyncStoreWithClient { if (!SettingsStore.getValue("feature_spaces")) return; switch (payload.action) { case "view_room": { - const room = this.matrixClient?.getRoom(payload.room_id); - // Don't auto-switch rooms when reacting to a context-switch // as this is not helpful and can create loops of rooms/space switching - if (!room || payload.context_switch) break; + if (payload.context_switch) break; - if (room.isSpaceRoom()) { + const roomId = payload.room_id; + const room = this.matrixClient?.getRoom(roomId); + if (room?.isSpaceRoom()) { // Don't context switch when navigating to the space room // as it will cause you to end up in the wrong room this.setActiveSpace(room, false); - } else if (!this.getSpaceFilteredRoomIds(this.activeSpace).has(room.roomId)) { - let parent = this.getCanonicalParent(room.roomId); - if (!parent) { - parent = this.rootSpaces.find(s => this.spaceFilteredRooms.get(s.roomId)?.has(room.roomId)); - } - if (!parent) { - const parents = Array.from(this.parentMap.get(room.roomId) || []); - parent = parents.find(p => this.matrixClient.getRoom(p)); - } - // don't trigger a context switch when we are switching a space to match the chosen room - this.setActiveSpace(parent || null, false); + } else if (!this.getSpaceFilteredRoomIds(this.activeSpace).has(roomId)) { + this.switchToRelatedSpace(roomId); } // Persist last viewed room from a space From ce28e5f122a5e03542b73456eef4802d43f83ea0 Mon Sep 17 00:00:00 2001 From: Christian Paul Date: Thu, 29 Apr 2021 14:56:18 +0000 Subject: [PATCH 0130/1449] Translated using Weblate (German) Currently translated at 99.0% (2895 of 2924 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 54afb5c22a..b17b28245e 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -2028,7 +2028,7 @@ "Doesn't look like a valid email address": "Das sieht nicht nach einer gültigen E-Mail-Adresse aus", "Enter phone number (required on this homeserver)": "Telefonnummer eingeben (auf diesem Heimserver erforderlich)", "Doesn't look like a valid phone number": "Das sieht nicht nach einer gültigen Telefonnummer aus", - "Sign in with SSO": "Mit Single-Sign-On anmelden", + "Sign in with SSO": "Mit „Single Sign-On“ anmelden", "Welcome to %(appName)s": "Willkommen bei %(appName)s", "Send a Direct Message": "Direktnachricht senden", "Create a Group Chat": "Gruppenchat erstellen", From d1c07a0e230e9e1d7eb0a9a7165609a2b5899841 Mon Sep 17 00:00:00 2001 From: libexus Date: Thu, 29 Apr 2021 14:55:35 +0000 Subject: [PATCH 0131/1449] Translated using Weblate (German) Currently translated at 99.0% (2895 of 2924 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index b17b28245e..b1a91c8c8b 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -125,7 +125,7 @@ "Sat": "Sa", "Jan": "Jan", "Feb": "Feb", - "Mar": "Mrz", + "Mar": "Mär", "Apr": "Apr", "May": "Mai", "Jun": "Jun", @@ -708,7 +708,7 @@ "Messages containing keywords": "Nachrichten mit Schlüsselwörtern", "Error saving email notification preferences": "Fehler beim Speichern der E-Mail-Benachrichtigungseinstellungen", "Tuesday": "Dienstag", - "Enter keywords separated by a comma:": "Schlüsselwörter kommagetrennt eingeben:", + "Enter keywords separated by a comma:": "Gib die Schlüsselwörter durch einen Beistrich getrennt ein:", "Forward Message": "Nachricht weiterleiten", "You have successfully set a password and an email address!": "Du hast erfolgreich ein Passwort und eine E-Mail-Adresse gesetzt!", "Remove %(name)s from the directory?": "Soll der Raum %(name)s aus dem Verzeichnis entfernt werden?", @@ -903,7 +903,7 @@ "Avoid repeated words and characters": "Vermeide wiederholte Worte und Zeichen", "Avoid sequences": "Vermeide Sätze", "Avoid recent years": "Vermeide die letzten Jahre", - "Avoid years that are associated with you": "Vermeide Jahre, die mit dir zusammenhängen", + "Avoid years that are associated with you": "Vermeide Jahreszahlen, die mit dir zu tun haben", "Avoid dates and years that are associated with you": "Vermeide Daten und Jahre, die mit dir in Verbindung stehen", "Capitalization doesn't help very much": "Großschreibung hilft nicht viel", "All-uppercase is almost as easy to guess as all-lowercase": "Alles groß zu schreiben ist genauso einfach zu erraten, wie alles klein zu schreiben", @@ -1101,12 +1101,12 @@ "Folder": "Ordner", "Pin": "Anheften", "Timeline": "Chatverlauf", - "Autocomplete delay (ms)": "Verzögerung zur Autovervollständigung (ms)", + "Autocomplete delay (ms)": "Verzögerung vor Autovervollständigung (ms)", "Roles & Permissions": "Rollen und Berechtigungen", "Changes to who can read history will only apply to future messages in this room. The visibility of existing history will be unchanged.": "Änderungen an der Sichtbarkeit des Chatverlaufs gelten nur für zukünftige Nachrichten. Die Sichtbarkeit des existierenden Verlaufs bleibt unverändert.", "Security & Privacy": "Sicherheit", "Encryption": "Verschlüsselung", - "Once enabled, encryption cannot be disabled.": "Sobald aktiviert, kann die Verschlüsselung nicht mehr deaktiviert werden.", + "Once enabled, encryption cannot be disabled.": "Sobald du die Verschlüsselung aktivierst, kann du sie nicht mehr deaktivieren.", "Encrypted": "Verschlüsselt", "Ignored users": "Blockierte Benutzer", "Key backup": "Schlüsselsicherung", @@ -1249,7 +1249,7 @@ "Please supply a https:// or http:// widget URL": "Bitte gib eine mit https:// oder http:// beginnende Widget-URL an", "Sends the given emote coloured as a rainbow": "Zeigt Aktionen in Regenbogenfarben", "%(senderName)s made no change.": "%(senderName)s hat keine Änderung vorgenommen.", - "%(senderName)s revoked the invitation for %(targetDisplayName)s to join the room.": "%(senderName)s hat die Einladung zum Raumbeitritt für %(targetDisplayName)s zurückgezogen.", + "%(senderName)s revoked the invitation for %(targetDisplayName)s to join the room.": "%(senderName)s hat die Einladung für %(targetDisplayName)s zurückgezogen.", "Cannot reach homeserver": "Der Heimserver ist nicht erreichbar", "Ensure you have a stable internet connection, or get in touch with the server admin": "Stelle sicher, dass du eine stabile Internetverbindung hast oder wende dich an deinen Serveradministrator", "Ask your %(brand)s admin to check your config for incorrect or duplicate entries.": "Wende dich an deinen %(brand)s-Admin um deine Konfiguration auf ungültige oder doppelte Einträge zu überprüfen.", @@ -2178,7 +2178,7 @@ "Waiting for your other session to verify…": "Warte auf die Verifikation deiner anderen Sitzungen…", "You've successfully verified your device!": "Du hast dein Gerät erfolgreich verifiziert!", "QR Code": "QR-Code", - "To continue, use Single Sign On to prove your identity.": "Zum Fortfahren, nutze Single Sign-On um deine Identität zu bestätigen.", + "To continue, use Single Sign On to prove your identity.": "Zum Fortfahren nutze Single Sign-On, um deine Identität zu bestätigen.", "Confirm to continue": "Bestätige um fortzufahren", "Click the button below to confirm your identity.": "Klicke den Button unten um deine Identität zu bestätigen.", "Confirm encryption setup": "Bestätige die Einrichtung der Verschlüsselung", @@ -2257,7 +2257,7 @@ "Light": "Hell", "Dark": "Dunkel", "Use the improved room list (will refresh to apply changes)": "Verwende die verbesserte Raumliste (lädt die Anwendung neu)", - "Use custom size": "Verwende individuelle Größe", + "Use custom size": "Andere Schriftgröße verwenden", "Hey you. You're the best!": "Hey du. Du bist großartig!", "Message layout": "Nachrichtenlayout", "Compact": "Kompakt", @@ -2570,7 +2570,7 @@ "Change the avatar of this room": "Icon von diesem Raum ändern", "See when the avatar changes in this room": "Sehen, wenn sich das Icon des Raums ändert", "Change the avatar of your active room": "Den Avatar deines aktiven Raums ändern", - "See when the avatar changes in your active room": "Sehen wenn ein Avatar in deinem aktiven Raum geändert wird", + "See when the avatar changes in your active room": "Sehen, wenn das Icon in deinem aktiven Raum geändert wird", "Send stickers to this room as you": "Einen Sticker in diesen Raum senden", "See when a sticker is posted in this room": "Sehe wenn ein Sticker in diesen Raum gesendet wird", "Send stickers to your active room as you": "Einen Sticker als du in deinen aktiven Raum senden", @@ -3003,7 +3003,7 @@ "Workspace: ": "Arbeitsraum: ", "Dial pad": "Wähltastatur", "There was an error looking up the phone number": "Beim Suchen der Telefonnummer ist ein Fehler aufgetreten", - "Change which room, message, or user you're viewing": "Ändere welchen Raum, Nachricht oder Nutzer du siehst", + "Change which room, message, or user you're viewing": "Ändere den sichtbaren Raum, Nachricht oder Nutzer", "Unable to look up phone number": "Telefonnummer konnte nicht gefunden werden", "This session has detected that your Security Phrase and key for Secure Messages have been removed.": "In dieser Sitzung wurde festgestellt, dass deine Sicherheitsphrase und dein Schlüssel für sichere Nachrichten entfernt wurden.", "A new Security Phrase and key for Secure Messages have been detected.": "Eine neue Sicherheitsphrase und ein neuer Schlüssel für sichere Nachrichten wurden erkannt.", From 284e7a9e6483eac91a89e4ef509915172c2ca3ff Mon Sep 17 00:00:00 2001 From: Sven Grewe Date: Thu, 29 Apr 2021 14:39:27 +0000 Subject: [PATCH 0132/1449] Translated using Weblate (German) Currently translated at 99.0% (2895 of 2924 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index b1a91c8c8b..739f0d0c57 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -582,7 +582,7 @@ "Notify the whole room": "Alle im Raum benachrichtigen", "Room Notification": "Raum-Benachrichtigung", "These rooms are displayed to community members on the community page. Community members can join the rooms by clicking on them.": "Diese Räume werden Community-Mitgliedern auf der Community-Seite angezeigt. Community-Mitglieder können diesen Räumen beitreten, indem sie diese anklicken.", - "Show these rooms to non-members on the community page and room list?": "Sollen diese Räume öffentlich auf der Community-Seite und in der Raum-Liste angezeigt werden?", + "Show these rooms to non-members on the community page and room list?": "Sollen diese Räume öffentlich auf der Communityseite und in der Raumliste angezeigt werden?", "

    HTML for your community's page

    \n

    \n Use the long description to introduce new members to the community, or distribute\n some important links\n

    \n

    \n You can even use 'img' tags\n

    \n": "

    HTML für deine Community-Seite

    \n

    \n Nutze die ausführliche Beschreibung, um neuen Mitgliedern diese Community vorzustellen\n oder um wichtige Links bereitzustellen.\n

    \n

    \n Du kannst sogar 'img'-Tags (HTML) verwenden\n

    \n", "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!": "Deine Community hat noch keine ausführliche Beschreibung, d. h. eine HTML-Seite, die Community-Mitgliedern angezeigt wird.
    Hier klicken, um die Einstellungen zu öffnen und eine Beschreibung zu erstellen!", "Enable inline URL previews by default": "URL-Vorschau standardmäßig aktivieren", From 279654cc9ea052bab065c208269a63614877787a Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 29 Apr 2021 16:08:59 +0100 Subject: [PATCH 0133/1449] Design iterations based on PR feedback --- res/css/structures/_SpaceRoomView.scss | 22 ++++++++++++++++--- res/css/views/beta/_BetaCard.scss | 1 + src/components/structures/MyGroups.js | 2 +- src/components/structures/SpaceRoomView.tsx | 2 +- src/components/views/beta/BetaCard.tsx | 21 ++++++++++++++++++ .../views/spaces/SpaceCreateMenu.tsx | 1 + src/i18n/strings/en_EN.json | 9 +++++--- src/settings/Settings.tsx | 8 ++++--- 8 files changed, 55 insertions(+), 11 deletions(-) diff --git a/res/css/structures/_SpaceRoomView.scss b/res/css/structures/_SpaceRoomView.scss index 04f8e02a9e..f7123fc4cb 100644 --- a/res/css/structures/_SpaceRoomView.scss +++ b/res/css/structures/_SpaceRoomView.scss @@ -143,10 +143,13 @@ $SpaceRoomViewInnerWidth: 428px; } // XXX remove this when spaces leaves Beta .mx_SpaceRoomView_preview_spaceBetaPrompt { - font-size: $font-15px; + font-weight: $font-semi-bold; + font-size: $font-14px; line-height: $font-24px; - color: $secondary-fg-color; - margin-top: 14px; + color: $primary-fg-color; + margin-top: 24px; + position: relative; + padding-left: 24px; .mx_AccessibleButton_kind_link { display: inline; @@ -154,6 +157,19 @@ $SpaceRoomViewInnerWidth: 428px; font-size: inherit; line-height: inherit; } + + &::before { + content: ""; + position: absolute; + height: $font-24px; + width: 20px; + left: 0; + mask-repeat: no-repeat; + mask-position: center; + mask-size: contain; + mask-image: url('$(res)/img/element-icons/room/room-summary.svg'); + background-color: $secondary-fg-color; + } } .mx_SpaceRoomView_preview_inviter { diff --git a/res/css/views/beta/_BetaCard.scss b/res/css/views/beta/_BetaCard.scss index 34b84515ce..05149b7f6c 100644 --- a/res/css/views/beta/_BetaCard.scss +++ b/res/css/views/beta/_BetaCard.scss @@ -45,6 +45,7 @@ limitations under the License. display: block; margin: 20px 0; padding: 12px 40px; + width: max-content; } .mx_BetaCard_disclaimer { diff --git a/src/components/structures/MyGroups.js b/src/components/structures/MyGroups.js index 14f22827a9..1fab6c4348 100644 --- a/src/components/structures/MyGroups.js +++ b/src/components/structures/MyGroups.js @@ -140,7 +140,7 @@ export default class MyGroups extends React.Component {
    */}
    - +
    { contentHeader } { content } diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx index 3d01c7cc2b..82a211c291 100644 --- a/src/components/structures/SpaceRoomView.tsx +++ b/src/components/structures/SpaceRoomView.tsx @@ -604,7 +604,7 @@ const SpaceSetupPrivateInvite = ({ space, onFinished }) => {
    - + { _t("This is an experimental feature. For now, " + "new users receiving an invite will have to open the invite on to actually join.", {}, { b: sub => { sub }, diff --git a/src/components/views/beta/BetaCard.tsx b/src/components/views/beta/BetaCard.tsx index 33b1fef9e6..1233f345d1 100644 --- a/src/components/views/beta/BetaCard.tsx +++ b/src/components/views/beta/BetaCard.tsx @@ -21,6 +21,7 @@ import {_t} from "../../../languageHandler"; import AccessibleButton from "../elements/AccessibleButton"; import SettingsStore from "../../../settings/SettingsStore"; import {SettingLevel} from "../../../settings/SettingLevel"; +import TextWithTooltip from "../elements/TextWithTooltip"; interface IProps { title?: string; @@ -28,6 +29,26 @@ interface IProps { } export const BetaPill = ({ onClick }: { onClick?: () => void }) => { + if (onClick) { + return +
    + { _t("Spaces is a beta feature") } +
    +
    + { _t("Tap for more info") } +
    +
    } + onClick={onClick} + tooltipProps={{ yOffset: -10 }} + > + { _t("Beta") } + ; + } + return { > { + onFinished(); defaultDispatcher.dispatch({ action: Action.ViewUserSettings, initialTabId: USER_LABS_TAB, diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 2367cf777a..7f5205efa3 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -785,10 +785,11 @@ "%(senderName)s: %(stickerName)s": "%(senderName)s: %(stickerName)s", "Change notification settings": "Change notification settings", "Spaces": "Spaces", - "Spaces are a new way to group people and rooms for fun, work, yourself or anything in between.": "Spaces are a new way to group people and rooms for fun, work, yourself or anything in between.", + "Spaces are new ways to group rooms and people.": "Spaces are new ways to group rooms and people.", "%(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "%(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.", "Beta available for web, desktop and Android. Thank you for trying the beta.": "Beta available for web, desktop and Android. Thank you for trying the beta.", - "%(brand)s will reload with Spaces enabled, communities and custom tags hidden.": "%(brand)s will reload with Spaces enabled, communities and custom tags hidden.", + "%(brand)s will reload with Spaces enabled. Communities and custom tags will be hidden.": "%(brand)s will reload with Spaces enabled. Communities and custom tags will be hidden.", + "You can leave the beta any time from settings or tapping on a beta badge, like the one above.": "You can leave the beta any time from settings or tapping on a beta badge, like the one above.", "Beta available for web, desktop and Android. Some features may be unavailable on your homeserver.": "Beta available for web, desktop and Android. Some features may be unavailable on your homeserver.", "Show options to enable 'Do not disturb' mode": "Show options to enable 'Do not disturb' mode", "Send and receive voice messages (in development)": "Send and receive voice messages (in development)", @@ -2459,6 +2460,8 @@ "Revoke permissions": "Revoke permissions", "Move left": "Move left", "Move right": "Move right", + "Spaces is a beta feature": "Spaces is a beta feature", + "Tap for more info": "Tap for more info", "Beta": "Beta", "Leave the beta": "Leave the beta", "Join the beta": "Join the beta", @@ -2595,7 +2598,7 @@ "Error whilst fetching joined communities": "Error whilst fetching joined communities", "Create a new community": "Create a new community", "Create a community to group together users and rooms! Build a custom homepage to mark out your space in the Matrix universe.": "Create a community to group together users and rooms! Build a custom homepage to mark out your space in the Matrix universe.", - "Communities are changing to spaces": "Communities are changing to spaces", + "Communities are changing to Spaces": "Communities are changing to Spaces", "You’re all caught up": "You’re all caught up", "You have no visible notifications.": "You have no visible notifications.", "%(brand)s failed to get the protocol list from the homeserver. The homeserver may be too old to support third party networks.": "%(brand)s failed to get the protocol list from the homeserver. The homeserver may be too old to support third party networks.", diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx index 907fc33a73..5bda746646 100644 --- a/src/settings/Settings.tsx +++ b/src/settings/Settings.tsx @@ -136,8 +136,7 @@ export const SETTINGS: {[setting: string]: ISetting} = { controller: new ReloadOnChangeController(), betaInfo: { title: _td("Spaces"), - caption: _td("Spaces are a new way to group people and rooms for fun, " + - "work, yourself or anything in between."), + caption: _td("Spaces are new ways to group rooms and people."), disclaimer: (enabled) => { if (enabled) { return <> @@ -150,9 +149,12 @@ export const SETTINGS: {[setting: string]: ISetting} = { } return <> -

    { _t("%(brand)s will reload with Spaces enabled, communities and custom tags hidden.", { +

    { _t("%(brand)s will reload with Spaces enabled. " + + "Communities and custom tags will be hidden.", { brand: SdkConfig.get().brand, }) }

    +

    { _t("You can leave the beta any time from settings or tapping on a beta badge, " + + "like the one above.") }

    { _t("Beta available for web, desktop and Android. " + "Some features may be unavailable on your homeserver.") }

    ; From 62198601d27ad59f847b2e03b980cd120150a299 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 29 Apr 2021 16:40:08 +0100 Subject: [PATCH 0134/1449] Tweak room list filter placeholder and results copy for spaces --- src/components/structures/RoomSearch.tsx | 21 +++++++++++++++++-- .../views/rooms/RoomListNumResults.tsx | 6 +++++- src/i18n/strings/en_EN.json | 3 +++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/components/structures/RoomSearch.tsx b/src/components/structures/RoomSearch.tsx index a64feed42c..586a0825dd 100644 --- a/src/components/structures/RoomSearch.tsx +++ b/src/components/structures/RoomSearch.tsx @@ -17,6 +17,8 @@ limitations under the License. import * as React from "react"; import { createRef } from "react"; import classNames from "classnames"; +import { Room } from "matrix-js-sdk/src/models/room"; + import defaultDispatcher from "../../dispatcher/dispatcher"; import { _t } from "../../languageHandler"; import { ActionPayload } from "../../dispatcher/payloads"; @@ -26,7 +28,7 @@ import RoomListStore from "../../stores/room-list/RoomListStore"; import { NameFilterCondition } from "../../stores/room-list/filters/NameFilterCondition"; import { getKeyBindingsManager, RoomListAction } from "../../KeyBindingsManager"; import {replaceableComponent} from "../../utils/replaceableComponent"; -import SpaceStore, {UPDATE_SELECTED_SPACE} from "../../stores/SpaceStore"; +import SpaceStore, {UPDATE_SELECTED_SPACE, UPDATE_TOP_LEVEL_SPACES} from "../../stores/SpaceStore"; interface IProps { isMinimized: boolean; @@ -40,6 +42,7 @@ interface IProps { interface IState { query: string; focused: boolean; + inSpaces: boolean; } @replaceableComponent("structures.RoomSearch") @@ -54,11 +57,13 @@ export default class RoomSearch extends React.PureComponent { this.state = { query: "", focused: false, + inSpaces: false, }; this.dispatcherRef = defaultDispatcher.register(this.onAction); // clear filter when changing spaces, in future we may wish to maintain a filter per-space SpaceStore.instance.on(UPDATE_SELECTED_SPACE, this.clearInput); + SpaceStore.instance.on(UPDATE_TOP_LEVEL_SPACES, this.onSpaces); } public componentDidUpdate(prevProps: Readonly, prevState: Readonly): void { @@ -79,8 +84,15 @@ export default class RoomSearch extends React.PureComponent { public componentWillUnmount() { defaultDispatcher.unregister(this.dispatcherRef); SpaceStore.instance.off(UPDATE_SELECTED_SPACE, this.clearInput); + SpaceStore.instance.off(UPDATE_TOP_LEVEL_SPACES, this.onSpaces); } + private onSpaces = (spaces: Room[]) => { + this.setState({ + inSpaces: spaces.length > 0, + }); + }; + private onAction = (payload: ActionPayload) => { if (payload.action === 'view_room' && payload.clear_search) { this.clearInput(); @@ -152,6 +164,11 @@ export default class RoomSearch extends React.PureComponent { 'mx_RoomSearch_inputExpanded': this.state.query || this.state.focused, }); + let placeholder = _t("Filter"); + if (SpaceStore.instance.spacePanelSpaces.length) { + placeholder = _t("Filter all spaces"); + } + let icon = (
    ); @@ -165,7 +182,7 @@ export default class RoomSearch extends React.PureComponent { onBlur={this.onBlur} onChange={this.onChange} onKeyDown={this.onKeyDown} - placeholder={_t("Filter")} + placeholder={placeholder} autoComplete="off" /> ); diff --git a/src/components/views/rooms/RoomListNumResults.tsx b/src/components/views/rooms/RoomListNumResults.tsx index fcac91a56a..01cbecf05d 100644 --- a/src/components/views/rooms/RoomListNumResults.tsx +++ b/src/components/views/rooms/RoomListNumResults.tsx @@ -19,6 +19,7 @@ import React, {useState} from "react"; import { _t } from "../../../languageHandler"; import RoomListStore, { LISTS_UPDATE_EVENT } from "../../../stores/room-list/RoomListStore"; import {useEventEmitter} from "../../../hooks/useEventEmitter"; +import SpaceStore from "../../../stores/SpaceStore"; const RoomListNumResults: React.FC = () => { const [count, setCount] = useState(null); @@ -34,7 +35,10 @@ const RoomListNumResults: React.FC = () => { if (typeof count !== "number") return null; return
    - {_t("%(count)s results", { count })} + { SpaceStore.instance.spacePanelSpaces.length + ? _t("%(count)s results in all spaces", { count }) + : _t("%(count)s results", { count }) + }
    ; }; diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 85e8e54258..5863f2a834 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1552,6 +1552,8 @@ "Explore all public rooms": "Explore all public rooms", "Quick actions": "Quick actions", "Use the + to make a new room or explore existing ones below": "Use the + to make a new room or explore existing ones below", + "%(count)s results in all spaces|other": "%(count)s results in all spaces", + "%(count)s results in all spaces|one": "%(count)s result in all spaces", "%(count)s results|other": "%(count)s results", "%(count)s results|one": "%(count)s result", "This room": "This room", @@ -2612,6 +2614,7 @@ "If you can't find the room you're looking for, ask for an invite or Create a new room.": "If you can't find the room you're looking for, ask for an invite or Create a new room.", "Explore rooms in %(communityName)s": "Explore rooms in %(communityName)s", "Filter": "Filter", + "Filter all spaces": "Filter all spaces", "Clear filter": "Clear filter", "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.", From 73abe51fb93bf8b87a12f8a76d554710301358d3 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 29 Apr 2021 16:46:21 +0100 Subject: [PATCH 0135/1449] actually use the new state --- src/components/structures/RoomSearch.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/RoomSearch.tsx b/src/components/structures/RoomSearch.tsx index 586a0825dd..34682877e0 100644 --- a/src/components/structures/RoomSearch.tsx +++ b/src/components/structures/RoomSearch.tsx @@ -165,7 +165,7 @@ export default class RoomSearch extends React.PureComponent { }); let placeholder = _t("Filter"); - if (SpaceStore.instance.spacePanelSpaces.length) { + if (this.state.inSpaces) { placeholder = _t("Filter all spaces"); } From d2de115b2f5f0aab5adbfb38b80a025a52a2dd1d Mon Sep 17 00:00:00 2001 From: Jaiwanth Date: Thu, 29 Apr 2021 21:37:44 +0530 Subject: [PATCH 0136/1449] Generate room preview even when minimized Signed-off-by: Jaiwanth --- src/components/views/rooms/RoomTile.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/RoomTile.tsx b/src/components/views/rooms/RoomTile.tsx index 8521992fa1..07dca95284 100644 --- a/src/components/views/rooms/RoomTile.tsx +++ b/src/components/views/rooms/RoomTile.tsx @@ -131,7 +131,7 @@ export default class RoomTile extends React.PureComponent { } private get showMessagePreview(): boolean { - return !this.props.isMinimized && this.props.showMessagePreview; + return this.props.showMessagePreview; } public componentDidUpdate(prevProps: Readonly, prevState: Readonly) { From 70204d6111bef4d640d2b1980f531bd5039c95e9 Mon Sep 17 00:00:00 2001 From: Jaiwanth Date: Thu, 29 Apr 2021 22:41:57 +0530 Subject: [PATCH 0137/1449] Prevent peeking members from reacting Signed-off-by: Jaiwanth --- src/components/views/messages/ReactionsRowButton.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/views/messages/ReactionsRowButton.js b/src/components/views/messages/ReactionsRowButton.js index 06421c02a2..b37a949e57 100644 --- a/src/components/views/messages/ReactionsRowButton.js +++ b/src/components/views/messages/ReactionsRowButton.js @@ -129,12 +129,13 @@ export default class ReactionsRowButton extends React.PureComponent { }, ); } - + const isPeeking = room.getMyMembership() !== "join"; const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); return From 232b87a3b41fb3937e938d79e1c4af88b7f0be99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 29 Apr 2021 19:57:02 +0200 Subject: [PATCH 0138/1449] Improve formatting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/GroupAddressPicker.js | 16 +-- src/TextForEvent.js | 18 ++-- src/components/structures/GroupView.js | 79 +++++++------- src/components/structures/ScrollPanel.js | 27 ++--- .../views/dialogs/RoomSettingsDialog.js | 8 +- .../views/dialogs/StorageEvictedDialog.js | 5 +- .../views/dialogs/UserSettingsDialog.js | 8 +- .../dialogs/WidgetOpenIDPermissionsDialog.js | 7 +- .../ConfirmDestroyCrossSigningDialog.js | 3 +- .../security/RestoreKeyBackupDialog.js | 51 +++++---- .../views/elements/EditableItemList.js | 8 +- .../messages/MKeyVerificationConclusion.js | 4 +- .../views/rooms/ReadReceiptMarker.js | 3 +- src/indexing/EventIndex.js | 10 +- src/stores/CustomRoomTagStore.js | 4 +- src/utils/MegolmExportEncryption.js | 3 +- .../elements/MemberEventListSummary-test.js | 102 +++++++++--------- 17 files changed, 193 insertions(+), 163 deletions(-) diff --git a/src/GroupAddressPicker.js b/src/GroupAddressPicker.js index 58b65769ae..d956189f0d 100644 --- a/src/GroupAddressPicker.js +++ b/src/GroupAddressPicker.js @@ -148,13 +148,15 @@ function _onGroupAddRoomFinished(groupId, addrs, addRoomsPublicly) { const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); Modal.createTrackedDialog( 'Failed to add the following room to the group', - '', ErrorDialog, + '', + ErrorDialog, { - title: _t( - "Failed to add the following rooms to %(groupId)s:", - {groupId}, - ), - description: errorList.join(", "), - }); + title: _t( + "Failed to add the following rooms to %(groupId)s:", + {groupId}, + ), + description: errorList.join(", "), + }, + ); }); } diff --git a/src/TextForEvent.js b/src/TextForEvent.js index fd7b4fd18f..86f9ff20f4 100644 --- a/src/TextForEvent.js +++ b/src/TextForEvent.js @@ -547,17 +547,23 @@ function textForMjolnirEvent(event) { // else the entity !== prevEntity - count as a removal & add if (USER_RULE_TYPES.includes(event.getType())) { - return _t("%(senderName)s changed a rule that was banning users matching %(oldGlob)s to matching " + + return _t( + "%(senderName)s changed a rule that was banning users matching %(oldGlob)s to matching " + "%(newGlob)s for %(reason)s", - {senderName, oldGlob: prevEntity, newGlob: entity, reason}); + {senderName, oldGlob: prevEntity, newGlob: entity, reason}, + ); } else if (ROOM_RULE_TYPES.includes(event.getType())) { - return _t("%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching " + + return _t( + "%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching " + "%(newGlob)s for %(reason)s", - {senderName, oldGlob: prevEntity, newGlob: entity, reason}); + {senderName, oldGlob: prevEntity, newGlob: entity, reason}, + ); } else if (SERVER_RULE_TYPES.includes(event.getType())) { - return _t("%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching " + + return _t( + "%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching " + "%(newGlob)s for %(reason)s", - {senderName, oldGlob: prevEntity, newGlob: entity, reason}); + {senderName, oldGlob: prevEntity, newGlob: entity, reason}, + ); } // Unknown type. We'll say something but we shouldn't end up here. diff --git a/src/components/structures/GroupView.js b/src/components/structures/GroupView.js index ef74499473..c17bae9d49 100644 --- a/src/components/structures/GroupView.js +++ b/src/components/structures/GroupView.js @@ -44,14 +44,14 @@ import {replaceableComponent} from "../../utils/replaceableComponent"; const LONG_DESC_PLACEHOLDER = _td( `

    HTML for your community's page

    -

    - Use the long description to introduce new members to the community, or distribute - some important links -

    -

    - You can even add images with Matrix URLs -

    -`); +

    + Use the long description to introduce new members to the community, or distribute + some important links +

    +

    + You can even add images with Matrix URLs +

    `, +); const RoomSummaryType = PropTypes.shape({ room_id: PropTypes.string.isRequired, @@ -110,13 +110,14 @@ class CategoryRoomList extends React.Component { const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); Modal.createTrackedDialog( 'Failed to add the following room to the group summary', - '', ErrorDialog, + '', + ErrorDialog, { - title: _t( - "Failed to add the following rooms to the summary of %(groupId)s:", - {groupId: this.props.groupId}, - ), - description: errorList.join(", "), + title: _t( + "Failed to add the following rooms to the summary of %(groupId)s:", + {groupId: this.props.groupId}, + ), + description: errorList.join(", "), }, ); }); @@ -146,8 +147,7 @@ class CategoryRoomList extends React.Component { let catHeader =
    ; if (this.props.category && this.props.category.profile) { - catHeader =
    + catHeader =
    { this.props.category.profile.name }
    ; } @@ -193,11 +193,11 @@ class FeaturedRoom extends React.Component { 'Failed to remove room from group summary', '', ErrorDialog, { - title: _t( - "Failed to remove the room from the summary of %(groupId)s", - {groupId: this.props.groupId}, - ), - description: _t("The room '%(roomName)s' could not be removed from the summary.", {roomName}), + title: _t( + "Failed to remove the room from the summary of %(groupId)s", + {groupId: this.props.groupId}, + ), + description: _t("The room '%(roomName)s' could not be removed from the summary.", {roomName}), }, ); }); @@ -287,12 +287,13 @@ class RoleUserList extends React.Component { 'Failed to add the following users to the community summary', '', ErrorDialog, { - title: _t( - "Failed to add the following users to the summary of %(groupId)s:", - {groupId: this.props.groupId}, - ), - description: errorList.join(", "), - }); + title: _t( + "Failed to add the following users to the summary of %(groupId)s:", + {groupId: this.props.groupId}, + ), + description: errorList.join(", "), + }, + ); }); }, }, /*className=*/null, /*isPriority=*/false, /*isStatic=*/true); @@ -355,13 +356,14 @@ class FeaturedUser extends React.Component { const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); Modal.createTrackedDialog( 'Failed to remove user from community summary', - '', ErrorDialog, + '', + ErrorDialog, { - title: _t( - "Failed to remove a user from the summary of %(groupId)s", - {groupId: this.props.groupId}, - ), - description: _t("The user '%(displayName)s' could not be removed from the summary.", {displayName}), + title: _t( + "Failed to remove a user from the summary of %(groupId)s", + {groupId: this.props.groupId}, + ), + description: _t("The user '%(displayName)s' could not be removed from the summary.", {displayName}), }, ); }); @@ -1059,11 +1061,12 @@ export default class GroupView extends React.Component { return null; } - const membershipButtonClasses = classnames([ - 'mx_RoomHeader_textButton', - 'mx_GroupView_textButton', - ], - membershipButtonExtraClasses, + const membershipButtonClasses = classnames( + [ + 'mx_RoomHeader_textButton', + 'mx_GroupView_textButton', + ], + membershipButtonExtraClasses, ); const membershipContainerClasses = classnames( diff --git a/src/components/structures/ScrollPanel.js b/src/components/structures/ScrollPanel.js index 93a4c29b81..d423d4413e 100644 --- a/src/components/structures/ScrollPanel.js +++ b/src/components/structures/ScrollPanel.js @@ -884,19 +884,20 @@ export default class ScrollPanel extends React.Component { // give the
      an explicit role=list because Safari+VoiceOver seems to think an ordered-list with // list-style-type: none; is no longer a list - return ( - { this.props.fixedChildren } -
      -
        - { this.props.children } -
      -
      -
      + return ( + + { this.props.fixedChildren } +
      +
        + { this.props.children } +
      +
      +
      ); } } diff --git a/src/components/views/dialogs/RoomSettingsDialog.js b/src/components/views/dialogs/RoomSettingsDialog.js index c052b5c5bb..b6c4d42243 100644 --- a/src/components/views/dialogs/RoomSettingsDialog.js +++ b/src/components/views/dialogs/RoomSettingsDialog.js @@ -116,8 +116,12 @@ export default class RoomSettingsDialog extends React.Component { const roomName = MatrixClientPeg.get().getRoom(this.props.roomId).name; return ( - +
      diff --git a/src/components/views/dialogs/StorageEvictedDialog.js b/src/components/views/dialogs/StorageEvictedDialog.js index 629990032f..1e17ab1738 100644 --- a/src/components/views/dialogs/StorageEvictedDialog.js +++ b/src/components/views/dialogs/StorageEvictedDialog.js @@ -45,9 +45,10 @@ export default class StorageEvictedDialog extends React.Component { let logRequest; if (SdkConfig.get().bug_report_endpoint_url) { logRequest = _t( - "To help us prevent this in future, please send us logs.", {}, + "To help us prevent this in future, please send us logs.", + {}, { - a: text => {text}, + a: text => {text}, }, ); } diff --git a/src/components/views/dialogs/UserSettingsDialog.js b/src/components/views/dialogs/UserSettingsDialog.js index 8d99ffb5cd..e7f6953589 100644 --- a/src/components/views/dialogs/UserSettingsDialog.js +++ b/src/components/views/dialogs/UserSettingsDialog.js @@ -155,8 +155,12 @@ export default class UserSettingsDialog extends React.Component { const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog'); return ( - +
      diff --git a/src/components/views/dialogs/WidgetOpenIDPermissionsDialog.js b/src/components/views/dialogs/WidgetOpenIDPermissionsDialog.js index bf3671a0fe..f77661c54e 100644 --- a/src/components/views/dialogs/WidgetOpenIDPermissionsDialog.js +++ b/src/components/views/dialogs/WidgetOpenIDPermissionsDialog.js @@ -70,9 +70,12 @@ export default class WidgetOpenIDPermissionsDialog extends React.Component { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); return ( - + title={_t("Allow this widget to verify your identity")} + >

      {_t("The widget will verify your user ID, but won't be able to perform actions for you:")} diff --git a/src/components/views/dialogs/security/ConfirmDestroyCrossSigningDialog.js b/src/components/views/dialogs/security/ConfirmDestroyCrossSigningDialog.js index dabd7950b4..e71983b074 100644 --- a/src/components/views/dialogs/security/ConfirmDestroyCrossSigningDialog.js +++ b/src/components/views/dialogs/security/ConfirmDestroyCrossSigningDialog.js @@ -43,7 +43,8 @@ export default class ConfirmDestroyCrossSigningDialog extends React.Component { className='mx_ConfirmDestroyCrossSigningDialog' hasCancel={true} onFinished={this.props.onFinished} - title={_t("Destroy cross-signing keys?")}> + title={_t("Destroy cross-signing keys?")} + >

      {_t( diff --git a/src/components/views/dialogs/security/RestoreKeyBackupDialog.js b/src/components/views/dialogs/security/RestoreKeyBackupDialog.js index faabbacb81..4ac15ab5a3 100644 --- a/src/components/views/dialogs/security/RestoreKeyBackupDialog.js +++ b/src/components/views/dialogs/security/RestoreKeyBackupDialog.js @@ -373,20 +373,23 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { {_t( "If you've forgotten your Security Phrase you can "+ "use your Security Key or " + - "set up new recovery options" - , {}, { - button1: s => - {s} - , - button2: s => - {s} - , + "set up new recovery options", + {}, + { + button1: s => + {s} + , + button2: s => + {s} + , })}

      ; } else { @@ -435,15 +438,17 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
      {_t( "If you've forgotten your Security Key you can "+ - "" - , {}, { - button: s => - {s} - , - })} + "", + {}, + { + button: s => + {s} + , + }, + )}
    ; } diff --git a/src/components/views/elements/EditableItemList.js b/src/components/views/elements/EditableItemList.js index e3fe54333a..d8ec5af278 100644 --- a/src/components/views/elements/EditableItemList.js +++ b/src/components/views/elements/EditableItemList.js @@ -127,8 +127,12 @@ export default class EditableItemList extends React.Component { _renderNewItemField() { return ( - + diff --git a/src/components/views/messages/MKeyVerificationConclusion.js b/src/components/views/messages/MKeyVerificationConclusion.js index 7fc5a62434..c9489711aa 100644 --- a/src/components/views/messages/MKeyVerificationConclusion.js +++ b/src/components/views/messages/MKeyVerificationConclusion.js @@ -82,9 +82,7 @@ export default class MKeyVerificationConclusion extends React.Component { } // User isn't actually verified - if (!MatrixClientPeg.get() - .checkUserTrust(request.otherUserId) - .isCrossSigningVerified()) { + if (!MatrixClientPeg.get().checkUserTrust(request.otherUserId).isCrossSigningVerified()) { return false; } diff --git a/src/components/views/rooms/ReadReceiptMarker.js b/src/components/views/rooms/ReadReceiptMarker.js index 4d01c38196..64f2c1160b 100644 --- a/src/components/views/rooms/ReadReceiptMarker.js +++ b/src/components/views/rooms/ReadReceiptMarker.js @@ -187,8 +187,7 @@ export default class ReadReceiptMarker extends React.PureComponent { } return ( - + } Resolves to true if events were added to the * timeline, false otherwise. */ - async populateFileTimeline(timelineSet, timeline, room, limit = 10, - fromEvent = null, direction = EventTimeline.BACKWARDS) { + async populateFileTimeline( + timelineSet, + timeline, + room, + limit = 10, + fromEvent = null, + direction = EventTimeline.BACKWARDS, + ) { const matrixEvents = await this.loadFileEvents(room, limit, fromEvent, direction); // If this is a normal fill request, not a pagination request, we need diff --git a/src/stores/CustomRoomTagStore.js b/src/stores/CustomRoomTagStore.js index 060f1f3749..55c9699f7a 100644 --- a/src/stores/CustomRoomTagStore.js +++ b/src/stores/CustomRoomTagStore.js @@ -124,15 +124,15 @@ class CustomRoomTagStore extends EventEmitter { const tags = Object.assign({}, oldTags, tag); this._setState({tags}); } - } break; + } case 'on_client_not_viable': case 'on_logged_out': { // we assume to always have a tags object in the state this._state = {tags: {}}; RoomListStore.instance.off(LISTS_UPDATE_EVENT, this._onListsUpdated); - } break; + } } } diff --git a/src/utils/MegolmExportEncryption.js b/src/utils/MegolmExportEncryption.js index 20f3cd6cb6..6f5c7104b1 100644 --- a/src/utils/MegolmExportEncryption.js +++ b/src/utils/MegolmExportEncryption.js @@ -310,8 +310,7 @@ function unpackMegolmKeyFile(data) { // look for the end line while (1) { const lineEnd = fileStr.indexOf('\n', lineStart); - const line = fileStr.slice(lineStart, lineEnd < 0 ? undefined : lineEnd) - .trim(); + const line = fileStr.slice(lineStart, lineEnd < 0 ? undefined : lineEnd).trim(); if (line === TRAILER_LINE) { break; } diff --git a/test/components/views/elements/MemberEventListSummary-test.js b/test/components/views/elements/MemberEventListSummary-test.js index 9386d8cf4a..95bf206d02 100644 --- a/test/components/views/elements/MemberEventListSummary-test.js +++ b/test/components/views/elements/MemberEventListSummary-test.js @@ -245,9 +245,8 @@ describe('MemberEventListSummary', function() { ); }); - it('truncates multiple sequences of repetitions with other events between', - function() { - const events = generateEvents([ + it('truncates multiple sequences of repetitions with other events between', function() { + const events = generateEvents([ { userId: "@user_1:some.domain", prevMembership: "ban", @@ -276,29 +275,28 @@ describe('MemberEventListSummary', function() { membership: "invite", senderId: "@some_other_user:some.domain", }, - ]); - const props = { + ]); + const props = { events: events, children: generateTiles(events), summaryLength: 1, avatarsMaxLength: 5, threshold: 3, - }; + }; - const instance = ReactTestUtils.renderIntoDocument( - , - ); - const summary = ReactTestUtils.findRenderedDOMComponentWithClass( - instance, "mx_EventListSummary_summary", - ); - const summaryText = summary.textContent; + const instance = ReactTestUtils.renderIntoDocument( + , + ); + const summary = ReactTestUtils.findRenderedDOMComponentWithClass( + instance, "mx_EventListSummary_summary", + ); + const summaryText = summary.textContent; - expect(summaryText).toBe( - "user_1 was unbanned, joined and left 2 times, was banned, " + + expect(summaryText).toBe( + "user_1 was unbanned, joined and left 2 times, was banned, " + "joined and left 3 times and was invited", - ); - }, - ); + ); + }); it('handles multiple users following the same sequence of memberships', function() { const events = generateEvents([ @@ -396,9 +394,8 @@ describe('MemberEventListSummary', function() { ); }); - it('correctly orders sequences of transitions by the order of their first event', - function() { - const events = generateEvents([ + it('correctly orders sequences of transitions by the order of their first event', function() { + const events = generateEvents([ { userId: "@user_2:some.domain", prevMembership: "ban", @@ -425,29 +422,28 @@ describe('MemberEventListSummary', function() { {userId: "@user_2:some.domain", prevMembership: "join", membership: "leave"}, {userId: "@user_2:some.domain", prevMembership: "leave", membership: "join"}, {userId: "@user_2:some.domain", prevMembership: "join", membership: "leave"}, - ]); - const props = { + ]); + const props = { events: events, children: generateTiles(events), summaryLength: 1, avatarsMaxLength: 5, threshold: 3, - }; + }; - const instance = ReactTestUtils.renderIntoDocument( - , - ); - const summary = ReactTestUtils.findRenderedDOMComponentWithClass( - instance, "mx_EventListSummary_summary", - ); - const summaryText = summary.textContent; + const instance = ReactTestUtils.renderIntoDocument( + , + ); + const summary = ReactTestUtils.findRenderedDOMComponentWithClass( + instance, "mx_EventListSummary_summary", + ); + const summaryText = summary.textContent; - expect(summaryText).toBe( - "user_2 was unbanned and joined and left 2 times, user_1 was unbanned, " + + expect(summaryText).toBe( + "user_2 was unbanned and joined and left 2 times, user_1 was unbanned, " + "joined and left 2 times and was banned", - ); - }, - ); + ); + }); it('correctly identifies transitions', function() { const events = generateEvents([ @@ -570,9 +566,8 @@ describe('MemberEventListSummary', function() { ); }); - it('handles invitation plurals correctly when there are multiple invites', - function() { - const events = generateEvents([ + it('handles invitation plurals correctly when there are multiple invites', function() { + const events = generateEvents([ { userId: "@user_1:some.domain", prevMembership: "invite", @@ -583,28 +578,27 @@ describe('MemberEventListSummary', function() { prevMembership: "invite", membership: "leave", }, - ]); - const props = { + ]); + const props = { events: events, children: generateTiles(events), summaryLength: 1, avatarsMaxLength: 5, threshold: 1, // threshold = 1 to force collapse - }; + }; - const instance = ReactTestUtils.renderIntoDocument( - , - ); - const summary = ReactTestUtils.findRenderedDOMComponentWithClass( - instance, "mx_EventListSummary_summary", - ); - const summaryText = summary.textContent; + const instance = ReactTestUtils.renderIntoDocument( + , + ); + const summary = ReactTestUtils.findRenderedDOMComponentWithClass( + instance, "mx_EventListSummary_summary", + ); + const summaryText = summary.textContent; - expect(summaryText).toBe( - "user_1 rejected their invitation 2 times", - ); - }, - ); + expect(summaryText).toBe( + "user_1 rejected their invitation 2 times", + ); + }); it('handles a summary length = 2, with no "others"', function() { const events = generateEvents([ From c6bd2c7d674e16e19c5a03cd93019604ea650d11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 29 Apr 2021 20:18:26 +0200 Subject: [PATCH 0139/1449] Fix some more formatting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/structures/GroupView.js | 16 ++++++++-------- src/i18n/strings/en_EN.json | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/components/structures/GroupView.js b/src/components/structures/GroupView.js index c17bae9d49..ce5cd65c22 100644 --- a/src/components/structures/GroupView.js +++ b/src/components/structures/GroupView.js @@ -43,14 +43,14 @@ import {mediaFromMxc} from "../../customisations/Media"; import {replaceableComponent} from "../../utils/replaceableComponent"; const LONG_DESC_PLACEHOLDER = _td( - `

    HTML for your community's page

    -

    - Use the long description to introduce new members to the community, or distribute - some important links -

    -

    - You can even add images with Matrix URLs -

    `, + "

    HTML for your community's page

    " + + "

    " + + "Use the long description to introduce new members to the community, or distribute" + + "some important links" + + "

    " + + "

    " + + "You can even add images with Matrix URLs " + + "

    ", ); const RoomSummaryType = PropTypes.shape({ diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 85e8e54258..0274e05bcf 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2508,7 +2508,7 @@ "Attach files from chat or just drag and drop them anywhere in a room.": "Attach files from chat or just drag and drop them anywhere in a room.", "Communities": "Communities", "Create community": "Create community", - "

    HTML for your community's page

    \n

    \n Use the long description to introduce new members to the community, or distribute\n some important links\n

    \n

    \n You can even add images with Matrix URLs \n

    \n": "

    HTML for your community's page

    \n

    \n Use the long description to introduce new members to the community, or distribute\n some important links\n

    \n

    \n You can even add images with Matrix URLs \n

    \n", + "

    HTML for your community's page

    Use the long description to introduce new members to the community, or distributesome important links

    You can even add images with Matrix URLs

    ": "

    HTML for your community's page

    Use the long description to introduce new members to the community, or distributesome important links

    You can even add images with Matrix URLs

    ", "Add rooms to the community summary": "Add rooms to the community summary", "Which rooms would you like to add to this summary?": "Which rooms would you like to add to this summary?", "Add to summary": "Add to summary", From 158a0f90cb969a497a7b4b3fab7a908bb5c4c57d Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 29 Apr 2021 22:02:18 +0100 Subject: [PATCH 0140/1449] Further design iteration --- res/css/structures/_MyGroups.scss | 4 ++-- src/settings/Settings.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/res/css/structures/_MyGroups.scss b/res/css/structures/_MyGroups.scss index 6ecc5570f4..9c0062b72d 100644 --- a/res/css/structures/_MyGroups.scss +++ b/res/css/structures/_MyGroups.scss @@ -19,8 +19,8 @@ limitations under the License. flex-direction: column; .mx_BetaCard { - margin: 0 40px; - max-width: 960px; + margin: 0 72px; + max-width: 760px; } } diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx index 5bda746646..2066cf2026 100644 --- a/src/settings/Settings.tsx +++ b/src/settings/Settings.tsx @@ -153,8 +153,8 @@ export const SETTINGS: {[setting: string]: ISetting} = { "Communities and custom tags will be hidden.", { brand: SdkConfig.get().brand, }) }

    -

    { _t("You can leave the beta any time from settings or tapping on a beta badge, " + - "like the one above.") }

    + { _t("You can leave the beta any time from settings or tapping on a beta badge, " + + "like the one above.") }

    { _t("Beta available for web, desktop and Android. " + "Some features may be unavailable on your homeserver.") }

    ; From f766f985e43d6ef8914529f4457c64b80a8b33bd Mon Sep 17 00:00:00 2001 From: Jaiwanth Date: Fri, 30 Apr 2021 08:25:58 +0530 Subject: [PATCH 0141/1449] Change cursor to not-allowed --- res/css/views/messages/_ReactionsRowButton.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/res/css/views/messages/_ReactionsRowButton.scss b/res/css/views/messages/_ReactionsRowButton.scss index 7158ffc027..c132fa5a0f 100644 --- a/res/css/views/messages/_ReactionsRowButton.scss +++ b/res/css/views/messages/_ReactionsRowButton.scss @@ -34,6 +34,10 @@ limitations under the License. border-color: $reaction-row-button-selected-border-color; } + &.mx_AccessibleButton_disabled { + cursor: not-allowed; + } + .mx_ReactionsRowButton_content { max-width: 100px; overflow: hidden; From 192c0c4941a1aecad61b372d94c1759641e20b7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 30 Apr 2021 11:01:34 +0200 Subject: [PATCH 0142/1449] Fix method name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- .../settings/tabs/user/PreferencesUserSettingsTab.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx index 24e4d8099e..bc2c120654 100644 --- a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx @@ -236,12 +236,12 @@ export default class PreferencesUserSettingsTab extends React.Component<{}, ISta
    {_t("Keybindings")} - {this._renderGroup(PreferencesUserSettingsTab.KEYBINDINGS_SETTINGS)} + {this.renderGroup(PreferencesUserSettingsTab.KEYBINDINGS_SETTINGS)}
    {_t("Displaying time")} - {this._renderGroup(PreferencesUserSettingsTab.TIME_SETTINGS)} + {this.renderGroup(PreferencesUserSettingsTab.TIME_SETTINGS)}
    @@ -251,17 +251,17 @@ export default class PreferencesUserSettingsTab extends React.Component<{}, ISta
    {_t("Code blocks")} - {this._renderGroup(PreferencesUserSettingsTab.CODE_BLOCKS_SETTINGS)} + {this.renderGroup(PreferencesUserSettingsTab.CODE_BLOCKS_SETTINGS)}
    {_t("Images, GIFs and videos")} - {this._renderGroup(PreferencesUserSettingsTab.IMAGES_AND_VIDEOS_SETTINGS)} + {this.renderGroup(PreferencesUserSettingsTab.IMAGES_AND_VIDEOS_SETTINGS)}
    {_t("Hide things on the timeline")} - {this._renderGroup(PreferencesUserSettingsTab.THINGS_TO_HIDE_ON_TIMELINE_SETTINGS)} + {this.renderGroup(PreferencesUserSettingsTab.THINGS_TO_HIDE_ON_TIMELINE_SETTINGS)}
    From 2c7139fb4de1ca37bb674718651d02cd2c4fcba4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 30 Apr 2021 11:03:22 +0200 Subject: [PATCH 0143/1449] Merge timeline section into one MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- .../tabs/user/PreferencesUserSettingsTab.tsx | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx index bc2c120654..404bc974be 100644 --- a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx @@ -71,7 +71,7 @@ export default class PreferencesUserSettingsTab extends React.Component<{}, ISta 'autoplayGifsAndVideos', 'showImages', ]; - static THINGS_TO_HIDE_ON_TIMELINE_SETTINGS = [ + static TIMELINE_SETTINGS = [ 'showTypingNotifications', 'showRedactions', 'showReadReceipts', @@ -79,14 +79,10 @@ export default class PreferencesUserSettingsTab extends React.Component<{}, ISta 'showDisplaynameChanges', 'showChatEffects', 'showAvatarChanges', - ]; - - static TIMELINE_SETTINGS = [ + 'Pill.shouldShowPillAvatar', 'TextualBody.enableBigEmoji', 'scrollToBottomOnMessageSent', - 'Pill.shouldShowPillAvatar', ]; - static GENERAL_SETTINGS = [ 'TagPanel.enableTagPanel', 'promptBeforeInviteUnknownUsers', @@ -259,11 +255,6 @@ export default class PreferencesUserSettingsTab extends React.Component<{}, ISta {this.renderGroup(PreferencesUserSettingsTab.IMAGES_AND_VIDEOS_SETTINGS)}
    -
    - {_t("Hide things on the timeline")} - {this.renderGroup(PreferencesUserSettingsTab.THINGS_TO_HIDE_ON_TIMELINE_SETTINGS)} -
    -
    {_t("Timeline")} {this.renderGroup(PreferencesUserSettingsTab.TIMELINE_SETTINGS)} From 70c8c6477248466c2bdf0528da709124d886d8c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 30 Apr 2021 11:03:55 +0200 Subject: [PATCH 0144/1449] Rename to Keyboard shortcuts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- .../views/settings/tabs/user/PreferencesUserSettingsTab.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx index 404bc974be..7dc25d1879 100644 --- a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx @@ -231,7 +231,7 @@ export default class PreferencesUserSettingsTab extends React.Component<{}, ISta
    - {_t("Keybindings")} + {_t("Keyboard shortcuts")} {this.renderGroup(PreferencesUserSettingsTab.KEYBINDINGS_SETTINGS)}
    From 5f6895487f31668cc76f35c5d504533c0caafcdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 30 Apr 2021 11:09:35 +0200 Subject: [PATCH 0145/1449] Rename ctrl+f 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 2a26eeac13..2912f0a8ee 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -384,7 +384,7 @@ export const SETTINGS: {[setting: string]: ISetting} = { }, "ctrlFForSearch": { supportedLevels: LEVELS_ACCOUNT_SETTINGS, - displayName: isMac ? _td("Use Command + F to search") : _td("Use Ctrl + F to search"), + displayName: isMac ? _td("Use Command + F to search current room") : _td("Use Ctrl + F to search current room"), default: false, }, "MessageComposerInput.ctrlEnterToSend": { From e52fd3791e18d5e42ce5f2d2a50904d4430ffacc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 30 Apr 2021 11:10:45 +0200 Subject: [PATCH 0146/1449] 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 | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 69e77cf1bc..2e21016933 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -823,8 +823,8 @@ "Enable big emoji in chat": "Enable big emoji in chat", "Send typing notifications": "Send typing notifications", "Show typing notifications": "Show typing notifications", - "Use Command + F to search": "Use Command + F to search", - "Use Ctrl + F to search": "Use Ctrl + F to search", + "Use Command + F to search current room": "Use Command + F to search current room", + "Use Ctrl + F to search current room": "Use Ctrl + F to search current room", "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", "Automatically replace plain text Emoji": "Automatically replace plain text Emoji", @@ -1296,12 +1296,11 @@ "Show tray icon and minimize window to it on close": "Show tray icon and minimize window to it on close", "Preferences": "Preferences", "Room list": "Room list", - "Keybindings": "Keybindings", + "Keyboard shortcuts": "Keyboard shortcuts", "Displaying time": "Displaying time", "Composer": "Composer", "Code blocks": "Code blocks", "Images, GIFs and videos": "Images, GIFs and videos", - "Hide things on the timeline": "Hide things on the timeline", "Timeline": "Timeline", "Autocomplete delay (ms)": "Autocomplete delay (ms)", "Read Marker lifetime (ms)": "Read Marker lifetime (ms)", From 2e62b1861766f09e6208a86c4e28879204cd845a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 30 Apr 2021 12:30:14 +0200 Subject: [PATCH 0147/1449] Revert some changes to avoid re-translation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/structures/GroupView.js | 18 +++++++++--------- src/i18n/strings/en_EN.json | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/components/structures/GroupView.js b/src/components/structures/GroupView.js index ce5cd65c22..3ab009d7b8 100644 --- a/src/components/structures/GroupView.js +++ b/src/components/structures/GroupView.js @@ -43,15 +43,15 @@ import {mediaFromMxc} from "../../customisations/Media"; import {replaceableComponent} from "../../utils/replaceableComponent"; const LONG_DESC_PLACEHOLDER = _td( - "

    HTML for your community's page

    " + - "

    " + - "Use the long description to introduce new members to the community, or distribute" + - "some important links" + - "

    " + - "

    " + - "You can even add images with Matrix URLs " + - "

    ", -); + `

    HTML for your community's page

    +

    + Use the long description to introduce new members to the community, or distribute + some important links +

    +

    + You can even add images with Matrix URLs +

    +`); const RoomSummaryType = PropTypes.shape({ room_id: PropTypes.string.isRequired, diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 0274e05bcf..85e8e54258 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2508,7 +2508,7 @@ "Attach files from chat or just drag and drop them anywhere in a room.": "Attach files from chat or just drag and drop them anywhere in a room.", "Communities": "Communities", "Create community": "Create community", - "

    HTML for your community's page

    Use the long description to introduce new members to the community, or distributesome important links

    You can even add images with Matrix URLs

    ": "

    HTML for your community's page

    Use the long description to introduce new members to the community, or distributesome important links

    You can even add images with Matrix URLs

    ", + "

    HTML for your community's page

    \n

    \n Use the long description to introduce new members to the community, or distribute\n some important links\n

    \n

    \n You can even add images with Matrix URLs \n

    \n": "

    HTML for your community's page

    \n

    \n Use the long description to introduce new members to the community, or distribute\n some important links\n

    \n

    \n You can even add images with Matrix URLs \n

    \n", "Add rooms to the community summary": "Add rooms to the community summary", "Which rooms would you like to add to this summary?": "Which rooms would you like to add to this summary?", "Add to summary": "Add to summary", From 43410835a3ff1db8fe7b627c27df75fa06374b5a Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 30 Apr 2021 11:53:56 +0100 Subject: [PATCH 0148/1449] Prevent room list keyboard handling from landing focus on hidden nodes --- src/components/structures/LeftPanel.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/LeftPanel.tsx b/src/components/structures/LeftPanel.tsx index e4762e35ad..44b404bd3a 100644 --- a/src/components/structures/LeftPanel.tsx +++ b/src/components/structures/LeftPanel.tsx @@ -347,7 +347,7 @@ export default class LeftPanel extends React.Component { if (element) { classes = element.classList; } - } while (element && !cssClasses.some(c => classes.contains(c))); + } while (element && (!cssClasses.some(c => classes.contains(c)) || element.offsetParent === null)); if (element) { element.focus(); From d2959e1acce8450d7b6144bcd661b78716966c41 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 30 Apr 2021 12:30:05 +0100 Subject: [PATCH 0149/1449] Add mechanism for disabling Betas --- src/components/views/beta/BetaCard.tsx | 5 ++++- src/settings/SettingsStore.ts | 7 ++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/components/views/beta/BetaCard.tsx b/src/components/views/beta/BetaCard.tsx index 1233f345d1..96b1fbabe5 100644 --- a/src/components/views/beta/BetaCard.tsx +++ b/src/components/views/beta/BetaCard.tsx @@ -60,7 +60,10 @@ export const BetaPill = ({ onClick }: { onClick?: () => void }) => { }; const BetaCard = ({ title: titleOverride, featureId }: IProps) => { - const { title, caption, disclaimer, image } = SettingsStore.getBetaInfo(featureId); + const info = SettingsStore.getBetaInfo(featureId); + if (!info) return null; // Beta is invalid/disabled + + const { title, caption, disclaimer, image } = info; const value = SettingsStore.getValue(featureId); return
    diff --git a/src/settings/SettingsStore.ts b/src/settings/SettingsStore.ts index ff3a5371b0..875a0a87ec 100644 --- a/src/settings/SettingsStore.ts +++ b/src/settings/SettingsStore.ts @@ -258,7 +258,12 @@ export default class SettingsStore { } public static getBetaInfo(settingName: string) { - return SETTINGS[settingName]?.betaInfo; + // consider a beta disabled if the config is explicitly set to false, in which case treat as normal Labs flag + if (SettingsStore.isFeature(settingName) + && SettingsStore.getValueAt(SettingLevel.CONFIG, settingName, null, true, true) !== false + ) { + return SETTINGS[settingName]?.betaInfo; + } } /** From 042ca658061310428af1e59390647482e2a712ef Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 30 Apr 2021 12:32:42 +0100 Subject: [PATCH 0150/1449] fix beta dot showing up when beta is disabled --- src/components/structures/GroupFilterPanel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/GroupFilterPanel.js b/src/components/structures/GroupFilterPanel.js index 066178c976..7992320352 100644 --- a/src/components/structures/GroupFilterPanel.js +++ b/src/components/structures/GroupFilterPanel.js @@ -124,7 +124,7 @@ class GroupFilterPanel extends React.Component { }); let betaDot; - if (!SettingsStore.getValue("feature_spaces") && !localStorage.getItem("mx_seenSpacesBeta")) { + if (SettingsStore.getBetaInfo("feature_spaces") && !localStorage.getItem("mx_seenSpacesBeta")) { betaDot =
    ; } From 2435332d370a0c39f7a161c016c738603b44b127 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 30 Apr 2021 12:42:16 +0100 Subject: [PATCH 0151/1449] fix beta disabled behaviour --- src/i18n/strings/en_EN.json | 1 + src/settings/Settings.tsx | 2 ++ src/settings/SettingsStore.ts | 4 ++-- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 7f5205efa3..2dbb36725f 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -784,6 +784,7 @@ "%(senderName)s: %(reaction)s": "%(senderName)s: %(reaction)s", "%(senderName)s: %(stickerName)s": "%(senderName)s: %(stickerName)s", "Change notification settings": "Change notification settings", + "Spaces prototype. Incompatible with Communities, Communities v2 and Custom Tags. Requires compatible homeserver for some features.": "Spaces prototype. Incompatible with Communities, Communities v2 and Custom Tags. Requires compatible homeserver for some features.", "Spaces": "Spaces", "Spaces are new ways to group rooms and people.": "Spaces are new ways to group rooms and people.", "%(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "%(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.", diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx index 2066cf2026..5b501a8e8b 100644 --- a/src/settings/Settings.tsx +++ b/src/settings/Settings.tsx @@ -131,6 +131,8 @@ export interface ISetting { export const SETTINGS: {[setting: string]: ISetting} = { "feature_spaces": { isFeature: true, + displayName: _td("Spaces prototype. Incompatible with Communities, Communities v2 and Custom Tags. " + + "Requires compatible homeserver for some features."), supportedLevels: LEVELS_FEATURE, default: false, controller: new ReloadOnChangeController(), diff --git a/src/settings/SettingsStore.ts b/src/settings/SettingsStore.ts index 875a0a87ec..c32bbe731d 100644 --- a/src/settings/SettingsStore.ts +++ b/src/settings/SettingsStore.ts @@ -454,8 +454,8 @@ export default class SettingsStore { throw new Error("Setting '" + settingName + "' does not appear to be a setting."); } - // When features are specified in the config.json, we force them as enabled or disabled. - if (SettingsStore.isFeature(settingName)) { + // When non-beta features are specified in the config.json, we force them as enabled or disabled. + if (SettingsStore.isFeature(settingName) && !SETTINGS[settingName]?.betaInfo) { const configVal = SettingsStore.getValueAt(SettingLevel.CONFIG, settingName, roomId, true, true); if (configVal === true || configVal === false) return false; } From 03a098887a66341d3193adaec3aec32b0f7e33bc Mon Sep 17 00:00:00 2001 From: Aaron Raimist Date: Fri, 30 Apr 2021 19:44:39 -0500 Subject: [PATCH 0152/1449] Change confirmation string in CreateSecretStorageDialog.js to match Signed-off-by: Aaron Raimist --- .../views/dialogs/security/CreateKeyBackupDialog.js | 2 +- src/i18n/strings/en_EN.json | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/async-components/views/dialogs/security/CreateKeyBackupDialog.js b/src/async-components/views/dialogs/security/CreateKeyBackupDialog.js index 863ee2b427..c1adc2c493 100644 --- a/src/async-components/views/dialogs/security/CreateKeyBackupDialog.js +++ b/src/async-components/views/dialogs/security/CreateKeyBackupDialog.js @@ -310,7 +310,7 @@ export default class CreateKeyBackupDialog extends React.PureComponent { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); return

    {_t( - "Please enter your Security Phrase a second time to confirm.", + "Enter your Security Phrase a second time to confirm it.", )}

    diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 7158156105..9cac041548 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2801,7 +2801,7 @@ "Use a different passphrase?": "Use a different passphrase?", "That doesn't match.": "That doesn't match.", "Go back to set it again.": "Go back to set it again.", - "Please enter your Security Phrase a second time to confirm.": "Please enter your Security Phrase a second time to confirm.", + "Enter your Security Phrase a second time to confirm it.": "Enter your Security Phrase a second time to confirm it.", "Repeat your Security Phrase...": "Repeat your Security Phrase...", "Your Security Key is a safety net - you can use it to restore access to your encrypted messages if you forget your Security Phrase.": "Your Security Key is a safety net - you can use it to restore access to your encrypted messages if you forget your Security Phrase.", "Keep a copy of it somewhere secure, like a password manager or even a safe.": "Keep a copy of it somewhere secure, like a password manager or even a safe.", @@ -2831,7 +2831,6 @@ "You'll need to authenticate with the server to confirm the upgrade.": "You'll need to authenticate with the server to confirm the upgrade.", "Upgrade this session to allow it to verify other sessions, granting them access to encrypted messages and marking them as trusted for other users.": "Upgrade this session to allow it to verify other sessions, granting them access to encrypted messages and marking them as trusted for other users.", "Enter a security phrase only you know, as it’s used to safeguard your data. To be secure, you shouldn’t re-use your account password.": "Enter a security phrase only you know, as it’s used to safeguard your data. To be secure, you shouldn’t re-use your account password.", - "Enter your Security Phrase a second time to confirm it.": "Enter your Security Phrase a second time to confirm it.", "Store your Security Key somewhere safe, like a password manager or a safe, as it’s used to safeguard your encrypted data.": "Store your Security Key somewhere safe, like a password manager or a safe, as it’s used to safeguard your encrypted data.", "Unable to query secret storage status": "Unable to query secret storage status", "If you cancel now, you may lose encrypted messages & data if you lose access to your logins.": "If you cancel now, you may lose encrypted messages & data if you lose access to your logins.", From 626a4ccc34c902b1dc234d01ede39318f97d345b Mon Sep 17 00:00:00 2001 From: Aaron Raimist Date: Fri, 30 Apr 2021 21:45:33 -0500 Subject: [PATCH 0153/1449] Make warning bold, close copied tooltip on escape Signed-off-by: Aaron Raimist --- .../views/settings/tabs/user/HelpUserSettingsTab.tsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx b/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx index 9046c074e6..45395bd10c 100644 --- a/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx @@ -60,6 +60,12 @@ export default class HelpUserSettingsTab extends React.Component }); } + componentWillUnmount() { + // if the Copied tooltip is open then get rid of it, there are ways to close the modal which wouldn't close + // the tooltip otherwise, such as pressing Escape + if (this.closeCopiedTooltip) this.closeCopiedTooltip(); + } + private onClearCacheAndReload = (e) => { if (!PlatformPeg.get()) return; @@ -168,7 +174,7 @@ export default class HelpUserSettingsTab extends React.Component ...toRightOf(buttonRect, 2), message: successful ? _t('Copied!') : _t('Failed to copy'), }); - target.onmouseleave = close; + this.closeCopiedTooltip = target.onmouseleave = close; } render() { @@ -290,8 +296,8 @@ export default class HelpUserSettingsTab extends React.Component
    {_t("Access Token")}
    - { _t("Your access token gives full access to your account." - + " Do not share it with anyone." ) } + {_t("Your access token gives full access to your account." + + " Do not share it with anyone." )}
    {MatrixClientPeg.get().getAccessToken()} Date: Fri, 30 Apr 2021 21:54:57 -0500 Subject: [PATCH 0154/1449] lint Signed-off-by: Aaron Raimist --- src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx b/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx index 45395bd10c..3fa0be478c 100644 --- a/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx @@ -42,6 +42,8 @@ interface IState { @replaceableComponent("views.settings.tabs.user.HelpUserSettingsTab") export default class HelpUserSettingsTab extends React.Component { + protected closeCopiedTooltip: () => void; + constructor(props) { super(props); From ee8d688de1819653cf1b69e917776bbb27858589 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sat, 1 May 2021 10:59:28 +0200 Subject: [PATCH 0155/1449] Fix saving room pill part to history MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/editor/parts.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/editor/parts.ts b/src/editor/parts.ts index 02c5d64895..b69f255f89 100644 --- a/src/editor/parts.ts +++ b/src/editor/parts.ts @@ -287,6 +287,14 @@ abstract class PillPart extends BasePart implements IPillPart { } } + serialize(): ISerializedPillPart { + return { + type: this.type, + text: this.text, + resourceId: this.resourceId, + }; + } + get canEdit() { return false; } @@ -394,14 +402,6 @@ class UserPillPart extends PillPart { get className() { return "mx_UserPill mx_Pill"; } - - serialize(): ISerializedPillPart { - return { - type: this.type, - text: this.text, - resourceId: this.resourceId, - }; - } } class PillCandidatePart extends PlainBasePart implements IPillCandidatePart { @@ -495,7 +495,7 @@ export class PartCreator { case Type.PillCandidate: return this.pillCandidate(part.text); case Type.RoomPill: - return this.roomPill(part.text); + return this.roomPill(part.resourceId); case Type.UserPill: return this.userPill(part.text, part.resourceId); } From c1549dfac58d64f979f937c328f36ed4f8787a6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sat, 1 May 2021 11:32:35 +0200 Subject: [PATCH 0156/1449] Make optional params optional MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/editor/model.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/editor/model.ts b/src/editor/model.ts index 2e70b872e9..f1b6f90957 100644 --- a/src/editor/model.ts +++ b/src/editor/model.ts @@ -158,7 +158,7 @@ export default class EditorModel { } } - reset(serializedParts: SerializedPart[], caret: Caret, inputType: string) { + reset(serializedParts: SerializedPart[], caret?: Caret, inputType?: string) { this._parts = serializedParts.map(p => this._partCreator.deserializePart(p)); if (!caret) { caret = this.getPositionAtEnd(); From 0c869364e961365f6648be64cb9a967dea6084cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sat, 1 May 2021 12:27:52 +0200 Subject: [PATCH 0157/1449] Don't serialize resourceId in AtRoomPill MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/editor/parts.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/editor/parts.ts b/src/editor/parts.ts index b69f255f89..6e3f35371d 100644 --- a/src/editor/parts.ts +++ b/src/editor/parts.ts @@ -34,7 +34,7 @@ interface ISerializedPart { interface ISerializedPillPart { type: Type.AtRoomPill | Type.RoomPill | Type.UserPill; text: string; - resourceId: string; + resourceId?: string; } export type SerializedPart = ISerializedPart | ISerializedPillPart; @@ -374,6 +374,13 @@ class AtRoomPillPart extends RoomPillPart { get type(): IPillPart["type"] { return Type.AtRoomPill; } + + serialize(): ISerializedPillPart { + return { + type: this.type, + text: this.text, + }; + } } class UserPillPart extends PillPart { From 1fe20853095432f3b95a3ec31e6c3bd672b5d10c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sat, 1 May 2021 12:28:18 +0200 Subject: [PATCH 0158/1449] Fix deserialize test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- test/editor/deserialize-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/editor/deserialize-test.js b/test/editor/deserialize-test.js index 07b75aaae5..7c7a2f84fb 100644 --- a/test/editor/deserialize-test.js +++ b/test/editor/deserialize-test.js @@ -178,7 +178,7 @@ describe('editor/deserialize', function() { const parts = normalize(parseEvent(htmlMessage(html), createPartCreator())); expect(parts.length).toBe(3); expect(parts[0]).toStrictEqual({type: "plain", text: "Try "}); - expect(parts[1]).toStrictEqual({type: "room-pill", text: "#room:hs.tld"}); + expect(parts[1]).toStrictEqual({type: "room-pill", text: "#room:hs.tld", resourceId: "#room:hs.tld"}); expect(parts[2]).toStrictEqual({type: "plain", text: "?"}); }); it('@room pill', function() { From a2ece699767018e49f62453f446bcaea68ef9946 Mon Sep 17 00:00:00 2001 From: libexus Date: Fri, 30 Apr 2021 09:11:54 +0000 Subject: [PATCH 0159/1449] Translated using Weblate (German) Currently translated at 99.2% (2903 of 2924 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 739f0d0c57..7a9c518193 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -1459,7 +1459,7 @@ "Your key share request has been sent - please check your other sessions for key share requests.": "Deine Schlüsselanfrage wurde gesendet - sieh in deinen anderen Sitzungen nach der Schlüsselanfrage.", "Key share requests are sent to your other sessions automatically. If you rejected or dismissed the key share request on your other sessions, click here to request the keys for this session again.": "Schlüsselanfragen werden automatisch an deine anderen Sitzungen gesendet. Wenn du sie abgelehnt oder ignoriert hast, klicke hier, um die Schlüssel erneut anzufordern.", "If your other sessions do not have the key for this message you will not be able to decrypt them.": "Wenn deine anderen Sitzungen nicht über den Schlüssel für diese Nachricht verfügen, kannst du die Nachricht nicht entschlüsseln.", - "Re-request encryption keys from your other sessions.": "Fordere die Schlüssel aus deinen anderen Sitzungen erneut an.", + "Re-request encryption keys from your other sessions.": "Schlüssel aus deinen anderen Sitzungen erneut anfordern.", "Room %(name)s": "Raum %(name)s", "Upgrading this room will shut down the current instance of the room and create an upgraded room with the same name.": "Ein Aktualisierung dieses Raums deaktiviert die aktuelle Instanz des Raums und erstellt einen aktualisierten Raum mit demselben Namen.", "%(name)s (%(userId)s) signed in to a new session without verifying it:": "%(name)s (%(userId)s) hat sich zu einer neuen Sitzung angemeldet, ohne sie zu verifizieren:", @@ -2028,7 +2028,7 @@ "Doesn't look like a valid email address": "Das sieht nicht nach einer gültigen E-Mail-Adresse aus", "Enter phone number (required on this homeserver)": "Telefonnummer eingeben (auf diesem Heimserver erforderlich)", "Doesn't look like a valid phone number": "Das sieht nicht nach einer gültigen Telefonnummer aus", - "Sign in with SSO": "Mit „Single Sign-On“ anmelden", + "Sign in with SSO": "Mit Single Sign-On anmelden", "Welcome to %(appName)s": "Willkommen bei %(appName)s", "Send a Direct Message": "Direktnachricht senden", "Create a Group Chat": "Gruppenchat erstellen", @@ -3222,7 +3222,7 @@ "Manage & explore rooms": "Räume entdecken und verwalten", "unknown person": "unbekannte Person", "Send and receive voice messages (in development)": "Sprachnachrichten senden und empfangen (in der Entwicklung)", - "Check your devices": "Überprüfe dein Gerät", + "Check your devices": "Überprüfe deine Sitzungen", "%(deviceId)s from %(ip)s": "%(deviceId)s von %(ip)s", "This homeserver has been blocked by it's administrator.": "Dieser Heimserver wurde von seiner Administration blockiert.", "You have unverified logins": "Du hast nicht-bestätigte Anmeldungen", @@ -3269,5 +3269,17 @@ "View all %(count)s members|other": "Alle %(count)s Mitglieder anzeigen", "View all %(count)s members|one": "Mitglied anzeigen", "%(count)s members including %(commaSeparatedMembers)s|one": "%(commaSeparatedMembers)s", - "Some of your messages have not been sent": "Einige Nachrichten konnten nicht gesendet werden" + "Some of your messages have not been sent": "Einige Nachrichten konnten nicht gesendet werden", + "Original event source": "Ursprüngliche Rohdaten", + "Decrypted event source": "Entschlüsselte Rohdaten", + "Sending": "Senden", + "You can select all or individual messages to retry or delete": "Du kannst einzelne oder alle Nachrichten erneut senden oder löschen", + "Delete all": "Alle löschen", + "Retry all": "Alle erneut senden", + "Without verifying, you won’t have access to all your messages and may appear as untrusted to others.": "Wenn du dich nicht verifizierst, kannst du keine deiner verschlüsselten Nachrichten lesen und andere vertrauen dir möglicherweise nicht.", + "Verify your identity to access encrypted messages and prove your identity to others.": "Verifiziere diese Anmeldung damit du auf deine verschlüsselten Nachrichten zugreifen kannst und anderen deine Identität zu bestätigen.", + "Use another login": "Mit anderem Gerät verifizeren", + "If you do, please note that none of your messages will be deleted, but the search experience might be degraded for a few moments whilst the index is recreated": "Falls du es wirklich willst: Es werden keine Nachrichten gelöscht. Außerdem wird die Suche, während der Index erstellt wird, etwas langsamer sein", + "%(count)s members including %(commaSeparatedMembers)s|other": "%(count)s Mitglieder inklusive %(commaSeparatedMembers)s", + "Including %(commaSeparatedMembers)s": "Inklusive%(commaSeparatedMembers)s" } From 8451e4aa4fcfbd12a333290f0c63839c07f48798 Mon Sep 17 00:00:00 2001 From: Hakim Oubouali Date: Thu, 29 Apr 2021 12:29:01 +0000 Subject: [PATCH 0160/1449] Translated using Weblate (Central Atlas Tamazight) Currently translated at 5.1% (152 of 2924 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/tzm/ --- src/i18n/strings/tzm.json | 119 +++++++++++++++++++++++++++++++++++++- 1 file changed, 118 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/tzm.json b/src/i18n/strings/tzm.json index 6b0fa316e6..f9ac9cf574 100644 --- a/src/i18n/strings/tzm.json +++ b/src/i18n/strings/tzm.json @@ -35,5 +35,122 @@ "The version of %(brand)s": "Taleqqemt n %(brand)s", "Add Phone Number": "Rnu uṭṭun n utilifun", "Add Email Address": "Rnu tasna imayl", - "Open": "Ṛẓem" + "Open": "Ṛẓem", + "Permissions": "Tisirag", + "Subscribe": "Zemmem", + "Change": "Senfel", + "Disconnect": "Kkes azday", + "exists": "illa", + "Santa": "Santa", + "Pizza": "Tapizzat", + "Corn": "Akbal", + "Cloud": "Tagut", + "Globe": "Amaḍal", + "Flower": "Ajeǧǧig", + "Butterfly": "Aferteṭṭu", + "Rooster": "Ayaẓiḍ", + "Panda": "Apanda", + "Upgrade": "Leqqem", + "Confirm": "Sentem", + "Brazil": "Brazil", + "Bolivia": "Bulivya", + "Bhutan": "Buṭan", + "Bermuda": "Birmuda", + "Benin": "Binin", + "Belize": "Biliz", + "Belgium": "Beljika", + "Belarus": "Bilarusya", + "Bahamas": "Bahamas", + "Aruba": "Aruba", + "Angola": "Angula", + "Andorra": "Andura", + "Algeria": "Dzayer", + "Albania": "Albanya", + "End": "End", + "Space": "Space", + "Shift": "Shift", + "Super": "Super", + "Ctrl": "Ctrl", + "Esc": "Esc", + "Calls": "Iɣuṛiten", + "Emoji": "Imuji", + "Afghanistan": "Afɣanistan", + "Logout": "Ffeɣ", + "Leave": "Fel", + "Phone": "Atilifun", + "Email": "Imayl", + "Go": "Ddu", + "Send": "Azen", + "example": "amedya", + "Example": "Amedya", + "Hide": "Ffer", + "Name": "Isem", + "Flags": "Icenyalen", + "Join": "Lkem", + "edited": "infel", + "Copied!": "inɣel!", + "Home": "Asnubeg", + "Reply": "Rar", + "Yes": "Yah", + "About": "Xef", + "Search…": "Arezzu…", + "A-Z": "A-Ẓ", + "Settings": "Tisɣal", + "Reject": "Agy", + "Re-join": "als-lkem", + "People": "Midden", + "Search": "Rzu", + "%(duration)sd": "%(duration)sas", + "Loading...": "Azdam...", + "Share": "Bḍu", + "Camera": "Takamiṛa", + "Microphone": "Amikṛu", + "Add": "Rnu", + "Ignore": "Nexxel", + "None": "Walu", + "Account": "Amiḍan", + "Theme": "Asgum", + "Algorithm:": "Talguritmit:", + "Save": "Ḥḍu", + "Profile": "Ifres", + "ID": "ID", + "Remove": "KKes", + "Folder": "Asdaw", + "Guitar": "Agiṭaṛ", + "Ball": "Tacama", + "Flag": "Acenyal", + "Telephone": "Atilifun", + "Key": "Tasarut", + "Book": "Adlis", + "Gift": "Timucit", + "Hat": "Tarazal", + "Robot": "Aṛubu", + "Heart": "Ul", + "Apple": "Tadeffuyt", + "Banana": "Tabanant", + "Fire": "Timessi", + "Moon": "Ayyur", + "Mushroom": "Agursel", + "Tree": "Aseklu", + "Fish": "Aselm", + "Turtle": "Ifker", + "Rabbit": "Agnin", + "Elephant": "Ilew", + "Pig": "Ilef", + "Close": "Rgel", + "Horse": "Ayyis", + "Lion": "Izem", + "Cat": "Amuc", + "Dog": "Aydi", + "or": "neɣ", + "Decline": "Agy", + "Guest": "Anebgi", + "Ok": "Wax", + "Notifications": "Tineɣmisin", + "No": "Uhu", + "Dark": "Adeɣmum", + "Usage": "Asemres", + "Feb": "Bṛa", + "Jan": "Yen", + "Continue": "Kemmel" } From e382684539394fd26e801755e89902a65f4b8764 Mon Sep 17 00:00:00 2001 From: Sebastian Lithgow Date: Fri, 30 Apr 2021 10:00:11 +0000 Subject: [PATCH 0161/1449] Translated using Weblate (Danish) Currently translated at 21.1% (617 of 2924 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/da/ --- src/i18n/strings/da.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/i18n/strings/da.json b/src/i18n/strings/da.json index ca28295c4f..15ce2986da 100644 --- a/src/i18n/strings/da.json +++ b/src/i18n/strings/da.json @@ -71,7 +71,7 @@ "No rooms to show": "Ingen rum at vise", "This email address is already in use": "Denne email adresse er allerede i brug", "This phone number is already in use": "Dette telefonnummer er allerede i brug", - "Failed to verify email address: make sure you clicked the link in the email": "Kunne ikke bekræfte emailaddressen: vær sikker på at klikke på linket i emailen", + "Failed to verify email address: make sure you clicked the link in the email": "Kunne ikke bekræfte emailaddressen: vær sikker på at klikke på linket i e-mailen", "Call Timeout": "Opkalds Timeout", "The remote side failed to pick up": "Den anden side tog den ikke", "Unable to capture screen": "Kunne ikke optage skærm", @@ -473,9 +473,9 @@ "Show a placeholder for removed messages": "Vis en pladsholder for fjernede beskeder", "Whether you're using %(brand)s on a device where touch is the primary input mechanism": "Hvorvidt du benytter %(brand)s på en enhed, hvor touch er den primære input-grænseflade", "Your user agent": "Din user agent", - "Use Single Sign On to continue": "Brug Single Sign On til at fortsætte", + "Use Single Sign On to continue": "Brug engangs login for at fortsætte", "Confirm adding this email address by using Single Sign On to prove your identity.": "Bekræft tilføjelsen af denne email adresse ved at bruge Single Sign On til at bevise din identitet.", - "Single Sign On": "Single Sign On", + "Single Sign On": "Engangs login", "Confirm adding email": "Bekræft tilføjelse af email", "Click the button below to confirm adding this email address.": "Klik på knappen herunder for at bekræfte tilføjelsen af denne email adresse.", "Confirm": "Bekræft", From b96bf63d6f1dfbdd3109857c777d1c9da827b70f Mon Sep 17 00:00:00 2001 From: waclaw66 Date: Thu, 29 Apr 2021 20:20:06 +0000 Subject: [PATCH 0162/1449] Translated using Weblate (Czech) Currently translated at 100.0% (2924 of 2924 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 | 52 ++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/i18n/strings/cs.json b/src/i18n/strings/cs.json index 714d34abfa..bc1dff54fd 100644 --- a/src/i18n/strings/cs.json +++ b/src/i18n/strings/cs.json @@ -323,7 +323,7 @@ "%(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, from the point they joined.": "%(senderName)s nastavil(a) viditelnost budoucích zpráv v této místnosti pro všechny její členy 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.", @@ -744,7 +744,7 @@ "e.g. ": "např. ", "Your device resolution": "Rozlišení obrazovky vašeho zařízení", "The information being sent to us to help make %(brand)s better includes:": "Abychom mohli %(brand)s zlepšovat, posíláte nám následující informace:", - "Where this page includes identifiable information, such as a room, user or group ID, that data is removed before being sent to the server.": "V případě, že se na stránce vyskytují identifikační údaje, jako například název místnosti, ID uživatele, místnosti a nebo skupiny, jsou tyto údaje před odesláním na server odstraněny.", + "Where this page includes identifiable information, such as a room, user or group ID, that data is removed before being sent to the server.": "Pokud tato stránka obsahuje identifikovatelné údaje, například ID místnosti, uživatele nebo skupiny, jsou tyto údaje před odesláním na server odstraněny.", "Call in Progress": "Probíhající hovor", "A call is currently being placed!": "Právě probíhá jiný hovor!", "A call is already in progress!": "Jeden hovor už probíhá!", @@ -990,7 +990,7 @@ "Straight rows of keys are easy to guess": "Řádky na klávesnici je moc jednoduché uhodnout", "Short keyboard patterns are easy to guess": "Krátké sekvence kláves je moc jednoduché uhodnout", "There was an error joining the room": "Při vstupu do místnosti došlo k chybě", - "Sorry, your homeserver is too old to participate in this room.": "Jejda, váš domovský server je moc zastaralý abyste do této místnosti mohli vstoupit.", + "Sorry, your homeserver is too old to participate in this room.": "Omlouváme se, ale váš domovský server je příliš zastaralý pro vstup do této místnosti.", "Please contact your homeserver administrator.": "Kontaktujte prosím správce domovského serveru.", "The other party cancelled the verification.": "Druhá strana ověření zrušila.", "Verified!": "Ověřeno!", @@ -1130,9 +1130,9 @@ "Without setting up Secure Message Recovery, you'll lose your secure message history when you log out.": "Bez nastavení bezpečného obnovení zpráv přijdete po odhlášení o historii šifrované komunikace.", "Show a reminder to enable Secure Message Recovery in encrypted rooms": "V šifrovaných konverzacích zobrazovat upozornění na možnost aktivovat bezpečné obnovení zpráv", "Gets or sets the room topic": "Nastaví nebo zjistí téma místnosti", - "Forces the current outbound group session in an encrypted room to be discarded": "Zahodí aktuálně používanou kryptografickou session na odchozí zprávy", + "Forces the current outbound group session in an encrypted room to be discarded": "Vynutí zahození aktuálně používané relace skupiny v zašifrované místnosti", "Custom user status messages": "Vlastní statusy", - "Group & filter rooms by custom tags (refresh to apply changes)": "Skupinkování a filtování místností podle štítků (vyžaduje znovunačtení stránky)", + "Group & filter rooms by custom tags (refresh to apply changes)": "Seskupování a filtrování místností podle vlastních štítků (vyžaduje znovunačtení stránky)", "Render simple counters in room header": "Zobrazovat stavová počítadla v hlavičce místnosti", "Enable Community Filter Panel": "Povolit panel Filtr skupiny", "Show developer tools": "Zobrazit nástroje pro vývojáře", @@ -1205,7 +1205,7 @@ "Remove messages": "Mazat zprávy", "Notify everyone": "Oznámení pro celou místnost", "Enable encryption?": "Povolit šifrování?", - "Once enabled, encryption for a room cannot be disabled. Messages sent in an encrypted room cannot be seen by the server, only by the participants of the room. Enabling encryption may prevent many bots and bridges from working correctly. Learn more about encryption.": "Po zapnutí už nelze šifrování v této místnosti vypnout. Zprávy v šifrovaných místnostech mohou číst jenom členové místnosti, server se k obsahu nedostane. Šifrování místností nepodporuje většina botů a propojení. Více informací o šifrování.", + "Once enabled, encryption for a room cannot be disabled. Messages sent in an encrypted room cannot be seen by the server, only by the participants of the room. Enabling encryption may prevent many bots and bridges from working correctly. Learn more about encryption.": "Po zapnutí již nelze šifrování v této místnosti vypnout. Zprávy v šifrovaných místnostech mohou číst jen členové místnosti, server se k obsahu nedostane. Šifrování místností nepodporuje většina botů a propojení. Více informací o šifrování.", "Error updating main address": "Nepovedlo se změnit hlavní adresu", "There was an error updating the room's main address. It may not be allowed by the server or a temporary failure occurred.": "Nastala chyba při pokusu o nastavení hlavní adresy místnosti. Mohl to zakázat server, nebo to může být dočasná chyba.", "Power level": "Úroveň oprávnění", @@ -1219,7 +1219,7 @@ "Your Matrix account on %(serverName)s": "Váš účet Matrix na serveru %(serverName)s", "Whether or not you're using the 'breadcrumbs' feature (avatars above the room list)": "Zda používáte funkci „breadcrumb“ (ikony nad seznamem místností)", "Replying With Files": "Odpovídání souborem", - "At this time it is not possible to reply with a file. Would you like to upload this file without replying?": "Aktuálně nelze odpovědět souborem. Chcete soubor nahrát a poslat bez odpovídání?", + "At this time it is not possible to reply with a file. Would you like to upload this file without replying?": "V tuto chvíli není možné odpovědět souborem. Chcete tento soubor nahrát bez odpovědi?", "The file '%(fileName)s' failed to upload.": "Soubor '%(fileName)s' se nepodařilo nahrát.", "The server does not support the room version specified.": "Server nepodporuje určenou verzi místnosti.", "Name or Matrix ID": "Jméno nebo Matrix ID", @@ -1354,12 +1354,12 @@ "Unexpected error resolving identity server configuration": "Chyba při hledání konfigurace serveru identity", "Use lowercase letters, numbers, dashes and underscores only": "Používejte pouze malá písmena, čísla, pomlčky a podtržítka", "Cannot reach identity server": "Nelze se připojit k serveru identity", - "You can register, but some features will be unavailable until the identity server is back online. If you keep seeing this warning, check your configuration or contact a server admin.": "Můžete se zaregistrovat, ale některé funkce nebudou dostupné dokud nezačne server identity fungovat. Pokud se vám toto varování zobrazuje pořád, tak zkontrolujte svojí konfiguraci a nebo kontaktujte správce serveru.", - "You can reset your password, but some features will be unavailable until the identity server is back online. If you keep seeing this warning, check your configuration or contact a server admin.": "Můžete si změnit heslo, ale některé funkce nebudou dostupné dokud nezačne server identity fungovat. Pokud se vám toto varování zobrazuje pořád, tak zkontrolujte svojí konfiguraci a nebo kontaktujte správce serveru.", - "You can log in, but some features will be unavailable until the identity server is back online. If you keep seeing this warning, check your configuration or contact a server admin.": "Můžete se přihlásit, ale některé funkce nebudou dostupné dokud nezačne server identity fungovat. Pokud se vám toto varování zobrazuje pořád, tak zkontrolujte svojí konfiguraci a nebo kontaktujte správce serveru.", + "You can register, but some features will be unavailable until the identity server is back online. If you keep seeing this warning, check your configuration or contact a server admin.": "Můžete se zaregistrovat, ale některé funkce nebudou dostupné dokud nezačne server identity fungovat. Pokud se vám toto varování zobrazuje i nadále, zkontrolujte svojí konfiguraci nebo kontaktujte správce serveru.", + "You can reset your password, but some features will be unavailable until the identity server is back online. If you keep seeing this warning, check your configuration or contact a server admin.": "Můžete si změnit heslo, ale některé funkce nebudou dostupné dokud nezačne server identity fungovat. Pokud se toto varování zobrazuje i nadále, zkontrolujte svojí konfiguraci nebo kontaktujte správce serveru.", + "You can log in, but some features will be unavailable until the identity server is back online. If you keep seeing this warning, check your configuration or contact a server admin.": "Můžete se přihlásit, ale některé funkce nebudou dostupné dokud nezačne server identity fungovat. Pokud se vám toto varování zobrazuje i nadále, zkontrolujte svojí konfiguraci nebo kontaktujte správce serveru.", "Call failed due to misconfigured server": "Volání selhalo, protože je rozbitá konfigurace serveru", - "Please ask the administrator of your homeserver (%(homeserverDomain)s) to configure a TURN server in order for calls to work reliably.": "Zeptejte se správce (%(homeserverDomain)s) jestli by nemohl nakonfigurovat server TURN, aby začalo fungoval volání.", - "Alternatively, you can try to use the public server at turn.matrix.org, but this will not be as reliable, and it will share your IP address with that server. You can also manage this in Settings.": "Případně můžete zkusit použít veřejný server turn.matrix.org, což nemusí fungovat tak spolehlivě a řekne to tomu cizímu serveru vaší IP adresu. Můžete to udělat v Nastavení.", + "Please ask the administrator of your homeserver (%(homeserverDomain)s) to configure a TURN server in order for calls to work reliably.": "Požádejte správce svého homeserveru (%(homeserverDomain)s) jestli by nemohl nakonfigurovat TURN server, aby volání fungovala spolehlivě.", + "Alternatively, you can try to use the public server at turn.matrix.org, but this will not be as reliable, and it will share your IP address with that server. You can also manage this in Settings.": "Můžete také zkusit použít veřejný server na adrese turn.matrix.org, ale ten nebude tak spolehlivý a bude sdílet vaši IP adresu s tímto serverem. To můžete spravovat také v Nastavení.", "Try using turn.matrix.org": "Zkuste použít turn.matrix.org", "Messages": "Zprávy", "Actions": "Akce", @@ -1368,7 +1368,7 @@ "Changes the avatar of the current room": "Změní avatar této místnosti", "Changes your avatar in all rooms": "Změní váš avatar pro všechny místnosti", "Use an identity server": "Používat server identit", - "Use an identity server to invite by email. Click continue to use the default identity server (%(defaultIdentityServerName)s) or manage in Settings.": "Použít server identit k odeslání e-mailové pozvánky. Pokračováním použijete výchozí server identit (%(defaultIdentityServerName)s) nebo ho můžete změnit v Nastavení.", + "Use an identity server to invite by email. Click continue to use the default identity server (%(defaultIdentityServerName)s) or manage in Settings.": "K pozvání e-mailem použijte server identit. Pokračováním použijete výchozí server identit (%(defaultIdentityServerName)s) nebo ho můžete změnit v Nastavení.", "Use an identity server to invite by email. Manage in Settings.": "Použít server identit na odeslání e-mailové pozvánky. Můžete spravovat v Nastavení.", "Displays list of commands with usages and descriptions": "Zobrazuje seznam příkazu s popiskem", "%(senderName)s made no change.": "%(senderName)s neudělal žádnou změnu.", @@ -1721,8 +1721,8 @@ "Unknown (user, session) pair:": "Neznámý pár (uživatel, relace):", "Session already verified!": "Relace je už ověřená!", "WARNING: Session already verified, but keys do NOT MATCH!": "VAROVÁNÍ: Relace je už ověřená, ale klíče NEODPOVÍDAJÍ!", - "WARNING: KEY VERIFICATION FAILED! The signing key for %(userId)s and session %(deviceId)s is \"%(fprint)s\" which does not match the provided key \"%(fingerprint)s\". This could mean your communications are being intercepted!": "VAROVÁNÍ: OVĚŘENÍ KLÍČŮ SELHALO! Podpisový klíč pro uživatele %(userId)s a relaci %(deviceId)s je „%(fprint)s“, což neodpovídá klíči „%(fingerprint)s“. Může to znamenat, že je vaše komunikace rušena!", - "The signing key you provided matches the signing key you received from %(userId)s's session %(deviceId)s. Session marked as verified.": "Zadaný podpisový klíč odpovídá klíči relace %(deviceId)s od uživatele %(userId)s. Relace byla označena za platnou.", + "WARNING: KEY VERIFICATION FAILED! The signing key for %(userId)s and session %(deviceId)s is \"%(fprint)s\" which does not match the provided key \"%(fingerprint)s\". This could mean your communications are being intercepted!": "VAROVÁNÍ: OVĚŘENÍ KLÍČE SE NEZDAŘILO! Podpisový klíč pro uživatele %(userId)s a relaci %(deviceId)s je „%(fprint)s“, což neodpovídá klíči „%(fingerprint)s“. To by mohlo znamenat, že vaše komunikace je zachycována!", + "The signing key you provided matches the signing key you received from %(userId)s's session %(deviceId)s. Session marked as verified.": "Zadaný podpisový klíč odpovídá klíči relace %(deviceId)s od uživatele %(userId)s. Relace byla označena jako ověřená.", "a few seconds ago": "před pár vteřinami", "about a minute ago": "před minutou", "%(num)s minutes ago": "před %(num)s minutami", @@ -1917,8 +1917,8 @@ "Compare unique emoji": "Porovnejte jedinečnou kombinaci emoji", "Compare a unique set of emoji if you don't have a camera on either device": "Pokud na žádném zařízení nemáte kameru, porovnejte jedinečnou kombinaci emoji", "Not Trusted": "Nedůvěryhodné", - "%(name)s (%(userId)s) signed in to a new session without verifying it:": "%(name)s (%(userId)s) se přihlásil do nové relace a neověřil ji:", - "Ask this user to verify their session, or manually verify it below.": "Poproste tohoto uživatele aby svojí relaci ověřil a nebo jí níže můžete ověřit manuálně.", + "%(name)s (%(userId)s) signed in to a new session without verifying it:": "%(name)s (%(userId)s) se přihlásil do nové relace bez ověření:", + "Ask this user to verify their session, or manually verify it below.": "Požádejte tohoto uživatele, aby ověřil svou relaci, nebo jí níže můžete ověřit manuálně.", "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", @@ -2032,8 +2032,8 @@ "Could not find user in room": "Nepovedlo se najít uživatele v místnosti", "Please supply a widget URL or embed code": "Zadejte prosím URL widgetu nebo jeho kód", "Send a bug report with logs": "Zaslat hlášení o chybě", - "You signed in to a new session without verifying it:": "Přihlásili jste se do nové relace, ale neoveřili jste ji:", - "Verify your other session using one of the options below.": "Ověřte ostatní relací jedním z následujících způsobů.", + "You signed in to a new session without verifying it:": "Přihlásili jste se do nové relace, aniž byste ji ověřili:", + "Verify your other session using one of the options below.": "Ověřte další relaci jedním z následujících způsobů.", "Click the button below to confirm deleting these sessions.|other": "Zmáčknutím tlačítka potvrdíte smazání těchto relací.", "Click the button below to confirm deleting these sessions.|one": "Zmáčknutím tlačítka potvrdíte smazání této relace.", "Delete sessions|other": "Smazat relace", @@ -2093,7 +2093,7 @@ "Please verify the room ID or address and try again.": "Ověřte prosím, že ID místnosti je správné a zkuste to znovu.", "Room ID or address of ban list": "ID nebo adresa seznamu zablokovaných", "Help us improve %(brand)s": "Pomozte nám zlepšovat %(brand)s", - "Send anonymous usage data which helps us improve %(brand)s. This will use a cookie.": "Zasílat anonymní data o použití aplikace, která nám pomáhají %(brand)s zlepšovat. Bedeme na to používat soubory cookie.", + "Send anonymous usage data which helps us improve %(brand)s. This will use a cookie.": "Zasílat anonymní údaje o použití aplikace, která nám pomáhají %(brand)s zlepšovat. K tomu se použije soubor cookie.", "I want to help": "Chci pomoci", "Your homeserver has exceeded its user limit.": "Na vašem domovském serveru byl překročen limit počtu uživatelů.", "Your homeserver has exceeded one of its resource limits.": "Na vašem domovském serveru byl překročen limit systémových požadavků.", @@ -2166,8 +2166,8 @@ "Signature upload failed": "Podpis se nepodařilo nahrát", "If the other version of %(brand)s is still open in another tab, please close it as using %(brand)s on the same host with both lazy loading enabled and disabled simultaneously will cause issues.": "Je-li jiná verze programu %(brand)s stále otevřená na jiné kartě, tak ji prosím zavřete, neboť užívání programu %(brand)s stejným hostitelem se zpožděným nahráváním současně povoleným i zakázaným bude působit problémy.", "Unexpected server error trying to leave the room": "Neočekávaná chyba serveru při odcházení z místnosti", - "The person who invited you already left the room.": "Uživatel který vás pozval už místnosti není.", - "The person who invited you already left the room, or their server is offline.": "Uživatel který vás pozvat už odešel z místnosti a nebo je jeho server offline.", + "The person who invited you already left the room.": "Uživatel, který vás pozval, již opustil místnost.", + "The person who invited you already left the room, or their server is offline.": "Uživatel, který vás pozval, již opustil místnost nebo je jeho server offline.", "You left the call": "Odešli jste z hovoru", "%(senderName)s left the call": "%(senderName)s opustil/a hovor", "Call ended": "Hovor skončil", @@ -2954,13 +2954,13 @@ "Mobile experience": "Zážitek na mobilních zařízeních", "Element Web is currently experimental on mobile. The native apps are recommended for most people.": "Element Web je v současné době experimentální na mobilních zařízeních. Nativní aplikace se doporučují pro většinu lidí.", "Use app for a better experience": "Pro lepší zážitek použijte aplikaci", - "Element Web is experimental on mobile. For a better experience and the latest features, use our free native app.": "Element Web je experimentální na mobilních zařízeních. Pro lepší zážitek a nejnovější funkce použijte naši bezplatnou nativní aplikaci.", + "Element Web is experimental on mobile. For a better experience and the latest features, use our free native app.": "Element Web je v mobilní verzi experimentální. Chcete-li získat lepší zážitek a nejnovější funkce, použijte naši bezplatnou nativní aplikaci.", "Use app": "Použijte aplikaci", "Something went wrong in confirming your identity. Cancel and try again.": "Při ověřování vaší identity se něco pokazilo. Zrušte to a zkuste to znovu.", - "Your homeserver rejected your log in attempt. This could be due to things just taking too long. Please try again. If this continues, please contact your homeserver administrator.": "Váš domovský server odmítl váš pokus o přihlášení. Může to být způsobeno tím, že věci trvají příliš dlouho. Prosím zkuste to znovu. Pokud to bude pokračovat, obraťte se na správce domovského serveru.", + "Your homeserver rejected your log in attempt. This could be due to things just taking too long. Please try again. If this continues, please contact your homeserver administrator.": "Váš domovský server odmítl váš pokus o přihlášení. To může to být způsobeno tím, že vše trvá příliš dlouho. Zkuste to prosím znovu. Pokud tento problém přetrvává, obraťte se na správce domovského serveru.", "Your homeserver was unreachable and was not able to log you in. Please try again. If this continues, please contact your homeserver administrator.": "Váš domovský server nebyl dosažitelný a nemohl vás přihlásit. Zkuste to prosím znovu. Pokud to bude pokračovat, obraťte se na správce domovského serveru.", "Try again": "Zkuste to znovu", - "We asked the browser to remember which homeserver you use to let you sign in, but unfortunately your browser has forgotten it. Go to the sign in page and try again.": "Požádali jsme prohlížeč, aby si pamatoval, který domovský server používáte k přihlášení, ale váš prohlížeč to bohužel zapomněl. Přejděte na přihlašovací stránku a zkuste to znovu.", + "We asked the browser to remember which homeserver you use to let you sign in, but unfortunately your browser has forgotten it. Go to the sign in page and try again.": "Požádali jsme prohlížeč, aby si zapamatoval, který domovský server používáte k přihlášení, ale váš prohlížeč to bohužel zapomněl. Přejděte na přihlašovací stránku a zkuste to znovu.", "We couldn't log you in": "Nemohli jsme vás přihlásit", "Show stickers button": "Tlačítko Zobrazit nálepky", "Windows": "Okna", @@ -3203,7 +3203,7 @@ "Let's create a room for each of them.": "Vytvořme pro každé z nich místnost.", "Use another login": "Použijte jiné přihlašovací jméno", "Without verifying, you won’t have access to all your messages and may appear as untrusted to others.": "Bez ověření nebudete mít přístup ke všem svým zprávám a ostatním se můžete zobrazit jako nedůvěryhodný.", - "You are the only person here. If you leave, no one will be able to join in the future, including you.": "Jste zde jediný člověk. Pokud odejdete, nikdo se v budoucnu nebude moci připojit, včetně vás.", + "You are the only person here. If you leave, no one will be able to join in the future, including you.": "Jste zde jediná osoba. Pokud odejdete, nikdo se v budoucnu nebude moci připojit, včetně vás.", "If you reset everything, you will restart with no trusted sessions, no trusted users, and might not be able to see past messages.": "Pokud vše resetujete, začnete bez důvěryhodných relací, bez důvěryhodných uživatelů a možná nebudete moci zobrazit minulé zprávy.", "Only do this if you have no other device to complete verification with.": "Udělejte to, pouze pokud nemáte žádné jiné zařízení, se kterým byste mohli dokončit ověření.", "Reset everything": "Resetovat vše", From bebcb32e8fb4270632c4c2a2a85a2271a8b121b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sun, 2 May 2021 16:23:35 +0200 Subject: [PATCH 0163/1449] Add dragCallbacks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/CallView.tsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/components/views/voip/CallView.tsx b/src/components/views/voip/CallView.tsx index 6745713845..65547bb814 100644 --- a/src/components/views/voip/CallView.tsx +++ b/src/components/views/voip/CallView.tsx @@ -49,6 +49,13 @@ interface IProps { // This is sort of a proxy for a number of things but we currently have no // need to control those things separately, so this is simpler. pipMode?: boolean; + + // Callbacks for dragging the CallView in PIP mode + dragCallbacks?: { + onStartMoving: (event: React.MouseEvent) => void; + onMoving: (event: React.MouseEvent) => void; + onEndMoving: () => void; + } } interface IState { From 8948c7419cdbd587550e20720ea0bb6f11a44358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sun, 2 May 2021 16:24:47 +0200 Subject: [PATCH 0164/1449] Call dragCallbacks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/CallView.tsx | 30 ++++++++++++++++---------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/components/views/voip/CallView.tsx b/src/components/views/voip/CallView.tsx index 65547bb814..c35e62448e 100644 --- a/src/components/views/voip/CallView.tsx +++ b/src/components/views/voip/CallView.tsx @@ -623,19 +623,27 @@ export default class CallView extends React.Component { ; } - header =
    - - - -
    -
    {callRoom.name}
    -
    - {callTypeText} - {secondaryCallInfo} + header = ( +
    + + + +
    +
    {callRoom.name}
    +
    + {callTypeText} + {secondaryCallInfo} +
    + {headerControls}
    - {headerControls} -
    ; + ); myClassName = 'mx_CallView_pip'; } From c97bbe11a93eb9c49ce45b4f1a4c2df280b344a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sun, 2 May 2021 16:26:03 +0200 Subject: [PATCH 0165/1449] Prep state and props for dragging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/CallPreview.tsx | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/components/views/voip/CallPreview.tsx b/src/components/views/voip/CallPreview.tsx index d31afddec9..8dca5314e5 100644 --- a/src/components/views/voip/CallPreview.tsx +++ b/src/components/views/voip/CallPreview.tsx @@ -50,6 +50,13 @@ interface IState { // Any other call we're displaying: only if the user is on two calls and not viewing either of the rooms // they belong to secondaryCall: MatrixCall; + + // Position of the CallPreview + translationX: number; + translationY: number; + + // True if the CallPreview is being dragged + moving: boolean; } // Splits a list of calls into one 'primary' one and a list @@ -106,9 +113,17 @@ export default class CallPreview extends React.Component { roomId, primaryCall: primaryCall, secondaryCall: secondaryCalls[0], + translationX: 0, + translationY: 0, + moving: false, }; } + private initX = 0; + private initY = 0; + private lastX = 0; + private lastY = 0; + public componentDidMount() { this.roomStoreToken = RoomViewStore.addListener(this.onRoomViewStoreUpdate); this.dispatcherRef = dis.register(this.onAction); From f64a9501955e5506b09e35009003133edf268dc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sun, 2 May 2021 16:26:41 +0200 Subject: [PATCH 0166/1449] Prep basic methods for dragging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/CallPreview.tsx | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/components/views/voip/CallPreview.tsx b/src/components/views/voip/CallPreview.tsx index 8dca5314e5..68fcef6747 100644 --- a/src/components/views/voip/CallPreview.tsx +++ b/src/components/views/voip/CallPreview.tsx @@ -184,6 +184,29 @@ export default class CallPreview extends React.Component { }); } + private onStartMoving = (event: React.MouseEvent) => { + this.setState({moving: true}); + + this.initX = event.pageX - this.lastX; + this.initY = event.pageY - this.lastY; + } + + private onMoving = (event: React.MouseEvent) => { + if (!this.state.moving) return; + + this.lastX = event.pageX - this.initX; + this.lastY = event.pageY - this.initY; + + this.setState({ + translationX: this.lastX, + translationY: this.lastY, + }); + } + + private onEndMoving = () => { + this.setState({moving: false}); + } + public render() { if (this.state.primaryCall) { return ( From 11222e7a467a6e58007ae14e539856a21251bd20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sun, 2 May 2021 16:26:54 +0200 Subject: [PATCH 0167/1449] Wire up dragging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/CallPreview.tsx | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/components/views/voip/CallPreview.tsx b/src/components/views/voip/CallPreview.tsx index 68fcef6747..499cdfb526 100644 --- a/src/components/views/voip/CallPreview.tsx +++ b/src/components/views/voip/CallPreview.tsx @@ -209,8 +209,26 @@ export default class CallPreview extends React.Component { public render() { if (this.state.primaryCall) { + const translatePixelsX = this.state.translationX + "px"; + const translatePixelsY = this.state.translationY + "px"; + const style = { + transform: `translateX(${translatePixelsX}) + translateY(${translatePixelsY})`, + }; + return ( - +
    + +
    ); } From b42872daa409d27ad4634d2418fee2bfa7dccfea Mon Sep 17 00:00:00 2001 From: Ayush PS Date: Sun, 2 May 2021 22:10:15 +0530 Subject: [PATCH 0168/1449] Fixed the Dial Pad and finalized the changes --- res/css/views/voip/_DialPadContextMenu.scss | 5 +++-- .../views/context_menus/DialpadContextMenu.tsx | 12 +++++------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/res/css/views/voip/_DialPadContextMenu.scss b/res/css/views/voip/_DialPadContextMenu.scss index c01ce0f2d9..31327113cf 100644 --- a/res/css/views/voip/_DialPadContextMenu.scss +++ b/res/css/views/voip/_DialPadContextMenu.scss @@ -33,14 +33,15 @@ limitations under the License. max-width: 150px; border: none; margin: 0px; - } -.mx_DialPadContextMenu_dialled input{ +.mx_DialPadContextMenu_dialled input { font-size: 18px; font-weight: 600; overflow: hidden; + max-width: 150px; text-align: left; direction: rtl; + padding: 8px 0px; background-color: rgb(0, 0, 0, 0); } diff --git a/src/components/views/context_menus/DialpadContextMenu.tsx b/src/components/views/context_menus/DialpadContextMenu.tsx index 0a1d8184f2..8879629055 100644 --- a/src/components/views/context_menus/DialpadContextMenu.tsx +++ b/src/components/views/context_menus/DialpadContextMenu.tsx @@ -48,7 +48,7 @@ export default class DialpadContextMenu extends React.Component onChange = (ev) => { this.setState({value: ev.target.value}); } - + render() { return @@ -56,12 +56,10 @@ export default class DialpadContextMenu extends React.Component
    {_t("Dial pad")}
    - - - +
    From 241e626e96a85fcf48a028f3af418ccd14e5235f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sun, 2 May 2021 20:55:05 +0200 Subject: [PATCH 0169/1449] Don't listen for onMouseLeave MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This would cause problems because the moving element wouldn't catch up with the user Signed-off-by: Šimon Brandner --- src/components/views/voip/CallView.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/views/voip/CallView.tsx b/src/components/views/voip/CallView.tsx index c35e62448e..23a4fcca59 100644 --- a/src/components/views/voip/CallView.tsx +++ b/src/components/views/voip/CallView.tsx @@ -629,7 +629,6 @@ export default class CallView extends React.Component { onMouseDown={this.props.dragCallbacks?.onStartMoving} onMouseMove={this.props.dragCallbacks?.onMoving} onMouseUp={this.props.dragCallbacks?.onEndMoving} - onMouseLeave={this.props.dragCallbacks?.onEndMoving} > From 53b8fd3072f8dddcb4e5e8b44da6d77c3a1e6ac3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sun, 2 May 2021 20:57:18 +0200 Subject: [PATCH 0170/1449] Listen for mousemove on document scale MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/CallPreview.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/views/voip/CallPreview.tsx b/src/components/views/voip/CallPreview.tsx index 499cdfb526..17e2e9cf1a 100644 --- a/src/components/views/voip/CallPreview.tsx +++ b/src/components/views/voip/CallPreview.tsx @@ -126,12 +126,14 @@ export default class CallPreview extends React.Component { public componentDidMount() { this.roomStoreToken = RoomViewStore.addListener(this.onRoomViewStoreUpdate); + document.addEventListener("mousemove", this.onMoving); this.dispatcherRef = dis.register(this.onAction); MatrixClientPeg.get().on(CallEvent.RemoteHoldUnhold, this.onCallRemoteHold); } public componentWillUnmount() { MatrixClientPeg.get().removeListener(CallEvent.RemoteHoldUnhold, this.onCallRemoteHold); + document.removeEventListener("mousemove", this.onMoving); if (this.roomStoreToken) { this.roomStoreToken.remove(); } @@ -191,7 +193,7 @@ export default class CallPreview extends React.Component { this.initY = event.pageY - this.lastY; } - private onMoving = (event: React.MouseEvent) => { + private onMoving = (event: React.MouseEvent | MouseEvent) => { if (!this.state.moving) return; this.lastX = event.pageX - this.initX; From fca5347668465341ef0757c56de0adb78235741a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sun, 2 May 2021 21:17:59 +0200 Subject: [PATCH 0171/1449] Add preventDefault() and stopPropagation() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This avoids text being selected while dragging Signed-off-by: Šimon Brandner --- src/components/views/voip/CallPreview.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/components/views/voip/CallPreview.tsx b/src/components/views/voip/CallPreview.tsx index 17e2e9cf1a..761458cb4c 100644 --- a/src/components/views/voip/CallPreview.tsx +++ b/src/components/views/voip/CallPreview.tsx @@ -187,6 +187,9 @@ export default class CallPreview extends React.Component { } private onStartMoving = (event: React.MouseEvent) => { + event.preventDefault(); + event.stopPropagation(); + this.setState({moving: true}); this.initX = event.pageX - this.lastX; @@ -194,6 +197,9 @@ export default class CallPreview extends React.Component { } private onMoving = (event: React.MouseEvent | MouseEvent) => { + event.preventDefault(); + event.stopPropagation(); + if (!this.state.moving) return; this.lastX = event.pageX - this.initX; From 51e80dd17228f5645c0b7bbab42206a0bffa43fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 3 May 2021 07:50:21 +0200 Subject: [PATCH 0172/1449] Remove onMoving listner from CallView MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is not necessary since we already listen for it in CallPreview Signed-off-by: Šimon Brandner --- src/components/views/voip/CallView.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/views/voip/CallView.tsx b/src/components/views/voip/CallView.tsx index 23a4fcca59..cbedfb3a3d 100644 --- a/src/components/views/voip/CallView.tsx +++ b/src/components/views/voip/CallView.tsx @@ -53,7 +53,6 @@ interface IProps { // Callbacks for dragging the CallView in PIP mode dragCallbacks?: { onStartMoving: (event: React.MouseEvent) => void; - onMoving: (event: React.MouseEvent) => void; onEndMoving: () => void; } } @@ -627,7 +626,6 @@ export default class CallView extends React.Component {
    From 7042eb38ddb7f838b2fe8dc952aef7c02f45e3e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 3 May 2021 08:12:54 +0200 Subject: [PATCH 0173/1449] Listen for mouseup on the document MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/CallPreview.tsx | 2 ++ src/components/views/voip/CallView.tsx | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/views/voip/CallPreview.tsx b/src/components/views/voip/CallPreview.tsx index 761458cb4c..aa2e71339e 100644 --- a/src/components/views/voip/CallPreview.tsx +++ b/src/components/views/voip/CallPreview.tsx @@ -127,6 +127,7 @@ export default class CallPreview extends React.Component { public componentDidMount() { this.roomStoreToken = RoomViewStore.addListener(this.onRoomViewStoreUpdate); document.addEventListener("mousemove", this.onMoving); + document.addEventListener("mouseup", this.onEndMoving); this.dispatcherRef = dis.register(this.onAction); MatrixClientPeg.get().on(CallEvent.RemoteHoldUnhold, this.onCallRemoteHold); } @@ -134,6 +135,7 @@ export default class CallPreview extends React.Component { public componentWillUnmount() { MatrixClientPeg.get().removeListener(CallEvent.RemoteHoldUnhold, this.onCallRemoteHold); document.removeEventListener("mousemove", this.onMoving); + document.removeEventListener("mouseup", this.onEndMoving); if (this.roomStoreToken) { this.roomStoreToken.remove(); } diff --git a/src/components/views/voip/CallView.tsx b/src/components/views/voip/CallView.tsx index cbedfb3a3d..1f555e5227 100644 --- a/src/components/views/voip/CallView.tsx +++ b/src/components/views/voip/CallView.tsx @@ -626,7 +626,6 @@ export default class CallView extends React.Component {
    From 24bf1b22a440ef810fac33b975015c65d1a3f03d Mon Sep 17 00:00:00 2001 From: Ayush PS Date: Mon, 3 May 2021 13:54:42 +0530 Subject: [PATCH 0174/1449] Removes the override on the Bubble Container --- res/css/views/rooms/_EventTile.scss | 2 -- 1 file changed, 2 deletions(-) diff --git a/res/css/views/rooms/_EventTile.scss b/res/css/views/rooms/_EventTile.scss index 2b3e179c54..5e110f9c6d 100644 --- a/res/css/views/rooms/_EventTile.scss +++ b/res/css/views/rooms/_EventTile.scss @@ -123,8 +123,6 @@ $left-gutter: 64px; .mx_EventTile_line { margin-right: 0; grid-column: 1 / 3; - // override default padding of mx_EventTile_line so that we can be centered - padding: 0 !important; } .mx_EventTile_msgOption { From 1f1f7decdfe57a702fc52da88f92711a558db403 Mon Sep 17 00:00:00 2001 From: iaiz Date: Sat, 1 May 2021 10:46:38 +0000 Subject: [PATCH 0175/1449] Translated using Weblate (Spanish) Currently translated at 100.0% (2924 of 2924 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/es/ --- src/i18n/strings/es.json | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/es.json b/src/i18n/strings/es.json index d396cc318f..155aed321b 100644 --- a/src/i18n/strings/es.json +++ b/src/i18n/strings/es.json @@ -3225,5 +3225,28 @@ "Use another login": "Usar otro inicio de sesión", "Verify your identity to access encrypted messages and prove your identity to others.": "Verifica tu identidad para acceder a mensajes cifrados y probar tu identidad a otros.", "Without verifying, you won’t have access to all your messages and may appear as untrusted to others.": "Si no verificas no tendrás acceso a todos tus mensajes y puede que aparezcas como no confiable para otros usuarios.", - "Invite messages are hidden by default. Click to show the message.": "Los mensajes de invitación no se muestran por defecto. Haz clic para mostrarlo." + "Invite messages are hidden by default. Click to show the message.": "Los mensajes de invitación no se muestran por defecto. Haz clic para mostrarlo.", + "You can select all or individual messages to retry or delete": "Puedes seleccionar uno o todos los mensajes para reintentar o eliminar", + "Sending": "Enviando", + "Retry all": "Reintentar todo", + "Delete all": "Borrar todo", + "Some of your messages have not been sent": "Algunos de tus mensajes no se han enviado", + "You are the only person here. If you leave, no one will be able to join in the future, including you.": "Eres la única persona aquí. Si te vas, no podrá unirse nadie en el futuro, incluyéndote a ti.", + "Forgotten or lost all recovery methods? Reset all": "¿Has olvidado o perdido todos los métodos de recuperación? Restablecer todo", + "If you reset everything, you will restart with no trusted sessions, no trusted users, and might not be able to see past messages.": "Si restableces todo, volverás a empezar sin sesiones ni usuarios de confianza, y puede que no puedas ver mensajes anteriores.", + "Only do this if you have no other device to complete verification with.": "Solo haz esto si no tienes ningún otro dispositivo con el que completar la verificación.", + "Reset everything": "Restablecer todo", + "If you do, please note that none of your messages will be deleted, but the search experience might be degraded for a few moments whilst the index is recreated": "Si lo haces, ten en cuenta que ninguno de tus mensajes serán eliminados, pero la experiencia de búsqueda será peor durante unos momentos mientras recreamos el índice", + "View message": "Ver mensaje", + "Zoom in": "Acercar", + "Zoom out": "Alejar", + "%(count)s members including %(commaSeparatedMembers)s|one": "%(commaSeparatedMembers)s", + "%(count)s members including %(commaSeparatedMembers)s|other": "%(count)s miembros, incluyendo a %(commaSeparatedMembers)s", + "Including %(commaSeparatedMembers)s": "Incluyendo %(commaSeparatedMembers)s", + "View all %(count)s members|one": "Ver 1 miembro", + "View all %(count)s members|other": "Ver los %(count)s miembros", + "%(seconds)ss left": "%(seconds)ss restantes", + "Failed to send": "No se ha podido mandar", + "Change server ACLs": "Cambiar los ACLs del servidor", + "Show options to enable 'Do not disturb' mode": "Mostrar opciones para activar el modo «no molestar»" } From 31596167d4f5a046b1ffca0e8564139e9666c4ea Mon Sep 17 00:00:00 2001 From: LinAGKar Date: Sun, 2 May 2021 10:18:19 +0000 Subject: [PATCH 0176/1449] Translated using Weblate (Swedish) Currently translated at 100.0% (2924 of 2924 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/sv/ --- src/i18n/strings/sv.json | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/sv.json b/src/i18n/strings/sv.json index 63db2ccee2..64cd8ae6ac 100644 --- a/src/i18n/strings/sv.json +++ b/src/i18n/strings/sv.json @@ -3231,5 +3231,13 @@ "Show options to enable 'Do not disturb' mode": "Visa alternativ för att aktivera 'Stör ej'-läget", "Delete all": "Radera alla", "View all %(count)s members|one": "Visa 1 medlem", - "View all %(count)s members|other": "Visa alla %(count)s medlemmar" + "View all %(count)s members|other": "Visa alla %(count)s medlemmar", + "You can select all or individual messages to retry or delete": "Du kan välja alla eller individuella meddelanden att försöka igen eller radera", + "Sending": "Skickar", + "Retry all": "Försök alla igen", + "Some of your messages have not been sent": "Vissa av dina meddelanden har inte skickats", + "%(count)s members including %(commaSeparatedMembers)s|one": "%(commaSeparatedMembers)s", + "%(count)s members including %(commaSeparatedMembers)s|other": "%(count)s medlemmar inklusive %(commaSeparatedMembers)s", + "Including %(commaSeparatedMembers)s": "Inklusive %(commaSeparatedMembers)s", + "Failed to send": "Misslyckades att skicka" } From 6127281c11a0863539268d099577ff46eee7e80f Mon Sep 17 00:00:00 2001 From: Sven Grewe Date: Sat, 1 May 2021 13:53:23 +0000 Subject: [PATCH 0177/1449] Translated using Weblate (German) Currently translated at 99.3% (2904 of 2924 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 7a9c518193..2bb593f09c 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -2028,7 +2028,7 @@ "Doesn't look like a valid email address": "Das sieht nicht nach einer gültigen E-Mail-Adresse aus", "Enter phone number (required on this homeserver)": "Telefonnummer eingeben (auf diesem Heimserver erforderlich)", "Doesn't look like a valid phone number": "Das sieht nicht nach einer gültigen Telefonnummer aus", - "Sign in with SSO": "Mit Single Sign-On anmelden", + "Sign in with SSO": "Einmalanmeldung verwenden", "Welcome to %(appName)s": "Willkommen bei %(appName)s", "Send a Direct Message": "Direktnachricht senden", "Create a Group Chat": "Gruppenchat erstellen", @@ -2178,7 +2178,7 @@ "Waiting for your other session to verify…": "Warte auf die Verifikation deiner anderen Sitzungen…", "You've successfully verified your device!": "Du hast dein Gerät erfolgreich verifiziert!", "QR Code": "QR-Code", - "To continue, use Single Sign On to prove your identity.": "Zum Fortfahren nutze Single Sign-On, um deine Identität zu bestätigen.", + "To continue, use Single Sign On to prove your identity.": "Zum Fortfahren nutze die Einmalanmeldung um deine Identität zu bestätigen.", "Confirm to continue": "Bestätige um fortzufahren", "Click the button below to confirm your identity.": "Klicke den Button unten um deine Identität zu bestätigen.", "Confirm encryption setup": "Bestätige die Einrichtung der Verschlüsselung", From adcdd72a0838e1eddd736cbafb0cb1883cfdf1bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 3 May 2021 15:07:25 +0200 Subject: [PATCH 0178/1449] preventDefault() and stopPropagation() only if moving MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/CallPreview.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/voip/CallPreview.tsx b/src/components/views/voip/CallPreview.tsx index aa2e71339e..3b7a297841 100644 --- a/src/components/views/voip/CallPreview.tsx +++ b/src/components/views/voip/CallPreview.tsx @@ -199,11 +199,11 @@ export default class CallPreview extends React.Component { } private onMoving = (event: React.MouseEvent | MouseEvent) => { + if (!this.state.moving) return; + event.preventDefault(); event.stopPropagation(); - if (!this.state.moving) return; - this.lastX = event.pageX - this.initX; this.lastY = event.pageY - this.initY; From 0851cf4415f3dd04502326909cee1b6400ea73ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 3 May 2021 15:16:08 +0200 Subject: [PATCH 0179/1449] Simplifie things MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/CallPreview.tsx | 6 +----- src/components/views/voip/CallView.tsx | 9 +++------ 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/components/views/voip/CallPreview.tsx b/src/components/views/voip/CallPreview.tsx index 3b7a297841..153258d2c8 100644 --- a/src/components/views/voip/CallPreview.tsx +++ b/src/components/views/voip/CallPreview.tsx @@ -232,11 +232,7 @@ export default class CallPreview extends React.Component { call={this.state.primaryCall} secondaryCall={this.state.secondaryCall} pipMode={true} - dragCallbacks={{ - onStartMoving: this.onStartMoving, - onMoving: this.onMoving, - onEndMoving: this.onEndMoving, - }} + onMouseDownOnHeader={this.onStartMoving} />
    ); diff --git a/src/components/views/voip/CallView.tsx b/src/components/views/voip/CallView.tsx index 1f555e5227..e8d3666c53 100644 --- a/src/components/views/voip/CallView.tsx +++ b/src/components/views/voip/CallView.tsx @@ -50,11 +50,8 @@ interface IProps { // need to control those things separately, so this is simpler. pipMode?: boolean; - // Callbacks for dragging the CallView in PIP mode - dragCallbacks?: { - onStartMoving: (event: React.MouseEvent) => void; - onEndMoving: () => void; - } + // Used for dragging the PiP CallView + onMouseDownOnHeader?: (event: React.MouseEvent) => void; } interface IState { @@ -625,7 +622,7 @@ export default class CallView extends React.Component { header = (
    From b8cb72345ccbe115ba3bdb861467ee139ecff20d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 3 May 2021 15:39:00 +0200 Subject: [PATCH 0180/1449] Remove unnecessary margin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/voip/_CallView.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/res/css/views/voip/_CallView.scss b/res/css/views/voip/_CallView.scss index 7292e325df..18e7c215cb 100644 --- a/res/css/views/voip/_CallView.scss +++ b/res/css/views/voip/_CallView.scss @@ -39,7 +39,6 @@ limitations under the License. .mx_CallView_pip { width: 320px; padding-bottom: 8px; - margin-top: 10px; background-color: $voipcall-plinth-color; box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.20); border-radius: 8px; From fe5fb1885fc95243a9964942877268f7e6eef993 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 3 May 2021 15:39:24 +0200 Subject: [PATCH 0181/1449] Add styling for CallPreview and make it fixed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/voip/_CallPreview.scss | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 res/css/views/voip/_CallPreview.scss diff --git a/res/css/views/voip/_CallPreview.scss b/res/css/views/voip/_CallPreview.scss new file mode 100644 index 0000000000..92348fb465 --- /dev/null +++ b/res/css/views/voip/_CallPreview.scss @@ -0,0 +1,21 @@ +/* +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. +*/ + +.mx_CallPreview { + position: fixed; + left: 0; + top: 0; +} From 7faf9eb4ccd56dfe9ab308964471a5ff099c805b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 3 May 2021 15:39:37 +0200 Subject: [PATCH 0182/1449] Use styling for CallPreview MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/_components.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/res/css/_components.scss b/res/css/_components.scss index 0057f8a8fc..c476e577df 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -254,6 +254,7 @@ @import "./views/voip/_CallContainer.scss"; @import "./views/voip/_CallView.scss"; @import "./views/voip/_CallViewForRoom.scss"; +@import "./views/voip/_CallPreview.scss"; @import "./views/voip/_DialPad.scss"; @import "./views/voip/_DialPadContextMenu.scss"; @import "./views/voip/_DialPadModal.scss"; From 76f503666c5e7594751302a5a5fabc9babc8a64e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 3 May 2021 15:40:12 +0200 Subject: [PATCH 0183/1449] Add default offset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/CallPreview.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/components/views/voip/CallPreview.tsx b/src/components/views/voip/CallPreview.tsx index 153258d2c8..74e1815631 100644 --- a/src/components/views/voip/CallPreview.tsx +++ b/src/components/views/voip/CallPreview.tsx @@ -29,6 +29,9 @@ import { MatrixClientPeg } from '../../../MatrixClientPeg'; import {replaceableComponent} from "../../../utils/replaceableComponent"; import { Action } from '../../../dispatcher/actions'; +const DEFAULT_X_OFFSET = 64; +const DEFAULT_Y_OFFSET = 64; + const SHOW_CALL_IN_STATES = [ CallState.Connected, CallState.InviteSent, @@ -113,16 +116,16 @@ export default class CallPreview extends React.Component { roomId, primaryCall: primaryCall, secondaryCall: secondaryCalls[0], - translationX: 0, - translationY: 0, + translationX: DEFAULT_X_OFFSET, + translationY: DEFAULT_Y_OFFSET, moving: false, }; } private initX = 0; private initY = 0; - private lastX = 0; - private lastY = 0; + private lastX = DEFAULT_X_OFFSET; + private lastY = DEFAULT_Y_OFFSET; public componentDidMount() { this.roomStoreToken = RoomViewStore.addListener(this.onRoomViewStoreUpdate); From 2c9231641b57ea7d5fa577c9aa9445347360665f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 3 May 2021 15:40:59 +0200 Subject: [PATCH 0184/1449] Add ref to callViewWrapper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/CallPreview.tsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/components/views/voip/CallPreview.tsx b/src/components/views/voip/CallPreview.tsx index 74e1815631..4a0ccc93b9 100644 --- a/src/components/views/voip/CallPreview.tsx +++ b/src/components/views/voip/CallPreview.tsx @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React from 'react'; +import React, { createRef } from 'react'; import CallView from "./CallView"; import RoomViewStore from '../../../stores/RoomViewStore'; @@ -122,6 +122,8 @@ export default class CallPreview extends React.Component { }; } + private callViewWrapper = createRef(); + private initX = 0; private initY = 0; private lastX = DEFAULT_X_OFFSET; @@ -230,7 +232,11 @@ export default class CallPreview extends React.Component { }; return ( -
    +
    Date: Mon, 3 May 2021 15:43:13 +0200 Subject: [PATCH 0185/1449] Add semicolons to event listeners MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/CallPreview.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/views/voip/CallPreview.tsx b/src/components/views/voip/CallPreview.tsx index 4a0ccc93b9..366b0d30b3 100644 --- a/src/components/views/voip/CallPreview.tsx +++ b/src/components/views/voip/CallPreview.tsx @@ -191,7 +191,7 @@ export default class CallPreview extends React.Component { primaryCall: primaryCall, secondaryCall: secondaryCalls[0], }); - } + }; private onStartMoving = (event: React.MouseEvent) => { event.preventDefault(); @@ -201,7 +201,7 @@ export default class CallPreview extends React.Component { this.initX = event.pageX - this.lastX; this.initY = event.pageY - this.lastY; - } + }; private onMoving = (event: React.MouseEvent | MouseEvent) => { if (!this.state.moving) return; @@ -216,11 +216,11 @@ export default class CallPreview extends React.Component { translationX: this.lastX, translationY: this.lastY, }); - } + }; private onEndMoving = () => { this.setState({moving: false}); - } + }; public render() { if (this.state.primaryCall) { From d8d380c74de6ff27d9e0b6c764e1db35b583119e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 3 May 2021 17:22:45 +0200 Subject: [PATCH 0186/1449] Always keep the PiP CallView on the screen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/CallPreview.tsx | 25 +++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/components/views/voip/CallPreview.tsx b/src/components/views/voip/CallPreview.tsx index 366b0d30b3..74d43dcb19 100644 --- a/src/components/views/voip/CallPreview.tsx +++ b/src/components/views/voip/CallPreview.tsx @@ -209,8 +209,29 @@ export default class CallPreview extends React.Component { event.preventDefault(); event.stopPropagation(); - this.lastX = event.pageX - this.initX; - this.lastY = event.pageY - this.initY; + const width = this.callViewWrapper.current.clientWidth; + const height = this.callViewWrapper.current.clientHeight; + + const precalculatedLastX = event.pageX - this.initX; + const precalculatedLastY = event.pageY - this.initY; + + // Avoid overflow on the x axis + if (precalculatedLastX + width >= window.innerWidth) { + this.lastX = window.innerWidth - width; + } else if (precalculatedLastX <= 0) { + this.lastX = 0; + } else { + this.lastX = precalculatedLastX; + } + + // Avoid overflow on the y axis + if (precalculatedLastY + height >= window.innerHeight) { + this.lastY = window.innerHeight - height; + } else if (precalculatedLastY <= 0) { + this.lastY = 0; + } else { + this.lastY = precalculatedLastY; + } this.setState({ translationX: this.lastX, From be2da6376e1c5b3a6be2c23a3bfbe89766e5bbc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 3 May 2021 17:49:55 +0200 Subject: [PATCH 0187/1449] Simplifie translation code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/CallPreview.tsx | 25 ++++++++++++----------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/components/views/voip/CallPreview.tsx b/src/components/views/voip/CallPreview.tsx index 74d43dcb19..9a9ebd5e92 100644 --- a/src/components/views/voip/CallPreview.tsx +++ b/src/components/views/voip/CallPreview.tsx @@ -126,8 +126,6 @@ export default class CallPreview extends React.Component { private initX = 0; private initY = 0; - private lastX = DEFAULT_X_OFFSET; - private lastY = DEFAULT_Y_OFFSET; public componentDidMount() { this.roomStoreToken = RoomViewStore.addListener(this.onRoomViewStoreUpdate); @@ -199,8 +197,8 @@ export default class CallPreview extends React.Component { this.setState({moving: true}); - this.initX = event.pageX - this.lastX; - this.initY = event.pageY - this.lastY; + this.initX = event.pageX - this.state.translationX; + this.initY = event.pageY - this.state.translationY; }; private onMoving = (event: React.MouseEvent | MouseEvent) => { @@ -215,27 +213,30 @@ export default class CallPreview extends React.Component { const precalculatedLastX = event.pageX - this.initX; const precalculatedLastY = event.pageY - this.initY; + let translationX; + let translationY; + // Avoid overflow on the x axis if (precalculatedLastX + width >= window.innerWidth) { - this.lastX = window.innerWidth - width; + translationX = window.innerWidth - width; } else if (precalculatedLastX <= 0) { - this.lastX = 0; + translationX = 0; } else { - this.lastX = precalculatedLastX; + translationX = precalculatedLastX; } // Avoid overflow on the y axis if (precalculatedLastY + height >= window.innerHeight) { - this.lastY = window.innerHeight - height; + translationY = window.innerHeight - height; } else if (precalculatedLastY <= 0) { - this.lastY = 0; + translationY = 0; } else { - this.lastY = precalculatedLastY; + translationY = precalculatedLastY; } this.setState({ - translationX: this.lastX, - translationY: this.lastY, + translationX: translationX, + translationY: translationY, }); }; From 0bf2b01f84ec490ca48b8d07172202dab7907dcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 3 May 2021 18:11:02 +0200 Subject: [PATCH 0188/1449] Keep PiP in the window when resizing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/CallPreview.tsx | 41 ++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/src/components/views/voip/CallPreview.tsx b/src/components/views/voip/CallPreview.tsx index 9a9ebd5e92..410b60dcb6 100644 --- a/src/components/views/voip/CallPreview.tsx +++ b/src/components/views/voip/CallPreview.tsx @@ -29,6 +29,9 @@ import { MatrixClientPeg } from '../../../MatrixClientPeg'; import {replaceableComponent} from "../../../utils/replaceableComponent"; import { Action } from '../../../dispatcher/actions'; +const PIP_VIEW_WIDTH = 320; +const PIP_VIEW_HEIGHT = 180; + const DEFAULT_X_OFFSET = 64; const DEFAULT_Y_OFFSET = 64; @@ -116,7 +119,7 @@ export default class CallPreview extends React.Component { roomId, primaryCall: primaryCall, secondaryCall: secondaryCalls[0], - translationX: DEFAULT_X_OFFSET, + translationX: window.innerWidth - DEFAULT_X_OFFSET - PIP_VIEW_WIDTH, translationY: DEFAULT_Y_OFFSET, moving: false, }; @@ -131,6 +134,7 @@ export default class CallPreview extends React.Component { this.roomStoreToken = RoomViewStore.addListener(this.onRoomViewStoreUpdate); document.addEventListener("mousemove", this.onMoving); document.addEventListener("mouseup", this.onEndMoving); + window.addEventListener("resize", this.onWindowSizeChanged); this.dispatcherRef = dis.register(this.onAction); MatrixClientPeg.get().on(CallEvent.RemoteHoldUnhold, this.onCallRemoteHold); } @@ -139,6 +143,7 @@ export default class CallPreview extends React.Component { MatrixClientPeg.get().removeListener(CallEvent.RemoteHoldUnhold, this.onCallRemoteHold); document.removeEventListener("mousemove", this.onMoving); document.removeEventListener("mouseup", this.onEndMoving); + window.removeEventListener("resize", this.onWindowSizeChanged); if (this.roomStoreToken) { this.roomStoreToken.remove(); } @@ -146,6 +151,40 @@ export default class CallPreview extends React.Component { SettingsStore.unwatchSetting(this.settingsWatcherRef); } + private onWindowSizeChanged = () => { + const width = this.callViewWrapper.current.clientWidth || PIP_VIEW_WIDTH; + const height = this.callViewWrapper.current.clientHeight || PIP_VIEW_HEIGHT; + + const precalculatedLastX = this.state.translationX; + const precalculatedLastY = this.state.translationY; + + let translationX; + let translationY; + + // Avoid overflow on the x axis + if (precalculatedLastX + width >= window.innerWidth) { + translationX = window.innerWidth - width; + } else if (precalculatedLastX <= 0) { + translationX = 0; + } else { + translationX = precalculatedLastX; + } + + // Avoid overflow on the y axis + if (precalculatedLastY + height >= window.innerHeight) { + translationY = window.innerHeight - height; + } else if (precalculatedLastY <= 0) { + translationY = 0; + } else { + translationY = precalculatedLastY; + } + + this.setState({ + translationX: translationX, + translationY: translationY, + }); + } + private onRoomViewStoreUpdate = (payload) => { if (RoomViewStore.getRoomId() === this.state.roomId) return; From 941a6e1c1bb48f2214638768f17018f4f0b4e77f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 3 May 2021 18:16:36 +0200 Subject: [PATCH 0189/1449] Don't duplicate code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/CallPreview.tsx | 67 +++++++---------------- 1 file changed, 19 insertions(+), 48 deletions(-) diff --git a/src/components/views/voip/CallPreview.tsx b/src/components/views/voip/CallPreview.tsx index 410b60dcb6..9ab2b9441a 100644 --- a/src/components/views/voip/CallPreview.tsx +++ b/src/components/views/voip/CallPreview.tsx @@ -152,36 +152,37 @@ export default class CallPreview extends React.Component { } private onWindowSizeChanged = () => { + this.setTranslation(this.state.translationX, this.state.translationY); + } + + private setTranslation(inTranslationX: number, inTranslationY: number) { const width = this.callViewWrapper.current.clientWidth || PIP_VIEW_WIDTH; const height = this.callViewWrapper.current.clientHeight || PIP_VIEW_HEIGHT; - const precalculatedLastX = this.state.translationX; - const precalculatedLastY = this.state.translationY; - - let translationX; - let translationY; + let outTranslationX; + let outTranslationY; // Avoid overflow on the x axis - if (precalculatedLastX + width >= window.innerWidth) { - translationX = window.innerWidth - width; - } else if (precalculatedLastX <= 0) { - translationX = 0; + if (inTranslationX + width >= window.innerWidth) { + outTranslationX = window.innerWidth - width; + } else if (inTranslationX <= 0) { + outTranslationX = 0; } else { - translationX = precalculatedLastX; + outTranslationX = inTranslationX; } // Avoid overflow on the y axis - if (precalculatedLastY + height >= window.innerHeight) { - translationY = window.innerHeight - height; - } else if (precalculatedLastY <= 0) { - translationY = 0; + if (inTranslationY + height >= window.innerHeight) { + outTranslationY = window.innerHeight - height; + } else if (inTranslationY <= 0) { + outTranslationY = 0; } else { - translationY = precalculatedLastY; + outTranslationY = inTranslationY; } this.setState({ - translationX: translationX, - translationY: translationY, + translationX: outTranslationX, + translationY: outTranslationY, }); } @@ -246,37 +247,7 @@ export default class CallPreview extends React.Component { event.preventDefault(); event.stopPropagation(); - const width = this.callViewWrapper.current.clientWidth; - const height = this.callViewWrapper.current.clientHeight; - - const precalculatedLastX = event.pageX - this.initX; - const precalculatedLastY = event.pageY - this.initY; - - let translationX; - let translationY; - - // Avoid overflow on the x axis - if (precalculatedLastX + width >= window.innerWidth) { - translationX = window.innerWidth - width; - } else if (precalculatedLastX <= 0) { - translationX = 0; - } else { - translationX = precalculatedLastX; - } - - // Avoid overflow on the y axis - if (precalculatedLastY + height >= window.innerHeight) { - translationY = window.innerHeight - height; - } else if (precalculatedLastY <= 0) { - translationY = 0; - } else { - translationY = precalculatedLastY; - } - - this.setState({ - translationX: translationX, - translationY: translationY, - }); + this.setTranslation(event.pageX - this.initX, event.pageY - this.initY); }; private onEndMoving = () => { From d7ed2d3486718d83ea42555946177ed7f3e3ab52 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 3 May 2021 10:27:15 -0600 Subject: [PATCH 0190/1449] Switch to m.audio with extensible events --- src/components/views/rooms/VoiceRecordComposerTile.tsx | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/components/views/rooms/VoiceRecordComposerTile.tsx b/src/components/views/rooms/VoiceRecordComposerTile.tsx index bab95291ba..981c1499ab 100644 --- a/src/components/views/rooms/VoiceRecordComposerTile.tsx +++ b/src/components/views/rooms/VoiceRecordComposerTile.tsx @@ -27,6 +27,7 @@ import LiveRecordingClock from "../voice_messages/LiveRecordingClock"; import {VoiceRecordingStore} from "../../../stores/VoiceRecordingStore"; import {UPDATE_EVENT} from "../../../stores/AsyncStore"; import RecordingPlayback from "../voice_messages/RecordingPlayback"; +import {MsgType} from "matrix-js-sdk/lib/@types/event"; interface IProps { room: Room; @@ -64,8 +65,8 @@ export default class VoiceRecordComposerTile extends React.PureComponent Math.round(v * 1024)), }, + "org.matrix.msc2516.voice": {}, // No content, this is a rendering hint }); await this.disposeRecording(); } From 889b90fbc3cd564f6c6717d365f37e5fc21c2f79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 3 May 2021 18:33:24 +0200 Subject: [PATCH 0191/1449] Fix const values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/CallPreview.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/views/voip/CallPreview.tsx b/src/components/views/voip/CallPreview.tsx index 9ab2b9441a..b3e66f09b3 100644 --- a/src/components/views/voip/CallPreview.tsx +++ b/src/components/views/voip/CallPreview.tsx @@ -29,11 +29,11 @@ import { MatrixClientPeg } from '../../../MatrixClientPeg'; import {replaceableComponent} from "../../../utils/replaceableComponent"; import { Action } from '../../../dispatcher/actions'; -const PIP_VIEW_WIDTH = 320; -const PIP_VIEW_HEIGHT = 180; +const PIP_VIEW_WIDTH = 336; +const PIP_VIEW_HEIGHT = 232; -const DEFAULT_X_OFFSET = 64; -const DEFAULT_Y_OFFSET = 64; +const DEFAULT_X_OFFSET = 16; +const DEFAULT_Y_OFFSET = 48; const SHOW_CALL_IN_STATES = [ CallState.Connected, From f79339c2dadd86bac266c7f0eab7e3eb0317b479 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 3 May 2021 18:36:11 +0200 Subject: [PATCH 0192/1449] Add missing semicolon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/CallPreview.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/voip/CallPreview.tsx b/src/components/views/voip/CallPreview.tsx index b3e66f09b3..60153732d8 100644 --- a/src/components/views/voip/CallPreview.tsx +++ b/src/components/views/voip/CallPreview.tsx @@ -153,7 +153,7 @@ export default class CallPreview extends React.Component { private onWindowSizeChanged = () => { this.setTranslation(this.state.translationX, this.state.translationY); - } + }; private setTranslation(inTranslationX: number, inTranslationY: number) { const width = this.callViewWrapper.current.clientWidth || PIP_VIEW_WIDTH; From 3f4ee9742abe9543a44ee3caa1dba31e6fb6e475 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 3 May 2021 11:41:14 -0600 Subject: [PATCH 0193/1449] Simple rendering of voice messages in the timeline Fixes https://github.com/vector-im/element-web/issues/17138 --- res/css/_components.scss | 1 + .../views/messages/_MVoiceMessageBody.scss | 19 ++++ .../views/messages/MVoiceMessageBody.tsx | 106 ++++++++++++++++++ .../views/messages/MVoiceOrAudioBody.tsx | 39 +++++++ src/components/views/messages/MessageEvent.js | 6 +- src/i18n/strings/en_EN.json | 1 + src/voice/Playback.ts | 2 +- 7 files changed, 168 insertions(+), 6 deletions(-) create mode 100644 res/css/views/messages/_MVoiceMessageBody.scss create mode 100644 src/components/views/messages/MVoiceMessageBody.tsx create mode 100644 src/components/views/messages/MVoiceOrAudioBody.tsx diff --git a/res/css/_components.scss b/res/css/_components.scss index 0057f8a8fc..ec9592f3a1 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -161,6 +161,7 @@ @import "./views/messages/_MStickerBody.scss"; @import "./views/messages/_MTextBody.scss"; @import "./views/messages/_MVideoBody.scss"; +@import "./views/messages/_MVoiceMessageBody.scss"; @import "./views/messages/_MessageActionBar.scss"; @import "./views/messages/_MessageTimestamp.scss"; @import "./views/messages/_MjolnirBody.scss"; diff --git a/res/css/views/messages/_MVoiceMessageBody.scss b/res/css/views/messages/_MVoiceMessageBody.scss new file mode 100644 index 0000000000..3dfb98f778 --- /dev/null +++ b/res/css/views/messages/_MVoiceMessageBody.scss @@ -0,0 +1,19 @@ +/* +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. +*/ + +.mx_MVoiceMessageBody { + display: inline-block; // makes the playback controls magically line up +} diff --git a/src/components/views/messages/MVoiceMessageBody.tsx b/src/components/views/messages/MVoiceMessageBody.tsx new file mode 100644 index 0000000000..4a2a83465d --- /dev/null +++ b/src/components/views/messages/MVoiceMessageBody.tsx @@ -0,0 +1,106 @@ +/* +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 React from "react"; +import {MatrixEvent} from "matrix-js-sdk/src/models/event"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; +import {Playback} from "../../../voice/Playback"; +import MFileBody from "./MFileBody"; +import InlineSpinner from '../elements/InlineSpinner'; +import {_t} from "../../../languageHandler"; +import {mediaFromContent} from "../../../customisations/Media"; +import {decryptFile} from "../../../utils/DecryptFile"; +import RecordingPlayback from "../voice_messages/RecordingPlayback"; + +interface IProps { + mxEvent: MatrixEvent; +} + +interface IState { + error?: Error; + playback?: Playback; + decryptedBlob?: Blob; +} + +@replaceableComponent("views.messages.MVoiceMessageBody") +export default class MVoiceMessageBody extends React.PureComponent { + constructor(props: IProps) { + super(props); + + this.state = {}; + } + + public async componentDidMount() { + let buffer: ArrayBuffer; + const content = this.props.mxEvent.getContent(); + const media = mediaFromContent(content); + if (media.isEncrypted) { + try { + const blob = await decryptFile(content.file); + buffer = await blob.arrayBuffer(); + this.setState({decryptedBlob: blob}); + } catch (e) { + this.setState({error: e}); + console.warn("Unable to decrypt voice message", e); + return; // stop processing the audio file + } + } else { + try { + buffer = await media.downloadSource().then(r => r.blob()).then(r => r.arrayBuffer()); + } catch (e) { + this.setState({error: e}); + console.warn("Unable to download voice message", e); + return; // stop processing the audio file + } + } + + const waveform = content?.["org.matrix.msc1767.audio"]?.waveform?.map(p => p / 1024); + + // We should have a buffer to work with now: let's set it up + const playback = new Playback(buffer, waveform); + this.setState({playback}); + // Note: the RecordingPlayback component will handle preparing the Playback class for us. + } + + public render() { + if (this.state.error) { + // TODO: @@TR: Verify error state + return ( + + + { _t("Error processing voice message") } + + ); + } + + if (!this.state.playback) { + // TODO: @@TR: Verify loading/decrypting state + return ( + + + + ); + } + + // At this point we should have a playable state + return ( + + + + + ) + } +} diff --git a/src/components/views/messages/MVoiceOrAudioBody.tsx b/src/components/views/messages/MVoiceOrAudioBody.tsx new file mode 100644 index 0000000000..0cebcf3440 --- /dev/null +++ b/src/components/views/messages/MVoiceOrAudioBody.tsx @@ -0,0 +1,39 @@ +/* +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 React from "react"; +import {MatrixEvent} from "matrix-js-sdk/src/models/event"; +import MAudioBody from "./MAudioBody"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; +import SettingsStore from "../../../settings/SettingsStore"; +import MVoiceMessageBody from "./MVoiceMessageBody"; + +interface IProps { + mxEvent: MatrixEvent; +} + +@replaceableComponent("views.messages.MVoiceOrAudioBody") +export default class MVoiceOrAudioBody extends React.PureComponent { + public render() { + const isVoiceMessage = !!this.props.mxEvent.getContent()['org.matrix.msc2516.voice']; + const voiceMessagesEnabled = SettingsStore.getValue("feature_voice_messages"); + if (isVoiceMessage && voiceMessagesEnabled) { + return ; + } else { + return ; + } + } +} diff --git a/src/components/views/messages/MessageEvent.js b/src/components/views/messages/MessageEvent.js index 60f7631c8e..78e0dc422d 100644 --- a/src/components/views/messages/MessageEvent.js +++ b/src/components/views/messages/MessageEvent.js @@ -72,12 +72,8 @@ export default class MessageEvent extends React.Component { 'm.emote': sdk.getComponent('messages.TextualBody'), 'm.image': sdk.getComponent('messages.MImageBody'), 'm.file': sdk.getComponent('messages.MFileBody'), - 'm.audio': sdk.getComponent('messages.MAudioBody'), + 'm.audio': sdk.getComponent('messages.MVoiceOrAudioBody'), 'm.video': sdk.getComponent('messages.MVideoBody'), - - // TODO: @@ TravisR: Use labs flag determination. - // MSC: https://github.com/matrix-org/matrix-doc/pull/2516 - 'org.matrix.msc2516.voice': sdk.getComponent('messages.MAudioBody'), }; const evTypes = { 'm.sticker': sdk.getComponent('messages.MStickerBody'), diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 5863f2a834..312e98e6d1 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1848,6 +1848,7 @@ "%(name)s wants to verify": "%(name)s wants to verify", "You sent a verification request": "You sent a verification request", "Error decrypting video": "Error decrypting video", + "Error processing voice message": "Error processing voice message", "Show all": "Show all", "Reactions": "Reactions", " reacted with %(content)s": " reacted with %(content)s", diff --git a/src/voice/Playback.ts b/src/voice/Playback.ts index 99b1f62866..49a80a35d1 100644 --- a/src/voice/Playback.ts +++ b/src/voice/Playback.ts @@ -49,7 +49,7 @@ export class Playback extends EventEmitter implements IDestroyable { constructor(private buf: ArrayBuffer, seedWaveform = DEFAULT_WAVEFORM) { super(); this.context = new AudioContext(); - this.resampledWaveform = arrayFastResample(seedWaveform, PLAYBACK_WAVEFORM_SAMPLES); + this.resampledWaveform = arrayFastResample(seedWaveform ?? DEFAULT_WAVEFORM, PLAYBACK_WAVEFORM_SAMPLES); this.waveformObservable.update(this.resampledWaveform); this.clock = new PlaybackClock(this.context); From 8abd251ec56f229137cda107da5759ea74fc3927 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 3 May 2021 11:43:46 -0600 Subject: [PATCH 0194/1449] delib --- src/components/views/rooms/VoiceRecordComposerTile.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/VoiceRecordComposerTile.tsx b/src/components/views/rooms/VoiceRecordComposerTile.tsx index 981c1499ab..f0acc4fb09 100644 --- a/src/components/views/rooms/VoiceRecordComposerTile.tsx +++ b/src/components/views/rooms/VoiceRecordComposerTile.tsx @@ -27,7 +27,7 @@ import LiveRecordingClock from "../voice_messages/LiveRecordingClock"; import {VoiceRecordingStore} from "../../../stores/VoiceRecordingStore"; import {UPDATE_EVENT} from "../../../stores/AsyncStore"; import RecordingPlayback from "../voice_messages/RecordingPlayback"; -import {MsgType} from "matrix-js-sdk/lib/@types/event"; +import {MsgType} from "matrix-js-sdk/src/@types/event"; interface IProps { room: Room; From 54e139a6adc7604411f041912ec5b97fb4903dba Mon Sep 17 00:00:00 2001 From: Jaiwanth Date: Mon, 3 May 2021 22:02:33 +0530 Subject: [PATCH 0195/1449] Generate previews when the room tile is maximised --- src/components/structures/LeftPanel.tsx | 2 +- src/components/views/rooms/RoomList.tsx | 1 + src/components/views/rooms/RoomSublist.tsx | 4 +++- src/components/views/rooms/RoomTile.tsx | 16 +++++++++++++++- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/components/structures/LeftPanel.tsx b/src/components/structures/LeftPanel.tsx index 44b404bd3a..7f9ef7516e 100644 --- a/src/components/structures/LeftPanel.tsx +++ b/src/components/structures/LeftPanel.tsx @@ -416,7 +416,7 @@ export default class LeftPanel extends React.Component { const roomList = { onResize={this.props.onResize} showSkeleton={showSkeleton} extraTiles={extraTiles} + resizeNotifier={this.props.resizeNotifier} alwaysVisible={ALWAYS_VISIBLE_TAGS.includes(orderedTagId)} /> }); diff --git a/src/components/views/rooms/RoomSublist.tsx b/src/components/views/rooms/RoomSublist.tsx index fb367349a2..dd80e9d40a 100644 --- a/src/components/views/rooms/RoomSublist.tsx +++ b/src/components/views/rooms/RoomSublist.tsx @@ -44,6 +44,7 @@ import { ActionPayload } from "../../../dispatcher/payloads"; import { Enable, Resizable } from "re-resizable"; import { Direction } from "re-resizable/lib/resizer"; import { polyfillTouchEvent } from "../../../@types/polyfill"; +import { ResizeNotifier } from "../../../utils/ResizeNotifier"; import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNotificationStateStore"; import RoomListLayoutStore from "../../../stores/room-list/RoomListLayoutStore"; import { arrayFastClone, arrayHasOrderChange } from "../../../utils/arrays"; @@ -75,7 +76,7 @@ interface IProps { onResize: () => void; showSkeleton?: boolean; alwaysVisible?: boolean; - + resizeNotifier: ResizeNotifier; extraTiles?: ReactComponentElement[]; // TODO: Account for https://github.com/vector-im/element-web/issues/14179 @@ -528,6 +529,7 @@ export default class RoomSublist extends React.Component { tiles.push(; @@ -102,6 +104,9 @@ export default class RoomTile extends React.PureComponent { }; this.notificationState = RoomNotificationStateStore.instance.getRoomState(this.props.room); this.roomProps = EchoChamber.forRoom(this.props.room); + if (this.props.resizeNotifier) { + this.props.resizeNotifier.on("middlePanelResizedNoisy", this.onResize); + } } private countUnsentEvents(): number { @@ -116,6 +121,12 @@ export default class RoomTile extends React.PureComponent { this.forceUpdate(); // notification state changed - update }; + private onResize = () => { + if (this.showMessagePreview && !this.state.messagePreview) { + this.setState({messagePreview: this.generatePreview()}); + } + }; + private onLocalEchoUpdated = (ev: MatrixEvent, room: Room) => { if (!room?.roomId === this.props.room.roomId) return; this.setState({hasUnsentEvents: this.countUnsentEvents() > 0}); @@ -131,7 +142,7 @@ export default class RoomTile extends React.PureComponent { } private get showMessagePreview(): boolean { - return this.props.showMessagePreview; + return !this.props.isMinimized && this.props.showMessagePreview; } public componentDidUpdate(prevProps: Readonly, prevState: Readonly) { @@ -195,6 +206,9 @@ export default class RoomTile extends React.PureComponent { ); this.props.room.off("Room.name", this.onRoomNameUpdate); } + if (this.props.resizeNotifier) { + this.props.resizeNotifier.off("middlePanelResizedNoisy", this.onResize); + } ActiveRoomObserver.removeListener(this.props.room.roomId, this.onActiveRoomUpdate); defaultDispatcher.unregister(this.dispatcherRef); this.notificationState.off(NOTIFICATION_STATE_UPDATE, this.onNotificationUpdate); From 9755da6f0915c8a3dec9726c33f60f4468f88037 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Mon, 3 May 2021 19:59:51 +0200 Subject: [PATCH 0196/1449] Add ? MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/voip/CallPreview.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/voip/CallPreview.tsx b/src/components/views/voip/CallPreview.tsx index 60153732d8..1b7c7f6e48 100644 --- a/src/components/views/voip/CallPreview.tsx +++ b/src/components/views/voip/CallPreview.tsx @@ -156,8 +156,8 @@ export default class CallPreview extends React.Component { }; private setTranslation(inTranslationX: number, inTranslationY: number) { - const width = this.callViewWrapper.current.clientWidth || PIP_VIEW_WIDTH; - const height = this.callViewWrapper.current.clientHeight || PIP_VIEW_HEIGHT; + const width = this.callViewWrapper.current?.clientWidth || PIP_VIEW_WIDTH; + const height = this.callViewWrapper.current?.clientHeight || PIP_VIEW_HEIGHT; let outTranslationX; let outTranslationY; From 0806af0f4d4f276ff38857ab7fb71b43ee923e9d Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 3 May 2021 15:07:52 -0600 Subject: [PATCH 0197/1449] Calculate the real waveform in the Playback class --- src/voice/Playback.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/voice/Playback.ts b/src/voice/Playback.ts index 99b1f62866..a927ad3104 100644 --- a/src/voice/Playback.ts +++ b/src/voice/Playback.ts @@ -20,6 +20,7 @@ import {arrayFastResample, arraySeed} from "../utils/arrays"; import {SimpleObservable} from "matrix-widget-api"; import {IDestroyable} from "../utils/IDestroyable"; import {PlaybackClock} from "./PlaybackClock"; +import {clamp} from "../utils/numbers"; export enum PlaybackState { Decoding = "decoding", @@ -52,8 +53,6 @@ export class Playback extends EventEmitter implements IDestroyable { this.resampledWaveform = arrayFastResample(seedWaveform, PLAYBACK_WAVEFORM_SAMPLES); this.waveformObservable.update(this.resampledWaveform); this.clock = new PlaybackClock(this.context); - - // TODO: @@ TR: Calculate real waveform } public get waveform(): number[] { @@ -93,6 +92,11 @@ export class Playback extends EventEmitter implements IDestroyable { public async prepare() { this.audioBuf = await this.context.decodeAudioData(this.buf); + + const waveform = Array.from(this.audioBuf.getChannelData(0)).map(v => clamp(v, 0, 1)); + this.resampledWaveform = arrayFastResample(waveform, PLAYBACK_WAVEFORM_SAMPLES); + this.waveformObservable.update(this.resampledWaveform); + this.emit(PlaybackState.Stopped); // signal that we're not decoding anymore this.clock.durationSeconds = this.audioBuf.duration; } From 7f56ec7bd263a67139e91583b102fc8a1c1bba99 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 3 May 2021 15:16:50 -0600 Subject: [PATCH 0198/1449] docs --- src/voice/Playback.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/voice/Playback.ts b/src/voice/Playback.ts index a927ad3104..954aa662c3 100644 --- a/src/voice/Playback.ts +++ b/src/voice/Playback.ts @@ -93,6 +93,8 @@ export class Playback extends EventEmitter implements IDestroyable { public async prepare() { this.audioBuf = await this.context.decodeAudioData(this.buf); + // Update the waveform to the real waveform once we have channel data to use. We don't + // exactly trust the user-provided waveform to be accurate... const waveform = Array.from(this.audioBuf.getChannelData(0)).map(v => clamp(v, 0, 1)); this.resampledWaveform = arrayFastResample(waveform, PLAYBACK_WAVEFORM_SAMPLES); this.waveformObservable.update(this.resampledWaveform); From 5dbe882c778e710917296319205f7a195189b00a Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 3 May 2021 15:20:29 -0600 Subject: [PATCH 0199/1449] Don't recurse on arrayFastResample Fixes https://github.com/vector-im/element-web/issues/17136 --- src/utils/arrays.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/utils/arrays.ts b/src/utils/arrays.ts index f7e693452b..1e130bd605 100644 --- a/src/utils/arrays.ts +++ b/src/utils/arrays.ts @@ -36,14 +36,12 @@ export function arrayFastResample(input: number[], points: number): number[] { } } else { // Smaller inputs mean we have to spread the values over the desired length. We - // end up overshooting the target length in doing this, so we'll resample down - // before returning. This recursion is risky, but mathematically should not go - // further than 1 level deep. + // end up overshooting the target length in doing this, but we're not looking to + // be super accurate so we'll let the sanity trims do their job. const spreadFactor = Math.ceil(points / input.length); for (const val of input) { samples.push(...arraySeed(val, spreadFactor)); } - samples = arrayFastResample(samples, points); } // Sanity fill, just in case From ba2da6826faf8a8da99a35aa0b8b86fa1c774784 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 3 May 2021 16:08:38 -0600 Subject: [PATCH 0200/1449] Support a dark theme for voice messages Fixes https://github.com/vector-im/element-web/issues/17137 --- res/css/views/rooms/_VoiceRecordComposerTile.scss | 2 +- res/css/views/voice_messages/_PlayPauseButton.scss | 4 ++-- res/themes/dark/css/_dark.scss | 8 ++++++++ res/themes/legacy-dark/css/_legacy-dark.scss | 9 +++++++++ res/themes/legacy-light/css/_legacy-light.scss | 3 +++ res/themes/light/css/_light.scss | 3 +++ 6 files changed, 26 insertions(+), 3 deletions(-) diff --git a/res/css/views/rooms/_VoiceRecordComposerTile.scss b/res/css/views/rooms/_VoiceRecordComposerTile.scss index e99e1a00e1..15daf81672 100644 --- a/res/css/views/rooms/_VoiceRecordComposerTile.scss +++ b/res/css/views/rooms/_VoiceRecordComposerTile.scss @@ -40,7 +40,7 @@ limitations under the License. height: 18px; vertical-align: middle; margin-right: 7px; // distance from left edge of waveform container (container has some margin too) - background-color: $muted-fg-color; + background-color: $voice-record-icon-color; mask-repeat: no-repeat; mask-size: contain; mask-image: url('$(res)/img/element-icons/trashcan.svg'); diff --git a/res/css/views/voice_messages/_PlayPauseButton.scss b/res/css/views/voice_messages/_PlayPauseButton.scss index c8ab162694..6caedafa29 100644 --- a/res/css/views/voice_messages/_PlayPauseButton.scss +++ b/res/css/views/voice_messages/_PlayPauseButton.scss @@ -19,12 +19,12 @@ limitations under the License. width: 32px; height: 32px; border-radius: 32px; - background-color: $primary-bg-color; + background-color: $voice-playback-button-bg-color; &::before { content: ''; position: absolute; // sizing varies by icon - background-color: $muted-fg-color; + background-color: $voice-playback-button-fg-color; mask-repeat: no-repeat; mask-size: contain; } diff --git a/res/themes/dark/css/_dark.scss b/res/themes/dark/css/_dark.scss index f9983dce9e..cfdda41619 100644 --- a/res/themes/dark/css/_dark.scss +++ b/res/themes/dark/css/_dark.scss @@ -42,6 +42,14 @@ $preview-bar-bg-color: $header-panel-bg-color; $groupFilterPanel-bg-color: rgba(38, 39, 43, 0.82); $inverted-bg-color: $base-color; +$voice-record-stop-border-color: #6F7882; // "Quarterly" +$voice-record-waveform-bg-color: #394049; // "Dark Tile" +$voice-record-waveform-fg-color: $tertiary-fg-color; +$voice-record-waveform-incomplete-fg-color: #5b646d; +$voice-record-icon-color: $tertiary-fg-color; +$voice-playback-button-bg-color: $tertiary-fg-color; +$voice-playback-button-fg-color: $bg-color; + // used by AddressSelector $selected-color: $room-highlight-color; diff --git a/res/themes/legacy-dark/css/_legacy-dark.scss b/res/themes/legacy-dark/css/_legacy-dark.scss index 194e89e548..6413a99ce0 100644 --- a/res/themes/legacy-dark/css/_legacy-dark.scss +++ b/res/themes/legacy-dark/css/_legacy-dark.scss @@ -124,6 +124,15 @@ $roomsublist-skeleton-ui-bg: linear-gradient(180deg, #3e444c 0%, #3e444c00 100%) $groupFilterPanel-divider-color: $roomlist-header-color; +// See non-legacy dark for variable information +$voice-record-stop-border-color: #6F7882; +$voice-record-waveform-bg-color: #394049; +$voice-record-waveform-fg-color: $tertiary-fg-color; +$voice-record-waveform-incomplete-fg-color: #5b646d; +$voice-record-icon-color: $tertiary-fg-color; +$voice-playback-button-bg-color: $tertiary-fg-color; +$voice-playback-button-fg-color: $bg-color; + $roomtile-preview-color: #9e9e9e; $roomtile-default-badge-bg-color: #61708b; $roomtile-selected-bg-color: #1A1D23; diff --git a/res/themes/legacy-light/css/_legacy-light.scss b/res/themes/legacy-light/css/_legacy-light.scss index d7352e5684..2151724071 100644 --- a/res/themes/legacy-light/css/_legacy-light.scss +++ b/res/themes/legacy-light/css/_legacy-light.scss @@ -198,6 +198,9 @@ $voice-record-waveform-bg-color: #E3E8F0; $voice-record-waveform-fg-color: $muted-fg-color; $voice-record-waveform-incomplete-fg-color: #C1C6CD; $voice-record-live-circle-color: #ff4b55; +$voice-record-icon-color: $muted-fg-color; +$voice-playback-button-bg-color: $primary-bg-color; +$voice-playback-button-fg-color: $muted-fg-color; $roomtile-preview-color: #9e9e9e; $roomtile-default-badge-bg-color: #61708b; diff --git a/res/themes/light/css/_light.scss b/res/themes/light/css/_light.scss index 20ccc2ee41..1763fcdd48 100644 --- a/res/themes/light/css/_light.scss +++ b/res/themes/light/css/_light.scss @@ -188,6 +188,9 @@ $voice-record-waveform-bg-color: #E3E8F0; $voice-record-waveform-fg-color: $muted-fg-color; $voice-record-waveform-incomplete-fg-color: #C1C6CD; $voice-record-live-circle-color: #ff4b55; // $warning-color, but without letting people change it in themes +$voice-record-icon-color: $muted-fg-color; +$voice-playback-button-bg-color: $primary-bg-color; +$voice-playback-button-fg-color: $muted-fg-color; $roomtile-preview-color: $secondary-fg-color; $roomtile-default-badge-bg-color: #61708b; From 87a57ec7e5c7f180f91681cc45a87a4f2162eee9 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 3 May 2021 16:41:39 -0600 Subject: [PATCH 0201/1449] Handle no/blocked microphones in voice messages Fixes https://github.com/vector-im/element-web/issues/17139 --- .../views/rooms/VoiceRecordComposerTile.tsx | 62 ++++++++++++++++--- src/i18n/strings/en_EN.json | 4 ++ 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/src/components/views/rooms/VoiceRecordComposerTile.tsx b/src/components/views/rooms/VoiceRecordComposerTile.tsx index bab95291ba..f7e72000c9 100644 --- a/src/components/views/rooms/VoiceRecordComposerTile.tsx +++ b/src/components/views/rooms/VoiceRecordComposerTile.tsx @@ -27,6 +27,9 @@ import LiveRecordingClock from "../voice_messages/LiveRecordingClock"; import {VoiceRecordingStore} from "../../../stores/VoiceRecordingStore"; import {UPDATE_EVENT} from "../../../stores/AsyncStore"; import RecordingPlayback from "../voice_messages/RecordingPlayback"; +import Modal from "../../../Modal"; +import ErrorDialog from "../dialogs/ErrorDialog"; +import CallMediaHandler from "../../../CallMediaHandler"; interface IProps { room: Room; @@ -115,16 +118,59 @@ export default class VoiceRecordComposerTile extends React.PureComponent { - if (ev === RecordingState.EndingSoon) return; // ignore this state: it has no UI purpose here - this.setState({recordingPhase: ev}); - }); + // The "microphone access error" dialogs are used a lot, so let's functionify them + const accessError = () => { + Modal.createTrackedDialog('Microphone Access Error', '', ErrorDialog, { + title: _t("Unable to access your microphone"), + description: <> +

    {_t( + "We were unable to access your microphone. Please check your browser settings and try again.", + )}

    + , + }); + }; - this.setState({recorder, recordingPhase: RecordingState.Started}); + // Do a sanity test to ensure we're about to grab a valid microphone reference. Things might + // change between this and recording, but at least we will have tried. + try { + const devices = await CallMediaHandler.getDevices(); + if (!devices?.['audioinput']?.length) { + Modal.createTrackedDialog('No Microphone Error', '', ErrorDialog, { + title: _t("No microphone found"), + description: <> +

    {_t( + "We didn't find a microphone on your device. Please check your settings and try again.", + )}

    + , + }); + return; + } + // else we probably have a device that is good enough + } catch (e) { + console.error("Error getting devices: ", e); + accessError(); + return; + } + + try { + const recorder = VoiceRecordingStore.instance.startRecording(); + await recorder.start(); + + // We don't need to remove the listener: the recorder will clean that up for us. + recorder.on(UPDATE_EVENT, (ev: RecordingState) => { + if (ev === RecordingState.EndingSoon) return; // ignore this state: it has no UI purpose here + this.setState({recordingPhase: ev}); + }); + + this.setState({recorder, recordingPhase: RecordingState.Started}); + } catch (e) { + console.error("Error starting recording: ", e); + accessError(); + + // noinspection ES6MissingAwait - if this goes wrong we don't want it to affect the call stack + VoiceRecordingStore.instance.disposeRecording(); + } }; private renderWaveformArea(): ReactNode { diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 5863f2a834..e194f93f1b 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1649,6 +1649,10 @@ "Invited by %(sender)s": "Invited by %(sender)s", "Jump to first unread message.": "Jump to first unread message.", "Mark all as read": "Mark all as read", + "Unable to access your microphone": "Unable to access your microphone", + "We were unable to access your microphone. Please check your browser settings and try again.": "We were unable to access your microphone. Please check your browser settings and try again.", + "No microphone found": "No microphone found", + "We didn't find a microphone on your device. Please check your settings and try again.": "We didn't find a microphone on your device. Please check your settings and try again.", "Record a voice message": "Record a voice message", "Stop the recording": "Stop the recording", "Delete recording": "Delete recording", From e04490284d1d0be35f446c485c3273556ebed751 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 3 May 2021 21:50:25 -0600 Subject: [PATCH 0202/1449] Support UI for MSC2876: Widgets reading events from rooms MSC: https://github.com/matrix-org/matrix-doc/pull/2876 Fixes https://github.com/vector-im/element-web/issues/15747 Requires https://github.com/matrix-org/matrix-widget-api/pull/34 --- src/i18n/strings/en_EN.json | 13 +++++++ src/stores/widgets/StopGapWidgetDriver.ts | 45 +++++++++++++++++++++++ src/widgets/CapabilityText.tsx | 20 ++++++++++ 3 files changed, 78 insertions(+) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 5863f2a834..8a240264c0 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -598,20 +598,33 @@ "Change which room, message, or user you're viewing": "Change which room, message, or user you're viewing", "Change the topic of this room": "Change the topic of this room", "See when the topic changes in this room": "See when the topic changes in this room", + "See the current topic for this room": "See the current topic for this room", "Change the topic of your active room": "Change the topic of your active room", "See when the topic changes in your active room": "See when the topic changes in your active room", + "See the current topic in your active room": "See the current topic in your active room", "Change the name of this room": "Change the name of this room", "See when the name changes in this room": "See when the name changes in this room", + "See the current name for this room": "See the current name for this room", "Change the name of your active room": "Change the name of your active room", "See when the name changes in your active room": "See when the name changes in your active room", + "See the current name of your active room": "See the current name of your active room", "Change the avatar of this room": "Change the avatar of this room", "See when the avatar changes in this room": "See when the avatar changes in this room", + "See the current avatar for this room": "See the current avatar for this room", "Change the avatar of your active room": "Change the avatar of your active room", "See when the avatar changes in your active room": "See when the avatar changes in your active room", + "See the current avatar for your active room": "See the current avatar for your active room", + "Kick, ban, or invite people to this room, and make you leave": "Kick, ban, or invite people to this room, and make you leave", + "See when people join, leave, or are invited to this room": "See when people join, leave, or are invited to this room", + "See the membership status of anyone in this room": "See the membership status of anyone in this room", + "Kick, ban, or invite people to your active room, and make you leave": "Kick, ban, or invite people to your active room, and make you leave", + "See when people join, leave, or are invited to your active room": "See when people join, leave, or are invited to your active room", "Send stickers to this room as you": "Send stickers to this room as you", "See when a sticker is posted in this room": "See when a sticker is posted in this room", + "See recent stickers posted to this room": "See recent stickers posted to this room", "Send stickers to your active room as you": "Send stickers to your active room as you", "See when anyone posts a sticker to your active room": "See when anyone posts a sticker to your active room", + "See recent stickers posted to your active room": "See recent stickers posted to your active room", "with an empty state key": "with an empty state key", "with state key %(stateKey)s": "with state key %(stateKey)s", "Send %(eventType)s events as you in this room": "Send %(eventType)s events as you in this room", diff --git a/src/stores/widgets/StopGapWidgetDriver.ts b/src/stores/widgets/StopGapWidgetDriver.ts index 8a286d909b..7d1c3f3791 100644 --- a/src/stores/widgets/StopGapWidgetDriver.ts +++ b/src/stores/widgets/StopGapWidgetDriver.ts @@ -44,6 +44,7 @@ import { CHAT_EFFECTS } from "../../effects"; import { containsEmoji } from "../../effects/utils"; import dis from "../../dispatcher/dispatcher"; import {tryTransformPermalinkToLocalHref} from "../../utils/permalinks/Permalinks"; +import {MatrixEvent} from "matrix-js-sdk/src/models/event"; // TODO: Purge this from the universe @@ -144,6 +145,50 @@ export class StopGapWidgetDriver extends WidgetDriver { return {roomId, eventId: r.event_id}; } + public async readRoomEvents(eventType: string, msgtype: string | undefined, limit: number): Promise { + limit = limit > 0 ? Math.min(limit, 25) : 25; // arbitrary choice + + const client = MatrixClientPeg.get(); + const roomId = ActiveRoomObserver.activeRoomId; + const room = client.getRoom(roomId); + if (!client || !roomId || !room) throw new Error("Not in a room or not attached to a client"); + + const results: MatrixEvent[] = []; + const events = room.getLiveTimeline().getEvents(); // timelines are most recent last + for (let i = events.length - 1; i > 0; i--) { + if (results.length >= limit) break; + + const ev = events[i]; + if (ev.getType() !== eventType) continue; + if (eventType === EventType.RoomMessage && msgtype && msgtype !== ev.getContent()['msgtype']) continue; + results.push(ev); + } + + return results.map(e => e.event); + } + + public async readStateEvents(eventType: string, stateKey: string | undefined, limit: number): Promise { + limit = limit > 0 ? Math.min(limit, 100) : 100; // arbitrary choice + + const client = MatrixClientPeg.get(); + const roomId = ActiveRoomObserver.activeRoomId; + const room = client.getRoom(roomId); + if (!client || !roomId || !room) throw new Error("Not in a room or not attached to a client"); + + const results: MatrixEvent[] = []; + const state = room.currentState.events.get(eventType); + if (state) { + if (stateKey === "" || !!stateKey) { + const forKey = state.get(stateKey); + if (forKey) results.push(forKey); + } else { + results.push(...Array.from(state.values())); + } + } + + return results.slice(0, limit).map(e => e.event); + } + public async askOpenID(observer: SimpleObservable) { const oidcState = WidgetPermissionStore.instance.getOIDCState( this.forWidget, this.forWidgetKind, this.inRoomId, diff --git a/src/widgets/CapabilityText.tsx b/src/widgets/CapabilityText.tsx index 273d22dc81..f7ff94947d 100644 --- a/src/widgets/CapabilityText.tsx +++ b/src/widgets/CapabilityText.tsx @@ -70,30 +70,48 @@ export class CapabilityText { [WidgetKind.Room]: { [EventDirection.Send]: _td("Change the topic of this room"), [EventDirection.Receive]: _td("See when the topic changes in this room"), + [EventDirection.Read]: _td("See the current topic for this room"), }, [GENERIC_WIDGET_KIND]: { [EventDirection.Send]: _td("Change the topic of your active room"), [EventDirection.Receive]: _td("See when the topic changes in your active room"), + [EventDirection.Read]: _td("See the current topic in your active room"), }, }, [EventType.RoomName]: { [WidgetKind.Room]: { [EventDirection.Send]: _td("Change the name of this room"), [EventDirection.Receive]: _td("See when the name changes in this room"), + [EventDirection.Read]: _td("See the current name for this room"), }, [GENERIC_WIDGET_KIND]: { [EventDirection.Send]: _td("Change the name of your active room"), [EventDirection.Receive]: _td("See when the name changes in your active room"), + [EventDirection.Read]: _td("See the current name of your active room"), }, }, [EventType.RoomAvatar]: { [WidgetKind.Room]: { [EventDirection.Send]: _td("Change the avatar of this room"), [EventDirection.Receive]: _td("See when the avatar changes in this room"), + [EventDirection.Read]: _td("See the current avatar for this room"), }, [GENERIC_WIDGET_KIND]: { [EventDirection.Send]: _td("Change the avatar of your active room"), [EventDirection.Receive]: _td("See when the avatar changes in your active room"), + [EventDirection.Read]: _td("See the current avatar for your active room"), + }, + }, + [EventType.RoomMember]: { + [WidgetKind.Room]: { + [EventDirection.Send]: _td("Kick, ban, or invite people to this room, and make you leave"), + [EventDirection.Receive]: _td("See when people join, leave, or are invited to this room"), + [EventDirection.Read]: _td("See the membership status of anyone in this room"), + }, + [GENERIC_WIDGET_KIND]: { + [EventDirection.Send]: _td("Kick, ban, or invite people to your active room, and make you leave"), + [EventDirection.Receive]: _td("See when people join, leave, or are invited to your active room"), + [EventDirection.Read]: _td("See the membership status of anyone in this room"), }, }, }; @@ -103,10 +121,12 @@ export class CapabilityText { [WidgetKind.Room]: { [EventDirection.Send]: _td("Send stickers to this room as you"), [EventDirection.Receive]: _td("See when a sticker is posted in this room"), + [EventDirection.Read]: _td("See recent stickers posted to this room"), }, [GENERIC_WIDGET_KIND]: { [EventDirection.Send]: _td("Send stickers to your active room as you"), [EventDirection.Receive]: _td("See when anyone posts a sticker to your active room"), + [EventDirection.Read]: _td("See recent stickers posted to your active room"), }, }, }; From 903cc77f3940190ffe64cddc6d9bc9b1271e3dd6 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 3 May 2021 21:53:23 -0600 Subject: [PATCH 0203/1449] Appease the linter --- src/stores/widgets/StopGapWidgetDriver.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/stores/widgets/StopGapWidgetDriver.ts b/src/stores/widgets/StopGapWidgetDriver.ts index 7d1c3f3791..25e81c47a2 100644 --- a/src/stores/widgets/StopGapWidgetDriver.ts +++ b/src/stores/widgets/StopGapWidgetDriver.ts @@ -167,7 +167,9 @@ export class StopGapWidgetDriver extends WidgetDriver { return results.map(e => e.event); } - public async readStateEvents(eventType: string, stateKey: string | undefined, limit: number): Promise { + public async readStateEvents( + eventType: string, stateKey: string | undefined, limit: number, + ): Promise { limit = limit > 0 ? Math.min(limit, 100) : 100; // arbitrary choice const client = MatrixClientPeg.get(); From db2070a83232ca0207de5377c5dae2bbc8f3688b Mon Sep 17 00:00:00 2001 From: c-cal Date: Mon, 3 May 2021 17:31:37 +0000 Subject: [PATCH 0204/1449] Translated using Weblate (French) Currently translated at 100.0% (2924 of 2924 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/fr/ --- src/i18n/strings/fr.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index 3db86ad59b..2c0d1a5f32 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -3043,7 +3043,7 @@ "Your homeserver was unreachable and was not able to log you in. Please try again. If this continues, please contact your homeserver administrator.": "Votre serveur d’accueil n’est pas accessible, nous n’avons pas pu vous connecter. Merci de réessayer. Si cela persiste, merci de contacter l’administrateur de votre serveur d’accueil.", "Try again": "Réessayez", "We asked the browser to remember which homeserver you use to let you sign in, but unfortunately your browser has forgotten it. Go to the sign in page and try again.": "Nous avons demandé à votre navigateur de mémoriser votre serveur d’accueil, mais il semble l’avoir oublié. Rendez-vous à la page de connexion et réessayez.", - "We couldn't log you in": "Impossible de vous déconnecter", + "We couldn't log you in": "Nous n'avons pas pu vous connecter", "Upgrade to %(hostSignupBrand)s": "Mettre à jour vers %(hostSignupBrand)s", "Edit Values": "Modifier les valeurs", "Values at explicit levels in this room:": "Valeurs pour les rangs explicites de ce salon :", @@ -3071,7 +3071,7 @@ "Original event source": "Événement source original", "Decrypted event source": "Événement source déchiffré", "We'll create rooms for each of them. You can add existing rooms after setup.": "Nous allons créer un salon pour chacun d’entre eux. Vous pourrez ajouter des salons après l’initialisation.", - "What projects are you working on?": "Sur quels projets travaillez vous ?", + "What projects are you working on?": "Sur quels projets travaillez-vous ?", "We'll create rooms for each topic.": "Nous allons créer un salon pour chaque sujet.", "What are some things you want to discuss?": "De quoi voulez vous discuter ?", "Inviting...": "Invitation…", @@ -3083,7 +3083,7 @@ "A private space just for you": "Un espace privé seulement pour vous", "Just Me": "Seulement moi", "Ensure the right people have access to the space.": "Vérifiez que les bonnes personnes ont accès à cet espace.", - "Who are you working with?": "Avec qui travaillez vous ?", + "Who are you working with?": "Avec qui travaillez-vous ?", "Finish": "Finir", "At the moment only you can see it.": "Pour l’instant vous seul pouvez le voir.", "Creating rooms...": "Création des salons…", @@ -3112,7 +3112,7 @@ "Remove from Space": "Supprimer de l’espace", "Undo": "Annuler", "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.": "Votre message n’a pas été envoyé car ce serveur d’accueil a été banni par son administrateur. Merci de contacter votre administrateur de service pour poursuivre l’usage de ce service.", - "Are you sure you want to leave the space '%(spaceName)s'?": "Êtes vous sûr de vouloir quitter l’espace « %(spaceName)s » ?", + "Are you sure you want to leave the space '%(spaceName)s'?": "Êtes-vous sûr de vouloir quitter l’espace « %(spaceName)s » ?", "This space is not public. You will not be able to rejoin without an invite.": "Cet espace n’est pas public. Vous ne pourrez pas le rejoindre sans invitation.", "Start audio stream": "Démarrer une diffusion audio", "Failed to start livestream": "Échec lors du démarrage de la diffusion en direct", @@ -3188,7 +3188,7 @@ "This room is suggested as a good one to join": "Ce salon recommandé peut être intéressant à rejoindre", "Verify this login to access your encrypted messages and prove to others that this login is really you.": "Vérifiez cette connexion pour accéder à vos messages chiffrés et prouver aux autres qu’il s’agit bien de vous.", "Verify with another session": "Vérifier avec une autre session", - "We'll create rooms for each of them. You can add more later too, including already existing ones.": "Nous allons créer un salon pour chaque. Vous pourrez en ajouter plus tard, y compris certains déjà existant.", + "We'll create rooms for each of them. You can add more later too, including already existing ones.": "Nous allons créer un salon pour chacun d'entre eux. Vous pourrez aussi en ajouter plus tard, y compris certains déjà existant.", "Let's create a room for each of them. You can add more later too, including already existing ones.": "Créons un salon pour chacun d’entre eux. Vous pourrez en ajouter plus tard, y compris certains déjà existant.", "Make sure the right people have access. You can invite more later.": "Assurez-vous que les accès sont accordés aux bonnes personnes. Vous pourrez en inviter d’autres plus tard.", "A private space to organise your rooms": "Un espace privé pour organiser vos salons", @@ -3232,7 +3232,7 @@ "Please choose a strong password": "Merci de choisir un mot de passe fort", "You can add more later too, including already existing ones.": "Vous pourrez en ajouter plus tard, y compris certains déjà existant.", "Let's create a room for each of them.": "Créons un salon pour chacun d’entre eux.", - "What are some things you want to discuss in %(spaceName)s?": "De quoi voulez vous discuter dans %(spaceName)s ?", + "What are some things you want to discuss in %(spaceName)s?": "De quoi voulez-vous discuter dans %(spaceName)s ?", "Verification requested": "Vérification requise", "Avatar": "Avatar", "Verify other login": "Vérifier l’autre connexion", From a7642b2b24476c4edb32409c4709a2eeb6ac444c Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 4 May 2021 10:48:34 +0100 Subject: [PATCH 0205/1449] Fix space name "Empty room" during creation wizard --- src/components/structures/SpaceRoomView.tsx | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx index 82a211c291..abb57dd9dd 100644 --- a/src/components/structures/SpaceRoomView.tsx +++ b/src/components/structures/SpaceRoomView.tsx @@ -483,9 +483,11 @@ const SpaceAddExistingRooms = ({ space, onFinished }) => {
    ; }; -const SpaceSetupPublicShare = ({ space, onFinished }) => { +const SpaceSetupPublicShare = ({ justCreatedOpts, space, onFinished }) => { return
    -

    { _t("Share %(name)s", { name: space.name }) }

    +

    { _t("Share %(name)s", { + name: justCreatedOpts?.createOpts?.name || space.name, + }) }

    { _t("It's just you at the moment, it will be even better with others.") }
    @@ -764,7 +766,7 @@ export default class SpaceRoomView extends React.PureComponent { return { onFinished={() => this.setState({ phase: Phase.PublicShare })} />; case Phase.PublicShare: - return ; + return ; case Phase.PrivateScope: return Date: Tue, 4 May 2021 15:39:46 +0530 Subject: [PATCH 0206/1449] Use middlePanelResized instead of noisy --- src/components/views/rooms/RoomTile.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/RoomTile.tsx b/src/components/views/rooms/RoomTile.tsx index 108e0979cb..7303f36489 100644 --- a/src/components/views/rooms/RoomTile.tsx +++ b/src/components/views/rooms/RoomTile.tsx @@ -105,7 +105,7 @@ export default class RoomTile extends React.PureComponent { this.notificationState = RoomNotificationStateStore.instance.getRoomState(this.props.room); this.roomProps = EchoChamber.forRoom(this.props.room); if (this.props.resizeNotifier) { - this.props.resizeNotifier.on("middlePanelResizedNoisy", this.onResize); + this.props.resizeNotifier.on("middlePanelResized", this.onResize); } } @@ -207,7 +207,7 @@ export default class RoomTile extends React.PureComponent { this.props.room.off("Room.name", this.onRoomNameUpdate); } if (this.props.resizeNotifier) { - this.props.resizeNotifier.off("middlePanelResizedNoisy", this.onResize); + this.props.resizeNotifier.off("middlePanelResized", this.onResize); } ActiveRoomObserver.removeListener(this.props.room.roomId, this.onActiveRoomUpdate); defaultDispatcher.unregister(this.dispatcherRef); From 0fe6a389d40c24deec0f9b427836df89011ae87f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 4 May 2021 12:36:22 +0200 Subject: [PATCH 0207/1449] Add a note about sharing your IP with P2P calls 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 +- src/settings/Settings.ts | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 85e8e54258..43df51981a 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -833,7 +833,7 @@ "Match system theme": "Match system theme", "Use a system font": "Use a system font", "System font name": "System font name", - "Allow Peer-to-Peer for 1:1 calls": "Allow Peer-to-Peer for 1:1 calls", + "Allow Peer-to-Peer for 1:1 calls (if you enable this, the other party might be able to see your IP address)": "Allow Peer-to-Peer for 1:1 calls (if you enable this, the other party might be able to see your IP address)", "Send analytics data": "Send analytics data", "Never send encrypted messages to unverified sessions from this session": "Never send encrypted messages to unverified sessions from this session", "Never send encrypted messages to unverified sessions in this room from this session": "Never send encrypted messages to unverified sessions in this room from this session", diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index 2a26eeac13..1497a2208d 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -438,7 +438,10 @@ export const SETTINGS: {[setting: string]: ISetting} = { }, "webRtcAllowPeerToPeer": { supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG, - displayName: _td('Allow Peer-to-Peer for 1:1 calls'), + displayName: _td( + "Allow Peer-to-Peer for 1:1 calls " + + "(if you enable this, the other party might be able to see your IP address)", + ), default: true, invertedSettingName: 'webRtcForceTURN', }, From 3eea1b836927a5bfc15313a80feb4ff5d35c1c30 Mon Sep 17 00:00:00 2001 From: Jaiwanth Date: Tue, 4 May 2021 16:42:22 +0530 Subject: [PATCH 0208/1449] Add cleanup functions for image view --- src/components/views/elements/ImageView.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/views/elements/ImageView.tsx b/src/components/views/elements/ImageView.tsx index fcacae2d39..05d487a9eb 100644 --- a/src/components/views/elements/ImageView.tsx +++ b/src/components/views/elements/ImageView.tsx @@ -114,6 +114,8 @@ export default class ImageView extends React.Component { componentWillUnmount() { this.focusLock.current.removeEventListener('wheel', this.onWheel); + window.removeEventListener("resize", this.calculateZoom); + this.image.current.removeEventListener("load", this.calculateZoom); } private calculateZoom = () => { From ac61c8eca8c7d22f16a2fae6e0b2fb75b11abcf5 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 4 May 2021 12:27:27 +0100 Subject: [PATCH 0209/1449] Adhere to updated sort order for space children --- .../structures/SpaceRoomDirectory.tsx | 7 +++++- src/stores/SpaceStore.tsx | 22 +++++++++++++------ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/components/structures/SpaceRoomDirectory.tsx b/src/components/structures/SpaceRoomDirectory.tsx index 8d6c9f0a70..db7fd13753 100644 --- a/src/components/structures/SpaceRoomDirectory.tsx +++ b/src/components/structures/SpaceRoomDirectory.tsx @@ -39,6 +39,7 @@ import {mediaFromMxc} from "../../customisations/Media"; import InfoTooltip from "../views/elements/InfoTooltip"; import TextWithTooltip from "../views/elements/TextWithTooltip"; import {useStateToggle} from "../../hooks/useStateToggle"; +import {getOrder} from "../../stores/SpaceStore"; interface IHierarchyProps { space: Room; @@ -254,7 +255,11 @@ export const HierarchyLevel = ({ const space = cli.getRoom(spaceId); const hasPermissions = space?.currentState.maySendStateEvent(EventType.SpaceChild, cli.getUserId()); - const sortedChildren = sortBy([...(relations.get(spaceId)?.values() || [])], ev => ev.content.order || null); + const children = Array.from(relations.get(spaceId)?.values() || []); + const sortedChildren = sortBy(children, ev => { + // XXX: Space Summary API doesn't give the child origin_server_ts but once it does we should use it for sorting + return getOrder(ev.content.order, null, ev.state_key); + }); const [subspaces, childRooms] = sortedChildren.reduce((result, ev: ISpaceSummaryEvent) => { const roomId = ev.state_key; if (!rooms.has(roomId)) return result; diff --git a/src/stores/SpaceStore.tsx b/src/stores/SpaceStore.tsx index ec6227e45e..db93a23216 100644 --- a/src/stores/SpaceStore.tsx +++ b/src/stores/SpaceStore.tsx @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {sortBy, throttle} from "lodash"; +import {ListIteratee, Many, sortBy, throttle} from "lodash"; import {EventType, RoomType} from "matrix-js-sdk/src/@types/event"; import {Room} from "matrix-js-sdk/src/models/room"; import {MatrixEvent} from "matrix-js-sdk/src/models/event"; @@ -61,15 +61,18 @@ const partitionSpacesAndRooms = (arr: Room[]): [Room[], Room[]] => { // [spaces, }, [[], []]); }; -const getOrder = (ev: MatrixEvent): string | null => { - const content = ev.getContent(); - if (typeof content.order === "string" && Array.from(content.order).every((c: string) => { +// For sorting space children using a validated `order`, `m.room.create`'s `origin_server_ts`, `room_id` +export const getOrder = (order: string, creationTs: number, roomId: string): Array>> => { + let validatedOrder: string = null; + + if (typeof order === "string" && Array.from(order).every((c: string) => { const charCode = c.charCodeAt(0); return charCode >= 0x20 && charCode <= 0x7F; })) { - return content.order; + validatedOrder = order; } - return null; + + return [validatedOrder, creationTs, roomId]; } const getRoomFn: FetchRoomFn = (room: Room) => { @@ -193,7 +196,12 @@ export class SpaceStoreClass extends AsyncStoreWithClient { private getChildren(spaceId: string): Room[] { const room = this.matrixClient?.getRoom(spaceId); const childEvents = room?.currentState.getStateEvents(EventType.SpaceChild).filter(ev => ev.getContent()?.via); - return sortBy(childEvents, getOrder) + return sortBy(childEvents, ev => { + const roomId = ev.getStateKey(); + const childRoom = this.matrixClient?.getRoom(roomId); + const createTs = childRoom?.currentState.getStateEvents(EventType.RoomCreate, "")?.getTs(); + return getOrder(ev.getContent().order, createTs, roomId); + }) .map(ev => this.matrixClient.getRoom(ev.getStateKey())) .filter(room => room?.getMyMembership() === "join" || room?.getMyMembership() === "invite") || []; } From c5cbca7c57d2ef9007927492861e05e4d7eeddf8 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 4 May 2021 12:38:55 +0100 Subject: [PATCH 0210/1449] Fix edge case with space panel alignment with subspaces on ff --- res/css/structures/_SpacePanel.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/res/css/structures/_SpacePanel.scss b/res/css/structures/_SpacePanel.scss index 59f2ea947c..0c5833b176 100644 --- a/res/css/structures/_SpacePanel.scss +++ b/res/css/structures/_SpacePanel.scss @@ -79,6 +79,7 @@ $activeBorderColor: $secondary-fg-color; .mx_SpaceItem { display: inline-flex; flex-flow: wrap; + align-self: baseline; } .mx_SpaceItem.collapsed { From d14ea1bd58f7ae53a496c5e3c4f0135250dfe4e6 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 4 May 2021 14:01:10 +0100 Subject: [PATCH 0211/1449] Fix layout issue with expanded space panel --- res/css/structures/_SpacePanel.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/res/css/structures/_SpacePanel.scss b/res/css/structures/_SpacePanel.scss index 0c5833b176..8f277806cb 100644 --- a/res/css/structures/_SpacePanel.scss +++ b/res/css/structures/_SpacePanel.scss @@ -80,6 +80,7 @@ $activeBorderColor: $secondary-fg-color; display: inline-flex; flex-flow: wrap; align-self: baseline; + width: 100%; } .mx_SpaceItem.collapsed { From 4489f8a6ead924f8124c2ee95f508f36d6e66c8e Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 4 May 2021 14:01:26 +0100 Subject: [PATCH 0212/1449] Fix hover behaviour of space invites --- res/css/structures/_SpacePanel.scss | 2 +- src/components/views/spaces/SpaceTreeLevel.tsx | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/res/css/structures/_SpacePanel.scss b/res/css/structures/_SpacePanel.scss index 8f277806cb..dbb18d02fd 100644 --- a/res/css/structures/_SpacePanel.scss +++ b/res/css/structures/_SpacePanel.scss @@ -277,7 +277,7 @@ $activeBorderColor: $secondary-fg-color; .mx_SpaceButton:hover, .mx_SpaceButton:focus-within, .mx_SpaceButton_hasMenuOpen { - &:not(.mx_SpaceButton_home) { + &:not(.mx_SpaceButton_home):not(.mx_SpaceButton_invite) { // Hide the badge container on hover because it'll be a menu button .mx_SpacePanel_badgeContainer { width: 0; diff --git a/src/components/views/spaces/SpaceTreeLevel.tsx b/src/components/views/spaces/SpaceTreeLevel.tsx index 6825d84013..9bdbced0b5 100644 --- a/src/components/views/spaces/SpaceTreeLevel.tsx +++ b/src/components/views/spaces/SpaceTreeLevel.tsx @@ -300,12 +300,15 @@ export class SpaceItem extends React.PureComponent { "collapsed": collapsed, "hasSubSpaces": childSpaces && childSpaces.length, }); + + const isInvite = space.getMyMembership() === "invite"; const classes = classNames("mx_SpaceButton", { mx_SpaceButton_active: isActive, mx_SpaceButton_hasMenuOpen: !!this.state.contextMenuPosition, mx_SpaceButton_narrow: isNarrow, + mx_SpaceButton_invite: isInvite, }); - const notificationState = space.getMyMembership() === "invite" + const notificationState = isInvite ? StaticNotificationState.forSymbol("!", NotificationColor.Red) : SpaceStore.instance.getNotificationState(space.roomId); From caa772348fd3d303d903ea7c1c05d1ebd8dd6f16 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 4 May 2021 14:14:06 +0100 Subject: [PATCH 0213/1449] Actually fix the layout bug without re-regressing the prior issue --- res/css/structures/_SpacePanel.scss | 6 ++++-- src/components/views/spaces/SpaceTreeLevel.tsx | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/res/css/structures/_SpacePanel.scss b/res/css/structures/_SpacePanel.scss index dbb18d02fd..9264e82ea5 100644 --- a/res/css/structures/_SpacePanel.scss +++ b/res/css/structures/_SpacePanel.scss @@ -79,8 +79,10 @@ $activeBorderColor: $secondary-fg-color; .mx_SpaceItem { display: inline-flex; flex-flow: wrap; - align-self: baseline; - width: 100%; + + &.mx_SpaceItem_narrow { + align-self: baseline; + } } .mx_SpaceItem.collapsed { diff --git a/src/components/views/spaces/SpaceTreeLevel.tsx b/src/components/views/spaces/SpaceTreeLevel.tsx index 9bdbced0b5..e48e1d5dc2 100644 --- a/src/components/views/spaces/SpaceTreeLevel.tsx +++ b/src/components/views/spaces/SpaceTreeLevel.tsx @@ -297,6 +297,7 @@ export class SpaceItem extends React.PureComponent { const isActive = activeSpaces.includes(space); const itemClasses = classNames({ "mx_SpaceItem": true, + "mx_SpaceItem_narrow": isNarrow, "collapsed": collapsed, "hasSubSpaces": childSpaces && childSpaces.length, }); From 9f5285d9f89994cccd1926bffba8299c62134960 Mon Sep 17 00:00:00 2001 From: Thibault Martin Date: Tue, 4 May 2021 06:07:34 +0000 Subject: [PATCH 0214/1449] Translated using Weblate (French) Currently translated at 100.0% (2924 of 2924 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/fr/ --- src/i18n/strings/fr.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index 2c0d1a5f32..984dce8595 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -3043,7 +3043,7 @@ "Your homeserver was unreachable and was not able to log you in. Please try again. If this continues, please contact your homeserver administrator.": "Votre serveur d’accueil n’est pas accessible, nous n’avons pas pu vous connecter. Merci de réessayer. Si cela persiste, merci de contacter l’administrateur de votre serveur d’accueil.", "Try again": "Réessayez", "We asked the browser to remember which homeserver you use to let you sign in, but unfortunately your browser has forgotten it. Go to the sign in page and try again.": "Nous avons demandé à votre navigateur de mémoriser votre serveur d’accueil, mais il semble l’avoir oublié. Rendez-vous à la page de connexion et réessayez.", - "We couldn't log you in": "Nous n'avons pas pu vous connecter", + "We couldn't log you in": "Nous n’avons pas pu vous connecter", "Upgrade to %(hostSignupBrand)s": "Mettre à jour vers %(hostSignupBrand)s", "Edit Values": "Modifier les valeurs", "Values at explicit levels in this room:": "Valeurs pour les rangs explicites de ce salon :", @@ -3188,7 +3188,7 @@ "This room is suggested as a good one to join": "Ce salon recommandé peut être intéressant à rejoindre", "Verify this login to access your encrypted messages and prove to others that this login is really you.": "Vérifiez cette connexion pour accéder à vos messages chiffrés et prouver aux autres qu’il s’agit bien de vous.", "Verify with another session": "Vérifier avec une autre session", - "We'll create rooms for each of them. You can add more later too, including already existing ones.": "Nous allons créer un salon pour chacun d'entre eux. Vous pourrez aussi en ajouter plus tard, y compris certains déjà existant.", + "We'll create rooms for each of them. You can add more later too, including already existing ones.": "Nous allons créer un salon pour chacun d’entre eux. Vous pourrez aussi en ajouter plus tard, y compris certains déjà existant.", "Let's create a room for each of them. You can add more later too, including already existing ones.": "Créons un salon pour chacun d’entre eux. Vous pourrez en ajouter plus tard, y compris certains déjà existant.", "Make sure the right people have access. You can invite more later.": "Assurez-vous que les accès sont accordés aux bonnes personnes. Vous pourrez en inviter d’autres plus tard.", "A private space to organise your rooms": "Un espace privé pour organiser vos salons", From 5954bf0a411db335ca02d4c6c000cb61e1c48701 Mon Sep 17 00:00:00 2001 From: Marek Date: Tue, 4 May 2021 13:29:46 +0000 Subject: [PATCH 0215/1449] Translated using Weblate (German) Currently translated at 99.5% (2912 of 2924 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 2bb593f09c..7f0d6a2747 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -78,7 +78,7 @@ "Someone": "Jemand", "Success": "Erfolg", "This doesn't appear to be a valid email address": "Dies scheint keine gültige E-Mail-Adresse zu sein", - "This room is not accessible by remote Matrix servers": "Nutzer von anderen Homeservern können auf diesen Raum nicht zugreifen", + "This room is not accessible by remote Matrix servers": "Dieser Raum ist von Personen auf anderen Matrix-Servern nicht betretbar", "Admin": "Administrator", "Server may be unavailable, overloaded, or you hit a bug.": "Server ist nicht verfügbar, überlastet oder du bist auf einen Softwarefehler gestoßen.", "Labs": "Labor", @@ -2597,7 +2597,7 @@ "See videos posted to your active room": "In deinen aktiven Raum gesendete Videos anzeigen", "See videos posted to this room": "In diesen Raum gesendete Videos anzeigen", "Send images as you in this room": "Bilder als du in diesen Raum senden", - "Send images as you in your active room": "Bilder als du in deinem aktiven Raum senden", + "Send images as you in your active room": "Sende Bilder als deine Person in den aktiven Raum.", "See images posted to this room": "In diesen Raum gesendete Bilder anzeigen", "See images posted to your active room": "In deinen aktiven Raum gesendete Bilder anzeigen", "Send videos as you in this room": "Videos als du in diesen Raum senden", @@ -2621,7 +2621,7 @@ "Call Paused": "Anruf pausiert", "Securely cache encrypted messages locally for them to appear in search results, using %(size)s to store messages from %(rooms)s rooms.|other": "Verschlüsselte Nachrichten sicher lokal zwischenspeichern, um sie in Suchergebnissen finden zu können. Es werden %(size)s benötigt, um die Nachrichten von %(rooms)s Räumen zu speichern.", "Securely cache encrypted messages locally for them to appear in search results, using %(size)s to store messages from %(rooms)s rooms.|one": "Verschlüsselte Nachrichten sicher lokal zwischenspeichern, um sie in Suchergebnissen finden zu können. Es werden %(size)s benötigt, um die Nachrichten vom Raum %(rooms)s zu speichern.", - "Only the two of you are in this conversation, unless either of you invites anyone to join.": "Nur ihr zwei seid in dieser Konversation, außer ihr ladet jemanden Neues ein.", + "Only the two of you are in this conversation, unless either of you invites anyone to join.": "Nur ihr beide nehmt an dieser Konversation teil, es sei denn, ihr ladet jemanden ein.", "This is the beginning of your direct message history with .": "Dies ist der Beginn deiner Direktnachrichten mit .", "Topic: %(topic)s (edit)": "Thema: %(topic)s (ändern)", "Topic: %(topic)s ": "Thema: %(topic)s ", @@ -2945,7 +2945,7 @@ "You can use the custom server options to sign into other Matrix servers by specifying a different homeserver URL. This allows you to use Element with an existing Matrix account on a different homeserver.": "Du kannst in den benutzerdefinierten Serveroptionen eine andere Heimserver-URL angeben, um dich bei anderen Matrixservern anzumelden.", "Server Options": "Servereinstellungen", "No other application is using the webcam": "keine andere Anwendung auf die Webcam zugreift", - "Permission is granted to use the webcam": "auf die Webcam zugegriffen werden darf", + "Permission is granted to use the webcam": "Zugriff auf die Webcam ist gestattet.", "A microphone and webcam are plugged in and set up correctly": "Mikrofon und Webcam eingesteckt und richtig eingerichtet sind", "Call failed because no microphone could not be accessed. Check that a microphone is plugged in and set up correctly.": "Der Anruf ist fehlgeschlagen weil nicht auf das Mikrofon zugegriffen werden konnte. Stelle sicher, dass das Mikrofon richtig eingesteckt und eingerichtet ist.", "Call failed because no webcam or microphone could not be accessed. Check that:": "Der Anruf ist fehlgeschlagen weil nicht auf das Mikrofon oder die Webcam zugegriffen werden konnte. Stelle sicher, dass:", @@ -2954,7 +2954,7 @@ "Host account on": "Benutzer*innenkonto betreiben an", "Hold": "Halten", "Resume": "Fortsetzen", - "We call the places where you can host your account ‘homeservers’.": "Den Ort, an dem du dein Benutzer*innenkonto betreibst, nennen wir „Heimserver“.", + "We call the places where you can host your account ‘homeservers’.": "Den Ort, an dem du dein Konto betreibst, nennen wir „Heimserver“.", "Invalid URL": "Ungültiger Link", "Unable to validate homeserver": "Überprüfung des Heimservers nicht möglich", "%(name)s paused": "%(name)s hat pausiert", @@ -3161,7 +3161,7 @@ "Invite to %(spaceName)s": "Leute zu %(spaceName)s einladen", "Spaces": "Spaces", "Invite People": "Personen einladen", - "Invite with email or username": "Personen mit E-Mail oder Benutzername einladen", + "Invite with email or username": "Personen mit E-Mail oder Benutzernamen einladen", "You can change these anytime.": "Du kannst diese jederzeit ändern.", "From %(deviceName)s (%(deviceId)s) at %(ip)s": "Von %(deviceName)s (%(deviceId)s) mit der Adresse %(ip)s", "A new login is accessing your account: %(name)s (%(deviceID)s) at %(ip)s": "Neue Anmeldung: %(name)s (%(deviceID)s) mit der IP-Adresse %(ip)s", @@ -3276,10 +3276,11 @@ "You can select all or individual messages to retry or delete": "Du kannst einzelne oder alle Nachrichten erneut senden oder löschen", "Delete all": "Alle löschen", "Retry all": "Alle erneut senden", - "Without verifying, you won’t have access to all your messages and may appear as untrusted to others.": "Wenn du dich nicht verifizierst, kannst du keine deiner verschlüsselten Nachrichten lesen und andere vertrauen dir möglicherweise nicht.", - "Verify your identity to access encrypted messages and prove your identity to others.": "Verifiziere diese Anmeldung damit du auf deine verschlüsselten Nachrichten zugreifen kannst und anderen deine Identität zu bestätigen.", + "Without verifying, you won’t have access to all your messages and may appear as untrusted to others.": "Ohne deine Verifikation kannst du keine deiner verschlüsselten Nachrichten lesen und andere vertrauen dir möglicherweise nicht.", + "Verify your identity to access encrypted messages and prove your identity to others.": "Verifiziere diese Anmeldung, um auf verschlüsselte Nachrichten zuzugreifen und dich anderen gegenüber zu identifizieren.", "Use another login": "Mit anderem Gerät verifizeren", "If you do, please note that none of your messages will be deleted, but the search experience might be degraded for a few moments whilst the index is recreated": "Falls du es wirklich willst: Es werden keine Nachrichten gelöscht. Außerdem wird die Suche, während der Index erstellt wird, etwas langsamer sein", "%(count)s members including %(commaSeparatedMembers)s|other": "%(count)s Mitglieder inklusive %(commaSeparatedMembers)s", - "Including %(commaSeparatedMembers)s": "Inklusive%(commaSeparatedMembers)s" + "Including %(commaSeparatedMembers)s": "Inklusive%(commaSeparatedMembers)s", + "Consulting with %(transferTarget)s. Transfer to %(transferee)s": "Beratung mit %(transferTarget)s. Übertragung zu %(transferee)s" } From ddc8f56b470fb498b5a74a163a72827412598483 Mon Sep 17 00:00:00 2001 From: waclaw66 Date: Tue, 4 May 2021 05:06:13 +0000 Subject: [PATCH 0216/1449] Translated using Weblate (Czech) Currently translated at 100.0% (2924 of 2924 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 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/cs.json b/src/i18n/strings/cs.json index bc1dff54fd..8633146420 100644 --- a/src/i18n/strings/cs.json +++ b/src/i18n/strings/cs.json @@ -1708,7 +1708,7 @@ "Backup has a invalid signature from this user": "Záloha má neplatný podpis od tohoto uživatele", "Backup has a signature from unknown user with ID %(deviceId)s": "Záloha je podepsaná neznámým uživatelem %(deviceId)s", "Close preview": "Zavřít náhled", - "Hide verified sessions": "Schovat ověřené relace", + "Hide verified sessions": "Skrýt ověřené relace", "%(count)s verified sessions|other": "%(count)s ověřených relací", "%(count)s verified sessions|one": "1 ověřená relace", "Language Dropdown": "Menu jazyků", From b777c83c908a9c86b6d99e966e566bebcabfae0a Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 4 May 2021 15:42:45 +0100 Subject: [PATCH 0217/1449] Upgrade matrix-js-sdk to 10.1.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 e54de8a96c..98141c6404 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,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": "10.1.0-rc.1", "matrix-widget-api": "^0.1.0-beta.13", "minimist": "^1.2.5", "opus-recorder": "^8.0.3", diff --git a/yarn.lock b/yarn.lock index acdca26e55..c1e04a0686 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5671,9 +5671,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 "10.0.0" - resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/c8f69c0b7937b9064938c134d708c4d064b71315" +matrix-js-sdk@10.1.0-rc.1: + version "10.1.0-rc.1" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-10.1.0-rc.1.tgz#67b04cd30cb3b3c8ee7a3a2ead1db567a99e35c8" + integrity sha512-jpCnSqvNAsVIHv/FRVx1xV11IKcQCd6zUy4cHLDfUH/6GxFDtW/Fk446A7XDIJnNvstqmWBghk4X65hdsfq5OQ== dependencies: "@babel/runtime" "^7.12.5" another-json "^0.2.0" From b5cb1534d3990f92ea399d126d83019c26dd2d94 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 4 May 2021 15:53:39 +0100 Subject: [PATCH 0218/1449] Prepare changelog for v3.20.0-rc.1 --- CHANGELOG.md | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d459b4e94a..fc6c0b7f76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,107 @@ +Changes in [3.20.0-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.20.0-rc.1) (2021-05-04) +=============================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v3.19.0...v3.20.0-rc.1) + + * Upgrade to JS SDK 10.1.0-rc.1 + * Translations update from Weblate + [\#5966](https://github.com/matrix-org/matrix-react-sdk/pull/5966) + * Fix more space panel layout and hover behaviour issues + [\#5965](https://github.com/matrix-org/matrix-react-sdk/pull/5965) + * Fix edge case with space panel alignment with subspaces on ff + [\#5964](https://github.com/matrix-org/matrix-react-sdk/pull/5964) + * Fix saving room pill part to history + [\#5951](https://github.com/matrix-org/matrix-react-sdk/pull/5951) + * Generate room preview even when minimized + [\#5948](https://github.com/matrix-org/matrix-react-sdk/pull/5948) + * Another change from recovery passphrase to Security Phrase + [\#5934](https://github.com/matrix-org/matrix-react-sdk/pull/5934) + * Sort rooms in the add existing to space dialog based on recency + [\#5943](https://github.com/matrix-org/matrix-react-sdk/pull/5943) + * Inhibit sending RR when context switching to a room + [\#5944](https://github.com/matrix-org/matrix-react-sdk/pull/5944) + * Prevent room list keyboard handling from landing focus on hidden nodes + [\#5950](https://github.com/matrix-org/matrix-react-sdk/pull/5950) + * Make the text filter search all spaces instead of just the selected one + [\#5942](https://github.com/matrix-org/matrix-react-sdk/pull/5942) + * Enable indent rule and fix indent + [\#5931](https://github.com/matrix-org/matrix-react-sdk/pull/5931) + * Prevent peeking members from reacting + [\#5946](https://github.com/matrix-org/matrix-react-sdk/pull/5946) + * Disallow inline display maths + [\#5939](https://github.com/matrix-org/matrix-react-sdk/pull/5939) + * Space creation prompt user to add existing rooms for "Just Me" spaces + [\#5923](https://github.com/matrix-org/matrix-react-sdk/pull/5923) + * Add test coverage collection script + [\#5937](https://github.com/matrix-org/matrix-react-sdk/pull/5937) + * Fix joining room using via servers regression + [\#5936](https://github.com/matrix-org/matrix-react-sdk/pull/5936) + * Revert "Fixes the two Todays problem in Redaction" + [\#5938](https://github.com/matrix-org/matrix-react-sdk/pull/5938) + * Handle encoded matrix URLs + [\#5903](https://github.com/matrix-org/matrix-react-sdk/pull/5903) + * Render ignored users setting regardless of if there are any + [\#5860](https://github.com/matrix-org/matrix-react-sdk/pull/5860) + * Fix inserting trailing colon after mention/pill + [\#5830](https://github.com/matrix-org/matrix-react-sdk/pull/5830) + * Fixes the two Todays problem in Redaction + [\#5917](https://github.com/matrix-org/matrix-react-sdk/pull/5917) + * Fix page up/down scrolling only half a page + [\#5920](https://github.com/matrix-org/matrix-react-sdk/pull/5920) + * Voice messages: Composer controls + [\#5935](https://github.com/matrix-org/matrix-react-sdk/pull/5935) + * Support MSC3086 asserted identity + [\#5886](https://github.com/matrix-org/matrix-react-sdk/pull/5886) + * Handle possible edge case with getting stuck in "unsent messages" bar + [\#5930](https://github.com/matrix-org/matrix-react-sdk/pull/5930) + * Fix suggested rooms not showing up regression from room list optimisation + [\#5932](https://github.com/matrix-org/matrix-react-sdk/pull/5932) + * Broadcast language change to ElectronPlatform + [\#5913](https://github.com/matrix-org/matrix-react-sdk/pull/5913) + * Fix VoIP PIP frame color + [\#5701](https://github.com/matrix-org/matrix-react-sdk/pull/5701) + * Convert some Flow-typed files to TypeScript + [\#5912](https://github.com/matrix-org/matrix-react-sdk/pull/5912) + * Initial SpaceStore tests work + [\#5906](https://github.com/matrix-org/matrix-react-sdk/pull/5906) + * Fix issues with space hierarchy in layout and with incompatible servers + [\#5926](https://github.com/matrix-org/matrix-react-sdk/pull/5926) + * Scale all mxc thumbs using device pixel ratio for hidpi + [\#5928](https://github.com/matrix-org/matrix-react-sdk/pull/5928) + * Fix add existing to space dialog no longer showing rooms for public spaces + [\#5918](https://github.com/matrix-org/matrix-react-sdk/pull/5918) + * Disable spaces context switching for when exploring a space + [\#5924](https://github.com/matrix-org/matrix-react-sdk/pull/5924) + * Autofocus search box in the add existing to space dialog + [\#5921](https://github.com/matrix-org/matrix-react-sdk/pull/5921) + * Use label element in add existing to space dialog for easier hit target + [\#5922](https://github.com/matrix-org/matrix-react-sdk/pull/5922) + * Dynamic max and min zoom in the new ImageView + [\#5916](https://github.com/matrix-org/matrix-react-sdk/pull/5916) + * Improve message error states + [\#5897](https://github.com/matrix-org/matrix-react-sdk/pull/5897) + * Check for null room in `VisibilityProvider` + [\#5914](https://github.com/matrix-org/matrix-react-sdk/pull/5914) + * Add unit tests for various collection-based utility functions + [\#5910](https://github.com/matrix-org/matrix-react-sdk/pull/5910) + * Spaces visual fixes + [\#5909](https://github.com/matrix-org/matrix-react-sdk/pull/5909) + * Remove reliance on DOM API to generated message preview + [\#5908](https://github.com/matrix-org/matrix-react-sdk/pull/5908) + * Expand upon voice message event & include overall waveform + [\#5888](https://github.com/matrix-org/matrix-react-sdk/pull/5888) + * Use floats for image background opacity + [\#5905](https://github.com/matrix-org/matrix-react-sdk/pull/5905) + * Show invites to spaces at the top of the space panel + [\#5902](https://github.com/matrix-org/matrix-react-sdk/pull/5902) + * Improve edge cases with spaces context switching + [\#5899](https://github.com/matrix-org/matrix-react-sdk/pull/5899) + * Fix spaces notification dots wrongly including upgraded (hidden) rooms + [\#5900](https://github.com/matrix-org/matrix-react-sdk/pull/5900) + * Iterate the spaces face pile design + [\#5898](https://github.com/matrix-org/matrix-react-sdk/pull/5898) + * Fix alignment issue with nested spaces being cut off wrong + [\#5890](https://github.com/matrix-org/matrix-react-sdk/pull/5890) + Changes in [3.19.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.19.0) (2021-04-26) ===================================================================================================== [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v3.19.0-rc.1...v3.19.0) From efc8c8c84e46a267c3553d53b4d703b9f4aff6f3 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 4 May 2021 15:53:40 +0100 Subject: [PATCH 0219/1449] v3.20.0-rc.1 --- package.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 98141c6404..f6471327cb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "3.19.0", + "version": "3.20.0-rc.1", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { @@ -25,7 +25,7 @@ "bin": { "reskindex": "scripts/reskindex.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", @@ -196,5 +196,6 @@ "coverageReporters": [ "text" ] - } + }, + "typings": "./lib/index.d.ts" } From 48237949ad6821e61c839fff14bb86738fab0575 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 4 May 2021 16:44:29 +0100 Subject: [PATCH 0220/1449] Only aggregate DM notifications on the Space Panel in the Home Space --- src/stores/SpaceStore.tsx | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/stores/SpaceStore.tsx b/src/stores/SpaceStore.tsx index ec6227e45e..22307d9f2e 100644 --- a/src/stores/SpaceStore.tsx +++ b/src/stores/SpaceStore.tsx @@ -406,7 +406,19 @@ export class SpaceStoreClass extends AsyncStoreWithClient { this.spaceFilteredRooms.forEach((roomIds, s) => { // Update NotificationStates - this.getNotificationState(s)?.setRooms(visibleRooms.filter(room => roomIds.has(room.roomId))); + this.getNotificationState(s)?.setRooms(visibleRooms.filter(room => { + if (roomIds.has(room.roomId)) { + // Don't aggregate notifications for DMs except in the Home Space + if (s !== HOME_SPACE) { + return !DMRoomMap.shared().getUserIdForRoomId(room.roomId) + || RoomListStore.instance.getTagsForRoom(room).includes(DefaultTagID.Favourite); + } + + return true; + } + + return false; + })); }); }, 100, {trailing: true, leading: true}); From a70be45b6e0f2ea1292f8a56067c59c81a88156f Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 4 May 2021 18:06:43 +0100 Subject: [PATCH 0221/1449] Experiment switching the Home Space out for an All rooms space --- src/components/structures/RoomSearch.tsx | 22 +--- .../views/rooms/RoomListNumResults.tsx | 6 +- src/components/views/spaces/SpacePanel.tsx | 10 +- src/i18n/strings/en_EN.json | 7 +- src/stores/SpaceStore.tsx | 103 +++--------------- src/stores/room-list/RoomListStore.ts | 14 +-- src/stores/room-list/SpaceWatcher.ts | 28 +++-- .../room-list/filters/SpaceFilterCondition.ts | 8 +- 8 files changed, 49 insertions(+), 149 deletions(-) diff --git a/src/components/structures/RoomSearch.tsx b/src/components/structures/RoomSearch.tsx index 34682877e0..b3ceb1588f 100644 --- a/src/components/structures/RoomSearch.tsx +++ b/src/components/structures/RoomSearch.tsx @@ -17,7 +17,6 @@ limitations under the License. import * as React from "react"; import { createRef } from "react"; import classNames from "classnames"; -import { Room } from "matrix-js-sdk/src/models/room"; import defaultDispatcher from "../../dispatcher/dispatcher"; import { _t } from "../../languageHandler"; @@ -27,8 +26,8 @@ import { Action } from "../../dispatcher/actions"; import RoomListStore from "../../stores/room-list/RoomListStore"; import { NameFilterCondition } from "../../stores/room-list/filters/NameFilterCondition"; import { getKeyBindingsManager, RoomListAction } from "../../KeyBindingsManager"; -import {replaceableComponent} from "../../utils/replaceableComponent"; -import SpaceStore, {UPDATE_SELECTED_SPACE, UPDATE_TOP_LEVEL_SPACES} from "../../stores/SpaceStore"; +import { replaceableComponent } from "../../utils/replaceableComponent"; +import SpaceStore, { UPDATE_SELECTED_SPACE } from "../../stores/SpaceStore"; interface IProps { isMinimized: boolean; @@ -42,7 +41,6 @@ interface IProps { interface IState { query: string; focused: boolean; - inSpaces: boolean; } @replaceableComponent("structures.RoomSearch") @@ -57,13 +55,11 @@ export default class RoomSearch extends React.PureComponent { this.state = { query: "", focused: false, - inSpaces: false, }; this.dispatcherRef = defaultDispatcher.register(this.onAction); // clear filter when changing spaces, in future we may wish to maintain a filter per-space SpaceStore.instance.on(UPDATE_SELECTED_SPACE, this.clearInput); - SpaceStore.instance.on(UPDATE_TOP_LEVEL_SPACES, this.onSpaces); } public componentDidUpdate(prevProps: Readonly, prevState: Readonly): void { @@ -84,15 +80,8 @@ export default class RoomSearch extends React.PureComponent { public componentWillUnmount() { defaultDispatcher.unregister(this.dispatcherRef); SpaceStore.instance.off(UPDATE_SELECTED_SPACE, this.clearInput); - SpaceStore.instance.off(UPDATE_TOP_LEVEL_SPACES, this.onSpaces); } - private onSpaces = (spaces: Room[]) => { - this.setState({ - inSpaces: spaces.length > 0, - }); - }; - private onAction = (payload: ActionPayload) => { if (payload.action === 'view_room' && payload.clear_search) { this.clearInput(); @@ -164,11 +153,6 @@ export default class RoomSearch extends React.PureComponent { 'mx_RoomSearch_inputExpanded': this.state.query || this.state.focused, }); - let placeholder = _t("Filter"); - if (this.state.inSpaces) { - placeholder = _t("Filter all spaces"); - } - let icon = (
    ); @@ -182,7 +166,7 @@ export default class RoomSearch extends React.PureComponent { onBlur={this.onBlur} onChange={this.onChange} onKeyDown={this.onKeyDown} - placeholder={placeholder} + placeholder={_t("Filter")} autoComplete="off" /> ); diff --git a/src/components/views/rooms/RoomListNumResults.tsx b/src/components/views/rooms/RoomListNumResults.tsx index 01cbecf05d..4215e5644c 100644 --- a/src/components/views/rooms/RoomListNumResults.tsx +++ b/src/components/views/rooms/RoomListNumResults.tsx @@ -19,7 +19,6 @@ import React, {useState} from "react"; import { _t } from "../../../languageHandler"; import RoomListStore, { LISTS_UPDATE_EVENT } from "../../../stores/room-list/RoomListStore"; import {useEventEmitter} from "../../../hooks/useEventEmitter"; -import SpaceStore from "../../../stores/SpaceStore"; const RoomListNumResults: React.FC = () => { const [count, setCount] = useState(null); @@ -35,10 +34,7 @@ const RoomListNumResults: React.FC = () => { if (typeof count !== "number") return null; return
    - { SpaceStore.instance.spacePanelSpaces.length - ? _t("%(count)s results in all spaces", { count }) - : _t("%(count)s results", { count }) - } + { _t("%(count)s results", { count }) }
    ; }; diff --git a/src/components/views/spaces/SpacePanel.tsx b/src/components/views/spaces/SpacePanel.tsx index 36ab423885..411b0f9b5e 100644 --- a/src/components/views/spaces/SpacePanel.tsx +++ b/src/components/views/spaces/SpacePanel.tsx @@ -26,13 +26,11 @@ import {SpaceItem} from "./SpaceTreeLevel"; import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; import {useEventEmitter} from "../../../hooks/useEventEmitter"; import SpaceStore, { - HOME_SPACE, UPDATE_INVITED_SPACES, UPDATE_SELECTED_SPACE, UPDATE_TOP_LEVEL_SPACES, } from "../../../stores/SpaceStore"; import AutoHideScrollbar from "../../structures/AutoHideScrollbar"; -import {SpaceNotificationState} from "../../../stores/notifications/SpaceNotificationState"; import NotificationBadge from "../rooms/NotificationBadge"; import { RovingAccessibleButton, @@ -40,13 +38,15 @@ import { RovingTabIndexProvider, } from "../../../accessibility/RovingTabIndex"; import {Key} from "../../../Keyboard"; +import {RoomNotificationStateStore} from "../../../stores/notifications/RoomNotificationStateStore"; +import {NotificationState} from "../../../stores/notifications/NotificationState"; interface IButtonProps { space?: Room; className?: string; selected?: boolean; tooltip?: string; - notificationState?: SpaceNotificationState; + notificationState?: NotificationState; isNarrow?: boolean; onClick(): void; } @@ -212,8 +212,8 @@ const SpacePanel = () => { className="mx_SpaceButton_home" onClick={() => SpaceStore.instance.setActiveSpace(null)} selected={!activeSpace} - tooltip={_t("Home")} - notificationState={SpaceStore.instance.getNotificationState(HOME_SPACE)} + tooltip={_t("All rooms")} + notificationState={RoomNotificationStateStore.instance.globalState} isNarrow={isPanelCollapsed} /> { invites.map(s => %(serverName)s": "Are you sure you want to remove %(serverName)s", "Remove server": "Remove server", @@ -2619,7 +2617,6 @@ "If you can't find the room you're looking for, ask for an invite or Create a new room.": "If you can't find the room you're looking for, ask for an invite or Create a new room.", "Explore rooms in %(communityName)s": "Explore rooms in %(communityName)s", "Filter": "Filter", - "Filter all spaces": "Filter all spaces", "Clear filter": "Clear filter", "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.", diff --git a/src/stores/SpaceStore.tsx b/src/stores/SpaceStore.tsx index 22307d9f2e..50c5ea56f7 100644 --- a/src/stores/SpaceStore.tsx +++ b/src/stores/SpaceStore.tsx @@ -31,28 +31,23 @@ import {RoomNotificationStateStore} from "./notifications/RoomNotificationStateS import {DefaultTagID} from "./room-list/models"; import {EnhancedMap, mapDiff} from "../utils/maps"; import {setHasDiff} from "../utils/sets"; -import {objectDiff} from "../utils/objects"; -import {arrayHasDiff} from "../utils/arrays"; import {ISpaceSummaryEvent, ISpaceSummaryRoom} from "../components/structures/SpaceRoomDirectory"; import RoomViewStore from "./RoomViewStore"; -type SpaceKey = string | symbol; - interface IState {} const ACTIVE_SPACE_LS_KEY = "mx_active_space"; -export const HOME_SPACE = Symbol("home-space"); export const SUGGESTED_ROOMS = Symbol("suggested-rooms"); export const UPDATE_TOP_LEVEL_SPACES = Symbol("top-level-spaces"); export const UPDATE_INVITED_SPACES = Symbol("invited-spaces"); export const UPDATE_SELECTED_SPACE = Symbol("selected-space"); -// Space Room ID/HOME_SPACE will be emitted when a Space's children change +// Space Room ID will be emitted when a Space's children change const MAX_SUGGESTED_ROOMS = 20; -const getSpaceContextKey = (space?: Room) => `mx_space_context_${space?.roomId || "home_space"}`; +const getSpaceContextKey = (space?: Room) => `mx_space_context_${space?.roomId || "ALL_ROOMS"}`; const partitionSpacesAndRooms = (arr: Room[]): [Room[], Room[]] => { // [spaces, rooms] return arr.reduce((result, room: Room) => { @@ -83,15 +78,13 @@ export class SpaceStoreClass extends AsyncStoreWithClient { // The spaces representing the roots of the various tree-like hierarchies private rootSpaces: Room[] = []; - // The list of rooms not present in any currently joined spaces - private orphanedRooms = new Set(); // Map from room ID to set of spaces which list it as a child private parentMap = new EnhancedMap>(); - // Map from space key to SpaceNotificationState instance representing that space - private notificationStateMap = new Map(); + // Map from spaceId to SpaceNotificationState instance representing that space + private notificationStateMap = new Map(); // Map from space key to Set of room IDs that should be shown as part of that space's filter - private spaceFilteredRooms = new Map>(); - // The space currently selected in the Space Panel - if null then `Home` is selected + private spaceFilteredRooms = new Map>(); + // The space currently selected in the Space Panel - if null then All Rooms is selected private _activeSpace?: Room = null; private _suggestedRooms: ISpaceSummaryRoom[] = []; private _invitedSpaces = new Set(); @@ -227,7 +220,10 @@ export class SpaceStoreClass extends AsyncStoreWithClient { } public getSpaceFilteredRoomIds = (space: Room | null): Set => { - return this.spaceFilteredRooms.get(space?.roomId || HOME_SPACE) || new Set(); + if (!space) { + return new Set(this.matrixClient.getVisibleRooms().map(r => r.roomId)); + } + return this.spaceFilteredRooms.get(space.roomId) || new Set(); }; private rebuild = throttle(() => { @@ -258,7 +254,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient { }); }); - const [rootSpaces, orphanedRooms] = partitionSpacesAndRooms(Array.from(unseenChildren)); + const [rootSpaces] = partitionSpacesAndRooms(Array.from(unseenChildren)); // somewhat algorithm to handle full-cycles const detachedNodes = new Set(spaces); @@ -299,7 +295,6 @@ export class SpaceStoreClass extends AsyncStoreWithClient { // rootSpaces.push(space); // }); - this.orphanedRooms = new Set(orphanedRooms); this.rootSpaces = rootSpaces; this.parentMap = backrefs; @@ -320,25 +315,6 @@ export class SpaceStoreClass extends AsyncStoreWithClient { this.rebuild(); } - private showInHomeSpace = (room: Room) => { - if (room.isSpaceRoom()) return false; - return !this.parentMap.get(room.roomId)?.size // put all orphaned rooms in the Home Space - || DMRoomMap.shared().getUserIdForRoomId(room.roomId) // put all DMs in the Home Space - || RoomListStore.instance.getTagsForRoom(room).includes(DefaultTagID.Favourite) // show all favourites - }; - - // Update a given room due to its tag changing (e.g DM-ness or Fav-ness) - // This can only change whether it shows up in the HOME_SPACE or not - private onRoomUpdate = (room: Room) => { - if (this.showInHomeSpace(room)) { - this.spaceFilteredRooms.get(HOME_SPACE)?.add(room.roomId); - this.emit(HOME_SPACE); - } else if (!this.orphanedRooms.has(room.roomId)) { - this.spaceFilteredRooms.get(HOME_SPACE)?.delete(room.roomId); - this.emit(HOME_SPACE); - } - }; - private onSpaceMembersChange = (ev: MatrixEvent) => { // skip this update if we do not have a DM with this user if (DMRoomMap.shared().getDMRoomsForUserId(ev.getStateKey()).length < 1) return; @@ -352,16 +328,6 @@ export class SpaceStoreClass extends AsyncStoreWithClient { const oldFilteredRooms = this.spaceFilteredRooms; this.spaceFilteredRooms = new Map(); - // put all room invites in the Home Space - const invites = visibleRooms.filter(r => !r.isSpaceRoom() && r.getMyMembership() === "invite"); - this.spaceFilteredRooms.set(HOME_SPACE, new Set(invites.map(room => room.roomId))); - - visibleRooms.forEach(room => { - if (this.showInHomeSpace(room)) { - this.spaceFilteredRooms.get(HOME_SPACE).add(room.roomId); - } - }); - this.rootSpaces.forEach(s => { // traverse each space tree in DFS to build up the supersets as you go up, // reusing results from like subtrees. @@ -408,13 +374,8 @@ export class SpaceStoreClass extends AsyncStoreWithClient { // Update NotificationStates this.getNotificationState(s)?.setRooms(visibleRooms.filter(room => { if (roomIds.has(room.roomId)) { - // Don't aggregate notifications for DMs except in the Home Space - if (s !== HOME_SPACE) { - return !DMRoomMap.shared().getUserIdForRoomId(room.roomId) - || RoomListStore.instance.getTagsForRoom(room).includes(DefaultTagID.Favourite); - } - - return true; + return !DMRoomMap.shared().getUserIdForRoomId(room.roomId) + || RoomListStore.instance.getTagsForRoom(room).includes(DefaultTagID.Favourite); } return false; @@ -475,8 +436,6 @@ export class SpaceStoreClass extends AsyncStoreWithClient { // TODO confirm this after implementing parenting behaviour if (room.isSpaceRoom()) { this.onSpaceUpdate(); - } else { - this.onRoomUpdate(room); } this.emit(room.roomId); break; @@ -489,38 +448,8 @@ export class SpaceStoreClass extends AsyncStoreWithClient { } }; - private onRoomAccountData = (ev: MatrixEvent, room: Room, lastEvent?: MatrixEvent) => { - if (ev.getType() === EventType.Tag && !room.isSpaceRoom()) { - // If the room was in favourites and now isn't or the opposite then update its position in the trees - const oldTags = lastEvent?.getContent()?.tags || {}; - const newTags = ev.getContent()?.tags || {}; - if (!!oldTags[DefaultTagID.Favourite] !== !!newTags[DefaultTagID.Favourite]) { - this.onRoomUpdate(room); - } - } - } - - private onAccountData = (ev: MatrixEvent, lastEvent: MatrixEvent) => { - if (ev.getType() === EventType.Direct) { - const lastContent = lastEvent.getContent(); - const content = ev.getContent(); - - const diff = objectDiff>(lastContent, content); - // filter out keys which changed by reference only by checking whether the sets differ - const changed = diff.changed.filter(k => arrayHasDiff(lastContent[k], content[k])); - // DM tag changes, refresh relevant rooms - new Set([...diff.added, ...diff.removed, ...changed]).forEach(roomId => { - const room = this.matrixClient?.getRoom(roomId); - if (room) { - this.onRoomUpdate(room); - } - }); - } - }; - protected async reset() { this.rootSpaces = []; - this.orphanedRooms = new Set(); this.parentMap = new EnhancedMap(); this.notificationStateMap = new Map(); this.spaceFilteredRooms = new Map(); @@ -535,8 +464,6 @@ export class SpaceStoreClass extends AsyncStoreWithClient { this.matrixClient.removeListener("Room", this.onRoom); this.matrixClient.removeListener("Room.myMembership", this.onRoom); this.matrixClient.removeListener("RoomState.events", this.onRoomState); - this.matrixClient.removeListener("Room.accountData", this.onRoomAccountData); - this.matrixClient.removeListener("accountData", this.onAccountData); } await this.reset(); } @@ -546,8 +473,6 @@ export class SpaceStoreClass extends AsyncStoreWithClient { this.matrixClient.on("Room", this.onRoom); this.matrixClient.on("Room.myMembership", this.onRoom); this.matrixClient.on("RoomState.events", this.onRoomState); - this.matrixClient.on("Room.accountData", this.onRoomAccountData); - this.matrixClient.on("accountData", this.onAccountData); await this.onSpaceUpdate(); // trigger an initial update @@ -602,7 +527,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient { } } - public getNotificationState(key: SpaceKey): SpaceNotificationState { + public getNotificationState(key: string): SpaceNotificationState { if (this.notificationStateMap.has(key)) { return this.notificationStateMap.get(key); } diff --git a/src/stores/room-list/RoomListStore.ts b/src/stores/room-list/RoomListStore.ts index 6e9216423a..caab46a0c2 100644 --- a/src/stores/room-list/RoomListStore.ts +++ b/src/stores/room-list/RoomListStore.ts @@ -601,11 +601,7 @@ export class RoomListStoreClass extends AsyncStoreWithClient { let rooms = this.matrixClient.getVisibleRooms().filter(r => VisibilityProvider.instance.isRoomVisible(r)); - // if spaces are enabled only consider the prefilter conditions when there are no runtime conditions - // for the search all spaces feature - if (this.prefilterConditions.length > 0 - && (!SettingsStore.getValue("feature_spaces") || !this.filterConditions.length) - ) { + if (this.prefilterConditions.length > 0) { rooms = rooms.filter(r => { for (const filter of this.prefilterConditions) { if (!filter.isVisible(r)) { @@ -679,10 +675,6 @@ export class RoomListStoreClass extends AsyncStoreWithClient { if (this.algorithm) { this.algorithm.addFilterCondition(filter); } - // Runtime filters with spaces disable prefiltering for the search all spaces effect - if (SettingsStore.getValue("feature_spaces")) { - promise = this.recalculatePrefiltering(); - } } promise.then(() => this.updateFn.trigger()); } @@ -706,10 +698,6 @@ export class RoomListStoreClass extends AsyncStoreWithClient { if (this.algorithm) { this.algorithm.removeFilterCondition(filter); - // Runtime filters with spaces disable prefiltering for the search all spaces effect - if (SettingsStore.getValue("feature_spaces")) { - promise = this.recalculatePrefiltering(); - } } } idx = this.prefilterConditions.indexOf(filter); diff --git a/src/stores/room-list/SpaceWatcher.ts b/src/stores/room-list/SpaceWatcher.ts index 13e1d83901..0b1b78bc75 100644 --- a/src/stores/room-list/SpaceWatcher.ts +++ b/src/stores/room-list/SpaceWatcher.ts @@ -24,26 +24,34 @@ import SpaceStore, { UPDATE_SELECTED_SPACE } from "../SpaceStore"; * Watches for changes in spaces to manage the filter on the provided RoomListStore */ export class SpaceWatcher { - private filter = new SpaceFilterCondition(); + private filter: SpaceFilterCondition; private activeSpace: Room = SpaceStore.instance.activeSpace; constructor(private store: RoomListStoreClass) { - this.updateFilter(); // get the filter into a consistent state - store.addFilter(this.filter); SpaceStore.instance.on(UPDATE_SELECTED_SPACE, this.onSelectedSpaceUpdated); } - private onSelectedSpaceUpdated = (activeSpace: Room) => { + private onSelectedSpaceUpdated = (activeSpace?: Room) => { this.activeSpace = activeSpace; - this.updateFilter(); + + if (this.filter) { + if (activeSpace) { + this.updateFilter(); + } else { + this.store.removeFilter(this.filter); + this.filter = null; + } + } else if (activeSpace) { + this.filter = new SpaceFilterCondition(); + this.updateFilter(); + this.store.addFilter(this.filter); + } }; private updateFilter = () => { - if (this.activeSpace) { - SpaceStore.instance.traverseSpace(this.activeSpace.roomId, roomId => { - this.store.matrixClient?.getRoom(roomId)?.loadMembersIfNeeded(); - }); - } + SpaceStore.instance.traverseSpace(this.activeSpace.roomId, roomId => { + this.store.matrixClient?.getRoom(roomId)?.loadMembersIfNeeded(); + }); this.filter.updateSpace(this.activeSpace); }; } diff --git a/src/stores/room-list/filters/SpaceFilterCondition.ts b/src/stores/room-list/filters/SpaceFilterCondition.ts index 43bdcb3879..6a06bee0d8 100644 --- a/src/stores/room-list/filters/SpaceFilterCondition.ts +++ b/src/stores/room-list/filters/SpaceFilterCondition.ts @@ -19,7 +19,7 @@ import { Room } from "matrix-js-sdk/src/models/room"; import { FILTER_CHANGED, FilterKind, IFilterCondition } from "./IFilterCondition"; import { IDestroyable } from "../../../utils/IDestroyable"; -import SpaceStore, {HOME_SPACE} from "../../SpaceStore"; +import SpaceStore from "../../SpaceStore"; import { setHasDiff } from "../../../utils/sets"; /** @@ -55,10 +55,12 @@ export class SpaceFilterCondition extends EventEmitter implements IFilterConditi } }; - private getSpaceEventKey = (space: Room | null) => space ? space.roomId : HOME_SPACE; + private getSpaceEventKey = (space: Room) => space.roomId; public updateSpace(space: Room) { - SpaceStore.instance.off(this.getSpaceEventKey(this.space), this.onStoreUpdate); + if (this.space) { + SpaceStore.instance.off(this.getSpaceEventKey(this.space), this.onStoreUpdate); + } SpaceStore.instance.on(this.getSpaceEventKey(this.space = space), this.onStoreUpdate); this.onStoreUpdate(); // initial update from the change to the space } From 08d6da5f2e37564b782654d0ef52aadcb9c7b13a Mon Sep 17 00:00:00 2001 From: Michael Sasser Date: Tue, 4 May 2021 16:31:07 +0000 Subject: [PATCH 0222/1449] Translated using Weblate (German) Currently translated at 99.2% (2910 of 2931 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 7f0d6a2747..a185f34d68 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -3282,5 +3282,7 @@ "If you do, please note that none of your messages will be deleted, but the search experience might be degraded for a few moments whilst the index is recreated": "Falls du es wirklich willst: Es werden keine Nachrichten gelöscht. Außerdem wird die Suche, während der Index erstellt wird, etwas langsamer sein", "%(count)s members including %(commaSeparatedMembers)s|other": "%(count)s Mitglieder inklusive %(commaSeparatedMembers)s", "Including %(commaSeparatedMembers)s": "Inklusive%(commaSeparatedMembers)s", - "Consulting with %(transferTarget)s. Transfer to %(transferee)s": "Beratung mit %(transferTarget)s. Übertragung zu %(transferee)s" + "Consulting with %(transferTarget)s. Transfer to %(transferee)s": "Beratung mit %(transferTarget)s. Übertragung zu %(transferee)s", + "Play": "Abspielen", + "Pause": "Pause" } From 74bc4b15a5e57d29611d1177327e73d70dbed7f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 4 May 2021 15:27:19 +0000 Subject: [PATCH 0223/1449] Translated using Weblate (Czech) Currently translated at 99.8% (2928 of 2931 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 | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/cs.json b/src/i18n/strings/cs.json index 8633146420..38c4d5bd64 100644 --- a/src/i18n/strings/cs.json +++ b/src/i18n/strings/cs.json @@ -3201,7 +3201,7 @@ "Please choose a strong password": "Vyberte silné heslo", "What are some things you want to discuss in %(spaceName)s?": "O kterých tématech chcete diskutovat v %(spaceName)s?", "Let's create a room for each of them.": "Vytvořme pro každé z nich místnost.", - "Use another login": "Použijte jiné přihlašovací jméno", + "Use another login": "Použít jinou relaci", "Without verifying, you won’t have access to all your messages and may appear as untrusted to others.": "Bez ověření nebudete mít přístup ke všem svým zprávám a ostatním se můžete zobrazit jako nedůvěryhodný.", "You are the only person here. If you leave, no one will be able to join in the future, including you.": "Jste zde jediná osoba. Pokud odejdete, nikdo se v budoucnu nebude moci připojit, včetně vás.", "If you reset everything, you will restart with no trusted sessions, no trusted users, and might not be able to see past messages.": "Pokud vše resetujete, začnete bez důvěryhodných relací, bez důvěryhodných uživatelů a možná nebudete moci zobrazit minulé zprávy.", @@ -3225,5 +3225,13 @@ "Including %(commaSeparatedMembers)s": "Včetně %(commaSeparatedMembers)s", "View all %(count)s members|one": "Zobrazit jednoho člena", "View all %(count)s members|other": "Zobrazit všech %(count)s členů", - "Failed to send": "Odeslání se nezdařilo" + "Failed to send": "Odeslání se nezdařilo", + "What do you want to organise?": "Co si přejete organizovat?", + "Filter all spaces": "Filtrovat všechny prostory", + "Delete recording": "Smazat zvukovou zprávu", + "Stop the recording": "Zastavit nahrávání", + "%(count)s results in all spaces|one": "%(count)s výsledek ve všech prostorech", + "%(count)s results in all spaces|other": "%(count)s výsledků ve všech prostorech", + "Play": "Přehrát", + "Pause": "Pozastavit" } From 1036d4d0a59bcfa39a820c80553a401c131b265a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Tue, 4 May 2021 15:25:11 +0000 Subject: [PATCH 0224/1449] Translated using Weblate (Estonian) Currently translated at 100.0% (2931 of 2931 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/et/ --- src/i18n/strings/et.json | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index 56f456b6e4..fc42ad73dd 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -3286,5 +3286,16 @@ "Including %(commaSeparatedMembers)s": "Sealhulgas %(commaSeparatedMembers)s", "View all %(count)s members|one": "Vaata üht liiget", "View all %(count)s members|other": "Vaata kõiki %(count)s liiget", - "Failed to send": "Saatmine ei õnnestunud" + "Failed to send": "Saatmine ei õnnestunud", + "Enter your Security Phrase a second time to confirm it.": "Kinnitamiseks palun sisesta turvafraas teist korda.", + "Pick rooms or conversations to add. This is just a space for you, no one will be informed. You can add more later.": "Lisamiseks vali vestlusi ja jututubasid. Hetkel on see kogukonnakeskus vaid sinu jaoks ja esialgu keegi ei saa sellest teada. Teisi saad liituma kutsuda hiljem.", + "What do you want to organise?": "Mida sa soovid ette võtta?", + "Filter all spaces": "Otsi kõikides kogukonnakeskustest", + "Delete recording": "Kustuta salvestus", + "Stop the recording": "Lõpeta salvestamine", + "%(count)s results in all spaces|one": "%(count)s tulemus kõikides kogukonnakeskustes", + "%(count)s results in all spaces|other": "%(count)s tulemust kõikides kogukonnakeskustes", + "You have no ignored users.": "Sa ei ole veel kedagi eiranud.", + "Play": "Esita", + "Pause": "Peata" } From 273851d0bd1722e6e30d5901638ec0461eaeb7bd Mon Sep 17 00:00:00 2001 From: Marek Date: Tue, 4 May 2021 19:17:26 +0000 Subject: [PATCH 0225/1449] Translated using Weblate (German) Currently translated at 99.5% (2919 of 2931 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index a185f34d68..bdb056aa88 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -2951,7 +2951,7 @@ "Call failed because no webcam or microphone could not be accessed. Check that:": "Der Anruf ist fehlgeschlagen weil nicht auf das Mikrofon oder die Webcam zugegriffen werden konnte. Stelle sicher, dass:", "Unable to access webcam / microphone": "Auf Webcam / Mikrofon konnte nicht zugegriffen werden", "Unable to access microphone": "Es konnte nicht auf das Mikrofon zugegriffen werden", - "Host account on": "Benutzer*innenkonto betreiben an", + "Host account on": "Konto betreiben an", "Hold": "Halten", "Resume": "Fortsetzen", "We call the places where you can host your account ‘homeservers’.": "Den Ort, an dem du dein Konto betreibst, nennen wir „Heimserver“.", @@ -3284,5 +3284,14 @@ "Including %(commaSeparatedMembers)s": "Inklusive%(commaSeparatedMembers)s", "Consulting with %(transferTarget)s. Transfer to %(transferee)s": "Beratung mit %(transferTarget)s. Übertragung zu %(transferee)s", "Play": "Abspielen", - "Pause": "Pause" + "Pause": "Pause", + "What do you want to organise?": "Was möchtenst Du organisieren?", + "Enter your Security Phrase a second time to confirm it.": "Gib dein Kennwort ein zweites Mal zur Bestätigung ein.", + "Pick rooms or conversations to add. This is just a space for you, no one will be informed. You can add more later.": "Wähle Räume oder Konversationen die Du hinzufügen möchtest. Dieser Bereich ist nur für Dich, niemand wird informiert. Du kannst später mehr hinzufügen.", + "Filter all spaces": "Alle Bereiche filtern", + "Delete recording": "Aufnahme löschen", + "Stop the recording": "Aufnahme stoppen", + "%(count)s results in all spaces|one": "%(count)s Ergebnis in allen Bereichen", + "%(count)s results in all spaces|other": "%(count)s Ergebnisse in allen Bereichen", + "You have no ignored users.": "Du ignorierst keine Benutzer." } From e627fd53c1fd5dd17cf1764c314277f25677b125 Mon Sep 17 00:00:00 2001 From: libexus Date: Tue, 4 May 2021 19:15:53 +0000 Subject: [PATCH 0226/1449] Translated using Weblate (German) Currently translated at 99.5% (2919 of 2931 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index bdb056aa88..a34c8b4f6d 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -88,7 +88,7 @@ "Unban": "Verbannung aufheben", "unknown error code": "Unbekannter Fehlercode", "Upload avatar": "Profilbild hochladen", - "Upload file": "Datei hochladen", + "Upload file": "Datei senden", "Users": "Benutzer", "Verification Pending": "Verifizierung ausstehend", "Video call": "Videoanruf", @@ -114,7 +114,7 @@ "VoIP is unsupported": "VoIP wird nicht unterstützt", "You are already in a call.": "Du bist bereits in einem Gespräch.", "You cannot place a call with yourself.": "Du kannst keinen Anruf mit dir selbst starten.", - "You cannot place VoIP calls in this browser.": "VoIP-Gespräche werden von diesem Browser nicht unterstützt.", + "You cannot place VoIP calls in this browser.": "Anrufe werden von diesem Browser nicht unterstützt.", "Your email address does not appear to be associated with a Matrix ID on this Homeserver.": "Deine E-Mail-Adresse scheint nicht mit einer Matrix-ID auf diesem Heimserver verbunden zu sein.", "Sun": "So", "Mon": "Mo", From e48ad31e4e619daca51094418e2138e107fe5ae3 Mon Sep 17 00:00:00 2001 From: Michael Sasser Date: Tue, 4 May 2021 19:10:18 +0000 Subject: [PATCH 0227/1449] Translated using Weblate (German) Currently translated at 99.5% (2919 of 2931 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index a34c8b4f6d..33bafb6284 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -1634,7 +1634,7 @@ "Show rooms with unread notifications first": "Räume mit ungelesenen Benachrichtigungen zuerst zeigen", "Show shortcuts to recently viewed rooms above the room list": "Kürzlich besuchte Räume anzeigen", "Use Single Sign On to continue": "Einmalanmeldung zum Fortfahren nutzen", - "Confirm adding this email address by using Single Sign On to prove your identity.": "Bestätige die hinzugefügte E-Mail-Adresse mit der Einmalanmeldung, um deine Identität nachzuweisen.", + "Confirm adding this email address by using Single Sign On to prove your identity.": "Bestätige das Hinzufügen dieser E-Mail-Adresse durch Single Sign-on, um deine Identität nachzuweisen.", "Single Sign On": "Einmalanmeldung", "Confirm adding email": "Hinzugefügte E-Mail-Addresse bestätigen", "Confirm adding this phone number by using Single Sign On to prove your identity.": "Bestätige die hinzugefügte Telefonnummer, indem du deine Identität mittels der Einmalanmeldung nachweist.", From 69604480fd9a8c439f04b8f4b614e50e36895499 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 4 May 2021 21:17:15 +0100 Subject: [PATCH 0228/1449] Add comment --- src/stores/SpaceStore.tsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/stores/SpaceStore.tsx b/src/stores/SpaceStore.tsx index 8e86253f75..43822007c9 100644 --- a/src/stores/SpaceStore.tsx +++ b/src/stores/SpaceStore.tsx @@ -112,6 +112,13 @@ export class SpaceStoreClass extends AsyncStoreWithClient { return this._suggestedRooms; } + /** + * Sets the active space, updates room list filters, + * optionally switches the user's room back to where they were when they last viewed that space. + * @param space which space to switch to. + * @param contextSwitch whether to switch the user's context, + * should not be done when the space switch is done implicitly due to another event like switching room. + */ public async setActiveSpace(space: Room | null, contextSwitch = true) { if (space === this.activeSpace || (space && !space?.isSpaceRoom())) return; @@ -305,7 +312,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient { // if the currently selected space no longer exists, remove its selection if (this._activeSpace && detachedNodes.has(this._activeSpace)) { - this.setActiveSpace(null); + this.setActiveSpace(null, false); } this.onRoomsUpdate(); // TODO only do this if a change has happened @@ -593,7 +600,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient { } case "after_leave_room": if (this._activeSpace && payload.room_id === this._activeSpace.roomId) { - this.setActiveSpace(null); + this.setActiveSpace(null, false); } break; } From a94c1a90c15c5fb29c31869b3a15ddde31ece576 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 4 May 2021 20:45:15 -0600 Subject: [PATCH 0229/1449] Update colours and sizing for voice messages Fixes https://github.com/vector-im/element-web/issues/17162 --- .../views/rooms/_VoiceRecordComposerTile.scss | 10 ++++++---- .../voice_messages/_PlaybackContainer.scss | 15 +++++++-------- res/themes/dark/css/_dark.scss | 10 +++++----- res/themes/legacy-dark/css/_legacy-dark.scss | 8 ++++---- .../legacy-light/css/_legacy-light.scss | 12 ++++++------ res/themes/light/css/_light.scss | 19 +++++++++++-------- .../voice_messages/LiveRecordingWaveform.tsx | 7 +++---- src/voice/Playback.ts | 2 +- src/voice/VoiceRecording.ts | 2 ++ 9 files changed, 45 insertions(+), 40 deletions(-) diff --git a/res/css/views/rooms/_VoiceRecordComposerTile.scss b/res/css/views/rooms/_VoiceRecordComposerTile.scss index 15daf81672..c0775b8371 100644 --- a/res/css/views/rooms/_VoiceRecordComposerTile.scss +++ b/res/css/views/rooms/_VoiceRecordComposerTile.scss @@ -39,7 +39,7 @@ limitations under the License. width: 14px; // w&h are size of icon height: 18px; vertical-align: middle; - margin-right: 7px; // distance from left edge of waveform container (container has some margin too) + margin-right: 11px; // distance from left edge of waveform container (container has some margin too) background-color: $voice-record-icon-color; mask-repeat: no-repeat; mask-size: contain; @@ -55,7 +55,9 @@ limitations under the License. position: relative; // important for the live circle &.mx_VoiceRecordComposerTile_recording { - padding-left: 16px; // +10px for the live circle, +6px for regular padding + // We are putting the circle in this padding, so we need +10px from the regular + // padding on the left side. + padding-left: 22px; &::before { animation: recording-pulse 2s infinite; @@ -65,8 +67,8 @@ limitations under the License. width: 10px; height: 10px; position: absolute; - left: 8px; - top: 16px; // vertically center + left: 12px; // 12px from the left edge for container padding + top: 18px; // vertically center (middle align with clock) border-radius: 10px; } } diff --git a/res/css/views/voice_messages/_PlaybackContainer.scss b/res/css/views/voice_messages/_PlaybackContainer.scss index 49bd81ef81..64e8f445e1 100644 --- a/res/css/views/voice_messages/_PlaybackContainer.scss +++ b/res/css/views/voice_messages/_PlaybackContainer.scss @@ -19,8 +19,9 @@ limitations under the License. // Container for live recording and playback controls .mx_VoiceMessagePrimaryContainer { - padding: 6px; // makes us 4px taller than the send/stop button - padding-right: 5px; // there's 1px from the waveform itself, so account for that + // 7px top and bottom for visual design. 12px left & right, but the waveform (right) + // has a 1px padding on it that we want to account for. + padding: 7px 12px 7px 11px; background-color: $voice-record-waveform-bg-color; border-radius: 12px; @@ -30,11 +31,9 @@ limitations under the License. color: $voice-record-waveform-fg-color; font-size: $font-14px; + line-height: $font-24px; .mx_Waveform { - // We want the bars to be 2px shorter than the play/pause button in the waveform control - height: 28px; // default is 30px, so we're subtracting the 2px border off the bars - .mx_Waveform_bar { background-color: $voice-record-waveform-incomplete-fg-color; @@ -47,8 +46,8 @@ limitations under the License. } .mx_Clock { - padding-right: 4px; // isolate from waveform - padding-left: 8px; // isolate from live circle - width: 40px; // we're not using a monospace font, so fake it + width: 42px; // we're not using a monospace font, so fake it + padding-right: 6px; // with the fixed width this ends up as a visual 8px most of the time, as intended. + padding-left: 8px; // isolate from recording circle / play control } } diff --git a/res/themes/dark/css/_dark.scss b/res/themes/dark/css/_dark.scss index cfdda41619..334bf581f3 100644 --- a/res/themes/dark/css/_dark.scss +++ b/res/themes/dark/css/_dark.scss @@ -42,13 +42,13 @@ $preview-bar-bg-color: $header-panel-bg-color; $groupFilterPanel-bg-color: rgba(38, 39, 43, 0.82); $inverted-bg-color: $base-color; -$voice-record-stop-border-color: #6F7882; // "Quarterly" +$voice-record-stop-border-color: #6F7882; // "Quartary" $voice-record-waveform-bg-color: #394049; // "Dark Tile" -$voice-record-waveform-fg-color: $tertiary-fg-color; -$voice-record-waveform-incomplete-fg-color: #5b646d; -$voice-record-icon-color: $tertiary-fg-color; +$voice-record-waveform-fg-color: $secondary-fg-color; +$voice-record-waveform-incomplete-fg-color: #6F7882; // "Quartary" +$voice-record-icon-color: #6F7882; // "Quartary" $voice-playback-button-bg-color: $tertiary-fg-color; -$voice-playback-button-fg-color: $bg-color; +$voice-playback-button-fg-color: #21262C; // "Separator" // used by AddressSelector $selected-color: $room-highlight-color; diff --git a/res/themes/legacy-dark/css/_legacy-dark.scss b/res/themes/legacy-dark/css/_legacy-dark.scss index 6413a99ce0..6a162bbda7 100644 --- a/res/themes/legacy-dark/css/_legacy-dark.scss +++ b/res/themes/legacy-dark/css/_legacy-dark.scss @@ -127,11 +127,11 @@ $groupFilterPanel-divider-color: $roomlist-header-color; // See non-legacy dark for variable information $voice-record-stop-border-color: #6F7882; $voice-record-waveform-bg-color: #394049; -$voice-record-waveform-fg-color: $tertiary-fg-color; -$voice-record-waveform-incomplete-fg-color: #5b646d; -$voice-record-icon-color: $tertiary-fg-color; +$voice-record-waveform-fg-color: $secondary-fg-color; +$voice-record-waveform-incomplete-fg-color: #6F7882; +$voice-record-icon-color: #6F7882; $voice-playback-button-bg-color: $tertiary-fg-color; -$voice-playback-button-fg-color: $bg-color; +$voice-playback-button-fg-color: #21262C; $roomtile-preview-color: #9e9e9e; $roomtile-default-badge-bg-color: #61708b; diff --git a/res/themes/legacy-light/css/_legacy-light.scss b/res/themes/legacy-light/css/_legacy-light.scss index 2151724071..cc0f54853e 100644 --- a/res/themes/legacy-light/css/_legacy-light.scss +++ b/res/themes/legacy-light/css/_legacy-light.scss @@ -192,15 +192,15 @@ $roomsublist-skeleton-ui-bg: linear-gradient(180deg, #ffffff 0%, #ffffff00 100%) $groupFilterPanel-divider-color: $roomlist-header-color; // See non-legacy _light for variable information -$voice-record-stop-border-color: #E3E8F0; $voice-record-stop-symbol-color: #ff4b55; -$voice-record-waveform-bg-color: #E3E8F0; -$voice-record-waveform-fg-color: $muted-fg-color; -$voice-record-waveform-incomplete-fg-color: #C1C6CD; $voice-record-live-circle-color: #ff4b55; -$voice-record-icon-color: $muted-fg-color; +$voice-record-stop-border-color: #E3E8F0; +$voice-record-waveform-bg-color: #E3E8F0; +$voice-record-waveform-fg-color: $secondary-fg-color; +$voice-record-waveform-incomplete-fg-color: #C1C6CD; +$voice-record-icon-color: $tertiary-fg-color; $voice-playback-button-bg-color: $primary-bg-color; -$voice-playback-button-fg-color: $muted-fg-color; +$voice-playback-button-fg-color: $secondary-fg-color; $roomtile-preview-color: #9e9e9e; $roomtile-default-badge-bg-color: #61708b; diff --git a/res/themes/light/css/_light.scss b/res/themes/light/css/_light.scss index 1763fcdd48..193b7f816c 100644 --- a/res/themes/light/css/_light.scss +++ b/res/themes/light/css/_light.scss @@ -182,15 +182,18 @@ $roomsublist-skeleton-ui-bg: linear-gradient(180deg, #ffffff 0%, #ffffff00 100%) $groupFilterPanel-divider-color: $roomlist-header-color; -$voice-record-stop-border-color: #E3E8F0; -$voice-record-stop-symbol-color: #ff4b55; // $warning-color, but without letting people change it in themes -$voice-record-waveform-bg-color: #E3E8F0; -$voice-record-waveform-fg-color: $muted-fg-color; -$voice-record-waveform-incomplete-fg-color: #C1C6CD; -$voice-record-live-circle-color: #ff4b55; // $warning-color, but without letting people change it in themes -$voice-record-icon-color: $muted-fg-color; +// These two don't change between themes. They are the $warning-color, but we don't +// want custom themes to affect them by accident. +$voice-record-stop-symbol-color: #ff4b55; +$voice-record-live-circle-color: #ff4b55; + +$voice-record-stop-border-color: #E3E8F0; // "Separator" +$voice-record-waveform-bg-color: #E3E8F0; // "Separator" +$voice-record-waveform-fg-color: $secondary-fg-color; +$voice-record-waveform-incomplete-fg-color: #C1C6CD; // "Quartary" +$voice-record-icon-color: $tertiary-fg-color; $voice-playback-button-bg-color: $primary-bg-color; -$voice-playback-button-fg-color: $muted-fg-color; +$voice-playback-button-fg-color: $secondary-fg-color; $roomtile-preview-color: $secondary-fg-color; $roomtile-default-badge-bg-color: #61708b; diff --git a/src/components/views/voice_messages/LiveRecordingWaveform.tsx b/src/components/views/voice_messages/LiveRecordingWaveform.tsx index e7c34c9177..aab89f6ab1 100644 --- a/src/components/views/voice_messages/LiveRecordingWaveform.tsx +++ b/src/components/views/voice_messages/LiveRecordingWaveform.tsx @@ -15,12 +15,11 @@ limitations under the License. */ import React from "react"; -import {IRecordingUpdate, VoiceRecording} from "../../../voice/VoiceRecording"; +import {IRecordingUpdate, RECORDING_PLAYBACK_SAMPLES, VoiceRecording} from "../../../voice/VoiceRecording"; import {replaceableComponent} from "../../../utils/replaceableComponent"; import {arrayFastResample, arraySeed} from "../../../utils/arrays"; import {percentageOf} from "../../../utils/numbers"; import Waveform from "./Waveform"; -import {PLAYBACK_WAVEFORM_SAMPLES} from "../../../voice/Playback"; interface IProps { recorder: VoiceRecording; @@ -38,14 +37,14 @@ export default class LiveRecordingWaveform extends React.PureComponent { // The waveform and the downsample target are pretty close, so we should be fine to // do this, despite the docs on arrayFastResample. - const bars = arrayFastResample(Array.from(update.waveform), PLAYBACK_WAVEFORM_SAMPLES); + const bars = arrayFastResample(Array.from(update.waveform), RECORDING_PLAYBACK_SAMPLES); this.setState({ // The incoming data is between zero and one, but typically even screaming into a // microphone won't send you over 0.6, so we artificially adjust the gain for the diff --git a/src/voice/Playback.ts b/src/voice/Playback.ts index ca48680ebd..b2525c2719 100644 --- a/src/voice/Playback.ts +++ b/src/voice/Playback.ts @@ -29,7 +29,7 @@ export enum PlaybackState { Playing = "playing", // active progress through timeline } -export const PLAYBACK_WAVEFORM_SAMPLES = 35; +export const PLAYBACK_WAVEFORM_SAMPLES = 38; const DEFAULT_WAVEFORM = arraySeed(0, PLAYBACK_WAVEFORM_SAMPLES); export class Playback extends EventEmitter implements IDestroyable { diff --git a/src/voice/VoiceRecording.ts b/src/voice/VoiceRecording.ts index eb705200ca..62496ce3d9 100644 --- a/src/voice/VoiceRecording.ts +++ b/src/voice/VoiceRecording.ts @@ -33,6 +33,8 @@ const BITRATE = 24000; // 24kbps is pretty high quality for our use case in opus const TARGET_MAX_LENGTH = 120; // 2 minutes in seconds. Somewhat arbitrary, though longer == larger files. const TARGET_WARN_TIME_LEFT = 10; // 10 seconds, also somewhat arbitrary. +export const RECORDING_PLAYBACK_SAMPLES = 43; + export interface IRecordingUpdate { waveform: number[]; // floating points between 0 (low) and 1 (high). timeSeconds: number; // float From ed43d9257937b6e205dd939a60a453f1bd9fbefc Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 4 May 2021 20:55:35 -0600 Subject: [PATCH 0230/1449] Match designs more closely with +1 sample --- src/voice/Playback.ts | 2 +- src/voice/VoiceRecording.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/voice/Playback.ts b/src/voice/Playback.ts index b2525c2719..caa5241e1a 100644 --- a/src/voice/Playback.ts +++ b/src/voice/Playback.ts @@ -29,7 +29,7 @@ export enum PlaybackState { Playing = "playing", // active progress through timeline } -export const PLAYBACK_WAVEFORM_SAMPLES = 38; +export const PLAYBACK_WAVEFORM_SAMPLES = 39; const DEFAULT_WAVEFORM = arraySeed(0, PLAYBACK_WAVEFORM_SAMPLES); export class Playback extends EventEmitter implements IDestroyable { diff --git a/src/voice/VoiceRecording.ts b/src/voice/VoiceRecording.ts index 62496ce3d9..c4a0a78ce5 100644 --- a/src/voice/VoiceRecording.ts +++ b/src/voice/VoiceRecording.ts @@ -33,7 +33,7 @@ const BITRATE = 24000; // 24kbps is pretty high quality for our use case in opus const TARGET_MAX_LENGTH = 120; // 2 minutes in seconds. Somewhat arbitrary, though longer == larger files. const TARGET_WARN_TIME_LEFT = 10; // 10 seconds, also somewhat arbitrary. -export const RECORDING_PLAYBACK_SAMPLES = 43; +export const RECORDING_PLAYBACK_SAMPLES = 44; export interface IRecordingUpdate { waveform: number[]; // floating points between 0 (low) and 1 (high). From b0cb996cacb90a6b1812f2eb8cc2ee48c952f78a Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 4 May 2021 21:13:37 -0600 Subject: [PATCH 0231/1449] Update visual style of plain files in the timeline --- res/css/views/messages/_MFileBody.scss | 8 ++++---- res/themes/dark/css/_dark.scss | 7 ++++--- res/themes/legacy-dark/css/_legacy-dark.scss | 7 ++++--- res/themes/legacy-light/css/_legacy-light.scss | 12 +++++++++--- res/themes/light/css/_light.scss | 7 ++++--- 5 files changed, 25 insertions(+), 16 deletions(-) diff --git a/res/css/views/messages/_MFileBody.scss b/res/css/views/messages/_MFileBody.scss index b45126acf8..c215d69ec2 100644 --- a/res/css/views/messages/_MFileBody.scss +++ b/res/css/views/messages/_MFileBody.scss @@ -61,9 +61,9 @@ limitations under the License. .mx_MFileBody_info { background-color: $message-body-panel-bg-color; - border-radius: 4px; - width: 270px; - padding: 8px; + border-radius: 12px; + width: 243px; // same width as a playable voice message, accounting for padding + padding: 6px 12px; color: $message-body-panel-fg-color; .mx_MFileBody_info_icon { @@ -82,7 +82,7 @@ limitations under the License. mask-position: center; mask-size: cover; mask-image: url('$(res)/img/element-icons/room/composer/attach.svg'); - background-color: $message-body-panel-fg-color; + background-color: $message-body-panel-icon-fg-color; width: 13px; height: 15px; diff --git a/res/themes/dark/css/_dark.scss b/res/themes/dark/css/_dark.scss index cfdda41619..d9fa61d055 100644 --- a/res/themes/dark/css/_dark.scss +++ b/res/themes/dark/css/_dark.scss @@ -213,9 +213,10 @@ $breadcrumb-placeholder-bg-color: #272c35; $user-tile-hover-bg-color: $header-panel-bg-color; -$message-body-panel-bg-color: #21262c82; -$message-body-panel-icon-bg-color: #8e99a4; -$message-body-panel-fg-color: $primary-fg-color; +$message-body-panel-fg-color: $secondary-fg-color; +$message-body-panel-bg-color: $voice-record-waveform-bg-color; +$message-body-panel-icon-fg-color: $primary-bg-color; +$message-body-panel-icon-bg-color: $tertiary-fg-color; // Appearance tab colors $appearance-tab-border-color: $room-highlight-color; diff --git a/res/themes/legacy-dark/css/_legacy-dark.scss b/res/themes/legacy-dark/css/_legacy-dark.scss index 6413a99ce0..38bc1803a4 100644 --- a/res/themes/legacy-dark/css/_legacy-dark.scss +++ b/res/themes/legacy-dark/css/_legacy-dark.scss @@ -209,9 +209,10 @@ $breadcrumb-placeholder-bg-color: #272c35; $user-tile-hover-bg-color: $header-panel-bg-color; -$message-body-panel-bg-color: #21262c82; -$message-body-panel-icon-bg-color: #8e99a4; -$message-body-panel-fg-color: $primary-fg-color; +$message-body-panel-fg-color: $secondary-fg-color; +$message-body-panel-bg-color: $voice-record-waveform-bg-color; +$message-body-panel-icon-fg-color: $primary-bg-color; +$message-body-panel-icon-bg-color: $secondary-fg-color; // Appearance tab colors $appearance-tab-border-color: $room-highlight-color; diff --git a/res/themes/legacy-light/css/_legacy-light.scss b/res/themes/legacy-light/css/_legacy-light.scss index 2151724071..3eefc6c0b8 100644 --- a/res/themes/legacy-light/css/_legacy-light.scss +++ b/res/themes/legacy-light/css/_legacy-light.scss @@ -202,6 +202,11 @@ $voice-record-icon-color: $muted-fg-color; $voice-playback-button-bg-color: $primary-bg-color; $voice-playback-button-fg-color: $muted-fg-color; +$fileinfo-bg-color: $voice-record-waveform-bg-color; +$fileinfo-fg-color: $secondary-fg-color; +$fileinfo-icon-bg-color: $primary-bg-color; +$fileinfo-icon-fg-color: $secondary-fg-color; + $roomtile-preview-color: #9e9e9e; $roomtile-default-badge-bg-color: #61708b; $roomtile-selected-bg-color: #fff; @@ -334,9 +339,10 @@ $breadcrumb-placeholder-bg-color: #e8eef5; $user-tile-hover-bg-color: $header-panel-bg-color; -$message-body-panel-bg-color: #e3e8f082; -$message-body-panel-icon-bg-color: #ffffff; -$message-body-panel-fg-color: $muted-fg-color; +$message-body-panel-fg-color: $secondary-fg-color; +$message-body-panel-bg-color: $voice-record-waveform-bg-color; +$message-body-panel-icon-fg-color: $secondary-fg-color; +$message-body-panel-icon-bg-color: $primary-bg-color; // FontSlider colors $appearance-tab-border-color: $input-darker-bg-color; diff --git a/res/themes/light/css/_light.scss b/res/themes/light/css/_light.scss index 1763fcdd48..036fed2d3a 100644 --- a/res/themes/light/css/_light.scss +++ b/res/themes/light/css/_light.scss @@ -331,9 +331,10 @@ $breadcrumb-placeholder-bg-color: #e8eef5; $user-tile-hover-bg-color: $header-panel-bg-color; -$message-body-panel-bg-color: #e3e8f082; -$message-body-panel-icon-bg-color: #ffffff; -$message-body-panel-fg-color: $muted-fg-color; +$message-body-panel-fg-color: $secondary-fg-color; +$message-body-panel-bg-color: $voice-record-waveform-bg-color; +$message-body-panel-icon-fg-color: $secondary-fg-color; +$message-body-panel-icon-bg-color: $primary-bg-color; // FontSlider colors $appearance-tab-border-color: $input-darker-bg-color; From ccdc9fbef6af3e3fd674517bde732168b3e7cfa8 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 4 May 2021 21:15:22 -0600 Subject: [PATCH 0232/1449] Fix issue where composer styles were being applied to the timeline --- res/css/views/rooms/_VoiceRecordComposerTile.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/css/views/rooms/_VoiceRecordComposerTile.scss b/res/css/views/rooms/_VoiceRecordComposerTile.scss index c0775b8371..b87211a847 100644 --- a/res/css/views/rooms/_VoiceRecordComposerTile.scss +++ b/res/css/views/rooms/_VoiceRecordComposerTile.scss @@ -46,7 +46,7 @@ limitations under the License. mask-image: url('$(res)/img/element-icons/trashcan.svg'); } -.mx_VoiceMessagePrimaryContainer { +.mx_VoiceRecordComposerTile_recording.mx_VoiceMessagePrimaryContainer { // Note: remaining class properties are in the PlayerContainer CSS. margin: 6px; // force the composer area to put a gutter around us From 791f39abcc3c72841fc5dc3ac385ea71764f65a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 5 May 2021 08:31:07 +0200 Subject: [PATCH 0233/1449] Initial support for persistent collapsed states MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/spaces/SpaceTreeLevel.tsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/components/views/spaces/SpaceTreeLevel.tsx b/src/components/views/spaces/SpaceTreeLevel.tsx index 6825d84013..6e00eac725 100644 --- a/src/components/views/spaces/SpaceTreeLevel.tsx +++ b/src/components/views/spaces/SpaceTreeLevel.tsx @@ -48,6 +48,8 @@ import {EventType} from "matrix-js-sdk/src/@types/event"; import {StaticNotificationState} from "../../../stores/notifications/StaticNotificationState"; import {NotificationColor} from "../../../stores/notifications/NotificationColor"; +const getSpaceCollapsedKey = (space: Room) => `mx_space_collapsed_${space.roomId}`; + interface IItemProps { space?: Room; activeSpaces: Room[]; @@ -68,8 +70,12 @@ export class SpaceItem extends React.PureComponent { constructor(props) { super(props); + // XXX: localStorage doesn't allow booleans + // default to collapsed for root items + const collapsed = localStorage.getItem(getSpaceCollapsedKey(props.space)) === "true" || !props.isNested; + this.state = { - collapsed: !props.isNested, // default to collapsed for root items + collapsed: collapsed, contextMenuPosition: null, }; } @@ -78,7 +84,10 @@ export class SpaceItem extends React.PureComponent { if (this.props.onExpand && this.state.collapsed) { this.props.onExpand(); } - this.setState({collapsed: !this.state.collapsed}); + const newCollapsedState = !this.state.collapsed; + // XXX: localStorage doesn't allow booleans + localStorage.setItem(getSpaceCollapsedKey(this.props.space), newCollapsedState.toString()); + this.setState({collapsed: newCollapsedState}); // don't bubble up so encapsulating button for space // doesn't get triggered evt.stopPropagation(); From 374d8c1c4c44c57df0691db531b13efcea968260 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 5 May 2021 08:43:24 +0200 Subject: [PATCH 0234/1449] Update link to Android SDK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 73afe34df0..81a4a00515 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Platform Targets: * WebRTC features (VoIP and Video calling) are only available in Chrome & Firefox. * Mobile Web is not currently a target platform - instead please use the native iOS (https://github.com/matrix-org/matrix-ios-kit) and Android - (https://github.com/matrix-org/matrix-android-sdk) SDKs. + (https://github.com/vector-im/element-android) SDKs. All code lands on the `develop` branch - `master` is only used for stable releases. **Please file PRs against `develop`!!** From 2044ff01493d3bf9944d596aae5d6066936e4a1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 5 May 2021 11:48:55 +0200 Subject: [PATCH 0235/1449] Correctly handle defaults MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/spaces/SpaceTreeLevel.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/views/spaces/SpaceTreeLevel.tsx b/src/components/views/spaces/SpaceTreeLevel.tsx index 6e00eac725..47ed0cd6ca 100644 --- a/src/components/views/spaces/SpaceTreeLevel.tsx +++ b/src/components/views/spaces/SpaceTreeLevel.tsx @@ -70,9 +70,10 @@ export class SpaceItem extends React.PureComponent { constructor(props) { super(props); + const collapsedLocalStorage = localStorage.getItem(getSpaceCollapsedKey(props.space)); // XXX: localStorage doesn't allow booleans // default to collapsed for root items - const collapsed = localStorage.getItem(getSpaceCollapsedKey(props.space)) === "true" || !props.isNested; + const collapsed = collapsedLocalStorage ? collapsedLocalStorage === "true" : !props.isNested; this.state = { collapsed: collapsed, From 07f5b6e8c48bd11d593408b72b27e443e754288c Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 5 May 2021 11:45:12 +0100 Subject: [PATCH 0236/1449] Add retry mechanism and progress bar to add existing to space dialog --- .../dialogs/_AddExistingToSpaceDialog.scss | 77 ++++++++-- .../dialogs/AddExistingToSpaceDialog.tsx | 134 ++++++++++++------ src/i18n/strings/en_EN.json | 9 +- 3 files changed, 162 insertions(+), 58 deletions(-) diff --git a/res/css/views/dialogs/_AddExistingToSpaceDialog.scss b/res/css/views/dialogs/_AddExistingToSpaceDialog.scss index 84f965e6bd..c29c9791a6 100644 --- a/res/css/views/dialogs/_AddExistingToSpaceDialog.scss +++ b/res/css/views/dialogs/_AddExistingToSpaceDialog.scss @@ -101,7 +101,7 @@ limitations under the License. .mx_BaseAvatar { display: inline-flex; - margin: 5px 16px 5px 5px; + margin: auto 16px auto 5px; vertical-align: middle; } @@ -160,31 +160,32 @@ limitations under the License. } } - .mx_AddExistingToSpaceDialog_errorText { - font-weight: $font-semi-bold; - font-size: $font-12px; - line-height: $font-15px; - color: $notice-primary-color; - margin-bottom: 28px; - } - .mx_AddExistingToSpace { display: contents; } .mx_AddExistingToSpaceDialog_footer { display: flex; - margin-top: 32px; + margin-top: 20px; > span { flex-grow: 1; - font-size: $font-14px; + font-size: $font-12px; line-height: $font-15px; - font-weight: $font-semi-bold; + color: $secondary-fg-color; - .mx_AccessibleButton { - font-size: inherit; - display: inline-block; + .mx_ProgressBar { + height: 8px; + width: 100%; + + @mixin ProgressBarBorderRadius "8px"; + } + + .mx_AddExistingToSpaceDialog_progressText { + margin-top: 8px; + font-size: $font-15px; + line-height: $font-24px; + color: $primary-fg-color; } > * { @@ -192,8 +193,54 @@ limitations under the License. } } + .mx_AddExistingToSpaceDialog_error { + padding-left: 12px; + + > img { + align-self: center; + } + + .mx_AddExistingToSpaceDialog_errorHeading { + font-weight: $font-semi-bold; + font-size: $font-15px; + line-height: $font-18px; + color: $notice-primary-color; + } + + .mx_AddExistingToSpaceDialog_errorCaption { + margin-top: 4px; + font-size: $font-12px; + line-height: $font-15px; + color: $primary-fg-color; + } + } + .mx_AccessibleButton { display: inline-block; + align-self: center; + } + + .mx_AccessibleButton_kind_primary { + padding: 8px 36px; + } + + .mx_AddExistingToSpaceDialog_retryButton { + margin-left: 12px; + padding-left: 24px; + position: relative; + + &::before { + content: ''; + position: absolute; + background-color: $primary-fg-color; + mask-repeat: no-repeat; + mask-position: center; + mask-size: contain; + mask-image: url('$(res)/img/element-icons/retry.svg'); + width: 18px; + height: 18px; + left: 0; + } } .mx_AccessibleButton_kind_link { diff --git a/src/components/views/dialogs/AddExistingToSpaceDialog.tsx b/src/components/views/dialogs/AddExistingToSpaceDialog.tsx index 2253b525e0..a33248200c 100644 --- a/src/components/views/dialogs/AddExistingToSpaceDialog.tsx +++ b/src/components/views/dialogs/AddExistingToSpaceDialog.tsx @@ -29,12 +29,13 @@ import RoomAvatar from "../avatars/RoomAvatar"; import {getDisplayAliasForRoom} from "../../../Rooms"; import AccessibleButton from "../elements/AccessibleButton"; import AutoHideScrollbar from "../../structures/AutoHideScrollbar"; -import {allSettled} from "../../../utils/promise"; +import {sleep} from "../../../utils/promise"; import DMRoomMap from "../../../utils/DMRoomMap"; import {calculateRoomVia} from "../../../utils/permalinks/Permalinks"; import StyledCheckbox from "../elements/StyledCheckbox"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; import {sortRooms} from "../../../stores/room-list/algorithms/tag-sorting/RecentAlgorithm"; +import ProgressBar from "../elements/ProgressBar"; interface IProps extends IDialogProps { matrixClient: MatrixClient; @@ -46,7 +47,11 @@ const Entry = ({ room, checked, onChange }) => { return ; }; @@ -104,9 +109,9 @@ export const AddExistingToSpace: React.FC = ({ space, key={room.roomId} room={room} checked={selected.has(room)} - onChange={(checked) => { + onChange={onChange ? (checked) => { onChange(checked, room); - }} + } : null} />; }) }
    @@ -120,9 +125,9 @@ export const AddExistingToSpace: React.FC = ({ space, key={space.roomId} room={space} checked={selected.has(space)} - onChange={(checked) => { + onChange={onChange ? (checked) => { onChange(checked, space); - }} + } : null} />; }) }
    @@ -136,9 +141,9 @@ export const AddExistingToSpace: React.FC = ({ space, key={room.roomId} room={room} checked={selected.has(room)} - onChange={(checked) => { + onChange={onChange ? (checked) => { onChange(checked, room); - }} + } : null} />; }) }
    @@ -156,8 +161,8 @@ const AddExistingToSpaceDialog: React.FC = ({ matrixClient: cli, space, const existingSubspaces = SpaceStore.instance.getChildSpaces(space.roomId); const [selectedToAdd, setSelectedToAdd] = useState(new Set()); - const [busy, setBusy] = useState(false); - const [error, setError] = useState(""); + const [progress, setProgress] = useState(null); + const [error, setError] = useState(null); let spaceOptionSection; if (existingSubspaces.length > 0) { @@ -197,6 +202,82 @@ const AddExistingToSpaceDialog: React.FC = ({ matrixClient: cli, space,
    ; + const addRooms = async () => { + setError(null); + setProgress(0); + + let error; + + for (const room of selectedToAdd) { + const via = calculateRoomVia(room); + try { + await SpaceStore.instance.addRoomToSpace(space, room.roomId, via).catch(async e => { + if (e.errcode === "M_LIMIT_EXCEEDED") { + await sleep(e.data.retry_after_ms); + return SpaceStore.instance.addRoomToSpace(space, room.roomId, via); // retry + } + + throw e; + }); + setProgress(i => i + 1); + } catch (e) { + console.error("Failed to add rooms to space", e); + setError(error = e); + break; + } + } + + if (!error) { + onFinished(true); + } + }; + + const busy = progress !== null; + + let footer; + if (error) { + footer = <> + + + +
    { _t("Not all selected were added") }
    +
    { _t("Try again") }
    +
    + + + { _t("Retry") } + + ; + } else if (busy) { + footer = + +
    + { _t("Adding rooms... (%(progress)s out of %(count)s)", { + count: selectedToAdd.size, + progress, + }) } +
    +
    ; + } else { + footer = <> + +
    { _t("Want to add a new room instead?") }
    + onCreateRoomClick(cli, space)} kind="link"> + { _t("Create a new room") } + +
    + + + { _t("Add") } + + ; + } + return = ({ matrixClient: cli, space, onFinished={onFinished} fixedWidth={false} > - { error &&
    { error }
    } - { + onChange={!busy && !error ? (checked, room) => { if (checked) { selectedToAdd.add(room); } else { selectedToAdd.delete(room); } setSelectedToAdd(new Set(selectedToAdd)); - }} + } : null} />
    - -
    { _t("Don't want to add an existing room?") }
    - onCreateRoomClick(cli, space)} kind="link"> - { _t("Create a new room") } - -
    - - { - // TODO rate limiting - setBusy(true); - try { - await allSettled(Array.from(selectedToAdd).map((room) => - SpaceStore.instance.addRoomToSpace(space, room.roomId, calculateRoomVia(room)))); - onFinished(true); - } catch (e) { - console.error("Failed to add rooms to space", e); - setError(_t("Failed to add rooms to space")); - } - setBusy(false); - }} - > - { busy ? _t("Adding...") : _t("Add") } - + { footer }
    ; }; diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 2e5431620d..6888148873 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2033,10 +2033,11 @@ "Direct Messages": "Direct Messages", "Space selection": "Space selection", "Add existing rooms": "Add existing rooms", - "Don't want to add an existing room?": "Don't want to add an existing room?", + "Not all selected were added": "Not all selected were added", + "Adding rooms... (%(progress)s out of %(count)s)|other": "Adding rooms... (%(progress)s out of %(count)s)", + "Adding rooms... (%(progress)s out of %(count)s)|one": "Adding room...", + "Want to add a new room instead?": "Want to add a new room instead?", "Create a new room": "Create a new room", - "Failed to add rooms to space": "Failed to add rooms to space", - "Adding...": "Adding...", "Matrix ID": "Matrix ID", "Matrix Room ID": "Matrix Room ID", "email address": "email address", @@ -2675,6 +2676,8 @@ "Failed to create initial space rooms": "Failed to create initial space rooms", "Skip for now": "Skip for now", "Creating rooms...": "Creating rooms...", + "Failed to add rooms to space": "Failed to add rooms to space", + "Adding...": "Adding...", "What do you want to organise?": "What do you want to organise?", "Pick rooms or conversations to add. This is just a space for you, no one will be informed. You can add more later.": "Pick rooms or conversations to add. This is just a space for you, no one will be informed. You can add more later.", "Share %(name)s": "Share %(name)s", From acce9a4548c449f7347f0c077f333375b5ec253b Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 5 May 2021 11:50:55 +0100 Subject: [PATCH 0237/1449] Fix rounded progress bars --- res/css/views/dialogs/_AddExistingToSpaceDialog.scss | 2 +- res/css/views/elements/_ProgressBar.scss | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/res/css/views/dialogs/_AddExistingToSpaceDialog.scss b/res/css/views/dialogs/_AddExistingToSpaceDialog.scss index c29c9791a6..524f107165 100644 --- a/res/css/views/dialogs/_AddExistingToSpaceDialog.scss +++ b/res/css/views/dialogs/_AddExistingToSpaceDialog.scss @@ -178,7 +178,7 @@ limitations under the License. height: 8px; width: 100%; - @mixin ProgressBarBorderRadius "8px"; + @mixin ProgressBarBorderRadius 8px; } .mx_AddExistingToSpaceDialog_progressText { diff --git a/res/css/views/elements/_ProgressBar.scss b/res/css/views/elements/_ProgressBar.scss index 770978e921..c075ac74ff 100644 --- a/res/css/views/elements/_ProgressBar.scss +++ b/res/css/views/elements/_ProgressBar.scss @@ -21,7 +21,7 @@ progress.mx_ProgressBar { appearance: none; border: none; - @mixin ProgressBarBorderRadius "6px"; + @mixin ProgressBarBorderRadius 6px; @mixin ProgressBarColour $progressbar-fg-color; @mixin ProgressBarBgColour $progressbar-bg-color; ::-webkit-progress-value { From 886959f32df0170ad65c1a95c3f8cdd9f56e325e Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 5 May 2021 11:54:14 +0100 Subject: [PATCH 0238/1449] port rate limiting code over to space creation wizard's add existing rooms --- src/components/structures/SpaceRoomView.tsx | 27 ++++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx index cdf9dc02d3..a7a95d711c 100644 --- a/src/components/structures/SpaceRoomView.tsx +++ b/src/components/structures/SpaceRoomView.tsx @@ -52,7 +52,7 @@ import {useStateToggle} from "../../hooks/useStateToggle"; import SpaceStore from "../../stores/SpaceStore"; import FacePile from "../views/elements/FacePile"; import {AddExistingToSpace} from "../views/dialogs/AddExistingToSpaceDialog"; -import {allSettled} from "../../utils/promise"; +import {sleep} from "../../utils/promise"; import {calculateRoomVia} from "../../utils/permalinks/Permalinks"; interface IProps { @@ -389,15 +389,24 @@ const SpaceAddExistingRooms = ({ space, onFinished }) => { let buttonLabel = _t("Skip for now"); if (selectedToAdd.size > 0) { onClick = async () => { - // TODO rate limiting setBusy(true); - try { - await allSettled(Array.from(selectedToAdd).map((room) => - SpaceStore.instance.addRoomToSpace(space, room.roomId, calculateRoomVia(room)))); - onFinished(true); - } catch (e) { - console.error("Failed to add rooms to space", e); - setError(_t("Failed to add rooms to space")); + + for (const room of selectedToAdd) { + const via = calculateRoomVia(room); + try { + await SpaceStore.instance.addRoomToSpace(space, room.roomId, via).catch(async e => { + if (e.errcode === "M_LIMIT_EXCEEDED") { + await sleep(e.data.retry_after_ms); + return SpaceStore.instance.addRoomToSpace(space, room.roomId, via); // retry + } + + throw e; + }); + } catch (e) { + console.error("Failed to add rooms to space", e); + setError(_t("Failed to add rooms to space")); + break; + } } setBusy(false); }; From 4279e99e4c2df546fea8536b8c6a46ea34d748a2 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 5 May 2021 15:27:31 +0100 Subject: [PATCH 0239/1449] Improve performance of search all spaces and space switching --- src/stores/room-list/RoomListStore.ts | 12 +++++++----- src/stores/room-list/algorithms/Algorithm.ts | 1 - 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/stores/room-list/RoomListStore.ts b/src/stores/room-list/RoomListStore.ts index 77beeb4ba1..58eb6ed317 100644 --- a/src/stores/room-list/RoomListStore.ts +++ b/src/stores/room-list/RoomListStore.ts @@ -668,7 +668,7 @@ export class RoomListStoreClass extends AsyncStoreWithClient { * and thus might not cause an update to the store immediately. * @param {IFilterCondition} filter The filter condition to add. */ - public addFilter(filter: IFilterCondition): void { + public async addFilter(filter: IFilterCondition): Promise { if (SettingsStore.getValue("advancedRoomListLogging")) { // TODO: Remove debug: https://github.com/vector-im/element-web/issues/14602 console.log("Adding filter condition:", filter); @@ -680,12 +680,14 @@ export class RoomListStoreClass extends AsyncStoreWithClient { promise = this.recalculatePrefiltering(); } else { this.filterConditions.push(filter); - if (this.algorithm) { - this.algorithm.addFilterCondition(filter); - } // Runtime filters with spaces disable prefiltering for the search all spaces effect if (SettingsStore.getValue("feature_spaces")) { - promise = this.recalculatePrefiltering(); + // this has to be awaited so that `setKnownRooms` is called in time for the `addFilterCondition` below + // this way the runtime filters are only evaluated on one dataset and not both. + await this.recalculatePrefiltering(); + } + if (this.algorithm) { + this.algorithm.addFilterCondition(filter); } } promise.then(() => this.updateFn.trigger()); diff --git a/src/stores/room-list/algorithms/Algorithm.ts b/src/stores/room-list/algorithms/Algorithm.ts index 83ee803115..c0268d57a8 100644 --- a/src/stores/room-list/algorithms/Algorithm.ts +++ b/src/stores/room-list/algorithms/Algorithm.ts @@ -579,7 +579,6 @@ export class Algorithm extends EventEmitter { this.cachedRooms = newTags; this.updateTagsFromCache(); - this.recalculateFilteredRooms(); // Now that we've finished generation, we need to update the sticky room to what // it was. It's entirely possible that it changed lists though, so if it did then From 7f396bedd03d52036ba123a28672651ba02d7698 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 5 May 2021 15:59:02 +0100 Subject: [PATCH 0240/1449] add comment --- src/stores/room-list/algorithms/Algorithm.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stores/room-list/algorithms/Algorithm.ts b/src/stores/room-list/algorithms/Algorithm.ts index c0268d57a8..f3f0b178dd 100644 --- a/src/stores/room-list/algorithms/Algorithm.ts +++ b/src/stores/room-list/algorithms/Algorithm.ts @@ -577,7 +577,7 @@ export class Algorithm extends EventEmitter { await this.generateFreshTags(newTags); - this.cachedRooms = newTags; + this.cachedRooms = newTags; // this recalculates the filtered rooms for us this.updateTagsFromCache(); // Now that we've finished generation, we need to update the sticky room to what From 81b97590f68665e9ed3026f3853a145a693dd27f Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 5 May 2021 16:51:46 +0100 Subject: [PATCH 0241/1449] fix styling of the disabled danger_outline button --- res/css/views/elements/_AccessibleButton.scss | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/res/css/views/elements/_AccessibleButton.scss b/res/css/views/elements/_AccessibleButton.scss index 0075dcb511..2997c83cfd 100644 --- a/res/css/views/elements/_AccessibleButton.scss +++ b/res/css/views/elements/_AccessibleButton.scss @@ -76,12 +76,16 @@ limitations under the License. border: 1px solid $button-danger-bg-color; } -.mx_AccessibleButton_kind_danger.mx_AccessibleButton_disabled, -.mx_AccessibleButton_kind_danger_outline.mx_AccessibleButton_disabled { +.mx_AccessibleButton_kind_danger.mx_AccessibleButton_disabled { color: $button-danger-disabled-fg-color; background-color: $button-danger-disabled-bg-color; } +.mx_AccessibleButton_kind_danger_outline.mx_AccessibleButton_disabled { + color: $button-danger-disabled-bg-color; + border-color: $button-danger-disabled-bg-color; +} + .mx_AccessibleButton_hasKind.mx_AccessibleButton_kind_danger_sm { padding: 5px 12px; color: $button-danger-fg-color; From 570c082573942a65fd1cf6052d498138c97f5f15 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 5 May 2021 09:58:45 -0600 Subject: [PATCH 0242/1449] Promote colour to a variable I refuse to try and type this variable name freehand. --- res/themes/dark/css/_dark.scss | 7 ++++--- res/themes/light/css/_light.scss | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/res/themes/dark/css/_dark.scss b/res/themes/dark/css/_dark.scss index 334bf581f3..d31b67d4ab 100644 --- a/res/themes/dark/css/_dark.scss +++ b/res/themes/dark/css/_dark.scss @@ -9,6 +9,7 @@ $header-panel-text-primary-color: #B9BEC6; $header-panel-text-secondary-color: #c8c8cd; $text-primary-color: #ffffff; $text-secondary-color: #B9BEC6; +$quaternary-fg-color: #6F7882; $search-bg-color: #181b21; $search-placeholder-color: #61708b; $room-highlight-color: #343a46; @@ -42,11 +43,11 @@ $preview-bar-bg-color: $header-panel-bg-color; $groupFilterPanel-bg-color: rgba(38, 39, 43, 0.82); $inverted-bg-color: $base-color; -$voice-record-stop-border-color: #6F7882; // "Quartary" +$voice-record-stop-border-color: $quaternary-fg-color; $voice-record-waveform-bg-color: #394049; // "Dark Tile" $voice-record-waveform-fg-color: $secondary-fg-color; -$voice-record-waveform-incomplete-fg-color: #6F7882; // "Quartary" -$voice-record-icon-color: #6F7882; // "Quartary" +$voice-record-waveform-incomplete-fg-color: $quaternary-fg-color; +$voice-record-icon-color: $quaternary-fg-color; $voice-playback-button-bg-color: $tertiary-fg-color; $voice-playback-button-fg-color: #21262C; // "Separator" diff --git a/res/themes/light/css/_light.scss b/res/themes/light/css/_light.scss index 193b7f816c..240e78b1e2 100644 --- a/res/themes/light/css/_light.scss +++ b/res/themes/light/css/_light.scss @@ -21,6 +21,7 @@ $notice-primary-bg-color: rgba(255, 75, 85, 0.16); $primary-fg-color: #2e2f32; $secondary-fg-color: #737D8C; $tertiary-fg-color: #8D99A5; +$quaternary-fg-color: #C1C6CD; $header-panel-bg-color: #f3f8fd; // typical text (dark-on-white in light skin) @@ -190,7 +191,7 @@ $voice-record-live-circle-color: #ff4b55; $voice-record-stop-border-color: #E3E8F0; // "Separator" $voice-record-waveform-bg-color: #E3E8F0; // "Separator" $voice-record-waveform-fg-color: $secondary-fg-color; -$voice-record-waveform-incomplete-fg-color: #C1C6CD; // "Quartary" +$voice-record-waveform-incomplete-fg-color: $quaternary-fg-color; $voice-record-icon-color: $tertiary-fg-color; $voice-playback-button-bg-color: $primary-bg-color; $voice-playback-button-fg-color: $secondary-fg-color; From 39ef376a793a26efcb34576a66f3aee21976826a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 5 May 2021 18:06:42 +0200 Subject: [PATCH 0243/1449] Use Android SDK instead Co-authored-by: J. Ryan Stinnett --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 81a4a00515..b3e96ef001 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Platform Targets: * WebRTC features (VoIP and Video calling) are only available in Chrome & Firefox. * Mobile Web is not currently a target platform - instead please use the native iOS (https://github.com/matrix-org/matrix-ios-kit) and Android - (https://github.com/vector-im/element-android) SDKs. + (https://github.com/matrix-org/matrix-android-sdk2) SDKs. All code lands on the `develop` branch - `master` is only used for stable releases. **Please file PRs against `develop`!!** From 650933096ae859fe86c944a3fd0b4b7bfa991d5c Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 5 May 2021 17:25:29 +0100 Subject: [PATCH 0244/1449] Iterate Spaces admin UX around room management --- res/css/structures/_SpaceRoomDirectory.scss | 2 +- res/css/structures/_SpaceRoomView.scss | 95 +++--------- .../structures/SpaceRoomDirectory.tsx | 141 ++++++++++-------- src/components/structures/SpaceRoomView.tsx | 109 ++++++++++---- src/i18n/strings/en_EN.json | 2 +- src/utils/space.tsx | 1 + 6 files changed, 183 insertions(+), 167 deletions(-) diff --git a/res/css/structures/_SpaceRoomDirectory.scss b/res/css/structures/_SpaceRoomDirectory.scss index c7d087d8e0..86bcd6a320 100644 --- a/res/css/structures/_SpaceRoomDirectory.scss +++ b/res/css/structures/_SpaceRoomDirectory.scss @@ -86,7 +86,7 @@ limitations under the License. color: $primary-fg-color; .mx_AccessibleButton { - padding: 2px 8px; + padding: 4px 8px; font-weight: normal; & + .mx_AccessibleButton { diff --git a/res/css/structures/_SpaceRoomView.scss b/res/css/structures/_SpaceRoomView.scss index 553919d862..b2712f82c0 100644 --- a/res/css/structures/_SpaceRoomView.scss +++ b/res/css/structures/_SpaceRoomView.scss @@ -254,6 +254,27 @@ $SpaceRoomViewInnerWidth: 428px; mask-image: url('$(res)/img/element-icons/room/invite.svg'); } } + + .mx_SpaceRoomView_landing_settingsButton { + position: relative; + margin-left: 16px; + width: 24px; + height: 24px; + + &::before { + position: absolute; + content: ""; + left: 0; + top: 0; + height: 24px; + width: 24px; + background: $tertiary-fg-color; + mask-position: center; + mask-size: contain; + mask-repeat: no-repeat; + mask-image: url('$(res)/img/element-icons/settings.svg'); + } + } } .mx_SpaceRoomView_landing_topic { @@ -268,80 +289,6 @@ $SpaceRoomViewInnerWidth: 428px; background-color: $groupFilterPanel-bg-color; } - .mx_SpaceRoomView_landing_adminButtons { - margin-top: 24px; - - .mx_AccessibleButton { - position: relative; - width: 160px; - height: 124px; - box-sizing: border-box; - padding: 72px 16px 0; - border-radius: 12px; - border: 1px solid $input-border-color; - margin-right: 28px; - margin-bottom: 20px; - font-size: $font-14px; - display: inline-block; - vertical-align: bottom; - - &:last-child { - margin-right: 0; - } - - &:hover { - background-color: rgba(141, 151, 165, 0.1); - } - - &::before, &::after { - position: absolute; - content: ""; - left: 16px; - top: 16px; - height: 40px; - width: 40px; - border-radius: 20px; - } - - &::after { - mask-position: center; - mask-size: 30px; - mask-repeat: no-repeat; - background: #ffffff; // white icon fill - } - - &.mx_SpaceRoomView_landing_addButton { - &::before { - background-color: #ac3ba8; - } - - &::after { - mask-image: url('$(res)/img/element-icons/roomlist/explore.svg'); - } - } - - &.mx_SpaceRoomView_landing_createButton { - &::before { - background-color: #368bd6; - } - - &::after { - mask-image: url('$(res)/img/element-icons/roomlist/explore.svg'); - } - } - - &.mx_SpaceRoomView_landing_settingsButton { - &::before { - background-color: #5c56f5; - } - - &::after { - mask-image: url('$(res)/img/element-icons/settings.svg'); - } - } - } - } - .mx_SearchBox { margin: 0 0 20px; } diff --git a/src/components/structures/SpaceRoomDirectory.tsx b/src/components/structures/SpaceRoomDirectory.tsx index 8d6c9f0a70..35f9f61695 100644 --- a/src/components/structures/SpaceRoomDirectory.tsx +++ b/src/components/structures/SpaceRoomDirectory.tsx @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {useMemo, useState} from "react"; +import React, {ReactNode, useMemo, useState} from "react"; import {Room} from "matrix-js-sdk/src/models/room"; import {MatrixClient} from "matrix-js-sdk/src/client"; import {EventType, RoomType} from "matrix-js-sdk/src/@types/event"; @@ -39,11 +39,13 @@ import {mediaFromMxc} from "../../customisations/Media"; import InfoTooltip from "../views/elements/InfoTooltip"; import TextWithTooltip from "../views/elements/TextWithTooltip"; import {useStateToggle} from "../../hooks/useStateToggle"; +import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton"; interface IHierarchyProps { space: Room; initialText?: string; refreshToken?: any; + additionalButtons?: ReactNode; showRoom(room: ISpaceSummaryRoom, viaServers?: string[], autoJoin?: boolean): void; } @@ -350,6 +352,7 @@ export const SpaceHierarchy: React.FC = ({ initialText = "", showRoom, refreshToken, + additionalButtons, children, }) => { const cli = MatrixClientPeg.get(); @@ -415,78 +418,83 @@ export const SpaceHierarchy: React.FC = ({ countsStr = _t("%(count)s rooms", { count: numRooms, numSpaces }); } - let editSection; + let manageButtons; if (space.getMyMembership() === "join" && space.currentState.maySendStateEvent(EventType.SpaceChild, userId)) { const selectedRelations = Array.from(selected.keys()).flatMap(parentId => { return [...selected.get(parentId).values()].map(childId => [parentId, childId]) as [string, string][]; }); - let buttons; - if (selectedRelations.length) { - const selectionAllSuggested = selectedRelations.every(([parentId, childId]) => { - return parentChildMap.get(parentId)?.get(childId)?.content.suggested; - }); + const selectionAllSuggested = selectedRelations.every(([parentId, childId]) => { + return parentChildMap.get(parentId)?.get(childId)?.content.suggested; + }); - const disabled = removing || saving; + const disabled = !selectedRelations.length || removing || saving; - buttons = <> - { - setRemoving(true); - try { - for (const [parentId, childId] of selectedRelations) { - await cli.sendStateEvent(parentId, EventType.SpaceChild, {}, childId); - parentChildMap.get(parentId).get(childId).content = {}; - parentChildMap.set(parentId, new Map(parentChildMap.get(parentId))); - } - } catch (e) { - setError(_t("Failed to remove some rooms. Try again later")); - } - setRemoving(false); - }} - kind="danger_outline" - disabled={disabled} - > - { removing ? _t("Removing...") : _t("Remove") } - - { - setSaving(true); - try { - for (const [parentId, childId] of selectedRelations) { - const suggested = !selectionAllSuggested; - const existingContent = parentChildMap.get(parentId)?.get(childId)?.content; - if (!existingContent || existingContent.suggested === suggested) continue; - - const content = { - ...existingContent, - suggested: !selectionAllSuggested, - }; - - await cli.sendStateEvent(parentId, EventType.SpaceChild, content, childId); - - parentChildMap.get(parentId).get(childId).content = content; - parentChildMap.set(parentId, new Map(parentChildMap.get(parentId))); - } - } catch (e) { - setError("Failed to update some suggestions. Try again later"); - } - setSaving(false); - }} - kind="primary_outline" - disabled={disabled} - > - { saving - ? _t("Saving...") - : (selectionAllSuggested ? _t("Mark as not suggested") : _t("Mark as suggested")) - } - - ; + let Button: React.ComponentType> = AccessibleButton; + let props = {}; + if (!selectedRelations.length) { + Button = AccessibleTooltipButton; + props = { + tooltip: _t("Select a room below first"), + yOffset: -40, + }; } - editSection = - { buttons } - ; + manageButtons = <> + + + ; } let results; @@ -532,7 +540,10 @@ export const SpaceHierarchy: React.FC = ({ content = <>
    { countsStr } - { editSection } + + { additionalButtons } + { manageButtons } +
    { error &&
    { error } diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx index cdf9dc02d3..ae45c1b903 100644 --- a/src/components/structures/SpaceRoomView.tsx +++ b/src/components/structures/SpaceRoomView.tsx @@ -54,6 +54,12 @@ import FacePile from "../views/elements/FacePile"; import {AddExistingToSpace} from "../views/dialogs/AddExistingToSpaceDialog"; import {allSettled} from "../../utils/promise"; import {calculateRoomVia} from "../../utils/permalinks/Permalinks"; +import {ChevronFace, ContextMenuButton, useContextMenu} from "./ContextMenu"; +import IconizedContextMenu, { + IconizedContextMenuOption, + IconizedContextMenuOptionList, +} from "../views/context_menus/IconizedContextMenu"; +import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton"; interface IProps { space: Room; @@ -217,6 +223,67 @@ const SpacePreview = ({ space, onJoinButtonClicked, onRejectButtonClicked }) =>
    ; }; +const SpaceLandingAddButton = ({ space, onNewRoomAdded }) => { + const cli = useContext(MatrixClientContext); + const [menuDisplayed, handle, openMenu, closeMenu] = useContextMenu(); + + let contextMenu; + if (menuDisplayed) { + const rect = handle.current.getBoundingClientRect(); + contextMenu = + + { + e.preventDefault(); + e.stopPropagation(); + closeMenu(); + + if (await showCreateNewRoom(cli, space)) { + onNewRoomAdded(); + } + }} + /> + { + e.preventDefault(); + e.stopPropagation(); + closeMenu(); + + const [added] = await showAddExistingRooms(cli, space); + if (added) { + onNewRoomAdded(); + } + }} + /> + + ; + } + + return <> + + { _t("Add") } + + { contextMenu } + ; +}; + const SpaceLanding = ({ space }) => { const cli = useContext(MatrixClientContext); const myMembership = useMyRoomMembership(space); @@ -241,32 +308,20 @@ const SpaceLanding = ({ space }) => { const [refreshToken, forceUpdate] = useStateToggle(false); - let addRoomButtons; + let addRoomButton; if (canAddRooms) { - addRoomButtons = - { - const [added] = await showAddExistingRooms(cli, space); - if (added) { - forceUpdate(); - } - }}> - { _t("Add existing rooms & spaces") } - - { - showCreateNewRoom(cli, space); - }}> - { _t("Create a new room") } - - ; + addRoomButton = ; } let settingsButton; if (shouldShowSpaceSettings(cli, space)) { - settingsButton = { - showSpaceSettings(cli, space); - }}> - { _t("Settings") } - ; + settingsButton = { + showSpaceSettings(cli, space); + }} + title={_t("Settings")} + />; } const onMembersClick = () => { @@ -293,17 +348,19 @@ const SpaceLanding = ({ space }) => { { inviteButton } + { settingsButton }

    -
    - { addRoomButtons } - { settingsButton } -
    - +
    ; }; diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 2e5431620d..abec4017c8 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2655,6 +2655,7 @@ "%(count)s rooms and %(numSpaces)s spaces|one": "%(count)s room and %(numSpaces)s spaces", "%(count)s rooms and 1 space|other": "%(count)s rooms and 1 space", "%(count)s rooms and 1 space|one": "%(count)s room and 1 space", + "Select a room below first": "Select a room below first", "Failed to remove some rooms. Try again later": "Failed to remove some rooms. Try again later", "Removing...": "Removing...", "Mark as not suggested": "Mark as not suggested", @@ -2667,7 +2668,6 @@ "Public space": "Public space", "Private space": "Private space", " invites you": " invites you", - "Add existing rooms & spaces": "Add existing rooms & spaces", "Welcome to ": "Welcome to ", "Random": "Random", "Support": "Support", diff --git a/src/utils/space.tsx b/src/utils/space.tsx index 3f2b6f9bb4..c14dc988d2 100644 --- a/src/utils/space.tsx +++ b/src/utils/space.tsx @@ -83,6 +83,7 @@ export const showCreateNewRoom = async (cli: MatrixClient, space: Room) => { if (shouldCreate) { await createRoom(opts); } + return shouldCreate; }; export const showSpaceInvite = (space: Room, initialText = "") => { From 2b703e8574a9d46b75ce75706ff00dec33dd0801 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 5 May 2021 17:30:14 +0100 Subject: [PATCH 0245/1449] tweak code style --- src/stores/SpaceStore.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/stores/SpaceStore.tsx b/src/stores/SpaceStore.tsx index db93a23216..5c5870a993 100644 --- a/src/stores/SpaceStore.tsx +++ b/src/stores/SpaceStore.tsx @@ -201,9 +201,11 @@ export class SpaceStoreClass extends AsyncStoreWithClient { const childRoom = this.matrixClient?.getRoom(roomId); const createTs = childRoom?.currentState.getStateEvents(EventType.RoomCreate, "")?.getTs(); return getOrder(ev.getContent().order, createTs, roomId); - }) - .map(ev => this.matrixClient.getRoom(ev.getStateKey())) - .filter(room => room?.getMyMembership() === "join" || room?.getMyMembership() === "invite") || []; + }).map(ev => { + return this.matrixClient.getRoom(ev.getStateKey()); + }).filter(room => { + return room?.getMyMembership() === "join" || room?.getMyMembership() === "invite"; + }) || []; } public getChildRooms(spaceId: string): Room[] { From 70087b30bf20e076ce8e1e080485ea320e6d4143 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 5 May 2021 17:53:31 +0100 Subject: [PATCH 0246/1449] Add disclaimer about subspaces being experimental in add existing dialog --- .../dialogs/_AddExistingToSpaceDialog.scss | 26 +++++++++++++++++++ .../dialogs/AddExistingToSpaceDialog.tsx | 4 +++ src/i18n/strings/en_EN.json | 2 ++ 3 files changed, 32 insertions(+) diff --git a/res/css/views/dialogs/_AddExistingToSpaceDialog.scss b/res/css/views/dialogs/_AddExistingToSpaceDialog.scss index 524f107165..91947be76a 100644 --- a/res/css/views/dialogs/_AddExistingToSpaceDialog.scss +++ b/res/css/views/dialogs/_AddExistingToSpaceDialog.scss @@ -79,6 +79,32 @@ limitations under the License. border-radius: 8px; } } + + .mx_AddExistingToSpace_section_experimental { + position: relative; + border-radius: 8px; + margin: 12px 0; + padding: 8px 8px 8px 42px; + background-color: $header-panel-bg-color; + + font-size: $font-12px; + line-height: $font-15px; + color: $secondary-fg-color; + + &::before { + content: ''; + position: absolute; + left: 10px; + top: calc(50% - 8px); // vertical centering + height: 16px; + width: 16px; + background-color: $secondary-fg-color; + mask-repeat: no-repeat; + mask-size: contain; + mask-image: url('$(res)/img/element-icons/room/room-summary.svg'); + mask-position: center; + } + } } .mx_AddExistingToSpaceDialog { diff --git a/src/components/views/dialogs/AddExistingToSpaceDialog.tsx b/src/components/views/dialogs/AddExistingToSpaceDialog.tsx index a33248200c..ed7ae613bd 100644 --- a/src/components/views/dialogs/AddExistingToSpaceDialog.tsx +++ b/src/components/views/dialogs/AddExistingToSpaceDialog.tsx @@ -120,6 +120,10 @@ export const AddExistingToSpace: React.FC = ({ space, { spaces.length > 0 ? (

    { _t("Spaces") }

    +
    +
    { _t("Feeling experimental?") }
    +
    { _t("You can add existing spaces to a space.") }
    +
    { spaces.map(space => { return Date: Wed, 5 May 2021 14:00:56 -0600 Subject: [PATCH 0247/1449] Move and update variable usage --- res/themes/dark/css/_dark.scss | 20 ++++++------- res/themes/legacy-dark/css/_legacy-dark.scss | 20 ++++++------- .../legacy-light/css/_legacy-light.scss | 29 ++++++++----------- res/themes/light/css/_light.scss | 28 +++++++++--------- 4 files changed, 46 insertions(+), 51 deletions(-) diff --git a/res/themes/dark/css/_dark.scss b/res/themes/dark/css/_dark.scss index 25b59d3ff4..2d0e3d2a8b 100644 --- a/res/themes/dark/css/_dark.scss +++ b/res/themes/dark/css/_dark.scss @@ -43,14 +43,6 @@ $preview-bar-bg-color: $header-panel-bg-color; $groupFilterPanel-bg-color: rgba(38, 39, 43, 0.82); $inverted-bg-color: $base-color; -$voice-record-stop-border-color: $quaternary-fg-color; -$voice-record-waveform-bg-color: #394049; // "Dark Tile" -$voice-record-waveform-fg-color: $secondary-fg-color; -$voice-record-waveform-incomplete-fg-color: $quaternary-fg-color; -$voice-record-icon-color: $quaternary-fg-color; -$voice-playback-button-bg-color: $tertiary-fg-color; -$voice-playback-button-fg-color: #21262C; // "Separator" - // used by AddressSelector $selected-color: $room-highlight-color; @@ -215,10 +207,18 @@ $breadcrumb-placeholder-bg-color: #272c35; $user-tile-hover-bg-color: $header-panel-bg-color; $message-body-panel-fg-color: $secondary-fg-color; -$message-body-panel-bg-color: $voice-record-waveform-bg-color; -$message-body-panel-icon-fg-color: $primary-bg-color; +$message-body-panel-bg-color: #394049; // "Dark Tile" +$message-body-panel-icon-fg-color: #21262C; // "Separator" $message-body-panel-icon-bg-color: $tertiary-fg-color; +$voice-record-stop-border-color: $quaternary-fg-color; +$voice-record-waveform-bg-color: $message-body-panel-bg-color; +$voice-record-waveform-fg-color: $message-body-panel-fg-color; +$voice-record-waveform-incomplete-fg-color: $quaternary-fg-color; +$voice-record-icon-color: $quaternary-fg-color; +$voice-playback-button-bg-color: $message-body-panel-icon-bg-color; +$voice-playback-button-fg-color: $message-body-panel-icon-fg-color; + // Appearance tab colors $appearance-tab-border-color: $room-highlight-color; diff --git a/res/themes/legacy-dark/css/_legacy-dark.scss b/res/themes/legacy-dark/css/_legacy-dark.scss index 79b264ae1a..a852ad94e9 100644 --- a/res/themes/legacy-dark/css/_legacy-dark.scss +++ b/res/themes/legacy-dark/css/_legacy-dark.scss @@ -124,15 +124,6 @@ $roomsublist-skeleton-ui-bg: linear-gradient(180deg, #3e444c 0%, #3e444c00 100%) $groupFilterPanel-divider-color: $roomlist-header-color; -// See non-legacy dark for variable information -$voice-record-stop-border-color: #6F7882; -$voice-record-waveform-bg-color: #394049; -$voice-record-waveform-fg-color: $secondary-fg-color; -$voice-record-waveform-incomplete-fg-color: #6F7882; -$voice-record-icon-color: #6F7882; -$voice-playback-button-bg-color: $tertiary-fg-color; -$voice-playback-button-fg-color: #21262C; - $roomtile-preview-color: #9e9e9e; $roomtile-default-badge-bg-color: #61708b; $roomtile-selected-bg-color: #1A1D23; @@ -210,10 +201,19 @@ $breadcrumb-placeholder-bg-color: #272c35; $user-tile-hover-bg-color: $header-panel-bg-color; $message-body-panel-fg-color: $secondary-fg-color; -$message-body-panel-bg-color: $voice-record-waveform-bg-color; +$message-body-panel-bg-color: #394049; $message-body-panel-icon-fg-color: $primary-bg-color; $message-body-panel-icon-bg-color: $secondary-fg-color; +// See non-legacy dark for variable information +$voice-record-stop-border-color: #6F7882; +$voice-record-waveform-bg-color: $message-body-panel-bg-color; +$voice-record-waveform-fg-color: $message-body-panel-fg-color; +$voice-record-waveform-incomplete-fg-color: #6F7882; +$voice-record-icon-color: #6F7882; +$voice-playback-button-bg-color: $tertiary-fg-color; +$voice-playback-button-fg-color: #21262C; + // Appearance tab colors $appearance-tab-border-color: $room-highlight-color; diff --git a/res/themes/legacy-light/css/_legacy-light.scss b/res/themes/legacy-light/css/_legacy-light.scss index 9c47a06c15..84666bc662 100644 --- a/res/themes/legacy-light/css/_legacy-light.scss +++ b/res/themes/legacy-light/css/_legacy-light.scss @@ -191,22 +191,6 @@ $roomsublist-skeleton-ui-bg: linear-gradient(180deg, #ffffff 0%, #ffffff00 100%) $groupFilterPanel-divider-color: $roomlist-header-color; -// See non-legacy _light for variable information -$voice-record-stop-symbol-color: #ff4b55; -$voice-record-live-circle-color: #ff4b55; -$voice-record-stop-border-color: #E3E8F0; -$voice-record-waveform-bg-color: #E3E8F0; -$voice-record-waveform-fg-color: $secondary-fg-color; -$voice-record-waveform-incomplete-fg-color: #C1C6CD; -$voice-record-icon-color: $tertiary-fg-color; -$voice-playback-button-bg-color: $primary-bg-color; -$voice-playback-button-fg-color: $secondary-fg-color; - -$fileinfo-bg-color: $voice-record-waveform-bg-color; -$fileinfo-fg-color: $secondary-fg-color; -$fileinfo-icon-bg-color: $primary-bg-color; -$fileinfo-icon-fg-color: $secondary-fg-color; - $roomtile-preview-color: #9e9e9e; $roomtile-default-badge-bg-color: #61708b; $roomtile-selected-bg-color: #fff; @@ -340,10 +324,21 @@ $breadcrumb-placeholder-bg-color: #e8eef5; $user-tile-hover-bg-color: $header-panel-bg-color; $message-body-panel-fg-color: $secondary-fg-color; -$message-body-panel-bg-color: $voice-record-waveform-bg-color; +$message-body-panel-bg-color: #E3E8F0; $message-body-panel-icon-fg-color: $secondary-fg-color; $message-body-panel-icon-bg-color: $primary-bg-color; +// See non-legacy _light for variable information +$voice-record-stop-symbol-color: #ff4b55; +$voice-record-live-circle-color: #ff4b55; +$voice-record-stop-border-color: #E3E8F0; +$voice-record-waveform-bg-color: $message-body-panel-bg-color; +$voice-record-waveform-fg-color: $message-body-panel-fg-color; +$voice-record-waveform-incomplete-fg-color: #C1C6CD; +$voice-record-icon-color: $tertiary-fg-color; +$voice-playback-button-bg-color: $message-body-panel-icon-bg-color; +$voice-playback-button-fg-color: $message-body-panel-icon-fg-color; + // FontSlider colors $appearance-tab-border-color: $input-darker-bg-color; diff --git a/res/themes/light/css/_light.scss b/res/themes/light/css/_light.scss index 750184a76b..c889f43d0b 100644 --- a/res/themes/light/css/_light.scss +++ b/res/themes/light/css/_light.scss @@ -183,19 +183,6 @@ $roomsublist-skeleton-ui-bg: linear-gradient(180deg, #ffffff 0%, #ffffff00 100%) $groupFilterPanel-divider-color: $roomlist-header-color; -// These two don't change between themes. They are the $warning-color, but we don't -// want custom themes to affect them by accident. -$voice-record-stop-symbol-color: #ff4b55; -$voice-record-live-circle-color: #ff4b55; - -$voice-record-stop-border-color: #E3E8F0; // "Separator" -$voice-record-waveform-bg-color: #E3E8F0; // "Separator" -$voice-record-waveform-fg-color: $secondary-fg-color; -$voice-record-waveform-incomplete-fg-color: $quaternary-fg-color; -$voice-record-icon-color: $tertiary-fg-color; -$voice-playback-button-bg-color: $primary-bg-color; -$voice-playback-button-fg-color: $secondary-fg-color; - $roomtile-preview-color: $secondary-fg-color; $roomtile-default-badge-bg-color: #61708b; $roomtile-selected-bg-color: #FFF; @@ -336,10 +323,23 @@ $breadcrumb-placeholder-bg-color: #e8eef5; $user-tile-hover-bg-color: $header-panel-bg-color; $message-body-panel-fg-color: $secondary-fg-color; -$message-body-panel-bg-color: $voice-record-waveform-bg-color; +$message-body-panel-bg-color: #E3E8F0; // "Separator" $message-body-panel-icon-fg-color: $secondary-fg-color; $message-body-panel-icon-bg-color: $primary-bg-color; +// These two don't change between themes. They are the $warning-color, but we don't +// want custom themes to affect them by accident. +$voice-record-stop-symbol-color: #ff4b55; +$voice-record-live-circle-color: #ff4b55; + +$voice-record-stop-border-color: #E3E8F0; // "Separator" +$voice-record-waveform-bg-color: $message-body-panel-bg-color; +$voice-record-waveform-fg-color: $message-body-panel-fg-color; +$voice-record-waveform-incomplete-fg-color: $quaternary-fg-color; +$voice-record-icon-color: $tertiary-fg-color; +$voice-playback-button-bg-color: $message-body-panel-icon-bg-color; +$voice-playback-button-fg-color: $message-body-panel-icon-fg-color; + // FontSlider colors $appearance-tab-border-color: $input-darker-bg-color; From 9518e4d415baaeab009c183dc4b47d9b577f39a2 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 5 May 2021 23:59:07 +0100 Subject: [PATCH 0248/1449] Guard all isSpaceRoom calls behind the labs flag --- src/Avatar.ts | 3 ++- src/components/structures/MatrixChat.tsx | 4 ++-- src/components/structures/RightPanel.js | 5 ++++- src/components/structures/RoomView.tsx | 7 +++++-- src/components/views/dialogs/InviteDialog.tsx | 2 +- src/components/views/right_panel/UserInfo.tsx | 18 +++++++++--------- src/components/views/rooms/MemberList.js | 5 +++-- .../views/rooms/ThirdPartyMemberInfo.tsx | 3 ++- src/stores/BreadcrumbsStore.ts | 2 +- src/stores/room-list/algorithms/Algorithm.ts | 6 ++++-- .../room-list/filters/VisibilityProvider.ts | 2 +- 11 files changed, 34 insertions(+), 23 deletions(-) diff --git a/src/Avatar.ts b/src/Avatar.ts index d218ae8b46..a6499c688e 100644 --- a/src/Avatar.ts +++ b/src/Avatar.ts @@ -20,6 +20,7 @@ import {Room} from "matrix-js-sdk/src/models/room"; import DMRoomMap from './utils/DMRoomMap'; import {mediaFromMxc} from "./customisations/Media"; +import SettingsStore from "./settings/SettingsStore"; export type ResizeMethod = "crop" | "scale"; @@ -143,7 +144,7 @@ export function avatarUrlForRoom(room: Room, width: number, height: number, resi } // space rooms cannot be DMs so skip the rest - if (room.isSpaceRoom()) return null; + if (SettingsStore.getValue("feature_spaces") && room.isSpaceRoom()) return null; let otherMember = null; const otherUserId = DMRoomMap.shared().getUserIdForRoomId(room.roomId); diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index 078b296295..e330dc7d38 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -1094,7 +1094,7 @@ export default class MatrixChat extends React.PureComponent { private leaveRoomWarnings(roomId: string) { const roomToLeave = MatrixClientPeg.get().getRoom(roomId); - const isSpace = roomToLeave?.isSpaceRoom(); + const isSpace = SettingsStore.getValue("feature_spaces") && roomToLeave?.isSpaceRoom(); // Show a warning if there are additional complications. const warnings = []; @@ -1133,7 +1133,7 @@ export default class MatrixChat extends React.PureComponent { const roomToLeave = MatrixClientPeg.get().getRoom(roomId); const warnings = this.leaveRoomWarnings(roomId); - const isSpace = roomToLeave?.isSpaceRoom(); + const isSpace = SettingsStore.getValue("feature_spaces") && roomToLeave?.isSpaceRoom(); Modal.createTrackedDialog(isSpace ? "Leave space" : "Leave room", '', QuestionDialog, { title: isSpace ? _t("Leave space") : _t("Leave room"), description: ( diff --git a/src/components/structures/RightPanel.js b/src/components/structures/RightPanel.js index 5bcb3b2450..d8c763eabd 100644 --- a/src/components/structures/RightPanel.js +++ b/src/components/structures/RightPanel.js @@ -35,6 +35,7 @@ import {Action} from "../../dispatcher/actions"; import RoomSummaryCard from "../views/right_panel/RoomSummaryCard"; import WidgetCard from "../views/right_panel/WidgetCard"; import {replaceableComponent} from "../../utils/replaceableComponent"; +import SettingsStore from "../../settings/SettingsStore"; @replaceableComponent("structures.RightPanel") export default class RightPanel extends React.Component { @@ -85,7 +86,9 @@ export default class RightPanel extends React.Component { return RightPanelPhases.GroupMemberList; } return rps.groupPanelPhase; - } else if (this.props.room?.isSpaceRoom() && !RIGHT_PANEL_SPACE_PHASES.includes(rps.roomPanelPhase)) { + } else if (SettingsStore.getValue("feature_spaces") && this.props.room?.isSpaceRoom() + && !RIGHT_PANEL_SPACE_PHASES.includes(rps.roomPanelPhase) + ) { return RightPanelPhases.SpaceMemberList; } else if (userForPanel) { // XXX FIXME AAAAAARGH: What is going on with this class!? It takes some of its state diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index 5108643673..58a87e6641 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -1750,7 +1750,10 @@ export default class RoomView extends React.Component { } const myMembership = this.state.room.getMyMembership(); - if (myMembership === "invite" && !this.state.room.isSpaceRoom()) { // SpaceRoomView handles invites itself + if (myMembership === "invite" + // SpaceRoomView handles invites itself + && (!SettingsStore.getValue("feature_spaces") || !this.state.room.isSpaceRoom()) + ) { if (this.state.joining || this.state.rejecting) { return ( @@ -1892,7 +1895,7 @@ export default class RoomView extends React.Component { room={this.state.room} /> ); - if (!this.state.canPeek && !this.state.room?.isSpaceRoom()) { + if (!this.state.canPeek && (!SettingsStore.getValue("feature_spaces") || !this.state.room?.isSpaceRoom())) { return (
    { previewBar } diff --git a/src/components/views/dialogs/InviteDialog.tsx b/src/components/views/dialogs/InviteDialog.tsx index 2ebc84ec7c..ec9c71ccbe 100644 --- a/src/components/views/dialogs/InviteDialog.tsx +++ b/src/components/views/dialogs/InviteDialog.tsx @@ -1312,7 +1312,7 @@ export default class InviteDialog extends React.PureComponent { +const warnSelfDemote = async (isSpace: boolean) => { const {finished} = Modal.createTrackedDialog('Demoting Self', '', QuestionDialog, { title: _t("Demote yourself?"), description: @@ -727,7 +727,7 @@ const MuteToggleButton: React.FC = ({member, room, powerLevels, // if muting self, warn as it may be irreversible if (target === cli.getUserId()) { try { - if (!(await warnSelfDemote(room?.isSpaceRoom()))) return; + if (!(await warnSelfDemote(SettingsStore.getValue("feature_spaces") && room?.isSpaceRoom()))) return; } catch (e) { console.error("Failed to warn about self demotion: ", e); return; @@ -816,7 +816,7 @@ const RoomAdminToolsContainer: React.FC = ({ if (canAffectUser && me.powerLevel >= kickPowerLevel) { kickButton = ; } - if (me.powerLevel >= redactPowerLevel && !room.isSpaceRoom()) { + if (me.powerLevel >= redactPowerLevel && (!SettingsStore.getValue("feature_spaces") || !room.isSpaceRoom())) { redactButton = ( ); @@ -1095,7 +1095,7 @@ const PowerLevelEditor: React.FC<{ } else if (myUserId === target) { // If we are changing our own PL it can only ever be decreasing, which we cannot reverse. try { - if (!(await warnSelfDemote(room?.isSpaceRoom()))) return; + if (!(await warnSelfDemote(SettingsStore.getValue("feature_spaces") && room?.isSpaceRoom()))) return; } catch (e) { console.error("Failed to warn about self demotion: ", e); } @@ -1325,10 +1325,10 @@ const BasicUserInfo: React.FC<{ if (!isRoomEncrypted) { if (!cryptoEnabled) { text = _t("This client does not support end-to-end encryption."); - } else if (room && !room.isSpaceRoom()) { + } else if (room && (!SettingsStore.getValue("feature_spaces") || !room.isSpaceRoom())) { text = _t("Messages in this room are not end-to-end encrypted."); } - } else if (!room.isSpaceRoom()) { + } else if (!SettingsStore.getValue("feature_spaces") || !room.isSpaceRoom()) { text = _t("Messages in this room are end-to-end encrypted."); } @@ -1405,7 +1405,7 @@ const BasicUserInfo: React.FC<{ canInvite={roomPermissions.canInvite} isIgnored={isIgnored} member={member} - isSpace={room?.isSpaceRoom()} + isSpace={SettingsStore.getValue("feature_spaces") && room?.isSpaceRoom()} /> { adminToolsContainer } @@ -1567,7 +1567,7 @@ const UserInfo: React.FC = ({ previousPhase = RightPanelPhases.RoomMemberInfo; refireParams = {member: member}; } else if (room) { - previousPhase = previousPhase = room.isSpaceRoom() + previousPhase = previousPhase = SettingsStore.getValue("feature_spaces") && room.isSpaceRoom() ? RightPanelPhases.SpaceMemberList : RightPanelPhases.RoomMemberList; } @@ -1616,7 +1616,7 @@ const UserInfo: React.FC = ({ } let scopeHeader; - if (room?.isSpaceRoom()) { + if (SettingsStore.getValue("feature_spaces") && room?.isSpaceRoom()) { scopeHeader =
    diff --git a/src/components/views/rooms/MemberList.js b/src/components/views/rooms/MemberList.js index 593132a283..fbc0e477a1 100644 --- a/src/components/views/rooms/MemberList.js +++ b/src/components/views/rooms/MemberList.js @@ -30,6 +30,7 @@ import {RightPanelPhases} from "../../../stores/RightPanelStorePhases"; import RoomAvatar from "../avatars/RoomAvatar"; import RoomName from "../elements/RoomName"; import {replaceableComponent} from "../../../utils/replaceableComponent"; +import SettingsStore from "../../../settings/SettingsStore"; const INITIAL_LOAD_NUM_MEMBERS = 30; const INITIAL_LOAD_NUM_INVITED = 5; @@ -460,7 +461,7 @@ export default class MemberList extends React.Component { const chat = CommunityPrototypeStore.instance.getSelectedCommunityGeneralChat(); if (chat && chat.roomId === this.props.roomId) { inviteButtonText = _t("Invite to this community"); - } else if (room.isSpaceRoom()) { + } else if (SettingsStore.getValue("feature_spaces") && room.isSpaceRoom()) { inviteButtonText = _t("Invite to this space"); } @@ -492,7 +493,7 @@ export default class MemberList extends React.Component { let previousPhase = RightPanelPhases.RoomSummary; // We have no previousPhase for when viewing a MemberList from a Space let scopeHeader; - if (room?.isSpaceRoom()) { + if (SettingsStore.getValue("feature_spaces") && room?.isSpaceRoom()) { previousPhase = undefined; scopeHeader =
    diff --git a/src/components/views/rooms/ThirdPartyMemberInfo.tsx b/src/components/views/rooms/ThirdPartyMemberInfo.tsx index 78fdc8b404..792e6ac8f7 100644 --- a/src/components/views/rooms/ThirdPartyMemberInfo.tsx +++ b/src/components/views/rooms/ThirdPartyMemberInfo.tsx @@ -26,6 +26,7 @@ import {isValid3pidInvite} from "../../../RoomInvite"; import RoomAvatar from "../avatars/RoomAvatar"; import RoomName from "../elements/RoomName"; import {replaceableComponent} from "../../../utils/replaceableComponent"; +import SettingsStore from "../../../settings/SettingsStore"; interface IProps { event: MatrixEvent; @@ -135,7 +136,7 @@ export default class ThirdPartyMemberInfo extends React.Component diff --git a/src/stores/BreadcrumbsStore.ts b/src/stores/BreadcrumbsStore.ts index 393f4f27a1..1a78a1b485 100644 --- a/src/stores/BreadcrumbsStore.ts +++ b/src/stores/BreadcrumbsStore.ts @@ -122,7 +122,7 @@ export class BreadcrumbsStore extends AsyncStoreWithClient { } private async appendRoom(room: Room) { - if (room.isSpaceRoom() && SettingsStore.getValue("feature_spaces")) return; // hide space rooms + if (SettingsStore.getValue("feature_spaces") && room.isSpaceRoom()) return; // hide space rooms let updated = false; const rooms = (this.state.rooms || []).slice(); // cheap clone diff --git a/src/stores/room-list/algorithms/Algorithm.ts b/src/stores/room-list/algorithms/Algorithm.ts index f3f0b178dd..024c484c41 100644 --- a/src/stores/room-list/algorithms/Algorithm.ts +++ b/src/stores/room-list/algorithms/Algorithm.ts @@ -199,8 +199,10 @@ export class Algorithm extends EventEmitter { } private async doUpdateStickyRoom(val: Room) { - // no-op sticky rooms for spaces - they're effectively virtual rooms - if (val?.isSpaceRoom() && val.getMyMembership() !== "invite") val = null; + if (SettingsStore.getValue("feature_spaces") && val?.isSpaceRoom() && val.getMyMembership() !== "invite") { + // no-op sticky rooms for spaces - they're effectively virtual rooms + val = null; + } // Note throughout: We need async so we can wait for handleRoomUpdate() to do its thing, // otherwise we risk duplicating rooms. diff --git a/src/stores/room-list/filters/VisibilityProvider.ts b/src/stores/room-list/filters/VisibilityProvider.ts index f212b1f9d9..c07c2b0b26 100644 --- a/src/stores/room-list/filters/VisibilityProvider.ts +++ b/src/stores/room-list/filters/VisibilityProvider.ts @@ -50,7 +50,7 @@ export class VisibilityProvider { } // hide space rooms as they'll be shown in the SpacePanel - if (room.isSpaceRoom() && SettingsStore.getValue("feature_spaces")) { + if (SettingsStore.getValue("feature_spaces") && room.isSpaceRoom()) { return false; } From f1413532e7f1fb30c275b391f32e24961b729497 Mon Sep 17 00:00:00 2001 From: Aaron Raimist Date: Thu, 6 May 2021 00:07:55 -0500 Subject: [PATCH 0249/1449] Revert "Also fix translations" This reverts commit 284b9e48cee1698fad9cf571709ba66e284e3aa8. Signed-off-by: Aaron Raimist --- src/i18n/strings/cs.json | 2 +- src/i18n/strings/de_DE.json | 2 +- src/i18n/strings/es.json | 2 +- src/i18n/strings/et.json | 2 +- src/i18n/strings/fr.json | 2 +- src/i18n/strings/gl.json | 2 +- src/i18n/strings/hu.json | 2 +- src/i18n/strings/it.json | 2 +- src/i18n/strings/nl.json | 2 +- src/i18n/strings/sq.json | 2 +- src/i18n/strings/sv.json | 2 +- src/i18n/strings/zh_Hant.json | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/i18n/strings/cs.json b/src/i18n/strings/cs.json index 87dbb6c70c..7f9ff9341c 100644 --- a/src/i18n/strings/cs.json +++ b/src/i18n/strings/cs.json @@ -3168,7 +3168,7 @@ "Open": "Otevřít", "Share decryption keys for room history when inviting users": "Při pozvání uživatelů sdílet dešifrovací klíče pro historii místnosti", "Manage & explore rooms": "Spravovat a prozkoumat místnosti", - "Message search initialisation failed": "Inicializace vyhledávání zpráv se nezdařila", + "Message search initilisation failed": "Inicializace vyhledávání zpráv se nezdařila", "%(count)s people you know have already joined|one": "%(count)s osoba, kterou znáte, se již připojila", "Invited people will be able to read old messages.": "Pozvaní lidé budou moci číst staré zprávy.", "If you do, please note that none of your messages will be deleted, but the search experience might be degraded for a few momentswhilst the index is recreated": "Pokud tak učiníte, nezapomeňte, že žádná z vašich zpráv nebude smazána, ale vyhledávání může být na několik okamžiků degradováno, zatímco index bude znovu vytvářen", diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 133cfc430d..9551f00e55 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -3227,7 +3227,7 @@ "This homeserver has been blocked by it's administrator.": "Dieser Heimserver wurde von seiner Administration blockiert.", "You have unverified logins": "Du hast nicht-bestätigte Anmeldungen", "Review to ensure your account is safe": "Überprüfen, um sicher zu sein, dass dein Konto sicher ist", - "Message search initialisation failed": "Initialisierung der Nachrichtensuche fehlgeschlagen", + "Message search initilisation failed": "Initialisierung der Nachrichtensuche fehlgeschlagen", "Support": "Unterstützen", "This room is suggested as a good one to join": "Dieser Raum wurde als gut zum Beitreten vorgeschlagen", "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.": "Deine Nachricht wurde nicht versendet, weil dieser Heimserver von dessen Administrator gesperrt wurde. Bitte kontaktiere deinen Dienstadministrator um den Dienst weiterzunutzen.", diff --git a/src/i18n/strings/es.json b/src/i18n/strings/es.json index a41dc65cc3..d396cc318f 100644 --- a/src/i18n/strings/es.json +++ b/src/i18n/strings/es.json @@ -3213,7 +3213,7 @@ "Review to ensure your account is safe": "Revisa que tu cuenta esté segura", "Sends the given message as a spoiler": "Envía el mensaje como un spoiler", "Consulting with %(transferTarget)s. Transfer to %(transferee)s": "Consultando a %(transferTarget)s. Transferir a %(transferee)s", - "Message search initialisation failed": "Ha fallado la inicialización de la búsqueda de mensajes", + "Message search initilisation failed": "Ha fallado la inicialización de la búsqueda de mensajes", "Reset event store?": "¿Restablecer almacenamiento de eventos?", "You most likely do not want to reset your event index store": "Lo más probable es que no quieras restablecer tu almacenamiento de índice de ecentos", "If you do, please note that none of your messages will be deleted, but the search experience might be degraded for a few momentswhilst the index is recreated": "Si lo haces, ten en cuenta que no se borrarán tus mensajes, pero la experiencia de búsqueda será peor durante unos momentos mientras se recrea el índice", diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index 509008012d..444475deea 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -3249,7 +3249,7 @@ "Reset event store": "Lähtesta sündmuste andmekogu", "Verify other login": "Verifitseeri muu sisselogimissessioon", "Consulting with %(transferTarget)s. Transfer to %(transferee)s": "Suhtlen teise osapoolega %(transferTarget)s. Saadan andmeid kasutajale %(transferee)s", - "Message search initialisation failed": "Sõnumite otsingu alustamine ei õnnestunud", + "Message search initilisation failed": "Sõnumite otsingu alustamine ei õnnestunud", "Invite messages are hidden by default. Click to show the message.": "Kutsed on vaikimisi peidetud. Sõnumi nägemiseks klõpsi.", "Accept on your other login…": "Nõustu oma teise sisselogimissessiooniga…", "Avatar": "Tunnuspilt", diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index 3962525271..fcc5ec9afe 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -3254,7 +3254,7 @@ "Quick actions": "Actions rapides", "Invite to just this room": "Inviter seulement dans ce salon", "Warn before quitting": "Avertir avant de quitter", - "Message search initialisation failed": "Échec de l’initialisation de la recherche de message", + "Message search initilisation failed": "Échec de l’initialisation de la recherche de message", "Manage & explore rooms": "Gérer et découvrir les salons", "Consulting with %(transferTarget)s. Transfer to %(transferee)s": "Consultation avec %(transferTarget)s. Transfert à %(transferee)s", "unknown person": "personne inconnue", diff --git a/src/i18n/strings/gl.json b/src/i18n/strings/gl.json index 4ac3e1bcdd..f6ebce684f 100644 --- a/src/i18n/strings/gl.json +++ b/src/i18n/strings/gl.json @@ -3269,7 +3269,7 @@ "unknown person": "persoa descoñecida", "Consulting with %(transferTarget)s. Transfer to %(transferee)s": "Consultando con %(transferTarget)s. Transferir a %(transferee)s", "Manage & explore rooms": "Xestionar e explorar salas", - "Message search initialisation failed": "Fallo a inicialización da busca de mensaxes", + "Message search initilisation failed": "Fallo a inicialización da busca de mensaxes", "Quick actions": "Accións rápidas", "Invite messages are hidden by default. Click to show the message.": "As mensaxes de convite están agochadas por defecto. Preme para amosar a mensaxe.", "Record a voice message": "Gravar mensaxe de voz", diff --git a/src/i18n/strings/hu.json b/src/i18n/strings/hu.json index 64949ad848..2ec5af8a17 100644 --- a/src/i18n/strings/hu.json +++ b/src/i18n/strings/hu.json @@ -3272,7 +3272,7 @@ "Quick actions": "Gyors műveletek", "Invite to just this room": "Meghívás csak ebbe a szobába", "Warn before quitting": "Kilépés előtt figyelmeztet", - "Message search initialisation failed": "Üzenet keresés beállítása sikertelen", + "Message search initilisation failed": "Üzenet keresés beállítása sikertelen", "Manage & explore rooms": "Szobák kezelése és felderítése", "Consulting with %(transferTarget)s. Transfer to %(transferee)s": "Egyeztetés vele: %(transferTarget)s. Átadás ide: %(transferee)s", "unknown person": "ismeretlen személy", diff --git a/src/i18n/strings/it.json b/src/i18n/strings/it.json index c4ed6cd640..2d0edb77e6 100644 --- a/src/i18n/strings/it.json +++ b/src/i18n/strings/it.json @@ -3260,7 +3260,7 @@ "Invite to just this room": "Invita solo in questa stanza", "%(count)s people you know have already joined|other": "%(count)s persone che conosci sono già entrate", "%(count)s people you know have already joined|one": "%(count)s persona che conosci è già entrata", - "Message search initialisation failed": "Inizializzazione ricerca messaggi fallita", + "Message search initilisation failed": "Inizializzazione ricerca messaggi fallita", "Add existing rooms": "Aggiungi stanze esistenti", "Warn before quitting": "Avvisa prima di uscire", "Invited people will be able to read old messages.": "Le persone invitate potranno leggere i vecchi messaggi.", diff --git a/src/i18n/strings/nl.json b/src/i18n/strings/nl.json index aa6482ccf5..de98a878e8 100644 --- a/src/i18n/strings/nl.json +++ b/src/i18n/strings/nl.json @@ -3163,7 +3163,7 @@ "Quick actions": "Snelle acties", "Invite to just this room": "Uitnodigen voor alleen dit gesprek", "Warn before quitting": "Waarschuwen voordat u afsluit", - "Message search initialisation failed": "Zoeken in berichten opstarten is mislukt", + "Message search initilisation failed": "Zoeken in berichten opstarten is mislukt", "Manage & explore rooms": "Beheer & ontdek gesprekken", "Consulting with %(transferTarget)s. Transfer to %(transferee)s": "Overleggen met %(transferTarget)s. Verstuur naar %(transferee)s", "unknown person": "onbekend persoon", diff --git a/src/i18n/strings/sq.json b/src/i18n/strings/sq.json index 1eabf09cac..ad768b59cb 100644 --- a/src/i18n/strings/sq.json +++ b/src/i18n/strings/sq.json @@ -3265,7 +3265,7 @@ "Quick actions": "Veprime të shpejta", "Invite to just this room": "Ftoje thjesht te kjo dhomë", "Warn before quitting": "Sinjalizo përpara daljes", - "Message search initialisation failed": "Dështoi gatitje kërkimi mesazhesh", + "Message search initilisation failed": "Dështoi gatitje kërkimi mesazhesh", "Manage & explore rooms": "Administroni & eksploroni dhoma", "unknown person": "person i panjohur", "Sends the given message as a spoiler": "E dërgon mesazhin e dhënë si spoiler", diff --git a/src/i18n/strings/sv.json b/src/i18n/strings/sv.json index 6e839750ff..42a7f78268 100644 --- a/src/i18n/strings/sv.json +++ b/src/i18n/strings/sv.json @@ -3212,7 +3212,7 @@ "Verification requested": "Verifiering begärd", "Sends the given message as a spoiler": "Skickar det angivna meddelandet som en spoiler", "Manage & explore rooms": "Hantera och utforska rum", - "Message search initialisation failed": "Initialisering av meddelandesökning misslyckades", + "Message search initilisation failed": "Initialisering av meddelandesökning misslyckades", "Please choose a strong password": "Vänligen välj ett starkt lösenord", "Use another login": "Använd annan inloggning", "Verify your identity to access encrypted messages and prove your identity to others.": "Verifiera din identitet för att komma åt krypterade meddelanden och bevisa din identitet för andra.", diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index 6d0e0854ed..c9bb9bb2d7 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -3254,7 +3254,7 @@ "You have unverified logins": "您有未驗證的登入", "unknown person": "不明身份的人", "Consulting with %(transferTarget)s. Transfer to %(transferee)s": "與 %(transferTarget)s 進行協商。轉讓至 %(transferee)s", - "Message search initialisation failed": "訊息搜尋初始化失敗", + "Message search initilisation failed": "訊息搜尋初始化失敗", "Invite to just this room": "邀請到此聊天室", "If you do, please note that none of your messages will be deleted, but the search experience might be degraded for a few momentswhilst the index is recreated": "如果這樣做,請注意,您的任何訊息都不會被刪除,但是在重新建立索引的同時,搜索體驗可能會降低片刻", "Let's create a room for each of them.": "讓我們為每個主題建立一個聊天室吧。", From 0c87a67caf645fb86e55dd7dca4649411b56ff5b Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Thu, 6 May 2021 11:46:25 +0100 Subject: [PATCH 0250/1449] Lazily decrypt events on room view --- src/components/structures/MatrixChat.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index 078b296295..41cacd2569 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -906,6 +906,7 @@ export default class MatrixChat extends React.PureComponent { let presentedId = roomInfo.room_alias || roomInfo.room_id; const room = MatrixClientPeg.get().getRoom(roomInfo.room_id); if (room) { + room.lazyDecryptEvents(); const theAlias = Rooms.getDisplayAliasForRoom(room); if (theAlias) { presentedId = theAlias; From d47eecbd24fd51af43e2c17f34ac9d6bbab7b562 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 6 May 2021 13:05:58 +0100 Subject: [PATCH 0251/1449] Make button sizes more consistent and fix untrapped behaviour of join button leaking to parent --- res/css/structures/_SpaceRoomDirectory.scss | 15 +++++++++++++-- src/components/structures/SpaceRoomDirectory.tsx | 14 +++++++++++--- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/res/css/structures/_SpaceRoomDirectory.scss b/res/css/structures/_SpaceRoomDirectory.scss index 86bcd6a320..7925686bf1 100644 --- a/res/css/structures/_SpaceRoomDirectory.scss +++ b/res/css/structures/_SpaceRoomDirectory.scss @@ -86,7 +86,7 @@ limitations under the License. color: $primary-fg-color; .mx_AccessibleButton { - padding: 4px 8px; + padding: 4px 12px; font-weight: normal; & + .mx_AccessibleButton { @@ -94,6 +94,11 @@ limitations under the License. } } + .mx_AccessibleButton_kind_danger_outline, + .mx_AccessibleButton_kind_primary_outline { + padding: 3px 12px; // to account for the 1px border + } + > span { margin-left: auto; } @@ -246,11 +251,17 @@ limitations under the License. grid-row: 1/3; .mx_AccessibleButton { - padding: 8px 18px; + line-height: $font-24px; + padding: 4px 16px; display: inline-block; visibility: hidden; } + .mx_AccessibleButton_kind_danger_outline, + .mx_AccessibleButton_kind_primary_outline { + padding: 3px 16px; // to account for the 1px border + } + .mx_Checkbox { display: inline-flex; vertical-align: middle; diff --git a/src/components/structures/SpaceRoomDirectory.tsx b/src/components/structures/SpaceRoomDirectory.tsx index 35f9f61695..79a1fbc10e 100644 --- a/src/components/structures/SpaceRoomDirectory.tsx +++ b/src/components/structures/SpaceRoomDirectory.tsx @@ -24,7 +24,7 @@ import {sortBy} from "lodash"; import {MatrixClientPeg} from "../../MatrixClientPeg"; import dis from "../../dispatcher/dispatcher"; import {_t} from "../../languageHandler"; -import AccessibleButton from "../views/elements/AccessibleButton"; +import AccessibleButton, {ButtonEvent} from "../views/elements/AccessibleButton"; import BaseDialog from "../views/dialogs/BaseDialog"; import Spinner from "../views/elements/Spinner"; import SearchBox from "./SearchBox"; @@ -108,8 +108,16 @@ const Tile: React.FC = ({ const cliRoom = cli.getRoom(room.room_id); const myMembership = cliRoom?.getMyMembership(); - const onPreviewClick = () => onViewRoomClick(false); - const onJoinClick = () => onViewRoomClick(true); + const onPreviewClick = (ev: ButtonEvent) => { + ev.preventDefault(); + ev.stopPropagation(); + onViewRoomClick(false); + } + const onJoinClick = (ev: ButtonEvent) => { + ev.preventDefault(); + ev.stopPropagation(); + onViewRoomClick(true); + } let button; if (myMembership === "join") { From 6e0c7611c35ecb9664da0c48c153b103d71751a9 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Thu, 6 May 2021 13:53:27 +0100 Subject: [PATCH 0252/1449] Extract blob-safe MIME types --- src/utils/DecryptFile.ts | 63 ++------------------------------ src/utils/blobs.ts | 78 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 60 deletions(-) create mode 100644 src/utils/blobs.ts diff --git a/src/utils/DecryptFile.ts b/src/utils/DecryptFile.ts index 93cedbc707..d073393170 100644 --- a/src/utils/DecryptFile.ts +++ b/src/utils/DecryptFile.ts @@ -17,63 +17,8 @@ limitations under the License. // Pull in the encryption lib so that we can decrypt attachments. import encrypt from 'browser-encrypt-attachment'; import {mediaFromContent} from "../customisations/Media"; -import {IEncryptedFile} from "../customisations/models/IMediaEventContent"; - -// WARNING: We have to be very careful about what mime-types we allow into blobs, -// as for performance reasons these are now rendered via URL.createObjectURL() -// rather than by converting into data: URIs. -// -// This means that the content is rendered using the origin of the script which -// called createObjectURL(), and so if the content contains any scripting then it -// will pose a XSS vulnerability when the browser renders it. This is particularly -// bad if the user right-clicks the URI and pastes it into a new window or tab, -// as the blob will then execute with access to Element's full JS environment(!) -// -// See https://github.com/matrix-org/matrix-react-sdk/pull/1820#issuecomment-385210647 -// for details. -// -// We mitigate this by only allowing mime-types into blobs which we know don't -// contain any scripting, and instantiate all others as application/octet-stream -// regardless of what mime-type the event claimed. Even if the payload itself -// is some malicious HTML, the fact we instantiate it with a media mimetype or -// application/octet-stream means the browser doesn't try to render it as such. -// -// One interesting edge case is image/svg+xml, which empirically *is* rendered -// correctly if the blob is set to the src attribute of an img tag (for thumbnails) -// *even if the mimetype is application/octet-stream*. However, empirically JS -// in the SVG isn't executed in this scenario, so we seem to be okay. -// -// Tested on Chrome 65 and Firefox 60 -// -// The list below is taken mainly from -// https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats -// N.B. Matrix doesn't currently specify which mimetypes are valid in given -// events, so we pick the ones which HTML5 browsers should be able to display -// -// For the record, mime-types which must NEVER enter this list below include: -// text/html, text/xhtml, image/svg, image/svg+xml, image/pdf, and similar. - -const ALLOWED_BLOB_MIMETYPES = [ - 'image/jpeg', - 'image/gif', - 'image/png', - - 'video/mp4', - 'video/webm', - 'video/ogg', - - 'audio/mp4', - 'audio/webm', - 'audio/aac', - 'audio/mpeg', - 'audio/ogg', - 'audio/wave', - 'audio/wav', - 'audio/x-wav', - 'audio/x-pn-wav', - 'audio/flac', - 'audio/x-flac', -]; +import { IEncryptedFile } from "../customisations/models/IMediaEventContent"; +import { getBlobSafeMimeType } from "./blobs"; /** * Decrypt a file attached to a matrix event. @@ -100,9 +45,7 @@ export function decryptFile(file: IEncryptedFile): Promise { // browser (e.g. by copying the URI into a new tab or window.) // See warning at top of file. let mimetype = file.mimetype ? file.mimetype.split(";")[0].trim() : ''; - if (!ALLOWED_BLOB_MIMETYPES.includes(mimetype)) { - mimetype = 'application/octet-stream'; - } + mimetype = getBlobSafeMimeType(mimetype); return new Blob([dataArray], {type: mimetype}); }); diff --git a/src/utils/blobs.ts b/src/utils/blobs.ts new file mode 100644 index 0000000000..4e073a3936 --- /dev/null +++ b/src/utils/blobs.ts @@ -0,0 +1,78 @@ +/* +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. +*/ + +// WARNING: We have to be very careful about what mime-types we allow into blobs, +// as for performance reasons these are now rendered via URL.createObjectURL() +// rather than by converting into data: URIs. +// +// This means that the content is rendered using the origin of the script which +// called createObjectURL(), and so if the content contains any scripting then it +// will pose a XSS vulnerability when the browser renders it. This is particularly +// bad if the user right-clicks the URI and pastes it into a new window or tab, +// as the blob will then execute with access to Element's full JS environment(!) +// +// See https://github.com/matrix-org/matrix-react-sdk/pull/1820#issuecomment-385210647 +// for details. +// +// We mitigate this by only allowing mime-types into blobs which we know don't +// contain any scripting, and instantiate all others as application/octet-stream +// regardless of what mime-type the event claimed. Even if the payload itself +// is some malicious HTML, the fact we instantiate it with a media mimetype or +// application/octet-stream means the browser doesn't try to render it as such. +// +// One interesting edge case is image/svg+xml, which empirically *is* rendered +// correctly if the blob is set to the src attribute of an img tag (for thumbnails) +// *even if the mimetype is application/octet-stream*. However, empirically JS +// in the SVG isn't executed in this scenario, so we seem to be okay. +// +// Tested on Chrome 65 and Firefox 60 +// +// The list below is taken mainly from +// https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats +// N.B. Matrix doesn't currently specify which mimetypes are valid in given +// events, so we pick the ones which HTML5 browsers should be able to display +// +// For the record, mime-types which must NEVER enter this list below include: +// text/html, text/xhtml, image/svg, image/svg+xml, image/pdf, and similar. + +const ALLOWED_BLOB_MIMETYPES = [ + 'image/jpeg', + 'image/gif', + 'image/png', + + 'video/mp4', + 'video/webm', + 'video/ogg', + + 'audio/mp4', + 'audio/webm', + 'audio/aac', + 'audio/mpeg', + 'audio/ogg', + 'audio/wave', + 'audio/wav', + 'audio/x-wav', + 'audio/x-pn-wav', + 'audio/flac', + 'audio/x-flac', +]; + +export function getBlobSafeMimeType(mimetype: string): string { + if (!ALLOWED_BLOB_MIMETYPES.includes(mimetype)) { + return 'application/octet-stream'; + } + return mimetype; +} From 437f13cf764cfcc289bddb758f6eff73f4c93649 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Thu, 6 May 2021 14:11:34 +0100 Subject: [PATCH 0253/1449] Convert UploadConfirmDialog to TSX --- ...nfirmDialog.js => UploadConfirmDialog.tsx} | 39 ++++++++++--------- 1 file changed, 20 insertions(+), 19 deletions(-) rename src/components/views/dialogs/{UploadConfirmDialog.js => UploadConfirmDialog.tsx} (80%) diff --git a/src/components/views/dialogs/UploadConfirmDialog.js b/src/components/views/dialogs/UploadConfirmDialog.tsx similarity index 80% rename from src/components/views/dialogs/UploadConfirmDialog.js rename to src/components/views/dialogs/UploadConfirmDialog.tsx index 2ff16b9440..8fdfbfda12 100644 --- a/src/components/views/dialogs/UploadConfirmDialog.js +++ b/src/components/views/dialogs/UploadConfirmDialog.tsx @@ -1,5 +1,5 @@ /* -Copyright 2019 New Vector Ltd +Copyright 2019, 2021 The Matrix.org Foundation C.I.C. Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> Licensed under the Apache License, Version 2.0 (the "License"); @@ -16,20 +16,21 @@ limitations under the License. */ import React from 'react'; -import PropTypes from 'prop-types'; import * as sdk from '../../../index'; import { _t } from '../../../languageHandler'; import filesize from "filesize"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; + +interface IProps { + file: File; + currentIndex: number; + totalFiles?: number; + onFinished: (uploadConfirmed: boolean, uploadAll?: boolean) => void; +} @replaceableComponent("views.dialogs.UploadConfirmDialog") -export default class UploadConfirmDialog extends React.Component { - static propTypes = { - file: PropTypes.object.isRequired, - currentIndex: PropTypes.number, - totalFiles: PropTypes.number, - onFinished: PropTypes.func.isRequired, - } +export default class UploadConfirmDialog extends React.Component { + private objectUrl: string; static defaultProps = { totalFiles: 1, @@ -38,22 +39,22 @@ export default class UploadConfirmDialog extends React.Component { constructor(props) { super(props); - this._objectUrl = URL.createObjectURL(props.file); + this.objectUrl = URL.createObjectURL(props.file); } componentWillUnmount() { - if (this._objectUrl) URL.revokeObjectURL(this._objectUrl); + if (this.objectUrl) URL.revokeObjectURL(this.objectUrl); } - _onCancelClick = () => { + private onCancelClick = () => { this.props.onFinished(false); } - _onUploadClick = () => { + private onUploadClick = () => { this.props.onFinished(true); } - _onUploadAllClick = () => { + private onUploadAllClick = () => { this.props.onFinished(true, true); } @@ -78,7 +79,7 @@ export default class UploadConfirmDialog extends React.Component { if (this.props.file.type.startsWith('image/')) { preview =
    -
    +
    {this.props.file.name} ({filesize(this.props.file.size)})
    ; @@ -95,7 +96,7 @@ export default class UploadConfirmDialog extends React.Component { let uploadAllButton; if (this.props.currentIndex + 1 < this.props.totalFiles) { - uploadAllButton = ; } @@ -103,7 +104,7 @@ export default class UploadConfirmDialog extends React.Component { return ( @@ -113,7 +114,7 @@ export default class UploadConfirmDialog extends React.Component { {uploadAllButton} From dc50d27985a94a2e8f5290e4ac645461f0d272af Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Thu, 6 May 2021 14:39:44 +0100 Subject: [PATCH 0254/1449] Adjust MIME type of upload confirmation if needed This filters the MIME type of uploaded files to ensure we display safely. --- src/components/views/dialogs/UploadConfirmDialog.tsx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/components/views/dialogs/UploadConfirmDialog.tsx b/src/components/views/dialogs/UploadConfirmDialog.tsx index 8fdfbfda12..7f6bcd27d1 100644 --- a/src/components/views/dialogs/UploadConfirmDialog.tsx +++ b/src/components/views/dialogs/UploadConfirmDialog.tsx @@ -20,6 +20,7 @@ import * as sdk from '../../../index'; import { _t } from '../../../languageHandler'; import filesize from "filesize"; import { replaceableComponent } from "../../../utils/replaceableComponent"; +import { getBlobSafeMimeType } from '../../../utils/blobs'; interface IProps { file: File; @@ -31,6 +32,7 @@ interface IProps { @replaceableComponent("views.dialogs.UploadConfirmDialog") export default class UploadConfirmDialog extends React.Component { private objectUrl: string; + private mimeType: string; static defaultProps = { totalFiles: 1, @@ -39,7 +41,13 @@ export default class UploadConfirmDialog extends React.Component { constructor(props) { super(props); - this.objectUrl = URL.createObjectURL(props.file); + // Create a fresh `Blob` for previewing (even though `File` already is + // one) so we can adjust the MIME type if needed. + this.mimeType = getBlobSafeMimeType(props.file.type); + const blob = new Blob([props.file], { type: + this.mimeType, + }); + this.objectUrl = URL.createObjectURL(blob); } componentWillUnmount() { @@ -76,7 +84,7 @@ export default class UploadConfirmDialog extends React.Component { } let preview; - if (this.props.file.type.startsWith('image/')) { + if (this.mimeType.startsWith('image/')) { preview =
    From bb9803a94ec83bb375e4b0c7df9c1b9572d2ff93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 6 May 2021 16:40:33 +0200 Subject: [PATCH 0255/1449] Don't try to use the event's metadata to calc the scale MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit That has lead to https://github.com/vector-im/element-web/issues/17184 Signed-off-by: Šimon Brandner --- src/components/views/elements/ImageView.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/components/views/elements/ImageView.tsx b/src/components/views/elements/ImageView.tsx index 05d487a9eb..2b3ead3940 100644 --- a/src/components/views/elements/ImageView.tsx +++ b/src/components/views/elements/ImageView.tsx @@ -108,8 +108,6 @@ export default class ImageView extends React.Component { window.addEventListener("resize", this.calculateZoom); // After the image loads for the first time we want to calculate the zoom this.image.current.addEventListener("load", this.calculateZoom); - // Try to precalculate the zoom from width and height props - this.calculateZoom(); } componentWillUnmount() { @@ -122,8 +120,8 @@ export default class ImageView extends React.Component { const image = this.image.current; const imageWrapper = this.imageWrapper.current; - const width = this.props.width || image.naturalWidth; - const height = this.props.height || image.naturalHeight; + const width = image.naturalWidth; + const height = image.naturalHeight; const zoomX = imageWrapper.clientWidth / width; const zoomY = imageWrapper.clientHeight / height; From 7ad270928ab9b94a38463484b07458fe74fa3c67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 6 May 2021 16:41:09 +0200 Subject: [PATCH 0256/1449] Simplifie code a bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/elements/ImageView.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/components/views/elements/ImageView.tsx b/src/components/views/elements/ImageView.tsx index 2b3ead3940..f736736acc 100644 --- a/src/components/views/elements/ImageView.tsx +++ b/src/components/views/elements/ImageView.tsx @@ -120,11 +120,8 @@ export default class ImageView extends React.Component { const image = this.image.current; const imageWrapper = this.imageWrapper.current; - const width = image.naturalWidth; - const height = image.naturalHeight; - - const zoomX = imageWrapper.clientWidth / width; - const zoomY = imageWrapper.clientHeight / height; + const zoomX = imageWrapper.clientWidth / image.naturalWidth; + const zoomY = imageWrapper.clientHeight / image.naturalHeight; // If the image is smaller in both dimensions set its the zoom to 1 to // display it in its original size From d2fc1c42b09412f1d8884fb6a6f73bd1e049d402 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 6 May 2021 15:58:22 +0100 Subject: [PATCH 0257/1449] Improve style of notification badges on the space panel --- res/css/structures/_SpacePanel.scss | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/res/css/structures/_SpacePanel.scss b/res/css/structures/_SpacePanel.scss index 9264e82ea5..b656ffa6ac 100644 --- a/res/css/structures/_SpacePanel.scss +++ b/res/css/structures/_SpacePanel.scss @@ -237,7 +237,6 @@ $activeBorderColor: $secondary-fg-color; .mx_SpacePanel_badgeContainer { position: absolute; - height: 16px; // Create a flexbox to make aligning dot badges easier display: flex; @@ -249,23 +248,37 @@ $activeBorderColor: $secondary-fg-color; .mx_NotificationBadge_dot { // make the smaller dot occupy the same width for centering - margin-left: 7px; - margin-right: 7px; + margin: 0 7px; } } &.collapsed { .mx_SpaceButton { .mx_SpacePanel_badgeContainer { - right: -3px; - top: -3px; + right: 0; + top: 0; + + .mx_NotificationBadge { + background-clip: padding-box; + } + + .mx_NotificationBadge_dot { + margin: 1px -1px 0 0; + border: 3px solid $groupFilterPanel-bg-color; + } + + .mx_NotificationBadge_2char, + .mx_NotificationBadge_3char { + margin: -5px -5px 0 0; + border: 2px solid $groupFilterPanel-bg-color; + } } &.mx_SpaceButton_active .mx_SpacePanel_badgeContainer { // when we draw the selection border we move the relative bounds of our parent // so update our position within the bounds of the parent to maintain position overall - right: -6px; - top: -6px; + right: -3px; + top: -3px; } } } From d924c7a1869034ee3aefc2eef6f4b4e9c1e60f55 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 6 May 2021 22:22:53 +0000 Subject: [PATCH 0258/1449] Bump ua-parser-js from 0.7.23 to 0.7.28 Bumps [ua-parser-js](https://github.com/faisalman/ua-parser-js) from 0.7.23 to 0.7.28. - [Release notes](https://github.com/faisalman/ua-parser-js/releases) - [Commits](https://github.com/faisalman/ua-parser-js/compare/0.7.23...0.7.28) Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index acdca26e55..22866a7af4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8070,9 +8070,9 @@ typescript@^4.1.3: integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg== ua-parser-js@^0.7.18: - version "0.7.23" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.23.tgz#704d67f951e13195fbcd3d78818577f5bc1d547b" - integrity sha512-m4hvMLxgGHXG3O3fQVAyyAQpZzDOvwnhOTjYz5Xmr7r/+LpkNy3vJXdVRWgd1TkAb7NGROZuSy96CrlNVjA7KA== + version "0.7.28" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.28.tgz#8ba04e653f35ce210239c64661685bf9121dec31" + integrity sha512-6Gurc1n//gjp9eQNXjD9O3M/sMwVtN5S8Lv9bvOYBfKfDNiIIhqiyi01vMBO45u4zkDE420w/e0se7Vs+sIg+g== unhomoglyph@^1.0.6: version "1.0.6" From 5d7535738ab6001ab581d47621d75171df6da413 Mon Sep 17 00:00:00 2001 From: Aaron Raimist Date: Thu, 6 May 2021 20:01:48 -0500 Subject: [PATCH 0259/1449] Show device ID in UserInfo when there is no device name Signed-off-by: Aaron Raimist --- src/components/views/right_panel/UserInfo.tsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/components/views/right_panel/UserInfo.tsx b/src/components/views/right_panel/UserInfo.tsx index be152d91bd..e50e71535d 100644 --- a/src/components/views/right_panel/UserInfo.tsx +++ b/src/components/views/right_panel/UserInfo.tsx @@ -187,9 +187,15 @@ function DeviceItem({userId, device}: {userId: string, device: IDevice}) { verifyDevice(cli.getUser(userId), device); }; - const deviceName = device.ambiguous ? - (device.getDisplayName() ? device.getDisplayName() : "") + " (" + device.deviceId + ")" : - device.getDisplayName(); + let deviceName; + if (device.getDisplayName() === null || device.getDisplayName().trim() === "") { + deviceName = device.deviceId; + } else { + deviceName = device.ambiguous ? + device.getDisplayName() + " (" + device.deviceId + ")" : + device.getDisplayName(); + } + let trustedLabel = null; if (userTrust.isVerified()) trustedLabel = isVerified ? _t("Trusted") : _t("Not trusted"); From b37985a5d20254e1e2bdb1c887537f5ee05f623b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 May 2021 01:13:44 +0000 Subject: [PATCH 0260/1449] Bump lodash from 4.17.20 to 4.17.21 Bumps [lodash](https://github.com/lodash/lodash) from 4.17.20 to 4.17.21. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.20...4.17.21) Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 22866a7af4..9b33c4387b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5580,9 +5580,9 @@ lodash.sortby@^4.7.0: integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.2.1: - version "4.17.20" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" - integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== log-symbols@^4.0.0: version "4.0.0" From 137189932e06e785e5e3bd20ac9d919a760e0b00 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 May 2021 01:13:47 +0000 Subject: [PATCH 0261/1449] Bump lodash from 4.17.19 to 4.17.21 in /test/end-to-end-tests Bumps [lodash](https://github.com/lodash/lodash) from 4.17.19 to 4.17.21. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.19...4.17.21) Signed-off-by: dependabot[bot] --- test/end-to-end-tests/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/end-to-end-tests/yarn.lock b/test/end-to-end-tests/yarn.lock index 7f2cefb92e..97b348fe50 100644 --- a/test/end-to-end-tests/yarn.lock +++ b/test/end-to-end-tests/yarn.lock @@ -435,9 +435,9 @@ jsprim@^1.2.2: verror "1.10.0" lodash@^4.15.0, lodash@^4.17.11: - version "4.17.19" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" - integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== mime-db@~1.38.0: version "1.38.0" From d270e232fd935e00a3fb2aa20669ca0fd74ba255 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 6 May 2021 21:40:58 -0600 Subject: [PATCH 0262/1449] Fix voice message playback being squished up against send button In the style shuffle of https://github.com/matrix-org/matrix-react-sdk/pull/5970 the playback bar got squished up against the send button. This just fixes the selector to actually hit the composer-based recorder all the time, not just when recording. --- res/css/views/rooms/_VoiceRecordComposerTile.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/res/css/views/rooms/_VoiceRecordComposerTile.scss b/res/css/views/rooms/_VoiceRecordComposerTile.scss index b87211a847..a3ee104bd8 100644 --- a/res/css/views/rooms/_VoiceRecordComposerTile.scss +++ b/res/css/views/rooms/_VoiceRecordComposerTile.scss @@ -46,11 +46,11 @@ limitations under the License. mask-image: url('$(res)/img/element-icons/trashcan.svg'); } -.mx_VoiceRecordComposerTile_recording.mx_VoiceMessagePrimaryContainer { +.mx_MessageComposer_row .mx_VoiceMessagePrimaryContainer { // Note: remaining class properties are in the PlayerContainer CSS. margin: 6px; // force the composer area to put a gutter around us - margin-right: 12px; // isolate from stop button + margin-right: 12px; // isolate from stop/send button position: relative; // important for the live circle From b61fe2f8e6b2f776f1df25bc9d159f931ea61f37 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 5 May 2021 22:30:22 -0600 Subject: [PATCH 0263/1449] Improve error recovery when starting a recording This helps return the microphone access to the user. --- src/rageshake/rageshake.js | 4 +- src/voice/VoiceRecording.ts | 153 ++++++++++++++++++++---------------- 2 files changed, 89 insertions(+), 68 deletions(-) diff --git a/src/rageshake/rageshake.js b/src/rageshake/rageshake.js index b886f369df..9512f62e42 100644 --- a/src/rageshake/rageshake.js +++ b/src/rageshake/rageshake.js @@ -73,7 +73,9 @@ class ConsoleLogger { // Convert objects and errors to helpful things args = args.map((arg) => { - if (arg instanceof Error) { + if (arg instanceof DOMException) { + return arg.message + ` (${arg.name} | ${arg.code}) ` + (arg.stack ? `\n${arg.stack}` : ''); + } else if (arg instanceof Error) { return arg.message + (arg.stack ? `\n${arg.stack}` : ''); } else if (typeof (arg) === 'object') { try { diff --git a/src/voice/VoiceRecording.ts b/src/voice/VoiceRecording.ts index c4a0a78ce5..402bd8beca 100644 --- a/src/voice/VoiceRecording.ts +++ b/src/voice/VoiceRecording.ts @@ -90,78 +90,97 @@ export class VoiceRecording extends EventEmitter implements IDestroyable { } private async makeRecorder() { - this.recorderStream = await navigator.mediaDevices.getUserMedia({ - audio: { - channelCount: CHANNELS, - noiseSuppression: true, // browsers ignore constraints they can't honour - deviceId: CallMediaHandler.getAudioInput(), - }, - }); - this.recorderContext = new AudioContext({ - // latencyHint: "interactive", // we don't want a latency hint (this causes data smoothing) - }); - this.recorderSource = this.recorderContext.createMediaStreamSource(this.recorderStream); - this.recorderFFT = this.recorderContext.createAnalyser(); + try { + this.recorderStream = await navigator.mediaDevices.getUserMedia({ + audio: { + channelCount: CHANNELS, + noiseSuppression: true, // browsers ignore constraints they can't honour + deviceId: CallMediaHandler.getAudioInput(), + }, + }); + this.recorderContext = new AudioContext({ + // latencyHint: "interactive", // we don't want a latency hint (this causes data smoothing) + }); + this.recorderSource = this.recorderContext.createMediaStreamSource(this.recorderStream); + this.recorderFFT = this.recorderContext.createAnalyser(); - // Bring the FFT time domain down a bit. The default is 2048, and this must be a power - // of two. We use 64 points because we happen to know down the line we need less than - // that, but 32 would be too few. Large numbers are not helpful here and do not add - // precision: they introduce higher precision outputs of the FFT (frequency data), but - // it makes the time domain less than helpful. - this.recorderFFT.fftSize = 64; + // Bring the FFT time domain down a bit. The default is 2048, and this must be a power + // of two. We use 64 points because we happen to know down the line we need less than + // that, but 32 would be too few. Large numbers are not helpful here and do not add + // precision: they introduce higher precision outputs of the FFT (frequency data), but + // it makes the time domain less than helpful. + this.recorderFFT.fftSize = 64; - // Set up our worklet. We use this for timing information and waveform analysis: the - // web audio API prefers this be done async to avoid holding the main thread with math. - const mxRecorderWorkletPath = document.body.dataset.vectorRecorderWorkletScript; - if (!mxRecorderWorkletPath) { - throw new Error("Unable to create recorder: no worklet script registered"); - } - await this.recorderContext.audioWorklet.addModule(mxRecorderWorkletPath); - this.recorderWorklet = new AudioWorkletNode(this.recorderContext, WORKLET_NAME); - - // Connect our inputs and outputs - this.recorderSource.connect(this.recorderFFT); - this.recorderSource.connect(this.recorderWorklet); - this.recorderWorklet.connect(this.recorderContext.destination); - - // Dev note: we can't use `addEventListener` for some reason. It just doesn't work. - this.recorderWorklet.port.onmessage = (ev) => { - switch (ev.data['ev']) { - case PayloadEvent.Timekeep: - this.processAudioUpdate(ev.data['timeSeconds']); - break; - case PayloadEvent.AmplitudeMark: - // Sanity check to make sure we're adding about one sample per second - if (ev.data['forSecond'] === this.amplitudes.length) { - this.amplitudes.push(ev.data['amplitude']); - } - break; + // Set up our worklet. We use this for timing information and waveform analysis: the + // web audio API prefers this be done async to avoid holding the main thread with math. + const mxRecorderWorkletPath = document.body.dataset.vectorRecorderWorkletScript; + if (!mxRecorderWorkletPath) { + // noinspection ExceptionCaughtLocallyJS + throw new Error("Unable to create recorder: no worklet script registered"); } - }; + await this.recorderContext.audioWorklet.addModule(mxRecorderWorkletPath); + this.recorderWorklet = new AudioWorkletNode(this.recorderContext, WORKLET_NAME); - this.recorder = new Recorder({ - encoderPath, // magic from webpack - encoderSampleRate: SAMPLE_RATE, - encoderApplication: 2048, // voice (default is "audio") - streamPages: true, // this speeds up the encoding process by using CPU over time - encoderFrameSize: 20, // ms, arbitrary frame size we send to the encoder - numberOfChannels: CHANNELS, - sourceNode: this.recorderSource, - encoderBitRate: BITRATE, + // Connect our inputs and outputs + this.recorderSource.connect(this.recorderFFT); + this.recorderSource.connect(this.recorderWorklet); + this.recorderWorklet.connect(this.recorderContext.destination); - // We use low values for the following to ease CPU usage - the resulting waveform - // is indistinguishable for a voice message. Note that the underlying library will - // pick defaults which prefer the highest possible quality, CPU be damned. - encoderComplexity: 3, // 0-10, 10 is slow and high quality. - resampleQuality: 3, // 0-10, 10 is slow and high quality - }); - this.recorder.ondataavailable = (a: ArrayBuffer) => { - const buf = new Uint8Array(a); - const newBuf = new Uint8Array(this.buffer.length + buf.length); - newBuf.set(this.buffer, 0); - newBuf.set(buf, this.buffer.length); - this.buffer = newBuf; - }; + // Dev note: we can't use `addEventListener` for some reason. It just doesn't work. + this.recorderWorklet.port.onmessage = (ev) => { + switch (ev.data['ev']) { + case PayloadEvent.Timekeep: + this.processAudioUpdate(ev.data['timeSeconds']); + break; + case PayloadEvent.AmplitudeMark: + // Sanity check to make sure we're adding about one sample per second + if (ev.data['forSecond'] === this.amplitudes.length) { + this.amplitudes.push(ev.data['amplitude']); + } + break; + } + }; + + this.recorder = new Recorder({ + encoderPath, // magic from webpack + encoderSampleRate: SAMPLE_RATE, + encoderApplication: 2048, // voice (default is "audio") + streamPages: true, // this speeds up the encoding process by using CPU over time + encoderFrameSize: 20, // ms, arbitrary frame size we send to the encoder + numberOfChannels: CHANNELS, + sourceNode: this.recorderSource, + encoderBitRate: BITRATE, + + // We use low values for the following to ease CPU usage - the resulting waveform + // is indistinguishable for a voice message. Note that the underlying library will + // pick defaults which prefer the highest possible quality, CPU be damned. + encoderComplexity: 3, // 0-10, 10 is slow and high quality. + resampleQuality: 3, // 0-10, 10 is slow and high quality + }); + this.recorder.ondataavailable = (a: ArrayBuffer) => { + const buf = new Uint8Array(a); + const newBuf = new Uint8Array(this.buffer.length + buf.length); + newBuf.set(this.buffer, 0); + newBuf.set(buf, this.buffer.length); + this.buffer = newBuf; + }; + } catch (e) { + console.error("Error starting recording: ", e); + if (e instanceof DOMException) { // Unhelpful DOMExceptions are common - parse them sanely + console.error(`${e.name} (${e.code}): ${e.message}`); + } + + // Clean up as best as possible + if (this.recorderStream) this.recorderStream.getTracks().forEach(t => t.stop()); + if (this.recorderSource) this.recorderSource.disconnect(); + if (this.recorder) this.recorder.close(); + if (this.recorderContext) { + // noinspection ES6MissingAwait - not important that we wait + this.recorderContext.close(); + } + + throw e; // rethrow so upstream can handle it + } } private get audioBuffer(): Uint8Array { From b08e47bfe1d477cb883f80ef4955fad9b5ea36a0 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 6 May 2021 21:38:48 -0600 Subject: [PATCH 0264/1449] Support compatibility points for Safari Tested on MacOS Big Sur, Safari 14.0.3 --- src/@types/global.d.ts | 3 ++ src/voice/Playback.ts | 21 +++++++++- src/voice/VoiceRecording.ts | 78 ++++++++++++++++++++++++++----------- src/voice/compat.ts | 78 +++++++++++++++++++++++++++++++++++++ 4 files changed, 155 insertions(+), 25 deletions(-) create mode 100644 src/voice/compat.ts diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts index e8f2f1bc08..f04a2ff237 100644 --- a/src/@types/global.d.ts +++ b/src/@types/global.d.ts @@ -52,6 +52,9 @@ declare global { init: () => Promise; }; + // Needed for Safari, unknown to TypeScript + webkitAudioContext: typeof AudioContext; + mxContentMessages: ContentMessages; mxToastStore: ToastStore; mxDeviceListener: DeviceListener; diff --git a/src/voice/Playback.ts b/src/voice/Playback.ts index caa5241e1a..66667b9c0c 100644 --- a/src/voice/Playback.ts +++ b/src/voice/Playback.ts @@ -21,6 +21,7 @@ import {SimpleObservable} from "matrix-widget-api"; import {IDestroyable} from "../utils/IDestroyable"; import {PlaybackClock} from "./PlaybackClock"; import {clamp} from "../utils/numbers"; +import {createAudioContext, decodeOgg} from "./compat"; export enum PlaybackState { Decoding = "decoding", @@ -49,7 +50,7 @@ export class Playback extends EventEmitter implements IDestroyable { */ constructor(private buf: ArrayBuffer, seedWaveform = DEFAULT_WAVEFORM) { super(); - this.context = new AudioContext(); + this.context = createAudioContext(); this.resampledWaveform = arrayFastResample(seedWaveform ?? DEFAULT_WAVEFORM, PLAYBACK_WAVEFORM_SAMPLES); this.waveformObservable.update(this.resampledWaveform); this.clock = new PlaybackClock(this.context); @@ -91,7 +92,23 @@ export class Playback extends EventEmitter implements IDestroyable { } public async prepare() { - this.audioBuf = await this.context.decodeAudioData(this.buf); + // Safari compat: promise API not supported on this function + this.audioBuf = await new Promise((resolve, reject) => { + this.context.decodeAudioData(this.buf, b => resolve(b), async e => { + // This error handler is largely for Safari as well, which doesn't support Opus/Ogg + // very well. + console.error("Error decoding recording: ", e); + console.warn("Trying to re-encode to WAV instead..."); + + const wav = await decodeOgg(this.buf); + + // noinspection ES6MissingAwait - not needed when using callbacks + this.context.decodeAudioData(wav, b => resolve(b), e => { + console.error("Still failed to decode recording: ", e); + reject(e); + }); + }); + }); // Update the waveform to the real waveform once we have channel data to use. We don't // exactly trust the user-provided waveform to be accurate... diff --git a/src/voice/VoiceRecording.ts b/src/voice/VoiceRecording.ts index 402bd8beca..fde5779fa2 100644 --- a/src/voice/VoiceRecording.ts +++ b/src/voice/VoiceRecording.ts @@ -19,16 +19,17 @@ import encoderPath from 'opus-recorder/dist/encoderWorker.min.js'; import {MatrixClient} from "matrix-js-sdk/src/client"; import CallMediaHandler from "../CallMediaHandler"; import {SimpleObservable} from "matrix-widget-api"; -import {clamp} from "../utils/numbers"; +import {clamp, percentageOf, percentageWithin} from "../utils/numbers"; import EventEmitter from "events"; import {IDestroyable} from "../utils/IDestroyable"; import {Singleflight} from "../utils/Singleflight"; import {PayloadEvent, WORKLET_NAME} from "./consts"; import {UPDATE_EVENT} from "../stores/AsyncStore"; import {Playback} from "./Playback"; +import {createAudioContext} from "./compat"; const CHANNELS = 1; // stereo isn't important -const SAMPLE_RATE = 48000; // 48khz is what WebRTC uses. 12khz is where we lose quality. +export const SAMPLE_RATE = 48000; // 48khz is what WebRTC uses. 12khz is where we lose quality. const BITRATE = 24000; // 24kbps is pretty high quality for our use case in opus. const TARGET_MAX_LENGTH = 120; // 2 minutes in seconds. Somewhat arbitrary, though longer == larger files. const TARGET_WARN_TIME_LEFT = 10; // 10 seconds, also somewhat arbitrary. @@ -55,6 +56,7 @@ export class VoiceRecording extends EventEmitter implements IDestroyable { private recorderStream: MediaStream; private recorderFFT: AnalyserNode; private recorderWorklet: AudioWorkletNode; + private recorderProcessor: ScriptProcessorNode; private buffer = new Uint8Array(0); // use this.audioBuffer to access private mxc: string; private recording = false; @@ -98,7 +100,7 @@ export class VoiceRecording extends EventEmitter implements IDestroyable { deviceId: CallMediaHandler.getAudioInput(), }, }); - this.recorderContext = new AudioContext({ + this.recorderContext = createAudioContext({ // latencyHint: "interactive", // we don't want a latency hint (this causes data smoothing) }); this.recorderSource = this.recorderContext.createMediaStreamSource(this.recorderStream); @@ -118,28 +120,38 @@ export class VoiceRecording extends EventEmitter implements IDestroyable { // noinspection ExceptionCaughtLocallyJS throw new Error("Unable to create recorder: no worklet script registered"); } - await this.recorderContext.audioWorklet.addModule(mxRecorderWorkletPath); - this.recorderWorklet = new AudioWorkletNode(this.recorderContext, WORKLET_NAME); // Connect our inputs and outputs this.recorderSource.connect(this.recorderFFT); - this.recorderSource.connect(this.recorderWorklet); - this.recorderWorklet.connect(this.recorderContext.destination); - // Dev note: we can't use `addEventListener` for some reason. It just doesn't work. - this.recorderWorklet.port.onmessage = (ev) => { - switch (ev.data['ev']) { - case PayloadEvent.Timekeep: - this.processAudioUpdate(ev.data['timeSeconds']); - break; - case PayloadEvent.AmplitudeMark: - // Sanity check to make sure we're adding about one sample per second - if (ev.data['forSecond'] === this.amplitudes.length) { - this.amplitudes.push(ev.data['amplitude']); - } - break; - } - }; + if (this.recorderContext.audioWorklet) { + await this.recorderContext.audioWorklet.addModule(mxRecorderWorkletPath); + this.recorderWorklet = new AudioWorkletNode(this.recorderContext, WORKLET_NAME); + this.recorderSource.connect(this.recorderWorklet); + this.recorderWorklet.connect(this.recorderContext.destination); + + // Dev note: we can't use `addEventListener` for some reason. It just doesn't work. + this.recorderWorklet.port.onmessage = (ev) => { + switch (ev.data['ev']) { + case PayloadEvent.Timekeep: + this.processAudioUpdate(ev.data['timeSeconds']); + break; + case PayloadEvent.AmplitudeMark: + // Sanity check to make sure we're adding about one sample per second + if (ev.data['forSecond'] === this.amplitudes.length) { + this.amplitudes.push(ev.data['amplitude']); + } + break; + } + }; + } else { + // Safari fallback: use a processor node instead, buffered to 1024 bytes of data + // like the worklet is. + this.recorderProcessor = this.recorderContext.createScriptProcessor(1024, CHANNELS, CHANNELS); + this.recorderSource.connect(this.recorderProcessor); + this.recorderProcessor.connect(this.recorderContext.destination); + this.recorderProcessor.addEventListener("audioprocess", this.onAudioProcess); + } this.recorder = new Recorder({ encoderPath, // magic from webpack @@ -209,6 +221,13 @@ export class VoiceRecording extends EventEmitter implements IDestroyable { return this.mxc; } + private onAudioProcess = (ev: AudioProcessingEvent) => { + this.processAudioUpdate(ev.playbackTime); + + // We skip the functionality of the worklet regarding waveform calculations: we + // should get that information pretty quick during the playback info. + }; + private processAudioUpdate = (timeSeconds: number) => { if (!this.recording) return; @@ -216,7 +235,16 @@ export class VoiceRecording extends EventEmitter implements IDestroyable { // size. The time domain is also known as the audio waveform. We're ignoring the // output of the FFT here (frequency data) because we're not interested in it. const data = new Float32Array(this.recorderFFT.fftSize); - this.recorderFFT.getFloatTimeDomainData(data); + if (!this.recorderFFT.getFloatTimeDomainData) { + // Safari compat + const data2 = new Uint8Array(this.recorderFFT.fftSize); + this.recorderFFT.getByteTimeDomainData(data2); + for (let i = 0; i < data2.length; i++) { + data[i] = percentageWithin(percentageOf(data2[i], 0, 256), -1, 1); + } + } else { + this.recorderFFT.getFloatTimeDomainData(data); + } // We can't just `Array.from()` the array because we're dealing with 32bit floats // and the built-in function won't consider that when converting between numbers. @@ -287,7 +315,11 @@ export class VoiceRecording extends EventEmitter implements IDestroyable { // Disconnect the source early to start shutting down resources await this.recorder.stop(); // stop first to flush the last frame this.recorderSource.disconnect(); - this.recorderWorklet.disconnect(); + if (this.recorderWorklet) this.recorderWorklet.disconnect(); + if (this.recorderProcessor) { + this.recorderProcessor.disconnect(); + this.recorderProcessor.removeEventListener("audioprocess", this.onAudioProcess); + } // close the context after the recorder so the recorder doesn't try to // connect anything to the context (this would generate a warning) diff --git a/src/voice/compat.ts b/src/voice/compat.ts new file mode 100644 index 0000000000..d91af31b6c --- /dev/null +++ b/src/voice/compat.ts @@ -0,0 +1,78 @@ +/* +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 wavEncoderPath from 'opus-recorder/dist/waveWorker.min.js'; +import decoderPath from 'opus-recorder/dist/decoderWorker.min.js'; +import {SAMPLE_RATE} from "./VoiceRecording"; +// @ts-ignore - we know that this is not a module. We're looking for a path. +import decoderWasmPath from 'opus-recorder/dist/decoderWorker.min.wasm'; + +export function createAudioContext(opts?: AudioContextOptions): AudioContext { + if (window.AudioContext) { + return new AudioContext(opts); + } else if (window.webkitAudioContext) { + return new window.webkitAudioContext(opts); + } else { + throw new Error("Unsupported browser"); + } +} + +export function decodeOgg(audioBuffer: ArrayBuffer): Promise { + // Condensed version of decoder example, using a promise: + // https://github.com/chris-rudmin/opus-recorder/blob/master/example/decoder.html + return new Promise((resolve) => { // no reject because the workers don't seem to have a fail path + console.log("Decoder WASM path: " + decoderWasmPath); // so we use the variable (avoid tree shake) + const typedArray = new Uint8Array(audioBuffer); + const decoderWorker = new Worker(decoderPath); + const wavWorker = new Worker(wavEncoderPath); + + decoderWorker.postMessage({ + command: 'init', + decoderSampleRate: SAMPLE_RATE, + outputBufferSampleRate: SAMPLE_RATE, + }); + + wavWorker.postMessage({ + command: 'init', + wavBitDepth: 24, // standard for 48khz (SAMPLE_RATE) + wavSampleRate: SAMPLE_RATE, + }); + + decoderWorker.onmessage = (ev) => { + if (ev.data === null) { // null == done + wavWorker.postMessage({command: 'done'}); + return; + } + + wavWorker.postMessage({ + command: 'encode', + buffers: ev.data, + }, ev.data.map(b => b.buffer)); + }; + + wavWorker.onmessage = (ev) => { + if (ev.data.message === 'page') { + // The encoding comes through as a single page + resolve(new Blob([ev.data.page], {type: "audio/wav"}).arrayBuffer()); + } + }; + + decoderWorker.postMessage({ + command: 'decode', + pages: typedArray, + }, [typedArray.buffer]); + }); +} From f65773ef95db8d873f33ba1fa1aa982c380a5e7c Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 6 May 2021 21:49:53 -0600 Subject: [PATCH 0265/1449] Appease the linter --- src/voice/compat.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/voice/compat.ts b/src/voice/compat.ts index d91af31b6c..45c56d5e69 100644 --- a/src/voice/compat.ts +++ b/src/voice/compat.ts @@ -24,6 +24,9 @@ export function createAudioContext(opts?: AudioContextOptions): AudioContext { if (window.AudioContext) { return new AudioContext(opts); } else if (window.webkitAudioContext) { + // While the linter is correct that "a constructor name should not start with + // a lowercase letter", it's also wrong to think that we have control over this. + // eslint-disable-next-line new-cap return new window.webkitAudioContext(opts); } else { throw new Error("Unsupported browser"); From 65f591b69b4b735ee9e2734aec7a3b0a0e93e487 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 6 May 2021 22:08:00 -0600 Subject: [PATCH 0266/1449] Make the tests happier Here we just override the workers because we're not expecting to be able to test them this way. The code paths involved shouldn't be touched. --- __mocks__/empty.js | 2 ++ package.json | 5 ++++- src/voice/compat.ts | 5 +++-- 3 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 __mocks__/empty.js diff --git a/__mocks__/empty.js b/__mocks__/empty.js new file mode 100644 index 0000000000..51fb4fe937 --- /dev/null +++ b/__mocks__/empty.js @@ -0,0 +1,2 @@ +// Yes, this is empty. +module.exports = {}; diff --git a/package.json b/package.json index e54de8a96c..d487603efb 100644 --- a/package.json +++ b/package.json @@ -185,7 +185,10 @@ ], "moduleNameMapper": { "\\.(gif|png|svg|ttf|woff2)$": "/__mocks__/imageMock.js", - "\\$webapp/i18n/languages.json": "/__mocks__/languages.json" + "\\$webapp/i18n/languages.json": "/__mocks__/languages.json", + "decoderWorker\\.min\\.js": "/__mocks__/empty.js", + "decoderWorker\\.min\\.wasm": "/__mocks__/empty.js", + "waveWorker\\.min\\.js": "/__mocks__/empty.js" }, "transformIgnorePatterns": [ "/node_modules/(?!matrix-js-sdk).+$" diff --git a/src/voice/compat.ts b/src/voice/compat.ts index 45c56d5e69..316d779e28 100644 --- a/src/voice/compat.ts +++ b/src/voice/compat.ts @@ -14,11 +14,12 @@ See the License for the specific language governing permissions and limitations under the License. */ -import wavEncoderPath from 'opus-recorder/dist/waveWorker.min.js'; -import decoderPath from 'opus-recorder/dist/decoderWorker.min.js'; import {SAMPLE_RATE} from "./VoiceRecording"; + // @ts-ignore - we know that this is not a module. We're looking for a path. import decoderWasmPath from 'opus-recorder/dist/decoderWorker.min.wasm'; +import wavEncoderPath from 'opus-recorder/dist/waveWorker.min.js'; +import decoderPath from 'opus-recorder/dist/decoderWorker.min.js'; export function createAudioContext(opts?: AudioContextOptions): AudioContext { if (window.AudioContext) { From d1f23fb99414181575ce90c6aa68e17ef8deda45 Mon Sep 17 00:00:00 2001 From: Ayush PS Date: Fri, 7 May 2021 11:45:52 +0530 Subject: [PATCH 0267/1449] Partially added the tests [WIP] --- .../structures/MessagePanel-test.js | 79 ++++++++++++++++++- test/test-utils.js | 33 ++++++++ 2 files changed, 108 insertions(+), 4 deletions(-) diff --git a/test/components/structures/MessagePanel-test.js b/test/components/structures/MessagePanel-test.js index 7347ff2658..55879a2f5c 100644 --- a/test/components/structures/MessagePanel-test.js +++ b/test/components/structures/MessagePanel-test.js @@ -77,7 +77,7 @@ describe('MessagePanel', function() { DMRoomMap.makeShared(); }); - afterEach(function() { + afterEach(function () { clock.uninstall(); }); @@ -88,7 +88,21 @@ describe('MessagePanel', function() { events.push(test_utils.mkMessage( { event: true, room: "!room:id", user: "@user:id", - ts: ts0 + i*1000, + ts: ts0 + i * 1000, + })); + } + return events; + } + + //Just to avoid breaking Dateseparator tests that might run at 00hrs + function mkOneDayEvents() { + const events = []; + const ts0 = Date.parse('09 May 2004 00:12:00 GMT'); + for (let i = 0; i < 10; i++) { + events.push(test_utils.mkMessage( + { + event: true, room: "!room:id", user: "@user:id", + ts: ts0 + i * 1000, })); } return events; @@ -104,7 +118,7 @@ describe('MessagePanel', function() { let i = 0; events.push(test_utils.mkMessage({ event: true, room: "!room:id", user: "@user:id", - ts: ts0 + ++i*1000, + ts: ts0 + ++i * 1000, })); for (i = 0; i < 10; i++) { @@ -151,7 +165,7 @@ describe('MessagePanel', function() { }, getMxcAvatarUrl: () => 'mxc://avatar.url/image.png', }, - ts: ts0 + i*1000, + ts: ts0 + i * 1000, mship: 'join', prevMship: 'join', name: 'A user', @@ -251,6 +265,33 @@ describe('MessagePanel', function() { ]; } + //Create a few redacted events + //isRedacted just checks the redacted_because + function mkRedactionEvents() { + const events = []; + const ts0 = Date.now(); + let i=0 + + let redaction = test_utils.mkEvent({ + type: "m.room.redaction", + event: true, room: "!room:id", user: "@user:id", ts: ts0 + ++i * 1000 , + content: {}, + }); + let event =test_utils.mkRedactedEvent({ + type: "m.room.message", + event: true, room: "!room:id", user: "@user:id", + ts: ts0 + i * 1000 , + // redacted_because: redaction This is not working at the moment + }) + redaction.redacts = event.event_id; + + events.push(event); + events.push(redaction); + + return events; + + } + function isReadMarkerVisible(rmContainer) { return rmContainer && rmContainer.children.length > 0; } @@ -437,4 +478,34 @@ describe('MessagePanel', function() { // read marker should be hidden given props and at the last event expect(isReadMarkerVisible(rm)).toBeFalsy(); }); + + it('should render Date separators for the events', function () { + const events = mkOneDayEvents() + const res = mount( + , + ); + const Dates = res.find(sdk.getComponent('messages.DateSeparator')); + + expect(Dates.length).toEqual(1); + + + }) + + it('should render only one Date separator for redacted events', function () { + const events = mkRedactionEvents() + const res = mount( + , + ); + const Dates = res.find(sdk.getComponent('messages.DateSeparator')); + + expect(Dates.length).toEqual(1); + + + }) }); diff --git a/test/test-utils.js b/test/test-utils.js index d259fcb95f..4d31241624 100644 --- a/test/test-utils.js +++ b/test/test-utils.js @@ -202,6 +202,39 @@ export function mkMessage(opts) { return mkEvent(opts); } + +/** + * Create an Redacted Event. + * @param {Object} opts Values for the event. + * @param {string} opts.type The event.type + * @param {string} opts.room The event.room_id + * @param {string} opts.user The event.user_id + * @param {string} opts.skey Optional. The state key (auto inserts empty string) + * @param {Number} opts.ts Optional. Timestamp for the event + * @param {Object} opts.content The event.content + * @param {boolean} opts.event True to make a MatrixEvent. + * @return {Object} a JSON object representing this event. + */ + export function mkRedactedEvent(opts) { + if (!opts.type ) { + throw new Error("Missing .type =>" + JSON.stringify(opts)); + } + const event = { + type: opts.type, + room_id: opts.room, + sender: opts.user, + content: {}, + prev_content: opts.prev_content, + event_id: "$" + Math.random() + "-" + Math.random(), + origin_server_ts: opts.ts, + //isRedacted() only checks if redacted_because is true or not + // unsigned :{redacted_because:opts.redacted_because} This is not working atm + }; + //Might want to add the other parameters for generalized tests + return opts.event ? new MatrixEvent(event) : event; +} + + export function mkStubRoom(roomId = null) { const stubTimeline = { getEvents: () => [] }; return { From f367d617c506325237b4f56b76a97819e5f715f8 Mon Sep 17 00:00:00 2001 From: Ayush PS Date: Fri, 7 May 2021 14:37:28 +0530 Subject: [PATCH 0268/1449] Added the extra classes --- res/css/views/rooms/_EventTile.scss | 7 +++++++ src/components/views/rooms/EventTile.js | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/res/css/views/rooms/_EventTile.scss b/res/css/views/rooms/_EventTile.scss index 5e110f9c6d..35a5d8fc15 100644 --- a/res/css/views/rooms/_EventTile.scss +++ b/res/css/views/rooms/_EventTile.scss @@ -123,11 +123,18 @@ $left-gutter: 64px; .mx_EventTile_line { margin-right: 0; grid-column: 1 / 3; + // override default padding of mx_EventTile_line so that we can be centered + padding: 0 !important; } .mx_EventTile_msgOption { grid-column: 2; } + + .hidden { + // override the overriden padding for hidden events + padding-left: 64px !important; + } } .mx_EventTile_reply { diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js index f6fb83c064..9e8f66705c 100644 --- a/src/components/views/rooms/EventTile.js +++ b/src/components/views/rooms/EventTile.js @@ -1101,7 +1101,7 @@ export default class EventTile extends React.Component { { ircTimestamp } { sender } { ircPadlock } -
    +
    { groupTimestamp } { groupPadlock } { thread } From db5c0012c258d7237afe1f0cb1e43a6a58f88948 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 7 May 2021 10:11:56 +0100 Subject: [PATCH 0269/1449] Add dev dependency for parse5 typings --- package.json | 1 + src/SlashCommands.tsx | 4 ++-- yarn.lock | 5 +++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index e54de8a96c..be195e2e9e 100644 --- a/package.json +++ b/package.json @@ -132,6 +132,7 @@ "@types/modernizr": "^3.5.3", "@types/node": "^14.14.22", "@types/pako": "^1.0.1", + "@types/parse5": "^6.0.0", "@types/qrcode": "^1.3.5", "@types/react": "^16.9", "@types/react-dom": "^16.9.10", diff --git a/src/SlashCommands.tsx b/src/SlashCommands.tsx index 6ce1439164..4a7b37b5e5 100644 --- a/src/SlashCommands.tsx +++ b/src/SlashCommands.tsx @@ -38,7 +38,7 @@ import {isPermalinkHost, parsePermalink} from "./utils/permalinks/Permalinks"; import {inviteUsersToRoom} from "./RoomInvite"; import { WidgetType } from "./widgets/WidgetType"; import { Jitsi } from "./widgets/Jitsi"; -import { parseFragment as parseHtml } from "parse5"; +import { parseFragment as parseHtml, Element as ChildElement } from "parse5"; import BugReportDialog from "./components/views/dialogs/BugReportDialog"; import { ensureDMExists } from "./createRoom"; import { ViewUserPayload } from "./dispatcher/payloads/ViewUserPayload"; @@ -856,7 +856,7 @@ export const Commands = [ // some superfast regex over the text so we don't have to. const embed = parseHtml(widgetUrl); if (embed && embed.childNodes && embed.childNodes.length === 1) { - const iframe = embed.childNodes[0]; + const iframe = embed.childNodes[0] as ChildElement; if (iframe.tagName.toLowerCase() === 'iframe' && iframe.attrs) { const srcAttr = iframe.attrs.find(a => a.name === 'src'); console.log("Pulling URL out of iframe (embed code)"); diff --git a/yarn.lock b/yarn.lock index acdca26e55..8464d4adf4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1594,6 +1594,11 @@ resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== +"@types/parse5@^6.0.0": + version "6.0.0" + resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-6.0.0.tgz#38590dc2c3cf5717154064e3ee9b6947ee21b299" + integrity sha512-oPwPSj4a1wu9rsXTEGIJz91ISU725t0BmSnUhb57sI+M8XEmvUop84lzuiYdq0Y5M6xLY8DBPg0C2xEQKLyvBA== + "@types/prettier@^2.0.0": version "2.1.6" resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.1.6.tgz#f4b1efa784e8db479cdb8b14403e2144b1e9ff03" From 03ca7e0107e2b67699e4472fc52e56dae5135fe7 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 7 May 2021 10:22:56 +0100 Subject: [PATCH 0270/1449] move notification dot on the space panel up by 1px --- res/css/structures/_SpacePanel.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/css/structures/_SpacePanel.scss b/res/css/structures/_SpacePanel.scss index b656ffa6ac..c433ccf275 100644 --- a/res/css/structures/_SpacePanel.scss +++ b/res/css/structures/_SpacePanel.scss @@ -263,7 +263,7 @@ $activeBorderColor: $secondary-fg-color; } .mx_NotificationBadge_dot { - margin: 1px -1px 0 0; + margin: 0 -1px 0 0; border: 3px solid $groupFilterPanel-bg-color; } From 4079b03ae00d997eb363f4f3e0d20b7ad63594a2 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 7 May 2021 10:39:35 +0100 Subject: [PATCH 0271/1449] Bring back filter all spaces behaviour --- src/components/structures/RoomSearch.tsx | 20 +++++++++++++++++-- .../views/rooms/RoomListNumResults.tsx | 6 +++++- src/stores/room-list/RoomListStore.ts | 18 +++++++++++++++-- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/components/structures/RoomSearch.tsx b/src/components/structures/RoomSearch.tsx index b3ceb1588f..bda46aef07 100644 --- a/src/components/structures/RoomSearch.tsx +++ b/src/components/structures/RoomSearch.tsx @@ -17,6 +17,7 @@ limitations under the License. import * as React from "react"; import { createRef } from "react"; import classNames from "classnames"; +import { Room } from "matrix-js-sdk/src/models/room"; import defaultDispatcher from "../../dispatcher/dispatcher"; import { _t } from "../../languageHandler"; @@ -27,7 +28,7 @@ import RoomListStore from "../../stores/room-list/RoomListStore"; import { NameFilterCondition } from "../../stores/room-list/filters/NameFilterCondition"; import { getKeyBindingsManager, RoomListAction } from "../../KeyBindingsManager"; import { replaceableComponent } from "../../utils/replaceableComponent"; -import SpaceStore, { UPDATE_SELECTED_SPACE } from "../../stores/SpaceStore"; +import SpaceStore, { UPDATE_SELECTED_SPACE, UPDATE_TOP_LEVEL_SPACES } from "../../stores/SpaceStore"; interface IProps { isMinimized: boolean; @@ -41,6 +42,7 @@ interface IProps { interface IState { query: string; focused: boolean; + inSpaces: boolean; } @replaceableComponent("structures.RoomSearch") @@ -55,11 +57,13 @@ export default class RoomSearch extends React.PureComponent { this.state = { query: "", focused: false, + inSpaces: false, }; this.dispatcherRef = defaultDispatcher.register(this.onAction); // clear filter when changing spaces, in future we may wish to maintain a filter per-space SpaceStore.instance.on(UPDATE_SELECTED_SPACE, this.clearInput); + SpaceStore.instance.on(UPDATE_TOP_LEVEL_SPACES, this.onSpaces); } public componentDidUpdate(prevProps: Readonly, prevState: Readonly): void { @@ -80,8 +84,15 @@ export default class RoomSearch extends React.PureComponent { public componentWillUnmount() { defaultDispatcher.unregister(this.dispatcherRef); SpaceStore.instance.off(UPDATE_SELECTED_SPACE, this.clearInput); + SpaceStore.instance.off(UPDATE_TOP_LEVEL_SPACES, this.onSpaces); } + private onSpaces = (spaces: Room[]) => { + this.setState({ + inSpaces: spaces.length > 0, + }); + }; + private onAction = (payload: ActionPayload) => { if (payload.action === 'view_room' && payload.clear_search) { this.clearInput(); @@ -153,6 +164,11 @@ export default class RoomSearch extends React.PureComponent { 'mx_RoomSearch_inputExpanded': this.state.query || this.state.focused, }); + let placeholder = _t("Filter"); + if (this.state.inSpaces) { + placeholder = _t("Filter all spaces"); + } + let icon = (
    ); @@ -166,7 +182,7 @@ export default class RoomSearch extends React.PureComponent { onBlur={this.onBlur} onChange={this.onChange} onKeyDown={this.onKeyDown} - placeholder={_t("Filter")} + placeholder={placeholder} autoComplete="off" /> ); diff --git a/src/components/views/rooms/RoomListNumResults.tsx b/src/components/views/rooms/RoomListNumResults.tsx index 4215e5644c..01cbecf05d 100644 --- a/src/components/views/rooms/RoomListNumResults.tsx +++ b/src/components/views/rooms/RoomListNumResults.tsx @@ -19,6 +19,7 @@ import React, {useState} from "react"; import { _t } from "../../../languageHandler"; import RoomListStore, { LISTS_UPDATE_EVENT } from "../../../stores/room-list/RoomListStore"; import {useEventEmitter} from "../../../hooks/useEventEmitter"; +import SpaceStore from "../../../stores/SpaceStore"; const RoomListNumResults: React.FC = () => { const [count, setCount] = useState(null); @@ -34,7 +35,10 @@ const RoomListNumResults: React.FC = () => { if (typeof count !== "number") return null; return
    - { _t("%(count)s results", { count }) } + { SpaceStore.instance.spacePanelSpaces.length + ? _t("%(count)s results in all spaces", { count }) + : _t("%(count)s results", { count }) + }
    ; }; diff --git a/src/stores/room-list/RoomListStore.ts b/src/stores/room-list/RoomListStore.ts index caab46a0c2..879ca45f3a 100644 --- a/src/stores/room-list/RoomListStore.ts +++ b/src/stores/room-list/RoomListStore.ts @@ -601,7 +601,11 @@ export class RoomListStoreClass extends AsyncStoreWithClient { let rooms = this.matrixClient.getVisibleRooms().filter(r => VisibilityProvider.instance.isRoomVisible(r)); - if (this.prefilterConditions.length > 0) { + // if spaces are enabled only consider the prefilter conditions when there are no runtime conditions + // for the search all spaces feature + if (this.prefilterConditions.length > 0 + && (!SettingsStore.getValue("feature_spaces") || !this.filterConditions.length) + ) { rooms = rooms.filter(r => { for (const filter of this.prefilterConditions) { if (!filter.isVisible(r)) { @@ -660,7 +664,7 @@ export class RoomListStoreClass extends AsyncStoreWithClient { * and thus might not cause an update to the store immediately. * @param {IFilterCondition} filter The filter condition to add. */ - public addFilter(filter: IFilterCondition): void { + public async addFilter(filter: IFilterCondition): Promise { if (SettingsStore.getValue("advancedRoomListLogging")) { // TODO: Remove debug: https://github.com/vector-im/element-web/issues/14602 console.log("Adding filter condition:", filter); @@ -672,6 +676,12 @@ export class RoomListStoreClass extends AsyncStoreWithClient { promise = this.recalculatePrefiltering(); } else { this.filterConditions.push(filter); + // Runtime filters with spaces disable prefiltering for the search all spaces feature + if (SettingsStore.getValue("feature_spaces")) { + // this has to be awaited so that `setKnownRooms` is called in time for the `addFilterCondition` below + // this way the runtime filters are only evaluated on one dataset and not both. + await this.recalculatePrefiltering(); + } if (this.algorithm) { this.algorithm.addFilterCondition(filter); } @@ -699,6 +709,10 @@ export class RoomListStoreClass extends AsyncStoreWithClient { if (this.algorithm) { this.algorithm.removeFilterCondition(filter); } + // Runtime filters with spaces disable prefiltering for the search all spaces feature + if (SettingsStore.getValue("feature_spaces")) { + promise = this.recalculatePrefiltering(); + } } idx = this.prefilterConditions.indexOf(filter); if (idx >= 0) { From 57be07481103fd016b3e1e5912cba5f4fbbddd49 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 7 May 2021 10:48:03 +0100 Subject: [PATCH 0272/1449] i18n --- 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 cb60545872..de06772583 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1554,6 +1554,8 @@ "Explore all public rooms": "Explore all public rooms", "Quick actions": "Quick actions", "Use the + to make a new room or explore existing ones below": "Use the + to make a new room or explore existing ones below", + "%(count)s results in all spaces|other": "%(count)s results in all spaces", + "%(count)s results in all spaces|one": "%(count)s result in all spaces", "%(count)s results|other": "%(count)s results", "%(count)s results|one": "%(count)s result", "This room": "This room", @@ -2619,6 +2621,7 @@ "If you can't find the room you're looking for, ask for an invite or Create a new room.": "If you can't find the room you're looking for, ask for an invite or Create a new room.", "Explore rooms in %(communityName)s": "Explore rooms in %(communityName)s", "Filter": "Filter", + "Filter all spaces": "Filter all spaces", "Clear filter": "Clear filter", "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.", From 9d9dce7a9135ee4c7510b7a0d7df1183bb84bf3d Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 7 May 2021 10:48:55 +0100 Subject: [PATCH 0273/1449] update orphan room behaviour test to expect new home space behaviour --- test/stores/SpaceStore-test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/stores/SpaceStore-test.ts b/test/stores/SpaceStore-test.ts index aef788647d..ce2def24a1 100644 --- a/test/stores/SpaceStore-test.ts +++ b/test/stores/SpaceStore-test.ts @@ -361,8 +361,8 @@ describe("SpaceStore", () => { expect(store.getSpaceFilteredRoomIds(null).has(invite2)).toBeTruthy(); }); - it("home space does not contain rooms/low priority from rooms within spaces", () => { - expect(store.getSpaceFilteredRoomIds(null).has(room1)).toBeFalsy(); + it("home space does contain rooms/low priority even if they are also shown in a space", () => { + expect(store.getSpaceFilteredRoomIds(null).has(room1)).toBeTruthy(); }); it("space contains child rooms", () => { From f0e61e6286050b88c0f3eca903a6fb8cec3aa265 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 7 May 2021 11:08:18 +0100 Subject: [PATCH 0274/1449] short circuit automatic switch to related space behaviour and fix tests --- src/stores/SpaceStore.tsx | 2 +- test/stores/SpaceStore-test.ts | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/stores/SpaceStore.tsx b/src/stores/SpaceStore.tsx index 20af6b249b..b1b8199f93 100644 --- a/src/stores/SpaceStore.tsx +++ b/src/stores/SpaceStore.tsx @@ -535,7 +535,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient { // Don't context switch when navigating to the space room // as it will cause you to end up in the wrong room this.setActiveSpace(room, false); - } else if (!this.getSpaceFilteredRoomIds(this.activeSpace).has(roomId)) { + } else if (this.activeSpace && !this.getSpaceFilteredRoomIds(this.activeSpace).has(roomId)) { this.switchToRelatedSpace(roomId); } diff --git a/test/stores/SpaceStore-test.ts b/test/stores/SpaceStore-test.ts index ce2def24a1..49fdd7308a 100644 --- a/test/stores/SpaceStore-test.ts +++ b/test/stores/SpaceStore-test.ts @@ -641,14 +641,14 @@ describe("SpaceStore", () => { it("switch to canonical parent space for room", async () => { viewRoom(room1); - await store.setActiveSpace(null, false); + await store.setActiveSpace(client.getRoom(space2), false); viewRoom(room2); expect(store.activeSpace).toBe(client.getRoom(space2)); }); it("switch to first containing space for room", async () => { viewRoom(room2); - await store.setActiveSpace(null, false); + await store.setActiveSpace(client.getRoom(space2), false); viewRoom(room1); expect(store.activeSpace).toBe(client.getRoom(space1)); }); @@ -659,6 +659,13 @@ describe("SpaceStore", () => { viewRoom(orphan1); expect(store.activeSpace).toBeNull(); }); + + it("when switching rooms in the all rooms home space don't switch to related space", async () => { + viewRoom(room2); + await store.setActiveSpace(null, false); + viewRoom(room1); + expect(store.activeSpace).toBeNull(); + }); }); describe("traverseSpace", () => { From 90fa738734165446ff05cd2a7faffa342f2d79e9 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 7 May 2021 11:22:10 +0100 Subject: [PATCH 0275/1449] Fix that one final pesky test --- test/stores/SpaceStore-test.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/stores/SpaceStore-test.ts b/test/stores/SpaceStore-test.ts index 49fdd7308a..20c48c29db 100644 --- a/test/stores/SpaceStore-test.ts +++ b/test/stores/SpaceStore-test.ts @@ -101,6 +101,7 @@ const invite1 = "!invite1:server"; const invite2 = "!invite2:server"; const room1 = "!room1:server"; const room2 = "!room2:server"; +const room3 = "!room3:server"; const space1 = "!space1:server"; const space2 = "!space2:server"; const space3 = "!space3:server"; @@ -614,8 +615,8 @@ describe("SpaceStore", () => { describe("space auto switching tests", () => { beforeEach(async () => { - [room1, room2, orphan1].forEach(mkRoom); - mkSpace(space1, [room1, room2]); + [room1, room2, room3, orphan1].forEach(mkRoom); + mkSpace(space1, [room1, room2, room3]); mkSpace(space2, [room1, room2]); client.getRoom(room2).currentState.getStateEvents.mockImplementation(mockStateEventImplementation([ @@ -649,7 +650,7 @@ describe("SpaceStore", () => { it("switch to first containing space for room", async () => { viewRoom(room2); await store.setActiveSpace(client.getRoom(space2), false); - viewRoom(room1); + viewRoom(room3); expect(store.activeSpace).toBe(client.getRoom(space1)); }); From 17099c656bdcc6997170659905068d93d7ad34a5 Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Fri, 7 May 2021 11:25:25 +0100 Subject: [PATCH 0276/1449] Call renamed room::decryptAllEvents method --- src/components/structures/MatrixChat.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index 41cacd2569..f691b7ab0b 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -906,7 +906,7 @@ export default class MatrixChat extends React.PureComponent { let presentedId = roomInfo.room_alias || roomInfo.room_id; const room = MatrixClientPeg.get().getRoom(roomInfo.room_id); if (room) { - room.lazyDecryptEvents(); + room.decryptAllEvents(); const theAlias = Rooms.getDisplayAliasForRoom(room); if (theAlias) { presentedId = theAlias; From 237399f13efa6332b6ed311b8d7ce85e788b90ce Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 7 May 2021 11:40:39 +0100 Subject: [PATCH 0277/1449] fix button height inconsistency between Chrome & FF --- res/css/structures/_SpaceRoomView.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/res/css/structures/_SpaceRoomView.scss b/res/css/structures/_SpaceRoomView.scss index b2712f82c0..ff51e28b7b 100644 --- a/res/css/structures/_SpaceRoomView.scss +++ b/res/css/structures/_SpaceRoomView.scss @@ -238,7 +238,8 @@ $SpaceRoomViewInnerWidth: 428px; .mx_SpaceRoomView_landing_inviteButton { position: relative; - padding-left: 40px; + padding: 4px 18px 4px 40px; + line-height: $font-24px; height: min-content; &::before { From 1fc591628a2157b6f1608f586d2383f7ee11cfe5 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 7 May 2021 11:51:37 +0100 Subject: [PATCH 0278/1449] i18n --- src/i18n/strings/en_EN.json | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index dcad970300..eda6153bb7 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -785,6 +785,13 @@ "%(senderName)s: %(stickerName)s": "%(senderName)s: %(stickerName)s", "Change notification settings": "Change notification settings", "Spaces prototype. Incompatible with Communities, Communities v2 and Custom Tags. Requires compatible homeserver for some features.": "Spaces prototype. Incompatible with Communities, Communities v2 and Custom Tags. Requires compatible homeserver for some features.", + "Spaces": "Spaces", + "Spaces are new ways to group rooms and people.": "Spaces are new ways to group rooms and people.", + "%(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "%(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.", + "Beta available for web, desktop and Android. Thank you for trying the beta.": "Beta available for web, desktop and Android. Thank you for trying the beta.", + "%(brand)s will reload with Spaces enabled. Communities and custom tags will be hidden.": "%(brand)s will reload with Spaces enabled. Communities and custom tags will be hidden.", + "You can leave the beta any time from settings or tapping on a beta badge, like the one above.": "You can leave the beta any time from settings or tapping on a beta badge, like the one above.", + "Beta available for web, desktop and Android. Some features may be unavailable on your homeserver.": "Beta available for web, desktop and Android. Some features may be unavailable on your homeserver.", "Show options to enable 'Do not disturb' mode": "Show options to enable 'Do not disturb' mode", "Send and receive voice messages (in development)": "Send and receive voice messages (in development)", "Render LaTeX maths in messages": "Render LaTeX maths in messages", @@ -1258,7 +1265,7 @@ "Copy": "Copy", "Clear cache and reload": "Clear cache and reload", "Labs": "Labs", - "Customise your experience with experimental labs features. Learn more.": "Customise your experience with experimental labs features. Learn more.", + "Feeling experimental? Labs are the best way to get things early, test out new features and help shape them before they actually launch. Learn more.": "Feeling experimental? Labs are the best way to get things early, test out new features and help shape them before they actually launch. Learn more.", "Ignored/Blocked": "Ignored/Blocked", "Error adding ignored user/server": "Error adding ignored user/server", "Something went wrong. Please try again or view your console for hints.": "Something went wrong. Please try again or view your console for hints.", @@ -2031,7 +2038,6 @@ "%(networkName)s rooms": "%(networkName)s rooms", "Matrix rooms": "Matrix rooms", "Filter your rooms and spaces": "Filter your rooms and spaces", - "Spaces": "Spaces", "Direct Messages": "Direct Messages", "Space selection": "Space selection", "Add existing rooms": "Add existing rooms", @@ -2464,6 +2470,11 @@ "Revoke permissions": "Revoke permissions", "Move left": "Move left", "Move right": "Move right", + "Spaces is a beta feature": "Spaces is a beta feature", + "Tap for more info": "Tap for more info", + "Beta": "Beta", + "Leave the beta": "Leave the beta", + "Join the beta": "Join the beta", "Avatar": "Avatar", "This room is public": "This room is public", "Away": "Away", @@ -2597,6 +2608,7 @@ "Error whilst fetching joined communities": "Error whilst fetching joined communities", "Create a new community": "Create a new community", "Create a community to group together users and rooms! Build a custom homepage to mark out your space in the Matrix universe.": "Create a community to group together users and rooms! Build a custom homepage to mark out your space in the Matrix universe.", + "Communities are changing to Spaces": "Communities are changing to Spaces", "You’re all caught up": "You’re all caught up", "You have no visible notifications.": "You have no visible notifications.", "%(brand)s failed to get the protocol list from the homeserver. The homeserver may be too old to support third party networks.": "%(brand)s failed to get the protocol list from the homeserver. The homeserver may be too old to support third party networks.", @@ -2670,6 +2682,8 @@ "Public space": "Public space", "Private space": "Private space", " invites you": " invites you", + "To view %(spaceName)s, turn on the Spaces beta": "To view %(spaceName)s, turn on the Spaces beta", + "To join %(spaceName)s, turn on the Spaces beta": "To join %(spaceName)s, turn on the Spaces beta", "Welcome to ": "Welcome to ", "Random": "Random", "Support": "Support", @@ -2694,6 +2708,7 @@ "Inviting...": "Inviting...", "Invite your teammates": "Invite your teammates", "Make sure the right people have access. You can invite more later.": "Make sure the right people have access. You can invite more later.", + "This is an experimental feature. For now, new users receiving an invite will have to open the invite on to actually join.": "This is an experimental feature. For now, new users receiving an invite will have to open the invite on to actually join.", "Invite by username": "Invite by username", "What are some things you want to discuss in %(spaceName)s?": "What are some things you want to discuss in %(spaceName)s?", "Let's create a room for each of them.": "Let's create a room for each of them.", From cb13200c2d8524e0a1c77da3ed0d5f0cf8d28041 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 7 May 2021 11:56:41 +0100 Subject: [PATCH 0279/1449] last minute copy tweak --- src/components/views/spaces/SpaceCreateMenu.tsx | 2 +- src/i18n/strings/en_EN.json | 4 ++-- src/settings/Settings.tsx | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/views/spaces/SpaceCreateMenu.tsx b/src/components/views/spaces/SpaceCreateMenu.tsx index c17c16f18f..35b8227897 100644 --- a/src/components/views/spaces/SpaceCreateMenu.tsx +++ b/src/components/views/spaces/SpaceCreateMenu.tsx @@ -111,7 +111,7 @@ const SpaceCreateMenu = ({ onFinished }) => { if (visibility === null) { body =

    { _t("Create a space") }

    -

    { _t("Spaces are new ways to group rooms and people. " + +

    { _t("Spaces are a new way to group rooms and people. " + "To join an existing space you'll need an invite.") }

    { if (enabled) { return <> From 5bd41209200798e93594776a29d6c789098f42e9 Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Fri, 7 May 2021 12:58:37 +0100 Subject: [PATCH 0280/1449] Decrypt breadcrumb events for better UX --- src/stores/BreadcrumbsStore.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/stores/BreadcrumbsStore.ts b/src/stores/BreadcrumbsStore.ts index 393f4f27a1..5c49fef148 100644 --- a/src/stores/BreadcrumbsStore.ts +++ b/src/stores/BreadcrumbsStore.ts @@ -22,6 +22,7 @@ import defaultDispatcher from "../dispatcher/dispatcher"; import { arrayHasDiff } from "../utils/arrays"; import { isNullOrUndefined } from "matrix-js-sdk/src/utils"; import { SettingLevel } from "../settings/SettingLevel"; +import {MatrixClientPeg} from '../MatrixClientPeg'; const MAX_ROOMS = 20; // arbitrary const AUTOJOIN_WAIT_THRESHOLD_MS = 90000; // 90s, the time we wait for an autojoined room to show up @@ -87,6 +88,23 @@ export class BreadcrumbsStore extends AsyncStoreWithClient { this.matrixClient.on("Room.myMembership", this.onMyMembership); this.matrixClient.on("Room", this.onRoom); + + const client = MatrixClientPeg.get(); + const breadcrumbs = client.store.getAccountData("im.vector.setting.breadcrumbs"); + const breadcrumbsRooms: string[] = breadcrumbs?.getContent().recent_rooms || []; + + breadcrumbsRooms.map(async roomId => { + const room = client.getRoom(roomId); + if (room) { + const [cryptoEvent] = room.currentState.getStateEvents("m.room.encryption"); + if (cryptoEvent) { + if (!client.isRoomEncrypted(roomId)) { + await client._crypto.onCryptoEvent(cryptoEvent); + } + return room?.decryptAllEvents(); + } + } + }); } protected async onNotReady() { From c84338704393d0598eaa30a29fda21ec52a950de Mon Sep 17 00:00:00 2001 From: Ayush PS Date: Fri, 7 May 2021 18:32:38 +0530 Subject: [PATCH 0281/1449] Merge branch 'develop' into Bubble-bericht --- .eslintrc.js | 1 - .gitignore | 1 + CHANGELOG.md | 118 +++ README.md | 2 +- package.json | 19 +- res/css/_components.scss | 3 + res/css/structures/_RoomStatusBar.scss | 97 ++- res/css/structures/_SpacePanel.scss | 33 +- res/css/structures/_SpaceRoomDirectory.scss | 108 +-- res/css/structures/_SpaceRoomView.scss | 108 +-- .../dialogs/_AddExistingToSpaceDialog.scss | 195 +++-- res/css/views/elements/_AccessibleButton.scss | 8 +- res/css/views/elements/_ImageView.scss | 3 +- res/css/views/elements/_ProgressBar.scss | 2 +- res/css/views/messages/_MFileBody.scss | 8 +- .../views/messages/_MVoiceMessageBody.scss | 19 + res/css/views/messages/_MessageActionBar.scss | 8 + .../views/messages/_ReactionsRowButton.scss | 4 + res/css/views/rooms/_EventTile.scss | 4 - .../views/rooms/_VoiceRecordComposerTile.scss | 62 +- .../tabs/user/_HelpUserSettingsTab.scss | 31 + .../voice_messages/_PlayPauseButton.scss | 51 ++ .../voice_messages/_PlaybackContainer.scss | 53 ++ res/css/views/voip/_CallView.scss | 16 +- res/css/views/voip/_VideoFeed.scss | 24 +- res/img/element-icons/pause.svg | 4 + res/img/element-icons/play.svg | 3 + res/img/element-icons/retry.svg | 3 + res/img/element-icons/trashcan.svg | 3 + res/themes/dark/css/_dark.scss | 20 +- res/themes/legacy-dark/css/_legacy-dark.scss | 20 +- .../legacy-light/css/_legacy-light.scss | 29 +- res/themes/light/css/_light.scss | 31 +- scripts/compare-file.js | 10 - scripts/gen-i18n.js | 304 -------- scripts/prune-i18n.js | 68 -- src/@types/global.d.ts | 22 +- src/Avatar.ts | 15 +- src/BasePlatform.ts | 2 +- src/CallHandler.tsx | 119 +-- src/CallMediaHandler.js | 5 +- src/GroupAddressPicker.js | 18 +- src/IdentityAuthClient.js | 2 +- src/KeyBindingsManager.ts | 6 +- src/Login.ts | 7 +- src/PasswordReset.js | 2 +- src/Resend.js | 10 +- ...calarAuthClient.js => ScalarAuthClient.ts} | 64 +- src/SlashCommands.tsx | 4 +- src/{Terms.js => Terms.ts} | 46 +- src/TextForEvent.js | 18 +- src/Unread.js | 2 +- src/VoipUserMapper.ts | 6 +- ...exDialog.js => ManageEventIndexDialog.tsx} | 34 +- .../dialogs/security/CreateKeyBackupDialog.js | 8 +- .../security/CreateSecretStorageDialog.js | 10 +- .../dialogs/security/ExportE2eKeysDialog.js | 7 +- .../dialogs/security/ImportE2eKeysDialog.js | 56 +- src/components/structures/FilePanel.js | 8 +- src/components/structures/GroupFilterPanel.js | 20 +- src/components/structures/GroupView.js | 95 +-- src/components/structures/LeftPanel.tsx | 4 +- src/components/structures/LoggedInView.tsx | 20 + src/components/structures/MatrixChat.tsx | 4 +- src/components/structures/MessagePanel.js | 26 +- src/components/structures/RightPanel.js | 5 +- src/components/structures/RoomSearch.tsx | 21 +- src/components/structures/RoomStatusBar.js | 155 ++-- src/components/structures/RoomView.tsx | 12 +- src/components/structures/ScrollPanel.js | 26 +- .../structures/SpaceRoomDirectory.tsx | 190 +++-- src/components/structures/SpaceRoomView.tsx | 189 ++++- src/components/structures/TimelinePanel.js | 20 +- src/components/structures/auth/Login.tsx | 4 +- .../structures/auth/Registration.tsx | 4 +- .../auth/{SoftLogout.js => SoftLogout.tsx} | 49 +- .../auth/InteractiveAuthEntryComponents.js | 4 +- src/components/views/avatars/MemberAvatar.tsx | 4 +- src/components/views/avatars/RoomAvatar.tsx | 11 +- .../views/context_menus/MessageContextMenu.js | 93 +-- .../dialogs/AddExistingToSpaceDialog.tsx | 310 +++++--- .../views/dialogs/BugReportDialog.js | 2 +- .../views/dialogs/ChangelogDialog.js | 2 +- .../views/dialogs/ConfirmWipeDeviceDialog.js | 9 +- .../views/dialogs/DevtoolsDialog.js | 94 +-- .../views/dialogs/IncomingSasDialog.js | 2 +- .../dialogs/IntegrationsDisabledDialog.js | 9 +- .../dialogs/IntegrationsImpossibleDialog.js | 9 +- src/components/views/dialogs/InviteDialog.tsx | 2 +- .../dialogs/KeySignatureUploadFailedDialog.js | 10 +- .../views/dialogs/MessageEditHistoryDialog.js | 8 +- .../views/dialogs/RoomSettingsDialog.js | 8 +- .../views/dialogs/ServerPickerDialog.tsx | 6 +- .../dialogs/SessionRestoreErrorDialog.js | 2 +- .../views/dialogs/StorageEvictedDialog.js | 10 +- .../views/dialogs/UserSettingsDialog.js | 8 +- .../dialogs/VerificationRequestDialog.js | 12 +- .../dialogs/WidgetOpenIDPermissionsDialog.js | 9 +- .../ConfirmDestroyCrossSigningDialog.js | 9 +- .../security/RestoreKeyBackupDialog.js | 59 +- src/components/views/elements/ActionButton.js | 4 +- src/components/views/elements/AppTile.js | 2 +- .../views/elements/EditableItemList.js | 26 +- src/components/views/elements/EditableText.js | 16 +- src/components/views/elements/ImageView.tsx | 197 +++-- .../views/elements/LabelledToggleSwitch.js | 8 +- .../views/elements/LanguageDropdown.js | 6 +- src/components/views/elements/Pill.js | 24 +- .../views/elements/PowerSelector.js | 15 +- .../views/elements/RoomAliasField.js | 23 +- .../views/elements/ServerPicker.tsx | 4 +- src/components/views/elements/TintableSvg.js | 14 +- .../views/groups/GroupMemberList.js | 12 +- .../views/groups/GroupPublicityToggle.js | 6 +- src/components/views/groups/GroupRoomList.js | 13 +- .../views/messages/EditHistoryMessage.js | 1 - src/components/views/messages/MImageBody.js | 35 +- .../messages/MKeyVerificationConclusion.js | 4 +- .../views/messages/MVoiceMessageBody.tsx | 106 +++ .../views/messages/MVoiceOrAudioBody.tsx | 39 + .../views/messages/MessageActionBar.js | 125 ++- src/components/views/messages/MessageEvent.js | 6 +- .../views/messages/ReactionsRowButton.js | 3 +- src/components/views/messages/TextualBody.js | 11 +- src/components/views/right_panel/UserInfo.tsx | 18 +- .../views/room_settings/AliasSettings.js | 17 +- .../room_settings/RoomProfileSettings.js | 34 +- .../views/room_settings/UrlPreviewSettings.js | 14 +- src/components/views/rooms/EntityTile.js | 7 +- .../rooms/{EventTile.js => EventTile.tsx} | 461 ++++++----- .../views/rooms/LinkPreviewWidget.js | 4 +- src/components/views/rooms/MemberList.js | 5 +- ...MessageComposer.js => MessageComposer.tsx} | 160 ++-- .../views/rooms/NotificationBadge.tsx | 2 +- src/components/views/rooms/PinnedEventTile.js | 13 +- .../views/rooms/PinnedEventsPanel.js | 20 +- .../views/rooms/ReadReceiptMarker.js | 3 +- src/components/views/rooms/ReplyPreview.js | 9 +- src/components/views/rooms/RoomDetailRow.js | 8 +- src/components/views/rooms/RoomList.tsx | 8 +- .../views/rooms/RoomListNumResults.tsx | 6 +- src/components/views/rooms/RoomSublist.tsx | 8 +- src/components/views/rooms/RoomTile.tsx | 69 +- .../views/rooms/SendMessageComposer.js | 5 +- src/components/views/rooms/Stickerpicker.js | 38 +- ...MemberInfo.js => ThirdPartyMemberInfo.tsx} | 26 +- .../views/rooms/VoiceRecordComposerTile.tsx | 231 ++++-- src/components/views/settings/ChangeAvatar.js | 2 +- .../views/settings/ChangePassword.js | 4 +- .../views/settings/CrossSigningPanel.js | 2 +- src/components/views/settings/DevicesPanel.js | 2 +- ...eAdvancedPanel.js => E2eAdvancedPanel.tsx} | 0 ...EventIndexPanel.js => EventIndexPanel.tsx} | 140 ++-- .../views/settings/Notifications.js | 34 +- .../views/settings/ProfileSettings.js | 8 +- .../{SetIdServer.js => SetIdServer.tsx} | 78 +- .../views/settings/account/EmailAddresses.js | 39 +- .../views/settings/account/PhoneNumbers.js | 21 +- .../tabs/room/GeneralRoomSettingsTab.js | 12 +- .../tabs/room/NotificationSettingsTab.js | 6 +- ...ettingsTab.js => RolesRoomSettingsTab.tsx} | 71 +- ...ingsTab.js => SecurityRoomSettingsTab.tsx} | 144 ++-- .../tabs/user/GeneralUserSettingsTab.js | 19 +- ...SettingsTab.js => HelpUserSettingsTab.tsx} | 159 ++-- ...tingsTab.js => MjolnirUserSettingsTab.tsx} | 54 +- ...sTab.js => PreferencesUserSettingsTab.tsx} | 64 +- .../tabs/user/SecurityUserSettingsTab.js | 21 +- .../tabs/user/VoiceUserSettingsTab.js | 12 +- .../views/spaces/SpaceTreeLevel.tsx | 6 +- .../verification/VerificationCancelled.js | 16 +- src/components/views/voice_messages/Clock.tsx | 10 +- .../voice_messages/LiveRecordingClock.tsx | 8 +- .../voice_messages/LiveRecordingWaveform.tsx | 8 +- .../views/voice_messages/PlayPauseButton.tsx | 61 ++ .../views/voice_messages/PlaybackClock.tsx | 71 ++ .../views/voice_messages/PlaybackWaveform.tsx | 68 ++ .../voice_messages/RecordingPlayback.tsx | 62 ++ .../views/voice_messages/Waveform.tsx | 17 +- src/components/views/voip/AudioFeed.tsx | 97 +++ .../views/voip/AudioFeedArrayForCall.tsx | 60 ++ src/components/views/voip/CallPreview.tsx | 24 +- src/components/views/voip/CallView.tsx | 162 +++- src/components/views/voip/CallViewForRoom.tsx | 16 +- src/components/views/voip/IncomingCallBox.tsx | 6 +- src/components/views/voip/VideoFeed.tsx | 125 ++- src/customisations/Media.ts | 7 + src/editor/autocomplete.ts | 6 +- src/editor/model.ts | 2 +- src/editor/parts.ts | 43 +- src/editor/serialize.ts | 8 +- src/i18n/strings/cs.json | 163 ++-- src/i18n/strings/da.json | 6 +- src/i18n/strings/de_DE.json | 140 ++-- src/i18n/strings/en_EN.json | 68 +- src/i18n/strings/en_US.json | 10 +- src/i18n/strings/eo.json | 32 +- src/i18n/strings/es.json | 25 +- src/i18n/strings/et.json | 25 +- src/i18n/strings/fa.json | 322 +++++++- src/i18n/strings/fr.json | 37 +- src/i18n/strings/gl.json | 25 +- src/i18n/strings/hu.json | 25 +- src/i18n/strings/it.json | 25 +- src/i18n/strings/nl.json | 25 +- src/i18n/strings/ru.json | 3 +- src/i18n/strings/sq.json | 24 +- src/i18n/strings/sv.json | 25 +- src/i18n/strings/tzm.json | 121 ++- src/i18n/strings/zh_Hant.json | 25 +- src/indexing/BaseEventIndexManager.ts | 6 +- src/indexing/EventIndex.js | 37 +- .../{EventIndexPeg.js => EventIndexPeg.ts} | 19 +- src/linkify-matrix.js | 2 +- src/mjolnir/{BanList.js => BanList.ts} | 0 src/mjolnir/{ListRule.js => ListRule.ts} | 0 src/mjolnir/{Mjolnir.js => Mjolnir.ts} | 0 src/settings/Settings.ts | 5 +- src/stores/BreadcrumbsStore.ts | 2 +- src/stores/CustomRoomTagStore.js | 4 +- src/stores/GroupFilterOrderStore.js | 8 +- src/stores/RoomViewStore.tsx | 19 +- src/stores/SpaceStore.tsx | 172 +++-- src/stores/{TypingStore.js => TypingStore.ts} | 24 +- src/stores/VoiceRecordingStore.ts | 2 + ...{WidgetEchoStore.js => WidgetEchoStore.ts} | 39 +- .../notifications/StaticNotificationState.ts | 2 + src/stores/room-list/RoomListStore.ts | 22 +- src/stores/room-list/algorithms/Algorithm.ts | 9 +- .../algorithms/tag-sorting/RecentAlgorithm.ts | 140 ++-- .../room-list/filters/VisibilityProvider.ts | 8 +- ...scoveryUtils.js => AutoDiscoveryUtils.tsx} | 32 +- src/utils/DMRoomMap.ts | 9 + src/utils/ErrorUtils.js | 6 - src/utils/{MatrixGlob.js => MatrixGlob.ts} | 0 src/utils/MegolmExportEncryption.js | 3 +- .../{StorageManager.js => StorageManager.ts} | 12 +- src/utils/{Timer.js => Timer.ts} | 70 +- src/utils/{TypeUtils.js => TypeUtils.ts} | 0 src/utils/arrays.ts | 26 +- ...ctor.js => ElementPermalinkConstructor.ts} | 24 +- ...Constructor.js => PermalinkConstructor.ts} | 0 .../{Permalinks.js => Permalinks.ts} | 167 ++-- ...tructor.js => SpecPermalinkConstructor.ts} | 0 src/utils/space.tsx | 1 + src/voice/Playback.ts | 147 ++++ src/voice/PlaybackClock.ts | 78 ++ src/voice/VoiceRecording.ts | 69 +- test/CallHandler-test.ts | 214 ++++++ test/ScalarAuthClient-test.js | 2 +- test/autocomplete/QueryMatcher-test.js | 2 +- .../dialogs/AccessSecretStorageDialog-test.js | 24 +- .../elements/MemberEventListSummary-test.js | 9 +- .../components/views/rooms/MemberList-test.js | 2 +- test/components/views/rooms/RoomList-test.js | 10 +- test/editor/deserialize-test.js | 2 +- test/end-to-end-tests/src/session.js | 8 +- test/end-to-end-tests/yarn.lock | 6 +- test/stores/SpaceStore-test.ts | 714 ++++++++++++++++++ test/test-utils.js | 32 +- test/utils/MegolmExportEncryption-test.js | 30 +- test/utils/ShieldUtils-test.js | 6 +- test/utils/arrays-test.ts | 33 + test/utils/test-utils.ts | 33 + yarn.lock | 113 ++- 264 files changed, 7383 insertions(+), 3268 deletions(-) create mode 100644 res/css/views/messages/_MVoiceMessageBody.scss create mode 100644 res/css/views/voice_messages/_PlayPauseButton.scss create mode 100644 res/css/views/voice_messages/_PlaybackContainer.scss create mode 100644 res/img/element-icons/pause.svg create mode 100644 res/img/element-icons/play.svg create mode 100644 res/img/element-icons/retry.svg create mode 100644 res/img/element-icons/trashcan.svg delete mode 100644 scripts/compare-file.js delete mode 100755 scripts/gen-i18n.js delete mode 100755 scripts/prune-i18n.js rename src/{ScalarAuthClient.js => ScalarAuthClient.ts} (84%) rename src/{Terms.js => Terms.ts} (87%) rename src/async-components/views/dialogs/eventindex/{ManageEventIndexDialog.js => ManageEventIndexDialog.tsx} (90%) rename src/components/structures/auth/{SoftLogout.js => SoftLogout.tsx} (92%) create mode 100644 src/components/views/messages/MVoiceMessageBody.tsx create mode 100644 src/components/views/messages/MVoiceOrAudioBody.tsx rename src/components/views/rooms/{EventTile.js => EventTile.tsx} (79%) rename src/components/views/rooms/{MessageComposer.js => MessageComposer.tsx} (80%) rename src/components/views/rooms/{ThirdPartyMemberInfo.js => ThirdPartyMemberInfo.tsx} (91%) rename src/components/views/settings/{E2eAdvancedPanel.js => E2eAdvancedPanel.tsx} (100%) rename src/components/views/settings/{EventIndexPanel.js => EventIndexPanel.tsx} (65%) rename src/components/views/settings/{SetIdServer.js => SetIdServer.tsx} (89%) rename src/components/views/settings/tabs/room/{RolesRoomSettingsTab.js => RolesRoomSettingsTab.tsx} (89%) rename src/components/views/settings/tabs/room/{SecurityRoomSettingsTab.js => SecurityRoomSettingsTab.tsx} (79%) rename src/components/views/settings/tabs/user/{HelpUserSettingsTab.js => HelpUserSettingsTab.tsx} (64%) rename src/components/views/settings/tabs/user/{MjolnirUserSettingsTab.js => MjolnirUserSettingsTab.tsx} (90%) rename src/components/views/settings/tabs/user/{PreferencesUserSettingsTab.js => PreferencesUserSettingsTab.tsx} (80%) create mode 100644 src/components/views/voice_messages/PlayPauseButton.tsx create mode 100644 src/components/views/voice_messages/PlaybackClock.tsx create mode 100644 src/components/views/voice_messages/PlaybackWaveform.tsx create mode 100644 src/components/views/voice_messages/RecordingPlayback.tsx create mode 100644 src/components/views/voip/AudioFeed.tsx create mode 100644 src/components/views/voip/AudioFeedArrayForCall.tsx rename src/indexing/{EventIndexPeg.js => EventIndexPeg.ts} (94%) rename src/mjolnir/{BanList.js => BanList.ts} (100%) rename src/mjolnir/{ListRule.js => ListRule.ts} (100%) rename src/mjolnir/{Mjolnir.js => Mjolnir.ts} (100%) rename src/stores/{TypingStore.js => TypingStore.ts} (84%) rename src/stores/{WidgetEchoStore.js => WidgetEchoStore.ts} (71%) rename src/utils/{AutoDiscoveryUtils.js => AutoDiscoveryUtils.tsx} (91%) rename src/utils/{MatrixGlob.js => MatrixGlob.ts} (100%) rename src/utils/{StorageManager.js => StorageManager.ts} (96%) rename src/utils/{Timer.js => Timer.ts} (60%) rename src/utils/{TypeUtils.js => TypeUtils.ts} (100%) rename src/utils/permalinks/{ElementPermalinkConstructor.js => ElementPermalinkConstructor.ts} (82%) rename src/utils/permalinks/{PermalinkConstructor.js => PermalinkConstructor.ts} (100%) rename src/utils/permalinks/{Permalinks.js => Permalinks.ts} (76%) rename src/utils/permalinks/{SpecPermalinkConstructor.js => SpecPermalinkConstructor.ts} (100%) create mode 100644 src/voice/Playback.ts create mode 100644 src/voice/PlaybackClock.ts create mode 100644 test/CallHandler-test.ts create mode 100644 test/stores/SpaceStore-test.ts create mode 100644 test/utils/test-utils.ts diff --git a/.eslintrc.js b/.eslintrc.js index 99695b7a03..4959b133a0 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -15,7 +15,6 @@ module.exports = { "prefer-promise-reject-errors": "off", "no-async-promise-executor": "off", "quotes": "off", - "indent": "off", }, overrides: [{ diff --git a/.gitignore b/.gitignore index e1dd7726e1..50aa10fbfd 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ /*.log package-lock.json +/coverage /node_modules /lib diff --git a/CHANGELOG.md b/CHANGELOG.md index ec73756ff9..d459b4e94a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,121 @@ +Changes in [3.19.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.19.0) (2021-04-26) +===================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v3.19.0-rc.1...v3.19.0) + + * Upgrade to JS SDK 10.0.0 + * [Release] Dynamic max and min zoom in the new ImageView + [\#5927](https://github.com/matrix-org/matrix-react-sdk/pull/5927) + * [Release] Add a WheelEvent normalization function + [\#5911](https://github.com/matrix-org/matrix-react-sdk/pull/5911) + * Add a WheelEvent normalization function + [\#5904](https://github.com/matrix-org/matrix-react-sdk/pull/5904) + * [Release] Use floats for image background opacity + [\#5907](https://github.com/matrix-org/matrix-react-sdk/pull/5907) + +Changes in [3.19.0-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.19.0-rc.1) (2021-04-21) +=============================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v3.18.0...v3.19.0-rc.1) + + * Upgrade to JS SDK 10.0.0-rc.1 + * Translations update from Weblate + [\#5896](https://github.com/matrix-org/matrix-react-sdk/pull/5896) + * Fix sticky tags header in room list + [\#5895](https://github.com/matrix-org/matrix-react-sdk/pull/5895) + * Fix spaces filtering sometimes lagging behind or behaving oddly + [\#5893](https://github.com/matrix-org/matrix-react-sdk/pull/5893) + * Fix issue with spaces context switching looping and breaking + [\#5894](https://github.com/matrix-org/matrix-react-sdk/pull/5894) + * Improve RoomList render time when filtering + [\#5874](https://github.com/matrix-org/matrix-react-sdk/pull/5874) + * Avoid being stuck in a space + [\#5891](https://github.com/matrix-org/matrix-react-sdk/pull/5891) + * [Spaces] Context switching + [\#5795](https://github.com/matrix-org/matrix-react-sdk/pull/5795) + * Warn when you attempt to leave room that you are the only member of + [\#5415](https://github.com/matrix-org/matrix-react-sdk/pull/5415) + * Ensure PersistedElement are unmounted on application logout + [\#5884](https://github.com/matrix-org/matrix-react-sdk/pull/5884) + * Add missing space in seshat dialog and the corresponding string + [\#5866](https://github.com/matrix-org/matrix-react-sdk/pull/5866) + * A tiny change to make the Add existing rooms dialog a little nicer + [\#5885](https://github.com/matrix-org/matrix-react-sdk/pull/5885) + * Remove weird margin from the file panel + [\#5889](https://github.com/matrix-org/matrix-react-sdk/pull/5889) + * Trigger lazy loading when filtering using spaces + [\#5882](https://github.com/matrix-org/matrix-react-sdk/pull/5882) + * Fix typo in method call in add existing to space dialog + [\#5883](https://github.com/matrix-org/matrix-react-sdk/pull/5883) + * New Image View fixes/improvements + [\#5872](https://github.com/matrix-org/matrix-react-sdk/pull/5872) + * Limit voice recording length + [\#5871](https://github.com/matrix-org/matrix-react-sdk/pull/5871) + * Clean up add existing to space dialog and include DMs in it too + [\#5881](https://github.com/matrix-org/matrix-react-sdk/pull/5881) + * Fix unknown slash command error exploding + [\#5853](https://github.com/matrix-org/matrix-react-sdk/pull/5853) + * Switch to a spec conforming email validation Regexp + [\#5852](https://github.com/matrix-org/matrix-react-sdk/pull/5852) + * Cleanup unused state in MessageComposer + [\#5877](https://github.com/matrix-org/matrix-react-sdk/pull/5877) + * Pulse animation for voice messages recording state + [\#5869](https://github.com/matrix-org/matrix-react-sdk/pull/5869) + * Don't include invisible rooms in notify summary + [\#5875](https://github.com/matrix-org/matrix-react-sdk/pull/5875) + * Properly disable composer access when recording a voice message + [\#5870](https://github.com/matrix-org/matrix-react-sdk/pull/5870) + * Stabilise starting a DM with multiple people flow + [\#5862](https://github.com/matrix-org/matrix-react-sdk/pull/5862) + * Render msgOption only if showReadReceipts is enabled + [\#5864](https://github.com/matrix-org/matrix-react-sdk/pull/5864) + * Labs: Add quick/cheap "do not disturb" flag + [\#5873](https://github.com/matrix-org/matrix-react-sdk/pull/5873) + * Fix ReadReceipts animations + [\#5836](https://github.com/matrix-org/matrix-react-sdk/pull/5836) + * Add tooltips to message previews + [\#5859](https://github.com/matrix-org/matrix-react-sdk/pull/5859) + * IRC Layout fix layout spacing in replies + [\#5855](https://github.com/matrix-org/matrix-react-sdk/pull/5855) + * Move user to welcome_page if continuing with previous session + [\#5849](https://github.com/matrix-org/matrix-react-sdk/pull/5849) + * Improve image view + [\#5521](https://github.com/matrix-org/matrix-react-sdk/pull/5521) + * Add a button to reset personal encryption state during login + [\#5819](https://github.com/matrix-org/matrix-react-sdk/pull/5819) + * Fix js-sdk import in SlashCommands + [\#5850](https://github.com/matrix-org/matrix-react-sdk/pull/5850) + * Fix useRoomPowerLevels hook + [\#5854](https://github.com/matrix-org/matrix-react-sdk/pull/5854) + * Prevent state events being rendered with invalid state keys + [\#5851](https://github.com/matrix-org/matrix-react-sdk/pull/5851) + * Give server ACLs a name in 'roles & permissions' tab + [\#5838](https://github.com/matrix-org/matrix-react-sdk/pull/5838) + * Don't hide notification badge on the home space button as it has no menu + [\#5845](https://github.com/matrix-org/matrix-react-sdk/pull/5845) + * User Info hide disambiguation as we always show MXID anyway + [\#5843](https://github.com/matrix-org/matrix-react-sdk/pull/5843) + * Improve kick state to not show if the target was not joined to begin with + [\#5846](https://github.com/matrix-org/matrix-react-sdk/pull/5846) + * Fix space store wrongly switching to a non-space filter + [\#5844](https://github.com/matrix-org/matrix-react-sdk/pull/5844) + * Tweak appearance of invite reason + [\#5847](https://github.com/matrix-org/matrix-react-sdk/pull/5847) + * Update Inter font to v3.18 + [\#5840](https://github.com/matrix-org/matrix-react-sdk/pull/5840) + * Enable sharing historical keys on invite + [\#5839](https://github.com/matrix-org/matrix-react-sdk/pull/5839) + * Add ability to hide post-login encryption setup with customisation point + [\#5834](https://github.com/matrix-org/matrix-react-sdk/pull/5834) + * Use LaTeX and TeX delimiters by default + [\#5515](https://github.com/matrix-org/matrix-react-sdk/pull/5515) + * Clone author's deps fork for Netlify previews + [\#5837](https://github.com/matrix-org/matrix-react-sdk/pull/5837) + * Show drop file UI only if dragging a file + [\#5827](https://github.com/matrix-org/matrix-react-sdk/pull/5827) + * Ignore punctuation when filtering rooms + [\#5824](https://github.com/matrix-org/matrix-react-sdk/pull/5824) + * Resizable CallView + [\#5710](https://github.com/matrix-org/matrix-react-sdk/pull/5710) + Changes in [3.18.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.18.0) (2021-04-12) ===================================================================================================== [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v3.18.0-rc.1...v3.18.0) diff --git a/README.md b/README.md index 73afe34df0..b3e96ef001 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Platform Targets: * WebRTC features (VoIP and Video calling) are only available in Chrome & Firefox. * Mobile Web is not currently a target platform - instead please use the native iOS (https://github.com/matrix-org/matrix-ios-kit) and Android - (https://github.com/matrix-org/matrix-android-sdk) SDKs. + (https://github.com/matrix-org/matrix-android-sdk2) SDKs. All code lands on the `develop` branch - `master` is only used for stable releases. **Please file PRs against `develop`!!** diff --git a/package.json b/package.json index 7c190c68bf..be195e2e9e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "3.18.0", + "version": "3.19.0", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { @@ -23,9 +23,7 @@ "package.json" ], "bin": { - "reskindex": "scripts/reskindex.js", - "matrix-gen-i18n": "scripts/gen-i18n.js", - "matrix-prune-i18n": "scripts/prune-i18n.js" + "reskindex": "scripts/reskindex.js" }, "main": "./src/index.js", "matrix_src_main": "./src/index.js", @@ -35,7 +33,7 @@ "prepublishOnly": "yarn build", "i18n": "matrix-gen-i18n", "prunei18n": "matrix-prune-i18n", - "diff-i18n": "cp src/i18n/strings/en_EN.json src/i18n/strings/en_EN_orig.json && ./scripts/gen-i18n.js && node scripts/compare-file.js src/i18n/strings/en_EN_orig.json src/i18n/strings/en_EN.json", + "diff-i18n": "cp src/i18n/strings/en_EN.json src/i18n/strings/en_EN_orig.json && matrix-gen-i18n && matrix-compare-i18n-files src/i18n/strings/en_EN_orig.json src/i18n/strings/en_EN.json", "reskindex": "node scripts/reskindex.js -h header", "reskindex:watch": "node scripts/reskindex.js -h header -w", "rethemendex": "res/css/rethemendex.sh", @@ -51,7 +49,8 @@ "lint:types": "tsc --noEmit --jsx react", "lint:style": "stylelint 'res/css/**/*.scss'", "test": "jest", - "test:e2e": "./test/end-to-end-tests/run.sh --app-url http://localhost:8080" + "test:e2e": "./test/end-to-end-tests/run.sh --app-url http://localhost:8080", + "coverage": "yarn test --coverage" }, "dependencies": { "@babel/runtime": "^7.12.5", @@ -133,6 +132,7 @@ "@types/modernizr": "^3.5.3", "@types/node": "^14.14.22", "@types/pako": "^1.0.1", + "@types/parse5": "^6.0.0", "@types/qrcode": "^1.3.5", "@types/react": "^16.9", "@types/react-dom": "^16.9.10", @@ -160,6 +160,7 @@ "jest-fetch-mock": "^3.0.3", "matrix-mock-request": "^1.2.3", "matrix-react-test-utils": "^0.2.2", + "matrix-web-i18n": "github:matrix-org/matrix-web-i18n", "olm": "https://packages.matrix.org/npm/olm/olm-3.2.1.tgz", "react-test-renderer": "^16.14.0", "rimraf": "^3.0.2", @@ -189,6 +190,12 @@ }, "transformIgnorePatterns": [ "/node_modules/(?!matrix-js-sdk).+$" + ], + "collectCoverageFrom": [ + "/src/**/*.{js,ts,tsx}" + ], + "coverageReporters": [ + "text" ] } } diff --git a/res/css/_components.scss b/res/css/_components.scss index 253f97bf42..ec9592f3a1 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -161,6 +161,7 @@ @import "./views/messages/_MStickerBody.scss"; @import "./views/messages/_MTextBody.scss"; @import "./views/messages/_MVideoBody.scss"; +@import "./views/messages/_MVoiceMessageBody.scss"; @import "./views/messages/_MessageActionBar.scss"; @import "./views/messages/_MessageTimestamp.scss"; @import "./views/messages/_MjolnirBody.scss"; @@ -248,6 +249,8 @@ @import "./views/toasts/_AnalyticsToast.scss"; @import "./views/toasts/_NonUrgentEchoFailureToast.scss"; @import "./views/verification/_VerificationShowSas.scss"; +@import "./views/voice_messages/_PlayPauseButton.scss"; +@import "./views/voice_messages/_PlaybackContainer.scss"; @import "./views/voice_messages/_Waveform.scss"; @import "./views/voip/_CallContainer.scss"; @import "./views/voip/_CallView.scss"; diff --git a/res/css/structures/_RoomStatusBar.scss b/res/css/structures/_RoomStatusBar.scss index 5bf2aee3ae..8cc00aba0f 100644 --- a/res/css/structures/_RoomStatusBar.scss +++ b/res/css/structures/_RoomStatusBar.scss @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -.mx_RoomStatusBar { +.mx_RoomStatusBar:not(.mx_RoomStatusBar_unsentMessages) { margin-left: 65px; min-height: 50px; } @@ -68,6 +68,99 @@ limitations under the License. min-height: 58px; } +.mx_RoomStatusBar_unsentMessages { + > div[role="alert"] { + // cheat some basic alignment + display: flex; + align-items: center; + min-height: 70px; + margin: 12px; + padding-left: 16px; + background-color: $header-panel-bg-color; + border-radius: 4px; + } + + .mx_RoomStatusBar_unsentBadge { + margin-right: 12px; + + .mx_NotificationBadge { + // Override sizing from the default badge + width: 24px !important; + height: 24px !important; + border-radius: 24px !important; + + .mx_NotificationBadge_count { + font-size: $font-16px !important; // override default + } + } + } + + .mx_RoomStatusBar_unsentTitle { + color: $warning-color; + font-size: $font-15px; + } + + .mx_RoomStatusBar_unsentDescription { + font-size: $font-12px; + } + + .mx_RoomStatusBar_unsentButtonBar { + flex-grow: 1; + text-align: right; + margin-right: 22px; + color: $muted-fg-color; + + .mx_AccessibleButton { + padding: 5px 10px; + padding-left: 28px; // 16px for the icon, 2px margin to text, 10px regular padding + display: inline-block; + position: relative; + + &:nth-child(2) { + border-left: 1px solid $resend-button-divider-color; + } + + &::before { + content: ''; + position: absolute; + left: 10px; // inset for regular button padding + background-color: $muted-fg-color; + mask-repeat: no-repeat; + mask-position: center; + mask-size: contain; + } + + &.mx_RoomStatusBar_unsentCancelAllBtn::before { + mask-image: url('$(res)/img/element-icons/trashcan.svg'); + width: 12px; + height: 16px; + top: calc(50% - 8px); // text sizes are dynamic + } + + &.mx_RoomStatusBar_unsentResendAllBtn { + padding-left: 34px; // 28px from above, but +6px to account for the wider icon + + &::before { + mask-image: url('$(res)/img/element-icons/retry.svg'); + width: 18px; + height: 18px; + top: calc(50% - 9px); // text sizes are dynamic + } + } + } + + .mx_InlineSpinner { + vertical-align: middle; + margin-right: 5px; + top: 1px; // just to help the vertical alignment be slightly better + + & + span { + margin-right: 10px; // same margin/padding as the rightmost button + } + } + } +} + .mx_RoomStatusBar_connectionLostBar img { padding-left: 10px; padding-right: 10px; @@ -103,7 +196,7 @@ limitations under the License. } .mx_MatrixChat_useCompactLayout { - .mx_RoomStatusBar { + .mx_RoomStatusBar:not(.mx_RoomStatusBar_unsentMessages) { min-height: 40px; } diff --git a/res/css/structures/_SpacePanel.scss b/res/css/structures/_SpacePanel.scss index 59f2ea947c..c433ccf275 100644 --- a/res/css/structures/_SpacePanel.scss +++ b/res/css/structures/_SpacePanel.scss @@ -79,6 +79,10 @@ $activeBorderColor: $secondary-fg-color; .mx_SpaceItem { display: inline-flex; flex-flow: wrap; + + &.mx_SpaceItem_narrow { + align-self: baseline; + } } .mx_SpaceItem.collapsed { @@ -233,7 +237,6 @@ $activeBorderColor: $secondary-fg-color; .mx_SpacePanel_badgeContainer { position: absolute; - height: 16px; // Create a flexbox to make aligning dot badges easier display: flex; @@ -245,23 +248,37 @@ $activeBorderColor: $secondary-fg-color; .mx_NotificationBadge_dot { // make the smaller dot occupy the same width for centering - margin-left: 7px; - margin-right: 7px; + margin: 0 7px; } } &.collapsed { .mx_SpaceButton { .mx_SpacePanel_badgeContainer { - right: -3px; - top: -3px; + right: 0; + top: 0; + + .mx_NotificationBadge { + background-clip: padding-box; + } + + .mx_NotificationBadge_dot { + margin: 0 -1px 0 0; + border: 3px solid $groupFilterPanel-bg-color; + } + + .mx_NotificationBadge_2char, + .mx_NotificationBadge_3char { + margin: -5px -5px 0 0; + border: 2px solid $groupFilterPanel-bg-color; + } } &.mx_SpaceButton_active .mx_SpacePanel_badgeContainer { // when we draw the selection border we move the relative bounds of our parent // so update our position within the bounds of the parent to maintain position overall - right: -6px; - top: -6px; + right: -3px; + top: -3px; } } } @@ -275,7 +292,7 @@ $activeBorderColor: $secondary-fg-color; .mx_SpaceButton:hover, .mx_SpaceButton:focus-within, .mx_SpaceButton_hasMenuOpen { - &:not(.mx_SpaceButton_home) { + &:not(.mx_SpaceButton_home):not(.mx_SpaceButton_invite) { // Hide the badge container on hover because it'll be a menu button .mx_SpacePanel_badgeContainer { width: 0; diff --git a/res/css/structures/_SpaceRoomDirectory.scss b/res/css/structures/_SpaceRoomDirectory.scss index dcceee6371..7925686bf1 100644 --- a/res/css/structures/_SpaceRoomDirectory.scss +++ b/res/css/structures/_SpaceRoomDirectory.scss @@ -26,7 +26,10 @@ limitations under the License. word-break: break-word; display: flex; flex-direction: column; +} +.mx_SpaceRoomDirectory, +.mx_SpaceRoomView_landing { .mx_Dialog_title { display: flex; @@ -56,65 +59,68 @@ limitations under the License. } } - .mx_Dialog_content { - .mx_AccessibleButton_kind_link { - padding: 0; - } + .mx_AccessibleButton_kind_link { + padding: 0; + } - .mx_SearchBox { - margin: 24px 0 16px; - } + .mx_SearchBox { + margin: 24px 0 16px; + } - .mx_SpaceRoomDirectory_noResults { - text-align: center; + .mx_SpaceRoomDirectory_noResults { + text-align: center; - > div { - font-size: $font-15px; - line-height: $font-24px; - color: $secondary-fg-color; - } - } - - .mx_SpaceRoomDirectory_listHeader { - display: flex; - min-height: 32px; - align-items: center; + > div { font-size: $font-15px; line-height: $font-24px; - color: $primary-fg-color; + color: $secondary-fg-color; + } + } - .mx_AccessibleButton { - padding: 2px 8px; - font-weight: normal; + .mx_SpaceRoomDirectory_listHeader { + display: flex; + min-height: 32px; + align-items: center; + font-size: $font-15px; + line-height: $font-24px; + color: $primary-fg-color; - & + .mx_AccessibleButton { - margin-left: 16px; - } - } + .mx_AccessibleButton { + padding: 4px 12px; + font-weight: normal; - > span { - margin-left: auto; + & + .mx_AccessibleButton { + margin-left: 16px; } } - .mx_SpaceRoomDirectory_error { - position: relative; - font-weight: $font-semi-bold; - color: $notice-primary-color; - font-size: $font-15px; - line-height: $font-18px; - margin: 20px auto 12px; - padding-left: 24px; - width: max-content; + .mx_AccessibleButton_kind_danger_outline, + .mx_AccessibleButton_kind_primary_outline { + padding: 3px 12px; // to account for the 1px border + } - &::before { - content: ""; - position: absolute; - height: 16px; - width: 16px; - left: 0; - background-image: url("$(res)/img/element-icons/warning-badge.svg"); - } + > span { + margin-left: auto; + } + } + + .mx_SpaceRoomDirectory_error { + position: relative; + font-weight: $font-semi-bold; + color: $notice-primary-color; + font-size: $font-15px; + line-height: $font-18px; + margin: 20px auto 12px; + padding-left: 24px; + width: max-content; + + &::before { + content: ""; + position: absolute; + height: 16px; + width: 16px; + left: 0; + background-image: url("$(res)/img/element-icons/warning-badge.svg"); } } } @@ -245,11 +251,17 @@ limitations under the License. grid-row: 1/3; .mx_AccessibleButton { - padding: 8px 18px; + line-height: $font-24px; + padding: 4px 16px; display: inline-block; visibility: hidden; } + .mx_AccessibleButton_kind_danger_outline, + .mx_AccessibleButton_kind_primary_outline { + padding: 3px 16px; // to account for the 1px border + } + .mx_Checkbox { display: inline-flex; vertical-align: middle; diff --git a/res/css/structures/_SpaceRoomView.scss b/res/css/structures/_SpaceRoomView.scss index 269f16beb7..ff51e28b7b 100644 --- a/res/css/structures/_SpaceRoomView.scss +++ b/res/css/structures/_SpaceRoomView.scss @@ -81,6 +81,16 @@ $SpaceRoomViewInnerWidth: 428px; color: $secondary-fg-color; margin-top: 12px; margin-bottom: 24px; + max-width: $SpaceRoomViewInnerWidth; + } + + .mx_AddExistingToSpace { + max-width: $SpaceRoomViewInnerWidth; + + .mx_AddExistingToSpace_content { + height: calc(100vh - 360px); + max-height: 400px; + } } .mx_SpaceRoomView_buttons { @@ -228,7 +238,8 @@ $SpaceRoomViewInnerWidth: 428px; .mx_SpaceRoomView_landing_inviteButton { position: relative; - padding-left: 40px; + padding: 4px 18px 4px 40px; + line-height: $font-24px; height: min-content; &::before { @@ -244,6 +255,27 @@ $SpaceRoomViewInnerWidth: 428px; mask-image: url('$(res)/img/element-icons/room/invite.svg'); } } + + .mx_SpaceRoomView_landing_settingsButton { + position: relative; + margin-left: 16px; + width: 24px; + height: 24px; + + &::before { + position: absolute; + content: ""; + left: 0; + top: 0; + height: 24px; + width: 24px; + background: $tertiary-fg-color; + mask-position: center; + mask-size: contain; + mask-repeat: no-repeat; + mask-image: url('$(res)/img/element-icons/settings.svg'); + } + } } .mx_SpaceRoomView_landing_topic { @@ -258,80 +290,6 @@ $SpaceRoomViewInnerWidth: 428px; background-color: $groupFilterPanel-bg-color; } - .mx_SpaceRoomView_landing_adminButtons { - margin-top: 24px; - - .mx_AccessibleButton { - position: relative; - width: 160px; - height: 124px; - box-sizing: border-box; - padding: 72px 16px 0; - border-radius: 12px; - border: 1px solid $input-border-color; - margin-right: 28px; - margin-bottom: 20px; - font-size: $font-14px; - display: inline-block; - vertical-align: bottom; - - &:last-child { - margin-right: 0; - } - - &:hover { - background-color: rgba(141, 151, 165, 0.1); - } - - &::before, &::after { - position: absolute; - content: ""; - left: 16px; - top: 16px; - height: 40px; - width: 40px; - border-radius: 20px; - } - - &::after { - mask-position: center; - mask-size: 30px; - mask-repeat: no-repeat; - background: #ffffff; // white icon fill - } - - &.mx_SpaceRoomView_landing_addButton { - &::before { - background-color: #ac3ba8; - } - - &::after { - mask-image: url('$(res)/img/element-icons/roomlist/explore.svg'); - } - } - - &.mx_SpaceRoomView_landing_createButton { - &::before { - background-color: #368bd6; - } - - &::after { - mask-image: url('$(res)/img/element-icons/roomlist/explore.svg'); - } - } - - &.mx_SpaceRoomView_landing_settingsButton { - &::before { - background-color: #5c56f5; - } - - &::after { - mask-image: url('$(res)/img/element-icons/settings.svg'); - } - } - } - } - .mx_SearchBox { margin: 0 0 20px; } diff --git a/res/css/views/dialogs/_AddExistingToSpaceDialog.scss b/res/css/views/dialogs/_AddExistingToSpaceDialog.scss index 247df52b4a..524f107165 100644 --- a/res/css/views/dialogs/_AddExistingToSpaceDialog.scss +++ b/res/css/views/dialogs/_AddExistingToSpaceDialog.scss @@ -21,6 +21,66 @@ limitations under the License. } } +.mx_AddExistingToSpace { + .mx_SearchBox { + // To match the space around the title + margin: 0 0 15px 0; + flex-grow: 0; + } + + .mx_AddExistingToSpace_content { + flex-grow: 1; + } + + .mx_AddExistingToSpace_noResults { + display: block; + margin-top: 24px; + } + + .mx_AddExistingToSpace_section { + &:not(:first-child) { + margin-top: 24px; + } + + > h3 { + margin: 0; + color: $secondary-fg-color; + font-size: $font-12px; + font-weight: $font-semi-bold; + line-height: $font-15px; + } + + .mx_AddExistingToSpace_entry { + display: flex; + margin-top: 12px; + + .mx_BaseAvatar { + margin-right: 12px; + } + + .mx_AddExistingToSpace_entry_name { + font-size: $font-15px; + line-height: 30px; + flex-grow: 1; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + margin-right: 12px; + } + + .mx_Checkbox { + align-items: center; + } + } + } + + .mx_AddExistingToSpace_section_spaces { + .mx_BaseAvatar_image { + border-radius: 8px; + } + } +} + .mx_AddExistingToSpaceDialog { width: 480px; color: $primary-fg-color; @@ -41,7 +101,7 @@ limitations under the License. .mx_BaseAvatar { display: inline-flex; - margin: 5px 16px 5px 5px; + margin: auto 16px auto 5px; vertical-align: middle; } @@ -100,85 +160,32 @@ limitations under the License. } } - .mx_SearchBox { - // To match the space around the title - margin: 0 0 15px 0; - flex-grow: 0; - } - - .mx_AddExistingToSpaceDialog_errorText { - font-weight: $font-semi-bold; - font-size: $font-12px; - line-height: $font-15px; - color: $notice-primary-color; - margin-bottom: 28px; - } - - .mx_AddExistingToSpaceDialog_content { - flex-grow: 1; - - .mx_AddExistingToSpaceDialog_noResults { - display: block; - margin-top: 24px; - } - } - - .mx_AddExistingToSpaceDialog_section { - &:not(:first-child) { - margin-top: 24px; - } - - > h3 { - margin: 0; - color: $secondary-fg-color; - font-size: $font-12px; - font-weight: $font-semi-bold; - line-height: $font-15px; - } - - .mx_AddExistingToSpaceDialog_entry { - display: flex; - margin-top: 12px; - - .mx_BaseAvatar { - margin-right: 12px; - } - - .mx_AddExistingToSpaceDialog_entry_name { - font-size: $font-15px; - line-height: 30px; - flex-grow: 1; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - margin-right: 12px; - } - - .mx_Checkbox { - align-items: center; - } - } - } - - .mx_AddExistingToSpaceDialog_section_spaces { - .mx_BaseAvatar_image { - border-radius: 8px; - } + .mx_AddExistingToSpace { + display: contents; } .mx_AddExistingToSpaceDialog_footer { display: flex; - margin-top: 32px; + margin-top: 20px; > span { flex-grow: 1; - font-size: $font-14px; + font-size: $font-12px; line-height: $font-15px; - font-weight: $font-semi-bold; + color: $secondary-fg-color; - .mx_AccessibleButton { - font-size: inherit; - display: inline-block; + .mx_ProgressBar { + height: 8px; + width: 100%; + + @mixin ProgressBarBorderRadius 8px; + } + + .mx_AddExistingToSpaceDialog_progressText { + margin-top: 8px; + font-size: $font-15px; + line-height: $font-24px; + color: $primary-fg-color; } > * { @@ -186,8 +193,54 @@ limitations under the License. } } + .mx_AddExistingToSpaceDialog_error { + padding-left: 12px; + + > img { + align-self: center; + } + + .mx_AddExistingToSpaceDialog_errorHeading { + font-weight: $font-semi-bold; + font-size: $font-15px; + line-height: $font-18px; + color: $notice-primary-color; + } + + .mx_AddExistingToSpaceDialog_errorCaption { + margin-top: 4px; + font-size: $font-12px; + line-height: $font-15px; + color: $primary-fg-color; + } + } + .mx_AccessibleButton { display: inline-block; + align-self: center; + } + + .mx_AccessibleButton_kind_primary { + padding: 8px 36px; + } + + .mx_AddExistingToSpaceDialog_retryButton { + margin-left: 12px; + padding-left: 24px; + position: relative; + + &::before { + content: ''; + position: absolute; + background-color: $primary-fg-color; + mask-repeat: no-repeat; + mask-position: center; + mask-size: contain; + mask-image: url('$(res)/img/element-icons/retry.svg'); + width: 18px; + height: 18px; + left: 0; + } } .mx_AccessibleButton_kind_link { diff --git a/res/css/views/elements/_AccessibleButton.scss b/res/css/views/elements/_AccessibleButton.scss index 0075dcb511..2997c83cfd 100644 --- a/res/css/views/elements/_AccessibleButton.scss +++ b/res/css/views/elements/_AccessibleButton.scss @@ -76,12 +76,16 @@ limitations under the License. border: 1px solid $button-danger-bg-color; } -.mx_AccessibleButton_kind_danger.mx_AccessibleButton_disabled, -.mx_AccessibleButton_kind_danger_outline.mx_AccessibleButton_disabled { +.mx_AccessibleButton_kind_danger.mx_AccessibleButton_disabled { color: $button-danger-disabled-fg-color; background-color: $button-danger-disabled-bg-color; } +.mx_AccessibleButton_kind_danger_outline.mx_AccessibleButton_disabled { + color: $button-danger-disabled-bg-color; + border-color: $button-danger-disabled-bg-color; +} + .mx_AccessibleButton_hasKind.mx_AccessibleButton_kind_danger_sm { padding: 5px 12px; color: $button-danger-fg-color; diff --git a/res/css/views/elements/_ImageView.scss b/res/css/views/elements/_ImageView.scss index 93ebcc2d56..71035dadc3 100644 --- a/res/css/views/elements/_ImageView.scss +++ b/res/css/views/elements/_ImageView.scss @@ -31,8 +31,7 @@ limitations under the License. .mx_ImageView_image { pointer-events: all; - max-width: 95%; - max-height: 95%; + flex-shrink: 0; } .mx_ImageView_panel { diff --git a/res/css/views/elements/_ProgressBar.scss b/res/css/views/elements/_ProgressBar.scss index 770978e921..c075ac74ff 100644 --- a/res/css/views/elements/_ProgressBar.scss +++ b/res/css/views/elements/_ProgressBar.scss @@ -21,7 +21,7 @@ progress.mx_ProgressBar { appearance: none; border: none; - @mixin ProgressBarBorderRadius "6px"; + @mixin ProgressBarBorderRadius 6px; @mixin ProgressBarColour $progressbar-fg-color; @mixin ProgressBarBgColour $progressbar-bg-color; ::-webkit-progress-value { diff --git a/res/css/views/messages/_MFileBody.scss b/res/css/views/messages/_MFileBody.scss index b45126acf8..c215d69ec2 100644 --- a/res/css/views/messages/_MFileBody.scss +++ b/res/css/views/messages/_MFileBody.scss @@ -61,9 +61,9 @@ limitations under the License. .mx_MFileBody_info { background-color: $message-body-panel-bg-color; - border-radius: 4px; - width: 270px; - padding: 8px; + border-radius: 12px; + width: 243px; // same width as a playable voice message, accounting for padding + padding: 6px 12px; color: $message-body-panel-fg-color; .mx_MFileBody_info_icon { @@ -82,7 +82,7 @@ limitations under the License. mask-position: center; mask-size: cover; mask-image: url('$(res)/img/element-icons/room/composer/attach.svg'); - background-color: $message-body-panel-fg-color; + background-color: $message-body-panel-icon-fg-color; width: 13px; height: 15px; diff --git a/res/css/views/messages/_MVoiceMessageBody.scss b/res/css/views/messages/_MVoiceMessageBody.scss new file mode 100644 index 0000000000..3dfb98f778 --- /dev/null +++ b/res/css/views/messages/_MVoiceMessageBody.scss @@ -0,0 +1,19 @@ +/* +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. +*/ + +.mx_MVoiceMessageBody { + display: inline-block; // makes the playback controls magically line up +} diff --git a/res/css/views/messages/_MessageActionBar.scss b/res/css/views/messages/_MessageActionBar.scss index 1254b496b5..3ecbef0d1f 100644 --- a/res/css/views/messages/_MessageActionBar.scss +++ b/res/css/views/messages/_MessageActionBar.scss @@ -105,3 +105,11 @@ limitations under the License. .mx_MessageActionBar_optionsButton::after { mask-image: url('$(res)/img/element-icons/context-menu.svg'); } + +.mx_MessageActionBar_resendButton::after { + mask-image: url('$(res)/img/element-icons/retry.svg'); +} + +.mx_MessageActionBar_cancelButton::after { + mask-image: url('$(res)/img/element-icons/trashcan.svg'); +} diff --git a/res/css/views/messages/_ReactionsRowButton.scss b/res/css/views/messages/_ReactionsRowButton.scss index 7158ffc027..c132fa5a0f 100644 --- a/res/css/views/messages/_ReactionsRowButton.scss +++ b/res/css/views/messages/_ReactionsRowButton.scss @@ -34,6 +34,10 @@ limitations under the License. border-color: $reaction-row-button-selected-border-color; } + &.mx_AccessibleButton_disabled { + cursor: not-allowed; + } + .mx_ReactionsRowButton_content { max-width: 100px; overflow: hidden; diff --git a/res/css/views/rooms/_EventTile.scss b/res/css/views/rooms/_EventTile.scss index 35a5d8fc15..a6ccde93d3 100644 --- a/res/css/views/rooms/_EventTile.scss +++ b/res/css/views/rooms/_EventTile.scss @@ -219,10 +219,6 @@ $left-gutter: 64px; color: $accent-fg-color; } -.mx_EventTile_notSent { - color: $event-notsent-color; -} - .mx_EventTile_receiptSent, .mx_EventTile_receiptSending { // We don't use `position: relative` on the element because then it won't line diff --git a/res/css/views/rooms/_VoiceRecordComposerTile.scss b/res/css/views/rooms/_VoiceRecordComposerTile.scss index 8100a03890..b87211a847 100644 --- a/res/css/views/rooms/_VoiceRecordComposerTile.scss +++ b/res/css/views/rooms/_VoiceRecordComposerTile.scss @@ -35,44 +35,42 @@ limitations under the License. } } -.mx_VoiceRecordComposerTile_waveformContainer { - padding: 5px; - padding-right: 4px; // there's 1px from the waveform itself, so account for that - padding-left: 15px; // +10px for the live circle, +5px for regular padding - background-color: $voice-record-waveform-bg-color; - border-radius: 12px; - margin-right: 12px; // isolate from stop button +.mx_VoiceRecordComposerTile_delete { + width: 14px; // w&h are size of icon + height: 18px; + vertical-align: middle; + margin-right: 11px; // distance from left edge of waveform container (container has some margin too) + background-color: $voice-record-icon-color; + mask-repeat: no-repeat; + mask-size: contain; + mask-image: url('$(res)/img/element-icons/trashcan.svg'); +} - // Cheat at alignment a bit - display: flex; - align-items: center; +.mx_VoiceRecordComposerTile_recording.mx_VoiceMessagePrimaryContainer { + // Note: remaining class properties are in the PlayerContainer CSS. + + margin: 6px; // force the composer area to put a gutter around us + margin-right: 12px; // isolate from stop button position: relative; // important for the live circle - color: $voice-record-waveform-fg-color; - font-size: $font-14px; + &.mx_VoiceRecordComposerTile_recording { + // We are putting the circle in this padding, so we need +10px from the regular + // padding on the left side. + padding-left: 22px; - &::before { - animation: recording-pulse 2s infinite; + &::before { + animation: recording-pulse 2s infinite; - content: ''; - background-color: $voice-record-live-circle-color; - width: 10px; - height: 10px; - position: absolute; - left: 8px; - top: 16px; // vertically center - border-radius: 10px; - } - - .mx_Waveform_bar { - background-color: $voice-record-waveform-fg-color; - } - - .mx_Clock { - padding-right: 8px; // isolate from waveform - padding-left: 10px; // isolate from live circle - width: 42px; // we're not using a monospace font, so fake it + content: ''; + background-color: $voice-record-live-circle-color; + width: 10px; + height: 10px; + position: absolute; + left: 12px; // 12px from the left edge for container padding + top: 18px; // vertically center (middle align with clock) + border-radius: 10px; + } } } diff --git a/res/css/views/settings/tabs/user/_HelpUserSettingsTab.scss b/res/css/views/settings/tabs/user/_HelpUserSettingsTab.scss index 109edfff81..0f879d209e 100644 --- a/res/css/views/settings/tabs/user/_HelpUserSettingsTab.scss +++ b/res/css/views/settings/tabs/user/_HelpUserSettingsTab.scss @@ -22,3 +22,34 @@ limitations under the License. .mx_HelpUserSettingsTab span.mx_AccessibleButton { word-break: break-word; } + +.mx_HelpUserSettingsTab code { + word-break: break-all; + user-select: all; +} + +.mx_HelpUserSettingsTab_accessToken { + display: flex; + justify-content: space-between; + border-radius: 5px; + border: solid 1px $light-fg-color; + margin-bottom: 10px; + margin-top: 10px; + padding: 10px; +} + +.mx_HelpUserSettingsTab_accessToken_copy { + flex-shrink: 0; + cursor: pointer; + margin-left: 20px; + display: inherit; +} + +.mx_HelpUserSettingsTab_accessToken_copy > div { + mask-image: url($copy-button-url); + background-color: $message-action-bar-fg-color; + margin-left: 5px; + width: 20px; + height: 20px; + background-repeat: no-repeat; +} diff --git a/res/css/views/voice_messages/_PlayPauseButton.scss b/res/css/views/voice_messages/_PlayPauseButton.scss new file mode 100644 index 0000000000..6caedafa29 --- /dev/null +++ b/res/css/views/voice_messages/_PlayPauseButton.scss @@ -0,0 +1,51 @@ +/* +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. +*/ + +.mx_PlayPauseButton { + position: relative; + width: 32px; + height: 32px; + border-radius: 32px; + background-color: $voice-playback-button-bg-color; + + &::before { + content: ''; + position: absolute; // sizing varies by icon + background-color: $voice-playback-button-fg-color; + mask-repeat: no-repeat; + mask-size: contain; + } + + &.mx_PlayPauseButton_disabled::before { + opacity: 0.5; + } + + &.mx_PlayPauseButton_play::before { + width: 13px; + height: 16px; + top: 8px; // center + left: 12px; // center + mask-image: url('$(res)/img/element-icons/play.svg'); + } + + &.mx_PlayPauseButton_pause::before { + width: 10px; + height: 12px; + top: 10px; // center + left: 11px; // center + mask-image: url('$(res)/img/element-icons/pause.svg'); + } +} diff --git a/res/css/views/voice_messages/_PlaybackContainer.scss b/res/css/views/voice_messages/_PlaybackContainer.scss new file mode 100644 index 0000000000..64e8f445e1 --- /dev/null +++ b/res/css/views/voice_messages/_PlaybackContainer.scss @@ -0,0 +1,53 @@ +/* +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. +*/ + +// Dev note: there's no actual component called . These classes +// are shared amongst multiple voice message components. + +// Container for live recording and playback controls +.mx_VoiceMessagePrimaryContainer { + // 7px top and bottom for visual design. 12px left & right, but the waveform (right) + // has a 1px padding on it that we want to account for. + padding: 7px 12px 7px 11px; + background-color: $voice-record-waveform-bg-color; + border-radius: 12px; + + // Cheat at alignment a bit + display: flex; + align-items: center; + + color: $voice-record-waveform-fg-color; + font-size: $font-14px; + line-height: $font-24px; + + .mx_Waveform { + .mx_Waveform_bar { + background-color: $voice-record-waveform-incomplete-fg-color; + + &.mx_Waveform_bar_100pct { + // Small animation to remove the mechanical feel of progress + transition: background-color 250ms ease; + background-color: $voice-record-waveform-fg-color; + } + } + } + + .mx_Clock { + width: 42px; // we're not using a monospace font, so fake it + padding-right: 6px; // with the fixed width this ends up as a visual 8px most of the time, as intended. + padding-left: 8px; // isolate from recording circle / play control + } +} diff --git a/res/css/views/voip/_CallView.scss b/res/css/views/voip/_CallView.scss index d13272c8c0..0be75be28c 100644 --- a/res/css/views/voip/_CallView.scss +++ b/res/css/views/voip/_CallView.scss @@ -17,7 +17,7 @@ limitations under the License. .mx_CallView { border-radius: 8px; - background-color: $voipcall-plinth-color; + background-color: $dark-panel-bg-color; padding-left: 8px; padding-right: 8px; // XXX: CallContainer sets pointer-events: none - should probably be set back in a better place @@ -40,7 +40,8 @@ limitations under the License. width: 320px; padding-bottom: 8px; margin-top: 10px; - box-shadow: 0px 14px 24px rgba(0, 0, 0, 0.08); + background-color: $voipcall-plinth-color; + box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.20); border-radius: 8px; .mx_CallView_voice { @@ -64,14 +65,17 @@ limitations under the License. } } -.mx_CallView_voice { +.mx_CallView_content { position: relative; display: flex; - flex-direction: column; + border-radius: 8px; +} + +.mx_CallView_voice { align-items: center; justify-content: center; + flex-direction: column; background-color: $inverted-bg-color; - border-radius: 8px; } .mx_CallView_voice_avatarsContainer { @@ -108,9 +112,7 @@ limitations under the License. .mx_CallView_video { width: 100%; height: 100%; - position: relative; z-index: 30; - border-radius: 8px; overflow: hidden; } diff --git a/res/css/views/voip/_VideoFeed.scss b/res/css/views/voip/_VideoFeed.scss index 8ead8bba3e..7d85ac264e 100644 --- a/res/css/views/voip/_VideoFeed.scss +++ b/res/css/views/voip/_VideoFeed.scss @@ -14,21 +14,37 @@ See the License for the specific language governing permissions and limitations under the License. */ +.mx_VideoFeed_voice { + // We don't want to collide with the call controls that have 52px of height + padding-bottom: 52px; + background-color: $inverted-bg-color; +} + + .mx_VideoFeed_remote { width: 100%; height: 100%; - background-color: #000; - z-index: 50; + display: flex; + justify-content: center; + align-items: center; + + &.mx_VideoFeed_video { + background-color: #000; + } } .mx_VideoFeed_local { - width: 25%; - height: 25%; + max-width: 25%; + max-height: 25%; position: absolute; right: 10px; top: 10px; z-index: 100; border-radius: 4px; + + &.mx_VideoFeed_video { + background-color: transparent; + } } .mx_VideoFeed_mirror { diff --git a/res/img/element-icons/pause.svg b/res/img/element-icons/pause.svg new file mode 100644 index 0000000000..293c0a10d8 --- /dev/null +++ b/res/img/element-icons/pause.svg @@ -0,0 +1,4 @@ + + + + diff --git a/res/img/element-icons/play.svg b/res/img/element-icons/play.svg new file mode 100644 index 0000000000..339e20b729 --- /dev/null +++ b/res/img/element-icons/play.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/img/element-icons/retry.svg b/res/img/element-icons/retry.svg new file mode 100644 index 0000000000..09448d6458 --- /dev/null +++ b/res/img/element-icons/retry.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/img/element-icons/trashcan.svg b/res/img/element-icons/trashcan.svg new file mode 100644 index 0000000000..f8fb8b5c46 --- /dev/null +++ b/res/img/element-icons/trashcan.svg @@ -0,0 +1,3 @@ + + + diff --git a/res/themes/dark/css/_dark.scss b/res/themes/dark/css/_dark.scss index 925d268eb0..2d0e3d2a8b 100644 --- a/res/themes/dark/css/_dark.scss +++ b/res/themes/dark/css/_dark.scss @@ -9,6 +9,7 @@ $header-panel-text-primary-color: #B9BEC6; $header-panel-text-secondary-color: #c8c8cd; $text-primary-color: #ffffff; $text-secondary-color: #B9BEC6; +$quaternary-fg-color: #6F7882; $search-bg-color: #181b21; $search-placeholder-color: #61708b; $room-highlight-color: #343a46; @@ -63,6 +64,8 @@ $input-invalid-border-color: $warning-color; $field-focused-label-bg-color: $bg-color; +$resend-button-divider-color: #b9bec64a; // muted-text with a 4A opacity. + // scrollbars $scrollbar-thumb-color: rgba(255, 255, 255, 0.2); $scrollbar-track-color: transparent; @@ -110,7 +113,7 @@ $header-divider-color: $header-panel-text-primary-color; $composer-e2e-icon-color: $header-panel-text-primary-color; // this probably shouldn't have it's own colour -$voipcall-plinth-color: #21262c; +$voipcall-plinth-color: #394049; // ******************** @@ -203,9 +206,18 @@ $breadcrumb-placeholder-bg-color: #272c35; $user-tile-hover-bg-color: $header-panel-bg-color; -$message-body-panel-bg-color: #21262c82; -$message-body-panel-icon-bg-color: #8e99a4; -$message-body-panel-fg-color: $primary-fg-color; +$message-body-panel-fg-color: $secondary-fg-color; +$message-body-panel-bg-color: #394049; // "Dark Tile" +$message-body-panel-icon-fg-color: #21262C; // "Separator" +$message-body-panel-icon-bg-color: $tertiary-fg-color; + +$voice-record-stop-border-color: $quaternary-fg-color; +$voice-record-waveform-bg-color: $message-body-panel-bg-color; +$voice-record-waveform-fg-color: $message-body-panel-fg-color; +$voice-record-waveform-incomplete-fg-color: $quaternary-fg-color; +$voice-record-icon-color: $quaternary-fg-color; +$voice-playback-button-bg-color: $message-body-panel-icon-bg-color; +$voice-playback-button-fg-color: $message-body-panel-icon-fg-color; // Appearance tab colors $appearance-tab-border-color: $room-highlight-color; diff --git a/res/themes/legacy-dark/css/_legacy-dark.scss b/res/themes/legacy-dark/css/_legacy-dark.scss index 28e6e22326..a852ad94e9 100644 --- a/res/themes/legacy-dark/css/_legacy-dark.scss +++ b/res/themes/legacy-dark/css/_legacy-dark.scss @@ -61,6 +61,8 @@ $input-invalid-border-color: $warning-color; $field-focused-label-bg-color: $bg-color; +$resend-button-divider-color: $muted-fg-color; + // scrollbars $scrollbar-thumb-color: rgba(255, 255, 255, 0.2); $scrollbar-track-color: transparent; @@ -107,7 +109,7 @@ $header-divider-color: $header-panel-text-primary-color; $composer-e2e-icon-color: $header-panel-text-primary-color; // this probably shouldn't have it's own colour -$voipcall-plinth-color: #f2f5f8; +$voipcall-plinth-color: #394049; // ******************** @@ -198,9 +200,19 @@ $breadcrumb-placeholder-bg-color: #272c35; $user-tile-hover-bg-color: $header-panel-bg-color; -$message-body-panel-bg-color: #21262c82; -$message-body-panel-icon-bg-color: #8e99a4; -$message-body-panel-fg-color: $primary-fg-color; +$message-body-panel-fg-color: $secondary-fg-color; +$message-body-panel-bg-color: #394049; +$message-body-panel-icon-fg-color: $primary-bg-color; +$message-body-panel-icon-bg-color: $secondary-fg-color; + +// See non-legacy dark for variable information +$voice-record-stop-border-color: #6F7882; +$voice-record-waveform-bg-color: $message-body-panel-bg-color; +$voice-record-waveform-fg-color: $message-body-panel-fg-color; +$voice-record-waveform-incomplete-fg-color: #6F7882; +$voice-record-icon-color: #6F7882; +$voice-playback-button-bg-color: $tertiary-fg-color; +$voice-playback-button-fg-color: #21262C; // Appearance tab colors $appearance-tab-border-color: $room-highlight-color; diff --git a/res/themes/legacy-light/css/_legacy-light.scss b/res/themes/legacy-light/css/_legacy-light.scss index 7b6bdad4a4..84666bc662 100644 --- a/res/themes/legacy-light/css/_legacy-light.scss +++ b/res/themes/legacy-light/css/_legacy-light.scss @@ -97,6 +97,8 @@ $input-invalid-border-color: $warning-color; $field-focused-label-bg-color: #ffffff; +$resend-button-divider-color: $input-darker-bg-color; + $button-bg-color: $accent-color; $button-fg-color: white; @@ -174,7 +176,7 @@ $composer-e2e-icon-color: #91a1c0; $header-divider-color: #91a1c0; // this probably shouldn't have it's own colour -$voipcall-plinth-color: #f2f5f8; +$voipcall-plinth-color: #F4F6FA; // ******************** @@ -189,13 +191,6 @@ $roomsublist-skeleton-ui-bg: linear-gradient(180deg, #ffffff 0%, #ffffff00 100%) $groupFilterPanel-divider-color: $roomlist-header-color; -// See non-legacy _light for variable information -$voice-record-stop-border-color: #E3E8F0; -$voice-record-stop-symbol-color: #ff4b55; -$voice-record-waveform-bg-color: #E3E8F0; -$voice-record-waveform-fg-color: $muted-fg-color; -$voice-record-live-circle-color: #ff4b55; - $roomtile-preview-color: #9e9e9e; $roomtile-default-badge-bg-color: #61708b; $roomtile-selected-bg-color: #fff; @@ -328,9 +323,21 @@ $breadcrumb-placeholder-bg-color: #e8eef5; $user-tile-hover-bg-color: $header-panel-bg-color; -$message-body-panel-bg-color: #e3e8f082; -$message-body-panel-icon-bg-color: #ffffff; -$message-body-panel-fg-color: $muted-fg-color; +$message-body-panel-fg-color: $secondary-fg-color; +$message-body-panel-bg-color: #E3E8F0; +$message-body-panel-icon-fg-color: $secondary-fg-color; +$message-body-panel-icon-bg-color: $primary-bg-color; + +// See non-legacy _light for variable information +$voice-record-stop-symbol-color: #ff4b55; +$voice-record-live-circle-color: #ff4b55; +$voice-record-stop-border-color: #E3E8F0; +$voice-record-waveform-bg-color: $message-body-panel-bg-color; +$voice-record-waveform-fg-color: $message-body-panel-fg-color; +$voice-record-waveform-incomplete-fg-color: #C1C6CD; +$voice-record-icon-color: $tertiary-fg-color; +$voice-playback-button-bg-color: $message-body-panel-icon-bg-color; +$voice-playback-button-fg-color: $message-body-panel-icon-fg-color; // FontSlider colors $appearance-tab-border-color: $input-darker-bg-color; diff --git a/res/themes/light/css/_light.scss b/res/themes/light/css/_light.scss index 5b46138dae..c889f43d0b 100644 --- a/res/themes/light/css/_light.scss +++ b/res/themes/light/css/_light.scss @@ -21,6 +21,7 @@ $notice-primary-bg-color: rgba(255, 75, 85, 0.16); $primary-fg-color: #2e2f32; $secondary-fg-color: #737D8C; $tertiary-fg-color: #8D99A5; +$quaternary-fg-color: #C1C6CD; $header-panel-bg-color: #f3f8fd; // typical text (dark-on-white in light skin) @@ -91,6 +92,8 @@ $field-focused-label-bg-color: #ffffff; $button-bg-color: $accent-color; $button-fg-color: white; +$resend-button-divider-color: $input-darker-bg-color; + // apart from login forms, which have stronger border $strong-input-border-color: #c7c7c7; @@ -165,7 +168,7 @@ $composer-e2e-icon-color: #91A1C0; $header-divider-color: #91A1C0; // this probably shouldn't have it's own colour -$voipcall-plinth-color: #f2f5f8; +$voipcall-plinth-color: #F4F6FA; // ******************** @@ -180,12 +183,6 @@ $roomsublist-skeleton-ui-bg: linear-gradient(180deg, #ffffff 0%, #ffffff00 100%) $groupFilterPanel-divider-color: $roomlist-header-color; -$voice-record-stop-border-color: #E3E8F0; -$voice-record-stop-symbol-color: #ff4b55; // $warning-color, but without letting people change it in themes -$voice-record-waveform-bg-color: #E3E8F0; -$voice-record-waveform-fg-color: $muted-fg-color; -$voice-record-live-circle-color: #ff4b55; // $warning-color, but without letting people change it in themes - $roomtile-preview-color: $secondary-fg-color; $roomtile-default-badge-bg-color: #61708b; $roomtile-selected-bg-color: #FFF; @@ -325,9 +322,23 @@ $breadcrumb-placeholder-bg-color: #e8eef5; $user-tile-hover-bg-color: $header-panel-bg-color; -$message-body-panel-bg-color: #e3e8f082; -$message-body-panel-icon-bg-color: #ffffff; -$message-body-panel-fg-color: $muted-fg-color; +$message-body-panel-fg-color: $secondary-fg-color; +$message-body-panel-bg-color: #E3E8F0; // "Separator" +$message-body-panel-icon-fg-color: $secondary-fg-color; +$message-body-panel-icon-bg-color: $primary-bg-color; + +// These two don't change between themes. They are the $warning-color, but we don't +// want custom themes to affect them by accident. +$voice-record-stop-symbol-color: #ff4b55; +$voice-record-live-circle-color: #ff4b55; + +$voice-record-stop-border-color: #E3E8F0; // "Separator" +$voice-record-waveform-bg-color: $message-body-panel-bg-color; +$voice-record-waveform-fg-color: $message-body-panel-fg-color; +$voice-record-waveform-incomplete-fg-color: $quaternary-fg-color; +$voice-record-icon-color: $tertiary-fg-color; +$voice-playback-button-bg-color: $message-body-panel-icon-bg-color; +$voice-playback-button-fg-color: $message-body-panel-icon-fg-color; // FontSlider colors $appearance-tab-border-color: $input-darker-bg-color; diff --git a/scripts/compare-file.js b/scripts/compare-file.js deleted file mode 100644 index f53275ebfa..0000000000 --- a/scripts/compare-file.js +++ /dev/null @@ -1,10 +0,0 @@ -const fs = require("fs"); - -if (process.argv.length < 4) throw new Error("Missing source and target file arguments"); - -const sourceFile = fs.readFileSync(process.argv[2], 'utf8'); -const targetFile = fs.readFileSync(process.argv[3], 'utf8'); - -if (sourceFile !== targetFile) { - throw new Error("Files do not match"); -} diff --git a/scripts/gen-i18n.js b/scripts/gen-i18n.js deleted file mode 100755 index 91733469f7..0000000000 --- a/scripts/gen-i18n.js +++ /dev/null @@ -1,304 +0,0 @@ -#!/usr/bin/env node - -/* -Copyright 2017 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. -*/ - -/** - * Regenerates the translations en_EN file by walking the source tree and - * parsing each file with the appropriate parser. Emits a JSON file with the - * translatable strings mapped to themselves in the order they appeared - * in the files and grouped by the file they appeared in. - * - * Usage: node scripts/gen-i18n.js - */ -const fs = require('fs'); -const path = require('path'); - -const walk = require('walk'); - -const parser = require("@babel/parser"); -const traverse = require("@babel/traverse"); - -const TRANSLATIONS_FUNCS = ['_t', '_td']; - -const INPUT_TRANSLATIONS_FILE = 'src/i18n/strings/en_EN.json'; -const OUTPUT_FILE = 'src/i18n/strings/en_EN.json'; - -// NB. The sync version of walk is broken for single files so we walk -// all of res rather than just res/home.html. -// https://git.daplie.com/Daplie/node-walk/merge_requests/1 fixes it, -// or if we get bored waiting for it to be merged, we could switch -// to a project that's actively maintained. -const SEARCH_PATHS = ['src', 'res']; - -function getObjectValue(obj, key) { - for (const prop of obj.properties) { - if (prop.key.type === 'Identifier' && prop.key.name === key) { - return prop.value; - } - } - return null; -} - -function getTKey(arg) { - if (arg.type === 'Literal' || arg.type === "StringLiteral") { - return arg.value; - } else if (arg.type === 'BinaryExpression' && arg.operator === '+') { - return getTKey(arg.left) + getTKey(arg.right); - } else if (arg.type === 'TemplateLiteral') { - return arg.quasis.map((q) => { - return q.value.raw; - }).join(''); - } - return null; -} - -function getFormatStrings(str) { - // Match anything that starts with % - // We could make a regex that matched the full placeholder, but this - // would just not match invalid placeholders and so wouldn't help us - // detect the invalid ones. - // Also note that for simplicity, this just matches a % character and then - // anything up to the next % character (or a single %, or end of string). - const formatStringRe = /%([^%]+|%|$)/g; - const formatStrings = new Set(); - - let match; - while ( (match = formatStringRe.exec(str)) !== null ) { - const placeholder = match[1]; // Minus the leading '%' - if (placeholder === '%') continue; // Literal % is %% - - const placeholderMatch = placeholder.match(/^\((.*?)\)(.)/); - if (placeholderMatch === null) { - throw new Error("Invalid format specifier: '"+match[0]+"'"); - } - if (placeholderMatch.length < 3) { - throw new Error("Malformed format specifier"); - } - const placeholderName = placeholderMatch[1]; - const placeholderFormat = placeholderMatch[2]; - - if (placeholderFormat !== 's') { - throw new Error(`'${placeholderFormat}' used as format character: you probably meant 's'`); - } - - formatStrings.add(placeholderName); - } - - return formatStrings; -} - -function getTranslationsJs(file) { - const contents = fs.readFileSync(file, { encoding: 'utf8' }); - - const trs = new Set(); - - try { - const plugins = [ - // https://babeljs.io/docs/en/babel-parser#plugins - "classProperties", - "objectRestSpread", - "throwExpressions", - "exportDefaultFrom", - "decorators-legacy", - ]; - - if (file.endsWith(".js") || file.endsWith(".jsx")) { - // all JS is assumed to be flow or react - plugins.push("flow", "jsx"); - } else if (file.endsWith(".ts")) { - // TS can't use JSX unless it's a TSX file (otherwise angle casts fail) - plugins.push("typescript"); - } else if (file.endsWith(".tsx")) { - // When the file is a TSX file though, enable JSX parsing - plugins.push("typescript", "jsx"); - } - - const babelParsed = parser.parse(contents, { - allowImportExportEverywhere: true, - errorRecovery: true, - sourceFilename: file, - tokens: true, - plugins, - }); - traverse.default(babelParsed, { - enter: (p) => { - const node = p.node; - if (p.isCallExpression() && node.callee && TRANSLATIONS_FUNCS.includes(node.callee.name)) { - const tKey = getTKey(node.arguments[0]); - - // This happens whenever we call _t with non-literals (ie. whenever we've - // had to use a _td to compensate) so is expected. - if (tKey === null) return; - - // check the format string against the args - // We only check _t: _td has no args - if (node.callee.name === '_t') { - try { - const placeholders = getFormatStrings(tKey); - for (const placeholder of placeholders) { - if (node.arguments.length < 2) { - throw new Error(`Placeholder found ('${placeholder}') but no substitutions given`); - } - const value = getObjectValue(node.arguments[1], placeholder); - if (value === null) { - throw new Error(`No value found for placeholder '${placeholder}'`); - } - } - - // Validate tag replacements - if (node.arguments.length > 2) { - const tagMap = node.arguments[2]; - for (const prop of tagMap.properties || []) { - if (prop.key.type === 'Literal') { - const tag = prop.key.value; - // RegExp same as in src/languageHandler.js - const regexp = new RegExp(`(<${tag}>(.*?)<\\/${tag}>|<${tag}>|<${tag}\\s*\\/>)`); - if (!tKey.match(regexp)) { - throw new Error(`No match for ${regexp} in ${tKey}`); - } - } - } - } - - } catch (e) { - console.log(); - console.error(`ERROR: ${file}:${node.loc.start.line} ${tKey}`); - console.error(e); - process.exit(1); - } - } - - let isPlural = false; - if (node.arguments.length > 1 && node.arguments[1].type === 'ObjectExpression') { - const countVal = getObjectValue(node.arguments[1], 'count'); - if (countVal) { - isPlural = true; - } - } - - if (isPlural) { - trs.add(tKey + "|other"); - const plurals = enPlurals[tKey]; - if (plurals) { - for (const pluralType of Object.keys(plurals)) { - trs.add(tKey + "|" + pluralType); - } - } - } else { - trs.add(tKey); - } - } - }, - }); - } catch (e) { - console.error(e); - process.exit(1); - } - - return trs; -} - -function getTranslationsOther(file) { - const contents = fs.readFileSync(file, { encoding: 'utf8' }); - - const trs = new Set(); - - // Taken from element-web src/components/structures/HomePage.js - const translationsRegex = /_t\(['"]([\s\S]*?)['"]\)/mg; - let matches; - while (matches = translationsRegex.exec(contents)) { - trs.add(matches[1]); - } - return trs; -} - -// gather en_EN plural strings from the input translations file: -// the en_EN strings are all in the source with the exception of -// pluralised strings, which we need to pull in from elsewhere. -const inputTranslationsRaw = JSON.parse(fs.readFileSync(INPUT_TRANSLATIONS_FILE, { encoding: 'utf8' })); -const enPlurals = {}; - -for (const key of Object.keys(inputTranslationsRaw)) { - const parts = key.split("|"); - if (parts.length > 1) { - const plurals = enPlurals[parts[0]] || {}; - plurals[parts[1]] = inputTranslationsRaw[key]; - enPlurals[parts[0]] = plurals; - } -} - -const translatables = new Set(); - -const walkOpts = { - listeners: { - names: function(root, nodeNamesArray) { - // Sort the names case insensitively and alphabetically to - // maintain some sense of order between the different strings. - nodeNamesArray.sort((a, b) => { - a = a.toLowerCase(); - b = b.toLowerCase(); - if (a > b) return 1; - if (a < b) return -1; - return 0; - }); - }, - file: function(root, fileStats, next) { - const fullPath = path.join(root, fileStats.name); - - let trs; - if (fileStats.name.endsWith('.js') || fileStats.name.endsWith('.ts') || fileStats.name.endsWith('.tsx')) { - trs = getTranslationsJs(fullPath); - } else if (fileStats.name.endsWith('.html')) { - trs = getTranslationsOther(fullPath); - } else { - return; - } - console.log(`${fullPath} (${trs.size} strings)`); - for (const tr of trs.values()) { - // Convert DOS line endings to unix - translatables.add(tr.replace(/\r\n/g, "\n")); - } - }, - } -}; - -for (const path of SEARCH_PATHS) { - if (fs.existsSync(path)) { - walk.walkSync(path, walkOpts); - } -} - -const trObj = {}; -for (const tr of translatables) { - if (tr.includes("|")) { - if (inputTranslationsRaw[tr]) { - trObj[tr] = inputTranslationsRaw[tr]; - } else { - trObj[tr] = tr.split("|")[0]; - } - } else { - trObj[tr] = tr; - } -} - -fs.writeFileSync( - OUTPUT_FILE, - JSON.stringify(trObj, translatables.values(), 4) + "\n" -); - -console.log(); -console.log(`Wrote ${translatables.size} strings to ${OUTPUT_FILE}`); diff --git a/scripts/prune-i18n.js b/scripts/prune-i18n.js deleted file mode 100755 index b4fe8d69f5..0000000000 --- a/scripts/prune-i18n.js +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env node - -/* -Copyright 2017 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. -*/ - -/* - * Looks through all the translation files and removes any strings - * which don't appear in en_EN.json. - * Use this if you remove a translation, but merge any outstanding changes - * from weblate first or you'll need to resolve the conflict in weblate. - */ - -const fs = require('fs'); -const path = require('path'); - -const I18NDIR = 'src/i18n/strings'; - -const enStringsRaw = JSON.parse(fs.readFileSync(path.join(I18NDIR, 'en_EN.json'))); - -const enStrings = new Set(); -for (const str of Object.keys(enStringsRaw)) { - const parts = str.split('|'); - if (parts.length > 1) { - enStrings.add(parts[0]); - } else { - enStrings.add(str); - } -} - -for (const filename of fs.readdirSync(I18NDIR)) { - if (filename === 'en_EN.json') continue; - if (filename === 'basefile.json') continue; - if (!filename.endsWith('.json')) continue; - - const trs = JSON.parse(fs.readFileSync(path.join(I18NDIR, filename))); - const oldLen = Object.keys(trs).length; - for (const tr of Object.keys(trs)) { - const parts = tr.split('|'); - const trKey = parts.length > 1 ? parts[0] : tr; - if (!enStrings.has(trKey)) { - delete trs[tr]; - } - } - - const removed = oldLen - Object.keys(trs).length; - if (removed > 0) { - console.log(`${filename}: removed ${removed} translations`); - // XXX: This is totally relying on the impl serialising the JSON object in the - // same order as they were parsed from the file. JSON.stringify() has a specific argument - // that can be used to control the order, but JSON.parse() lacks any kind of equivalent. - // Empirically this does maintain the order on my system, so I'm going to leave it like - // this for now. - fs.writeFileSync(path.join(I18NDIR, filename), JSON.stringify(trs, undefined, 4) + "\n"); - } -} diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts index 41257c21f0..e8f2f1bc08 100644 --- a/src/@types/global.d.ts +++ b/src/@types/global.d.ts @@ -1,5 +1,5 @@ /* -Copyright 2020 The Matrix.org Foundation C.I.C. +Copyright 2020-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. @@ -39,7 +39,9 @@ import {ModalWidgetStore} from "../stores/ModalWidgetStore"; import { WidgetLayoutStore } from "../stores/widgets/WidgetLayoutStore"; import VoipUserMapper from "../VoipUserMapper"; import {SpaceStoreClass} from "../stores/SpaceStore"; -import {VoiceRecording} from "../voice/VoiceRecording"; +import TypingStore from "../stores/TypingStore"; +import { EventIndexPeg } from "../indexing/EventIndexPeg"; +import {VoiceRecordingStore} from "../stores/VoiceRecordingStore"; declare global { interface Window { @@ -71,12 +73,16 @@ declare global { mxModalWidgetStore: ModalWidgetStore; mxVoipUserMapper: VoipUserMapper; mxSpaceStore: SpaceStoreClass; - mxVoiceRecorder: typeof VoiceRecording; + mxVoiceRecordingStore: VoiceRecordingStore; + mxTypingStore: TypingStore; + mxEventIndexPeg: EventIndexPeg; } interface Document { // https://developer.mozilla.org/en-US/docs/Web/API/Document/hasStorageAccess hasStorageAccess?: () => Promise; + // https://developer.mozilla.org/en-US/docs/Web/API/Document/requestStorageAccess + requestStorageAccess?: () => Promise; // Safari & IE11 only have this prefixed: we used prefixed versions // previously so let's continue to support them for now @@ -112,6 +118,16 @@ declare global { interface HTMLAudioElement { type?: string; + // sinkId & setSinkId are experimental and typescript doesn't know about them + sinkId: string; + setSinkId(outputId: string); + } + + interface HTMLVideoElement { + type?: string; + // sinkId & setSinkId are experimental and typescript doesn't know about them + sinkId: string; + setSinkId(outputId: string); } interface Element { diff --git a/src/Avatar.ts b/src/Avatar.ts index 76c88faa1c..a6499c688e 100644 --- a/src/Avatar.ts +++ b/src/Avatar.ts @@ -20,6 +20,7 @@ import {Room} from "matrix-js-sdk/src/models/room"; import DMRoomMap from './utils/DMRoomMap'; import {mediaFromMxc} from "./customisations/Media"; +import SettingsStore from "./settings/SettingsStore"; export type ResizeMethod = "crop" | "scale"; @@ -27,11 +28,7 @@ export type ResizeMethod = "crop" | "scale"; export function avatarUrlForMember(member: RoomMember, width: number, height: number, resizeMethod: ResizeMethod) { let url: string; if (member?.getMxcAvatarUrl()) { - url = mediaFromMxc(member.getMxcAvatarUrl()).getThumbnailOfSourceHttp( - Math.floor(width * window.devicePixelRatio), - Math.floor(height * window.devicePixelRatio), - resizeMethod, - ); + url = mediaFromMxc(member.getMxcAvatarUrl()).getThumbnailOfSourceHttp(width, height, resizeMethod); } if (!url) { // member can be null here currently since on invites, the JS SDK @@ -44,11 +41,7 @@ export function avatarUrlForMember(member: RoomMember, width: number, height: nu export function avatarUrlForUser(user: User, width: number, height: number, resizeMethod?: ResizeMethod) { if (!user.avatarUrl) return null; - return mediaFromMxc(user.avatarUrl).getThumbnailOfSourceHttp( - Math.floor(width * window.devicePixelRatio), - Math.floor(height * window.devicePixelRatio), - resizeMethod, - ); + return mediaFromMxc(user.avatarUrl).getThumbnailOfSourceHttp(width, height, resizeMethod); } function isValidHexColor(color: string): boolean { @@ -151,7 +144,7 @@ export function avatarUrlForRoom(room: Room, width: number, height: number, resi } // space rooms cannot be DMs so skip the rest - if (room.isSpaceRoom()) return null; + if (SettingsStore.getValue("feature_spaces") && room.isSpaceRoom()) return null; let otherMember = null; const otherUserId = DMRoomMap.shared().getUserIdForRoomId(room.roomId); diff --git a/src/BasePlatform.ts b/src/BasePlatform.ts index b6012d7597..5483ea6874 100644 --- a/src/BasePlatform.ts +++ b/src/BasePlatform.ts @@ -258,7 +258,7 @@ export default abstract class BasePlatform { return null; } - setLanguage(preferredLangs: string[]) {} + async setLanguage(preferredLangs: string[]) {} setSpellCheckLanguages(preferredLangs: string[]) {} diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx index be687a4474..0268ebfe46 100644 --- a/src/CallHandler.tsx +++ b/src/CallHandler.tsx @@ -59,7 +59,6 @@ import {MatrixClientPeg} from './MatrixClientPeg'; import PlatformPeg from './PlatformPeg'; import Modal from './Modal'; import { _t } from './languageHandler'; -import { createNewMatrixCall } from 'matrix-js-sdk/src/webrtc/call'; import dis from './dispatcher/dispatcher'; import WidgetUtils from './utils/WidgetUtils'; import WidgetEchoStore from './stores/WidgetEchoStore'; @@ -86,6 +85,9 @@ import { Action } from './dispatcher/actions'; import VoipUserMapper from './VoipUserMapper'; import { addManagedHybridWidget, isManagedHybridWidgetEnabled } from './widgets/ManagedHybrid'; import { randomUppercaseString, randomLowercaseString } from "matrix-js-sdk/src/randomstring"; +import EventEmitter from 'events'; +import SdkConfig from './SdkConfig'; +import { ensureDMExists, findDMForUser } from './createRoom'; export const PROTOCOL_PSTN = 'm.protocol.pstn'; export const PROTOCOL_PSTN_PREFIXED = 'im.vector.protocol.pstn'; @@ -137,22 +139,12 @@ export enum PlaceCallType { ScreenSharing = 'screensharing', } -function getRemoteAudioElement(): HTMLAudioElement { - // this needs to be somewhere at the top of the DOM which - // always exists to avoid audio interruptions. - // Might as well just use DOM. - const remoteAudioElement = document.getElementById("remoteAudio") as HTMLAudioElement; - if (!remoteAudioElement) { - console.error( - "Failed to find remoteAudio element - cannot play audio!" + - "You need to add an
    ), button: _t("Trust"), - }); + }); const [confirmed] = await finished; if (confirmed) { // eslint-disable-next-line react-hooks/rules-of-hooks diff --git a/src/KeyBindingsManager.ts b/src/KeyBindingsManager.ts index d862f10c02..aac14bde20 100644 --- a/src/KeyBindingsManager.ts +++ b/src/KeyBindingsManager.ts @@ -231,8 +231,10 @@ export class KeyBindingsManager { /** * Finds a matching KeyAction for a given KeyboardEvent */ - private getAction(getters: KeyBindingGetter[], ev: KeyboardEvent | React.KeyboardEvent) - : T | undefined { + private getAction( + getters: KeyBindingGetter[], + ev: KeyboardEvent | React.KeyboardEvent, + ): T | undefined { for (const getter of getters) { const bindings = getter(); const binding = bindings.find(it => isKeyComboMatch(ev, it.keyCombo, isMac)); diff --git a/src/Login.ts b/src/Login.ts index db3c4c11e4..d584df7dfe 100644 --- a/src/Login.ts +++ b/src/Login.ts @@ -1,9 +1,6 @@ /* -Copyright 2015, 2016 OpenMarket Ltd -Copyright 2017 Vector Creations Ltd -Copyright 2018 New Vector Ltd +Copyright 2015-2021 The Matrix.org Foundation C.I.C. Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> -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. @@ -59,7 +56,7 @@ export type LoginFlow = ISSOFlow | IPasswordFlow; // TODO: Move this to JS SDK /* eslint-disable camelcase */ interface ILoginParams { - identifier?: string; + identifier?: object; password?: string; token?: string; device_id?: string; diff --git a/src/PasswordReset.js b/src/PasswordReset.js index 6fe6ca82cc..88ae00d088 100644 --- a/src/PasswordReset.js +++ b/src/PasswordReset.js @@ -54,7 +54,7 @@ export default class PasswordReset { return res; }, function(err) { if (err.errcode === 'M_THREEPID_NOT_FOUND') { - err.message = _t('This email address was not found'); + err.message = _t('This email address was not found'); } else if (err.httpStatus) { err.message = err.message + ` (Status ${err.httpStatus})`; } diff --git a/src/Resend.js b/src/Resend.js index bf69e59c1a..f1e5fb38f5 100644 --- a/src/Resend.js +++ b/src/Resend.js @@ -21,11 +21,11 @@ import { EventStatus } from 'matrix-js-sdk/src/models/event'; export default class Resend { static resendUnsentEvents(room) { - room.getPendingEvents().filter(function(ev) { + return Promise.all(room.getPendingEvents().filter(function(ev) { return ev.status === EventStatus.NOT_SENT; - }).forEach(function(event) { - Resend.resend(event); - }); + }).map(function(event) { + return Resend.resend(event); + })); } static cancelUnsentEvents(room) { @@ -38,7 +38,7 @@ export default class Resend { static resend(event) { const room = MatrixClientPeg.get().getRoom(event.getRoomId()); - MatrixClientPeg.get().resendEvent(event, room).then(function(res) { + return MatrixClientPeg.get().resendEvent(event, room).then(function(res) { dis.dispatch({ action: 'message_sent', event: event, diff --git a/src/ScalarAuthClient.js b/src/ScalarAuthClient.ts similarity index 84% rename from src/ScalarAuthClient.js rename to src/ScalarAuthClient.ts index 200b4fd7b9..a09c3494a8 100644 --- a/src/ScalarAuthClient.js +++ b/src/ScalarAuthClient.ts @@ -1,6 +1,5 @@ /* -Copyright 2016 OpenMarket Ltd -Copyright 2019 The Matrix.org Foundation C.I.C. +Copyright 2016, 2019, 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. @@ -17,13 +16,14 @@ limitations under the License. import url from 'url'; import SettingsStore from "./settings/SettingsStore"; -import { Service, startTermsFlow, TermsNotSignedError } from './Terms'; +import { Service, startTermsFlow, TermsInteractionCallback, TermsNotSignedError } from './Terms'; import {MatrixClientPeg} from "./MatrixClientPeg"; import request from "browser-request"; import SdkConfig from "./SdkConfig"; import {WidgetType} from "./widgets/WidgetType"; import {SERVICE_TYPES} from "matrix-js-sdk/src/service-types"; +import { Room } from "matrix-js-sdk/src/models/room"; // The version of the integration manager API we're intending to work with const imApiVersion = "1.1"; @@ -31,9 +31,11 @@ const imApiVersion = "1.1"; // TODO: Generify the name of this class and all components within - it's not just for Scalar. export default class ScalarAuthClient { - constructor(apiUrl, uiUrl) { - this.apiUrl = apiUrl; - this.uiUrl = uiUrl; + private scalarToken: string; + private termsInteractionCallback: TermsInteractionCallback; + private isDefaultManager: boolean; + + constructor(private apiUrl: string, private uiUrl: string) { this.scalarToken = null; // `undefined` to allow `startTermsFlow` to fallback to a default // callback if this is unset. @@ -46,7 +48,7 @@ export default class ScalarAuthClient { this.isDefaultManager = apiUrl === configApiUrl && configUiUrl === uiUrl; } - _writeTokenToStore() { + private writeTokenToStore() { window.localStorage.setItem("mx_scalar_token_at_" + this.apiUrl, this.scalarToken); if (this.isDefaultManager) { // We remove the old token from storage to migrate upwards. This is safe @@ -56,7 +58,7 @@ export default class ScalarAuthClient { } } - _readTokenFromStore() { + private readTokenFromStore(): string { let token = window.localStorage.getItem("mx_scalar_token_at_" + this.apiUrl); if (!token && this.isDefaultManager) { token = window.localStorage.getItem("mx_scalar_token"); @@ -64,33 +66,33 @@ export default class ScalarAuthClient { return token; } - _readToken() { + private readToken(): string { if (this.scalarToken) return this.scalarToken; - return this._readTokenFromStore(); + return this.readTokenFromStore(); } setTermsInteractionCallback(callback) { this.termsInteractionCallback = callback; } - connect() { + connect(): Promise { return this.getScalarToken().then((tok) => { this.scalarToken = tok; }); } - hasCredentials() { + hasCredentials(): boolean { return this.scalarToken != null; // undef or null } // Returns a promise that resolves to a scalar_token string - getScalarToken() { - const token = this._readToken(); + getScalarToken(): Promise { + const token = this.readToken(); if (!token) { return this.registerForToken(); } else { - return this._checkToken(token).catch((e) => { + return this.checkToken(token).catch((e) => { if (e instanceof TermsNotSignedError) { // retrying won't help this throw e; @@ -100,7 +102,7 @@ export default class ScalarAuthClient { } } - _getAccountName(token) { + private getAccountName(token: string): Promise { const url = this.apiUrl + "/account"; return new Promise(function(resolve, reject) { @@ -125,8 +127,8 @@ export default class ScalarAuthClient { }); } - _checkToken(token) { - return this._getAccountName(token).then(userId => { + private checkToken(token: string): Promise { + return this.getAccountName(token).then(userId => { const me = MatrixClientPeg.get().getUserId(); if (userId !== me) { throw new Error("Scalar token is owned by someone else: " + me); @@ -154,7 +156,7 @@ export default class ScalarAuthClient { parsedImRestUrl.pathname = ''; return startTermsFlow([new Service( SERVICE_TYPES.IM, - parsedImRestUrl.format(), + url.format(parsedImRestUrl), token, )], this.termsInteractionCallback).then(() => { return token; @@ -165,22 +167,22 @@ export default class ScalarAuthClient { }); } - registerForToken() { + registerForToken(): Promise { // Get openid bearer token from the HS as the first part of our dance return MatrixClientPeg.get().getOpenIdToken().then((tokenObject) => { // Now we can send that to scalar and exchange it for a scalar token return this.exchangeForScalarToken(tokenObject); }).then((token) => { // Validate it (this mostly checks to see if the IM needs us to agree to some terms) - return this._checkToken(token); + return this.checkToken(token); }).then((token) => { this.scalarToken = token; - this._writeTokenToStore(); + this.writeTokenToStore(); return token; }); } - exchangeForScalarToken(openidTokenObject) { + exchangeForScalarToken(openidTokenObject: any): Promise { const scalarRestUrl = this.apiUrl; return new Promise(function(resolve, reject) { @@ -194,7 +196,7 @@ export default class ScalarAuthClient { if (err) { reject(err); } else if (response.statusCode / 100 !== 2) { - reject({statusCode: response.statusCode}); + reject(new Error(`Scalar request failed: ${response.statusCode}`)); } else if (!body || !body.scalar_token) { reject(new Error("Missing scalar_token in response")); } else { @@ -204,7 +206,7 @@ export default class ScalarAuthClient { }); } - getScalarPageTitle(url) { + getScalarPageTitle(url: string): Promise { let scalarPageLookupUrl = this.apiUrl + '/widgets/title_lookup'; scalarPageLookupUrl = this.getStarterLink(scalarPageLookupUrl); scalarPageLookupUrl += '&curl=' + encodeURIComponent(url); @@ -218,7 +220,7 @@ export default class ScalarAuthClient { if (err) { reject(err); } else if (response.statusCode / 100 !== 2) { - reject({statusCode: response.statusCode}); + reject(new Error(`Scalar request failed: ${response.statusCode}`)); } else if (!body) { reject(new Error("Missing page title in response")); } else { @@ -240,10 +242,10 @@ export default class ScalarAuthClient { * @param {string} widgetId The widget ID to disable assets for * @return {Promise} Resolves on completion */ - disableWidgetAssets(widgetType: WidgetType, widgetId) { + disableWidgetAssets(widgetType: WidgetType, widgetId: string): Promise { let url = this.apiUrl + '/widgets/set_assets_state'; url = this.getStarterLink(url); - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { request({ method: 'GET', // XXX: Actions shouldn't be GET requests uri: url, @@ -257,7 +259,7 @@ export default class ScalarAuthClient { if (err) { reject(err); } else if (response.statusCode / 100 !== 2) { - reject({statusCode: response.statusCode}); + reject(new Error(`Scalar request failed: ${response.statusCode}`)); } else if (!body) { reject(new Error("Failed to set widget assets state")); } else { @@ -267,7 +269,7 @@ export default class ScalarAuthClient { }); } - getScalarInterfaceUrlForRoom(room, screen, id) { + getScalarInterfaceUrlForRoom(room: Room, screen: string, id: string): string { const roomId = room.roomId; const roomName = room.name; let url = this.uiUrl; @@ -284,7 +286,7 @@ export default class ScalarAuthClient { return url; } - getStarterLink(starterLinkUrl) { + getStarterLink(starterLinkUrl: string): string { return starterLinkUrl + "?scalar_token=" + encodeURIComponent(this.scalarToken); } } diff --git a/src/SlashCommands.tsx b/src/SlashCommands.tsx index 6ce1439164..4a7b37b5e5 100644 --- a/src/SlashCommands.tsx +++ b/src/SlashCommands.tsx @@ -38,7 +38,7 @@ import {isPermalinkHost, parsePermalink} from "./utils/permalinks/Permalinks"; import {inviteUsersToRoom} from "./RoomInvite"; import { WidgetType } from "./widgets/WidgetType"; import { Jitsi } from "./widgets/Jitsi"; -import { parseFragment as parseHtml } from "parse5"; +import { parseFragment as parseHtml, Element as ChildElement } from "parse5"; import BugReportDialog from "./components/views/dialogs/BugReportDialog"; import { ensureDMExists } from "./createRoom"; import { ViewUserPayload } from "./dispatcher/payloads/ViewUserPayload"; @@ -856,7 +856,7 @@ export const Commands = [ // some superfast regex over the text so we don't have to. const embed = parseHtml(widgetUrl); if (embed && embed.childNodes && embed.childNodes.length === 1) { - const iframe = embed.childNodes[0]; + const iframe = embed.childNodes[0] as ChildElement; if (iframe.tagName.toLowerCase() === 'iframe' && iframe.attrs) { const srcAttr = iframe.attrs.find(a => a.name === 'src'); console.log("Pulling URL out of iframe (embed code)"); diff --git a/src/Terms.js b/src/Terms.ts similarity index 87% rename from src/Terms.js rename to src/Terms.ts index 6ae89f9a2c..1bdff36cbc 100644 --- a/src/Terms.js +++ b/src/Terms.ts @@ -1,5 +1,5 @@ /* -Copyright 2019 The Matrix.org Foundation C.I.C. +Copyright 2019, 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. @@ -17,7 +17,7 @@ limitations under the License. import classNames from 'classnames'; import {MatrixClientPeg} from './MatrixClientPeg'; -import * as sdk from './'; +import * as sdk from '.'; import Modal from './Modal'; export class TermsNotSignedError extends Error {} @@ -32,13 +32,30 @@ export class Service { * @param {string} baseUrl The Base URL of the service (ie. before '/_matrix') * @param {string} accessToken The user's access token for the service */ - constructor(serviceType, baseUrl, accessToken) { - this.serviceType = serviceType; - this.baseUrl = baseUrl; - this.accessToken = accessToken; + constructor(public serviceType: string, public baseUrl: string, public accessToken: string) { } } +interface Policy { + // @ts-ignore: No great way to express indexed types together with other keys + version: string; + [lang: string]: { + url: string; + }; +} +type Policies = { + [policy: string]: Policy, +}; + +export type TermsInteractionCallback = ( + policiesAndServicePairs: { + service: Service, + policies: Policies, + }[], + agreedUrls: string[], + extraClassNames?: string, +) => Promise; + /** * Start a flow where the user is presented with terms & conditions for some services * @@ -51,8 +68,8 @@ export class Service { * if they cancel. */ export async function startTermsFlow( - services, - interactionCallback = dialogTermsInteractionCallback, + services: Service[], + interactionCallback: TermsInteractionCallback = dialogTermsInteractionCallback, ) { const termsPromises = services.map( (s) => MatrixClientPeg.get().getTerms(s.serviceType, s.baseUrl), @@ -77,7 +94,7 @@ export async function startTermsFlow( * } */ - const terms = await Promise.all(termsPromises); + const terms: { policies: Policies }[] = await Promise.all(termsPromises); const policiesAndServicePairs = terms.map((t, i) => { return { 'service': services[i], 'policies': t.policies }; }); // fetch the set of agreed policy URLs from account data @@ -158,10 +175,13 @@ export async function startTermsFlow( } export function dialogTermsInteractionCallback( - policiesAndServicePairs, - agreedUrls, - extraClassNames, -) { + policiesAndServicePairs: { + service: Service, + policies: { [policy: string]: Policy }, + }[], + agreedUrls: string[], + extraClassNames?: string, +): Promise { return new Promise((resolve, reject) => { console.log("Terms that need agreement", policiesAndServicePairs); const TermsDialog = sdk.getComponent("views.dialogs.TermsDialog"); diff --git a/src/TextForEvent.js b/src/TextForEvent.js index a6787c647d..86f9ff20f4 100644 --- a/src/TextForEvent.js +++ b/src/TextForEvent.js @@ -547,17 +547,23 @@ function textForMjolnirEvent(event) { // else the entity !== prevEntity - count as a removal & add if (USER_RULE_TYPES.includes(event.getType())) { - return _t("%(senderName)s changed a rule that was banning users matching %(oldGlob)s to matching " + + return _t( + "%(senderName)s changed a rule that was banning users matching %(oldGlob)s to matching " + "%(newGlob)s for %(reason)s", - {senderName, oldGlob: prevEntity, newGlob: entity, reason}); + {senderName, oldGlob: prevEntity, newGlob: entity, reason}, + ); } else if (ROOM_RULE_TYPES.includes(event.getType())) { - return _t("%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching " + + return _t( + "%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching " + "%(newGlob)s for %(reason)s", - {senderName, oldGlob: prevEntity, newGlob: entity, reason}); + {senderName, oldGlob: prevEntity, newGlob: entity, reason}, + ); } else if (SERVER_RULE_TYPES.includes(event.getType())) { - return _t("%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching " + + return _t( + "%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching " + "%(newGlob)s for %(reason)s", - {senderName, oldGlob: prevEntity, newGlob: entity, reason}); + {senderName, oldGlob: prevEntity, newGlob: entity, reason}, + ); } // Unknown type. We'll say something but we shouldn't end up here. diff --git a/src/Unread.js b/src/Unread.js index ddf225ac64..12c15eb6af 100644 --- a/src/Unread.js +++ b/src/Unread.js @@ -45,7 +45,7 @@ export function eventTriggersUnreadCount(ev) { } export function doesRoomHaveUnreadMessages(room) { - const myUserId = MatrixClientPeg.get().credentials.userId; + const myUserId = MatrixClientPeg.get().getUserId(); // get the most recent read receipt sent by our account. // N.B. this is NOT a read marker (RM, aka "read up to marker"), diff --git a/src/VoipUserMapper.ts b/src/VoipUserMapper.ts index 4f5613b4a8..e5bed2e812 100644 --- a/src/VoipUserMapper.ts +++ b/src/VoipUserMapper.ts @@ -57,7 +57,11 @@ export default class VoipUserMapper { if (!virtualRoom) return null; const virtualRoomEvent = virtualRoom.getAccountData(VIRTUAL_ROOM_EVENT_TYPE); if (!virtualRoomEvent || !virtualRoomEvent.getContent()) return null; - return virtualRoomEvent.getContent()['native_room'] || null; + const nativeRoomID = virtualRoomEvent.getContent()['native_room']; + const nativeRoom = MatrixClientPeg.get().getRoom(nativeRoomID); + if (!nativeRoom || nativeRoom.getMyMembership() !== 'join') return null; + + return nativeRoomID; } public isVirtualRoom(room: Room): boolean { diff --git a/src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.js b/src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.tsx similarity index 90% rename from src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.js rename to src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.tsx index be3368b87b..0710c513da 100644 --- a/src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.js +++ b/src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.tsx @@ -1,5 +1,5 @@ /* -Copyright 2020 The Matrix.org Foundation C.I.C. +Copyright 2020-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. @@ -16,7 +16,6 @@ limitations under the License. import React from 'react'; import * as sdk from '../../../../index'; -import PropTypes from 'prop-types'; import { _t } from '../../../../languageHandler'; import SdkConfig from '../../../../SdkConfig'; import SettingsStore from "../../../../settings/SettingsStore"; @@ -26,14 +25,23 @@ import {formatBytes, formatCountLong} from "../../../../utils/FormattingUtils"; import EventIndexPeg from "../../../../indexing/EventIndexPeg"; import {SettingLevel} from "../../../../settings/SettingLevel"; +interface IProps { + onFinished: (confirmed: boolean) => void; +} + +interface IState { + eventIndexSize: number; + eventCount: number; + crawlingRoomsCount: number; + roomCount: number; + currentRoom: string; + crawlerSleepTime: number; +} + /* * Allows the user to introspect the event index state and disable it. */ -export default class ManageEventIndexDialog extends React.Component { - static propTypes = { - onFinished: PropTypes.func.isRequired, - }; - +export default class ManageEventIndexDialog extends React.Component { constructor(props) { super(props); @@ -84,7 +92,7 @@ export default class ManageEventIndexDialog extends React.Component { } } - async componentDidMount(): void { + async componentDidMount(): Promise { let eventIndexSize = 0; let crawlingRoomsCount = 0; let roomCount = 0; @@ -123,14 +131,14 @@ export default class ManageEventIndexDialog extends React.Component { }); } - _onDisable = async () => { + private onDisable = async () => { Modal.createTrackedDialogAsync("Disable message search", "Disable message search", import("./DisableEventIndexDialog"), null, null, /* priority = */ false, /* static = */ true, ); }; - _onCrawlerSleepTimeChange = (e) => { + private onCrawlerSleepTimeChange = (e) => { this.setState({crawlerSleepTime: e.target.value}); SettingsStore.setValue("crawlerSleepTime", null, SettingLevel.DEVICE, e.target.value); }; @@ -144,7 +152,7 @@ export default class ManageEventIndexDialog extends React.Component { crawlerState = _t("Not currently indexing messages for any room."); } else { crawlerState = ( - _t("Currently indexing: %(currentRoom)s", { currentRoom: this.state.currentRoom }) + _t("Currently indexing: %(currentRoom)s", { currentRoom: this.state.currentRoom }) ); } @@ -169,7 +177,7 @@ export default class ManageEventIndexDialog extends React.Component { label={_t('Message downloading sleep time(ms)')} type='number' value={this.state.crawlerSleepTime} - onChange={this._onCrawlerSleepTimeChange} /> + onChange={this.onCrawlerSleepTimeChange} />
    ); @@ -188,7 +196,7 @@ export default class ManageEventIndexDialog extends React.Component { onPrimaryButtonClick={this.props.onFinished} primaryButtonClass="primary" cancelButton={_t("Disable")} - onCancel={this._onDisable} + onCancel={this.onDisable} cancelButtonClass="danger" /> diff --git a/src/async-components/views/dialogs/security/CreateKeyBackupDialog.js b/src/async-components/views/dialogs/security/CreateKeyBackupDialog.js index 863ee2b427..549494b5cb 100644 --- a/src/async-components/views/dialogs/security/CreateKeyBackupDialog.js +++ b/src/async-components/views/dialogs/security/CreateKeyBackupDialog.js @@ -310,7 +310,7 @@ export default class CreateKeyBackupDialog extends React.PureComponent { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); return

    {_t( - "Please enter your Security Phrase a second time to confirm.", + "Enter your Security Phrase a second time to confirm it.", )}

    @@ -498,9 +498,9 @@ export default class CreateKeyBackupDialog extends React.PureComponent { title={this._titleForPhase(this.state.phase)} hasCancel={[PHASE_PASSPHRASE, PHASE_DONE].includes(this.state.phase)} > -
    - {content} -
    +
    + {content} +
    ); } diff --git a/src/async-components/views/dialogs/security/CreateSecretStorageDialog.js b/src/async-components/views/dialogs/security/CreateSecretStorageDialog.js index 84cb58536a..6d5703a768 100644 --- a/src/async-components/views/dialogs/security/CreateSecretStorageDialog.js +++ b/src/async-components/views/dialogs/security/CreateSecretStorageDialog.js @@ -647,7 +647,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent { } return

    {_t( - "Enter your recovery passphrase a second time to confirm it.", + "Enter your Security Phrase a second time to confirm it.", )}

    @@ -856,9 +856,9 @@ export default class CreateSecretStorageDialog extends React.PureComponent { hasCancel={this.props.hasCancel && [PHASE_PASSPHRASE].includes(this.state.phase)} fixedWidth={false} > -
    - {content} -
    +
    + {content} +
    ); } diff --git a/src/async-components/views/dialogs/security/ExportE2eKeysDialog.js b/src/async-components/views/dialogs/security/ExportE2eKeysDialog.js index eeb68b94bd..60f2ca9168 100644 --- a/src/async-components/views/dialogs/security/ExportE2eKeysDialog.js +++ b/src/async-components/views/dialogs/security/ExportE2eKeysDialog.js @@ -170,8 +170,11 @@ export default class ExportE2eKeysDialog extends React.Component {
    -
    -
    - -
    -
    - -
    +
    + +
    +
    + +
    -
    - -
    -
    - -
    +
    + +
    +
    + +
    diff --git a/src/components/structures/FilePanel.js b/src/components/structures/FilePanel.js index 32db5c251c..d5e4b092e2 100644 --- a/src/components/structures/FilePanel.js +++ b/src/components/structures/FilePanel.js @@ -200,10 +200,10 @@ class FilePanel extends React.Component { previousPhase={RightPanelPhases.RoomSummary} >
    - { _t("You must register to use this functionality", - {}, - { 'a': (sub) => { sub } }) - } + { _t("You must register to use this functionality", + {}, + { 'a': (sub) => { sub } }) + }
    ; } else if (this.noRoom) { diff --git a/src/components/structures/GroupFilterPanel.js b/src/components/structures/GroupFilterPanel.js index 976b2d81a5..7c050e7433 100644 --- a/src/components/structures/GroupFilterPanel.js +++ b/src/components/structures/GroupFilterPanel.js @@ -153,17 +153,17 @@ class GroupFilterPanel extends React.Component { type="draggable-TagTile" > { (provided, snapshot) => ( -
    - { this.renderGlobalIcon() } - { tags } -
    - {createButton} -
    - { provided.placeholder } +
    + { this.renderGlobalIcon() } + { tags } +
    + {createButton}
    + { provided.placeholder } +
    ) } diff --git a/src/components/structures/GroupView.js b/src/components/structures/GroupView.js index ed6167cbe7..3ab009d7b8 100644 --- a/src/components/structures/GroupView.js +++ b/src/components/structures/GroupView.js @@ -43,7 +43,7 @@ import {mediaFromMxc} from "../../customisations/Media"; import {replaceableComponent} from "../../utils/replaceableComponent"; const LONG_DESC_PLACEHOLDER = _td( -`

    HTML for your community's page

    + `

    HTML for your community's page

    Use the long description to introduce new members to the community, or distribute some important links @@ -110,14 +110,16 @@ class CategoryRoomList extends React.Component { const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); Modal.createTrackedDialog( 'Failed to add the following room to the group summary', - '', ErrorDialog, - { - title: _t( - "Failed to add the following rooms to the summary of %(groupId)s:", - {groupId: this.props.groupId}, - ), - description: errorList.join(", "), - }); + '', + ErrorDialog, + { + title: _t( + "Failed to add the following rooms to the summary of %(groupId)s:", + {groupId: this.props.groupId}, + ), + description: errorList.join(", "), + }, + ); }); }, }, /*className=*/null, /*isPriority=*/false, /*isStatic=*/true); @@ -146,8 +148,8 @@ class CategoryRoomList extends React.Component { let catHeader =

    ; if (this.props.category && this.props.category.profile) { catHeader =
    - { this.props.category.profile.name } -
    ; + { this.props.category.profile.name } +
    ; } return
    { catHeader } @@ -190,13 +192,14 @@ class FeaturedRoom extends React.Component { Modal.createTrackedDialog( 'Failed to remove room from group summary', '', ErrorDialog, - { - title: _t( - "Failed to remove the room from the summary of %(groupId)s", - {groupId: this.props.groupId}, - ), - description: _t("The room '%(roomName)s' could not be removed from the summary.", {roomName}), - }); + { + title: _t( + "Failed to remove the room from the summary of %(groupId)s", + {groupId: this.props.groupId}, + ), + description: _t("The room '%(roomName)s' could not be removed from the summary.", {roomName}), + }, + ); }); }; @@ -283,13 +286,14 @@ class RoleUserList extends React.Component { Modal.createTrackedDialog( 'Failed to add the following users to the community summary', '', ErrorDialog, - { - title: _t( - "Failed to add the following users to the summary of %(groupId)s:", - {groupId: this.props.groupId}, - ), - description: errorList.join(", "), - }); + { + title: _t( + "Failed to add the following users to the summary of %(groupId)s:", + {groupId: this.props.groupId}, + ), + description: errorList.join(", "), + }, + ); }); }, }, /*className=*/null, /*isPriority=*/false, /*isStatic=*/true); @@ -299,11 +303,11 @@ class RoleUserList extends React.Component { const TintableSvg = sdk.getComponent("elements.TintableSvg"); const addButton = this.props.editing ? ( - -
    - { _t('Add a User') } -
    -
    ) :
    ; + +
    + { _t('Add a User') } +
    + ) :
    ; const userNodes = this.props.users.map((u) => { return - { _t("Leave %(groupName)s?", {groupName: this.props.groupId}) } - { warnings } + { _t("Leave %(groupName)s?", {groupName: this.props.groupId}) } + { warnings } ), button: _t("Leave"), @@ -1055,10 +1061,11 @@ export default class GroupView extends React.Component { return null; } - const membershipButtonClasses = classnames([ - 'mx_RoomHeader_textButton', - 'mx_GroupView_textButton', - ], + const membershipButtonClasses = classnames( + [ + 'mx_RoomHeader_textButton', + 'mx_GroupView_textButton', + ], membershipButtonExtraClasses, ); diff --git a/src/components/structures/LeftPanel.tsx b/src/components/structures/LeftPanel.tsx index e4762e35ad..7f9ef7516e 100644 --- a/src/components/structures/LeftPanel.tsx +++ b/src/components/structures/LeftPanel.tsx @@ -347,7 +347,7 @@ export default class LeftPanel extends React.Component { if (element) { classes = element.classList; } - } while (element && !cssClasses.some(c => classes.contains(c))); + } while (element && (!cssClasses.some(c => classes.contains(c)) || element.offsetParent === null)); if (element) { element.focus(); @@ -416,7 +416,7 @@ export default class LeftPanel extends React.Component { const roomList = ; } /** @@ -160,6 +164,7 @@ class LoggedInView extends React.Component { // use compact timeline view useCompactLayout: SettingsStore.getValue('useCompactLayout'), usageLimitDismissed: false, + activeCalls: [], }; // stash the MatrixClient in case we log out before we are unmounted @@ -175,6 +180,7 @@ class LoggedInView extends React.Component { componentDidMount() { document.addEventListener('keydown', this._onNativeKeyDown, false); + CallHandler.sharedInstance().addListener(CallHandlerEvent.CallsChanged, this.onCallsChanged); this._updateServerNoticeEvents(); @@ -199,6 +205,7 @@ class LoggedInView extends React.Component { componentWillUnmount() { document.removeEventListener('keydown', this._onNativeKeyDown, false); + CallHandler.sharedInstance().removeListener(CallHandlerEvent.CallsChanged, this.onCallsChanged); this._matrixClient.removeListener("accountData", this.onAccountData); this._matrixClient.removeListener("sync", this.onSync); this._matrixClient.removeListener("RoomState.events", this.onRoomStateEvents); @@ -206,6 +213,12 @@ class LoggedInView extends React.Component { this.resizer.detach(); } + private onCallsChanged = () => { + this.setState({ + activeCalls: CallHandler.sharedInstance().getAllActiveCalls(), + }); + }; + // Child components assume that the client peg will not be null, so give them some // sort of assurance here by only allowing a re-render if the client is truthy. // @@ -661,6 +674,12 @@ class LoggedInView extends React.Component { bodyClasses += ' mx_MatrixChat_useCompactLayout'; } + const audioFeedArraysForCalls = this.state.activeCalls.map((call) => { + return ( + + ); + }); + return (
    { + {audioFeedArraysForCalls} ); } diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index 078b296295..e330dc7d38 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -1094,7 +1094,7 @@ export default class MatrixChat extends React.PureComponent { private leaveRoomWarnings(roomId: string) { const roomToLeave = MatrixClientPeg.get().getRoom(roomId); - const isSpace = roomToLeave?.isSpaceRoom(); + const isSpace = SettingsStore.getValue("feature_spaces") && roomToLeave?.isSpaceRoom(); // Show a warning if there are additional complications. const warnings = []; @@ -1133,7 +1133,7 @@ export default class MatrixChat extends React.PureComponent { const roomToLeave = MatrixClientPeg.get().getRoom(roomId); const warnings = this.leaveRoomWarnings(roomId); - const isSpace = roomToLeave?.isSpaceRoom(); + const isSpace = SettingsStore.getValue("feature_spaces") && roomToLeave?.isSpaceRoom(); Modal.createTrackedDialog(isSpace ? "Leave space" : "Leave room", '', QuestionDialog, { title: isSpace ? _t("Leave space") : _t("Leave room"), description: ( diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index 132d9ab4c3..c93f07fa0f 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -427,8 +427,10 @@ export default class MessagePanel extends React.Component { // we get a new DOM node (restarting the animation) when the ghost // moves to a different event. return ( -
  • +
  • { hr }
  • ); @@ -1014,13 +1016,13 @@ class CreationGrouper { ret.push( - { eventTiles } + { eventTiles } , ); @@ -1222,11 +1224,11 @@ class MemberGrouper { ret.push( - { eventTiles } + { eventTiles } , ); diff --git a/src/components/structures/RightPanel.js b/src/components/structures/RightPanel.js index 5bcb3b2450..d8c763eabd 100644 --- a/src/components/structures/RightPanel.js +++ b/src/components/structures/RightPanel.js @@ -35,6 +35,7 @@ import {Action} from "../../dispatcher/actions"; import RoomSummaryCard from "../views/right_panel/RoomSummaryCard"; import WidgetCard from "../views/right_panel/WidgetCard"; import {replaceableComponent} from "../../utils/replaceableComponent"; +import SettingsStore from "../../settings/SettingsStore"; @replaceableComponent("structures.RightPanel") export default class RightPanel extends React.Component { @@ -85,7 +86,9 @@ export default class RightPanel extends React.Component { return RightPanelPhases.GroupMemberList; } return rps.groupPanelPhase; - } else if (this.props.room?.isSpaceRoom() && !RIGHT_PANEL_SPACE_PHASES.includes(rps.roomPanelPhase)) { + } else if (SettingsStore.getValue("feature_spaces") && this.props.room?.isSpaceRoom() + && !RIGHT_PANEL_SPACE_PHASES.includes(rps.roomPanelPhase) + ) { return RightPanelPhases.SpaceMemberList; } else if (userForPanel) { // XXX FIXME AAAAAARGH: What is going on with this class!? It takes some of its state diff --git a/src/components/structures/RoomSearch.tsx b/src/components/structures/RoomSearch.tsx index a64feed42c..34682877e0 100644 --- a/src/components/structures/RoomSearch.tsx +++ b/src/components/structures/RoomSearch.tsx @@ -17,6 +17,8 @@ limitations under the License. import * as React from "react"; import { createRef } from "react"; import classNames from "classnames"; +import { Room } from "matrix-js-sdk/src/models/room"; + import defaultDispatcher from "../../dispatcher/dispatcher"; import { _t } from "../../languageHandler"; import { ActionPayload } from "../../dispatcher/payloads"; @@ -26,7 +28,7 @@ import RoomListStore from "../../stores/room-list/RoomListStore"; import { NameFilterCondition } from "../../stores/room-list/filters/NameFilterCondition"; import { getKeyBindingsManager, RoomListAction } from "../../KeyBindingsManager"; import {replaceableComponent} from "../../utils/replaceableComponent"; -import SpaceStore, {UPDATE_SELECTED_SPACE} from "../../stores/SpaceStore"; +import SpaceStore, {UPDATE_SELECTED_SPACE, UPDATE_TOP_LEVEL_SPACES} from "../../stores/SpaceStore"; interface IProps { isMinimized: boolean; @@ -40,6 +42,7 @@ interface IProps { interface IState { query: string; focused: boolean; + inSpaces: boolean; } @replaceableComponent("structures.RoomSearch") @@ -54,11 +57,13 @@ export default class RoomSearch extends React.PureComponent { this.state = { query: "", focused: false, + inSpaces: false, }; this.dispatcherRef = defaultDispatcher.register(this.onAction); // clear filter when changing spaces, in future we may wish to maintain a filter per-space SpaceStore.instance.on(UPDATE_SELECTED_SPACE, this.clearInput); + SpaceStore.instance.on(UPDATE_TOP_LEVEL_SPACES, this.onSpaces); } public componentDidUpdate(prevProps: Readonly, prevState: Readonly): void { @@ -79,8 +84,15 @@ export default class RoomSearch extends React.PureComponent { public componentWillUnmount() { defaultDispatcher.unregister(this.dispatcherRef); SpaceStore.instance.off(UPDATE_SELECTED_SPACE, this.clearInput); + SpaceStore.instance.off(UPDATE_TOP_LEVEL_SPACES, this.onSpaces); } + private onSpaces = (spaces: Room[]) => { + this.setState({ + inSpaces: spaces.length > 0, + }); + }; + private onAction = (payload: ActionPayload) => { if (payload.action === 'view_room' && payload.clear_search) { this.clearInput(); @@ -152,6 +164,11 @@ export default class RoomSearch extends React.PureComponent { 'mx_RoomSearch_inputExpanded': this.state.query || this.state.focused, }); + let placeholder = _t("Filter"); + if (this.state.inSpaces) { + placeholder = _t("Filter all spaces"); + } + let icon = (
    ); @@ -165,7 +182,7 @@ export default class RoomSearch extends React.PureComponent { onBlur={this.onBlur} onChange={this.onChange} onKeyDown={this.onKeyDown} - placeholder={_t("Filter")} + placeholder={placeholder} autoComplete="off" /> ); diff --git a/src/components/structures/RoomStatusBar.js b/src/components/structures/RoomStatusBar.js index 54b6fee233..b2f0c70bd7 100644 --- a/src/components/structures/RoomStatusBar.js +++ b/src/components/structures/RoomStatusBar.js @@ -1,5 +1,5 @@ /* -Copyright 2015-2020 The Matrix.org Foundation C.I.C. +Copyright 2015-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. @@ -20,16 +20,20 @@ import { _t, _td } from '../../languageHandler'; import {MatrixClientPeg} from '../../MatrixClientPeg'; import Resend from '../../Resend'; import dis from '../../dispatcher/dispatcher'; -import {messageForResourceLimitError, messageForSendError} from '../../utils/ErrorUtils'; +import {messageForResourceLimitError} from '../../utils/ErrorUtils'; import {Action} from "../../dispatcher/actions"; import {replaceableComponent} from "../../utils/replaceableComponent"; import {EventStatus} from "matrix-js-sdk/src/models/event"; +import NotificationBadge from "../views/rooms/NotificationBadge"; +import {StaticNotificationState} from "../../stores/notifications/StaticNotificationState"; +import AccessibleButton from "../views/elements/AccessibleButton"; +import InlineSpinner from "../views/elements/InlineSpinner"; const STATUS_BAR_HIDDEN = 0; const STATUS_BAR_EXPANDED = 1; const STATUS_BAR_EXPANDED_LARGE = 2; -function getUnsentMessages(room) { +export function getUnsentMessages(room) { if (!room) { return []; } return room.getPendingEvents().filter(function(ev) { return ev.status === EventStatus.NOT_SENT; @@ -76,6 +80,7 @@ export default class RoomStatusBar extends React.Component { syncState: MatrixClientPeg.get().getSyncState(), syncStateData: MatrixClientPeg.get().getSyncStateData(), unsentMessages: getUnsentMessages(this.props.room), + isResending: false, }; componentDidMount() { @@ -109,7 +114,10 @@ export default class RoomStatusBar extends React.Component { }; _onResendAllClick = () => { - Resend.resendUnsentEvents(this.props.room); + Resend.resendUnsentEvents(this.props.room).then(() => { + this.setState({isResending: false}); + }); + this.setState({isResending: true}); dis.fire(Action.FocusComposer); }; @@ -120,9 +128,10 @@ export default class RoomStatusBar extends React.Component { _onRoomLocalEchoUpdated = (event, room, oldEventId, oldStatus) => { if (room.roomId !== this.props.room.roomId) return; - + const messages = getUnsentMessages(this.props.room); this.setState({ - unsentMessages: getUnsentMessages(this.props.room), + unsentMessages: messages, + isResending: messages.length > 0 && this.state.isResending, }); }; @@ -141,7 +150,7 @@ export default class RoomStatusBar extends React.Component { _getSize() { if (this._shouldShowConnectionError()) { return STATUS_BAR_EXPANDED; - } else if (this.state.unsentMessages.length > 0) { + } else if (this.state.unsentMessages.length > 0 || this.state.isResending) { return STATUS_BAR_EXPANDED_LARGE; } return STATUS_BAR_HIDDEN; @@ -162,7 +171,6 @@ export default class RoomStatusBar extends React.Component { _getUnsentMessageContent() { const unsentMessages = this.state.unsentMessages; - if (!unsentMessages.length) return null; let title; @@ -192,89 +200,92 @@ export default class RoomStatusBar extends React.Component { } else if (resourceLimitError) { title = messageForResourceLimitError( resourceLimitError.data.limit_type, - resourceLimitError.data.admin_contact, { - 'monthly_active_user': _td( - "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.", - ), - }); - } else if ( - unsentMessages.length === 1 && - unsentMessages[0].error && - unsentMessages[0].error.data && - unsentMessages[0].error.data.error - ) { - title = messageForSendError(unsentMessages[0].error.data) || unsentMessages[0].error.data.error; + resourceLimitError.data.admin_contact, + { + 'monthly_active_user': _td( + "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.", + ), + }, + ); } else { - title = _t('%(count)s of your messages have not been sent.', { count: unsentMessages.length }); + title = _t('Some of your messages have not been sent'); } - const content = _t("%(count)s Resend all or cancel all " + - "now. You can also select individual messages to resend or cancel.", - { count: unsentMessages.length }, - { - 'resendText': (sub) => - { sub }, - 'cancelText': (sub) => - { sub }, - }, - ); + let buttonRow = <> + + {_t("Delete all")} + + + {_t("Retry all")} + + ; + if (this.state.isResending) { + buttonRow = <> + + {/* span for css */} + {_t("Sending")} + ; + } - return
    - -
    -
    - { title } -
    -
    - { content } + return <> +
    +
    +
    + +
    +
    +
    + { title } +
    +
    + { _t("You can select all or individual messages to retry or delete") } +
    +
    +
    + {buttonRow} +
    -
    ; + ; } - // return suitable content for the main (text) part of the status bar. - _getContent() { + render() { if (this._shouldShowConnectionError()) { return ( -
    - /!\ -
    -
    - { _t('Connectivity to the server has been lost.') } -
    -
    - { _t('Sent messages will be stored until your connection has returned.') } +
    +
    +
    + /!\ +
    +
    + {_t('Connectivity to the server has been lost.')} +
    +
    + {_t('Sent messages will be stored until your connection has returned.')} +
    +
    ); } - if (this.state.unsentMessages.length > 0) { + if (this.state.unsentMessages.length > 0 || this.state.isResending) { return this._getUnsentMessageContent(); } return null; } - - render() { - const content = this._getContent(); - - return ( -
    -
    - { content } -
    -
    - ); - } } diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index 7168b7d139..58a87e6641 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -190,6 +190,9 @@ export interface IState { rejectError?: Error; hasPinnedWidgets?: boolean; dragCounter: number; + // whether or not a spaces context switch brought us here, + // if it did we don't want the room to be marked as read as soon as it is loaded. + wasContextSwitch?: boolean; } @replaceableComponent("structures.RoomView") @@ -326,6 +329,7 @@ export default class RoomView extends React.Component { shouldPeek: this.state.matrixClientIsReady && RoomViewStore.shouldPeek(), showingPinned: SettingsStore.getValue("PinnedEvents.isOpen", roomId), showReadReceipts: SettingsStore.getValue("showReadReceipts", roomId), + wasContextSwitch: RoomViewStore.getWasContextSwitch(), }; if (!initial && this.state.shouldPeek && !newState.shouldPeek) { @@ -1746,7 +1750,10 @@ export default class RoomView extends React.Component { } const myMembership = this.state.room.getMyMembership(); - if (myMembership === "invite" && !this.state.room.isSpaceRoom()) { // SpaceRoomView handles invites itself + if (myMembership === "invite" + // SpaceRoomView handles invites itself + && (!SettingsStore.getValue("feature_spaces") || !this.state.room.isSpaceRoom()) + ) { if (this.state.joining || this.state.rejecting) { return ( @@ -1888,7 +1895,7 @@ export default class RoomView extends React.Component { room={this.state.room} /> ); - if (!this.state.canPeek && !this.state.room?.isSpaceRoom()) { + if (!this.state.canPeek && (!SettingsStore.getValue("feature_spaces") || !this.state.room?.isSpaceRoom())) { return (
    { previewBar } @@ -2014,6 +2021,7 @@ export default class RoomView extends React.Component { timelineSet={this.state.room.getUnfilteredTimelineSet()} showReadReceipts={this.state.showReadReceipts} manageReadReceipts={!this.state.isPeeking} + sendReadReceiptOnLoad={!this.state.wasContextSwitch} manageReadMarkers={!this.state.isPeeking} hidden={hideMessagePanel} highlightedEventId={highlightedEventId} diff --git a/src/components/structures/ScrollPanel.js b/src/components/structures/ScrollPanel.js index 976734680c..5c5062633d 100644 --- a/src/components/structures/ScrollPanel.js +++ b/src/components/structures/ScrollPanel.js @@ -525,7 +525,7 @@ export default class ScrollPanel extends React.Component { */ scrollRelative = mult => { const scrollNode = this._getScrollNode(); - const delta = mult * scrollNode.clientHeight * 0.5; + const delta = mult * scrollNode.clientHeight * 0.9; scrollNode.scrollBy(0, delta); this._saveScrollState(); }; @@ -884,16 +884,20 @@ export default class ScrollPanel extends React.Component { // give the
      an explicit role=list because Safari+VoiceOver seems to think an ordered-list with // list-style-type: none; is no longer a list - return ( - { this.props.fixedChildren } -
      -
        - { this.props.children } -
      -
      -
      - ); + className={`mx_ScrollPanel ${this.props.className}`} + style={this.props.style} + > + { this.props.fixedChildren } +
      +
        + { this.props.children } +
      +
      + + ); } } diff --git a/src/components/structures/SpaceRoomDirectory.tsx b/src/components/structures/SpaceRoomDirectory.tsx index 930cfa15a9..74415cc58f 100644 --- a/src/components/structures/SpaceRoomDirectory.tsx +++ b/src/components/structures/SpaceRoomDirectory.tsx @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {useMemo, useState} from "react"; +import React, {ReactNode, useMemo, useState} from "react"; import {Room} from "matrix-js-sdk/src/models/room"; import {MatrixClient} from "matrix-js-sdk/src/client"; import {EventType, RoomType} from "matrix-js-sdk/src/@types/event"; @@ -24,7 +24,7 @@ import {sortBy} from "lodash"; import {MatrixClientPeg} from "../../MatrixClientPeg"; import dis from "../../dispatcher/dispatcher"; import {_t} from "../../languageHandler"; -import AccessibleButton from "../views/elements/AccessibleButton"; +import AccessibleButton, {ButtonEvent} from "../views/elements/AccessibleButton"; import BaseDialog from "../views/dialogs/BaseDialog"; import Spinner from "../views/elements/Spinner"; import SearchBox from "./SearchBox"; @@ -39,11 +39,14 @@ import {mediaFromMxc} from "../../customisations/Media"; import InfoTooltip from "../views/elements/InfoTooltip"; import TextWithTooltip from "../views/elements/TextWithTooltip"; import {useStateToggle} from "../../hooks/useStateToggle"; +import {getOrder} from "../../stores/SpaceStore"; +import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton"; interface IHierarchyProps { space: Room; initialText?: string; refreshToken?: any; + additionalButtons?: ReactNode; showRoom(room: ISpaceSummaryRoom, viaServers?: string[], autoJoin?: boolean): void; } @@ -106,8 +109,16 @@ const Tile: React.FC = ({ const cliRoom = cli.getRoom(room.room_id); const myMembership = cliRoom?.getMyMembership(); - const onPreviewClick = () => onViewRoomClick(false); - const onJoinClick = () => onViewRoomClick(true); + const onPreviewClick = (ev: ButtonEvent) => { + ev.preventDefault(); + ev.stopPropagation(); + onViewRoomClick(false); + } + const onJoinClick = (ev: ButtonEvent) => { + ev.preventDefault(); + ev.stopPropagation(); + onViewRoomClick(true); + } let button; if (myMembership === "join") { @@ -136,7 +147,7 @@ const Tile: React.FC = ({ let url: string; if (room.avatar_url) { - url = mediaFromMxc(room.avatar_url).getSquareThumbnailHttp(Math.floor(20 * window.devicePixelRatio)); + url = mediaFromMxc(room.avatar_url).getSquareThumbnailHttp(20); } let description = _t("%(count)s members", { count: room.num_joined_members }); @@ -254,7 +265,11 @@ export const HierarchyLevel = ({ const space = cli.getRoom(spaceId); const hasPermissions = space?.currentState.maySendStateEvent(EventType.SpaceChild, cli.getUserId()); - const sortedChildren = sortBy([...(relations.get(spaceId)?.values() || [])], ev => ev.content.order || null); + const children = Array.from(relations.get(spaceId)?.values() || []); + const sortedChildren = sortBy(children, ev => { + // XXX: Space Summary API doesn't give the child origin_server_ts but once it does we should use it for sorting + return getOrder(ev.content.order, null, ev.state_key); + }); const [subspaces, childRooms] = sortedChildren.reduce((result, ev: ISpaceSummaryEvent) => { const roomId = ev.state_key; if (!rooms.has(roomId)) return result; @@ -312,11 +327,12 @@ export const HierarchyLevel = ({ // mutate argument refreshToken to force a reload export const useSpaceSummary = (cli: MatrixClient, space: Room, refreshToken?: any): [ + null, ISpaceSummaryRoom[], - Map>, - Map>, - Map>, -] | [] => { + Map>?, + Map>?, + Map>?, +] | [Error] => { // TODO pagination return useAsyncMemo(async () => { try { @@ -336,13 +352,12 @@ export const useSpaceSummary = (cli: MatrixClient, space: Room, refreshToken?: a } }); - return [data.rooms as ISpaceSummaryRoom[], parentChildRelations, viaMap, childParentRelations]; + return [null, data.rooms as ISpaceSummaryRoom[], parentChildRelations, viaMap, childParentRelations]; } catch (e) { console.error(e); // TODO + return [e]; } - - return []; - }, [space, refreshToken], []); + }, [space, refreshToken], [undefined]); }; export const SpaceHierarchy: React.FC = ({ @@ -350,6 +365,7 @@ export const SpaceHierarchy: React.FC = ({ initialText = "", showRoom, refreshToken, + additionalButtons, children, }) => { const cli = MatrixClientPeg.get(); @@ -358,7 +374,7 @@ export const SpaceHierarchy: React.FC = ({ const [selected, setSelected] = useState(new Map>()); // Map> - const [rooms, parentChildMap, viaMap, childParentMap] = useSpaceSummary(cli, space, refreshToken); + const [summaryError, rooms, parentChildMap, viaMap, childParentMap] = useSpaceSummary(cli, space, refreshToken); const roomsMap = useMemo(() => { if (!rooms) return null; @@ -397,6 +413,10 @@ export const SpaceHierarchy: React.FC = ({ const [removing, setRemoving] = useState(false); const [saving, setSaving] = useState(false); + if (summaryError) { + return

      {_t("Your server does not support showing space hierarchies.")}

      ; + } + let content; if (roomsMap) { const numRooms = Array.from(roomsMap.values()).filter(r => r.room_type !== RoomType.Space).length; @@ -411,78 +431,83 @@ export const SpaceHierarchy: React.FC = ({ countsStr = _t("%(count)s rooms", { count: numRooms, numSpaces }); } - let editSection; + let manageButtons; if (space.getMyMembership() === "join" && space.currentState.maySendStateEvent(EventType.SpaceChild, userId)) { const selectedRelations = Array.from(selected.keys()).flatMap(parentId => { return [...selected.get(parentId).values()].map(childId => [parentId, childId]) as [string, string][]; }); - let buttons; - if (selectedRelations.length) { - const selectionAllSuggested = selectedRelations.every(([parentId, childId]) => { - return parentChildMap.get(parentId)?.get(childId)?.content.suggested; - }); + const selectionAllSuggested = selectedRelations.every(([parentId, childId]) => { + return parentChildMap.get(parentId)?.get(childId)?.content.suggested; + }); - const disabled = removing || saving; + const disabled = !selectedRelations.length || removing || saving; - buttons = <> - { - setRemoving(true); - try { - for (const [parentId, childId] of selectedRelations) { - await cli.sendStateEvent(parentId, EventType.SpaceChild, {}, childId); - parentChildMap.get(parentId).get(childId).content = {}; - parentChildMap.set(parentId, new Map(parentChildMap.get(parentId))); - } - } catch (e) { - setError(_t("Failed to remove some rooms. Try again later")); - } - setRemoving(false); - }} - kind="danger_outline" - disabled={disabled} - > - { removing ? _t("Removing...") : _t("Remove") } - - { - setSaving(true); - try { - for (const [parentId, childId] of selectedRelations) { - const suggested = !selectionAllSuggested; - const existingContent = parentChildMap.get(parentId)?.get(childId)?.content; - if (!existingContent || existingContent.suggested === suggested) continue; - - const content = { - ...existingContent, - suggested: !selectionAllSuggested, - }; - - await cli.sendStateEvent(parentId, EventType.SpaceChild, content, childId); - - parentChildMap.get(parentId).get(childId).content = content; - parentChildMap.set(parentId, new Map(parentChildMap.get(parentId))); - } - } catch (e) { - setError("Failed to update some suggestions. Try again later"); - } - setSaving(false); - }} - kind="primary_outline" - disabled={disabled} - > - { saving - ? _t("Saving...") - : (selectionAllSuggested ? _t("Mark as not suggested") : _t("Mark as suggested")) - } - - ; + let Button: React.ComponentType> = AccessibleButton; + let props = {}; + if (!selectedRelations.length) { + Button = AccessibleTooltipButton; + props = { + tooltip: _t("Select a room below first"), + yOffset: -40, + }; } - editSection = - { buttons } - ; + manageButtons = <> + + + ; } let results; @@ -528,7 +553,10 @@ export const SpaceHierarchy: React.FC = ({ content = <>
      { countsStr } - { editSection } + + { additionalButtons } + { manageButtons } +
      { error &&
      { error } @@ -538,10 +566,8 @@ export const SpaceHierarchy: React.FC = ({ { children } ; - } else if (!rooms) { - content = ; } else { - content =

      {_t("Your server does not support showing space hierarchies.")}

      ; + content = ; } // TODO loading state/error state diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx index 31358a3731..5db54815b7 100644 --- a/src/components/structures/SpaceRoomView.tsx +++ b/src/components/structures/SpaceRoomView.tsx @@ -51,6 +51,15 @@ import MemberAvatar from "../views/avatars/MemberAvatar"; import {useStateToggle} from "../../hooks/useStateToggle"; import SpaceStore from "../../stores/SpaceStore"; import FacePile from "../views/elements/FacePile"; +import {AddExistingToSpace} from "../views/dialogs/AddExistingToSpaceDialog"; +import {sleep} from "../../utils/promise"; +import {calculateRoomVia} from "../../utils/permalinks/Permalinks"; +import {ChevronFace, ContextMenuButton, useContextMenu} from "./ContextMenu"; +import IconizedContextMenu, { + IconizedContextMenuOption, + IconizedContextMenuOptionList, +} from "../views/context_menus/IconizedContextMenu"; +import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton"; interface IProps { space: Room; @@ -214,6 +223,67 @@ const SpacePreview = ({ space, onJoinButtonClicked, onRejectButtonClicked }) =>
      ; }; +const SpaceLandingAddButton = ({ space, onNewRoomAdded }) => { + const cli = useContext(MatrixClientContext); + const [menuDisplayed, handle, openMenu, closeMenu] = useContextMenu(); + + let contextMenu; + if (menuDisplayed) { + const rect = handle.current.getBoundingClientRect(); + contextMenu = + + { + e.preventDefault(); + e.stopPropagation(); + closeMenu(); + + if (await showCreateNewRoom(cli, space)) { + onNewRoomAdded(); + } + }} + /> + { + e.preventDefault(); + e.stopPropagation(); + closeMenu(); + + const [added] = await showAddExistingRooms(cli, space); + if (added) { + onNewRoomAdded(); + } + }} + /> + + ; + } + + return <> + + { _t("Add") } + + { contextMenu } + ; +}; + const SpaceLanding = ({ space }) => { const cli = useContext(MatrixClientContext); const myMembership = useMyRoomMembership(space); @@ -238,32 +308,20 @@ const SpaceLanding = ({ space }) => { const [refreshToken, forceUpdate] = useStateToggle(false); - let addRoomButtons; + let addRoomButton; if (canAddRooms) { - addRoomButtons = - { - const [added] = await showAddExistingRooms(cli, space); - if (added) { - forceUpdate(); - } - }}> - { _t("Add existing rooms & spaces") } - - { - showCreateNewRoom(cli, space); - }}> - { _t("Create a new room") } - - ; + addRoomButton = ; } let settingsButton; if (shouldShowSpaceSettings(cli, space)) { - settingsButton = { - showSpaceSettings(cli, space); - }}> - { _t("Settings") } - ; + settingsButton = { + showSpaceSettings(cli, space); + }} + title={_t("Settings")} + />; } const onMembersClick = () => { @@ -290,17 +348,19 @@ const SpaceLanding = ({ space }) => { { inviteButton } + { settingsButton }

    -
    - { addRoomButtons } - { settingsButton } -
    - +
    ; }; @@ -354,7 +414,7 @@ const SpaceSetupFirstRooms = ({ space, title, description, onFinished }) => { let buttonLabel = _t("Skip for now"); if (roomNames.some(name => name.trim())) { onClick = onNextClick; - buttonLabel = busy ? _t("Creating rooms...") : _t("Continue") + buttonLabel = busy ? _t("Creating rooms...") : _t("Continue"); } return
    @@ -376,6 +436,74 @@ const SpaceSetupFirstRooms = ({ space, title, description, onFinished }) => {
    ; }; +const SpaceAddExistingRooms = ({ space, onFinished }) => { + const [selectedToAdd, setSelectedToAdd] = useState(new Set()); + + const [busy, setBusy] = useState(false); + const [error, setError] = useState(""); + + let onClick = onFinished; + let buttonLabel = _t("Skip for now"); + if (selectedToAdd.size > 0) { + onClick = async () => { + setBusy(true); + + for (const room of selectedToAdd) { + const via = calculateRoomVia(room); + try { + await SpaceStore.instance.addRoomToSpace(space, room.roomId, via).catch(async e => { + if (e.errcode === "M_LIMIT_EXCEEDED") { + await sleep(e.data.retry_after_ms); + return SpaceStore.instance.addRoomToSpace(space, room.roomId, via); // retry + } + + throw e; + }); + } catch (e) { + console.error("Failed to add rooms to space", e); + setError(_t("Failed to add rooms to space")); + break; + } + } + setBusy(false); + }; + buttonLabel = busy ? _t("Adding...") : _t("Add"); + } + + return
    +

    { _t("What do you want to organise?") }

    +
    + { _t("Pick rooms or conversations to add. This is just a space for you, " + + "no one will be informed. You can add more later.") } +
    + + { error &&
    { error }
    } + + { + if (checked) { + selectedToAdd.add(room); + } else { + selectedToAdd.delete(room); + } + setSelectedToAdd(new Set(selectedToAdd)); + }} + /> + +
    + + { buttonLabel } + +
    +
    ; +}; + const SpaceSetupPublicShare = ({ space, onFinished }) => { return

    { _t("Share %(name)s", { name: space.name }) }

    @@ -659,7 +787,7 @@ export default class SpaceRoomView extends React.PureComponent { return { - this.setState({ phase: invite ? Phase.PrivateInvite : Phase.PrivateCreateRooms }); + this.setState({ phase: invite ? Phase.PrivateInvite : Phase.PrivateExistingRooms }); }} />; case Phase.PrivateInvite: @@ -675,6 +803,11 @@ export default class SpaceRoomView extends React.PureComponent { "You can add more later too, including already existing ones.")} onFinished={() => this.setState({ phase: Phase.Landing })} />; + case Phase.PrivateExistingRooms: + return this.setState({ phase: Phase.Landing })} + />; } } diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index 12f5d6e890..8cc344f66b 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -68,6 +68,7 @@ class TimelinePanel extends React.Component { showReadReceipts: PropTypes.bool, // Enable managing RRs and RMs. These require the timelineSet to have a room. manageReadReceipts: PropTypes.bool, + sendReadReceiptOnLoad: PropTypes.bool, manageReadMarkers: PropTypes.bool, // true to give the component a 'display: none' style. @@ -126,6 +127,7 @@ class TimelinePanel extends React.Component { // event tile heights. (See _unpaginateEvents) timelineCap: Number.MAX_VALUE, className: 'mx_RoomView_messagePanel', + sendReadReceiptOnLoad: true, }; constructor(props) { @@ -785,8 +787,10 @@ class TimelinePanel extends React.Component { return; } const lastDisplayedEvent = this.state.events[lastDisplayedIndex]; - this._setReadMarker(lastDisplayedEvent.getId(), - lastDisplayedEvent.getTs()); + this._setReadMarker( + lastDisplayedEvent.getId(), + lastDisplayedEvent.getTs(), + ); // the read-marker should become invisible, so that if the user scrolls // down, they don't see it. @@ -872,7 +876,7 @@ class TimelinePanel extends React.Component { // The messagepanel knows where the RM is, so we must have loaded // the relevant event. this._messagePanel.current.scrollToEvent(this.state.readMarkerEventId, - 0, 1/3); + 0, 1/3); return; } @@ -1044,12 +1048,14 @@ class TimelinePanel extends React.Component { } if (eventId) { this._messagePanel.current.scrollToEvent(eventId, pixelOffset, - offsetBase); + offsetBase); } else { this._messagePanel.current.scrollToBottom(); } - this.sendReadReceipt(); + if (this.props.sendReadReceiptOnLoad) { + this.sendReadReceipt(); + } }); }; @@ -1418,8 +1424,8 @@ class TimelinePanel extends React.Component { ['PREPARED', 'CATCHUP'].includes(this.state.clientSyncState) ); const events = this.state.firstVisibleEventIndex - ? this.state.events.slice(this.state.firstVisibleEventIndex) - : this.state.events; + ? this.state.events.slice(this.state.firstVisibleEventIndex) + : this.state.events; return ( void, +} + +interface IState { + loginView: number; + keyBackupNeeded: boolean; + busy: boolean; + password: string; + errorText: string; + flows: LoginFlow[]; +} + +@replaceableComponent("structures.auth.SoftLogout") +export default class SoftLogout extends React.Component { + constructor(props) { + super(props); this.state = { loginView: LOGIN_VIEW.LOADING, keyBackupNeeded: true, // assume we do while we figure it out (see componentDidMount) - busy: false, password: "", errorText: "", + flows: [], }; } @@ -72,7 +83,7 @@ export default class SoftLogout extends React.Component { return; } - this._initLogin(); + this.initLogin(); const cli = MatrixClientPeg.get(); if (cli.isCryptoEnabled()) { @@ -94,7 +105,7 @@ export default class SoftLogout extends React.Component { }); }; - async _initLogin() { + private async initLogin() { const queryParams = this.props.realQueryParams; const hasAllParams = queryParams && queryParams['loginToken']; if (hasAllParams) { @@ -189,7 +200,7 @@ export default class SoftLogout extends React.Component { }); } - _renderSignInSection() { + private renderSignInSection() { if (this.state.loginView === LOGIN_VIEW.LOADING) { const Spinner = sdk.getComponent("elements.Spinner"); return ; @@ -247,7 +258,7 @@ export default class SoftLogout extends React.Component { } // else we already have a message and should use it (key backup warning) const loginType = this.state.loginView === LOGIN_VIEW.CAS ? "cas" : "sso"; - const flow = this.state.flows.find(flow => flow.type === "m.login." + loginType); + const flow = this.state.flows.find(flow => flow.type === "m.login." + loginType) as ISSOFlow; return (
    @@ -289,7 +300,7 @@ export default class SoftLogout extends React.Component {

    {_t("Sign in")}

    - {this._renderSignInSection()} + {this.renderSignInSection()}

    {_t("Clear personal data")}

    diff --git a/src/components/views/auth/InteractiveAuthEntryComponents.js b/src/components/views/auth/InteractiveAuthEntryComponents.js index 6cbecd22ee..e34349c474 100644 --- a/src/components/views/auth/InteractiveAuthEntryComponents.js +++ b/src/components/views/auth/InteractiveAuthEntryComponents.js @@ -169,7 +169,7 @@ export class PasswordAuthEntry extends React.Component { { submitButtonOrSpinner }
    - { errorSection } + { errorSection }
    ); } @@ -375,7 +375,7 @@ export class TermsAuthEntry extends React.Component { if (this.props.showContinue !== false) { // XXX: button classes submitButton = ; + onClick={this._trySubmit} disabled={!allChecked}>{_t("Accept")}; } return ( diff --git a/src/components/views/avatars/MemberAvatar.tsx b/src/components/views/avatars/MemberAvatar.tsx index c79cbc0d32..3205ca372c 100644 --- a/src/components/views/avatars/MemberAvatar.tsx +++ b/src/components/views/avatars/MemberAvatar.tsx @@ -68,8 +68,8 @@ export default class MemberAvatar extends React.Component { let imageUrl = null; if (props.member.getMxcAvatarUrl()) { imageUrl = mediaFromMxc(props.member.getMxcAvatarUrl()).getThumbnailOfSourceHttp( - Math.floor(props.width * window.devicePixelRatio), - Math.floor(props.height * window.devicePixelRatio), + props.width, + props.height, props.resizeMethod, ); } diff --git a/src/components/views/avatars/RoomAvatar.tsx b/src/components/views/avatars/RoomAvatar.tsx index ad0eb45a52..4693d907ba 100644 --- a/src/components/views/avatars/RoomAvatar.tsx +++ b/src/components/views/avatars/RoomAvatar.tsx @@ -93,8 +93,8 @@ export default class RoomAvatar extends React.Component { let oobAvatar = null; if (props.oobData.avatarUrl) { oobAvatar = mediaFromMxc(props.oobData.avatarUrl).getThumbnailOfSourceHttp( - Math.floor(props.width * window.devicePixelRatio), - Math.floor(props.height * window.devicePixelRatio), + props.width, + props.height, props.resizeMethod, ); } @@ -109,12 +109,7 @@ export default class RoomAvatar extends React.Component { private static getRoomAvatarUrl(props: IProps): string { if (!props.room) return null; - return Avatar.avatarUrlForRoom( - props.room, - Math.floor(props.width * window.devicePixelRatio), - Math.floor(props.height * window.devicePixelRatio), - props.resizeMethod, - ); + return Avatar.avatarUrlForRoom(props.room, props.width, props.height, props.resizeMethod); } private onRoomAvatarClick = () => { diff --git a/src/components/views/context_menus/MessageContextMenu.js b/src/components/views/context_menus/MessageContextMenu.js index f86cd26f32..35efd12c9c 100644 --- a/src/components/views/context_menus/MessageContextMenu.js +++ b/src/components/views/context_menus/MessageContextMenu.js @@ -1,8 +1,6 @@ /* -Copyright 2015, 2016 OpenMarket Ltd -Copyright 2018 New Vector Ltd Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> -Copyright 2019 The Matrix.org Foundation C.I.C. +Copyright 2015, 2016, 2018, 2019, 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. @@ -34,7 +32,7 @@ import {MenuItem} from "../../structures/ContextMenu"; import {EventType} from "matrix-js-sdk/src/@types/event"; import {replaceableComponent} from "../../../utils/replaceableComponent"; -function canCancel(eventStatus) { +export function canCancel(eventStatus) { return eventStatus === EventStatus.QUEUED || eventStatus === EventStatus.NOT_SENT; } @@ -98,21 +96,6 @@ export default class MessageContextMenu extends React.Component { return content.pinned && Array.isArray(content.pinned) && content.pinned.includes(this.props.mxEvent.getId()); } - onResendClick = () => { - Resend.resend(this.props.mxEvent); - this.closeMenu(); - }; - - onResendEditClick = () => { - Resend.resend(this.props.mxEvent.replacingEvent()); - this.closeMenu(); - }; - - onResendRedactionClick = () => { - Resend.resend(this.props.mxEvent.localRedactionEvent()); - this.closeMenu(); - }; - onResendReactionsClick = () => { for (const reaction of this._getUnsentReactions()) { Resend.resend(reaction); @@ -170,29 +153,6 @@ export default class MessageContextMenu extends React.Component { this.closeMenu(); }; - onCancelSendClick = () => { - const mxEvent = this.props.mxEvent; - const editEvent = mxEvent.replacingEvent(); - const redactEvent = mxEvent.localRedactionEvent(); - const pendingReactions = this._getPendingReactions(); - - if (editEvent && canCancel(editEvent.status)) { - Resend.removeFromQueue(editEvent); - } - if (redactEvent && canCancel(redactEvent.status)) { - Resend.removeFromQueue(redactEvent); - } - if (pendingReactions.length) { - for (const reaction of pendingReactions) { - Resend.removeFromQueue(reaction); - } - } - if (canCancel(mxEvent.status)) { - Resend.removeFromQueue(this.props.mxEvent); - } - this.closeMenu(); - }; - onForwardClick = () => { if (this.props.onCloseDialog) this.props.onCloseDialog(); dis.dispatch({ @@ -285,20 +245,9 @@ export default class MessageContextMenu extends React.Component { const me = cli.getUserId(); const mxEvent = this.props.mxEvent; const eventStatus = mxEvent.status; - const editStatus = mxEvent.replacingEvent() && mxEvent.replacingEvent().status; - const redactStatus = mxEvent.localRedactionEvent() && mxEvent.localRedactionEvent().status; const unsentReactionsCount = this._getUnsentReactions().length; - const pendingReactionsCount = this._getPendingReactions().length; - const allowCancel = canCancel(mxEvent.status) || - canCancel(editStatus) || - canCancel(redactStatus) || - pendingReactionsCount !== 0; - let resendButton; - let resendEditButton; let resendReactionsButton; - let resendRedactionButton; let redactButton; - let cancelButton; let forwardButton; let pinButton; let unhidePreviewButton; @@ -309,22 +258,6 @@ export default class MessageContextMenu extends React.Component { // status is SENT before remote-echo, null after const isSent = !eventStatus || eventStatus === EventStatus.SENT; if (!mxEvent.isRedacted()) { - if (eventStatus === EventStatus.NOT_SENT) { - resendButton = ( - - { _t('Resend') } - - ); - } - - if (editStatus === EventStatus.NOT_SENT) { - resendEditButton = ( - - { _t('Resend edit') } - - ); - } - if (unsentReactionsCount !== 0) { resendReactionsButton = ( @@ -334,14 +267,6 @@ export default class MessageContextMenu extends React.Component { } } - if (redactStatus === EventStatus.NOT_SENT) { - resendRedactionButton = ( - - { _t('Resend removal') } - - ); - } - if (isSent && this.state.canRedact) { redactButton = ( @@ -350,14 +275,6 @@ export default class MessageContextMenu extends React.Component { ); } - if (allowCancel) { - cancelButton = ( - - { _t('Cancel Sending') } - - ); - } - if (isContentActionable(mxEvent)) { forwardButton = ( @@ -433,7 +350,7 @@ export default class MessageContextMenu extends React.Component { > { _t('Source URL') } - ); + ); } if (this.props.collapseReplyThread) { @@ -455,12 +372,8 @@ export default class MessageContextMenu extends React.Component { return (
    - { resendButton } - { resendEditButton } { resendReactionsButton } - { resendRedactionButton } { redactButton } - { cancelButton } { forwardButton } { pinButton } { viewSourceButton } diff --git a/src/components/views/dialogs/AddExistingToSpaceDialog.tsx b/src/components/views/dialogs/AddExistingToSpaceDialog.tsx index 0f58a624f3..a33248200c 100644 --- a/src/components/views/dialogs/AddExistingToSpaceDialog.tsx +++ b/src/components/views/dialogs/AddExistingToSpaceDialog.tsx @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {useState} from "react"; +import React, {useContext, useMemo, useState} from "react"; import classNames from "classnames"; import {Room} from "matrix-js-sdk/src/models/room"; import {MatrixClient} from "matrix-js-sdk/src/client"; @@ -29,10 +29,13 @@ import RoomAvatar from "../avatars/RoomAvatar"; import {getDisplayAliasForRoom} from "../../../Rooms"; import AccessibleButton from "../elements/AccessibleButton"; import AutoHideScrollbar from "../../structures/AutoHideScrollbar"; -import {allSettled} from "../../../utils/promise"; +import {sleep} from "../../../utils/promise"; import DMRoomMap from "../../../utils/DMRoomMap"; import {calculateRoomVia} from "../../../utils/permalinks/Permalinks"; import StyledCheckbox from "../elements/StyledCheckbox"; +import MatrixClientContext from "../../../contexts/MatrixClientContext"; +import {sortRooms} from "../../../stores/room-list/algorithms/tag-sorting/RecentAlgorithm"; +import ProgressBar from "../elements/ProgressBar"; interface IProps extends IDialogProps { matrixClient: MatrixClient; @@ -41,45 +44,128 @@ interface IProps extends IDialogProps { } const Entry = ({ room, checked, onChange }) => { - return
    + return
    ; + { room.name } + onChange(e.target.checked) : null} + checked={checked} + disabled={!onChange} + /> + ; }; -const AddExistingToSpaceDialog: React.FC = ({ matrixClient: cli, space, onCreateRoomClick, onFinished }) => { +interface IAddExistingToSpaceProps { + space: Room; + selected: Set; + onChange(checked: boolean, room: Room): void; +} + +export const AddExistingToSpace: React.FC = ({ space, selected, onChange }) => { + const cli = useContext(MatrixClientContext); + const visibleRooms = useMemo(() => sortRooms(cli.getVisibleRooms()), [cli]); + const [query, setQuery] = useState(""); const lcQuery = query.toLowerCase(); - const [selectedSpace, setSelectedSpace] = useState(space); - const [selectedToAdd, setSelectedToAdd] = useState(new Set()); - const existingSubspaces = SpaceStore.instance.getChildSpaces(space.roomId); const existingSubspacesSet = new Set(existingSubspaces); const existingRoomsSet = new Set(SpaceStore.instance.getChildRooms(space.roomId)); - const joinRule = selectedSpace.getJoinRule(); - const [spaces, rooms, dms] = cli.getVisibleRooms().reduce((arr, room) => { + const joinRule = space.getJoinRule(); + const [spaces, rooms, dms] = visibleRooms.reduce((arr, room) => { if (room.getMyMembership() !== "join") return arr; if (!room.name.toLowerCase().includes(lcQuery)) return arr; if (room.isSpaceRoom()) { - if (room !== space && room !== selectedSpace && !existingSubspacesSet.has(room)) { + if (room !== space && !existingSubspacesSet.has(room)) { arr[0].push(room); } - } else if (!existingRoomsSet.has(room) && joinRule !== "public") { - // Only show DMs for non-public spaces as they make very little sense in spaces other than "Just Me" ones. - arr[DMRoomMap.shared().getUserIdForRoomId(room.roomId) ? 2 : 1].push(room); + } else if (!existingRoomsSet.has(room)) { + if (!DMRoomMap.shared().getUserIdForRoomId(room.roomId)) { + arr[1].push(room); + } else if (joinRule !== "public") { + // Only show DMs for non-public spaces as they make very little sense in spaces other than "Just Me" ones. + arr[2].push(room); + } } return arr; }, [[], [], []]); - const [busy, setBusy] = useState(false); - const [error, setError] = useState(""); + return
    + + + { rooms.length > 0 ? ( +
    +

    { _t("Rooms") }

    + { rooms.map(room => { + return { + onChange(checked, room); + } : null} + />; + }) } +
    + ) : undefined } + + { spaces.length > 0 ? ( +
    +

    { _t("Spaces") }

    + { spaces.map(space => { + return { + onChange(checked, space); + } : null} + />; + }) } +
    + ) : null } + + { dms.length > 0 ? ( +
    +

    { _t("Direct Messages") }

    + { dms.map(room => { + return { + onChange(checked, room); + } : null} + />; + }) } +
    + ) : null } + + { spaces.length + rooms.length + dms.length < 1 ? + { _t("No results") } + : undefined } +
    +
    ; +}; + +const AddExistingToSpaceDialog: React.FC = ({ matrixClient: cli, space, onCreateRoomClick, onFinished }) => { + const [selectedSpace, setSelectedSpace] = useState(space); + const existingSubspaces = SpaceStore.instance.getChildSpaces(space.roomId); + const [selectedToAdd, setSelectedToAdd] = useState(new Set()); + + const [progress, setProgress] = useState(null); + const [error, setError] = useState(null); let spaceOptionSection; - if (existingSubspacesSet.size > 0) { + if (existingSubspaces.length > 0) { const options = [space, ...existingSubspaces].map((space) => { const classes = classNames("mx_AddExistingToSpaceDialog_dropdownOption", { mx_AddExistingToSpaceDialog_dropdownOptionActive: space === selectedSpace, @@ -116,116 +202,106 @@ const AddExistingToSpaceDialog: React.FC = ({ matrixClient: cli, space,
    ; - return - { error &&
    { error }
    } + const addRooms = async () => { + setError(null); + setProgress(0); - - - { rooms.length > 0 ? ( -
    -

    { _t("Rooms") }

    - { rooms.map(room => { - return { - if (checked) { - selectedToAdd.add(room); - } else { - selectedToAdd.delete(room); - } - setSelectedToAdd(new Set(selectedToAdd)); - }} - />; - }) } -
    - ) : undefined } + let error; - { spaces.length > 0 ? ( -
    -

    { _t("Spaces") }

    - { spaces.map(space => { - return { - if (checked) { - selectedToAdd.add(space); - } else { - selectedToAdd.delete(space); - } - setSelectedToAdd(new Set(selectedToAdd)); - }} - />; - }) } -
    - ) : null } + for (const room of selectedToAdd) { + const via = calculateRoomVia(room); + try { + await SpaceStore.instance.addRoomToSpace(space, room.roomId, via).catch(async e => { + if (e.errcode === "M_LIMIT_EXCEEDED") { + await sleep(e.data.retry_after_ms); + return SpaceStore.instance.addRoomToSpace(space, room.roomId, via); // retry + } - { dms.length > 0 ? ( -
    -

    { _t("Direct Messages") }

    - { dms.map(space => { - return { - if (checked) { - selectedToAdd.add(space); - } else { - selectedToAdd.delete(space); - } - setSelectedToAdd(new Set(selectedToAdd)); - }} - />; - }) } -
    - ) : null } + throw e; + }); + setProgress(i => i + 1); + } catch (e) { + console.error("Failed to add rooms to space", e); + setError(error = e); + break; + } + } - { spaces.length + rooms.length + dms.length < 1 ? - { _t("No results") } - : undefined } -
    + if (!error) { + onFinished(true); + } + }; -
    + const busy = progress !== null; + + let footer; + if (error) { + footer = <> + + + +
    { _t("Not all selected were added") }
    +
    { _t("Try again") }
    +
    + + + { _t("Retry") } + + ; + } else if (busy) { + footer = + +
    + { _t("Adding rooms... (%(progress)s out of %(count)s)", { + count: selectedToAdd.size, + progress, + }) } +
    +
    ; + } else { + footer = <> -
    { _t("Don't want to add an existing room?") }
    +
    { _t("Want to add a new room instead?") }
    onCreateRoomClick(cli, space)} kind="link"> { _t("Create a new room") }
    - { - setBusy(true); - try { - await allSettled(Array.from(selectedToAdd).map((room) => - SpaceStore.instance.addRoomToSpace(space, room.roomId, calculateRoomVia(room)))); - onFinished(true); - } catch (e) { - console.error("Failed to add rooms to space", e); - setError(_t("Failed to add rooms to space")); - } - setBusy(false); - }} - > - { busy ? _t("Adding...") : _t("Add") } + + { _t("Add") } + ; + } + + return + + { + if (checked) { + selectedToAdd.add(room); + } else { + selectedToAdd.delete(room); + } + setSelectedToAdd(new Set(selectedToAdd)); + } : null} + /> + + +
    + { footer }
    ; }; diff --git a/src/components/views/dialogs/BugReportDialog.js b/src/components/views/dialogs/BugReportDialog.js index 8948c14c7c..cbe0130649 100644 --- a/src/components/views/dialogs/BugReportDialog.js +++ b/src/components/views/dialogs/BugReportDialog.js @@ -184,7 +184,7 @@ export default class BugReportDialog extends React.Component { return (
    diff --git a/src/components/views/dialogs/ChangelogDialog.js b/src/components/views/dialogs/ChangelogDialog.js index 50bc13cff5..efbeba3977 100644 --- a/src/components/views/dialogs/ChangelogDialog.js +++ b/src/components/views/dialogs/ChangelogDialog.js @@ -95,7 +95,7 @@ export default class ChangelogDialog extends React.Component { description={content} button={_t("Update")} onFinished={this.props.onFinished} - /> + /> ); } } diff --git a/src/components/views/dialogs/ConfirmWipeDeviceDialog.js b/src/components/views/dialogs/ConfirmWipeDeviceDialog.js index 4faaad0f7e..333e1522f1 100644 --- a/src/components/views/dialogs/ConfirmWipeDeviceDialog.js +++ b/src/components/views/dialogs/ConfirmWipeDeviceDialog.js @@ -39,9 +39,12 @@ export default class ConfirmWipeDeviceDialog extends React.Component { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); return ( - +

    {_t( diff --git a/src/components/views/dialogs/DevtoolsDialog.js b/src/components/views/dialogs/DevtoolsDialog.js index 9f5513e0a3..8a035263cc 100644 --- a/src/components/views/dialogs/DevtoolsDialog.js +++ b/src/components/views/dialogs/DevtoolsDialog.js @@ -70,8 +70,16 @@ class GenericEditor extends React.PureComponent { } textInput(id, label) { - return ; + return ; } } @@ -155,7 +163,7 @@ export class SendCustomEvent extends GenericEditor {
    + autoComplete="off" value={this.state.evContent} onChange={this._onChange} element="textarea" />

    @@ -239,7 +247,7 @@ class SendAccountData extends GenericEditor {
    + autoComplete="off" value={this.state.evContent} onChange={this._onChange} element="textarea" />
    @@ -315,15 +323,15 @@ class FilteredList extends React.PureComponent { const TruncatedList = sdk.getComponent("elements.TruncatedList"); return
    + type="text" autoComplete="off" value={this.props.query} onChange={this.onQuery} + className="mx_TextInputDialog_input mx_DevTools_RoomStateExplorer_query" + // force re-render so that autoFocus is applied when this component is re-used + key={this.props.children[0] ? this.props.children[0].key : ''} /> + getChildCount={this.getChildCount} + truncateAt={this.state.truncateAt} + createOverflowElement={this.createOverflowElement} />
    ; } } @@ -647,7 +655,7 @@ function VerificationRequest({txnId, request}) { /* Note that request.timeout is a getter, so its value changes */ const id = setInterval(() => { - setRequestTimeout(request.timeout); + setRequestTimeout(request.timeout); }, 500); return () => { clearInterval(id); }; @@ -941,35 +949,35 @@ class SettingsExplorer extends React.Component { /> - - - - - + + + + + - {allSettings.map(i => ( - - + - - - - ))} + + + + + + ))}
    {_t("Setting ID")}{_t("Value")}{_t("Value in this room")}
    {_t("Setting ID")}{_t("Value")}{_t("Value in this room")}
    - this.onViewClick(e, i)}> - {i} - - this.onEditClick(e, i)} - className='mx_DevTools_SettingsExplorer_edit' - > + {allSettings.map(i => ( +
    + this.onViewClick(e, i)}> + {i} + + this.onEditClick(e, i)} + className='mx_DevTools_SettingsExplorer_edit' + > ✏ - - - {this.renderSettingValue(SettingsStore.getValue(i))} - - - {this.renderSettingValue(SettingsStore.getValue(i, room.roomId))} - -
    + {this.renderSettingValue(SettingsStore.getValue(i))} + + + {this.renderSettingValue(SettingsStore.getValue(i, room.roomId))} + +
    @@ -998,11 +1006,11 @@ class SettingsExplorer extends React.Component {
    - - - - - + + + + + {LEVEL_ORDER.map(lvl => ( diff --git a/src/components/views/dialogs/IncomingSasDialog.js b/src/components/views/dialogs/IncomingSasDialog.js index f18b7a9d0c..5df02d7a6f 100644 --- a/src/components/views/dialogs/IncomingSasDialog.js +++ b/src/components/views/dialogs/IncomingSasDialog.js @@ -130,7 +130,7 @@ export default class IncomingSasDialog extends React.Component { const oppProfile = this.state.opponentProfile; if (oppProfile) { const url = oppProfile.avatar_url - ? mediaFromMxc(oppProfile.avatar_url).getSquareThumbnailHttp(Math.floor(48 * window.devicePixelRatio)) + ? mediaFromMxc(oppProfile.avatar_url).getSquareThumbnailHttp(48) : null; profile =
    +

    {_t("Enable 'Manage Integrations' in Settings to do this.")}

    diff --git a/src/components/views/dialogs/IntegrationsImpossibleDialog.js b/src/components/views/dialogs/IntegrationsImpossibleDialog.js index 9bc9d02ba6..e14d40aaef 100644 --- a/src/components/views/dialogs/IntegrationsImpossibleDialog.js +++ b/src/components/views/dialogs/IntegrationsImpossibleDialog.js @@ -37,9 +37,12 @@ export default class IntegrationsImpossibleDialog extends React.Component { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); return ( - +

    {_t( diff --git a/src/components/views/dialogs/InviteDialog.tsx b/src/components/views/dialogs/InviteDialog.tsx index 2ebc84ec7c..ec9c71ccbe 100644 --- a/src/components/views/dialogs/InviteDialog.tsx +++ b/src/components/views/dialogs/InviteDialog.tsx @@ -1312,7 +1312,7 @@ export default class InviteDialog extends React.PureComponent {success ? - {_t("Upload completed")} : - cancelled ? - {_t("Cancelled signature upload")} : - {_t("Unable to upload")}} + {_t("Upload completed")} : + cancelled ? + {_t("Cancelled signature upload")} : + {_t("Unable to upload")}} + {content} ); diff --git a/src/components/views/dialogs/RoomSettingsDialog.js b/src/components/views/dialogs/RoomSettingsDialog.js index 9c2f23ef22..b6c4d42243 100644 --- a/src/components/views/dialogs/RoomSettingsDialog.js +++ b/src/components/views/dialogs/RoomSettingsDialog.js @@ -116,8 +116,12 @@ export default class RoomSettingsDialog extends React.Component { const roomName = MatrixClientPeg.get().getRoom(this.props.roomId).name; return ( - +

    diff --git a/src/components/views/dialogs/ServerPickerDialog.tsx b/src/components/views/dialogs/ServerPickerDialog.tsx index 4abc0a88b1..62a2b95c68 100644 --- a/src/components/views/dialogs/ServerPickerDialog.tsx +++ b/src/components/views/dialogs/ServerPickerDialog.tsx @@ -1,5 +1,5 @@ /* -Copyright 2020 The Matrix.org Foundation C.I.C. +Copyright 2020-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. @@ -110,7 +110,7 @@ export default class ServerPickerDialog extends React.PureComponent diff --git a/src/components/views/dialogs/SessionRestoreErrorDialog.js b/src/components/views/dialogs/SessionRestoreErrorDialog.js index 50d7fbea09..43e73a2f83 100644 --- a/src/components/views/dialogs/SessionRestoreErrorDialog.js +++ b/src/components/views/dialogs/SessionRestoreErrorDialog.js @@ -98,7 +98,7 @@ export default class SessionRestoreErrorDialog extends React.Component { "may be incompatible with this version. Close this window and return " + "to the more recent version.", { brand }, - ) }

    + ) }

    { _t( "Clearing your browser's storage may fix the problem, but will sign you " + diff --git a/src/components/views/dialogs/StorageEvictedDialog.js b/src/components/views/dialogs/StorageEvictedDialog.js index 15c5347644..1e17ab1738 100644 --- a/src/components/views/dialogs/StorageEvictedDialog.js +++ b/src/components/views/dialogs/StorageEvictedDialog.js @@ -45,10 +45,12 @@ export default class StorageEvictedDialog extends React.Component { let logRequest; if (SdkConfig.get().bug_report_endpoint_url) { logRequest = _t( - "To help us prevent this in future, please send us logs.", {}, - { - a: text => {text}, - }); + "To help us prevent this in future, please send us logs.", + {}, + { + a: text => {text}, + }, + ); } return ( diff --git a/src/components/views/dialogs/UserSettingsDialog.js b/src/components/views/dialogs/UserSettingsDialog.js index eb9eaeb5dd..e7f6953589 100644 --- a/src/components/views/dialogs/UserSettingsDialog.js +++ b/src/components/views/dialogs/UserSettingsDialog.js @@ -155,8 +155,12 @@ export default class UserSettingsDialog extends React.Component { const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog'); return ( - +

    diff --git a/src/components/views/dialogs/VerificationRequestDialog.js b/src/components/views/dialogs/VerificationRequestDialog.js index 205597a1c4..9281275e6a 100644 --- a/src/components/views/dialogs/VerificationRequestDialog.js +++ b/src/components/views/dialogs/VerificationRequestDialog.js @@ -52,11 +52,13 @@ export default class VerificationRequestDialog extends React.Component { const title = request && request.isSelfVerification ? _t("Verify other login") : _t("Verification Request"); - return + return +

    {_t("The widget will verify your user ID, but won't be able to perform actions for you:")} diff --git a/src/components/views/dialogs/security/ConfirmDestroyCrossSigningDialog.js b/src/components/views/dialogs/security/ConfirmDestroyCrossSigningDialog.js index 43fb25f152..e71983b074 100644 --- a/src/components/views/dialogs/security/ConfirmDestroyCrossSigningDialog.js +++ b/src/components/views/dialogs/security/ConfirmDestroyCrossSigningDialog.js @@ -40,10 +40,11 @@ export default class ConfirmDestroyCrossSigningDialog extends React.Component { return ( + className='mx_ConfirmDestroyCrossSigningDialog' + hasCancel={true} + onFinished={this.props.onFinished} + title={_t("Destroy cross-signing keys?")} + >

    {_t( diff --git a/src/components/views/dialogs/security/RestoreKeyBackupDialog.js b/src/components/views/dialogs/security/RestoreKeyBackupDialog.js index 1fafe03d95..4ac15ab5a3 100644 --- a/src/components/views/dialogs/security/RestoreKeyBackupDialog.js +++ b/src/components/views/dialogs/security/RestoreKeyBackupDialog.js @@ -373,21 +373,24 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { {_t( "If you've forgotten your Security Phrase you can "+ "use your Security Key or " + - "set up new recovery options" - , {}, { - button1: s => - {s} - , - button2: s => - {s} - , - })} + "set up new recovery options", + {}, + { + button1: s => + {s} + , + button2: s => + {s} + , + })}

    ; } else { title = _t("Enter Security Key"); @@ -435,15 +438,17 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
    {_t( "If you've forgotten your Security Key you can "+ - "" - , {}, { - button: s => - {s} - , - })} + "", + {}, + { + button: s => + {s} + , + }, + )}
    ; } @@ -452,9 +457,9 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { onFinished={this.props.onFinished} title={title} > -
    - {content} -
    +
    + {content} +
    ); } diff --git a/src/components/views/elements/ActionButton.js b/src/components/views/elements/ActionButton.js index 1714891cb5..9903c631b2 100644 --- a/src/components/views/elements/ActionButton.js +++ b/src/components/views/elements/ActionButton.js @@ -70,8 +70,8 @@ export default class ActionButton extends React.Component { } const icon = this.props.iconPath ? - () : - undefined; + () : + undefined; const classNames = ["mx_RoleButton"]; if (this.props.className) { diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index e206fda797..b898ad2ebc 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -109,7 +109,7 @@ export default class AppTile extends React.Component { const childContentProtocol = u.protocol; if (parentContentProtocol === 'https:' && childContentProtocol !== 'https:') { console.warn("Refusing to load mixed-content app:", - parentContentProtocol, childContentProtocol, window.location, this.props.app.url); + parentContentProtocol, childContentProtocol, window.location, this.props.app.url); return true; } return false; diff --git a/src/components/views/elements/EditableItemList.js b/src/components/views/elements/EditableItemList.js index ff62f169fa..d8ec5af278 100644 --- a/src/components/views/elements/EditableItemList.js +++ b/src/components/views/elements/EditableItemList.js @@ -65,12 +65,18 @@ export class EditableItem extends React.Component { {_t("Are you sure?")} - + {_t("Yes")} - + {_t("No")}
    @@ -121,11 +127,15 @@ export default class EditableItemList extends React.Component { _renderNewItemField() { return ( - + + autoComplete="off" value={this.props.newItem || ""} onChange={this._onNewItemChanged} + list={this.props.suggestionsListId} /> {_t("Add")} diff --git a/src/components/views/elements/EditableText.js b/src/components/views/elements/EditableText.js index 638fd02553..7c38ac1777 100644 --- a/src/components/views/elements/EditableText.js +++ b/src/components/views/elements/EditableText.js @@ -221,13 +221,15 @@ export default class EditableText extends React.Component { ; } else { // show the content editable div, but manually manage its contents as react and contentEditable don't play nice together - editableEl =
    ; + editableEl =
    ; } return editableEl; diff --git a/src/components/views/elements/ImageView.tsx b/src/components/views/elements/ImageView.tsx index cbced07bfe..05d487a9eb 100644 --- a/src/components/views/elements/ImageView.tsx +++ b/src/components/views/elements/ImageView.tsx @@ -34,16 +34,15 @@ import {RoomPermalinkCreator} from "../../../utils/permalinks/Permalinks" import {MatrixEvent} from "matrix-js-sdk/src/models/event"; import {normalizeWheelEvent} from "../../../utils/Mouse"; -const MIN_ZOOM = 100; -const MAX_ZOOM = 300; +// Max scale to keep gaps around the image +const MAX_SCALE = 0.95; // This is used for the buttons -const ZOOM_STEP = 10; +const ZOOM_STEP = 0.10; // This is used for mouse wheel events -const ZOOM_COEFFICIENT = 0.5; +const ZOOM_COEFFICIENT = 0.0025; // If we have moved only this much we can zoom const ZOOM_DISTANCE = 10; - interface IProps { src: string, // the source of the image being displayed name?: string, // the main title ('name') for the image @@ -62,8 +61,10 @@ interface IProps { } interface IState { - rotation: number, zoom: number, + minZoom: number, + maxZoom: number, + rotation: number, translationX: number, translationY: number, moving: boolean, @@ -75,8 +76,10 @@ export default class ImageView extends React.Component { constructor(props) { super(props); this.state = { + zoom: 0, + minZoom: MAX_SCALE, + maxZoom: MAX_SCALE, rotation: 0, - zoom: MIN_ZOOM, translationX: 0, translationY: 0, moving: false, @@ -87,6 +90,8 @@ export default class ImageView extends React.Component { // XXX: Refs to functional components private contextMenuButton = createRef(); private focusLock = createRef(); + private imageWrapper = createRef(); + private image = createRef(); private initX = 0; private initY = 0; @@ -99,12 +104,89 @@ export default class ImageView extends React.Component { // We have to use addEventListener() because the listener // needs to be passive in order to work with Chromium this.focusLock.current.addEventListener('wheel', this.onWheel, { passive: false }); + // We want to recalculate zoom whenever the window's size changes + window.addEventListener("resize", this.calculateZoom); + // After the image loads for the first time we want to calculate the zoom + this.image.current.addEventListener("load", this.calculateZoom); + // Try to precalculate the zoom from width and height props + this.calculateZoom(); } componentWillUnmount() { this.focusLock.current.removeEventListener('wheel', this.onWheel); + window.removeEventListener("resize", this.calculateZoom); + this.image.current.removeEventListener("load", this.calculateZoom); } + private calculateZoom = () => { + const image = this.image.current; + const imageWrapper = this.imageWrapper.current; + + const width = this.props.width || image.naturalWidth; + const height = this.props.height || image.naturalHeight; + + const zoomX = imageWrapper.clientWidth / width; + const zoomY = imageWrapper.clientHeight / height; + + // If the image is smaller in both dimensions set its the zoom to 1 to + // display it in its original size + if (zoomX >= 1 && zoomY >= 1) { + this.setState({ + zoom: 1, + minZoom: 1, + maxZoom: 1, + }); + return; + } + // We set minZoom to the min of the zoomX and zoomY to avoid overflow in + // any direction. We also multiply by MAX_SCALE to get a gap around the + // image by default + const minZoom = Math.min(zoomX, zoomY) * MAX_SCALE; + + if (this.state.zoom <= this.state.minZoom) this.setState({zoom: minZoom}); + this.setState({ + minZoom: minZoom, + maxZoom: 1, + }); + } + + private zoom(delta: number) { + const newZoom = this.state.zoom + delta; + + if (newZoom <= this.state.minZoom) { + this.setState({ + zoom: this.state.minZoom, + translationX: 0, + translationY: 0, + }); + return; + } + if (newZoom >= this.state.maxZoom) { + this.setState({zoom: this.state.maxZoom}); + return; + } + + this.setState({ + zoom: newZoom, + }); + } + + private onWheel = (ev: WheelEvent) => { + ev.stopPropagation(); + ev.preventDefault(); + + const {deltaY} = normalizeWheelEvent(ev); + this.zoom(-(deltaY * ZOOM_COEFFICIENT)); + }; + + private onZoomInClick = () => { + this.zoom(ZOOM_STEP); + }; + + private onZoomOutClick = () => { + this.zoom(-ZOOM_STEP); + }; + private onKeyDown = (ev: KeyboardEvent) => { if (ev.key === Key.ESCAPE) { ev.stopPropagation(); @@ -113,31 +195,6 @@ export default class ImageView extends React.Component { } }; - private onWheel = (ev: WheelEvent) => { - ev.stopPropagation(); - ev.preventDefault(); - - const {deltaY} = normalizeWheelEvent(ev); - const newZoom = this.state.zoom - (deltaY * ZOOM_COEFFICIENT); - - if (newZoom <= MIN_ZOOM) { - this.setState({ - zoom: MIN_ZOOM, - translationX: 0, - translationY: 0, - }); - return; - } - if (newZoom >= MAX_ZOOM) { - this.setState({zoom: MAX_ZOOM}); - return; - } - - this.setState({ - zoom: newZoom, - }); - }; - private onRotateCounterClockwiseClick = () => { const cur = this.state.rotation; const rotationDegrees = cur - 90; @@ -150,31 +207,6 @@ export default class ImageView extends React.Component { this.setState({ rotation: rotationDegrees }); }; - private onZoomInClick = () => { - if (this.state.zoom >= MAX_ZOOM) { - this.setState({zoom: MAX_ZOOM}); - return; - } - - this.setState({ - zoom: this.state.zoom + ZOOM_STEP, - }); - }; - - private onZoomOutClick = () => { - if (this.state.zoom <= MIN_ZOOM) { - this.setState({ - zoom: MIN_ZOOM, - translationX: 0, - translationY: 0, - }); - return; - } - this.setState({ - zoom: this.state.zoom - ZOOM_STEP, - }); - }; - private onDownloadClick = () => { const a = document.createElement("a"); a.href = this.props.src; @@ -217,8 +249,8 @@ export default class ImageView extends React.Component { if (ev.button !== 0) return; // Zoom in if we are completely zoomed out - if (this.state.zoom === MIN_ZOOM) { - this.setState({zoom: MAX_ZOOM}); + if (this.state.zoom === this.state.minZoom) { + this.setState({zoom: this.state.maxZoom}); return; } @@ -251,7 +283,7 @@ export default class ImageView extends React.Component { Math.abs(this.state.translationY - this.previousY) < ZOOM_DISTANCE ) { this.setState({ - zoom: MIN_ZOOM, + zoom: this.state.minZoom, translationX: 0, translationY: 0, }); @@ -286,17 +318,20 @@ export default class ImageView extends React.Component { render() { const showEventMeta = !!this.props.mxEvent; + const zoomingDisabled = this.state.maxZoom === this.state.minZoom; let cursor; if (this.state.moving) { cursor= "grabbing"; - } else if (this.state.zoom === MIN_ZOOM) { + } else if (zoomingDisabled) { + cursor = "default"; + } else if (this.state.zoom === this.state.minZoom) { cursor = "zoom-in"; } else { cursor = "zoom-out"; } const rotationDegrees = this.state.rotation + "deg"; - const zoomPercentage = this.state.zoom/100; + const zoom = this.state.zoom; const translatePixelsX = this.state.translationX + "px"; const translatePixelsY = this.state.translationY + "px"; // The order of the values is important! @@ -308,7 +343,7 @@ export default class ImageView extends React.Component { transition: this.state.moving ? null : "transform 200ms ease 0s", transform: `translateX(${translatePixelsX}) translateY(${translatePixelsY}) - scale(${zoomPercentage}) + scale(${zoom}) rotate(${rotationDegrees})`, }; @@ -380,6 +415,25 @@ export default class ImageView extends React.Component { ); } + let zoomOutButton; + let zoomInButton; + if (!zoomingDisabled) { + zoomOutButton = ( + + + ); + zoomInButton = ( + + + ); + } + return ( { title={_t("Rotate Left")} onClick={ this.onRotateCounterClockwiseClick }> - - - - + {zoomOutButton} + {zoomInButton} { {this.renderContextMenu()}
    -
    +
    {this.props.label}; - let secondPart = ; + let secondPart = ; if (this.props.toggleInFront) { const temp = firstPart; diff --git a/src/components/views/elements/LanguageDropdown.js b/src/components/views/elements/LanguageDropdown.js index 2e961be700..b8734c5afb 100644 --- a/src/components/views/elements/LanguageDropdown.js +++ b/src/components/views/elements/LanguageDropdown.js @@ -60,10 +60,10 @@ export default class LanguageDropdown extends React.Component { // doesn't know this, therefore we do this. const language = SettingsStore.getValue("language", null, /*excludeDefault:*/true); if (language) { - this.props.onOptionChange(language); + this.props.onOptionChange(language); } else { - const language = languageHandler.normalizeLanguageKey(languageHandler.getLanguageFromBrowser()); - this.props.onOptionChange(language); + const language = languageHandler.normalizeLanguageKey(languageHandler.getLanguageFromBrowser()); + this.props.onOptionChange(language); } } } diff --git a/src/components/views/elements/Pill.js b/src/components/views/elements/Pill.js index a8e16813e6..ace41db39d 100644 --- a/src/components/views/elements/Pill.js +++ b/src/components/views/elements/Pill.js @@ -225,19 +225,19 @@ class Pill extends React.Component { } break; case Pill.TYPE_USER_MENTION: { - // If this user is not a member of this room, default to the empty member - const member = this.state.member; - if (member) { - userId = member.userId; - member.rawDisplayName = member.rawDisplayName || ''; - linkText = member.rawDisplayName; - if (this.props.shouldShowPillAvatar) { - avatar =
    -
    {_t("Level")}{_t("Settable at global")}{_t("Settable at room")}
    {_t("Level")}{_t("Settable at global")}{_t("Settable at room")}
    {_t("Homeserver feature support:")} {homeserverSupportsCrossSigning ? _t("exists") : _t("not found")}
    +
    {errorSection} {actionRow} diff --git a/src/components/views/settings/DevicesPanel.js b/src/components/views/settings/DevicesPanel.js index e7d300b0f8..b1ad605a37 100644 --- a/src/components/views/settings/DevicesPanel.js +++ b/src/components/views/settings/DevicesPanel.js @@ -214,7 +214,7 @@ export default class DevicesPanel extends React.Component { const deleteButton = this.state.deleting ? : - { _t("Delete %(count)s sessions", {count: this.state.selectedDevices.length}) } + { _t("Delete %(count)s sessions", {count: this.state.selectedDevices.length})} ; const classes = classNames(this.props.className, "mx_DevicesPanel"); diff --git a/src/components/views/settings/E2eAdvancedPanel.js b/src/components/views/settings/E2eAdvancedPanel.tsx similarity index 100% rename from src/components/views/settings/E2eAdvancedPanel.js rename to src/components/views/settings/E2eAdvancedPanel.tsx diff --git a/src/components/views/settings/EventIndexPanel.js b/src/components/views/settings/EventIndexPanel.tsx similarity index 65% rename from src/components/views/settings/EventIndexPanel.js rename to src/components/views/settings/EventIndexPanel.tsx index d1a02de16d..fa84063ee8 100644 --- a/src/components/views/settings/EventIndexPanel.js +++ b/src/components/views/settings/EventIndexPanel.tsx @@ -1,5 +1,5 @@ /* -Copyright 2020 The Matrix.org Foundation C.I.C. +Copyright 2020-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. @@ -28,10 +28,17 @@ import {SettingLevel} from "../../../settings/SettingLevel"; import {replaceableComponent} from "../../../utils/replaceableComponent"; import SeshatResetDialog from '../dialogs/SeshatResetDialog'; +interface IState { + enabling: boolean; + eventIndexSize: number; + roomCount: number; + eventIndexingEnabled: boolean; +} + @replaceableComponent("views.settings.EventIndexPanel") -export default class EventIndexPanel extends React.Component { - constructor() { - super(); +export default class EventIndexPanel extends React.Component<{}, IState> { + constructor(props) { + super(props); this.state = { enabling: false, @@ -68,7 +75,7 @@ export default class EventIndexPanel extends React.Component { } } - async componentDidMount(): void { + componentDidMount(): void { this.updateState(); } @@ -102,8 +109,10 @@ export default class EventIndexPanel extends React.Component { }); } - _onManage = async () => { + private onManage = async () => { Modal.createTrackedDialogAsync('Message search', 'Message search', + // @ts-ignore: TS doesn't seem to like the type of this now that it + // has also been converted to TS as well, but I can't figure out why... import('../../../async-components/views/dialogs/eventindex/ManageEventIndexDialog'), { onFinished: () => {}, @@ -111,7 +120,7 @@ export default class EventIndexPanel extends React.Component { ); } - _onEnable = async () => { + private onEnable = async () => { this.setState({ enabling: true, }); @@ -123,14 +132,13 @@ export default class EventIndexPanel extends React.Component { await this.updateState(); } - _confirmEventStoreReset = () => { - const self = this; + private confirmEventStoreReset = () => { const { close } = Modal.createDialog(SeshatResetDialog, { onFinished: async (success) => { if (success) { await SettingsStore.setValue('enableEventIndexing', null, SettingLevel.DEVICE, false); await EventIndexPeg.deleteEventIndex(); - await self._onEnable(); + await this.onEnable(); close(); } }, @@ -145,20 +153,19 @@ export default class EventIndexPanel extends React.Component { if (EventIndexPeg.get() !== null) { eventIndexingSettings = (
    -
    - {_t("Securely cache encrypted messages locally for them " + - "to appear in search results, using %(size)s to store messages from %(rooms)s rooms.", - { - size: formatBytes(this.state.eventIndexSize, 0), - // This drives the singular / plural string - // selection for "room" / "rooms" only. - count: this.state.roomCount, - rooms: formatCountLong(this.state.roomCount), - }, - )} -
    +
    {_t( + "Securely cache encrypted messages locally for them " + + "to appear in search results, using %(size)s to store messages from %(rooms)s rooms.", + { + size: formatBytes(this.state.eventIndexSize, 0), + // This drives the singular / plural string + // selection for "room" / "rooms" only. + count: this.state.roomCount, + rooms: formatCountLong(this.state.roomCount), + }, + )}
    - + {_t("Manage")}
    @@ -167,13 +174,13 @@ export default class EventIndexPanel extends React.Component { } else if (!this.state.eventIndexingEnabled && EventIndexPeg.supportIsInstalled()) { eventIndexingSettings = (
    -
    - {_t( "Securely cache encrypted messages locally for them to " + - "appear in search results.")} -
    +
    {_t( + "Securely cache encrypted messages locally for them to " + + "appear in search results.", + )}
    + onClick={this.onEnable}> {_t("Enable")} {this.state.enabling ? :
    } @@ -188,40 +195,36 @@ export default class EventIndexPanel extends React.Component { ); eventIndexingSettings = ( -
    +
    {_t( + "%(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.", { - _t( "%(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, - }, - { - 'nativeLink': (sub) => {sub}, - }, - ) - } -
    + brand, + }, + { + nativeLink: sub => {sub}, + }, + )}
    ); } else if (!EventIndexPeg.platformHasSupport()) { eventIndexingSettings = ( -
    +
    {_t( + "%(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.", { - _t( "%(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, - }, - { - 'desktopLink': (sub) => {sub}, - }, - ) - } -
    + brand, + }, + { + desktopLink: sub => {sub}, + }, + )}
    ); } else { eventIndexingSettings = ( @@ -233,19 +236,18 @@ export default class EventIndexPanel extends React.Component { }

    {EventIndexPeg.error && ( -
    - {_t("Advanced")} - - {EventIndexPeg.error.message} - -

    - - {_t("Reset")} - -

    -
    +
    + {_t("Advanced")} + + {EventIndexPeg.error.message} + +

    + + {_t("Reset")} + +

    +
    )} -
    ); } diff --git a/src/components/views/settings/Notifications.js b/src/components/views/settings/Notifications.js index 25fe434994..5756536085 100644 --- a/src/components/views/settings/Notifications.js +++ b/src/components/views/settings/Notifications.js @@ -100,7 +100,7 @@ export default class Notifications extends React.Component { MatrixClientPeg.get().setPushRuleEnabled( 'global', self.state.masterPushRule.kind, self.state.masterPushRule.rule_id, !checked, ).then(function() { - self._refreshFromServer(); + self._refreshFromServer(); }); }; @@ -580,12 +580,12 @@ export default class Notifications extends React.Component { "vectorRuleId": "_keywords", "description": ( - { _t('Messages containing keywords', - {}, - { 'span': (sub) => - {sub}, - }, - )} + { _t('Messages containing keywords', + {}, + { 'span': (sub) => + {sub}, + }, + )} ), "vectorState": self.state.vectorContentRules.vectorState, @@ -743,8 +743,8 @@ export default class Notifications extends React.Component { emailNotificationsRow(address, label) { return ; + onChange={this.onEnableEmailNotificationsChange.bind(this, address)} + label={label} key={`emailNotif_${label}`} />; } render() { @@ -757,8 +757,8 @@ export default class Notifications extends React.Component { let masterPushRuleDiv; if (this.state.masterPushRule) { masterPushRuleDiv = ; + onChange={this.onEnableNotificationsChange} + label={_t('Enable notifications for this account')} />; } let clearNotificationsButton; @@ -874,16 +874,16 @@ export default class Notifications extends React.Component { { spinner } + onChange={this.onEnableDesktopNotificationsChange} + label={_t('Enable desktop notifications for this session')} /> + onChange={this.onEnableDesktopNotificationBodyChange} + label={_t('Show message in desktop notification')} /> + onChange={this.onEnableAudioNotificationsChange} + label={_t('Enable audible notifications for this session')} /> { emailNotificationsRows } diff --git a/src/components/views/settings/ProfileSettings.js b/src/components/views/settings/ProfileSettings.js index 971b868751..9ecf369eba 100644 --- a/src/components/views/settings/ProfileSettings.js +++ b/src/components/views/settings/ProfileSettings.js @@ -170,8 +170,12 @@ export default class ProfileSettings extends React.Component { noValidate={true} className="mx_ProfileSettings_profileForm" > - +
    {_t("Profile")} diff --git a/src/components/views/settings/SetIdServer.js b/src/components/views/settings/SetIdServer.tsx similarity index 89% rename from src/components/views/settings/SetIdServer.js rename to src/components/views/settings/SetIdServer.tsx index fa2a36476d..05d1f83387 100644 --- a/src/components/views/settings/SetIdServer.js +++ b/src/components/views/settings/SetIdServer.tsx @@ -1,5 +1,5 @@ /* -Copyright 2019 The Matrix.org Foundation C.I.C. +Copyright 2019-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. @@ -16,7 +16,6 @@ limitations under the License. import url from 'url'; import React from 'react'; -import PropTypes from 'prop-types'; import {_t} from "../../../languageHandler"; import * as sdk from '../../../index'; import {MatrixClientPeg} from "../../../MatrixClientPeg"; @@ -28,6 +27,7 @@ import {abbreviateUrl, unabbreviateUrl} from "../../../utils/UrlUtils"; import { getDefaultIdentityServerUrl, doesIdentityServerHaveTerms } from '../../../utils/IdentityServerUtils'; import {timeout} from "../../../utils/promise"; import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { ActionPayload } from '../../../dispatcher/payloads'; // We'll wait up to this long when checking for 3PID bindings on the IS. const REACHABILITY_TIMEOUT = 10000; // ms @@ -59,16 +59,28 @@ async function checkIdentityServerUrl(u) { } } -@replaceableComponent("views.settings.SetIdServer") -export default class SetIdServer extends React.Component { - static propTypes = { - // Whether or not the ID server is missing terms. This affects the text - // shown to the user. - missingTerms: PropTypes.bool, - }; +interface IProps { + // Whether or not the ID server is missing terms. This affects the text + // shown to the user. + missingTerms: boolean; +} - constructor() { - super(); +interface IState { + defaultIdServer?: string; + currentClientIdServer: string; + idServer?: string; + error?: string; + busy: boolean; + disconnectBusy: boolean; + checking: boolean; +} + +@replaceableComponent("views.settings.SetIdServer") +export default class SetIdServer extends React.Component { + private dispatcherRef: string; + + constructor(props) { + super(props); let defaultIdServer = ''; if (!MatrixClientPeg.get().getIdentityServerUrl() && getDefaultIdentityServerUrl()) { @@ -96,7 +108,7 @@ export default class SetIdServer extends React.Component { dis.unregister(this.dispatcherRef); } - onAction = (payload) => { + private onAction = (payload: ActionPayload) => { // We react to changes in the ID server in the event the user is staring at this form // when changing their identity server on another device. if (payload.action !== "id_server_changed") return; @@ -106,13 +118,13 @@ export default class SetIdServer extends React.Component { }); }; - _onIdentityServerChanged = (ev) => { + private onIdentityServerChanged = (ev) => { const u = ev.target.value; this.setState({idServer: u}); }; - _getTooltip = () => { + private getTooltip = () => { if (this.state.checking) { const InlineSpinner = sdk.getComponent('views.elements.InlineSpinner'); return
    @@ -126,11 +138,11 @@ export default class SetIdServer extends React.Component { } }; - _idServerChangeEnabled = () => { + private idServerChangeEnabled = () => { return !!this.state.idServer && !this.state.busy; }; - _saveIdServer = (fullUrl) => { + private saveIdServer = (fullUrl) => { // Account data change will update localstorage, client, etc through dispatcher MatrixClientPeg.get().setAccountData("m.identity_server", { base_url: fullUrl, @@ -143,7 +155,7 @@ export default class SetIdServer extends React.Component { }); }; - _checkIdServer = async (e) => { + private checkIdServer = async (e) => { e.preventDefault(); const { idServer, currentClientIdServer } = this.state; @@ -166,14 +178,14 @@ export default class SetIdServer extends React.Component { // Double check that the identity server even has terms of service. const hasTerms = await doesIdentityServerHaveTerms(fullUrl); if (!hasTerms) { - const [confirmed] = await this._showNoTermsWarning(fullUrl); + const [confirmed] = await this.showNoTermsWarning(fullUrl); save = confirmed; } // Show a general warning, possibly with details about any bound // 3PIDs that would be left behind. if (save && currentClientIdServer && fullUrl !== currentClientIdServer) { - const [confirmed] = await this._showServerChangeWarning({ + const [confirmed] = await this.showServerChangeWarning({ title: _t("Change identity server"), unboundMessage: _t( "Disconnect from the identity server and " + @@ -189,7 +201,7 @@ export default class SetIdServer extends React.Component { } if (save) { - this._saveIdServer(fullUrl); + this.saveIdServer(fullUrl); } } catch (e) { console.error(e); @@ -204,7 +216,7 @@ export default class SetIdServer extends React.Component { }); }; - _showNoTermsWarning(fullUrl) { + private showNoTermsWarning(fullUrl) { const QuestionDialog = sdk.getComponent("views.dialogs.QuestionDialog"); const { finished } = Modal.createTrackedDialog('No Terms Warning', '', QuestionDialog, { title: _t("Identity server has no terms of service"), @@ -223,10 +235,10 @@ export default class SetIdServer extends React.Component { return finished; } - _onDisconnectClicked = async () => { + private onDisconnectClicked = async () => { this.setState({disconnectBusy: true}); try { - const [confirmed] = await this._showServerChangeWarning({ + const [confirmed] = await this.showServerChangeWarning({ title: _t("Disconnect identity server"), unboundMessage: _t( "Disconnect from the identity server ?", {}, @@ -235,14 +247,14 @@ export default class SetIdServer extends React.Component { button: _t("Disconnect"), }); if (confirmed) { - this._disconnectIdServer(); + this.disconnectIdServer(); } } finally { this.setState({disconnectBusy: false}); } }; - async _showServerChangeWarning({ title, unboundMessage, button }) { + private async showServerChangeWarning({ title, unboundMessage, button }) { const { currentClientIdServer } = this.state; let threepids = []; @@ -318,7 +330,7 @@ export default class SetIdServer extends React.Component { return finished; } - _disconnectIdServer = () => { + private disconnectIdServer = () => { // Account data change will update localstorage, client, etc through dispatcher MatrixClientPeg.get().setAccountData("m.identity_server", { base_url: null, // clear @@ -371,7 +383,7 @@ export default class SetIdServer extends React.Component { let discoSection; if (idServerUrl) { - let discoButtonContent = _t("Disconnect"); + let discoButtonContent: React.ReactNode = _t("Disconnect"); let discoBodyText = _t( "Disconnecting from your identity server will mean you " + "won't be discoverable by other users and you won't be " + @@ -391,14 +403,14 @@ export default class SetIdServer extends React.Component { } discoSection =
    {discoBodyText} - + {discoButtonContent}
    ; } return ( - + {sectionTitle} @@ -411,15 +423,15 @@ export default class SetIdServer extends React.Component { autoComplete="off" placeholder={this.state.defaultIdServer} value={this.state.idServer} - onChange={this._onIdentityServerChanged} - tooltipContent={this._getTooltip()} + onChange={this.onIdentityServerChanged} + tooltipContent={this.getTooltip()} tooltipClassName="mx_SetIdServer_tooltip" disabled={this.state.busy} forceValidity={this.state.error ? false : null} /> {_t("Change")} {discoSection} diff --git a/src/components/views/settings/account/EmailAddresses.js b/src/components/views/settings/account/EmailAddresses.js index 1ebd374173..a36369cf88 100644 --- a/src/components/views/settings/account/EmailAddresses.js +++ b/src/components/views/settings/account/EmailAddresses.js @@ -90,12 +90,18 @@ export class ExistingEmailAddress extends React.Component { {_t("Remove %(email)s?", {email: this.props.email.address} )} - + {_t("Remove")} - + {_t("Cancel")}
    @@ -228,21 +234,28 @@ export default class EmailAddresses extends React.Component { ); if (this.state.verifying) { addButton = ( -
    -
    {_t("We've sent you an email to verify your address. Please follow the instructions there and then click the button below.")}
    - - {_t("Continue")} - -
    +
    +
    {_t("We've sent you an email to verify your address. Please follow the instructions there and then click the button below.")}
    + + {_t("Continue")} + +
    ); } return (
    {existingEmailElements} -
    + {_t("Remove %(phone)s?", {phone: this.props.msisdn.address})} - + {_t("Remove")} - + {_t("Cancel")}
    @@ -246,8 +252,11 @@ export default class PhoneNumbers extends React.Component { value={this.state.newPhoneNumberCode} onChange={this._onChangeNewPhoneNumberCode} /> - + {_t("Continue")} diff --git a/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.js b/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.js index cd4a043622..139cfd5fbd 100644 --- a/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.js +++ b/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.js @@ -80,9 +80,11 @@ export default class GeneralRoomSettingsTab extends React.Component { flairSection = <> {_t("Flair")}
    - +
    ; } @@ -97,8 +99,8 @@ export default class GeneralRoomSettingsTab extends React.Component {
    {_t("Room Addresses")}
    + canSetCanonicalAlias={canSetCanonical} canSetAliases={canSetAliases} + canonicalAliasEvent={canonicalAliasEv} aliasEvents={aliasEvents} />
    {_t("Other")}
    { flairSection } diff --git a/src/components/views/settings/tabs/room/NotificationSettingsTab.js b/src/components/views/settings/tabs/room/NotificationSettingsTab.js index baefb5ae20..fa56fa2cb6 100644 --- a/src/components/views/settings/tabs/room/NotificationSettingsTab.js +++ b/src/components/views/settings/tabs/room/NotificationSettingsTab.js @@ -155,7 +155,7 @@ export default class NotificationsSettingsTab extends React.Component {
    {_t("Notification sound")}: {this.state.currentSound}
    - {_t("Reset")} + {_t("Reset")}
    @@ -167,11 +167,11 @@ export default class NotificationsSettingsTab extends React.Component { {currentUploadedFile} - {_t("Browse")} + {_t("Browse")} - {_t("Save")} + {_t("Save")}
    diff --git a/src/components/views/settings/tabs/room/RolesRoomSettingsTab.js b/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx similarity index 89% rename from src/components/views/settings/tabs/room/RolesRoomSettingsTab.js rename to src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx index 59a175906d..4fa521f598 100644 --- a/src/components/views/settings/tabs/room/RolesRoomSettingsTab.js +++ b/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx @@ -1,5 +1,5 @@ /* -Copyright 2019, 2021 The Matrix.org Foundation C.I.C. +Copyright 2019-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. @@ -15,7 +15,6 @@ limitations under the License. */ import React from 'react'; -import PropTypes from 'prop-types'; import {_t, _td} from "../../../../../languageHandler"; import {MatrixClientPeg} from "../../../../../MatrixClientPeg"; import * as sdk from "../../../../.."; @@ -23,6 +22,9 @@ import AccessibleButton from "../../../elements/AccessibleButton"; import Modal from "../../../../../Modal"; import {replaceableComponent} from "../../../../../utils/replaceableComponent"; import {EventType} from "matrix-js-sdk/src/@types/event"; +import { RoomMember } from "matrix-js-sdk/src/models/room-member"; +import { MatrixEvent } from "matrix-js-sdk/src/models/event"; +import { RoomState } from "matrix-js-sdk/src/models/room-state"; const plEventsToLabels = { // These will be translated for us later. @@ -63,15 +65,15 @@ function parseIntWithDefault(val, def) { return isNaN(res) ? def : res; } -export class BannedUser extends React.Component { - static propTypes = { - canUnban: PropTypes.bool, - member: PropTypes.object.isRequired, // js-sdk RoomMember - by: PropTypes.string.isRequired, - reason: PropTypes.string, - }; +interface IBannedUserProps { + canUnban?: boolean; + member: RoomMember; + by: string; + reason?: string; +} - _onUnbanClick = (e) => { +export class BannedUser extends React.Component { + private onUnbanClick = (e) => { MatrixClientPeg.get().unban(this.props.member.roomId, this.props.member.userId).catch((err) => { const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); console.error("Failed to unban: " + err); @@ -87,8 +89,10 @@ export class BannedUser extends React.Component { if (this.props.canUnban) { unbanButton = ( - + { _t('Unban') } ); @@ -107,29 +111,29 @@ export class BannedUser extends React.Component { } } -@replaceableComponent("views.settings.tabs.room.RolesRoomSettingsTab") -export default class RolesRoomSettingsTab extends React.Component { - static propTypes = { - roomId: PropTypes.string.isRequired, - }; +interface IProps { + roomId: string; +} - componentDidMount(): void { - MatrixClientPeg.get().on("RoomState.members", this._onRoomMembership); +@replaceableComponent("views.settings.tabs.room.RolesRoomSettingsTab") +export default class RolesRoomSettingsTab extends React.Component { + componentDidMount() { + MatrixClientPeg.get().on("RoomState.members", this.onRoomMembership); } - componentWillUnmount(): void { + componentWillUnmount() { const client = MatrixClientPeg.get(); if (client) { - client.removeListener("RoomState.members", this._onRoomMembership); + client.removeListener("RoomState.members", this.onRoomMembership); } } - _onRoomMembership = (event, state, member) => { + private onRoomMembership = (event: MatrixEvent, state: RoomState, member: RoomMember) => { if (state.roomId !== this.props.roomId) return; this.forceUpdate(); }; - _populateDefaultPlEvents(eventsSection, stateLevel, eventsLevel) { + private populateDefaultPlEvents(eventsSection: Record, stateLevel: number, eventsLevel: number) { for (const desiredEvent of Object.keys(plEventsToShow)) { if (!(desiredEvent in eventsSection)) { eventsSection[desiredEvent] = (plEventsToShow[desiredEvent].isState ? stateLevel : eventsLevel); @@ -137,7 +141,7 @@ export default class RolesRoomSettingsTab extends React.Component { } } - _onPowerLevelsChanged = (value, powerLevelKey) => { + private onPowerLevelsChanged = (inputValue: string, powerLevelKey: string) => { const client = MatrixClientPeg.get(); const room = client.getRoom(this.props.roomId); const plEvent = room.currentState.getStateEvents('m.room.power_levels', ''); @@ -148,7 +152,7 @@ export default class RolesRoomSettingsTab extends React.Component { const eventsLevelPrefix = "event_levels_"; - value = parseInt(value); + const value = parseInt(inputValue); if (powerLevelKey.startsWith(eventsLevelPrefix)) { // deep copy "events" object, Object.assign itself won't deep copy @@ -182,7 +186,7 @@ export default class RolesRoomSettingsTab extends React.Component { }); }; - _onUserPowerLevelChanged = (value, powerLevelKey) => { + private onUserPowerLevelChanged = (value: string, powerLevelKey: string) => { const client = MatrixClientPeg.get(); const room = client.getRoom(this.props.roomId); const plEvent = room.currentState.getStateEvents('m.room.power_levels', ''); @@ -266,7 +270,7 @@ export default class RolesRoomSettingsTab extends React.Component { currentUserLevel = defaultUserLevel; } - this._populateDefaultPlEvents( + this.populateDefaultPlEvents( eventsLevels, parseIntWithDefault(plContent.state_default, powerLevelDescriptors.state_default.defaultValue), parseIntWithDefault(plContent.events_default, powerLevelDescriptors.events_default.defaultValue), @@ -288,7 +292,7 @@ export default class RolesRoomSettingsTab extends React.Component { label={user} key={user} powerLevelKey={user} // Will be sent as the second parameter to `onChange` - onChange={this._onUserPowerLevelChanged} + onChange={this.onUserPowerLevelChanged} />, ); } else if (userLevels[user] < defaultUserLevel) { // muted @@ -299,7 +303,7 @@ export default class RolesRoomSettingsTab extends React.Component { label={user} key={user} powerLevelKey={user} // Will be sent as the second parameter to `onChange` - onChange={this._onUserPowerLevelChanged} + onChange={this.onUserPowerLevelChanged} />, ); } @@ -345,8 +349,9 @@ export default class RolesRoomSettingsTab extends React.Component { if (sender) bannedBy = sender.name; return ( + member={member} reason={banEvent.reason} + by={bannedBy} + /> ); })} @@ -373,7 +378,7 @@ export default class RolesRoomSettingsTab extends React.Component { usersDefault={defaultUserLevel} disabled={!canChangeLevels || currentUserLevel < value} powerLevelKey={key} // Will be sent as the second parameter to `onChange` - onChange={this._onPowerLevelsChanged} + onChange={this.onPowerLevelsChanged} />
    ; }); @@ -398,7 +403,7 @@ export default class RolesRoomSettingsTab extends React.Component { usersDefault={defaultUserLevel} disabled={!canChangeLevels || currentUserLevel < eventsLevels[eventType]} powerLevelKey={"event_levels_" + eventType} - onChange={this._onPowerLevelsChanged} + onChange={this.onPowerLevelsChanged} />
    ); diff --git a/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.js b/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx similarity index 79% rename from src/components/views/settings/tabs/room/SecurityRoomSettingsTab.js rename to src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx index ce883c6d23..02bbcfb751 100644 --- a/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.js +++ b/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx @@ -1,5 +1,5 @@ /* -Copyright 2019 New Vector Ltd +Copyright 2019-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. @@ -15,7 +15,7 @@ limitations under the License. */ import React from 'react'; -import PropTypes from 'prop-types'; +import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import {_t} from "../../../../../languageHandler"; import {MatrixClientPeg} from "../../../../../MatrixClientPeg"; import * as sdk from "../../../../.."; @@ -26,64 +26,92 @@ import StyledRadioGroup from '../../../elements/StyledRadioGroup'; import {SettingLevel} from "../../../../../settings/SettingLevel"; import SettingsStore from "../../../../../settings/SettingsStore"; import {UIFeature} from "../../../../../settings/UIFeature"; -import {replaceableComponent} from "../../../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../../../utils/replaceableComponent"; + +// Knock and private are reserved keywords which are not yet implemented. +enum JoinRule { + Public = "public", + Knock = "knock", + Invite = "invite", + Private = "private", +} + +enum GuestAccess { + CanJoin = "can_join", + Forbidden = "forbidden", +} + +enum HistoryVisibility { + Invited = "invited", + Joined = "joined", + Shared = "shared", + WorldReadable = "world_readable", +} + +interface IProps { + roomId: string; +} + +interface IState { + joinRule: JoinRule; + guestAccess: GuestAccess; + history: HistoryVisibility; + hasAliases: boolean; + encrypted: boolean; +} @replaceableComponent("views.settings.tabs.room.SecurityRoomSettingsTab") -export default class SecurityRoomSettingsTab extends React.Component { - static propTypes = { - roomId: PropTypes.string.isRequired, - }; - - constructor() { - super(); +export default class SecurityRoomSettingsTab extends React.Component { + constructor(props) { + super(props); this.state = { - joinRule: "invite", - guestAccess: "can_join", - history: "shared", + joinRule: JoinRule.Invite, + guestAccess: GuestAccess.CanJoin, + history: HistoryVisibility.Shared, hasAliases: false, encrypted: false, }; } // TODO: [REACT-WARNING] Move this to constructor - async UNSAFE_componentWillMount(): void { // eslint-disable-line camelcase - MatrixClientPeg.get().on("RoomState.events", this._onStateEvent); + async UNSAFE_componentWillMount() { // eslint-disable-line camelcase + MatrixClientPeg.get().on("RoomState.events", this.onStateEvent); const room = MatrixClientPeg.get().getRoom(this.props.roomId); const state = room.currentState; - const joinRule = this._pullContentPropertyFromEvent( + const joinRule: JoinRule = this.pullContentPropertyFromEvent( state.getStateEvents("m.room.join_rules", ""), 'join_rule', - 'invite', + JoinRule.Invite, ); - const guestAccess = this._pullContentPropertyFromEvent( + const guestAccess: GuestAccess = this.pullContentPropertyFromEvent( state.getStateEvents("m.room.guest_access", ""), 'guest_access', - 'forbidden', + GuestAccess.Forbidden, ); - const history = this._pullContentPropertyFromEvent( + const history: HistoryVisibility = this.pullContentPropertyFromEvent( state.getStateEvents("m.room.history_visibility", ""), 'history_visibility', - 'shared', + HistoryVisibility.Shared, ); const encrypted = MatrixClientPeg.get().isRoomEncrypted(this.props.roomId); this.setState({joinRule, guestAccess, history, encrypted}); - const hasAliases = await this._hasAliases(); + const hasAliases = await this.hasAliases(); this.setState({hasAliases}); } - _pullContentPropertyFromEvent(event, key, defaultValue) { + private pullContentPropertyFromEvent(event: MatrixEvent, key: string, defaultValue: T): T { if (!event || !event.getContent()) return defaultValue; return event.getContent()[key] || defaultValue; } - componentWillUnmount(): void { - MatrixClientPeg.get().removeListener("RoomState.events", this._onStateEvent); + componentWillUnmount() { + MatrixClientPeg.get().removeListener("RoomState.events", this.onStateEvent); } - _onStateEvent = (e) => { + private onStateEvent = (e: MatrixEvent) => { const refreshWhenTypes = [ 'm.room.join_rules', 'm.room.guest_access', @@ -93,7 +121,7 @@ export default class SecurityRoomSettingsTab extends React.Component { if (refreshWhenTypes.includes(e.getType())) this.forceUpdate(); }; - _onEncryptionChange = (e) => { + private onEncryptionChange = (e: React.ChangeEvent) => { Modal.createTrackedDialog('Enable encryption', '', QuestionDialog, { title: _t('Enable encryption?'), description: _t( @@ -102,10 +130,9 @@ export default class SecurityRoomSettingsTab extends React.Component { "may prevent many bots and bridges from working correctly. Learn more about encryption.", {}, { - 'a': (sub) => { - return {sub}; - }, + a: sub => {sub}, }, ), onFinished: (confirm) => { @@ -127,12 +154,12 @@ export default class SecurityRoomSettingsTab extends React.Component { }); }; - _fixGuestAccess = (e) => { + private fixGuestAccess = (e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation(); - const joinRule = "invite"; - const guestAccess = "can_join"; + const joinRule = JoinRule.Invite; + const guestAccess = GuestAccess.CanJoin; const beforeJoinRule = this.state.joinRule; const beforeGuestAccess = this.state.guestAccess; @@ -149,7 +176,7 @@ export default class SecurityRoomSettingsTab extends React.Component { }); }; - _onRoomAccessRadioToggle = (roomAccess) => { + private onRoomAccessRadioToggle = (roomAccess: string) => { // join_rule // INVITE | PUBLIC // ----------------------+---------------- @@ -163,20 +190,20 @@ export default class SecurityRoomSettingsTab extends React.Component { // invite them, you clearly want them to join, whether they're a // guest or not. In practice, guest_access should probably have // been implemented as part of the join_rules enum. - let joinRule = "invite"; - let guestAccess = "can_join"; + let joinRule = JoinRule.Invite; + let guestAccess = GuestAccess.CanJoin; switch (roomAccess) { case "invite_only": // no change - use defaults above break; case "public_no_guests": - joinRule = "public"; - guestAccess = "forbidden"; + joinRule = JoinRule.Public; + guestAccess = GuestAccess.Forbidden; break; case "public_with_guests": - joinRule = "public"; - guestAccess = "can_join"; + joinRule = JoinRule.Public; + guestAccess = GuestAccess.CanJoin; break; } @@ -195,7 +222,7 @@ export default class SecurityRoomSettingsTab extends React.Component { }); }; - _onHistoryRadioToggle = (history) => { + private onHistoryRadioToggle = (history: HistoryVisibility) => { const beforeHistory = this.state.history; this.setState({history: history}); MatrixClientPeg.get().sendStateEvent(this.props.roomId, "m.room.history_visibility", { @@ -206,11 +233,11 @@ export default class SecurityRoomSettingsTab extends React.Component { }); }; - _updateBlacklistDevicesFlag = (checked) => { + private updateBlacklistDevicesFlag = (checked: boolean) => { MatrixClientPeg.get().getRoom(this.props.roomId).setBlacklistUnverifiedDevices(checked); }; - async _hasAliases() { + private async hasAliases(): Promise { const cli = MatrixClientPeg.get(); if (await cli.doesServerSupportUnstableFeature("org.matrix.msc2432")) { const response = await cli.unstableGetLocalAliases(this.props.roomId); @@ -224,7 +251,7 @@ export default class SecurityRoomSettingsTab extends React.Component { } } - _renderRoomAccess() { + private renderRoomAccess() { const client = MatrixClientPeg.get(); const room = client.getRoom(this.props.roomId); const joinRule = this.state.joinRule; @@ -240,7 +267,7 @@ export default class SecurityRoomSettingsTab extends React.Component { {_t("Guests cannot join this room even if explicitly invited.")}  - {_t("Click here to fix")} + {_t("Click here to fix")}
    ); @@ -265,7 +292,7 @@ export default class SecurityRoomSettingsTab extends React.Component { ; } @@ -356,7 +383,7 @@ export default class SecurityRoomSettingsTab extends React.Component { let historySection = (<> {_t("Who can read history?")}
    - {this._renderHistory()} + {this.renderHistory()}
    ); if (!SettingsStore.getValue(UIFeature.RoomHistorySettings)) { @@ -373,15 +400,16 @@ export default class SecurityRoomSettingsTab extends React.Component {
    {_t("Once enabled, encryption cannot be disabled.")}
    - +
    {encryptionSettings}
    {_t("Who can access this room?")}
    - {this._renderRoomAccess()} + {this.renderRoomAccess()}
    {historySection} diff --git a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js index b1ad9f3d23..5118414903 100644 --- a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js @@ -192,7 +192,11 @@ export default class GeneralUserSettingsTab extends React.Component { SettingsStore.setValue("language", null, SettingLevel.DEVICE, newLanguage); this.setState({language: newLanguage}); - PlatformPeg.get().reload(); + const platform = PlatformPeg.get(); + if (platform) { + platform.setLanguage(newLanguage); + platform.reload(); + } }; _onSpellCheckLanguagesChange = (languages) => { @@ -319,8 +323,11 @@ export default class GeneralUserSettingsTab extends React.Component { return (
    {_t("Language and region")} - +
    ); } @@ -329,8 +336,10 @@ export default class GeneralUserSettingsTab extends React.Component { return (
    {_t("Spell check dictionaries")} - +
    ); } diff --git a/src/components/views/settings/tabs/user/HelpUserSettingsTab.js b/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx similarity index 64% rename from src/components/views/settings/tabs/user/HelpUserSettingsTab.js rename to src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx index e16ee686f5..3fa0be478c 100644 --- a/src/components/views/settings/tabs/user/HelpUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx @@ -1,6 +1,5 @@ /* -Copyright 2019 New Vector Ltd -Copyright 2020 The Matrix.org Foundation C.I.C. +Copyright 2019-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. @@ -16,27 +15,37 @@ limitations under the License. */ import React from 'react'; -import PropTypes from 'prop-types'; import {_t, getCurrentLanguage} from "../../../../../languageHandler"; import {MatrixClientPeg} from "../../../../../MatrixClientPeg"; import AccessibleButton from "../../../elements/AccessibleButton"; +import AccessibleTooltipButton from '../../../elements/AccessibleTooltipButton'; import SdkConfig from "../../../../../SdkConfig"; import createRoom from "../../../../../createRoom"; import Modal from "../../../../../Modal"; -import * as sdk from "../../../../../"; +import * as sdk from "../../../../.."; import PlatformPeg from "../../../../../PlatformPeg"; import * as KeyboardShortcuts from "../../../../../accessibility/KeyboardShortcuts"; import UpdateCheckButton from "../../UpdateCheckButton"; -import {replaceableComponent} from "../../../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../../../utils/replaceableComponent"; +import { copyPlaintext } from "../../../../../utils/strings"; +import * as ContextMenu from "../../../../structures/ContextMenu"; +import { toRightOf } from "../../../../structures/ContextMenu"; + +interface IProps { + closeSettingsFn: () => {}; +} + +interface IState { + appVersion: string; + canUpdate: boolean; +} @replaceableComponent("views.settings.tabs.user.HelpUserSettingsTab") -export default class HelpUserSettingsTab extends React.Component { - static propTypes = { - closeSettingsFn: PropTypes.func.isRequired, - }; +export default class HelpUserSettingsTab extends React.Component { + protected closeCopiedTooltip: () => void; - constructor() { - super(); + constructor(props) { + super(props); this.state = { appVersion: null, @@ -53,7 +62,13 @@ export default class HelpUserSettingsTab extends React.Component { }); } - _onClearCacheAndReload = (e) => { + componentWillUnmount() { + // if the Copied tooltip is open then get rid of it, there are ways to close the modal which wouldn't close + // the tooltip otherwise, such as pressing Escape + if (this.closeCopiedTooltip) this.closeCopiedTooltip(); + } + + private onClearCacheAndReload = (e) => { if (!PlatformPeg.get()) return; // Dev note: please keep this log line, it's useful when troubleshooting a MatrixClient suddenly @@ -65,7 +80,7 @@ export default class HelpUserSettingsTab extends React.Component { }); }; - _onBugReport = (e) => { + private onBugReport = (e) => { const BugReportDialog = sdk.getComponent("dialogs.BugReportDialog"); if (!BugReportDialog) { return; @@ -73,7 +88,7 @@ export default class HelpUserSettingsTab extends React.Component { Modal.createTrackedDialog('Bug Report Dialog', '', BugReportDialog, {}); }; - _onStartBotChat = (e) => { + private onStartBotChat = (e) => { this.props.closeSettingsFn(); createRoom({ dmUserId: SdkConfig.get().welcomeUserId, @@ -81,7 +96,7 @@ export default class HelpUserSettingsTab extends React.Component { }); }; - _showSpoiler = (event) => { + private showSpoiler = (event) => { const target = event.target; target.innerHTML = target.getAttribute('data-spoiler'); @@ -93,7 +108,7 @@ export default class HelpUserSettingsTab extends React.Component { selection.addRange(range); }; - _renderLegal() { + private renderLegal() { const tocLinks = SdkConfig.get().terms_and_conditions_links; if (!tocLinks) return null; @@ -114,7 +129,7 @@ export default class HelpUserSettingsTab extends React.Component { ); } - _renderCredits() { + private renderCredits() { // Note: This is not translated because it is legal text. // Also,   is ugly but necessary. return ( @@ -122,34 +137,48 @@ export default class HelpUserSettingsTab extends React.Component { {_t("Credits")}
    ); } + onAccessTokenCopyClick = async (e) => { + e.preventDefault(); + const target = e.target; // copy target before we go async and React throws it away + + const successful = await copyPlaintext(MatrixClientPeg.get().getAccessToken()); + const buttonRect = target.getBoundingClientRect(); + const GenericTextContextMenu = sdk.getComponent('context_menus.GenericTextContextMenu'); + const {close} = ContextMenu.createMenu(GenericTextContextMenu, { + ...toRightOf(buttonRect, 2), + message: successful ? _t('Copied!') : _t('Failed to copy'), + }); + this.closeCopiedTooltip = target.onmouseleave = close; + } + render() { const brand = SdkConfig.get().brand; @@ -188,7 +217,7 @@ export default class HelpUserSettingsTab extends React.Component { }, )}
    - + {_t("Chat with %(brand)s Bot", { brand })}
    @@ -212,28 +241,27 @@ export default class HelpUserSettingsTab extends React.Component {
    {_t('Bug reporting')}
    - { - _t( "If you've submitted a bug via GitHub, debug logs can help " + - "us track down the problem. Debug logs contain application " + - "usage data including your username, the IDs or aliases of " + - "the rooms or groups you have visited and the usernames of " + - "other users. They do not contain messages.", - ) - } + {_t( + "If you've submitted a bug via GitHub, debug logs can help " + + "us track down the problem. Debug logs contain application " + + "usage data including your username, the IDs or aliases of " + + "the rooms or groups you have visited and the usernames of " + + "other users. They do not contain messages.", + )}
    - + {_t("Submit debug logs")}
    - { - _t( "To report a Matrix-related security issue, please read the Matrix.org " + - "Security Disclosure Policy.", {}, - { - 'a': (sub) => - {sub}, - }) - } + {_t( + "To report a Matrix-related security issue, please read the Matrix.org " + + "Security Disclosure Policy.", {}, + { + a: sub => {sub}, + }, + )}
    ); @@ -260,20 +288,29 @@ export default class HelpUserSettingsTab extends React.Component { {updateButton}
    - {this._renderLegal()} - {this._renderCredits()} + {this.renderLegal()} + {this.renderCredits()}
    {_t("Advanced")}
    {_t("Homeserver is")} {MatrixClientPeg.get().getHomeserverUrl()}
    {_t("Identity Server is")} {MatrixClientPeg.get().getIdentityServerUrl()}
    - {_t("Access Token:") + ' '} - - <{ _t("click to reveal") }> - +
    +
    + {_t("Access Token")}
    + {_t("Your access token gives full access to your account." + + " Do not share it with anyone." )} +
    + {MatrixClientPeg.get().getAccessToken()} + +
    +

    - + {_t("Clear cache and reload")}
    diff --git a/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.js b/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.tsx similarity index 90% rename from src/components/views/settings/tabs/user/MjolnirUserSettingsTab.js rename to src/components/views/settings/tabs/user/MjolnirUserSettingsTab.tsx index 91f6728a7a..6997defea9 100644 --- a/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.tsx @@ -1,5 +1,5 @@ /* -Copyright 2019, 2020 The Matrix.org Foundation C.I.C. +Copyright 2019-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. @@ -25,10 +25,16 @@ import {MatrixClientPeg} from "../../../../../MatrixClientPeg"; import * as sdk from "../../../../../index"; import {replaceableComponent} from "../../../../../utils/replaceableComponent"; +interface IState { + busy: boolean; + newPersonalRule: string; + newList: string; +} + @replaceableComponent("views.settings.tabs.user.MjolnirUserSettingsTab") -export default class MjolnirUserSettingsTab extends React.Component { - constructor() { - super(); +export default class MjolnirUserSettingsTab extends React.Component<{}, IState> { + constructor(props) { + super(props); this.state = { busy: false, @@ -37,15 +43,15 @@ export default class MjolnirUserSettingsTab extends React.Component { }; } - _onPersonalRuleChanged = (e) => { + private onPersonalRuleChanged = (e) => { this.setState({newPersonalRule: e.target.value}); }; - _onNewListChanged = (e) => { + private onNewListChanged = (e) => { this.setState({newList: e.target.value}); }; - _onAddPersonalRule = async (e) => { + private onAddPersonalRule = async (e) => { e.preventDefault(); e.stopPropagation(); @@ -72,7 +78,7 @@ export default class MjolnirUserSettingsTab extends React.Component { } }; - _onSubscribeList = async (e) => { + private onSubscribeList = async (e) => { e.preventDefault(); e.stopPropagation(); @@ -94,7 +100,7 @@ export default class MjolnirUserSettingsTab extends React.Component { } }; - async _removePersonalRule(rule: ListRule) { + private async removePersonalRule(rule: ListRule) { this.setState({busy: true}); try { const list = Mjolnir.sharedInstance().getPersonalList(); @@ -112,7 +118,7 @@ export default class MjolnirUserSettingsTab extends React.Component { } } - async _unsubscribeFromList(list: BanList) { + private async unsubscribeFromList(list: BanList) { this.setState({busy: true}); try { await Mjolnir.sharedInstance().unsubscribeFromList(list.roomId); @@ -130,7 +136,7 @@ export default class MjolnirUserSettingsTab extends React.Component { } } - _viewListRules(list: BanList) { + private viewListRules(list: BanList) { const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); const room = MatrixClientPeg.get().getRoom(list.roomId); @@ -161,7 +167,7 @@ export default class MjolnirUserSettingsTab extends React.Component { }); } - _renderPersonalBanListRules() { + private renderPersonalBanListRules() { const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); const list = Mjolnir.sharedInstance().getPersonalList(); @@ -174,7 +180,7 @@ export default class MjolnirUserSettingsTab extends React.Component {
  • this._removePersonalRule(rule)} + onClick={() => this.removePersonalRule(rule)} disabled={this.state.busy} > {_t("Remove")} @@ -192,7 +198,7 @@ export default class MjolnirUserSettingsTab extends React.Component { ); } - _renderSubscribedBanLists() { + private renderSubscribedBanLists() { const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); const personalList = Mjolnir.sharedInstance().getPersonalList(); @@ -209,14 +215,14 @@ export default class MjolnirUserSettingsTab extends React.Component {
  • this._unsubscribeFromList(list)} + onClick={() => this.unsubscribeFromList(list)} disabled={this.state.busy} > {_t("Unsubscribe")}   this._viewListRules(list)} + onClick={() => this.viewListRules(list)} disabled={this.state.busy} > {_t("View rules")} @@ -271,21 +277,21 @@ export default class MjolnirUserSettingsTab extends React.Component { )}
  • - {this._renderPersonalBanListRules()} + {this.renderPersonalBanListRules()}
    -
    + {_t("Ignore")} @@ -303,20 +309,20 @@ export default class MjolnirUserSettingsTab extends React.Component { )}
    - {this._renderSubscribedBanLists()} + {this.renderSubscribedBanLists()}
    - + {_t("Subscribe")} diff --git a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx similarity index 80% rename from src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js rename to src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx index 0cd3dd6698..f02c5c9ce0 100644 --- a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx @@ -1,5 +1,5 @@ /* -Copyright 2019 New Vector Ltd +Copyright 2019-2021 The Matrix.org Foundation C.I.C. Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,10 +23,24 @@ import Field from "../../../elements/Field"; import * as sdk from "../../../../.."; import PlatformPeg from "../../../../../PlatformPeg"; import {SettingLevel} from "../../../../../settings/SettingLevel"; -import {replaceableComponent} from "../../../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../../../utils/replaceableComponent"; + +interface IState { + autoLaunch: boolean; + autoLaunchSupported: boolean; + warnBeforeExit: boolean; + warnBeforeExitSupported: boolean; + alwaysShowMenuBarSupported: boolean; + alwaysShowMenuBar: boolean; + minimizeToTraySupported: boolean; + minimizeToTray: boolean; + autocompleteDelay: string; + readMarkerInViewThresholdMs: string; + readMarkerOutOfViewThresholdMs: string; +} @replaceableComponent("views.settings.tabs.user.PreferencesUserSettingsTab") -export default class PreferencesUserSettingsTab extends React.Component { +export default class PreferencesUserSettingsTab extends React.Component<{}, IState> { static ROOM_LIST_SETTINGS = [ 'breadcrumbs', ]; @@ -68,8 +82,8 @@ export default class PreferencesUserSettingsTab extends React.Component { // Autocomplete delay (niche text box) ]; - constructor() { - super(); + constructor(props) { + super(props); this.state = { autoLaunch: false, @@ -89,7 +103,7 @@ export default class PreferencesUserSettingsTab extends React.Component { }; } - async componentDidMount(): void { + async componentDidMount() { const platform = PlatformPeg.get(); const autoLaunchSupported = await platform.supportsAutoLaunch(); @@ -128,38 +142,38 @@ export default class PreferencesUserSettingsTab extends React.Component { }); } - _onAutoLaunchChange = (checked) => { + private onAutoLaunchChange = (checked: boolean) => { PlatformPeg.get().setAutoLaunchEnabled(checked).then(() => this.setState({autoLaunch: checked})); }; - _onWarnBeforeExitChange = (checked) => { + private onWarnBeforeExitChange = (checked: boolean) => { PlatformPeg.get().setWarnBeforeExit(checked).then(() => this.setState({warnBeforeExit: checked})); } - _onAlwaysShowMenuBarChange = (checked) => { + private onAlwaysShowMenuBarChange = (checked: boolean) => { PlatformPeg.get().setAutoHideMenuBarEnabled(!checked).then(() => this.setState({alwaysShowMenuBar: checked})); }; - _onMinimizeToTrayChange = (checked) => { + private onMinimizeToTrayChange = (checked: boolean) => { PlatformPeg.get().setMinimizeToTrayEnabled(checked).then(() => this.setState({minimizeToTray: checked})); }; - _onAutocompleteDelayChange = (e) => { + private onAutocompleteDelayChange = (e: React.ChangeEvent) => { this.setState({autocompleteDelay: e.target.value}); SettingsStore.setValue("autocompleteDelay", null, SettingLevel.DEVICE, e.target.value); }; - _onReadMarkerInViewThresholdMs = (e) => { + private onReadMarkerInViewThresholdMs = (e: React.ChangeEvent) => { this.setState({readMarkerInViewThresholdMs: e.target.value}); SettingsStore.setValue("readMarkerInViewThresholdMs", null, SettingLevel.DEVICE, e.target.value); }; - _onReadMarkerOutOfViewThresholdMs = (e) => { + private onReadMarkerOutOfViewThresholdMs = (e: React.ChangeEvent) => { this.setState({readMarkerOutOfViewThresholdMs: e.target.value}); SettingsStore.setValue("readMarkerOutOfViewThresholdMs", null, SettingLevel.DEVICE, e.target.value); }; - _renderGroup(settingIds) { + private renderGroup(settingIds: string[]): React.ReactNodeArray { const SettingsFlag = sdk.getComponent("views.elements.SettingsFlag"); return settingIds.filter(SettingsStore.isEnabled).map(i => { return ; @@ -171,7 +185,7 @@ export default class PreferencesUserSettingsTab extends React.Component { if (this.state.autoLaunchSupported) { autoLaunchOption = ; } @@ -179,7 +193,7 @@ export default class PreferencesUserSettingsTab extends React.Component { if (this.state.warnBeforeExitSupported) { warnBeforeExitOption = ; } @@ -187,7 +201,7 @@ export default class PreferencesUserSettingsTab extends React.Component { if (this.state.alwaysShowMenuBarSupported) { autoHideMenuOption = ; } @@ -195,7 +209,7 @@ export default class PreferencesUserSettingsTab extends React.Component { if (this.state.minimizeToTraySupported) { minimizeToTrayOption = ; } @@ -205,22 +219,22 @@ export default class PreferencesUserSettingsTab extends React.Component {
    {_t("Room list")} - {this._renderGroup(PreferencesUserSettingsTab.ROOM_LIST_SETTINGS)} + {this.renderGroup(PreferencesUserSettingsTab.ROOM_LIST_SETTINGS)}
    {_t("Composer")} - {this._renderGroup(PreferencesUserSettingsTab.COMPOSER_SETTINGS)} + {this.renderGroup(PreferencesUserSettingsTab.COMPOSER_SETTINGS)}
    {_t("Timeline")} - {this._renderGroup(PreferencesUserSettingsTab.TIMELINE_SETTINGS)} + {this.renderGroup(PreferencesUserSettingsTab.TIMELINE_SETTINGS)}
    {_t("General")} - {this._renderGroup(PreferencesUserSettingsTab.GENERAL_SETTINGS)} + {this.renderGroup(PreferencesUserSettingsTab.GENERAL_SETTINGS)} {minimizeToTrayOption} {autoHideMenuOption} {autoLaunchOption} @@ -229,17 +243,17 @@ export default class PreferencesUserSettingsTab extends React.Component { label={_t('Autocomplete delay (ms)')} type='number' value={this.state.autocompleteDelay} - onChange={this._onAutocompleteDelayChange} /> + onChange={this.onAutocompleteDelayChange} /> + onChange={this.onReadMarkerInViewThresholdMs} /> + onChange={this.onReadMarkerOutOfViewThresholdMs} />
    ); diff --git a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js index 8a70811399..53ed511b0a 100644 --- a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js @@ -255,15 +255,18 @@ export default class SecurityUserSettingsTab extends React.Component { _renderIgnoredUsers() { const {waitingUnignored, ignoredUserIds} = this.state; - if (!ignoredUserIds || ignoredUserIds.length === 0) return null; - - const userIds = ignoredUserIds - .map((u) => ); + const userIds = !ignoredUserIds?.length + ? _t('You have no ignored users.') + : ignoredUserIds.map((u) => { + return ( + + ); + }); return (
    diff --git a/src/components/views/settings/tabs/user/VoiceUserSettingsTab.js b/src/components/views/settings/tabs/user/VoiceUserSettingsTab.js index d8adab55f6..362059f8ed 100644 --- a/src/components/views/settings/tabs/user/VoiceUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/VoiceUserSettingsTab.js @@ -176,8 +176,8 @@ export default class VoiceUserSettingsTab extends React.Component { const defaultDevice = getDefaultDevice(audioOutputs); speakerDropdown = ( + value={this.state.activeAudioOutput || defaultDevice} + onChange={this._setAudioOutput}> {this._renderDeviceOptions(audioOutputs, 'audioOutput')} ); @@ -188,8 +188,8 @@ export default class VoiceUserSettingsTab extends React.Component { const defaultDevice = getDefaultDevice(audioInputs); microphoneDropdown = ( + value={this.state.activeAudioInput || defaultDevice} + onChange={this._setAudioInput}> {this._renderDeviceOptions(audioInputs, 'audioInput')} ); @@ -200,8 +200,8 @@ export default class VoiceUserSettingsTab extends React.Component { const defaultDevice = getDefaultDevice(videoInputs); webcamDropdown = ( + value={this.state.activeVideoInput || defaultDevice} + onChange={this._setVideoInput}> {this._renderDeviceOptions(videoInputs, 'videoInput')} ); diff --git a/src/components/views/spaces/SpaceTreeLevel.tsx b/src/components/views/spaces/SpaceTreeLevel.tsx index 6825d84013..e48e1d5dc2 100644 --- a/src/components/views/spaces/SpaceTreeLevel.tsx +++ b/src/components/views/spaces/SpaceTreeLevel.tsx @@ -297,15 +297,19 @@ export class SpaceItem extends React.PureComponent { const isActive = activeSpaces.includes(space); const itemClasses = classNames({ "mx_SpaceItem": true, + "mx_SpaceItem_narrow": isNarrow, "collapsed": collapsed, "hasSubSpaces": childSpaces && childSpaces.length, }); + + const isInvite = space.getMyMembership() === "invite"; const classes = classNames("mx_SpaceButton", { mx_SpaceButton_active: isActive, mx_SpaceButton_hasMenuOpen: !!this.state.contextMenuPosition, mx_SpaceButton_narrow: isNarrow, + mx_SpaceButton_invite: isInvite, }); - const notificationState = space.getMyMembership() === "invite" + const notificationState = isInvite ? StaticNotificationState.forSymbol("!", NotificationColor.Red) : SpaceStore.instance.getNotificationState(space.roomId); diff --git a/src/components/views/verification/VerificationCancelled.js b/src/components/views/verification/VerificationCancelled.js index 0bbaea1804..c57094d9b5 100644 --- a/src/components/views/verification/VerificationCancelled.js +++ b/src/components/views/verification/VerificationCancelled.js @@ -29,14 +29,14 @@ export default class VerificationCancelled extends React.Component { render() { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); return
    -

    {_t( - "The other party cancelled the verification.", - )}

    - +

    {_t( + "The other party cancelled the verification.", + )}

    +
    ; } } diff --git a/src/components/views/voice_messages/Clock.tsx b/src/components/views/voice_messages/Clock.tsx index 6c256957e9..23e6762c52 100644 --- a/src/components/views/voice_messages/Clock.tsx +++ b/src/components/views/voice_messages/Clock.tsx @@ -29,14 +29,20 @@ interface IState { * displayed, making it possible to see "82:29". */ @replaceableComponent("views.voice_messages.Clock") -export default class Clock extends React.PureComponent { +export default class Clock extends React.Component { public constructor(props) { super(props); } + shouldComponentUpdate(nextProps: Readonly, nextState: Readonly, nextContext: any): boolean { + const currentFloor = Math.floor(this.props.seconds); + const nextFloor = Math.floor(nextProps.seconds); + return currentFloor !== nextFloor; + } + public render() { const minutes = Math.floor(this.props.seconds / 60).toFixed(0).padStart(2, '0'); - const seconds = Math.round(this.props.seconds % 60).toFixed(0).padStart(2, '0'); // hide millis + const seconds = Math.floor(this.props.seconds % 60).toFixed(0).padStart(2, '0'); // hide millis return {minutes}:{seconds}; } } diff --git a/src/components/views/voice_messages/LiveRecordingClock.tsx b/src/components/views/voice_messages/LiveRecordingClock.tsx index 5e9006c6ab..b82539eb16 100644 --- a/src/components/views/voice_messages/LiveRecordingClock.tsx +++ b/src/components/views/voice_messages/LiveRecordingClock.tsx @@ -31,7 +31,7 @@ interface IState { * A clock for a live recording. */ @replaceableComponent("views.voice_messages.LiveRecordingClock") -export default class LiveRecordingClock extends React.Component { +export default class LiveRecordingClock extends React.PureComponent { public constructor(props) { super(props); @@ -39,12 +39,6 @@ export default class LiveRecordingClock extends React.Component this.props.recorder.liveData.onUpdate(this.onRecordingUpdate); } - shouldComponentUpdate(nextProps: Readonly, nextState: Readonly, nextContext: any): boolean { - const currentFloor = Math.floor(this.state.seconds); - const nextFloor = Math.floor(nextState.seconds); - return currentFloor !== nextFloor; - } - private onRecordingUpdate = (update: IRecordingUpdate) => { this.setState({seconds: update.timeSeconds}); }; diff --git a/src/components/views/voice_messages/LiveRecordingWaveform.tsx b/src/components/views/voice_messages/LiveRecordingWaveform.tsx index c1f5e97fff..aab89f6ab1 100644 --- a/src/components/views/voice_messages/LiveRecordingWaveform.tsx +++ b/src/components/views/voice_messages/LiveRecordingWaveform.tsx @@ -15,7 +15,7 @@ limitations under the License. */ import React from "react"; -import {IRecordingUpdate, VoiceRecording} from "../../../voice/VoiceRecording"; +import {IRecordingUpdate, RECORDING_PLAYBACK_SAMPLES, VoiceRecording} from "../../../voice/VoiceRecording"; import {replaceableComponent} from "../../../utils/replaceableComponent"; import {arrayFastResample, arraySeed} from "../../../utils/arrays"; import {percentageOf} from "../../../utils/numbers"; @@ -29,8 +29,6 @@ interface IState { heights: number[]; } -const DOWNSAMPLE_TARGET = 35; // number of bars we want - /** * A waveform which shows the waveform of a live recording */ @@ -39,14 +37,14 @@ export default class LiveRecordingWaveform extends React.PureComponent { // The waveform and the downsample target are pretty close, so we should be fine to // do this, despite the docs on arrayFastResample. - const bars = arrayFastResample(Array.from(update.waveform), DOWNSAMPLE_TARGET); + const bars = arrayFastResample(Array.from(update.waveform), RECORDING_PLAYBACK_SAMPLES); this.setState({ // The incoming data is between zero and one, but typically even screaming into a // microphone won't send you over 0.6, so we artificially adjust the gain for the diff --git a/src/components/views/voice_messages/PlayPauseButton.tsx b/src/components/views/voice_messages/PlayPauseButton.tsx new file mode 100644 index 0000000000..1f87eb012d --- /dev/null +++ b/src/components/views/voice_messages/PlayPauseButton.tsx @@ -0,0 +1,61 @@ +/* +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 React, {ReactNode} from "react"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; +import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; +import {_t} from "../../../languageHandler"; +import {Playback, PlaybackState} from "../../../voice/Playback"; +import classNames from "classnames"; + +interface IProps { + // Playback instance to manipulate. Cannot change during the component lifecycle. + playback: Playback; + + // The playback phase to render. Able to change during the component lifecycle. + playbackPhase: PlaybackState; +} + +/** + * Displays a play/pause button (activating the play/pause function of the recorder) + * to be displayed in reference to a recording. + */ +@replaceableComponent("views.voice_messages.PlayPauseButton") +export default class PlayPauseButton extends React.PureComponent { + public constructor(props) { + super(props); + } + + private onClick = async () => { + await this.props.playback.toggle(); + }; + + public render(): ReactNode { + const isPlaying = this.props.playback.isPlaying; + const isDisabled = this.props.playbackPhase === PlaybackState.Decoding; + const classes = classNames('mx_PlayPauseButton', { + 'mx_PlayPauseButton_play': !isPlaying, + 'mx_PlayPauseButton_pause': isPlaying, + 'mx_PlayPauseButton_disabled': isDisabled, + }); + return ; + } +} diff --git a/src/components/views/voice_messages/PlaybackClock.tsx b/src/components/views/voice_messages/PlaybackClock.tsx new file mode 100644 index 0000000000..2e8ec9a3e7 --- /dev/null +++ b/src/components/views/voice_messages/PlaybackClock.tsx @@ -0,0 +1,71 @@ +/* +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 React from "react"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; +import Clock from "./Clock"; +import {Playback, PlaybackState} from "../../../voice/Playback"; +import {UPDATE_EVENT} from "../../../stores/AsyncStore"; + +interface IProps { + playback: Playback; +} + +interface IState { + seconds: number; + durationSeconds: number; + playbackPhase: PlaybackState; +} + +/** + * A clock for a playback of a recording. + */ +@replaceableComponent("views.voice_messages.PlaybackClock") +export default class PlaybackClock extends React.PureComponent { + public constructor(props) { + super(props); + + this.state = { + seconds: this.props.playback.clockInfo.timeSeconds, + // we track the duration on state because we won't really know what the clip duration + // is until the first time update, and as a PureComponent we are trying to dedupe state + // updates as much as possible. This is just the easiest way to avoid a forceUpdate() or + // member property to track "did we get a duration". + durationSeconds: this.props.playback.clockInfo.durationSeconds, + playbackPhase: PlaybackState.Stopped, // assume not started, so full clock + }; + this.props.playback.on(UPDATE_EVENT, this.onPlaybackUpdate); + this.props.playback.clockInfo.liveData.onUpdate(this.onTimeUpdate); + } + + private onPlaybackUpdate = (ev: PlaybackState) => { + // Convert Decoding -> Stopped because we don't care about the distinction here + if (ev === PlaybackState.Decoding) ev = PlaybackState.Stopped; + this.setState({playbackPhase: ev}); + }; + + private onTimeUpdate = (time: number[]) => { + this.setState({seconds: time[0], durationSeconds: time[1]}); + }; + + public render() { + let seconds = this.state.seconds; + if (this.state.playbackPhase === PlaybackState.Stopped) { + seconds = this.state.durationSeconds; + } + return ; + } +} diff --git a/src/components/views/voice_messages/PlaybackWaveform.tsx b/src/components/views/voice_messages/PlaybackWaveform.tsx new file mode 100644 index 0000000000..123af5dfa5 --- /dev/null +++ b/src/components/views/voice_messages/PlaybackWaveform.tsx @@ -0,0 +1,68 @@ +/* +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 React from "react"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; +import {arraySeed, arrayTrimFill} from "../../../utils/arrays"; +import Waveform from "./Waveform"; +import {Playback, PLAYBACK_WAVEFORM_SAMPLES} from "../../../voice/Playback"; +import {percentageOf} from "../../../utils/numbers"; + +interface IProps { + playback: Playback; +} + +interface IState { + heights: number[]; + progress: number; +} + +/** + * A waveform which shows the waveform of a previously recorded recording + */ +@replaceableComponent("views.voice_messages.PlaybackWaveform") +export default class PlaybackWaveform extends React.PureComponent { + public constructor(props) { + super(props); + + this.state = { + heights: this.toHeights(this.props.playback.waveform), + progress: 0, // default no progress + }; + + this.props.playback.waveformData.onUpdate(this.onWaveformUpdate); + this.props.playback.clockInfo.liveData.onUpdate(this.onTimeUpdate); + } + + private toHeights(waveform: number[]) { + const seed = arraySeed(0, PLAYBACK_WAVEFORM_SAMPLES); + return arrayTrimFill(waveform, PLAYBACK_WAVEFORM_SAMPLES, seed); + } + + private onWaveformUpdate = (waveform: number[]) => { + this.setState({heights: this.toHeights(waveform)}); + }; + + private onTimeUpdate = (time: number[]) => { + // Track percentages to very coarse precision, otherwise 0.002 ends up highlighting a bar. + const progress = Number(percentageOf(time[0], 0, time[1]).toFixed(1)); + this.setState({progress}); + }; + + public render() { + return ; + } +} diff --git a/src/components/views/voice_messages/RecordingPlayback.tsx b/src/components/views/voice_messages/RecordingPlayback.tsx new file mode 100644 index 0000000000..776997cec2 --- /dev/null +++ b/src/components/views/voice_messages/RecordingPlayback.tsx @@ -0,0 +1,62 @@ +/* +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 {Playback, PlaybackState} from "../../../voice/Playback"; +import React, {ReactNode} from "react"; +import {UPDATE_EVENT} from "../../../stores/AsyncStore"; +import PlaybackWaveform from "./PlaybackWaveform"; +import PlayPauseButton from "./PlayPauseButton"; +import PlaybackClock from "./PlaybackClock"; + +interface IProps { + // Playback instance to render. Cannot change during component lifecycle: create + // an all-new component instead. + playback: Playback; +} + +interface IState { + playbackPhase: PlaybackState; +} + +export default class RecordingPlayback extends React.PureComponent { + constructor(props: IProps) { + super(props); + + this.state = { + playbackPhase: PlaybackState.Decoding, // default assumption + }; + + // We don't need to de-register: the class handles this for us internally + this.props.playback.on(UPDATE_EVENT, this.onPlaybackUpdate); + + // Don't wait for the promise to complete - it will emit a progress update when it + // is done, and it's not meant to take long anyhow. + // noinspection JSIgnoredPromiseFromCall + this.props.playback.prepare(); + } + + private onPlaybackUpdate = (ev: PlaybackState) => { + this.setState({playbackPhase: ev}); + }; + + public render(): ReactNode { + return
    + + + +
    + } +} diff --git a/src/components/views/voice_messages/Waveform.tsx b/src/components/views/voice_messages/Waveform.tsx index 5fa68dcadc..840a5a12b3 100644 --- a/src/components/views/voice_messages/Waveform.tsx +++ b/src/components/views/voice_messages/Waveform.tsx @@ -16,9 +16,11 @@ limitations under the License. import React from "react"; import {replaceableComponent} from "../../../utils/replaceableComponent"; +import classNames from "classnames"; interface IProps { relHeights: number[]; // relative heights (0-1) + progress: number; // percent complete, 0-1, default 100% } interface IState { @@ -28,9 +30,16 @@ interface IState { * A simple waveform component. This renders bars (centered vertically) for each * height provided in the component properties. Updating the properties will update * the rendered waveform. + * + * For CSS purposes, a mx_Waveform_bar_100pct class is added when the bar should be + * "filled", as a demonstration of the progress property. */ @replaceableComponent("views.voice_messages.Waveform") export default class Waveform extends React.PureComponent { + public static defaultProps = { + progress: 1, + }; + public constructor(props) { super(props); } @@ -38,7 +47,13 @@ export default class Waveform extends React.PureComponent { public render() { return
    {this.props.relHeights.map((h, i) => { - return ; + const progress = this.props.progress; + const isCompleteBar = (i / this.props.relHeights.length) <= progress && progress > 0; + const classes = classNames({ + 'mx_Waveform_bar': true, + 'mx_Waveform_bar_100pct': isCompleteBar, + }); + return ; })}
    ; } diff --git a/src/components/views/voip/AudioFeed.tsx b/src/components/views/voip/AudioFeed.tsx new file mode 100644 index 0000000000..c78f0c0fc8 --- /dev/null +++ b/src/components/views/voip/AudioFeed.tsx @@ -0,0 +1,97 @@ +/* +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. +*/ + +import React, {createRef} from 'react'; +import { CallFeed, CallFeedEvent } from 'matrix-js-sdk/src/webrtc/callFeed'; +import { logger } from 'matrix-js-sdk/src/logger'; +import CallMediaHandler from "../../../CallMediaHandler"; + +interface IProps { + feed: CallFeed, +} + +export default class AudioFeed extends React.Component { + private element = createRef(); + + componentDidMount() { + this.props.feed.addListener(CallFeedEvent.NewStream, this.onNewStream); + this.playMedia(); + } + + componentWillUnmount() { + this.props.feed.removeListener(CallFeedEvent.NewStream, this.onNewStream); + this.stopMedia(); + } + + private playMedia() { + const element = this.element.current; + const audioOutput = CallMediaHandler.getAudioOutput(); + + if (audioOutput) { + try { + // This seems quite unreliable in Chrome, although I haven't yet managed to make a jsfiddle where + // it fails. + // It seems reliable if you set the sink ID after setting the srcObject and then set the sink ID + // back to the default after the call is over - Dave + element.setSinkId(audioOutput); + } catch (e) { + console.error("Couldn't set requested audio output device: using default", e); + logger.warn("Couldn't set requested audio output device: using default", e); + } + } + + element.muted = false; + element.srcObject = this.props.feed.stream; + element.autoplay = true; + + try { + // A note on calling methods on media elements: + // We used to have queues per media element to serialise all calls on those elements. + // The reason given for this was that load() and play() were racing. However, we now + // never call load() explicitly so this seems unnecessary. However, serialising every + // operation was causing bugs where video would not resume because some play command + // had got stuck and all media operations were queued up behind it. If necessary, we + // should serialise the ones that need to be serialised but then be able to interrupt + // them with another load() which will cancel the pending one, but since we don't call + // load() explicitly, it shouldn't be a problem. - Dave + element.play() + } catch (e) { + logger.info("Failed to play media element with feed", this.props.feed, e); + } + } + + private stopMedia() { + const element = this.element.current; + + element.pause(); + element.src = null; + + // As per comment in componentDidMount, setting the sink ID back to the + // default once the call is over makes setSinkId work reliably. - Dave + // Since we are not using the same element anymore, the above doesn't + // seem to be necessary - Šimon + } + + private onNewStream = () => { + this.playMedia(); + }; + + render() { + return ( +
    ; + const avatarSize = this.props.pipMode ? 76 : 160; + // The 'content' for the call, ie. the videos for a video call and profile picture // for voice calls (fills the bg) let contentView: React.ReactNode; @@ -482,11 +492,13 @@ export default class CallView extends React.Component { const isOnHold = this.state.isLocalOnHold || this.state.isRemoteOnHold; let holdTransferContent; if (transfereeCall) { - const transferTargetRoom = MatrixClientPeg.get().getRoom(CallHandler.roomIdForCall(this.props.call)); + const transferTargetRoom = MatrixClientPeg.get().getRoom( + CallHandler.sharedInstance().roomIdForCall(this.props.call), + ); const transferTargetName = transferTargetRoom ? transferTargetRoom.name : _t("unknown person"); const transfereeRoom = MatrixClientPeg.get().getRoom( - CallHandler.roomIdForCall(transfereeCall), + CallHandler.sharedInstance().roomIdForCall(transfereeCall), ); const transfereeName = transfereeRoom ? transfereeRoom.name : _t("unknown person"); @@ -522,41 +534,85 @@ export default class CallView extends React.Component {
    ; } - if (this.props.call.type === CallType.Video) { - let localVideoFeed = null; - let onHoldBackground = null; - const backgroundStyle: CSSProperties = {}; - const containerClasses = classNames({ - mx_CallView_video: true, - mx_CallView_video_hold: isOnHold, - }); - if (isOnHold) { + // This is a bit messy. I can't see a reason to have two onHold/transfer screens + if (isOnHold || transfereeCall) { + if (this.props.call.type === CallType.Video) { + const containerClasses = classNames({ + mx_CallView_content: true, + mx_CallView_video: true, + mx_CallView_video_hold: isOnHold, + }); + let onHoldBackground = null; + const backgroundStyle: CSSProperties = {}; const backgroundAvatarUrl = avatarUrlForMember( - // is it worth getting the size of the div to pass here? + // is it worth getting the size of the div to pass here? this.props.call.getOpponentMember(), 1024, 1024, 'crop', ); backgroundStyle.backgroundImage = 'url(' + backgroundAvatarUrl + ')'; onHoldBackground =
    ; - } - if (!this.state.vidMuted) { - localVideoFeed = ; - } - contentView =
    - {onHoldBackground} - - {localVideoFeed} - {holdTransferContent} - {callControls} -
    ; - } else { - const avatarSize = this.props.pipMode ? 76 : 160; + contentView = ( +
    + {onHoldBackground} + {holdTransferContent} + {callControls} +
    + ); + } else { + const classes = classNames({ + mx_CallView_content: true, + mx_CallView_voice: true, + mx_CallView_voice_hold: isOnHold, + }); + + contentView =( +
    +
    +
    + +
    +
    + {holdTransferContent} + {callControls} +
    + ); + } + } else if (this.props.call.noIncomingFeeds()) { + // Here we're reusing the css classes from voice on hold, because + // I am lazy. If this gets merged, the CallView might be subject + // to change anyway - I might take an axe to this file in order to + // try to get other things working const classes = classNames({ + mx_CallView_content: true, mx_CallView_voice: true, - mx_CallView_voice_hold: isOnHold, }); + const feeds = this.props.call.getLocalFeeds().map((feed, i) => { + // Here we check to hide local audio feeds to achieve the same UI/UX + // as before. But once again this might be subject to change + if (feed.isVideoMuted()) return; + return ( + + ); + }); + + // Saying "Connecting" here isn't really true, but the best thing + // I can come up with, but this might be subject to change as well contentView =
    + {feeds}
    { />
    - {holdTransferContent} +
    {_t("Connecting")}
    + {callControls} +
    ; + } else { + const containerClasses = classNames({ + mx_CallView_content: true, + mx_CallView_video: true, + }); + + // TODO: Later the CallView should probably be reworked to support + // any number of feeds but now we can always expect there to be two + // feeds. This is because the js-sdk ignores any new incoming streams + const feeds = this.state.feeds.map((feed, i) => { + // Here we check to hide local audio feeds to achieve the same UI/UX + // as before. But once again this might be subject to change + if (feed.isVideoMuted() && feed.isLocal()) return; + return ( + + ); + }); + + contentView =
    + {feeds} {callControls}
    ; } diff --git a/src/components/views/voip/CallViewForRoom.tsx b/src/components/views/voip/CallViewForRoom.tsx index 878b6af20f..0c785f758d 100644 --- a/src/components/views/voip/CallViewForRoom.tsx +++ b/src/components/views/voip/CallViewForRoom.tsx @@ -16,7 +16,7 @@ limitations under the License. import { CallState, MatrixCall } from 'matrix-js-sdk/src/webrtc/call'; import React from 'react'; -import CallHandler from '../../../CallHandler'; +import CallHandler, { CallHandlerEvent } from '../../../CallHandler'; import CallView from './CallView'; import dis from '../../../dispatcher/dispatcher'; import {Resizable} from "re-resizable"; @@ -54,24 +54,30 @@ export default class CallViewForRoom extends React.Component { public componentDidMount() { this.dispatcherRef = dis.register(this.onAction); + CallHandler.sharedInstance().addListener(CallHandlerEvent.CallChangeRoom, this.updateCall); } public componentWillUnmount() { dis.unregister(this.dispatcherRef); + CallHandler.sharedInstance().removeListener(CallHandlerEvent.CallChangeRoom, this.updateCall); } private onAction = (payload) => { switch (payload.action) { case 'call_state': { - const newCall = this.getCall(); - if (newCall !== this.state.call) { - this.setState({call: newCall}); - } + this.updateCall(); break; } } }; + private updateCall = () => { + const newCall = this.getCall(); + if (newCall !== this.state.call) { + this.setState({call: newCall}); + } + }; + private getCall(): MatrixCall { const call = CallHandler.sharedInstance().getCallForRoom(this.props.roomId); diff --git a/src/components/views/voip/IncomingCallBox.tsx b/src/components/views/voip/IncomingCallBox.tsx index 0ca2a196c2..2abdc0641d 100644 --- a/src/components/views/voip/IncomingCallBox.tsx +++ b/src/components/views/voip/IncomingCallBox.tsx @@ -72,7 +72,7 @@ export default class IncomingCallBox extends React.Component { e.stopPropagation(); dis.dispatch({ action: 'answer', - room_id: CallHandler.roomIdForCall(this.state.incomingCall), + room_id: CallHandler.sharedInstance().roomIdForCall(this.state.incomingCall), }); }; @@ -80,7 +80,7 @@ export default class IncomingCallBox extends React.Component { e.stopPropagation(); dis.dispatch({ action: 'reject', - room_id: CallHandler.roomIdForCall(this.state.incomingCall), + room_id: CallHandler.sharedInstance().roomIdForCall(this.state.incomingCall), }); }; @@ -91,7 +91,7 @@ export default class IncomingCallBox extends React.Component { let room = null; if (this.state.incomingCall) { - room = MatrixClientPeg.get().getRoom(CallHandler.roomIdForCall(this.state.incomingCall)); + room = MatrixClientPeg.get().getRoom(CallHandler.sharedInstance().roomIdForCall(this.state.incomingCall)); } const caller = room ? room.name : _t("Unknown caller"); diff --git a/src/components/views/voip/VideoFeed.tsx b/src/components/views/voip/VideoFeed.tsx index 2981fb6c04..d22fa055ce 100644 --- a/src/components/views/voip/VideoFeed.tsx +++ b/src/components/views/voip/VideoFeed.tsx @@ -18,52 +18,102 @@ import classnames from 'classnames'; import { MatrixCall } from 'matrix-js-sdk/src/webrtc/call'; import React, {createRef} from 'react'; import SettingsStore from "../../../settings/SettingsStore"; +import { CallFeed, CallFeedEvent } from 'matrix-js-sdk/src/webrtc/callFeed'; +import { logger } from 'matrix-js-sdk/src/logger'; +import MemberAvatar from "../avatars/MemberAvatar" import {replaceableComponent} from "../../../utils/replaceableComponent"; -export enum VideoFeedType { - Local, - Remote, -} - interface IProps { call: MatrixCall, - type: VideoFeedType, + feed: CallFeed, + + // Whether this call view is for picture-in-picture mode + // otherwise, it's the larger call view when viewing the room the call is in. + // This is sort of a proxy for a number of things but we currently have no + // need to control those things separately, so this is simpler. + pipMode?: boolean; // a callback which is called when the video element is resized // due to a change in video metadata onResize?: (e: Event) => void, } -@replaceableComponent("views.voip.VideoFeed") -export default class VideoFeed extends React.Component { - private vid = createRef(); +interface IState { + audioMuted: boolean; + videoMuted: boolean; +} - componentDidMount() { - this.vid.current.addEventListener('resize', this.onResize); - this.setVideoElement(); +@replaceableComponent("views.voip.VideoFeed") +export default class VideoFeed extends React.Component { + private element = createRef(); + + constructor(props: IProps) { + super(props); + + this.state = { + audioMuted: this.props.feed.isAudioMuted(), + videoMuted: this.props.feed.isVideoMuted(), + }; } - componentDidUpdate(prevProps) { - if (this.props.call !== prevProps.call) { - this.setVideoElement(); - } + componentDidMount() { + this.props.feed.addListener(CallFeedEvent.NewStream, this.onNewStream); + this.playMedia(); } componentWillUnmount() { - this.vid.current.removeEventListener('resize', this.onResize); + this.props.feed.removeListener(CallFeedEvent.NewStream, this.onNewStream); + this.element.current?.removeEventListener('resize', this.onResize); + this.stopMedia(); } - private setVideoElement() { - if (this.props.type === VideoFeedType.Local) { - this.props.call.setLocalVideoElement(this.vid.current); - } else { - this.props.call.setRemoteVideoElement(this.vid.current); + private playMedia() { + const element = this.element.current; + if (!element) return; + // We play audio in AudioFeed, not here + element.muted = true; + element.srcObject = this.props.feed.stream; + element.autoplay = true; + try { + // A note on calling methods on media elements: + // We used to have queues per media element to serialise all calls on those elements. + // The reason given for this was that load() and play() were racing. However, we now + // never call load() explicitly so this seems unnecessary. However, serialising every + // operation was causing bugs where video would not resume because some play command + // had got stuck and all media operations were queued up behind it. If necessary, we + // should serialise the ones that need to be serialised but then be able to interrupt + // them with another load() which will cancel the pending one, but since we don't call + // load() explicitly, it shouldn't be a problem. - Dave + element.play() + } catch (e) { + logger.info("Failed to play media element with feed", this.props.feed, e); } } - onResize = (e) => { - if (this.props.onResize) { + private stopMedia() { + const element = this.element.current; + if (!element) return; + + element.pause(); + element.src = null; + + // As per comment in componentDidMount, setting the sink ID back to the + // default once the call is over makes setSinkId work reliably. - Dave + // Since we are not using the same element anymore, the above doesn't + // seem to be necessary - Šimon + } + + private onNewStream = () => { + this.setState({ + audioMuted: this.props.feed.isAudioMuted(), + videoMuted: this.props.feed.isVideoMuted(), + }); + this.playMedia(); + }; + + private onResize = (e) => { + if (this.props.onResize && !this.props.feed.isLocal()) { this.props.onResize(e); } }; @@ -71,14 +121,33 @@ export default class VideoFeed extends React.Component { render() { const videoClasses = { mx_VideoFeed: true, - mx_VideoFeed_local: this.props.type === VideoFeedType.Local, - mx_VideoFeed_remote: this.props.type === VideoFeedType.Remote, + mx_VideoFeed_local: this.props.feed.isLocal(), + mx_VideoFeed_remote: !this.props.feed.isLocal(), + mx_VideoFeed_voice: this.state.videoMuted, + mx_VideoFeed_video: !this.state.videoMuted, mx_VideoFeed_mirror: ( - this.props.type === VideoFeedType.Local && + this.props.feed.isLocal() && SettingsStore.getValue('VideoView.flipVideoHorizontally') ), }; - return
    ), button: _t("Trust"), - }); + }); const [confirmed] = await finished; if (confirmed) { // eslint-disable-next-line react-hooks/rules-of-hooks diff --git a/src/KeyBindingsManager.ts b/src/KeyBindingsManager.ts index d862f10c02..aac14bde20 100644 --- a/src/KeyBindingsManager.ts +++ b/src/KeyBindingsManager.ts @@ -231,8 +231,10 @@ export class KeyBindingsManager { /** * Finds a matching KeyAction for a given KeyboardEvent */ - private getAction(getters: KeyBindingGetter[], ev: KeyboardEvent | React.KeyboardEvent) - : T | undefined { + private getAction( + getters: KeyBindingGetter[], + ev: KeyboardEvent | React.KeyboardEvent, + ): T | undefined { for (const getter of getters) { const bindings = getter(); const binding = bindings.find(it => isKeyComboMatch(ev, it.keyCombo, isMac)); diff --git a/src/Login.ts b/src/Login.ts index db3c4c11e4..d584df7dfe 100644 --- a/src/Login.ts +++ b/src/Login.ts @@ -1,9 +1,6 @@ /* -Copyright 2015, 2016 OpenMarket Ltd -Copyright 2017 Vector Creations Ltd -Copyright 2018 New Vector Ltd +Copyright 2015-2021 The Matrix.org Foundation C.I.C. Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> -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. @@ -59,7 +56,7 @@ export type LoginFlow = ISSOFlow | IPasswordFlow; // TODO: Move this to JS SDK /* eslint-disable camelcase */ interface ILoginParams { - identifier?: string; + identifier?: object; password?: string; token?: string; device_id?: string; diff --git a/src/PasswordReset.js b/src/PasswordReset.js index 6fe6ca82cc..88ae00d088 100644 --- a/src/PasswordReset.js +++ b/src/PasswordReset.js @@ -54,7 +54,7 @@ export default class PasswordReset { return res; }, function(err) { if (err.errcode === 'M_THREEPID_NOT_FOUND') { - err.message = _t('This email address was not found'); + err.message = _t('This email address was not found'); } else if (err.httpStatus) { err.message = err.message + ` (Status ${err.httpStatus})`; } diff --git a/src/Resend.js b/src/Resend.js index bf69e59c1a..f1e5fb38f5 100644 --- a/src/Resend.js +++ b/src/Resend.js @@ -21,11 +21,11 @@ import { EventStatus } from 'matrix-js-sdk/src/models/event'; export default class Resend { static resendUnsentEvents(room) { - room.getPendingEvents().filter(function(ev) { + return Promise.all(room.getPendingEvents().filter(function(ev) { return ev.status === EventStatus.NOT_SENT; - }).forEach(function(event) { - Resend.resend(event); - }); + }).map(function(event) { + return Resend.resend(event); + })); } static cancelUnsentEvents(room) { @@ -38,7 +38,7 @@ export default class Resend { static resend(event) { const room = MatrixClientPeg.get().getRoom(event.getRoomId()); - MatrixClientPeg.get().resendEvent(event, room).then(function(res) { + return MatrixClientPeg.get().resendEvent(event, room).then(function(res) { dis.dispatch({ action: 'message_sent', event: event, diff --git a/src/ScalarAuthClient.js b/src/ScalarAuthClient.ts similarity index 84% rename from src/ScalarAuthClient.js rename to src/ScalarAuthClient.ts index 200b4fd7b9..a09c3494a8 100644 --- a/src/ScalarAuthClient.js +++ b/src/ScalarAuthClient.ts @@ -1,6 +1,5 @@ /* -Copyright 2016 OpenMarket Ltd -Copyright 2019 The Matrix.org Foundation C.I.C. +Copyright 2016, 2019, 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. @@ -17,13 +16,14 @@ limitations under the License. import url from 'url'; import SettingsStore from "./settings/SettingsStore"; -import { Service, startTermsFlow, TermsNotSignedError } from './Terms'; +import { Service, startTermsFlow, TermsInteractionCallback, TermsNotSignedError } from './Terms'; import {MatrixClientPeg} from "./MatrixClientPeg"; import request from "browser-request"; import SdkConfig from "./SdkConfig"; import {WidgetType} from "./widgets/WidgetType"; import {SERVICE_TYPES} from "matrix-js-sdk/src/service-types"; +import { Room } from "matrix-js-sdk/src/models/room"; // The version of the integration manager API we're intending to work with const imApiVersion = "1.1"; @@ -31,9 +31,11 @@ const imApiVersion = "1.1"; // TODO: Generify the name of this class and all components within - it's not just for Scalar. export default class ScalarAuthClient { - constructor(apiUrl, uiUrl) { - this.apiUrl = apiUrl; - this.uiUrl = uiUrl; + private scalarToken: string; + private termsInteractionCallback: TermsInteractionCallback; + private isDefaultManager: boolean; + + constructor(private apiUrl: string, private uiUrl: string) { this.scalarToken = null; // `undefined` to allow `startTermsFlow` to fallback to a default // callback if this is unset. @@ -46,7 +48,7 @@ export default class ScalarAuthClient { this.isDefaultManager = apiUrl === configApiUrl && configUiUrl === uiUrl; } - _writeTokenToStore() { + private writeTokenToStore() { window.localStorage.setItem("mx_scalar_token_at_" + this.apiUrl, this.scalarToken); if (this.isDefaultManager) { // We remove the old token from storage to migrate upwards. This is safe @@ -56,7 +58,7 @@ export default class ScalarAuthClient { } } - _readTokenFromStore() { + private readTokenFromStore(): string { let token = window.localStorage.getItem("mx_scalar_token_at_" + this.apiUrl); if (!token && this.isDefaultManager) { token = window.localStorage.getItem("mx_scalar_token"); @@ -64,33 +66,33 @@ export default class ScalarAuthClient { return token; } - _readToken() { + private readToken(): string { if (this.scalarToken) return this.scalarToken; - return this._readTokenFromStore(); + return this.readTokenFromStore(); } setTermsInteractionCallback(callback) { this.termsInteractionCallback = callback; } - connect() { + connect(): Promise { return this.getScalarToken().then((tok) => { this.scalarToken = tok; }); } - hasCredentials() { + hasCredentials(): boolean { return this.scalarToken != null; // undef or null } // Returns a promise that resolves to a scalar_token string - getScalarToken() { - const token = this._readToken(); + getScalarToken(): Promise { + const token = this.readToken(); if (!token) { return this.registerForToken(); } else { - return this._checkToken(token).catch((e) => { + return this.checkToken(token).catch((e) => { if (e instanceof TermsNotSignedError) { // retrying won't help this throw e; @@ -100,7 +102,7 @@ export default class ScalarAuthClient { } } - _getAccountName(token) { + private getAccountName(token: string): Promise { const url = this.apiUrl + "/account"; return new Promise(function(resolve, reject) { @@ -125,8 +127,8 @@ export default class ScalarAuthClient { }); } - _checkToken(token) { - return this._getAccountName(token).then(userId => { + private checkToken(token: string): Promise { + return this.getAccountName(token).then(userId => { const me = MatrixClientPeg.get().getUserId(); if (userId !== me) { throw new Error("Scalar token is owned by someone else: " + me); @@ -154,7 +156,7 @@ export default class ScalarAuthClient { parsedImRestUrl.pathname = ''; return startTermsFlow([new Service( SERVICE_TYPES.IM, - parsedImRestUrl.format(), + url.format(parsedImRestUrl), token, )], this.termsInteractionCallback).then(() => { return token; @@ -165,22 +167,22 @@ export default class ScalarAuthClient { }); } - registerForToken() { + registerForToken(): Promise { // Get openid bearer token from the HS as the first part of our dance return MatrixClientPeg.get().getOpenIdToken().then((tokenObject) => { // Now we can send that to scalar and exchange it for a scalar token return this.exchangeForScalarToken(tokenObject); }).then((token) => { // Validate it (this mostly checks to see if the IM needs us to agree to some terms) - return this._checkToken(token); + return this.checkToken(token); }).then((token) => { this.scalarToken = token; - this._writeTokenToStore(); + this.writeTokenToStore(); return token; }); } - exchangeForScalarToken(openidTokenObject) { + exchangeForScalarToken(openidTokenObject: any): Promise { const scalarRestUrl = this.apiUrl; return new Promise(function(resolve, reject) { @@ -194,7 +196,7 @@ export default class ScalarAuthClient { if (err) { reject(err); } else if (response.statusCode / 100 !== 2) { - reject({statusCode: response.statusCode}); + reject(new Error(`Scalar request failed: ${response.statusCode}`)); } else if (!body || !body.scalar_token) { reject(new Error("Missing scalar_token in response")); } else { @@ -204,7 +206,7 @@ export default class ScalarAuthClient { }); } - getScalarPageTitle(url) { + getScalarPageTitle(url: string): Promise { let scalarPageLookupUrl = this.apiUrl + '/widgets/title_lookup'; scalarPageLookupUrl = this.getStarterLink(scalarPageLookupUrl); scalarPageLookupUrl += '&curl=' + encodeURIComponent(url); @@ -218,7 +220,7 @@ export default class ScalarAuthClient { if (err) { reject(err); } else if (response.statusCode / 100 !== 2) { - reject({statusCode: response.statusCode}); + reject(new Error(`Scalar request failed: ${response.statusCode}`)); } else if (!body) { reject(new Error("Missing page title in response")); } else { @@ -240,10 +242,10 @@ export default class ScalarAuthClient { * @param {string} widgetId The widget ID to disable assets for * @return {Promise} Resolves on completion */ - disableWidgetAssets(widgetType: WidgetType, widgetId) { + disableWidgetAssets(widgetType: WidgetType, widgetId: string): Promise { let url = this.apiUrl + '/widgets/set_assets_state'; url = this.getStarterLink(url); - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { request({ method: 'GET', // XXX: Actions shouldn't be GET requests uri: url, @@ -257,7 +259,7 @@ export default class ScalarAuthClient { if (err) { reject(err); } else if (response.statusCode / 100 !== 2) { - reject({statusCode: response.statusCode}); + reject(new Error(`Scalar request failed: ${response.statusCode}`)); } else if (!body) { reject(new Error("Failed to set widget assets state")); } else { @@ -267,7 +269,7 @@ export default class ScalarAuthClient { }); } - getScalarInterfaceUrlForRoom(room, screen, id) { + getScalarInterfaceUrlForRoom(room: Room, screen: string, id: string): string { const roomId = room.roomId; const roomName = room.name; let url = this.uiUrl; @@ -284,7 +286,7 @@ export default class ScalarAuthClient { return url; } - getStarterLink(starterLinkUrl) { + getStarterLink(starterLinkUrl: string): string { return starterLinkUrl + "?scalar_token=" + encodeURIComponent(this.scalarToken); } } diff --git a/src/SlashCommands.tsx b/src/SlashCommands.tsx index 6ce1439164..4a7b37b5e5 100644 --- a/src/SlashCommands.tsx +++ b/src/SlashCommands.tsx @@ -38,7 +38,7 @@ import {isPermalinkHost, parsePermalink} from "./utils/permalinks/Permalinks"; import {inviteUsersToRoom} from "./RoomInvite"; import { WidgetType } from "./widgets/WidgetType"; import { Jitsi } from "./widgets/Jitsi"; -import { parseFragment as parseHtml } from "parse5"; +import { parseFragment as parseHtml, Element as ChildElement } from "parse5"; import BugReportDialog from "./components/views/dialogs/BugReportDialog"; import { ensureDMExists } from "./createRoom"; import { ViewUserPayload } from "./dispatcher/payloads/ViewUserPayload"; @@ -856,7 +856,7 @@ export const Commands = [ // some superfast regex over the text so we don't have to. const embed = parseHtml(widgetUrl); if (embed && embed.childNodes && embed.childNodes.length === 1) { - const iframe = embed.childNodes[0]; + const iframe = embed.childNodes[0] as ChildElement; if (iframe.tagName.toLowerCase() === 'iframe' && iframe.attrs) { const srcAttr = iframe.attrs.find(a => a.name === 'src'); console.log("Pulling URL out of iframe (embed code)"); diff --git a/src/Terms.js b/src/Terms.ts similarity index 87% rename from src/Terms.js rename to src/Terms.ts index 6ae89f9a2c..1bdff36cbc 100644 --- a/src/Terms.js +++ b/src/Terms.ts @@ -1,5 +1,5 @@ /* -Copyright 2019 The Matrix.org Foundation C.I.C. +Copyright 2019, 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. @@ -17,7 +17,7 @@ limitations under the License. import classNames from 'classnames'; import {MatrixClientPeg} from './MatrixClientPeg'; -import * as sdk from './'; +import * as sdk from '.'; import Modal from './Modal'; export class TermsNotSignedError extends Error {} @@ -32,13 +32,30 @@ export class Service { * @param {string} baseUrl The Base URL of the service (ie. before '/_matrix') * @param {string} accessToken The user's access token for the service */ - constructor(serviceType, baseUrl, accessToken) { - this.serviceType = serviceType; - this.baseUrl = baseUrl; - this.accessToken = accessToken; + constructor(public serviceType: string, public baseUrl: string, public accessToken: string) { } } +interface Policy { + // @ts-ignore: No great way to express indexed types together with other keys + version: string; + [lang: string]: { + url: string; + }; +} +type Policies = { + [policy: string]: Policy, +}; + +export type TermsInteractionCallback = ( + policiesAndServicePairs: { + service: Service, + policies: Policies, + }[], + agreedUrls: string[], + extraClassNames?: string, +) => Promise; + /** * Start a flow where the user is presented with terms & conditions for some services * @@ -51,8 +68,8 @@ export class Service { * if they cancel. */ export async function startTermsFlow( - services, - interactionCallback = dialogTermsInteractionCallback, + services: Service[], + interactionCallback: TermsInteractionCallback = dialogTermsInteractionCallback, ) { const termsPromises = services.map( (s) => MatrixClientPeg.get().getTerms(s.serviceType, s.baseUrl), @@ -77,7 +94,7 @@ export async function startTermsFlow( * } */ - const terms = await Promise.all(termsPromises); + const terms: { policies: Policies }[] = await Promise.all(termsPromises); const policiesAndServicePairs = terms.map((t, i) => { return { 'service': services[i], 'policies': t.policies }; }); // fetch the set of agreed policy URLs from account data @@ -158,10 +175,13 @@ export async function startTermsFlow( } export function dialogTermsInteractionCallback( - policiesAndServicePairs, - agreedUrls, - extraClassNames, -) { + policiesAndServicePairs: { + service: Service, + policies: { [policy: string]: Policy }, + }[], + agreedUrls: string[], + extraClassNames?: string, +): Promise { return new Promise((resolve, reject) => { console.log("Terms that need agreement", policiesAndServicePairs); const TermsDialog = sdk.getComponent("views.dialogs.TermsDialog"); diff --git a/src/TextForEvent.js b/src/TextForEvent.js index a6787c647d..86f9ff20f4 100644 --- a/src/TextForEvent.js +++ b/src/TextForEvent.js @@ -547,17 +547,23 @@ function textForMjolnirEvent(event) { // else the entity !== prevEntity - count as a removal & add if (USER_RULE_TYPES.includes(event.getType())) { - return _t("%(senderName)s changed a rule that was banning users matching %(oldGlob)s to matching " + + return _t( + "%(senderName)s changed a rule that was banning users matching %(oldGlob)s to matching " + "%(newGlob)s for %(reason)s", - {senderName, oldGlob: prevEntity, newGlob: entity, reason}); + {senderName, oldGlob: prevEntity, newGlob: entity, reason}, + ); } else if (ROOM_RULE_TYPES.includes(event.getType())) { - return _t("%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching " + + return _t( + "%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching " + "%(newGlob)s for %(reason)s", - {senderName, oldGlob: prevEntity, newGlob: entity, reason}); + {senderName, oldGlob: prevEntity, newGlob: entity, reason}, + ); } else if (SERVER_RULE_TYPES.includes(event.getType())) { - return _t("%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching " + + return _t( + "%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching " + "%(newGlob)s for %(reason)s", - {senderName, oldGlob: prevEntity, newGlob: entity, reason}); + {senderName, oldGlob: prevEntity, newGlob: entity, reason}, + ); } // Unknown type. We'll say something but we shouldn't end up here. diff --git a/src/Unread.js b/src/Unread.js index ddf225ac64..12c15eb6af 100644 --- a/src/Unread.js +++ b/src/Unread.js @@ -45,7 +45,7 @@ export function eventTriggersUnreadCount(ev) { } export function doesRoomHaveUnreadMessages(room) { - const myUserId = MatrixClientPeg.get().credentials.userId; + const myUserId = MatrixClientPeg.get().getUserId(); // get the most recent read receipt sent by our account. // N.B. this is NOT a read marker (RM, aka "read up to marker"), diff --git a/src/VoipUserMapper.ts b/src/VoipUserMapper.ts index 4f5613b4a8..e5bed2e812 100644 --- a/src/VoipUserMapper.ts +++ b/src/VoipUserMapper.ts @@ -57,7 +57,11 @@ export default class VoipUserMapper { if (!virtualRoom) return null; const virtualRoomEvent = virtualRoom.getAccountData(VIRTUAL_ROOM_EVENT_TYPE); if (!virtualRoomEvent || !virtualRoomEvent.getContent()) return null; - return virtualRoomEvent.getContent()['native_room'] || null; + const nativeRoomID = virtualRoomEvent.getContent()['native_room']; + const nativeRoom = MatrixClientPeg.get().getRoom(nativeRoomID); + if (!nativeRoom || nativeRoom.getMyMembership() !== 'join') return null; + + return nativeRoomID; } public isVirtualRoom(room: Room): boolean { diff --git a/src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.js b/src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.tsx similarity index 90% rename from src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.js rename to src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.tsx index be3368b87b..0710c513da 100644 --- a/src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.js +++ b/src/async-components/views/dialogs/eventindex/ManageEventIndexDialog.tsx @@ -1,5 +1,5 @@ /* -Copyright 2020 The Matrix.org Foundation C.I.C. +Copyright 2020-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. @@ -16,7 +16,6 @@ limitations under the License. import React from 'react'; import * as sdk from '../../../../index'; -import PropTypes from 'prop-types'; import { _t } from '../../../../languageHandler'; import SdkConfig from '../../../../SdkConfig'; import SettingsStore from "../../../../settings/SettingsStore"; @@ -26,14 +25,23 @@ import {formatBytes, formatCountLong} from "../../../../utils/FormattingUtils"; import EventIndexPeg from "../../../../indexing/EventIndexPeg"; import {SettingLevel} from "../../../../settings/SettingLevel"; +interface IProps { + onFinished: (confirmed: boolean) => void; +} + +interface IState { + eventIndexSize: number; + eventCount: number; + crawlingRoomsCount: number; + roomCount: number; + currentRoom: string; + crawlerSleepTime: number; +} + /* * Allows the user to introspect the event index state and disable it. */ -export default class ManageEventIndexDialog extends React.Component { - static propTypes = { - onFinished: PropTypes.func.isRequired, - }; - +export default class ManageEventIndexDialog extends React.Component { constructor(props) { super(props); @@ -84,7 +92,7 @@ export default class ManageEventIndexDialog extends React.Component { } } - async componentDidMount(): void { + async componentDidMount(): Promise { let eventIndexSize = 0; let crawlingRoomsCount = 0; let roomCount = 0; @@ -123,14 +131,14 @@ export default class ManageEventIndexDialog extends React.Component { }); } - _onDisable = async () => { + private onDisable = async () => { Modal.createTrackedDialogAsync("Disable message search", "Disable message search", import("./DisableEventIndexDialog"), null, null, /* priority = */ false, /* static = */ true, ); }; - _onCrawlerSleepTimeChange = (e) => { + private onCrawlerSleepTimeChange = (e) => { this.setState({crawlerSleepTime: e.target.value}); SettingsStore.setValue("crawlerSleepTime", null, SettingLevel.DEVICE, e.target.value); }; @@ -144,7 +152,7 @@ export default class ManageEventIndexDialog extends React.Component { crawlerState = _t("Not currently indexing messages for any room."); } else { crawlerState = ( - _t("Currently indexing: %(currentRoom)s", { currentRoom: this.state.currentRoom }) + _t("Currently indexing: %(currentRoom)s", { currentRoom: this.state.currentRoom }) ); } @@ -169,7 +177,7 @@ export default class ManageEventIndexDialog extends React.Component { label={_t('Message downloading sleep time(ms)')} type='number' value={this.state.crawlerSleepTime} - onChange={this._onCrawlerSleepTimeChange} /> + onChange={this.onCrawlerSleepTimeChange} />
    ); @@ -188,7 +196,7 @@ export default class ManageEventIndexDialog extends React.Component { onPrimaryButtonClick={this.props.onFinished} primaryButtonClass="primary" cancelButton={_t("Disable")} - onCancel={this._onDisable} + onCancel={this.onDisable} cancelButtonClass="danger" /> diff --git a/src/async-components/views/dialogs/security/CreateKeyBackupDialog.js b/src/async-components/views/dialogs/security/CreateKeyBackupDialog.js index 863ee2b427..549494b5cb 100644 --- a/src/async-components/views/dialogs/security/CreateKeyBackupDialog.js +++ b/src/async-components/views/dialogs/security/CreateKeyBackupDialog.js @@ -310,7 +310,7 @@ export default class CreateKeyBackupDialog extends React.PureComponent { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); return

    {_t( - "Please enter your Security Phrase a second time to confirm.", + "Enter your Security Phrase a second time to confirm it.", )}

    @@ -498,9 +498,9 @@ export default class CreateKeyBackupDialog extends React.PureComponent { title={this._titleForPhase(this.state.phase)} hasCancel={[PHASE_PASSPHRASE, PHASE_DONE].includes(this.state.phase)} > -
    - {content} -
    +
    + {content} +
    ); } diff --git a/src/async-components/views/dialogs/security/CreateSecretStorageDialog.js b/src/async-components/views/dialogs/security/CreateSecretStorageDialog.js index 84cb58536a..6d5703a768 100644 --- a/src/async-components/views/dialogs/security/CreateSecretStorageDialog.js +++ b/src/async-components/views/dialogs/security/CreateSecretStorageDialog.js @@ -647,7 +647,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent { } return

    {_t( - "Enter your recovery passphrase a second time to confirm it.", + "Enter your Security Phrase a second time to confirm it.", )}

    @@ -856,9 +856,9 @@ export default class CreateSecretStorageDialog extends React.PureComponent { hasCancel={this.props.hasCancel && [PHASE_PASSPHRASE].includes(this.state.phase)} fixedWidth={false} > -
    - {content} -
    +
    + {content} +
    ); } diff --git a/src/async-components/views/dialogs/security/ExportE2eKeysDialog.js b/src/async-components/views/dialogs/security/ExportE2eKeysDialog.js index eeb68b94bd..60f2ca9168 100644 --- a/src/async-components/views/dialogs/security/ExportE2eKeysDialog.js +++ b/src/async-components/views/dialogs/security/ExportE2eKeysDialog.js @@ -170,8 +170,11 @@ export default class ExportE2eKeysDialog extends React.Component {
    -
    -
    - -
    -
    - -
    +
    + +
    +
    + +
    -
    - -
    -
    - -
    +
    + +
    +
    + +
    diff --git a/src/components/structures/FilePanel.js b/src/components/structures/FilePanel.js index 32db5c251c..d5e4b092e2 100644 --- a/src/components/structures/FilePanel.js +++ b/src/components/structures/FilePanel.js @@ -200,10 +200,10 @@ class FilePanel extends React.Component { previousPhase={RightPanelPhases.RoomSummary} >
    - { _t("You must register to use this functionality", - {}, - { 'a': (sub) => { sub } }) - } + { _t("You must register to use this functionality", + {}, + { 'a': (sub) => { sub } }) + }
    ; } else if (this.noRoom) { diff --git a/src/components/structures/GroupFilterPanel.js b/src/components/structures/GroupFilterPanel.js index 976b2d81a5..7c050e7433 100644 --- a/src/components/structures/GroupFilterPanel.js +++ b/src/components/structures/GroupFilterPanel.js @@ -153,17 +153,17 @@ class GroupFilterPanel extends React.Component { type="draggable-TagTile" > { (provided, snapshot) => ( -
    - { this.renderGlobalIcon() } - { tags } -
    - {createButton} -
    - { provided.placeholder } +
    + { this.renderGlobalIcon() } + { tags } +
    + {createButton}
    + { provided.placeholder } +
    ) } diff --git a/src/components/structures/GroupView.js b/src/components/structures/GroupView.js index ed6167cbe7..3ab009d7b8 100644 --- a/src/components/structures/GroupView.js +++ b/src/components/structures/GroupView.js @@ -43,7 +43,7 @@ import {mediaFromMxc} from "../../customisations/Media"; import {replaceableComponent} from "../../utils/replaceableComponent"; const LONG_DESC_PLACEHOLDER = _td( -`

    HTML for your community's page

    + `

    HTML for your community's page

    Use the long description to introduce new members to the community, or distribute some important links @@ -110,14 +110,16 @@ class CategoryRoomList extends React.Component { const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); Modal.createTrackedDialog( 'Failed to add the following room to the group summary', - '', ErrorDialog, - { - title: _t( - "Failed to add the following rooms to the summary of %(groupId)s:", - {groupId: this.props.groupId}, - ), - description: errorList.join(", "), - }); + '', + ErrorDialog, + { + title: _t( + "Failed to add the following rooms to the summary of %(groupId)s:", + {groupId: this.props.groupId}, + ), + description: errorList.join(", "), + }, + ); }); }, }, /*className=*/null, /*isPriority=*/false, /*isStatic=*/true); @@ -146,8 +148,8 @@ class CategoryRoomList extends React.Component { let catHeader =

    ; if (this.props.category && this.props.category.profile) { catHeader =
    - { this.props.category.profile.name } -
    ; + { this.props.category.profile.name } +
    ; } return
    { catHeader } @@ -190,13 +192,14 @@ class FeaturedRoom extends React.Component { Modal.createTrackedDialog( 'Failed to remove room from group summary', '', ErrorDialog, - { - title: _t( - "Failed to remove the room from the summary of %(groupId)s", - {groupId: this.props.groupId}, - ), - description: _t("The room '%(roomName)s' could not be removed from the summary.", {roomName}), - }); + { + title: _t( + "Failed to remove the room from the summary of %(groupId)s", + {groupId: this.props.groupId}, + ), + description: _t("The room '%(roomName)s' could not be removed from the summary.", {roomName}), + }, + ); }); }; @@ -283,13 +286,14 @@ class RoleUserList extends React.Component { Modal.createTrackedDialog( 'Failed to add the following users to the community summary', '', ErrorDialog, - { - title: _t( - "Failed to add the following users to the summary of %(groupId)s:", - {groupId: this.props.groupId}, - ), - description: errorList.join(", "), - }); + { + title: _t( + "Failed to add the following users to the summary of %(groupId)s:", + {groupId: this.props.groupId}, + ), + description: errorList.join(", "), + }, + ); }); }, }, /*className=*/null, /*isPriority=*/false, /*isStatic=*/true); @@ -299,11 +303,11 @@ class RoleUserList extends React.Component { const TintableSvg = sdk.getComponent("elements.TintableSvg"); const addButton = this.props.editing ? ( - -
    - { _t('Add a User') } -
    -
    ) :
    ; + +
    + { _t('Add a User') } +
    + ) :
    ; const userNodes = this.props.users.map((u) => { return - { _t("Leave %(groupName)s?", {groupName: this.props.groupId}) } - { warnings } + { _t("Leave %(groupName)s?", {groupName: this.props.groupId}) } + { warnings } ), button: _t("Leave"), @@ -1055,10 +1061,11 @@ export default class GroupView extends React.Component { return null; } - const membershipButtonClasses = classnames([ - 'mx_RoomHeader_textButton', - 'mx_GroupView_textButton', - ], + const membershipButtonClasses = classnames( + [ + 'mx_RoomHeader_textButton', + 'mx_GroupView_textButton', + ], membershipButtonExtraClasses, ); diff --git a/src/components/structures/LeftPanel.tsx b/src/components/structures/LeftPanel.tsx index e4762e35ad..7f9ef7516e 100644 --- a/src/components/structures/LeftPanel.tsx +++ b/src/components/structures/LeftPanel.tsx @@ -347,7 +347,7 @@ export default class LeftPanel extends React.Component { if (element) { classes = element.classList; } - } while (element && !cssClasses.some(c => classes.contains(c))); + } while (element && (!cssClasses.some(c => classes.contains(c)) || element.offsetParent === null)); if (element) { element.focus(); @@ -416,7 +416,7 @@ export default class LeftPanel extends React.Component { const roomList = ; } /** @@ -160,6 +164,7 @@ class LoggedInView extends React.Component { // use compact timeline view useCompactLayout: SettingsStore.getValue('useCompactLayout'), usageLimitDismissed: false, + activeCalls: [], }; // stash the MatrixClient in case we log out before we are unmounted @@ -175,6 +180,7 @@ class LoggedInView extends React.Component { componentDidMount() { document.addEventListener('keydown', this._onNativeKeyDown, false); + CallHandler.sharedInstance().addListener(CallHandlerEvent.CallsChanged, this.onCallsChanged); this._updateServerNoticeEvents(); @@ -199,6 +205,7 @@ class LoggedInView extends React.Component { componentWillUnmount() { document.removeEventListener('keydown', this._onNativeKeyDown, false); + CallHandler.sharedInstance().removeListener(CallHandlerEvent.CallsChanged, this.onCallsChanged); this._matrixClient.removeListener("accountData", this.onAccountData); this._matrixClient.removeListener("sync", this.onSync); this._matrixClient.removeListener("RoomState.events", this.onRoomStateEvents); @@ -206,6 +213,12 @@ class LoggedInView extends React.Component { this.resizer.detach(); } + private onCallsChanged = () => { + this.setState({ + activeCalls: CallHandler.sharedInstance().getAllActiveCalls(), + }); + }; + // Child components assume that the client peg will not be null, so give them some // sort of assurance here by only allowing a re-render if the client is truthy. // @@ -661,6 +674,12 @@ class LoggedInView extends React.Component { bodyClasses += ' mx_MatrixChat_useCompactLayout'; } + const audioFeedArraysForCalls = this.state.activeCalls.map((call) => { + return ( + + ); + }); + return (
    { + {audioFeedArraysForCalls} ); } diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index 078b296295..e330dc7d38 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -1094,7 +1094,7 @@ export default class MatrixChat extends React.PureComponent { private leaveRoomWarnings(roomId: string) { const roomToLeave = MatrixClientPeg.get().getRoom(roomId); - const isSpace = roomToLeave?.isSpaceRoom(); + const isSpace = SettingsStore.getValue("feature_spaces") && roomToLeave?.isSpaceRoom(); // Show a warning if there are additional complications. const warnings = []; @@ -1133,7 +1133,7 @@ export default class MatrixChat extends React.PureComponent { const roomToLeave = MatrixClientPeg.get().getRoom(roomId); const warnings = this.leaveRoomWarnings(roomId); - const isSpace = roomToLeave?.isSpaceRoom(); + const isSpace = SettingsStore.getValue("feature_spaces") && roomToLeave?.isSpaceRoom(); Modal.createTrackedDialog(isSpace ? "Leave space" : "Leave room", '', QuestionDialog, { title: isSpace ? _t("Leave space") : _t("Leave room"), description: ( diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index c6d45f87d8..0c61dd759c 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -427,8 +427,10 @@ export default class MessagePanel extends React.Component { // we get a new DOM node (restarting the animation) when the ghost // moves to a different event. return ( -
  • +
  • { hr }
  • ); @@ -1016,13 +1018,13 @@ class CreationGrouper { ret.push( - { eventTiles } + { eventTiles } , ); @@ -1226,11 +1228,11 @@ class MemberGrouper { ret.push( - { eventTiles } + { eventTiles } , ); diff --git a/src/components/structures/RightPanel.js b/src/components/structures/RightPanel.js index 5bcb3b2450..d8c763eabd 100644 --- a/src/components/structures/RightPanel.js +++ b/src/components/structures/RightPanel.js @@ -35,6 +35,7 @@ import {Action} from "../../dispatcher/actions"; import RoomSummaryCard from "../views/right_panel/RoomSummaryCard"; import WidgetCard from "../views/right_panel/WidgetCard"; import {replaceableComponent} from "../../utils/replaceableComponent"; +import SettingsStore from "../../settings/SettingsStore"; @replaceableComponent("structures.RightPanel") export default class RightPanel extends React.Component { @@ -85,7 +86,9 @@ export default class RightPanel extends React.Component { return RightPanelPhases.GroupMemberList; } return rps.groupPanelPhase; - } else if (this.props.room?.isSpaceRoom() && !RIGHT_PANEL_SPACE_PHASES.includes(rps.roomPanelPhase)) { + } else if (SettingsStore.getValue("feature_spaces") && this.props.room?.isSpaceRoom() + && !RIGHT_PANEL_SPACE_PHASES.includes(rps.roomPanelPhase) + ) { return RightPanelPhases.SpaceMemberList; } else if (userForPanel) { // XXX FIXME AAAAAARGH: What is going on with this class!? It takes some of its state diff --git a/src/components/structures/RoomSearch.tsx b/src/components/structures/RoomSearch.tsx index a64feed42c..34682877e0 100644 --- a/src/components/structures/RoomSearch.tsx +++ b/src/components/structures/RoomSearch.tsx @@ -17,6 +17,8 @@ limitations under the License. import * as React from "react"; import { createRef } from "react"; import classNames from "classnames"; +import { Room } from "matrix-js-sdk/src/models/room"; + import defaultDispatcher from "../../dispatcher/dispatcher"; import { _t } from "../../languageHandler"; import { ActionPayload } from "../../dispatcher/payloads"; @@ -26,7 +28,7 @@ import RoomListStore from "../../stores/room-list/RoomListStore"; import { NameFilterCondition } from "../../stores/room-list/filters/NameFilterCondition"; import { getKeyBindingsManager, RoomListAction } from "../../KeyBindingsManager"; import {replaceableComponent} from "../../utils/replaceableComponent"; -import SpaceStore, {UPDATE_SELECTED_SPACE} from "../../stores/SpaceStore"; +import SpaceStore, {UPDATE_SELECTED_SPACE, UPDATE_TOP_LEVEL_SPACES} from "../../stores/SpaceStore"; interface IProps { isMinimized: boolean; @@ -40,6 +42,7 @@ interface IProps { interface IState { query: string; focused: boolean; + inSpaces: boolean; } @replaceableComponent("structures.RoomSearch") @@ -54,11 +57,13 @@ export default class RoomSearch extends React.PureComponent { this.state = { query: "", focused: false, + inSpaces: false, }; this.dispatcherRef = defaultDispatcher.register(this.onAction); // clear filter when changing spaces, in future we may wish to maintain a filter per-space SpaceStore.instance.on(UPDATE_SELECTED_SPACE, this.clearInput); + SpaceStore.instance.on(UPDATE_TOP_LEVEL_SPACES, this.onSpaces); } public componentDidUpdate(prevProps: Readonly, prevState: Readonly): void { @@ -79,8 +84,15 @@ export default class RoomSearch extends React.PureComponent { public componentWillUnmount() { defaultDispatcher.unregister(this.dispatcherRef); SpaceStore.instance.off(UPDATE_SELECTED_SPACE, this.clearInput); + SpaceStore.instance.off(UPDATE_TOP_LEVEL_SPACES, this.onSpaces); } + private onSpaces = (spaces: Room[]) => { + this.setState({ + inSpaces: spaces.length > 0, + }); + }; + private onAction = (payload: ActionPayload) => { if (payload.action === 'view_room' && payload.clear_search) { this.clearInput(); @@ -152,6 +164,11 @@ export default class RoomSearch extends React.PureComponent { 'mx_RoomSearch_inputExpanded': this.state.query || this.state.focused, }); + let placeholder = _t("Filter"); + if (this.state.inSpaces) { + placeholder = _t("Filter all spaces"); + } + let icon = (
    ); @@ -165,7 +182,7 @@ export default class RoomSearch extends React.PureComponent { onBlur={this.onBlur} onChange={this.onChange} onKeyDown={this.onKeyDown} - placeholder={_t("Filter")} + placeholder={placeholder} autoComplete="off" /> ); diff --git a/src/components/structures/RoomStatusBar.js b/src/components/structures/RoomStatusBar.js index 54b6fee233..b2f0c70bd7 100644 --- a/src/components/structures/RoomStatusBar.js +++ b/src/components/structures/RoomStatusBar.js @@ -1,5 +1,5 @@ /* -Copyright 2015-2020 The Matrix.org Foundation C.I.C. +Copyright 2015-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. @@ -20,16 +20,20 @@ import { _t, _td } from '../../languageHandler'; import {MatrixClientPeg} from '../../MatrixClientPeg'; import Resend from '../../Resend'; import dis from '../../dispatcher/dispatcher'; -import {messageForResourceLimitError, messageForSendError} from '../../utils/ErrorUtils'; +import {messageForResourceLimitError} from '../../utils/ErrorUtils'; import {Action} from "../../dispatcher/actions"; import {replaceableComponent} from "../../utils/replaceableComponent"; import {EventStatus} from "matrix-js-sdk/src/models/event"; +import NotificationBadge from "../views/rooms/NotificationBadge"; +import {StaticNotificationState} from "../../stores/notifications/StaticNotificationState"; +import AccessibleButton from "../views/elements/AccessibleButton"; +import InlineSpinner from "../views/elements/InlineSpinner"; const STATUS_BAR_HIDDEN = 0; const STATUS_BAR_EXPANDED = 1; const STATUS_BAR_EXPANDED_LARGE = 2; -function getUnsentMessages(room) { +export function getUnsentMessages(room) { if (!room) { return []; } return room.getPendingEvents().filter(function(ev) { return ev.status === EventStatus.NOT_SENT; @@ -76,6 +80,7 @@ export default class RoomStatusBar extends React.Component { syncState: MatrixClientPeg.get().getSyncState(), syncStateData: MatrixClientPeg.get().getSyncStateData(), unsentMessages: getUnsentMessages(this.props.room), + isResending: false, }; componentDidMount() { @@ -109,7 +114,10 @@ export default class RoomStatusBar extends React.Component { }; _onResendAllClick = () => { - Resend.resendUnsentEvents(this.props.room); + Resend.resendUnsentEvents(this.props.room).then(() => { + this.setState({isResending: false}); + }); + this.setState({isResending: true}); dis.fire(Action.FocusComposer); }; @@ -120,9 +128,10 @@ export default class RoomStatusBar extends React.Component { _onRoomLocalEchoUpdated = (event, room, oldEventId, oldStatus) => { if (room.roomId !== this.props.room.roomId) return; - + const messages = getUnsentMessages(this.props.room); this.setState({ - unsentMessages: getUnsentMessages(this.props.room), + unsentMessages: messages, + isResending: messages.length > 0 && this.state.isResending, }); }; @@ -141,7 +150,7 @@ export default class RoomStatusBar extends React.Component { _getSize() { if (this._shouldShowConnectionError()) { return STATUS_BAR_EXPANDED; - } else if (this.state.unsentMessages.length > 0) { + } else if (this.state.unsentMessages.length > 0 || this.state.isResending) { return STATUS_BAR_EXPANDED_LARGE; } return STATUS_BAR_HIDDEN; @@ -162,7 +171,6 @@ export default class RoomStatusBar extends React.Component { _getUnsentMessageContent() { const unsentMessages = this.state.unsentMessages; - if (!unsentMessages.length) return null; let title; @@ -192,89 +200,92 @@ export default class RoomStatusBar extends React.Component { } else if (resourceLimitError) { title = messageForResourceLimitError( resourceLimitError.data.limit_type, - resourceLimitError.data.admin_contact, { - 'monthly_active_user': _td( - "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.", - ), - }); - } else if ( - unsentMessages.length === 1 && - unsentMessages[0].error && - unsentMessages[0].error.data && - unsentMessages[0].error.data.error - ) { - title = messageForSendError(unsentMessages[0].error.data) || unsentMessages[0].error.data.error; + resourceLimitError.data.admin_contact, + { + 'monthly_active_user': _td( + "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.", + ), + }, + ); } else { - title = _t('%(count)s of your messages have not been sent.', { count: unsentMessages.length }); + title = _t('Some of your messages have not been sent'); } - const content = _t("%(count)s Resend all or cancel all " + - "now. You can also select individual messages to resend or cancel.", - { count: unsentMessages.length }, - { - 'resendText': (sub) => - { sub }, - 'cancelText': (sub) => - { sub }, - }, - ); + let buttonRow = <> + + {_t("Delete all")} + + + {_t("Retry all")} + + ; + if (this.state.isResending) { + buttonRow = <> + + {/* span for css */} + {_t("Sending")} + ; + } - return
    - -
    -
    - { title } -
    -
    - { content } + return <> +
    +
    +
    + +
    +
    +
    + { title } +
    +
    + { _t("You can select all or individual messages to retry or delete") } +
    +
    +
    + {buttonRow} +
    -
    ; + ; } - // return suitable content for the main (text) part of the status bar. - _getContent() { + render() { if (this._shouldShowConnectionError()) { return ( -
    - /!\ -
    -
    - { _t('Connectivity to the server has been lost.') } -
    -
    - { _t('Sent messages will be stored until your connection has returned.') } +
    +
    +
    + /!\ +
    +
    + {_t('Connectivity to the server has been lost.')} +
    +
    + {_t('Sent messages will be stored until your connection has returned.')} +
    +
    ); } - if (this.state.unsentMessages.length > 0) { + if (this.state.unsentMessages.length > 0 || this.state.isResending) { return this._getUnsentMessageContent(); } return null; } - - render() { - const content = this._getContent(); - - return ( -
    -
    - { content } -
    -
    - ); - } } diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index 7168b7d139..58a87e6641 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -190,6 +190,9 @@ export interface IState { rejectError?: Error; hasPinnedWidgets?: boolean; dragCounter: number; + // whether or not a spaces context switch brought us here, + // if it did we don't want the room to be marked as read as soon as it is loaded. + wasContextSwitch?: boolean; } @replaceableComponent("structures.RoomView") @@ -326,6 +329,7 @@ export default class RoomView extends React.Component { shouldPeek: this.state.matrixClientIsReady && RoomViewStore.shouldPeek(), showingPinned: SettingsStore.getValue("PinnedEvents.isOpen", roomId), showReadReceipts: SettingsStore.getValue("showReadReceipts", roomId), + wasContextSwitch: RoomViewStore.getWasContextSwitch(), }; if (!initial && this.state.shouldPeek && !newState.shouldPeek) { @@ -1746,7 +1750,10 @@ export default class RoomView extends React.Component { } const myMembership = this.state.room.getMyMembership(); - if (myMembership === "invite" && !this.state.room.isSpaceRoom()) { // SpaceRoomView handles invites itself + if (myMembership === "invite" + // SpaceRoomView handles invites itself + && (!SettingsStore.getValue("feature_spaces") || !this.state.room.isSpaceRoom()) + ) { if (this.state.joining || this.state.rejecting) { return ( @@ -1888,7 +1895,7 @@ export default class RoomView extends React.Component { room={this.state.room} /> ); - if (!this.state.canPeek && !this.state.room?.isSpaceRoom()) { + if (!this.state.canPeek && (!SettingsStore.getValue("feature_spaces") || !this.state.room?.isSpaceRoom())) { return (
    { previewBar } @@ -2014,6 +2021,7 @@ export default class RoomView extends React.Component { timelineSet={this.state.room.getUnfilteredTimelineSet()} showReadReceipts={this.state.showReadReceipts} manageReadReceipts={!this.state.isPeeking} + sendReadReceiptOnLoad={!this.state.wasContextSwitch} manageReadMarkers={!this.state.isPeeking} hidden={hideMessagePanel} highlightedEventId={highlightedEventId} diff --git a/src/components/structures/ScrollPanel.js b/src/components/structures/ScrollPanel.js index 976734680c..5c5062633d 100644 --- a/src/components/structures/ScrollPanel.js +++ b/src/components/structures/ScrollPanel.js @@ -525,7 +525,7 @@ export default class ScrollPanel extends React.Component { */ scrollRelative = mult => { const scrollNode = this._getScrollNode(); - const delta = mult * scrollNode.clientHeight * 0.5; + const delta = mult * scrollNode.clientHeight * 0.9; scrollNode.scrollBy(0, delta); this._saveScrollState(); }; @@ -884,16 +884,20 @@ export default class ScrollPanel extends React.Component { // give the
      an explicit role=list because Safari+VoiceOver seems to think an ordered-list with // list-style-type: none; is no longer a list - return ( - { this.props.fixedChildren } -
      -
        - { this.props.children } -
      -
      -
      - ); + className={`mx_ScrollPanel ${this.props.className}`} + style={this.props.style} + > + { this.props.fixedChildren } +
      +
        + { this.props.children } +
      +
      + + ); } } diff --git a/src/components/structures/SpaceRoomDirectory.tsx b/src/components/structures/SpaceRoomDirectory.tsx index 930cfa15a9..74415cc58f 100644 --- a/src/components/structures/SpaceRoomDirectory.tsx +++ b/src/components/structures/SpaceRoomDirectory.tsx @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {useMemo, useState} from "react"; +import React, {ReactNode, useMemo, useState} from "react"; import {Room} from "matrix-js-sdk/src/models/room"; import {MatrixClient} from "matrix-js-sdk/src/client"; import {EventType, RoomType} from "matrix-js-sdk/src/@types/event"; @@ -24,7 +24,7 @@ import {sortBy} from "lodash"; import {MatrixClientPeg} from "../../MatrixClientPeg"; import dis from "../../dispatcher/dispatcher"; import {_t} from "../../languageHandler"; -import AccessibleButton from "../views/elements/AccessibleButton"; +import AccessibleButton, {ButtonEvent} from "../views/elements/AccessibleButton"; import BaseDialog from "../views/dialogs/BaseDialog"; import Spinner from "../views/elements/Spinner"; import SearchBox from "./SearchBox"; @@ -39,11 +39,14 @@ import {mediaFromMxc} from "../../customisations/Media"; import InfoTooltip from "../views/elements/InfoTooltip"; import TextWithTooltip from "../views/elements/TextWithTooltip"; import {useStateToggle} from "../../hooks/useStateToggle"; +import {getOrder} from "../../stores/SpaceStore"; +import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton"; interface IHierarchyProps { space: Room; initialText?: string; refreshToken?: any; + additionalButtons?: ReactNode; showRoom(room: ISpaceSummaryRoom, viaServers?: string[], autoJoin?: boolean): void; } @@ -106,8 +109,16 @@ const Tile: React.FC = ({ const cliRoom = cli.getRoom(room.room_id); const myMembership = cliRoom?.getMyMembership(); - const onPreviewClick = () => onViewRoomClick(false); - const onJoinClick = () => onViewRoomClick(true); + const onPreviewClick = (ev: ButtonEvent) => { + ev.preventDefault(); + ev.stopPropagation(); + onViewRoomClick(false); + } + const onJoinClick = (ev: ButtonEvent) => { + ev.preventDefault(); + ev.stopPropagation(); + onViewRoomClick(true); + } let button; if (myMembership === "join") { @@ -136,7 +147,7 @@ const Tile: React.FC = ({ let url: string; if (room.avatar_url) { - url = mediaFromMxc(room.avatar_url).getSquareThumbnailHttp(Math.floor(20 * window.devicePixelRatio)); + url = mediaFromMxc(room.avatar_url).getSquareThumbnailHttp(20); } let description = _t("%(count)s members", { count: room.num_joined_members }); @@ -254,7 +265,11 @@ export const HierarchyLevel = ({ const space = cli.getRoom(spaceId); const hasPermissions = space?.currentState.maySendStateEvent(EventType.SpaceChild, cli.getUserId()); - const sortedChildren = sortBy([...(relations.get(spaceId)?.values() || [])], ev => ev.content.order || null); + const children = Array.from(relations.get(spaceId)?.values() || []); + const sortedChildren = sortBy(children, ev => { + // XXX: Space Summary API doesn't give the child origin_server_ts but once it does we should use it for sorting + return getOrder(ev.content.order, null, ev.state_key); + }); const [subspaces, childRooms] = sortedChildren.reduce((result, ev: ISpaceSummaryEvent) => { const roomId = ev.state_key; if (!rooms.has(roomId)) return result; @@ -312,11 +327,12 @@ export const HierarchyLevel = ({ // mutate argument refreshToken to force a reload export const useSpaceSummary = (cli: MatrixClient, space: Room, refreshToken?: any): [ + null, ISpaceSummaryRoom[], - Map>, - Map>, - Map>, -] | [] => { + Map>?, + Map>?, + Map>?, +] | [Error] => { // TODO pagination return useAsyncMemo(async () => { try { @@ -336,13 +352,12 @@ export const useSpaceSummary = (cli: MatrixClient, space: Room, refreshToken?: a } }); - return [data.rooms as ISpaceSummaryRoom[], parentChildRelations, viaMap, childParentRelations]; + return [null, data.rooms as ISpaceSummaryRoom[], parentChildRelations, viaMap, childParentRelations]; } catch (e) { console.error(e); // TODO + return [e]; } - - return []; - }, [space, refreshToken], []); + }, [space, refreshToken], [undefined]); }; export const SpaceHierarchy: React.FC = ({ @@ -350,6 +365,7 @@ export const SpaceHierarchy: React.FC = ({ initialText = "", showRoom, refreshToken, + additionalButtons, children, }) => { const cli = MatrixClientPeg.get(); @@ -358,7 +374,7 @@ export const SpaceHierarchy: React.FC = ({ const [selected, setSelected] = useState(new Map>()); // Map> - const [rooms, parentChildMap, viaMap, childParentMap] = useSpaceSummary(cli, space, refreshToken); + const [summaryError, rooms, parentChildMap, viaMap, childParentMap] = useSpaceSummary(cli, space, refreshToken); const roomsMap = useMemo(() => { if (!rooms) return null; @@ -397,6 +413,10 @@ export const SpaceHierarchy: React.FC = ({ const [removing, setRemoving] = useState(false); const [saving, setSaving] = useState(false); + if (summaryError) { + return

      {_t("Your server does not support showing space hierarchies.")}

      ; + } + let content; if (roomsMap) { const numRooms = Array.from(roomsMap.values()).filter(r => r.room_type !== RoomType.Space).length; @@ -411,78 +431,83 @@ export const SpaceHierarchy: React.FC = ({ countsStr = _t("%(count)s rooms", { count: numRooms, numSpaces }); } - let editSection; + let manageButtons; if (space.getMyMembership() === "join" && space.currentState.maySendStateEvent(EventType.SpaceChild, userId)) { const selectedRelations = Array.from(selected.keys()).flatMap(parentId => { return [...selected.get(parentId).values()].map(childId => [parentId, childId]) as [string, string][]; }); - let buttons; - if (selectedRelations.length) { - const selectionAllSuggested = selectedRelations.every(([parentId, childId]) => { - return parentChildMap.get(parentId)?.get(childId)?.content.suggested; - }); + const selectionAllSuggested = selectedRelations.every(([parentId, childId]) => { + return parentChildMap.get(parentId)?.get(childId)?.content.suggested; + }); - const disabled = removing || saving; + const disabled = !selectedRelations.length || removing || saving; - buttons = <> - { - setRemoving(true); - try { - for (const [parentId, childId] of selectedRelations) { - await cli.sendStateEvent(parentId, EventType.SpaceChild, {}, childId); - parentChildMap.get(parentId).get(childId).content = {}; - parentChildMap.set(parentId, new Map(parentChildMap.get(parentId))); - } - } catch (e) { - setError(_t("Failed to remove some rooms. Try again later")); - } - setRemoving(false); - }} - kind="danger_outline" - disabled={disabled} - > - { removing ? _t("Removing...") : _t("Remove") } - - { - setSaving(true); - try { - for (const [parentId, childId] of selectedRelations) { - const suggested = !selectionAllSuggested; - const existingContent = parentChildMap.get(parentId)?.get(childId)?.content; - if (!existingContent || existingContent.suggested === suggested) continue; - - const content = { - ...existingContent, - suggested: !selectionAllSuggested, - }; - - await cli.sendStateEvent(parentId, EventType.SpaceChild, content, childId); - - parentChildMap.get(parentId).get(childId).content = content; - parentChildMap.set(parentId, new Map(parentChildMap.get(parentId))); - } - } catch (e) { - setError("Failed to update some suggestions. Try again later"); - } - setSaving(false); - }} - kind="primary_outline" - disabled={disabled} - > - { saving - ? _t("Saving...") - : (selectionAllSuggested ? _t("Mark as not suggested") : _t("Mark as suggested")) - } - - ; + let Button: React.ComponentType> = AccessibleButton; + let props = {}; + if (!selectedRelations.length) { + Button = AccessibleTooltipButton; + props = { + tooltip: _t("Select a room below first"), + yOffset: -40, + }; } - editSection = - { buttons } - ; + manageButtons = <> + + + ; } let results; @@ -528,7 +553,10 @@ export const SpaceHierarchy: React.FC = ({ content = <>
      { countsStr } - { editSection } + + { additionalButtons } + { manageButtons } +
      { error &&
      { error } @@ -538,10 +566,8 @@ export const SpaceHierarchy: React.FC = ({ { children } ; - } else if (!rooms) { - content = ; } else { - content =

      {_t("Your server does not support showing space hierarchies.")}

      ; + content = ; } // TODO loading state/error state diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx index 31358a3731..5db54815b7 100644 --- a/src/components/structures/SpaceRoomView.tsx +++ b/src/components/structures/SpaceRoomView.tsx @@ -51,6 +51,15 @@ import MemberAvatar from "../views/avatars/MemberAvatar"; import {useStateToggle} from "../../hooks/useStateToggle"; import SpaceStore from "../../stores/SpaceStore"; import FacePile from "../views/elements/FacePile"; +import {AddExistingToSpace} from "../views/dialogs/AddExistingToSpaceDialog"; +import {sleep} from "../../utils/promise"; +import {calculateRoomVia} from "../../utils/permalinks/Permalinks"; +import {ChevronFace, ContextMenuButton, useContextMenu} from "./ContextMenu"; +import IconizedContextMenu, { + IconizedContextMenuOption, + IconizedContextMenuOptionList, +} from "../views/context_menus/IconizedContextMenu"; +import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton"; interface IProps { space: Room; @@ -214,6 +223,67 @@ const SpacePreview = ({ space, onJoinButtonClicked, onRejectButtonClicked }) =>
      ; }; +const SpaceLandingAddButton = ({ space, onNewRoomAdded }) => { + const cli = useContext(MatrixClientContext); + const [menuDisplayed, handle, openMenu, closeMenu] = useContextMenu(); + + let contextMenu; + if (menuDisplayed) { + const rect = handle.current.getBoundingClientRect(); + contextMenu = + + { + e.preventDefault(); + e.stopPropagation(); + closeMenu(); + + if (await showCreateNewRoom(cli, space)) { + onNewRoomAdded(); + } + }} + /> + { + e.preventDefault(); + e.stopPropagation(); + closeMenu(); + + const [added] = await showAddExistingRooms(cli, space); + if (added) { + onNewRoomAdded(); + } + }} + /> + + ; + } + + return <> + + { _t("Add") } + + { contextMenu } + ; +}; + const SpaceLanding = ({ space }) => { const cli = useContext(MatrixClientContext); const myMembership = useMyRoomMembership(space); @@ -238,32 +308,20 @@ const SpaceLanding = ({ space }) => { const [refreshToken, forceUpdate] = useStateToggle(false); - let addRoomButtons; + let addRoomButton; if (canAddRooms) { - addRoomButtons = - { - const [added] = await showAddExistingRooms(cli, space); - if (added) { - forceUpdate(); - } - }}> - { _t("Add existing rooms & spaces") } - - { - showCreateNewRoom(cli, space); - }}> - { _t("Create a new room") } - - ; + addRoomButton = ; } let settingsButton; if (shouldShowSpaceSettings(cli, space)) { - settingsButton = { - showSpaceSettings(cli, space); - }}> - { _t("Settings") } - ; + settingsButton = { + showSpaceSettings(cli, space); + }} + title={_t("Settings")} + />; } const onMembersClick = () => { @@ -290,17 +348,19 @@ const SpaceLanding = ({ space }) => { { inviteButton } + { settingsButton }

    -
    - { addRoomButtons } - { settingsButton } -
    - +
    ; }; @@ -354,7 +414,7 @@ const SpaceSetupFirstRooms = ({ space, title, description, onFinished }) => { let buttonLabel = _t("Skip for now"); if (roomNames.some(name => name.trim())) { onClick = onNextClick; - buttonLabel = busy ? _t("Creating rooms...") : _t("Continue") + buttonLabel = busy ? _t("Creating rooms...") : _t("Continue"); } return
    @@ -376,6 +436,74 @@ const SpaceSetupFirstRooms = ({ space, title, description, onFinished }) => {
    ; }; +const SpaceAddExistingRooms = ({ space, onFinished }) => { + const [selectedToAdd, setSelectedToAdd] = useState(new Set()); + + const [busy, setBusy] = useState(false); + const [error, setError] = useState(""); + + let onClick = onFinished; + let buttonLabel = _t("Skip for now"); + if (selectedToAdd.size > 0) { + onClick = async () => { + setBusy(true); + + for (const room of selectedToAdd) { + const via = calculateRoomVia(room); + try { + await SpaceStore.instance.addRoomToSpace(space, room.roomId, via).catch(async e => { + if (e.errcode === "M_LIMIT_EXCEEDED") { + await sleep(e.data.retry_after_ms); + return SpaceStore.instance.addRoomToSpace(space, room.roomId, via); // retry + } + + throw e; + }); + } catch (e) { + console.error("Failed to add rooms to space", e); + setError(_t("Failed to add rooms to space")); + break; + } + } + setBusy(false); + }; + buttonLabel = busy ? _t("Adding...") : _t("Add"); + } + + return
    +

    { _t("What do you want to organise?") }

    +
    + { _t("Pick rooms or conversations to add. This is just a space for you, " + + "no one will be informed. You can add more later.") } +
    + + { error &&
    { error }
    } + + { + if (checked) { + selectedToAdd.add(room); + } else { + selectedToAdd.delete(room); + } + setSelectedToAdd(new Set(selectedToAdd)); + }} + /> + +
    + + { buttonLabel } + +
    +
    ; +}; + const SpaceSetupPublicShare = ({ space, onFinished }) => { return

    { _t("Share %(name)s", { name: space.name }) }

    @@ -659,7 +787,7 @@ export default class SpaceRoomView extends React.PureComponent { return { - this.setState({ phase: invite ? Phase.PrivateInvite : Phase.PrivateCreateRooms }); + this.setState({ phase: invite ? Phase.PrivateInvite : Phase.PrivateExistingRooms }); }} />; case Phase.PrivateInvite: @@ -675,6 +803,11 @@ export default class SpaceRoomView extends React.PureComponent { "You can add more later too, including already existing ones.")} onFinished={() => this.setState({ phase: Phase.Landing })} />; + case Phase.PrivateExistingRooms: + return this.setState({ phase: Phase.Landing })} + />; } } diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index 12f5d6e890..8cc344f66b 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -68,6 +68,7 @@ class TimelinePanel extends React.Component { showReadReceipts: PropTypes.bool, // Enable managing RRs and RMs. These require the timelineSet to have a room. manageReadReceipts: PropTypes.bool, + sendReadReceiptOnLoad: PropTypes.bool, manageReadMarkers: PropTypes.bool, // true to give the component a 'display: none' style. @@ -126,6 +127,7 @@ class TimelinePanel extends React.Component { // event tile heights. (See _unpaginateEvents) timelineCap: Number.MAX_VALUE, className: 'mx_RoomView_messagePanel', + sendReadReceiptOnLoad: true, }; constructor(props) { @@ -785,8 +787,10 @@ class TimelinePanel extends React.Component { return; } const lastDisplayedEvent = this.state.events[lastDisplayedIndex]; - this._setReadMarker(lastDisplayedEvent.getId(), - lastDisplayedEvent.getTs()); + this._setReadMarker( + lastDisplayedEvent.getId(), + lastDisplayedEvent.getTs(), + ); // the read-marker should become invisible, so that if the user scrolls // down, they don't see it. @@ -872,7 +876,7 @@ class TimelinePanel extends React.Component { // The messagepanel knows where the RM is, so we must have loaded // the relevant event. this._messagePanel.current.scrollToEvent(this.state.readMarkerEventId, - 0, 1/3); + 0, 1/3); return; } @@ -1044,12 +1048,14 @@ class TimelinePanel extends React.Component { } if (eventId) { this._messagePanel.current.scrollToEvent(eventId, pixelOffset, - offsetBase); + offsetBase); } else { this._messagePanel.current.scrollToBottom(); } - this.sendReadReceipt(); + if (this.props.sendReadReceiptOnLoad) { + this.sendReadReceipt(); + } }); }; @@ -1418,8 +1424,8 @@ class TimelinePanel extends React.Component { ['PREPARED', 'CATCHUP'].includes(this.state.clientSyncState) ); const events = this.state.firstVisibleEventIndex - ? this.state.events.slice(this.state.firstVisibleEventIndex) - : this.state.events; + ? this.state.events.slice(this.state.firstVisibleEventIndex) + : this.state.events; return ( void, +} + +interface IState { + loginView: number; + keyBackupNeeded: boolean; + busy: boolean; + password: string; + errorText: string; + flows: LoginFlow[]; +} + +@replaceableComponent("structures.auth.SoftLogout") +export default class SoftLogout extends React.Component { + constructor(props) { + super(props); this.state = { loginView: LOGIN_VIEW.LOADING, keyBackupNeeded: true, // assume we do while we figure it out (see componentDidMount) - busy: false, password: "", errorText: "", + flows: [], }; } @@ -72,7 +83,7 @@ export default class SoftLogout extends React.Component { return; } - this._initLogin(); + this.initLogin(); const cli = MatrixClientPeg.get(); if (cli.isCryptoEnabled()) { @@ -94,7 +105,7 @@ export default class SoftLogout extends React.Component { }); }; - async _initLogin() { + private async initLogin() { const queryParams = this.props.realQueryParams; const hasAllParams = queryParams && queryParams['loginToken']; if (hasAllParams) { @@ -189,7 +200,7 @@ export default class SoftLogout extends React.Component { }); } - _renderSignInSection() { + private renderSignInSection() { if (this.state.loginView === LOGIN_VIEW.LOADING) { const Spinner = sdk.getComponent("elements.Spinner"); return ; @@ -247,7 +258,7 @@ export default class SoftLogout extends React.Component { } // else we already have a message and should use it (key backup warning) const loginType = this.state.loginView === LOGIN_VIEW.CAS ? "cas" : "sso"; - const flow = this.state.flows.find(flow => flow.type === "m.login." + loginType); + const flow = this.state.flows.find(flow => flow.type === "m.login." + loginType) as ISSOFlow; return (
    @@ -289,7 +300,7 @@ export default class SoftLogout extends React.Component {

    {_t("Sign in")}

    - {this._renderSignInSection()} + {this.renderSignInSection()}

    {_t("Clear personal data")}

    diff --git a/src/components/views/auth/InteractiveAuthEntryComponents.js b/src/components/views/auth/InteractiveAuthEntryComponents.js index 6cbecd22ee..e34349c474 100644 --- a/src/components/views/auth/InteractiveAuthEntryComponents.js +++ b/src/components/views/auth/InteractiveAuthEntryComponents.js @@ -169,7 +169,7 @@ export class PasswordAuthEntry extends React.Component { { submitButtonOrSpinner }
    - { errorSection } + { errorSection }
    ); } @@ -375,7 +375,7 @@ export class TermsAuthEntry extends React.Component { if (this.props.showContinue !== false) { // XXX: button classes submitButton = ; + onClick={this._trySubmit} disabled={!allChecked}>{_t("Accept")}; } return ( diff --git a/src/components/views/avatars/MemberAvatar.tsx b/src/components/views/avatars/MemberAvatar.tsx index c79cbc0d32..3205ca372c 100644 --- a/src/components/views/avatars/MemberAvatar.tsx +++ b/src/components/views/avatars/MemberAvatar.tsx @@ -68,8 +68,8 @@ export default class MemberAvatar extends React.Component { let imageUrl = null; if (props.member.getMxcAvatarUrl()) { imageUrl = mediaFromMxc(props.member.getMxcAvatarUrl()).getThumbnailOfSourceHttp( - Math.floor(props.width * window.devicePixelRatio), - Math.floor(props.height * window.devicePixelRatio), + props.width, + props.height, props.resizeMethod, ); } diff --git a/src/components/views/avatars/RoomAvatar.tsx b/src/components/views/avatars/RoomAvatar.tsx index ad0eb45a52..4693d907ba 100644 --- a/src/components/views/avatars/RoomAvatar.tsx +++ b/src/components/views/avatars/RoomAvatar.tsx @@ -93,8 +93,8 @@ export default class RoomAvatar extends React.Component { let oobAvatar = null; if (props.oobData.avatarUrl) { oobAvatar = mediaFromMxc(props.oobData.avatarUrl).getThumbnailOfSourceHttp( - Math.floor(props.width * window.devicePixelRatio), - Math.floor(props.height * window.devicePixelRatio), + props.width, + props.height, props.resizeMethod, ); } @@ -109,12 +109,7 @@ export default class RoomAvatar extends React.Component { private static getRoomAvatarUrl(props: IProps): string { if (!props.room) return null; - return Avatar.avatarUrlForRoom( - props.room, - Math.floor(props.width * window.devicePixelRatio), - Math.floor(props.height * window.devicePixelRatio), - props.resizeMethod, - ); + return Avatar.avatarUrlForRoom(props.room, props.width, props.height, props.resizeMethod); } private onRoomAvatarClick = () => { diff --git a/src/components/views/context_menus/MessageContextMenu.js b/src/components/views/context_menus/MessageContextMenu.js index f86cd26f32..35efd12c9c 100644 --- a/src/components/views/context_menus/MessageContextMenu.js +++ b/src/components/views/context_menus/MessageContextMenu.js @@ -1,8 +1,6 @@ /* -Copyright 2015, 2016 OpenMarket Ltd -Copyright 2018 New Vector Ltd Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> -Copyright 2019 The Matrix.org Foundation C.I.C. +Copyright 2015, 2016, 2018, 2019, 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. @@ -34,7 +32,7 @@ import {MenuItem} from "../../structures/ContextMenu"; import {EventType} from "matrix-js-sdk/src/@types/event"; import {replaceableComponent} from "../../../utils/replaceableComponent"; -function canCancel(eventStatus) { +export function canCancel(eventStatus) { return eventStatus === EventStatus.QUEUED || eventStatus === EventStatus.NOT_SENT; } @@ -98,21 +96,6 @@ export default class MessageContextMenu extends React.Component { return content.pinned && Array.isArray(content.pinned) && content.pinned.includes(this.props.mxEvent.getId()); } - onResendClick = () => { - Resend.resend(this.props.mxEvent); - this.closeMenu(); - }; - - onResendEditClick = () => { - Resend.resend(this.props.mxEvent.replacingEvent()); - this.closeMenu(); - }; - - onResendRedactionClick = () => { - Resend.resend(this.props.mxEvent.localRedactionEvent()); - this.closeMenu(); - }; - onResendReactionsClick = () => { for (const reaction of this._getUnsentReactions()) { Resend.resend(reaction); @@ -170,29 +153,6 @@ export default class MessageContextMenu extends React.Component { this.closeMenu(); }; - onCancelSendClick = () => { - const mxEvent = this.props.mxEvent; - const editEvent = mxEvent.replacingEvent(); - const redactEvent = mxEvent.localRedactionEvent(); - const pendingReactions = this._getPendingReactions(); - - if (editEvent && canCancel(editEvent.status)) { - Resend.removeFromQueue(editEvent); - } - if (redactEvent && canCancel(redactEvent.status)) { - Resend.removeFromQueue(redactEvent); - } - if (pendingReactions.length) { - for (const reaction of pendingReactions) { - Resend.removeFromQueue(reaction); - } - } - if (canCancel(mxEvent.status)) { - Resend.removeFromQueue(this.props.mxEvent); - } - this.closeMenu(); - }; - onForwardClick = () => { if (this.props.onCloseDialog) this.props.onCloseDialog(); dis.dispatch({ @@ -285,20 +245,9 @@ export default class MessageContextMenu extends React.Component { const me = cli.getUserId(); const mxEvent = this.props.mxEvent; const eventStatus = mxEvent.status; - const editStatus = mxEvent.replacingEvent() && mxEvent.replacingEvent().status; - const redactStatus = mxEvent.localRedactionEvent() && mxEvent.localRedactionEvent().status; const unsentReactionsCount = this._getUnsentReactions().length; - const pendingReactionsCount = this._getPendingReactions().length; - const allowCancel = canCancel(mxEvent.status) || - canCancel(editStatus) || - canCancel(redactStatus) || - pendingReactionsCount !== 0; - let resendButton; - let resendEditButton; let resendReactionsButton; - let resendRedactionButton; let redactButton; - let cancelButton; let forwardButton; let pinButton; let unhidePreviewButton; @@ -309,22 +258,6 @@ export default class MessageContextMenu extends React.Component { // status is SENT before remote-echo, null after const isSent = !eventStatus || eventStatus === EventStatus.SENT; if (!mxEvent.isRedacted()) { - if (eventStatus === EventStatus.NOT_SENT) { - resendButton = ( - - { _t('Resend') } - - ); - } - - if (editStatus === EventStatus.NOT_SENT) { - resendEditButton = ( - - { _t('Resend edit') } - - ); - } - if (unsentReactionsCount !== 0) { resendReactionsButton = ( @@ -334,14 +267,6 @@ export default class MessageContextMenu extends React.Component { } } - if (redactStatus === EventStatus.NOT_SENT) { - resendRedactionButton = ( - - { _t('Resend removal') } - - ); - } - if (isSent && this.state.canRedact) { redactButton = ( @@ -350,14 +275,6 @@ export default class MessageContextMenu extends React.Component { ); } - if (allowCancel) { - cancelButton = ( - - { _t('Cancel Sending') } - - ); - } - if (isContentActionable(mxEvent)) { forwardButton = ( @@ -433,7 +350,7 @@ export default class MessageContextMenu extends React.Component { > { _t('Source URL') } - ); + ); } if (this.props.collapseReplyThread) { @@ -455,12 +372,8 @@ export default class MessageContextMenu extends React.Component { return (
    - { resendButton } - { resendEditButton } { resendReactionsButton } - { resendRedactionButton } { redactButton } - { cancelButton } { forwardButton } { pinButton } { viewSourceButton } diff --git a/src/components/views/dialogs/AddExistingToSpaceDialog.tsx b/src/components/views/dialogs/AddExistingToSpaceDialog.tsx index 0f58a624f3..a33248200c 100644 --- a/src/components/views/dialogs/AddExistingToSpaceDialog.tsx +++ b/src/components/views/dialogs/AddExistingToSpaceDialog.tsx @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {useState} from "react"; +import React, {useContext, useMemo, useState} from "react"; import classNames from "classnames"; import {Room} from "matrix-js-sdk/src/models/room"; import {MatrixClient} from "matrix-js-sdk/src/client"; @@ -29,10 +29,13 @@ import RoomAvatar from "../avatars/RoomAvatar"; import {getDisplayAliasForRoom} from "../../../Rooms"; import AccessibleButton from "../elements/AccessibleButton"; import AutoHideScrollbar from "../../structures/AutoHideScrollbar"; -import {allSettled} from "../../../utils/promise"; +import {sleep} from "../../../utils/promise"; import DMRoomMap from "../../../utils/DMRoomMap"; import {calculateRoomVia} from "../../../utils/permalinks/Permalinks"; import StyledCheckbox from "../elements/StyledCheckbox"; +import MatrixClientContext from "../../../contexts/MatrixClientContext"; +import {sortRooms} from "../../../stores/room-list/algorithms/tag-sorting/RecentAlgorithm"; +import ProgressBar from "../elements/ProgressBar"; interface IProps extends IDialogProps { matrixClient: MatrixClient; @@ -41,45 +44,128 @@ interface IProps extends IDialogProps { } const Entry = ({ room, checked, onChange }) => { - return
    + return
    ; + { room.name } + onChange(e.target.checked) : null} + checked={checked} + disabled={!onChange} + /> + ; }; -const AddExistingToSpaceDialog: React.FC = ({ matrixClient: cli, space, onCreateRoomClick, onFinished }) => { +interface IAddExistingToSpaceProps { + space: Room; + selected: Set; + onChange(checked: boolean, room: Room): void; +} + +export const AddExistingToSpace: React.FC = ({ space, selected, onChange }) => { + const cli = useContext(MatrixClientContext); + const visibleRooms = useMemo(() => sortRooms(cli.getVisibleRooms()), [cli]); + const [query, setQuery] = useState(""); const lcQuery = query.toLowerCase(); - const [selectedSpace, setSelectedSpace] = useState(space); - const [selectedToAdd, setSelectedToAdd] = useState(new Set()); - const existingSubspaces = SpaceStore.instance.getChildSpaces(space.roomId); const existingSubspacesSet = new Set(existingSubspaces); const existingRoomsSet = new Set(SpaceStore.instance.getChildRooms(space.roomId)); - const joinRule = selectedSpace.getJoinRule(); - const [spaces, rooms, dms] = cli.getVisibleRooms().reduce((arr, room) => { + const joinRule = space.getJoinRule(); + const [spaces, rooms, dms] = visibleRooms.reduce((arr, room) => { if (room.getMyMembership() !== "join") return arr; if (!room.name.toLowerCase().includes(lcQuery)) return arr; if (room.isSpaceRoom()) { - if (room !== space && room !== selectedSpace && !existingSubspacesSet.has(room)) { + if (room !== space && !existingSubspacesSet.has(room)) { arr[0].push(room); } - } else if (!existingRoomsSet.has(room) && joinRule !== "public") { - // Only show DMs for non-public spaces as they make very little sense in spaces other than "Just Me" ones. - arr[DMRoomMap.shared().getUserIdForRoomId(room.roomId) ? 2 : 1].push(room); + } else if (!existingRoomsSet.has(room)) { + if (!DMRoomMap.shared().getUserIdForRoomId(room.roomId)) { + arr[1].push(room); + } else if (joinRule !== "public") { + // Only show DMs for non-public spaces as they make very little sense in spaces other than "Just Me" ones. + arr[2].push(room); + } } return arr; }, [[], [], []]); - const [busy, setBusy] = useState(false); - const [error, setError] = useState(""); + return
    + + + { rooms.length > 0 ? ( +
    +

    { _t("Rooms") }

    + { rooms.map(room => { + return { + onChange(checked, room); + } : null} + />; + }) } +
    + ) : undefined } + + { spaces.length > 0 ? ( +
    +

    { _t("Spaces") }

    + { spaces.map(space => { + return { + onChange(checked, space); + } : null} + />; + }) } +
    + ) : null } + + { dms.length > 0 ? ( +
    +

    { _t("Direct Messages") }

    + { dms.map(room => { + return { + onChange(checked, room); + } : null} + />; + }) } +
    + ) : null } + + { spaces.length + rooms.length + dms.length < 1 ? + { _t("No results") } + : undefined } +
    +
    ; +}; + +const AddExistingToSpaceDialog: React.FC = ({ matrixClient: cli, space, onCreateRoomClick, onFinished }) => { + const [selectedSpace, setSelectedSpace] = useState(space); + const existingSubspaces = SpaceStore.instance.getChildSpaces(space.roomId); + const [selectedToAdd, setSelectedToAdd] = useState(new Set()); + + const [progress, setProgress] = useState(null); + const [error, setError] = useState(null); let spaceOptionSection; - if (existingSubspacesSet.size > 0) { + if (existingSubspaces.length > 0) { const options = [space, ...existingSubspaces].map((space) => { const classes = classNames("mx_AddExistingToSpaceDialog_dropdownOption", { mx_AddExistingToSpaceDialog_dropdownOptionActive: space === selectedSpace, @@ -116,116 +202,106 @@ const AddExistingToSpaceDialog: React.FC = ({ matrixClient: cli, space,
    ; - return - { error &&
    { error }
    } + const addRooms = async () => { + setError(null); + setProgress(0); - - - { rooms.length > 0 ? ( -
    -

    { _t("Rooms") }

    - { rooms.map(room => { - return { - if (checked) { - selectedToAdd.add(room); - } else { - selectedToAdd.delete(room); - } - setSelectedToAdd(new Set(selectedToAdd)); - }} - />; - }) } -
    - ) : undefined } + let error; - { spaces.length > 0 ? ( -
    -

    { _t("Spaces") }

    - { spaces.map(space => { - return { - if (checked) { - selectedToAdd.add(space); - } else { - selectedToAdd.delete(space); - } - setSelectedToAdd(new Set(selectedToAdd)); - }} - />; - }) } -
    - ) : null } + for (const room of selectedToAdd) { + const via = calculateRoomVia(room); + try { + await SpaceStore.instance.addRoomToSpace(space, room.roomId, via).catch(async e => { + if (e.errcode === "M_LIMIT_EXCEEDED") { + await sleep(e.data.retry_after_ms); + return SpaceStore.instance.addRoomToSpace(space, room.roomId, via); // retry + } - { dms.length > 0 ? ( -
    -

    { _t("Direct Messages") }

    - { dms.map(space => { - return { - if (checked) { - selectedToAdd.add(space); - } else { - selectedToAdd.delete(space); - } - setSelectedToAdd(new Set(selectedToAdd)); - }} - />; - }) } -
    - ) : null } + throw e; + }); + setProgress(i => i + 1); + } catch (e) { + console.error("Failed to add rooms to space", e); + setError(error = e); + break; + } + } - { spaces.length + rooms.length + dms.length < 1 ? - { _t("No results") } - : undefined } -
    + if (!error) { + onFinished(true); + } + }; -
    + const busy = progress !== null; + + let footer; + if (error) { + footer = <> + + + +
    { _t("Not all selected were added") }
    +
    { _t("Try again") }
    +
    + + + { _t("Retry") } + + ; + } else if (busy) { + footer = + +
    + { _t("Adding rooms... (%(progress)s out of %(count)s)", { + count: selectedToAdd.size, + progress, + }) } +
    +
    ; + } else { + footer = <> -
    { _t("Don't want to add an existing room?") }
    +
    { _t("Want to add a new room instead?") }
    onCreateRoomClick(cli, space)} kind="link"> { _t("Create a new room") }
    - { - setBusy(true); - try { - await allSettled(Array.from(selectedToAdd).map((room) => - SpaceStore.instance.addRoomToSpace(space, room.roomId, calculateRoomVia(room)))); - onFinished(true); - } catch (e) { - console.error("Failed to add rooms to space", e); - setError(_t("Failed to add rooms to space")); - } - setBusy(false); - }} - > - { busy ? _t("Adding...") : _t("Add") } + + { _t("Add") } + ; + } + + return + + { + if (checked) { + selectedToAdd.add(room); + } else { + selectedToAdd.delete(room); + } + setSelectedToAdd(new Set(selectedToAdd)); + } : null} + /> + + +
    + { footer }
    ; }; diff --git a/src/components/views/dialogs/BugReportDialog.js b/src/components/views/dialogs/BugReportDialog.js index 8948c14c7c..cbe0130649 100644 --- a/src/components/views/dialogs/BugReportDialog.js +++ b/src/components/views/dialogs/BugReportDialog.js @@ -184,7 +184,7 @@ export default class BugReportDialog extends React.Component { return (
    diff --git a/src/components/views/dialogs/ChangelogDialog.js b/src/components/views/dialogs/ChangelogDialog.js index 50bc13cff5..efbeba3977 100644 --- a/src/components/views/dialogs/ChangelogDialog.js +++ b/src/components/views/dialogs/ChangelogDialog.js @@ -95,7 +95,7 @@ export default class ChangelogDialog extends React.Component { description={content} button={_t("Update")} onFinished={this.props.onFinished} - /> + /> ); } } diff --git a/src/components/views/dialogs/ConfirmWipeDeviceDialog.js b/src/components/views/dialogs/ConfirmWipeDeviceDialog.js index 4faaad0f7e..333e1522f1 100644 --- a/src/components/views/dialogs/ConfirmWipeDeviceDialog.js +++ b/src/components/views/dialogs/ConfirmWipeDeviceDialog.js @@ -39,9 +39,12 @@ export default class ConfirmWipeDeviceDialog extends React.Component { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); return ( - +

    {_t( diff --git a/src/components/views/dialogs/DevtoolsDialog.js b/src/components/views/dialogs/DevtoolsDialog.js index 9f5513e0a3..8a035263cc 100644 --- a/src/components/views/dialogs/DevtoolsDialog.js +++ b/src/components/views/dialogs/DevtoolsDialog.js @@ -70,8 +70,16 @@ class GenericEditor extends React.PureComponent { } textInput(id, label) { - return ; + return ; } } @@ -155,7 +163,7 @@ export class SendCustomEvent extends GenericEditor {
    + autoComplete="off" value={this.state.evContent} onChange={this._onChange} element="textarea" />

    @@ -239,7 +247,7 @@ class SendAccountData extends GenericEditor {
    + autoComplete="off" value={this.state.evContent} onChange={this._onChange} element="textarea" />
    @@ -315,15 +323,15 @@ class FilteredList extends React.PureComponent { const TruncatedList = sdk.getComponent("elements.TruncatedList"); return
    + type="text" autoComplete="off" value={this.props.query} onChange={this.onQuery} + className="mx_TextInputDialog_input mx_DevTools_RoomStateExplorer_query" + // force re-render so that autoFocus is applied when this component is re-used + key={this.props.children[0] ? this.props.children[0].key : ''} /> + getChildCount={this.getChildCount} + truncateAt={this.state.truncateAt} + createOverflowElement={this.createOverflowElement} />
    ; } } @@ -647,7 +655,7 @@ function VerificationRequest({txnId, request}) { /* Note that request.timeout is a getter, so its value changes */ const id = setInterval(() => { - setRequestTimeout(request.timeout); + setRequestTimeout(request.timeout); }, 500); return () => { clearInterval(id); }; @@ -941,35 +949,35 @@ class SettingsExplorer extends React.Component { /> - - - - - + + + + + - {allSettings.map(i => ( - - + - - - - ))} + + + + + + ))}
    {_t("Setting ID")}{_t("Value")}{_t("Value in this room")}
    {_t("Setting ID")}{_t("Value")}{_t("Value in this room")}
    - this.onViewClick(e, i)}> - {i} - - this.onEditClick(e, i)} - className='mx_DevTools_SettingsExplorer_edit' - > + {allSettings.map(i => ( +
    + this.onViewClick(e, i)}> + {i} + + this.onEditClick(e, i)} + className='mx_DevTools_SettingsExplorer_edit' + > ✏ - - - {this.renderSettingValue(SettingsStore.getValue(i))} - - - {this.renderSettingValue(SettingsStore.getValue(i, room.roomId))} - -
    + {this.renderSettingValue(SettingsStore.getValue(i))} + + + {this.renderSettingValue(SettingsStore.getValue(i, room.roomId))} + +
    @@ -998,11 +1006,11 @@ class SettingsExplorer extends React.Component {
    - - - - - + + + + + {LEVEL_ORDER.map(lvl => ( diff --git a/src/components/views/dialogs/IncomingSasDialog.js b/src/components/views/dialogs/IncomingSasDialog.js index f18b7a9d0c..5df02d7a6f 100644 --- a/src/components/views/dialogs/IncomingSasDialog.js +++ b/src/components/views/dialogs/IncomingSasDialog.js @@ -130,7 +130,7 @@ export default class IncomingSasDialog extends React.Component { const oppProfile = this.state.opponentProfile; if (oppProfile) { const url = oppProfile.avatar_url - ? mediaFromMxc(oppProfile.avatar_url).getSquareThumbnailHttp(Math.floor(48 * window.devicePixelRatio)) + ? mediaFromMxc(oppProfile.avatar_url).getSquareThumbnailHttp(48) : null; profile =
    +

    {_t("Enable 'Manage Integrations' in Settings to do this.")}

    diff --git a/src/components/views/dialogs/IntegrationsImpossibleDialog.js b/src/components/views/dialogs/IntegrationsImpossibleDialog.js index 9bc9d02ba6..e14d40aaef 100644 --- a/src/components/views/dialogs/IntegrationsImpossibleDialog.js +++ b/src/components/views/dialogs/IntegrationsImpossibleDialog.js @@ -37,9 +37,12 @@ export default class IntegrationsImpossibleDialog extends React.Component { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); return ( - +

    {_t( diff --git a/src/components/views/dialogs/InviteDialog.tsx b/src/components/views/dialogs/InviteDialog.tsx index 2ebc84ec7c..ec9c71ccbe 100644 --- a/src/components/views/dialogs/InviteDialog.tsx +++ b/src/components/views/dialogs/InviteDialog.tsx @@ -1312,7 +1312,7 @@ export default class InviteDialog extends React.PureComponent {success ? - {_t("Upload completed")} : - cancelled ? - {_t("Cancelled signature upload")} : - {_t("Unable to upload")}} + {_t("Upload completed")} : + cancelled ? + {_t("Cancelled signature upload")} : + {_t("Unable to upload")}} + {content} ); diff --git a/src/components/views/dialogs/RoomSettingsDialog.js b/src/components/views/dialogs/RoomSettingsDialog.js index 9c2f23ef22..b6c4d42243 100644 --- a/src/components/views/dialogs/RoomSettingsDialog.js +++ b/src/components/views/dialogs/RoomSettingsDialog.js @@ -116,8 +116,12 @@ export default class RoomSettingsDialog extends React.Component { const roomName = MatrixClientPeg.get().getRoom(this.props.roomId).name; return ( - +

    diff --git a/src/components/views/dialogs/ServerPickerDialog.tsx b/src/components/views/dialogs/ServerPickerDialog.tsx index 4abc0a88b1..62a2b95c68 100644 --- a/src/components/views/dialogs/ServerPickerDialog.tsx +++ b/src/components/views/dialogs/ServerPickerDialog.tsx @@ -1,5 +1,5 @@ /* -Copyright 2020 The Matrix.org Foundation C.I.C. +Copyright 2020-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. @@ -110,7 +110,7 @@ export default class ServerPickerDialog extends React.PureComponent diff --git a/src/components/views/dialogs/SessionRestoreErrorDialog.js b/src/components/views/dialogs/SessionRestoreErrorDialog.js index 50d7fbea09..43e73a2f83 100644 --- a/src/components/views/dialogs/SessionRestoreErrorDialog.js +++ b/src/components/views/dialogs/SessionRestoreErrorDialog.js @@ -98,7 +98,7 @@ export default class SessionRestoreErrorDialog extends React.Component { "may be incompatible with this version. Close this window and return " + "to the more recent version.", { brand }, - ) }

    + ) }

    { _t( "Clearing your browser's storage may fix the problem, but will sign you " + diff --git a/src/components/views/dialogs/StorageEvictedDialog.js b/src/components/views/dialogs/StorageEvictedDialog.js index 15c5347644..1e17ab1738 100644 --- a/src/components/views/dialogs/StorageEvictedDialog.js +++ b/src/components/views/dialogs/StorageEvictedDialog.js @@ -45,10 +45,12 @@ export default class StorageEvictedDialog extends React.Component { let logRequest; if (SdkConfig.get().bug_report_endpoint_url) { logRequest = _t( - "To help us prevent this in future, please send us logs.", {}, - { - a: text => {text}, - }); + "To help us prevent this in future, please send us logs.", + {}, + { + a: text => {text}, + }, + ); } return ( diff --git a/src/components/views/dialogs/UserSettingsDialog.js b/src/components/views/dialogs/UserSettingsDialog.js index eb9eaeb5dd..e7f6953589 100644 --- a/src/components/views/dialogs/UserSettingsDialog.js +++ b/src/components/views/dialogs/UserSettingsDialog.js @@ -155,8 +155,12 @@ export default class UserSettingsDialog extends React.Component { const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog'); return ( - +

    diff --git a/src/components/views/dialogs/VerificationRequestDialog.js b/src/components/views/dialogs/VerificationRequestDialog.js index 205597a1c4..9281275e6a 100644 --- a/src/components/views/dialogs/VerificationRequestDialog.js +++ b/src/components/views/dialogs/VerificationRequestDialog.js @@ -52,11 +52,13 @@ export default class VerificationRequestDialog extends React.Component { const title = request && request.isSelfVerification ? _t("Verify other login") : _t("Verification Request"); - return + return +

    {_t("The widget will verify your user ID, but won't be able to perform actions for you:")} diff --git a/src/components/views/dialogs/security/ConfirmDestroyCrossSigningDialog.js b/src/components/views/dialogs/security/ConfirmDestroyCrossSigningDialog.js index 43fb25f152..e71983b074 100644 --- a/src/components/views/dialogs/security/ConfirmDestroyCrossSigningDialog.js +++ b/src/components/views/dialogs/security/ConfirmDestroyCrossSigningDialog.js @@ -40,10 +40,11 @@ export default class ConfirmDestroyCrossSigningDialog extends React.Component { return ( + className='mx_ConfirmDestroyCrossSigningDialog' + hasCancel={true} + onFinished={this.props.onFinished} + title={_t("Destroy cross-signing keys?")} + >

    {_t( diff --git a/src/components/views/dialogs/security/RestoreKeyBackupDialog.js b/src/components/views/dialogs/security/RestoreKeyBackupDialog.js index 1fafe03d95..4ac15ab5a3 100644 --- a/src/components/views/dialogs/security/RestoreKeyBackupDialog.js +++ b/src/components/views/dialogs/security/RestoreKeyBackupDialog.js @@ -373,21 +373,24 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { {_t( "If you've forgotten your Security Phrase you can "+ "use your Security Key or " + - "set up new recovery options" - , {}, { - button1: s => - {s} - , - button2: s => - {s} - , - })} + "set up new recovery options", + {}, + { + button1: s => + {s} + , + button2: s => + {s} + , + })}

    ; } else { title = _t("Enter Security Key"); @@ -435,15 +438,17 @@ export default class RestoreKeyBackupDialog extends React.PureComponent {
    {_t( "If you've forgotten your Security Key you can "+ - "" - , {}, { - button: s => - {s} - , - })} + "", + {}, + { + button: s => + {s} + , + }, + )}
    ; } @@ -452,9 +457,9 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { onFinished={this.props.onFinished} title={title} > -
    - {content} -
    +
    + {content} +
    ); } diff --git a/src/components/views/elements/ActionButton.js b/src/components/views/elements/ActionButton.js index 1714891cb5..9903c631b2 100644 --- a/src/components/views/elements/ActionButton.js +++ b/src/components/views/elements/ActionButton.js @@ -70,8 +70,8 @@ export default class ActionButton extends React.Component { } const icon = this.props.iconPath ? - () : - undefined; + () : + undefined; const classNames = ["mx_RoleButton"]; if (this.props.className) { diff --git a/src/components/views/elements/AppTile.js b/src/components/views/elements/AppTile.js index e206fda797..b898ad2ebc 100644 --- a/src/components/views/elements/AppTile.js +++ b/src/components/views/elements/AppTile.js @@ -109,7 +109,7 @@ export default class AppTile extends React.Component { const childContentProtocol = u.protocol; if (parentContentProtocol === 'https:' && childContentProtocol !== 'https:') { console.warn("Refusing to load mixed-content app:", - parentContentProtocol, childContentProtocol, window.location, this.props.app.url); + parentContentProtocol, childContentProtocol, window.location, this.props.app.url); return true; } return false; diff --git a/src/components/views/elements/EditableItemList.js b/src/components/views/elements/EditableItemList.js index ff62f169fa..d8ec5af278 100644 --- a/src/components/views/elements/EditableItemList.js +++ b/src/components/views/elements/EditableItemList.js @@ -65,12 +65,18 @@ export class EditableItem extends React.Component { {_t("Are you sure?")} - + {_t("Yes")} - + {_t("No")}
    @@ -121,11 +127,15 @@ export default class EditableItemList extends React.Component { _renderNewItemField() { return ( - + + autoComplete="off" value={this.props.newItem || ""} onChange={this._onNewItemChanged} + list={this.props.suggestionsListId} /> {_t("Add")} diff --git a/src/components/views/elements/EditableText.js b/src/components/views/elements/EditableText.js index 638fd02553..7c38ac1777 100644 --- a/src/components/views/elements/EditableText.js +++ b/src/components/views/elements/EditableText.js @@ -221,13 +221,15 @@ export default class EditableText extends React.Component { ; } else { // show the content editable div, but manually manage its contents as react and contentEditable don't play nice together - editableEl =
    ; + editableEl =
    ; } return editableEl; diff --git a/src/components/views/elements/ImageView.tsx b/src/components/views/elements/ImageView.tsx index cbced07bfe..05d487a9eb 100644 --- a/src/components/views/elements/ImageView.tsx +++ b/src/components/views/elements/ImageView.tsx @@ -34,16 +34,15 @@ import {RoomPermalinkCreator} from "../../../utils/permalinks/Permalinks" import {MatrixEvent} from "matrix-js-sdk/src/models/event"; import {normalizeWheelEvent} from "../../../utils/Mouse"; -const MIN_ZOOM = 100; -const MAX_ZOOM = 300; +// Max scale to keep gaps around the image +const MAX_SCALE = 0.95; // This is used for the buttons -const ZOOM_STEP = 10; +const ZOOM_STEP = 0.10; // This is used for mouse wheel events -const ZOOM_COEFFICIENT = 0.5; +const ZOOM_COEFFICIENT = 0.0025; // If we have moved only this much we can zoom const ZOOM_DISTANCE = 10; - interface IProps { src: string, // the source of the image being displayed name?: string, // the main title ('name') for the image @@ -62,8 +61,10 @@ interface IProps { } interface IState { - rotation: number, zoom: number, + minZoom: number, + maxZoom: number, + rotation: number, translationX: number, translationY: number, moving: boolean, @@ -75,8 +76,10 @@ export default class ImageView extends React.Component { constructor(props) { super(props); this.state = { + zoom: 0, + minZoom: MAX_SCALE, + maxZoom: MAX_SCALE, rotation: 0, - zoom: MIN_ZOOM, translationX: 0, translationY: 0, moving: false, @@ -87,6 +90,8 @@ export default class ImageView extends React.Component { // XXX: Refs to functional components private contextMenuButton = createRef(); private focusLock = createRef(); + private imageWrapper = createRef(); + private image = createRef(); private initX = 0; private initY = 0; @@ -99,12 +104,89 @@ export default class ImageView extends React.Component { // We have to use addEventListener() because the listener // needs to be passive in order to work with Chromium this.focusLock.current.addEventListener('wheel', this.onWheel, { passive: false }); + // We want to recalculate zoom whenever the window's size changes + window.addEventListener("resize", this.calculateZoom); + // After the image loads for the first time we want to calculate the zoom + this.image.current.addEventListener("load", this.calculateZoom); + // Try to precalculate the zoom from width and height props + this.calculateZoom(); } componentWillUnmount() { this.focusLock.current.removeEventListener('wheel', this.onWheel); + window.removeEventListener("resize", this.calculateZoom); + this.image.current.removeEventListener("load", this.calculateZoom); } + private calculateZoom = () => { + const image = this.image.current; + const imageWrapper = this.imageWrapper.current; + + const width = this.props.width || image.naturalWidth; + const height = this.props.height || image.naturalHeight; + + const zoomX = imageWrapper.clientWidth / width; + const zoomY = imageWrapper.clientHeight / height; + + // If the image is smaller in both dimensions set its the zoom to 1 to + // display it in its original size + if (zoomX >= 1 && zoomY >= 1) { + this.setState({ + zoom: 1, + minZoom: 1, + maxZoom: 1, + }); + return; + } + // We set minZoom to the min of the zoomX and zoomY to avoid overflow in + // any direction. We also multiply by MAX_SCALE to get a gap around the + // image by default + const minZoom = Math.min(zoomX, zoomY) * MAX_SCALE; + + if (this.state.zoom <= this.state.minZoom) this.setState({zoom: minZoom}); + this.setState({ + minZoom: minZoom, + maxZoom: 1, + }); + } + + private zoom(delta: number) { + const newZoom = this.state.zoom + delta; + + if (newZoom <= this.state.minZoom) { + this.setState({ + zoom: this.state.minZoom, + translationX: 0, + translationY: 0, + }); + return; + } + if (newZoom >= this.state.maxZoom) { + this.setState({zoom: this.state.maxZoom}); + return; + } + + this.setState({ + zoom: newZoom, + }); + } + + private onWheel = (ev: WheelEvent) => { + ev.stopPropagation(); + ev.preventDefault(); + + const {deltaY} = normalizeWheelEvent(ev); + this.zoom(-(deltaY * ZOOM_COEFFICIENT)); + }; + + private onZoomInClick = () => { + this.zoom(ZOOM_STEP); + }; + + private onZoomOutClick = () => { + this.zoom(-ZOOM_STEP); + }; + private onKeyDown = (ev: KeyboardEvent) => { if (ev.key === Key.ESCAPE) { ev.stopPropagation(); @@ -113,31 +195,6 @@ export default class ImageView extends React.Component { } }; - private onWheel = (ev: WheelEvent) => { - ev.stopPropagation(); - ev.preventDefault(); - - const {deltaY} = normalizeWheelEvent(ev); - const newZoom = this.state.zoom - (deltaY * ZOOM_COEFFICIENT); - - if (newZoom <= MIN_ZOOM) { - this.setState({ - zoom: MIN_ZOOM, - translationX: 0, - translationY: 0, - }); - return; - } - if (newZoom >= MAX_ZOOM) { - this.setState({zoom: MAX_ZOOM}); - return; - } - - this.setState({ - zoom: newZoom, - }); - }; - private onRotateCounterClockwiseClick = () => { const cur = this.state.rotation; const rotationDegrees = cur - 90; @@ -150,31 +207,6 @@ export default class ImageView extends React.Component { this.setState({ rotation: rotationDegrees }); }; - private onZoomInClick = () => { - if (this.state.zoom >= MAX_ZOOM) { - this.setState({zoom: MAX_ZOOM}); - return; - } - - this.setState({ - zoom: this.state.zoom + ZOOM_STEP, - }); - }; - - private onZoomOutClick = () => { - if (this.state.zoom <= MIN_ZOOM) { - this.setState({ - zoom: MIN_ZOOM, - translationX: 0, - translationY: 0, - }); - return; - } - this.setState({ - zoom: this.state.zoom - ZOOM_STEP, - }); - }; - private onDownloadClick = () => { const a = document.createElement("a"); a.href = this.props.src; @@ -217,8 +249,8 @@ export default class ImageView extends React.Component { if (ev.button !== 0) return; // Zoom in if we are completely zoomed out - if (this.state.zoom === MIN_ZOOM) { - this.setState({zoom: MAX_ZOOM}); + if (this.state.zoom === this.state.minZoom) { + this.setState({zoom: this.state.maxZoom}); return; } @@ -251,7 +283,7 @@ export default class ImageView extends React.Component { Math.abs(this.state.translationY - this.previousY) < ZOOM_DISTANCE ) { this.setState({ - zoom: MIN_ZOOM, + zoom: this.state.minZoom, translationX: 0, translationY: 0, }); @@ -286,17 +318,20 @@ export default class ImageView extends React.Component { render() { const showEventMeta = !!this.props.mxEvent; + const zoomingDisabled = this.state.maxZoom === this.state.minZoom; let cursor; if (this.state.moving) { cursor= "grabbing"; - } else if (this.state.zoom === MIN_ZOOM) { + } else if (zoomingDisabled) { + cursor = "default"; + } else if (this.state.zoom === this.state.minZoom) { cursor = "zoom-in"; } else { cursor = "zoom-out"; } const rotationDegrees = this.state.rotation + "deg"; - const zoomPercentage = this.state.zoom/100; + const zoom = this.state.zoom; const translatePixelsX = this.state.translationX + "px"; const translatePixelsY = this.state.translationY + "px"; // The order of the values is important! @@ -308,7 +343,7 @@ export default class ImageView extends React.Component { transition: this.state.moving ? null : "transform 200ms ease 0s", transform: `translateX(${translatePixelsX}) translateY(${translatePixelsY}) - scale(${zoomPercentage}) + scale(${zoom}) rotate(${rotationDegrees})`, }; @@ -380,6 +415,25 @@ export default class ImageView extends React.Component { ); } + let zoomOutButton; + let zoomInButton; + if (!zoomingDisabled) { + zoomOutButton = ( + + + ); + zoomInButton = ( + + + ); + } + return ( { title={_t("Rotate Left")} onClick={ this.onRotateCounterClockwiseClick }> - - - - + {zoomOutButton} + {zoomInButton} { {this.renderContextMenu()}
    -
    +
    {this.props.label}; - let secondPart = ; + let secondPart = ; if (this.props.toggleInFront) { const temp = firstPart; diff --git a/src/components/views/elements/LanguageDropdown.js b/src/components/views/elements/LanguageDropdown.js index 2e961be700..b8734c5afb 100644 --- a/src/components/views/elements/LanguageDropdown.js +++ b/src/components/views/elements/LanguageDropdown.js @@ -60,10 +60,10 @@ export default class LanguageDropdown extends React.Component { // doesn't know this, therefore we do this. const language = SettingsStore.getValue("language", null, /*excludeDefault:*/true); if (language) { - this.props.onOptionChange(language); + this.props.onOptionChange(language); } else { - const language = languageHandler.normalizeLanguageKey(languageHandler.getLanguageFromBrowser()); - this.props.onOptionChange(language); + const language = languageHandler.normalizeLanguageKey(languageHandler.getLanguageFromBrowser()); + this.props.onOptionChange(language); } } } diff --git a/src/components/views/elements/Pill.js b/src/components/views/elements/Pill.js index a8e16813e6..ace41db39d 100644 --- a/src/components/views/elements/Pill.js +++ b/src/components/views/elements/Pill.js @@ -225,19 +225,19 @@ class Pill extends React.Component { } break; case Pill.TYPE_USER_MENTION: { - // If this user is not a member of this room, default to the empty member - const member = this.state.member; - if (member) { - userId = member.userId; - member.rawDisplayName = member.rawDisplayName || ''; - linkText = member.rawDisplayName; - if (this.props.shouldShowPillAvatar) { - avatar =
    -
    {_t("Level")}{_t("Settable at global")}{_t("Settable at room")}
    {_t("Level")}{_t("Settable at global")}{_t("Settable at room")}
    {_t("Homeserver feature support:")} {homeserverSupportsCrossSigning ? _t("exists") : _t("not found")}
    + {errorSection} {actionRow} diff --git a/src/components/views/settings/DevicesPanel.js b/src/components/views/settings/DevicesPanel.js index e7d300b0f8..b1ad605a37 100644 --- a/src/components/views/settings/DevicesPanel.js +++ b/src/components/views/settings/DevicesPanel.js @@ -214,7 +214,7 @@ export default class DevicesPanel extends React.Component { const deleteButton = this.state.deleting ? : - { _t("Delete %(count)s sessions", {count: this.state.selectedDevices.length}) } + { _t("Delete %(count)s sessions", {count: this.state.selectedDevices.length})} ; const classes = classNames(this.props.className, "mx_DevicesPanel"); diff --git a/src/components/views/settings/E2eAdvancedPanel.js b/src/components/views/settings/E2eAdvancedPanel.tsx similarity index 100% rename from src/components/views/settings/E2eAdvancedPanel.js rename to src/components/views/settings/E2eAdvancedPanel.tsx diff --git a/src/components/views/settings/EventIndexPanel.js b/src/components/views/settings/EventIndexPanel.tsx similarity index 65% rename from src/components/views/settings/EventIndexPanel.js rename to src/components/views/settings/EventIndexPanel.tsx index d1a02de16d..fa84063ee8 100644 --- a/src/components/views/settings/EventIndexPanel.js +++ b/src/components/views/settings/EventIndexPanel.tsx @@ -1,5 +1,5 @@ /* -Copyright 2020 The Matrix.org Foundation C.I.C. +Copyright 2020-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. @@ -28,10 +28,17 @@ import {SettingLevel} from "../../../settings/SettingLevel"; import {replaceableComponent} from "../../../utils/replaceableComponent"; import SeshatResetDialog from '../dialogs/SeshatResetDialog'; +interface IState { + enabling: boolean; + eventIndexSize: number; + roomCount: number; + eventIndexingEnabled: boolean; +} + @replaceableComponent("views.settings.EventIndexPanel") -export default class EventIndexPanel extends React.Component { - constructor() { - super(); +export default class EventIndexPanel extends React.Component<{}, IState> { + constructor(props) { + super(props); this.state = { enabling: false, @@ -68,7 +75,7 @@ export default class EventIndexPanel extends React.Component { } } - async componentDidMount(): void { + componentDidMount(): void { this.updateState(); } @@ -102,8 +109,10 @@ export default class EventIndexPanel extends React.Component { }); } - _onManage = async () => { + private onManage = async () => { Modal.createTrackedDialogAsync('Message search', 'Message search', + // @ts-ignore: TS doesn't seem to like the type of this now that it + // has also been converted to TS as well, but I can't figure out why... import('../../../async-components/views/dialogs/eventindex/ManageEventIndexDialog'), { onFinished: () => {}, @@ -111,7 +120,7 @@ export default class EventIndexPanel extends React.Component { ); } - _onEnable = async () => { + private onEnable = async () => { this.setState({ enabling: true, }); @@ -123,14 +132,13 @@ export default class EventIndexPanel extends React.Component { await this.updateState(); } - _confirmEventStoreReset = () => { - const self = this; + private confirmEventStoreReset = () => { const { close } = Modal.createDialog(SeshatResetDialog, { onFinished: async (success) => { if (success) { await SettingsStore.setValue('enableEventIndexing', null, SettingLevel.DEVICE, false); await EventIndexPeg.deleteEventIndex(); - await self._onEnable(); + await this.onEnable(); close(); } }, @@ -145,20 +153,19 @@ export default class EventIndexPanel extends React.Component { if (EventIndexPeg.get() !== null) { eventIndexingSettings = (
    -
    - {_t("Securely cache encrypted messages locally for them " + - "to appear in search results, using %(size)s to store messages from %(rooms)s rooms.", - { - size: formatBytes(this.state.eventIndexSize, 0), - // This drives the singular / plural string - // selection for "room" / "rooms" only. - count: this.state.roomCount, - rooms: formatCountLong(this.state.roomCount), - }, - )} -
    +
    {_t( + "Securely cache encrypted messages locally for them " + + "to appear in search results, using %(size)s to store messages from %(rooms)s rooms.", + { + size: formatBytes(this.state.eventIndexSize, 0), + // This drives the singular / plural string + // selection for "room" / "rooms" only. + count: this.state.roomCount, + rooms: formatCountLong(this.state.roomCount), + }, + )}
    - + {_t("Manage")}
    @@ -167,13 +174,13 @@ export default class EventIndexPanel extends React.Component { } else if (!this.state.eventIndexingEnabled && EventIndexPeg.supportIsInstalled()) { eventIndexingSettings = (
    -
    - {_t( "Securely cache encrypted messages locally for them to " + - "appear in search results.")} -
    +
    {_t( + "Securely cache encrypted messages locally for them to " + + "appear in search results.", + )}
    + onClick={this.onEnable}> {_t("Enable")} {this.state.enabling ? :
    } @@ -188,40 +195,36 @@ export default class EventIndexPanel extends React.Component { ); eventIndexingSettings = ( -
    +
    {_t( + "%(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.", { - _t( "%(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, - }, - { - 'nativeLink': (sub) => {sub}, - }, - ) - } -
    + brand, + }, + { + nativeLink: sub => {sub}, + }, + )}
    ); } else if (!EventIndexPeg.platformHasSupport()) { eventIndexingSettings = ( -
    +
    {_t( + "%(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.", { - _t( "%(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, - }, - { - 'desktopLink': (sub) => {sub}, - }, - ) - } -
    + brand, + }, + { + desktopLink: sub => {sub}, + }, + )}
    ); } else { eventIndexingSettings = ( @@ -233,19 +236,18 @@ export default class EventIndexPanel extends React.Component { }

    {EventIndexPeg.error && ( -
    - {_t("Advanced")} - - {EventIndexPeg.error.message} - -

    - - {_t("Reset")} - -

    -
    +
    + {_t("Advanced")} + + {EventIndexPeg.error.message} + +

    + + {_t("Reset")} + +

    +
    )} -
    ); } diff --git a/src/components/views/settings/Notifications.js b/src/components/views/settings/Notifications.js index 25fe434994..5756536085 100644 --- a/src/components/views/settings/Notifications.js +++ b/src/components/views/settings/Notifications.js @@ -100,7 +100,7 @@ export default class Notifications extends React.Component { MatrixClientPeg.get().setPushRuleEnabled( 'global', self.state.masterPushRule.kind, self.state.masterPushRule.rule_id, !checked, ).then(function() { - self._refreshFromServer(); + self._refreshFromServer(); }); }; @@ -580,12 +580,12 @@ export default class Notifications extends React.Component { "vectorRuleId": "_keywords", "description": ( - { _t('Messages containing keywords', - {}, - { 'span': (sub) => - {sub}, - }, - )} + { _t('Messages containing keywords', + {}, + { 'span': (sub) => + {sub}, + }, + )} ), "vectorState": self.state.vectorContentRules.vectorState, @@ -743,8 +743,8 @@ export default class Notifications extends React.Component { emailNotificationsRow(address, label) { return ; + onChange={this.onEnableEmailNotificationsChange.bind(this, address)} + label={label} key={`emailNotif_${label}`} />; } render() { @@ -757,8 +757,8 @@ export default class Notifications extends React.Component { let masterPushRuleDiv; if (this.state.masterPushRule) { masterPushRuleDiv = ; + onChange={this.onEnableNotificationsChange} + label={_t('Enable notifications for this account')} />; } let clearNotificationsButton; @@ -874,16 +874,16 @@ export default class Notifications extends React.Component { { spinner } + onChange={this.onEnableDesktopNotificationsChange} + label={_t('Enable desktop notifications for this session')} /> + onChange={this.onEnableDesktopNotificationBodyChange} + label={_t('Show message in desktop notification')} /> + onChange={this.onEnableAudioNotificationsChange} + label={_t('Enable audible notifications for this session')} /> { emailNotificationsRows } diff --git a/src/components/views/settings/ProfileSettings.js b/src/components/views/settings/ProfileSettings.js index 971b868751..9ecf369eba 100644 --- a/src/components/views/settings/ProfileSettings.js +++ b/src/components/views/settings/ProfileSettings.js @@ -170,8 +170,12 @@ export default class ProfileSettings extends React.Component { noValidate={true} className="mx_ProfileSettings_profileForm" > - +
    {_t("Profile")} diff --git a/src/components/views/settings/SetIdServer.js b/src/components/views/settings/SetIdServer.tsx similarity index 89% rename from src/components/views/settings/SetIdServer.js rename to src/components/views/settings/SetIdServer.tsx index fa2a36476d..05d1f83387 100644 --- a/src/components/views/settings/SetIdServer.js +++ b/src/components/views/settings/SetIdServer.tsx @@ -1,5 +1,5 @@ /* -Copyright 2019 The Matrix.org Foundation C.I.C. +Copyright 2019-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. @@ -16,7 +16,6 @@ limitations under the License. import url from 'url'; import React from 'react'; -import PropTypes from 'prop-types'; import {_t} from "../../../languageHandler"; import * as sdk from '../../../index'; import {MatrixClientPeg} from "../../../MatrixClientPeg"; @@ -28,6 +27,7 @@ import {abbreviateUrl, unabbreviateUrl} from "../../../utils/UrlUtils"; import { getDefaultIdentityServerUrl, doesIdentityServerHaveTerms } from '../../../utils/IdentityServerUtils'; import {timeout} from "../../../utils/promise"; import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { ActionPayload } from '../../../dispatcher/payloads'; // We'll wait up to this long when checking for 3PID bindings on the IS. const REACHABILITY_TIMEOUT = 10000; // ms @@ -59,16 +59,28 @@ async function checkIdentityServerUrl(u) { } } -@replaceableComponent("views.settings.SetIdServer") -export default class SetIdServer extends React.Component { - static propTypes = { - // Whether or not the ID server is missing terms. This affects the text - // shown to the user. - missingTerms: PropTypes.bool, - }; +interface IProps { + // Whether or not the ID server is missing terms. This affects the text + // shown to the user. + missingTerms: boolean; +} - constructor() { - super(); +interface IState { + defaultIdServer?: string; + currentClientIdServer: string; + idServer?: string; + error?: string; + busy: boolean; + disconnectBusy: boolean; + checking: boolean; +} + +@replaceableComponent("views.settings.SetIdServer") +export default class SetIdServer extends React.Component { + private dispatcherRef: string; + + constructor(props) { + super(props); let defaultIdServer = ''; if (!MatrixClientPeg.get().getIdentityServerUrl() && getDefaultIdentityServerUrl()) { @@ -96,7 +108,7 @@ export default class SetIdServer extends React.Component { dis.unregister(this.dispatcherRef); } - onAction = (payload) => { + private onAction = (payload: ActionPayload) => { // We react to changes in the ID server in the event the user is staring at this form // when changing their identity server on another device. if (payload.action !== "id_server_changed") return; @@ -106,13 +118,13 @@ export default class SetIdServer extends React.Component { }); }; - _onIdentityServerChanged = (ev) => { + private onIdentityServerChanged = (ev) => { const u = ev.target.value; this.setState({idServer: u}); }; - _getTooltip = () => { + private getTooltip = () => { if (this.state.checking) { const InlineSpinner = sdk.getComponent('views.elements.InlineSpinner'); return
    @@ -126,11 +138,11 @@ export default class SetIdServer extends React.Component { } }; - _idServerChangeEnabled = () => { + private idServerChangeEnabled = () => { return !!this.state.idServer && !this.state.busy; }; - _saveIdServer = (fullUrl) => { + private saveIdServer = (fullUrl) => { // Account data change will update localstorage, client, etc through dispatcher MatrixClientPeg.get().setAccountData("m.identity_server", { base_url: fullUrl, @@ -143,7 +155,7 @@ export default class SetIdServer extends React.Component { }); }; - _checkIdServer = async (e) => { + private checkIdServer = async (e) => { e.preventDefault(); const { idServer, currentClientIdServer } = this.state; @@ -166,14 +178,14 @@ export default class SetIdServer extends React.Component { // Double check that the identity server even has terms of service. const hasTerms = await doesIdentityServerHaveTerms(fullUrl); if (!hasTerms) { - const [confirmed] = await this._showNoTermsWarning(fullUrl); + const [confirmed] = await this.showNoTermsWarning(fullUrl); save = confirmed; } // Show a general warning, possibly with details about any bound // 3PIDs that would be left behind. if (save && currentClientIdServer && fullUrl !== currentClientIdServer) { - const [confirmed] = await this._showServerChangeWarning({ + const [confirmed] = await this.showServerChangeWarning({ title: _t("Change identity server"), unboundMessage: _t( "Disconnect from the identity server and " + @@ -189,7 +201,7 @@ export default class SetIdServer extends React.Component { } if (save) { - this._saveIdServer(fullUrl); + this.saveIdServer(fullUrl); } } catch (e) { console.error(e); @@ -204,7 +216,7 @@ export default class SetIdServer extends React.Component { }); }; - _showNoTermsWarning(fullUrl) { + private showNoTermsWarning(fullUrl) { const QuestionDialog = sdk.getComponent("views.dialogs.QuestionDialog"); const { finished } = Modal.createTrackedDialog('No Terms Warning', '', QuestionDialog, { title: _t("Identity server has no terms of service"), @@ -223,10 +235,10 @@ export default class SetIdServer extends React.Component { return finished; } - _onDisconnectClicked = async () => { + private onDisconnectClicked = async () => { this.setState({disconnectBusy: true}); try { - const [confirmed] = await this._showServerChangeWarning({ + const [confirmed] = await this.showServerChangeWarning({ title: _t("Disconnect identity server"), unboundMessage: _t( "Disconnect from the identity server ?", {}, @@ -235,14 +247,14 @@ export default class SetIdServer extends React.Component { button: _t("Disconnect"), }); if (confirmed) { - this._disconnectIdServer(); + this.disconnectIdServer(); } } finally { this.setState({disconnectBusy: false}); } }; - async _showServerChangeWarning({ title, unboundMessage, button }) { + private async showServerChangeWarning({ title, unboundMessage, button }) { const { currentClientIdServer } = this.state; let threepids = []; @@ -318,7 +330,7 @@ export default class SetIdServer extends React.Component { return finished; } - _disconnectIdServer = () => { + private disconnectIdServer = () => { // Account data change will update localstorage, client, etc through dispatcher MatrixClientPeg.get().setAccountData("m.identity_server", { base_url: null, // clear @@ -371,7 +383,7 @@ export default class SetIdServer extends React.Component { let discoSection; if (idServerUrl) { - let discoButtonContent = _t("Disconnect"); + let discoButtonContent: React.ReactNode = _t("Disconnect"); let discoBodyText = _t( "Disconnecting from your identity server will mean you " + "won't be discoverable by other users and you won't be " + @@ -391,14 +403,14 @@ export default class SetIdServer extends React.Component { } discoSection =
    {discoBodyText} - + {discoButtonContent}
    ; } return ( - + {sectionTitle} @@ -411,15 +423,15 @@ export default class SetIdServer extends React.Component { autoComplete="off" placeholder={this.state.defaultIdServer} value={this.state.idServer} - onChange={this._onIdentityServerChanged} - tooltipContent={this._getTooltip()} + onChange={this.onIdentityServerChanged} + tooltipContent={this.getTooltip()} tooltipClassName="mx_SetIdServer_tooltip" disabled={this.state.busy} forceValidity={this.state.error ? false : null} /> {_t("Change")} {discoSection} diff --git a/src/components/views/settings/account/EmailAddresses.js b/src/components/views/settings/account/EmailAddresses.js index 1ebd374173..a36369cf88 100644 --- a/src/components/views/settings/account/EmailAddresses.js +++ b/src/components/views/settings/account/EmailAddresses.js @@ -90,12 +90,18 @@ export class ExistingEmailAddress extends React.Component { {_t("Remove %(email)s?", {email: this.props.email.address} )} - + {_t("Remove")} - + {_t("Cancel")}
    @@ -228,21 +234,28 @@ export default class EmailAddresses extends React.Component { ); if (this.state.verifying) { addButton = ( -
    -
    {_t("We've sent you an email to verify your address. Please follow the instructions there and then click the button below.")}
    - - {_t("Continue")} - -
    +
    +
    {_t("We've sent you an email to verify your address. Please follow the instructions there and then click the button below.")}
    + + {_t("Continue")} + +
    ); } return (
    {existingEmailElements} -
    + {_t("Remove %(phone)s?", {phone: this.props.msisdn.address})} - + {_t("Remove")} - + {_t("Cancel")}
    @@ -246,8 +252,11 @@ export default class PhoneNumbers extends React.Component { value={this.state.newPhoneNumberCode} onChange={this._onChangeNewPhoneNumberCode} /> - + {_t("Continue")} diff --git a/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.js b/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.js index cd4a043622..139cfd5fbd 100644 --- a/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.js +++ b/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.js @@ -80,9 +80,11 @@ export default class GeneralRoomSettingsTab extends React.Component { flairSection = <> {_t("Flair")}
    - +
    ; } @@ -97,8 +99,8 @@ export default class GeneralRoomSettingsTab extends React.Component {
    {_t("Room Addresses")}
    + canSetCanonicalAlias={canSetCanonical} canSetAliases={canSetAliases} + canonicalAliasEvent={canonicalAliasEv} aliasEvents={aliasEvents} />
    {_t("Other")}
    { flairSection } diff --git a/src/components/views/settings/tabs/room/NotificationSettingsTab.js b/src/components/views/settings/tabs/room/NotificationSettingsTab.js index baefb5ae20..fa56fa2cb6 100644 --- a/src/components/views/settings/tabs/room/NotificationSettingsTab.js +++ b/src/components/views/settings/tabs/room/NotificationSettingsTab.js @@ -155,7 +155,7 @@ export default class NotificationsSettingsTab extends React.Component {
    {_t("Notification sound")}: {this.state.currentSound}
    - {_t("Reset")} + {_t("Reset")}
    @@ -167,11 +167,11 @@ export default class NotificationsSettingsTab extends React.Component { {currentUploadedFile} - {_t("Browse")} + {_t("Browse")} - {_t("Save")} + {_t("Save")}
    diff --git a/src/components/views/settings/tabs/room/RolesRoomSettingsTab.js b/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx similarity index 89% rename from src/components/views/settings/tabs/room/RolesRoomSettingsTab.js rename to src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx index 59a175906d..4fa521f598 100644 --- a/src/components/views/settings/tabs/room/RolesRoomSettingsTab.js +++ b/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx @@ -1,5 +1,5 @@ /* -Copyright 2019, 2021 The Matrix.org Foundation C.I.C. +Copyright 2019-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. @@ -15,7 +15,6 @@ limitations under the License. */ import React from 'react'; -import PropTypes from 'prop-types'; import {_t, _td} from "../../../../../languageHandler"; import {MatrixClientPeg} from "../../../../../MatrixClientPeg"; import * as sdk from "../../../../.."; @@ -23,6 +22,9 @@ import AccessibleButton from "../../../elements/AccessibleButton"; import Modal from "../../../../../Modal"; import {replaceableComponent} from "../../../../../utils/replaceableComponent"; import {EventType} from "matrix-js-sdk/src/@types/event"; +import { RoomMember } from "matrix-js-sdk/src/models/room-member"; +import { MatrixEvent } from "matrix-js-sdk/src/models/event"; +import { RoomState } from "matrix-js-sdk/src/models/room-state"; const plEventsToLabels = { // These will be translated for us later. @@ -63,15 +65,15 @@ function parseIntWithDefault(val, def) { return isNaN(res) ? def : res; } -export class BannedUser extends React.Component { - static propTypes = { - canUnban: PropTypes.bool, - member: PropTypes.object.isRequired, // js-sdk RoomMember - by: PropTypes.string.isRequired, - reason: PropTypes.string, - }; +interface IBannedUserProps { + canUnban?: boolean; + member: RoomMember; + by: string; + reason?: string; +} - _onUnbanClick = (e) => { +export class BannedUser extends React.Component { + private onUnbanClick = (e) => { MatrixClientPeg.get().unban(this.props.member.roomId, this.props.member.userId).catch((err) => { const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); console.error("Failed to unban: " + err); @@ -87,8 +89,10 @@ export class BannedUser extends React.Component { if (this.props.canUnban) { unbanButton = ( - + { _t('Unban') } ); @@ -107,29 +111,29 @@ export class BannedUser extends React.Component { } } -@replaceableComponent("views.settings.tabs.room.RolesRoomSettingsTab") -export default class RolesRoomSettingsTab extends React.Component { - static propTypes = { - roomId: PropTypes.string.isRequired, - }; +interface IProps { + roomId: string; +} - componentDidMount(): void { - MatrixClientPeg.get().on("RoomState.members", this._onRoomMembership); +@replaceableComponent("views.settings.tabs.room.RolesRoomSettingsTab") +export default class RolesRoomSettingsTab extends React.Component { + componentDidMount() { + MatrixClientPeg.get().on("RoomState.members", this.onRoomMembership); } - componentWillUnmount(): void { + componentWillUnmount() { const client = MatrixClientPeg.get(); if (client) { - client.removeListener("RoomState.members", this._onRoomMembership); + client.removeListener("RoomState.members", this.onRoomMembership); } } - _onRoomMembership = (event, state, member) => { + private onRoomMembership = (event: MatrixEvent, state: RoomState, member: RoomMember) => { if (state.roomId !== this.props.roomId) return; this.forceUpdate(); }; - _populateDefaultPlEvents(eventsSection, stateLevel, eventsLevel) { + private populateDefaultPlEvents(eventsSection: Record, stateLevel: number, eventsLevel: number) { for (const desiredEvent of Object.keys(plEventsToShow)) { if (!(desiredEvent in eventsSection)) { eventsSection[desiredEvent] = (plEventsToShow[desiredEvent].isState ? stateLevel : eventsLevel); @@ -137,7 +141,7 @@ export default class RolesRoomSettingsTab extends React.Component { } } - _onPowerLevelsChanged = (value, powerLevelKey) => { + private onPowerLevelsChanged = (inputValue: string, powerLevelKey: string) => { const client = MatrixClientPeg.get(); const room = client.getRoom(this.props.roomId); const plEvent = room.currentState.getStateEvents('m.room.power_levels', ''); @@ -148,7 +152,7 @@ export default class RolesRoomSettingsTab extends React.Component { const eventsLevelPrefix = "event_levels_"; - value = parseInt(value); + const value = parseInt(inputValue); if (powerLevelKey.startsWith(eventsLevelPrefix)) { // deep copy "events" object, Object.assign itself won't deep copy @@ -182,7 +186,7 @@ export default class RolesRoomSettingsTab extends React.Component { }); }; - _onUserPowerLevelChanged = (value, powerLevelKey) => { + private onUserPowerLevelChanged = (value: string, powerLevelKey: string) => { const client = MatrixClientPeg.get(); const room = client.getRoom(this.props.roomId); const plEvent = room.currentState.getStateEvents('m.room.power_levels', ''); @@ -266,7 +270,7 @@ export default class RolesRoomSettingsTab extends React.Component { currentUserLevel = defaultUserLevel; } - this._populateDefaultPlEvents( + this.populateDefaultPlEvents( eventsLevels, parseIntWithDefault(plContent.state_default, powerLevelDescriptors.state_default.defaultValue), parseIntWithDefault(plContent.events_default, powerLevelDescriptors.events_default.defaultValue), @@ -288,7 +292,7 @@ export default class RolesRoomSettingsTab extends React.Component { label={user} key={user} powerLevelKey={user} // Will be sent as the second parameter to `onChange` - onChange={this._onUserPowerLevelChanged} + onChange={this.onUserPowerLevelChanged} />, ); } else if (userLevels[user] < defaultUserLevel) { // muted @@ -299,7 +303,7 @@ export default class RolesRoomSettingsTab extends React.Component { label={user} key={user} powerLevelKey={user} // Will be sent as the second parameter to `onChange` - onChange={this._onUserPowerLevelChanged} + onChange={this.onUserPowerLevelChanged} />, ); } @@ -345,8 +349,9 @@ export default class RolesRoomSettingsTab extends React.Component { if (sender) bannedBy = sender.name; return ( + member={member} reason={banEvent.reason} + by={bannedBy} + /> ); })} @@ -373,7 +378,7 @@ export default class RolesRoomSettingsTab extends React.Component { usersDefault={defaultUserLevel} disabled={!canChangeLevels || currentUserLevel < value} powerLevelKey={key} // Will be sent as the second parameter to `onChange` - onChange={this._onPowerLevelsChanged} + onChange={this.onPowerLevelsChanged} />
    ; }); @@ -398,7 +403,7 @@ export default class RolesRoomSettingsTab extends React.Component { usersDefault={defaultUserLevel} disabled={!canChangeLevels || currentUserLevel < eventsLevels[eventType]} powerLevelKey={"event_levels_" + eventType} - onChange={this._onPowerLevelsChanged} + onChange={this.onPowerLevelsChanged} />
    ); diff --git a/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.js b/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx similarity index 79% rename from src/components/views/settings/tabs/room/SecurityRoomSettingsTab.js rename to src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx index ce883c6d23..02bbcfb751 100644 --- a/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.js +++ b/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx @@ -1,5 +1,5 @@ /* -Copyright 2019 New Vector Ltd +Copyright 2019-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. @@ -15,7 +15,7 @@ limitations under the License. */ import React from 'react'; -import PropTypes from 'prop-types'; +import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import {_t} from "../../../../../languageHandler"; import {MatrixClientPeg} from "../../../../../MatrixClientPeg"; import * as sdk from "../../../../.."; @@ -26,64 +26,92 @@ import StyledRadioGroup from '../../../elements/StyledRadioGroup'; import {SettingLevel} from "../../../../../settings/SettingLevel"; import SettingsStore from "../../../../../settings/SettingsStore"; import {UIFeature} from "../../../../../settings/UIFeature"; -import {replaceableComponent} from "../../../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../../../utils/replaceableComponent"; + +// Knock and private are reserved keywords which are not yet implemented. +enum JoinRule { + Public = "public", + Knock = "knock", + Invite = "invite", + Private = "private", +} + +enum GuestAccess { + CanJoin = "can_join", + Forbidden = "forbidden", +} + +enum HistoryVisibility { + Invited = "invited", + Joined = "joined", + Shared = "shared", + WorldReadable = "world_readable", +} + +interface IProps { + roomId: string; +} + +interface IState { + joinRule: JoinRule; + guestAccess: GuestAccess; + history: HistoryVisibility; + hasAliases: boolean; + encrypted: boolean; +} @replaceableComponent("views.settings.tabs.room.SecurityRoomSettingsTab") -export default class SecurityRoomSettingsTab extends React.Component { - static propTypes = { - roomId: PropTypes.string.isRequired, - }; - - constructor() { - super(); +export default class SecurityRoomSettingsTab extends React.Component { + constructor(props) { + super(props); this.state = { - joinRule: "invite", - guestAccess: "can_join", - history: "shared", + joinRule: JoinRule.Invite, + guestAccess: GuestAccess.CanJoin, + history: HistoryVisibility.Shared, hasAliases: false, encrypted: false, }; } // TODO: [REACT-WARNING] Move this to constructor - async UNSAFE_componentWillMount(): void { // eslint-disable-line camelcase - MatrixClientPeg.get().on("RoomState.events", this._onStateEvent); + async UNSAFE_componentWillMount() { // eslint-disable-line camelcase + MatrixClientPeg.get().on("RoomState.events", this.onStateEvent); const room = MatrixClientPeg.get().getRoom(this.props.roomId); const state = room.currentState; - const joinRule = this._pullContentPropertyFromEvent( + const joinRule: JoinRule = this.pullContentPropertyFromEvent( state.getStateEvents("m.room.join_rules", ""), 'join_rule', - 'invite', + JoinRule.Invite, ); - const guestAccess = this._pullContentPropertyFromEvent( + const guestAccess: GuestAccess = this.pullContentPropertyFromEvent( state.getStateEvents("m.room.guest_access", ""), 'guest_access', - 'forbidden', + GuestAccess.Forbidden, ); - const history = this._pullContentPropertyFromEvent( + const history: HistoryVisibility = this.pullContentPropertyFromEvent( state.getStateEvents("m.room.history_visibility", ""), 'history_visibility', - 'shared', + HistoryVisibility.Shared, ); const encrypted = MatrixClientPeg.get().isRoomEncrypted(this.props.roomId); this.setState({joinRule, guestAccess, history, encrypted}); - const hasAliases = await this._hasAliases(); + const hasAliases = await this.hasAliases(); this.setState({hasAliases}); } - _pullContentPropertyFromEvent(event, key, defaultValue) { + private pullContentPropertyFromEvent(event: MatrixEvent, key: string, defaultValue: T): T { if (!event || !event.getContent()) return defaultValue; return event.getContent()[key] || defaultValue; } - componentWillUnmount(): void { - MatrixClientPeg.get().removeListener("RoomState.events", this._onStateEvent); + componentWillUnmount() { + MatrixClientPeg.get().removeListener("RoomState.events", this.onStateEvent); } - _onStateEvent = (e) => { + private onStateEvent = (e: MatrixEvent) => { const refreshWhenTypes = [ 'm.room.join_rules', 'm.room.guest_access', @@ -93,7 +121,7 @@ export default class SecurityRoomSettingsTab extends React.Component { if (refreshWhenTypes.includes(e.getType())) this.forceUpdate(); }; - _onEncryptionChange = (e) => { + private onEncryptionChange = (e: React.ChangeEvent) => { Modal.createTrackedDialog('Enable encryption', '', QuestionDialog, { title: _t('Enable encryption?'), description: _t( @@ -102,10 +130,9 @@ export default class SecurityRoomSettingsTab extends React.Component { "may prevent many bots and bridges from working correctly. Learn more about encryption.", {}, { - 'a': (sub) => { - return {sub}; - }, + a: sub => {sub}, }, ), onFinished: (confirm) => { @@ -127,12 +154,12 @@ export default class SecurityRoomSettingsTab extends React.Component { }); }; - _fixGuestAccess = (e) => { + private fixGuestAccess = (e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation(); - const joinRule = "invite"; - const guestAccess = "can_join"; + const joinRule = JoinRule.Invite; + const guestAccess = GuestAccess.CanJoin; const beforeJoinRule = this.state.joinRule; const beforeGuestAccess = this.state.guestAccess; @@ -149,7 +176,7 @@ export default class SecurityRoomSettingsTab extends React.Component { }); }; - _onRoomAccessRadioToggle = (roomAccess) => { + private onRoomAccessRadioToggle = (roomAccess: string) => { // join_rule // INVITE | PUBLIC // ----------------------+---------------- @@ -163,20 +190,20 @@ export default class SecurityRoomSettingsTab extends React.Component { // invite them, you clearly want them to join, whether they're a // guest or not. In practice, guest_access should probably have // been implemented as part of the join_rules enum. - let joinRule = "invite"; - let guestAccess = "can_join"; + let joinRule = JoinRule.Invite; + let guestAccess = GuestAccess.CanJoin; switch (roomAccess) { case "invite_only": // no change - use defaults above break; case "public_no_guests": - joinRule = "public"; - guestAccess = "forbidden"; + joinRule = JoinRule.Public; + guestAccess = GuestAccess.Forbidden; break; case "public_with_guests": - joinRule = "public"; - guestAccess = "can_join"; + joinRule = JoinRule.Public; + guestAccess = GuestAccess.CanJoin; break; } @@ -195,7 +222,7 @@ export default class SecurityRoomSettingsTab extends React.Component { }); }; - _onHistoryRadioToggle = (history) => { + private onHistoryRadioToggle = (history: HistoryVisibility) => { const beforeHistory = this.state.history; this.setState({history: history}); MatrixClientPeg.get().sendStateEvent(this.props.roomId, "m.room.history_visibility", { @@ -206,11 +233,11 @@ export default class SecurityRoomSettingsTab extends React.Component { }); }; - _updateBlacklistDevicesFlag = (checked) => { + private updateBlacklistDevicesFlag = (checked: boolean) => { MatrixClientPeg.get().getRoom(this.props.roomId).setBlacklistUnverifiedDevices(checked); }; - async _hasAliases() { + private async hasAliases(): Promise { const cli = MatrixClientPeg.get(); if (await cli.doesServerSupportUnstableFeature("org.matrix.msc2432")) { const response = await cli.unstableGetLocalAliases(this.props.roomId); @@ -224,7 +251,7 @@ export default class SecurityRoomSettingsTab extends React.Component { } } - _renderRoomAccess() { + private renderRoomAccess() { const client = MatrixClientPeg.get(); const room = client.getRoom(this.props.roomId); const joinRule = this.state.joinRule; @@ -240,7 +267,7 @@ export default class SecurityRoomSettingsTab extends React.Component { {_t("Guests cannot join this room even if explicitly invited.")}  - {_t("Click here to fix")} + {_t("Click here to fix")}
    ); @@ -265,7 +292,7 @@ export default class SecurityRoomSettingsTab extends React.Component { ; } @@ -356,7 +383,7 @@ export default class SecurityRoomSettingsTab extends React.Component { let historySection = (<> {_t("Who can read history?")}
    - {this._renderHistory()} + {this.renderHistory()}
    ); if (!SettingsStore.getValue(UIFeature.RoomHistorySettings)) { @@ -373,15 +400,16 @@ export default class SecurityRoomSettingsTab extends React.Component {
    {_t("Once enabled, encryption cannot be disabled.")}
    - +
    {encryptionSettings}
    {_t("Who can access this room?")}
    - {this._renderRoomAccess()} + {this.renderRoomAccess()}
    {historySection} diff --git a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js index b1ad9f3d23..5118414903 100644 --- a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js @@ -192,7 +192,11 @@ export default class GeneralUserSettingsTab extends React.Component { SettingsStore.setValue("language", null, SettingLevel.DEVICE, newLanguage); this.setState({language: newLanguage}); - PlatformPeg.get().reload(); + const platform = PlatformPeg.get(); + if (platform) { + platform.setLanguage(newLanguage); + platform.reload(); + } }; _onSpellCheckLanguagesChange = (languages) => { @@ -319,8 +323,11 @@ export default class GeneralUserSettingsTab extends React.Component { return (
    {_t("Language and region")} - +
    ); } @@ -329,8 +336,10 @@ export default class GeneralUserSettingsTab extends React.Component { return (
    {_t("Spell check dictionaries")} - +
    ); } diff --git a/src/components/views/settings/tabs/user/HelpUserSettingsTab.js b/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx similarity index 64% rename from src/components/views/settings/tabs/user/HelpUserSettingsTab.js rename to src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx index e16ee686f5..3fa0be478c 100644 --- a/src/components/views/settings/tabs/user/HelpUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx @@ -1,6 +1,5 @@ /* -Copyright 2019 New Vector Ltd -Copyright 2020 The Matrix.org Foundation C.I.C. +Copyright 2019-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. @@ -16,27 +15,37 @@ limitations under the License. */ import React from 'react'; -import PropTypes from 'prop-types'; import {_t, getCurrentLanguage} from "../../../../../languageHandler"; import {MatrixClientPeg} from "../../../../../MatrixClientPeg"; import AccessibleButton from "../../../elements/AccessibleButton"; +import AccessibleTooltipButton from '../../../elements/AccessibleTooltipButton'; import SdkConfig from "../../../../../SdkConfig"; import createRoom from "../../../../../createRoom"; import Modal from "../../../../../Modal"; -import * as sdk from "../../../../../"; +import * as sdk from "../../../../.."; import PlatformPeg from "../../../../../PlatformPeg"; import * as KeyboardShortcuts from "../../../../../accessibility/KeyboardShortcuts"; import UpdateCheckButton from "../../UpdateCheckButton"; -import {replaceableComponent} from "../../../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../../../utils/replaceableComponent"; +import { copyPlaintext } from "../../../../../utils/strings"; +import * as ContextMenu from "../../../../structures/ContextMenu"; +import { toRightOf } from "../../../../structures/ContextMenu"; + +interface IProps { + closeSettingsFn: () => {}; +} + +interface IState { + appVersion: string; + canUpdate: boolean; +} @replaceableComponent("views.settings.tabs.user.HelpUserSettingsTab") -export default class HelpUserSettingsTab extends React.Component { - static propTypes = { - closeSettingsFn: PropTypes.func.isRequired, - }; +export default class HelpUserSettingsTab extends React.Component { + protected closeCopiedTooltip: () => void; - constructor() { - super(); + constructor(props) { + super(props); this.state = { appVersion: null, @@ -53,7 +62,13 @@ export default class HelpUserSettingsTab extends React.Component { }); } - _onClearCacheAndReload = (e) => { + componentWillUnmount() { + // if the Copied tooltip is open then get rid of it, there are ways to close the modal which wouldn't close + // the tooltip otherwise, such as pressing Escape + if (this.closeCopiedTooltip) this.closeCopiedTooltip(); + } + + private onClearCacheAndReload = (e) => { if (!PlatformPeg.get()) return; // Dev note: please keep this log line, it's useful when troubleshooting a MatrixClient suddenly @@ -65,7 +80,7 @@ export default class HelpUserSettingsTab extends React.Component { }); }; - _onBugReport = (e) => { + private onBugReport = (e) => { const BugReportDialog = sdk.getComponent("dialogs.BugReportDialog"); if (!BugReportDialog) { return; @@ -73,7 +88,7 @@ export default class HelpUserSettingsTab extends React.Component { Modal.createTrackedDialog('Bug Report Dialog', '', BugReportDialog, {}); }; - _onStartBotChat = (e) => { + private onStartBotChat = (e) => { this.props.closeSettingsFn(); createRoom({ dmUserId: SdkConfig.get().welcomeUserId, @@ -81,7 +96,7 @@ export default class HelpUserSettingsTab extends React.Component { }); }; - _showSpoiler = (event) => { + private showSpoiler = (event) => { const target = event.target; target.innerHTML = target.getAttribute('data-spoiler'); @@ -93,7 +108,7 @@ export default class HelpUserSettingsTab extends React.Component { selection.addRange(range); }; - _renderLegal() { + private renderLegal() { const tocLinks = SdkConfig.get().terms_and_conditions_links; if (!tocLinks) return null; @@ -114,7 +129,7 @@ export default class HelpUserSettingsTab extends React.Component { ); } - _renderCredits() { + private renderCredits() { // Note: This is not translated because it is legal text. // Also,   is ugly but necessary. return ( @@ -122,34 +137,48 @@ export default class HelpUserSettingsTab extends React.Component { {_t("Credits")}
    ); } + onAccessTokenCopyClick = async (e) => { + e.preventDefault(); + const target = e.target; // copy target before we go async and React throws it away + + const successful = await copyPlaintext(MatrixClientPeg.get().getAccessToken()); + const buttonRect = target.getBoundingClientRect(); + const GenericTextContextMenu = sdk.getComponent('context_menus.GenericTextContextMenu'); + const {close} = ContextMenu.createMenu(GenericTextContextMenu, { + ...toRightOf(buttonRect, 2), + message: successful ? _t('Copied!') : _t('Failed to copy'), + }); + this.closeCopiedTooltip = target.onmouseleave = close; + } + render() { const brand = SdkConfig.get().brand; @@ -188,7 +217,7 @@ export default class HelpUserSettingsTab extends React.Component { }, )}
    - + {_t("Chat with %(brand)s Bot", { brand })}
    @@ -212,28 +241,27 @@ export default class HelpUserSettingsTab extends React.Component {
    {_t('Bug reporting')}
    - { - _t( "If you've submitted a bug via GitHub, debug logs can help " + - "us track down the problem. Debug logs contain application " + - "usage data including your username, the IDs or aliases of " + - "the rooms or groups you have visited and the usernames of " + - "other users. They do not contain messages.", - ) - } + {_t( + "If you've submitted a bug via GitHub, debug logs can help " + + "us track down the problem. Debug logs contain application " + + "usage data including your username, the IDs or aliases of " + + "the rooms or groups you have visited and the usernames of " + + "other users. They do not contain messages.", + )}
    - + {_t("Submit debug logs")}
    - { - _t( "To report a Matrix-related security issue, please read the Matrix.org " + - "Security Disclosure Policy.", {}, - { - 'a': (sub) => - {sub}, - }) - } + {_t( + "To report a Matrix-related security issue, please read the Matrix.org " + + "Security Disclosure Policy.", {}, + { + a: sub => {sub}, + }, + )}
    ); @@ -260,20 +288,29 @@ export default class HelpUserSettingsTab extends React.Component { {updateButton}
    - {this._renderLegal()} - {this._renderCredits()} + {this.renderLegal()} + {this.renderCredits()}
    {_t("Advanced")}
    {_t("Homeserver is")} {MatrixClientPeg.get().getHomeserverUrl()}
    {_t("Identity Server is")} {MatrixClientPeg.get().getIdentityServerUrl()}
    - {_t("Access Token:") + ' '} - - <{ _t("click to reveal") }> - +
    +
    + {_t("Access Token")}
    + {_t("Your access token gives full access to your account." + + " Do not share it with anyone." )} +
    + {MatrixClientPeg.get().getAccessToken()} + +
    +

    - + {_t("Clear cache and reload")}
    diff --git a/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.js b/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.tsx similarity index 90% rename from src/components/views/settings/tabs/user/MjolnirUserSettingsTab.js rename to src/components/views/settings/tabs/user/MjolnirUserSettingsTab.tsx index 91f6728a7a..6997defea9 100644 --- a/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.tsx @@ -1,5 +1,5 @@ /* -Copyright 2019, 2020 The Matrix.org Foundation C.I.C. +Copyright 2019-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. @@ -25,10 +25,16 @@ import {MatrixClientPeg} from "../../../../../MatrixClientPeg"; import * as sdk from "../../../../../index"; import {replaceableComponent} from "../../../../../utils/replaceableComponent"; +interface IState { + busy: boolean; + newPersonalRule: string; + newList: string; +} + @replaceableComponent("views.settings.tabs.user.MjolnirUserSettingsTab") -export default class MjolnirUserSettingsTab extends React.Component { - constructor() { - super(); +export default class MjolnirUserSettingsTab extends React.Component<{}, IState> { + constructor(props) { + super(props); this.state = { busy: false, @@ -37,15 +43,15 @@ export default class MjolnirUserSettingsTab extends React.Component { }; } - _onPersonalRuleChanged = (e) => { + private onPersonalRuleChanged = (e) => { this.setState({newPersonalRule: e.target.value}); }; - _onNewListChanged = (e) => { + private onNewListChanged = (e) => { this.setState({newList: e.target.value}); }; - _onAddPersonalRule = async (e) => { + private onAddPersonalRule = async (e) => { e.preventDefault(); e.stopPropagation(); @@ -72,7 +78,7 @@ export default class MjolnirUserSettingsTab extends React.Component { } }; - _onSubscribeList = async (e) => { + private onSubscribeList = async (e) => { e.preventDefault(); e.stopPropagation(); @@ -94,7 +100,7 @@ export default class MjolnirUserSettingsTab extends React.Component { } }; - async _removePersonalRule(rule: ListRule) { + private async removePersonalRule(rule: ListRule) { this.setState({busy: true}); try { const list = Mjolnir.sharedInstance().getPersonalList(); @@ -112,7 +118,7 @@ export default class MjolnirUserSettingsTab extends React.Component { } } - async _unsubscribeFromList(list: BanList) { + private async unsubscribeFromList(list: BanList) { this.setState({busy: true}); try { await Mjolnir.sharedInstance().unsubscribeFromList(list.roomId); @@ -130,7 +136,7 @@ export default class MjolnirUserSettingsTab extends React.Component { } } - _viewListRules(list: BanList) { + private viewListRules(list: BanList) { const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); const room = MatrixClientPeg.get().getRoom(list.roomId); @@ -161,7 +167,7 @@ export default class MjolnirUserSettingsTab extends React.Component { }); } - _renderPersonalBanListRules() { + private renderPersonalBanListRules() { const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); const list = Mjolnir.sharedInstance().getPersonalList(); @@ -174,7 +180,7 @@ export default class MjolnirUserSettingsTab extends React.Component {
  • this._removePersonalRule(rule)} + onClick={() => this.removePersonalRule(rule)} disabled={this.state.busy} > {_t("Remove")} @@ -192,7 +198,7 @@ export default class MjolnirUserSettingsTab extends React.Component { ); } - _renderSubscribedBanLists() { + private renderSubscribedBanLists() { const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); const personalList = Mjolnir.sharedInstance().getPersonalList(); @@ -209,14 +215,14 @@ export default class MjolnirUserSettingsTab extends React.Component {
  • this._unsubscribeFromList(list)} + onClick={() => this.unsubscribeFromList(list)} disabled={this.state.busy} > {_t("Unsubscribe")}   this._viewListRules(list)} + onClick={() => this.viewListRules(list)} disabled={this.state.busy} > {_t("View rules")} @@ -271,21 +277,21 @@ export default class MjolnirUserSettingsTab extends React.Component { )}
  • - {this._renderPersonalBanListRules()} + {this.renderPersonalBanListRules()}
    -
    + {_t("Ignore")} @@ -303,20 +309,20 @@ export default class MjolnirUserSettingsTab extends React.Component { )}
    - {this._renderSubscribedBanLists()} + {this.renderSubscribedBanLists()}
    - + {_t("Subscribe")} diff --git a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx similarity index 80% rename from src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js rename to src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx index 0cd3dd6698..f02c5c9ce0 100644 --- a/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx @@ -1,5 +1,5 @@ /* -Copyright 2019 New Vector Ltd +Copyright 2019-2021 The Matrix.org Foundation C.I.C. Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,10 +23,24 @@ import Field from "../../../elements/Field"; import * as sdk from "../../../../.."; import PlatformPeg from "../../../../../PlatformPeg"; import {SettingLevel} from "../../../../../settings/SettingLevel"; -import {replaceableComponent} from "../../../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../../../utils/replaceableComponent"; + +interface IState { + autoLaunch: boolean; + autoLaunchSupported: boolean; + warnBeforeExit: boolean; + warnBeforeExitSupported: boolean; + alwaysShowMenuBarSupported: boolean; + alwaysShowMenuBar: boolean; + minimizeToTraySupported: boolean; + minimizeToTray: boolean; + autocompleteDelay: string; + readMarkerInViewThresholdMs: string; + readMarkerOutOfViewThresholdMs: string; +} @replaceableComponent("views.settings.tabs.user.PreferencesUserSettingsTab") -export default class PreferencesUserSettingsTab extends React.Component { +export default class PreferencesUserSettingsTab extends React.Component<{}, IState> { static ROOM_LIST_SETTINGS = [ 'breadcrumbs', ]; @@ -68,8 +82,8 @@ export default class PreferencesUserSettingsTab extends React.Component { // Autocomplete delay (niche text box) ]; - constructor() { - super(); + constructor(props) { + super(props); this.state = { autoLaunch: false, @@ -89,7 +103,7 @@ export default class PreferencesUserSettingsTab extends React.Component { }; } - async componentDidMount(): void { + async componentDidMount() { const platform = PlatformPeg.get(); const autoLaunchSupported = await platform.supportsAutoLaunch(); @@ -128,38 +142,38 @@ export default class PreferencesUserSettingsTab extends React.Component { }); } - _onAutoLaunchChange = (checked) => { + private onAutoLaunchChange = (checked: boolean) => { PlatformPeg.get().setAutoLaunchEnabled(checked).then(() => this.setState({autoLaunch: checked})); }; - _onWarnBeforeExitChange = (checked) => { + private onWarnBeforeExitChange = (checked: boolean) => { PlatformPeg.get().setWarnBeforeExit(checked).then(() => this.setState({warnBeforeExit: checked})); } - _onAlwaysShowMenuBarChange = (checked) => { + private onAlwaysShowMenuBarChange = (checked: boolean) => { PlatformPeg.get().setAutoHideMenuBarEnabled(!checked).then(() => this.setState({alwaysShowMenuBar: checked})); }; - _onMinimizeToTrayChange = (checked) => { + private onMinimizeToTrayChange = (checked: boolean) => { PlatformPeg.get().setMinimizeToTrayEnabled(checked).then(() => this.setState({minimizeToTray: checked})); }; - _onAutocompleteDelayChange = (e) => { + private onAutocompleteDelayChange = (e: React.ChangeEvent) => { this.setState({autocompleteDelay: e.target.value}); SettingsStore.setValue("autocompleteDelay", null, SettingLevel.DEVICE, e.target.value); }; - _onReadMarkerInViewThresholdMs = (e) => { + private onReadMarkerInViewThresholdMs = (e: React.ChangeEvent) => { this.setState({readMarkerInViewThresholdMs: e.target.value}); SettingsStore.setValue("readMarkerInViewThresholdMs", null, SettingLevel.DEVICE, e.target.value); }; - _onReadMarkerOutOfViewThresholdMs = (e) => { + private onReadMarkerOutOfViewThresholdMs = (e: React.ChangeEvent) => { this.setState({readMarkerOutOfViewThresholdMs: e.target.value}); SettingsStore.setValue("readMarkerOutOfViewThresholdMs", null, SettingLevel.DEVICE, e.target.value); }; - _renderGroup(settingIds) { + private renderGroup(settingIds: string[]): React.ReactNodeArray { const SettingsFlag = sdk.getComponent("views.elements.SettingsFlag"); return settingIds.filter(SettingsStore.isEnabled).map(i => { return ; @@ -171,7 +185,7 @@ export default class PreferencesUserSettingsTab extends React.Component { if (this.state.autoLaunchSupported) { autoLaunchOption = ; } @@ -179,7 +193,7 @@ export default class PreferencesUserSettingsTab extends React.Component { if (this.state.warnBeforeExitSupported) { warnBeforeExitOption = ; } @@ -187,7 +201,7 @@ export default class PreferencesUserSettingsTab extends React.Component { if (this.state.alwaysShowMenuBarSupported) { autoHideMenuOption = ; } @@ -195,7 +209,7 @@ export default class PreferencesUserSettingsTab extends React.Component { if (this.state.minimizeToTraySupported) { minimizeToTrayOption = ; } @@ -205,22 +219,22 @@ export default class PreferencesUserSettingsTab extends React.Component {
    {_t("Room list")} - {this._renderGroup(PreferencesUserSettingsTab.ROOM_LIST_SETTINGS)} + {this.renderGroup(PreferencesUserSettingsTab.ROOM_LIST_SETTINGS)}
    {_t("Composer")} - {this._renderGroup(PreferencesUserSettingsTab.COMPOSER_SETTINGS)} + {this.renderGroup(PreferencesUserSettingsTab.COMPOSER_SETTINGS)}
    {_t("Timeline")} - {this._renderGroup(PreferencesUserSettingsTab.TIMELINE_SETTINGS)} + {this.renderGroup(PreferencesUserSettingsTab.TIMELINE_SETTINGS)}
    {_t("General")} - {this._renderGroup(PreferencesUserSettingsTab.GENERAL_SETTINGS)} + {this.renderGroup(PreferencesUserSettingsTab.GENERAL_SETTINGS)} {minimizeToTrayOption} {autoHideMenuOption} {autoLaunchOption} @@ -229,17 +243,17 @@ export default class PreferencesUserSettingsTab extends React.Component { label={_t('Autocomplete delay (ms)')} type='number' value={this.state.autocompleteDelay} - onChange={this._onAutocompleteDelayChange} /> + onChange={this.onAutocompleteDelayChange} /> + onChange={this.onReadMarkerInViewThresholdMs} /> + onChange={this.onReadMarkerOutOfViewThresholdMs} />
    ); diff --git a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js index 8a70811399..53ed511b0a 100644 --- a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js @@ -255,15 +255,18 @@ export default class SecurityUserSettingsTab extends React.Component { _renderIgnoredUsers() { const {waitingUnignored, ignoredUserIds} = this.state; - if (!ignoredUserIds || ignoredUserIds.length === 0) return null; - - const userIds = ignoredUserIds - .map((u) => ); + const userIds = !ignoredUserIds?.length + ? _t('You have no ignored users.') + : ignoredUserIds.map((u) => { + return ( + + ); + }); return (
    diff --git a/src/components/views/settings/tabs/user/VoiceUserSettingsTab.js b/src/components/views/settings/tabs/user/VoiceUserSettingsTab.js index d8adab55f6..362059f8ed 100644 --- a/src/components/views/settings/tabs/user/VoiceUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/VoiceUserSettingsTab.js @@ -176,8 +176,8 @@ export default class VoiceUserSettingsTab extends React.Component { const defaultDevice = getDefaultDevice(audioOutputs); speakerDropdown = ( + value={this.state.activeAudioOutput || defaultDevice} + onChange={this._setAudioOutput}> {this._renderDeviceOptions(audioOutputs, 'audioOutput')} ); @@ -188,8 +188,8 @@ export default class VoiceUserSettingsTab extends React.Component { const defaultDevice = getDefaultDevice(audioInputs); microphoneDropdown = ( + value={this.state.activeAudioInput || defaultDevice} + onChange={this._setAudioInput}> {this._renderDeviceOptions(audioInputs, 'audioInput')} ); @@ -200,8 +200,8 @@ export default class VoiceUserSettingsTab extends React.Component { const defaultDevice = getDefaultDevice(videoInputs); webcamDropdown = ( + value={this.state.activeVideoInput || defaultDevice} + onChange={this._setVideoInput}> {this._renderDeviceOptions(videoInputs, 'videoInput')} ); diff --git a/src/components/views/spaces/SpaceTreeLevel.tsx b/src/components/views/spaces/SpaceTreeLevel.tsx index 6825d84013..e48e1d5dc2 100644 --- a/src/components/views/spaces/SpaceTreeLevel.tsx +++ b/src/components/views/spaces/SpaceTreeLevel.tsx @@ -297,15 +297,19 @@ export class SpaceItem extends React.PureComponent { const isActive = activeSpaces.includes(space); const itemClasses = classNames({ "mx_SpaceItem": true, + "mx_SpaceItem_narrow": isNarrow, "collapsed": collapsed, "hasSubSpaces": childSpaces && childSpaces.length, }); + + const isInvite = space.getMyMembership() === "invite"; const classes = classNames("mx_SpaceButton", { mx_SpaceButton_active: isActive, mx_SpaceButton_hasMenuOpen: !!this.state.contextMenuPosition, mx_SpaceButton_narrow: isNarrow, + mx_SpaceButton_invite: isInvite, }); - const notificationState = space.getMyMembership() === "invite" + const notificationState = isInvite ? StaticNotificationState.forSymbol("!", NotificationColor.Red) : SpaceStore.instance.getNotificationState(space.roomId); diff --git a/src/components/views/verification/VerificationCancelled.js b/src/components/views/verification/VerificationCancelled.js index 0bbaea1804..c57094d9b5 100644 --- a/src/components/views/verification/VerificationCancelled.js +++ b/src/components/views/verification/VerificationCancelled.js @@ -29,14 +29,14 @@ export default class VerificationCancelled extends React.Component { render() { const DialogButtons = sdk.getComponent('views.elements.DialogButtons'); return
    -

    {_t( - "The other party cancelled the verification.", - )}

    - +

    {_t( + "The other party cancelled the verification.", + )}

    +
    ; } } diff --git a/src/components/views/voice_messages/Clock.tsx b/src/components/views/voice_messages/Clock.tsx index 6c256957e9..23e6762c52 100644 --- a/src/components/views/voice_messages/Clock.tsx +++ b/src/components/views/voice_messages/Clock.tsx @@ -29,14 +29,20 @@ interface IState { * displayed, making it possible to see "82:29". */ @replaceableComponent("views.voice_messages.Clock") -export default class Clock extends React.PureComponent { +export default class Clock extends React.Component { public constructor(props) { super(props); } + shouldComponentUpdate(nextProps: Readonly, nextState: Readonly, nextContext: any): boolean { + const currentFloor = Math.floor(this.props.seconds); + const nextFloor = Math.floor(nextProps.seconds); + return currentFloor !== nextFloor; + } + public render() { const minutes = Math.floor(this.props.seconds / 60).toFixed(0).padStart(2, '0'); - const seconds = Math.round(this.props.seconds % 60).toFixed(0).padStart(2, '0'); // hide millis + const seconds = Math.floor(this.props.seconds % 60).toFixed(0).padStart(2, '0'); // hide millis return {minutes}:{seconds}; } } diff --git a/src/components/views/voice_messages/LiveRecordingClock.tsx b/src/components/views/voice_messages/LiveRecordingClock.tsx index 5e9006c6ab..b82539eb16 100644 --- a/src/components/views/voice_messages/LiveRecordingClock.tsx +++ b/src/components/views/voice_messages/LiveRecordingClock.tsx @@ -31,7 +31,7 @@ interface IState { * A clock for a live recording. */ @replaceableComponent("views.voice_messages.LiveRecordingClock") -export default class LiveRecordingClock extends React.Component { +export default class LiveRecordingClock extends React.PureComponent { public constructor(props) { super(props); @@ -39,12 +39,6 @@ export default class LiveRecordingClock extends React.Component this.props.recorder.liveData.onUpdate(this.onRecordingUpdate); } - shouldComponentUpdate(nextProps: Readonly, nextState: Readonly, nextContext: any): boolean { - const currentFloor = Math.floor(this.state.seconds); - const nextFloor = Math.floor(nextState.seconds); - return currentFloor !== nextFloor; - } - private onRecordingUpdate = (update: IRecordingUpdate) => { this.setState({seconds: update.timeSeconds}); }; diff --git a/src/components/views/voice_messages/LiveRecordingWaveform.tsx b/src/components/views/voice_messages/LiveRecordingWaveform.tsx index c1f5e97fff..aab89f6ab1 100644 --- a/src/components/views/voice_messages/LiveRecordingWaveform.tsx +++ b/src/components/views/voice_messages/LiveRecordingWaveform.tsx @@ -15,7 +15,7 @@ limitations under the License. */ import React from "react"; -import {IRecordingUpdate, VoiceRecording} from "../../../voice/VoiceRecording"; +import {IRecordingUpdate, RECORDING_PLAYBACK_SAMPLES, VoiceRecording} from "../../../voice/VoiceRecording"; import {replaceableComponent} from "../../../utils/replaceableComponent"; import {arrayFastResample, arraySeed} from "../../../utils/arrays"; import {percentageOf} from "../../../utils/numbers"; @@ -29,8 +29,6 @@ interface IState { heights: number[]; } -const DOWNSAMPLE_TARGET = 35; // number of bars we want - /** * A waveform which shows the waveform of a live recording */ @@ -39,14 +37,14 @@ export default class LiveRecordingWaveform extends React.PureComponent { // The waveform and the downsample target are pretty close, so we should be fine to // do this, despite the docs on arrayFastResample. - const bars = arrayFastResample(Array.from(update.waveform), DOWNSAMPLE_TARGET); + const bars = arrayFastResample(Array.from(update.waveform), RECORDING_PLAYBACK_SAMPLES); this.setState({ // The incoming data is between zero and one, but typically even screaming into a // microphone won't send you over 0.6, so we artificially adjust the gain for the diff --git a/src/components/views/voice_messages/PlayPauseButton.tsx b/src/components/views/voice_messages/PlayPauseButton.tsx new file mode 100644 index 0000000000..1f87eb012d --- /dev/null +++ b/src/components/views/voice_messages/PlayPauseButton.tsx @@ -0,0 +1,61 @@ +/* +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 React, {ReactNode} from "react"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; +import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; +import {_t} from "../../../languageHandler"; +import {Playback, PlaybackState} from "../../../voice/Playback"; +import classNames from "classnames"; + +interface IProps { + // Playback instance to manipulate. Cannot change during the component lifecycle. + playback: Playback; + + // The playback phase to render. Able to change during the component lifecycle. + playbackPhase: PlaybackState; +} + +/** + * Displays a play/pause button (activating the play/pause function of the recorder) + * to be displayed in reference to a recording. + */ +@replaceableComponent("views.voice_messages.PlayPauseButton") +export default class PlayPauseButton extends React.PureComponent { + public constructor(props) { + super(props); + } + + private onClick = async () => { + await this.props.playback.toggle(); + }; + + public render(): ReactNode { + const isPlaying = this.props.playback.isPlaying; + const isDisabled = this.props.playbackPhase === PlaybackState.Decoding; + const classes = classNames('mx_PlayPauseButton', { + 'mx_PlayPauseButton_play': !isPlaying, + 'mx_PlayPauseButton_pause': isPlaying, + 'mx_PlayPauseButton_disabled': isDisabled, + }); + return ; + } +} diff --git a/src/components/views/voice_messages/PlaybackClock.tsx b/src/components/views/voice_messages/PlaybackClock.tsx new file mode 100644 index 0000000000..2e8ec9a3e7 --- /dev/null +++ b/src/components/views/voice_messages/PlaybackClock.tsx @@ -0,0 +1,71 @@ +/* +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 React from "react"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; +import Clock from "./Clock"; +import {Playback, PlaybackState} from "../../../voice/Playback"; +import {UPDATE_EVENT} from "../../../stores/AsyncStore"; + +interface IProps { + playback: Playback; +} + +interface IState { + seconds: number; + durationSeconds: number; + playbackPhase: PlaybackState; +} + +/** + * A clock for a playback of a recording. + */ +@replaceableComponent("views.voice_messages.PlaybackClock") +export default class PlaybackClock extends React.PureComponent { + public constructor(props) { + super(props); + + this.state = { + seconds: this.props.playback.clockInfo.timeSeconds, + // we track the duration on state because we won't really know what the clip duration + // is until the first time update, and as a PureComponent we are trying to dedupe state + // updates as much as possible. This is just the easiest way to avoid a forceUpdate() or + // member property to track "did we get a duration". + durationSeconds: this.props.playback.clockInfo.durationSeconds, + playbackPhase: PlaybackState.Stopped, // assume not started, so full clock + }; + this.props.playback.on(UPDATE_EVENT, this.onPlaybackUpdate); + this.props.playback.clockInfo.liveData.onUpdate(this.onTimeUpdate); + } + + private onPlaybackUpdate = (ev: PlaybackState) => { + // Convert Decoding -> Stopped because we don't care about the distinction here + if (ev === PlaybackState.Decoding) ev = PlaybackState.Stopped; + this.setState({playbackPhase: ev}); + }; + + private onTimeUpdate = (time: number[]) => { + this.setState({seconds: time[0], durationSeconds: time[1]}); + }; + + public render() { + let seconds = this.state.seconds; + if (this.state.playbackPhase === PlaybackState.Stopped) { + seconds = this.state.durationSeconds; + } + return ; + } +} diff --git a/src/components/views/voice_messages/PlaybackWaveform.tsx b/src/components/views/voice_messages/PlaybackWaveform.tsx new file mode 100644 index 0000000000..123af5dfa5 --- /dev/null +++ b/src/components/views/voice_messages/PlaybackWaveform.tsx @@ -0,0 +1,68 @@ +/* +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 React from "react"; +import {replaceableComponent} from "../../../utils/replaceableComponent"; +import {arraySeed, arrayTrimFill} from "../../../utils/arrays"; +import Waveform from "./Waveform"; +import {Playback, PLAYBACK_WAVEFORM_SAMPLES} from "../../../voice/Playback"; +import {percentageOf} from "../../../utils/numbers"; + +interface IProps { + playback: Playback; +} + +interface IState { + heights: number[]; + progress: number; +} + +/** + * A waveform which shows the waveform of a previously recorded recording + */ +@replaceableComponent("views.voice_messages.PlaybackWaveform") +export default class PlaybackWaveform extends React.PureComponent { + public constructor(props) { + super(props); + + this.state = { + heights: this.toHeights(this.props.playback.waveform), + progress: 0, // default no progress + }; + + this.props.playback.waveformData.onUpdate(this.onWaveformUpdate); + this.props.playback.clockInfo.liveData.onUpdate(this.onTimeUpdate); + } + + private toHeights(waveform: number[]) { + const seed = arraySeed(0, PLAYBACK_WAVEFORM_SAMPLES); + return arrayTrimFill(waveform, PLAYBACK_WAVEFORM_SAMPLES, seed); + } + + private onWaveformUpdate = (waveform: number[]) => { + this.setState({heights: this.toHeights(waveform)}); + }; + + private onTimeUpdate = (time: number[]) => { + // Track percentages to very coarse precision, otherwise 0.002 ends up highlighting a bar. + const progress = Number(percentageOf(time[0], 0, time[1]).toFixed(1)); + this.setState({progress}); + }; + + public render() { + return ; + } +} diff --git a/src/components/views/voice_messages/RecordingPlayback.tsx b/src/components/views/voice_messages/RecordingPlayback.tsx new file mode 100644 index 0000000000..776997cec2 --- /dev/null +++ b/src/components/views/voice_messages/RecordingPlayback.tsx @@ -0,0 +1,62 @@ +/* +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 {Playback, PlaybackState} from "../../../voice/Playback"; +import React, {ReactNode} from "react"; +import {UPDATE_EVENT} from "../../../stores/AsyncStore"; +import PlaybackWaveform from "./PlaybackWaveform"; +import PlayPauseButton from "./PlayPauseButton"; +import PlaybackClock from "./PlaybackClock"; + +interface IProps { + // Playback instance to render. Cannot change during component lifecycle: create + // an all-new component instead. + playback: Playback; +} + +interface IState { + playbackPhase: PlaybackState; +} + +export default class RecordingPlayback extends React.PureComponent { + constructor(props: IProps) { + super(props); + + this.state = { + playbackPhase: PlaybackState.Decoding, // default assumption + }; + + // We don't need to de-register: the class handles this for us internally + this.props.playback.on(UPDATE_EVENT, this.onPlaybackUpdate); + + // Don't wait for the promise to complete - it will emit a progress update when it + // is done, and it's not meant to take long anyhow. + // noinspection JSIgnoredPromiseFromCall + this.props.playback.prepare(); + } + + private onPlaybackUpdate = (ev: PlaybackState) => { + this.setState({playbackPhase: ev}); + }; + + public render(): ReactNode { + return
    + + + +
    + } +} diff --git a/src/components/views/voice_messages/Waveform.tsx b/src/components/views/voice_messages/Waveform.tsx index 5fa68dcadc..840a5a12b3 100644 --- a/src/components/views/voice_messages/Waveform.tsx +++ b/src/components/views/voice_messages/Waveform.tsx @@ -16,9 +16,11 @@ limitations under the License. import React from "react"; import {replaceableComponent} from "../../../utils/replaceableComponent"; +import classNames from "classnames"; interface IProps { relHeights: number[]; // relative heights (0-1) + progress: number; // percent complete, 0-1, default 100% } interface IState { @@ -28,9 +30,16 @@ interface IState { * A simple waveform component. This renders bars (centered vertically) for each * height provided in the component properties. Updating the properties will update * the rendered waveform. + * + * For CSS purposes, a mx_Waveform_bar_100pct class is added when the bar should be + * "filled", as a demonstration of the progress property. */ @replaceableComponent("views.voice_messages.Waveform") export default class Waveform extends React.PureComponent { + public static defaultProps = { + progress: 1, + }; + public constructor(props) { super(props); } @@ -38,7 +47,13 @@ export default class Waveform extends React.PureComponent { public render() { return
    {this.props.relHeights.map((h, i) => { - return ; + const progress = this.props.progress; + const isCompleteBar = (i / this.props.relHeights.length) <= progress && progress > 0; + const classes = classNames({ + 'mx_Waveform_bar': true, + 'mx_Waveform_bar_100pct': isCompleteBar, + }); + return ; })}
    ; } diff --git a/src/components/views/voip/AudioFeed.tsx b/src/components/views/voip/AudioFeed.tsx new file mode 100644 index 0000000000..c78f0c0fc8 --- /dev/null +++ b/src/components/views/voip/AudioFeed.tsx @@ -0,0 +1,97 @@ +/* +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. +*/ + +import React, {createRef} from 'react'; +import { CallFeed, CallFeedEvent } from 'matrix-js-sdk/src/webrtc/callFeed'; +import { logger } from 'matrix-js-sdk/src/logger'; +import CallMediaHandler from "../../../CallMediaHandler"; + +interface IProps { + feed: CallFeed, +} + +export default class AudioFeed extends React.Component { + private element = createRef(); + + componentDidMount() { + this.props.feed.addListener(CallFeedEvent.NewStream, this.onNewStream); + this.playMedia(); + } + + componentWillUnmount() { + this.props.feed.removeListener(CallFeedEvent.NewStream, this.onNewStream); + this.stopMedia(); + } + + private playMedia() { + const element = this.element.current; + const audioOutput = CallMediaHandler.getAudioOutput(); + + if (audioOutput) { + try { + // This seems quite unreliable in Chrome, although I haven't yet managed to make a jsfiddle where + // it fails. + // It seems reliable if you set the sink ID after setting the srcObject and then set the sink ID + // back to the default after the call is over - Dave + element.setSinkId(audioOutput); + } catch (e) { + console.error("Couldn't set requested audio output device: using default", e); + logger.warn("Couldn't set requested audio output device: using default", e); + } + } + + element.muted = false; + element.srcObject = this.props.feed.stream; + element.autoplay = true; + + try { + // A note on calling methods on media elements: + // We used to have queues per media element to serialise all calls on those elements. + // The reason given for this was that load() and play() were racing. However, we now + // never call load() explicitly so this seems unnecessary. However, serialising every + // operation was causing bugs where video would not resume because some play command + // had got stuck and all media operations were queued up behind it. If necessary, we + // should serialise the ones that need to be serialised but then be able to interrupt + // them with another load() which will cancel the pending one, but since we don't call + // load() explicitly, it shouldn't be a problem. - Dave + element.play() + } catch (e) { + logger.info("Failed to play media element with feed", this.props.feed, e); + } + } + + private stopMedia() { + const element = this.element.current; + + element.pause(); + element.src = null; + + // As per comment in componentDidMount, setting the sink ID back to the + // default once the call is over makes setSinkId work reliably. - Dave + // Since we are not using the same element anymore, the above doesn't + // seem to be necessary - Šimon + } + + private onNewStream = () => { + this.playMedia(); + }; + + render() { + return ( +
    ; + const avatarSize = this.props.pipMode ? 76 : 160; + // The 'content' for the call, ie. the videos for a video call and profile picture // for voice calls (fills the bg) let contentView: React.ReactNode; @@ -482,11 +492,13 @@ export default class CallView extends React.Component { const isOnHold = this.state.isLocalOnHold || this.state.isRemoteOnHold; let holdTransferContent; if (transfereeCall) { - const transferTargetRoom = MatrixClientPeg.get().getRoom(CallHandler.roomIdForCall(this.props.call)); + const transferTargetRoom = MatrixClientPeg.get().getRoom( + CallHandler.sharedInstance().roomIdForCall(this.props.call), + ); const transferTargetName = transferTargetRoom ? transferTargetRoom.name : _t("unknown person"); const transfereeRoom = MatrixClientPeg.get().getRoom( - CallHandler.roomIdForCall(transfereeCall), + CallHandler.sharedInstance().roomIdForCall(transfereeCall), ); const transfereeName = transfereeRoom ? transfereeRoom.name : _t("unknown person"); @@ -522,41 +534,85 @@ export default class CallView extends React.Component {
    ; } - if (this.props.call.type === CallType.Video) { - let localVideoFeed = null; - let onHoldBackground = null; - const backgroundStyle: CSSProperties = {}; - const containerClasses = classNames({ - mx_CallView_video: true, - mx_CallView_video_hold: isOnHold, - }); - if (isOnHold) { + // This is a bit messy. I can't see a reason to have two onHold/transfer screens + if (isOnHold || transfereeCall) { + if (this.props.call.type === CallType.Video) { + const containerClasses = classNames({ + mx_CallView_content: true, + mx_CallView_video: true, + mx_CallView_video_hold: isOnHold, + }); + let onHoldBackground = null; + const backgroundStyle: CSSProperties = {}; const backgroundAvatarUrl = avatarUrlForMember( - // is it worth getting the size of the div to pass here? + // is it worth getting the size of the div to pass here? this.props.call.getOpponentMember(), 1024, 1024, 'crop', ); backgroundStyle.backgroundImage = 'url(' + backgroundAvatarUrl + ')'; onHoldBackground =
    ; - } - if (!this.state.vidMuted) { - localVideoFeed = ; - } - contentView =
    - {onHoldBackground} - - {localVideoFeed} - {holdTransferContent} - {callControls} -
    ; - } else { - const avatarSize = this.props.pipMode ? 76 : 160; + contentView = ( +
    + {onHoldBackground} + {holdTransferContent} + {callControls} +
    + ); + } else { + const classes = classNames({ + mx_CallView_content: true, + mx_CallView_voice: true, + mx_CallView_voice_hold: isOnHold, + }); + + contentView =( +
    +
    +
    + +
    +
    + {holdTransferContent} + {callControls} +
    + ); + } + } else if (this.props.call.noIncomingFeeds()) { + // Here we're reusing the css classes from voice on hold, because + // I am lazy. If this gets merged, the CallView might be subject + // to change anyway - I might take an axe to this file in order to + // try to get other things working const classes = classNames({ + mx_CallView_content: true, mx_CallView_voice: true, - mx_CallView_voice_hold: isOnHold, }); + const feeds = this.props.call.getLocalFeeds().map((feed, i) => { + // Here we check to hide local audio feeds to achieve the same UI/UX + // as before. But once again this might be subject to change + if (feed.isVideoMuted()) return; + return ( + + ); + }); + + // Saying "Connecting" here isn't really true, but the best thing + // I can come up with, but this might be subject to change as well contentView =
    + {feeds}
    { />
    - {holdTransferContent} +
    {_t("Connecting")}
    + {callControls} +
    ; + } else { + const containerClasses = classNames({ + mx_CallView_content: true, + mx_CallView_video: true, + }); + + // TODO: Later the CallView should probably be reworked to support + // any number of feeds but now we can always expect there to be two + // feeds. This is because the js-sdk ignores any new incoming streams + const feeds = this.state.feeds.map((feed, i) => { + // Here we check to hide local audio feeds to achieve the same UI/UX + // as before. But once again this might be subject to change + if (feed.isVideoMuted() && feed.isLocal()) return; + return ( + + ); + }); + + contentView =
    + {feeds} {callControls}
    ; } diff --git a/src/components/views/voip/CallViewForRoom.tsx b/src/components/views/voip/CallViewForRoom.tsx index 878b6af20f..0c785f758d 100644 --- a/src/components/views/voip/CallViewForRoom.tsx +++ b/src/components/views/voip/CallViewForRoom.tsx @@ -16,7 +16,7 @@ limitations under the License. import { CallState, MatrixCall } from 'matrix-js-sdk/src/webrtc/call'; import React from 'react'; -import CallHandler from '../../../CallHandler'; +import CallHandler, { CallHandlerEvent } from '../../../CallHandler'; import CallView from './CallView'; import dis from '../../../dispatcher/dispatcher'; import {Resizable} from "re-resizable"; @@ -54,24 +54,30 @@ export default class CallViewForRoom extends React.Component { public componentDidMount() { this.dispatcherRef = dis.register(this.onAction); + CallHandler.sharedInstance().addListener(CallHandlerEvent.CallChangeRoom, this.updateCall); } public componentWillUnmount() { dis.unregister(this.dispatcherRef); + CallHandler.sharedInstance().removeListener(CallHandlerEvent.CallChangeRoom, this.updateCall); } private onAction = (payload) => { switch (payload.action) { case 'call_state': { - const newCall = this.getCall(); - if (newCall !== this.state.call) { - this.setState({call: newCall}); - } + this.updateCall(); break; } } }; + private updateCall = () => { + const newCall = this.getCall(); + if (newCall !== this.state.call) { + this.setState({call: newCall}); + } + }; + private getCall(): MatrixCall { const call = CallHandler.sharedInstance().getCallForRoom(this.props.roomId); diff --git a/src/components/views/voip/IncomingCallBox.tsx b/src/components/views/voip/IncomingCallBox.tsx index 0ca2a196c2..2abdc0641d 100644 --- a/src/components/views/voip/IncomingCallBox.tsx +++ b/src/components/views/voip/IncomingCallBox.tsx @@ -72,7 +72,7 @@ export default class IncomingCallBox extends React.Component { e.stopPropagation(); dis.dispatch({ action: 'answer', - room_id: CallHandler.roomIdForCall(this.state.incomingCall), + room_id: CallHandler.sharedInstance().roomIdForCall(this.state.incomingCall), }); }; @@ -80,7 +80,7 @@ export default class IncomingCallBox extends React.Component { e.stopPropagation(); dis.dispatch({ action: 'reject', - room_id: CallHandler.roomIdForCall(this.state.incomingCall), + room_id: CallHandler.sharedInstance().roomIdForCall(this.state.incomingCall), }); }; @@ -91,7 +91,7 @@ export default class IncomingCallBox extends React.Component { let room = null; if (this.state.incomingCall) { - room = MatrixClientPeg.get().getRoom(CallHandler.roomIdForCall(this.state.incomingCall)); + room = MatrixClientPeg.get().getRoom(CallHandler.sharedInstance().roomIdForCall(this.state.incomingCall)); } const caller = room ? room.name : _t("Unknown caller"); diff --git a/src/components/views/voip/VideoFeed.tsx b/src/components/views/voip/VideoFeed.tsx index 2981fb6c04..d22fa055ce 100644 --- a/src/components/views/voip/VideoFeed.tsx +++ b/src/components/views/voip/VideoFeed.tsx @@ -18,52 +18,102 @@ import classnames from 'classnames'; import { MatrixCall } from 'matrix-js-sdk/src/webrtc/call'; import React, {createRef} from 'react'; import SettingsStore from "../../../settings/SettingsStore"; +import { CallFeed, CallFeedEvent } from 'matrix-js-sdk/src/webrtc/callFeed'; +import { logger } from 'matrix-js-sdk/src/logger'; +import MemberAvatar from "../avatars/MemberAvatar" import {replaceableComponent} from "../../../utils/replaceableComponent"; -export enum VideoFeedType { - Local, - Remote, -} - interface IProps { call: MatrixCall, - type: VideoFeedType, + feed: CallFeed, + + // Whether this call view is for picture-in-picture mode + // otherwise, it's the larger call view when viewing the room the call is in. + // This is sort of a proxy for a number of things but we currently have no + // need to control those things separately, so this is simpler. + pipMode?: boolean; // a callback which is called when the video element is resized // due to a change in video metadata onResize?: (e: Event) => void, } -@replaceableComponent("views.voip.VideoFeed") -export default class VideoFeed extends React.Component { - private vid = createRef(); +interface IState { + audioMuted: boolean; + videoMuted: boolean; +} - componentDidMount() { - this.vid.current.addEventListener('resize', this.onResize); - this.setVideoElement(); +@replaceableComponent("views.voip.VideoFeed") +export default class VideoFeed extends React.Component { + private element = createRef(); + + constructor(props: IProps) { + super(props); + + this.state = { + audioMuted: this.props.feed.isAudioMuted(), + videoMuted: this.props.feed.isVideoMuted(), + }; } - componentDidUpdate(prevProps) { - if (this.props.call !== prevProps.call) { - this.setVideoElement(); - } + componentDidMount() { + this.props.feed.addListener(CallFeedEvent.NewStream, this.onNewStream); + this.playMedia(); } componentWillUnmount() { - this.vid.current.removeEventListener('resize', this.onResize); + this.props.feed.removeListener(CallFeedEvent.NewStream, this.onNewStream); + this.element.current?.removeEventListener('resize', this.onResize); + this.stopMedia(); } - private setVideoElement() { - if (this.props.type === VideoFeedType.Local) { - this.props.call.setLocalVideoElement(this.vid.current); - } else { - this.props.call.setRemoteVideoElement(this.vid.current); + private playMedia() { + const element = this.element.current; + if (!element) return; + // We play audio in AudioFeed, not here + element.muted = true; + element.srcObject = this.props.feed.stream; + element.autoplay = true; + try { + // A note on calling methods on media elements: + // We used to have queues per media element to serialise all calls on those elements. + // The reason given for this was that load() and play() were racing. However, we now + // never call load() explicitly so this seems unnecessary. However, serialising every + // operation was causing bugs where video would not resume because some play command + // had got stuck and all media operations were queued up behind it. If necessary, we + // should serialise the ones that need to be serialised but then be able to interrupt + // them with another load() which will cancel the pending one, but since we don't call + // load() explicitly, it shouldn't be a problem. - Dave + element.play() + } catch (e) { + logger.info("Failed to play media element with feed", this.props.feed, e); } } - onResize = (e) => { - if (this.props.onResize) { + private stopMedia() { + const element = this.element.current; + if (!element) return; + + element.pause(); + element.src = null; + + // As per comment in componentDidMount, setting the sink ID back to the + // default once the call is over makes setSinkId work reliably. - Dave + // Since we are not using the same element anymore, the above doesn't + // seem to be necessary - Šimon + } + + private onNewStream = () => { + this.setState({ + audioMuted: this.props.feed.isAudioMuted(), + videoMuted: this.props.feed.isVideoMuted(), + }); + this.playMedia(); + }; + + private onResize = (e) => { + if (this.props.onResize && !this.props.feed.isLocal()) { this.props.onResize(e); } }; @@ -71,14 +121,33 @@ export default class VideoFeed extends React.Component { render() { const videoClasses = { mx_VideoFeed: true, - mx_VideoFeed_local: this.props.type === VideoFeedType.Local, - mx_VideoFeed_remote: this.props.type === VideoFeedType.Remote, + mx_VideoFeed_local: this.props.feed.isLocal(), + mx_VideoFeed_remote: !this.props.feed.isLocal(), + mx_VideoFeed_voice: this.state.videoMuted, + mx_VideoFeed_video: !this.state.videoMuted, mx_VideoFeed_mirror: ( - this.props.type === VideoFeedType.Local && + this.props.feed.isLocal() && SettingsStore.getValue('VideoView.flipVideoHorizontally') ), }; - return
    diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index ed49fb6b44..6f2a4e8aee 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1458,7 +1458,6 @@ "Encrypting your message...": "Encrypting your message...", "Your message was sent": "Your message was sent", "Failed to send": "Failed to send", - "Please select the destination room for this message": "Please select the destination room for this message", "Scroll to most recent messages": "Scroll to most recent messages", "Close preview": "Close preview", "and %(count)s others...|other": "and %(count)s others...", diff --git a/src/stores/RoomViewStore.tsx b/src/stores/RoomViewStore.tsx index fe2e0a66b2..37162c8ae7 100644 --- a/src/stores/RoomViewStore.tsx +++ b/src/stores/RoomViewStore.tsx @@ -53,8 +53,6 @@ const INITIAL_STATE = { // Any error that has occurred during loading roomLoadError: null, - forwardingEvent: null, - quotingEvent: null, replyingToEvent: null, @@ -149,11 +147,6 @@ class RoomViewStore extends Store { case 'on_logged_out': this.reset(); break; - case 'forward_event': - this.setState({ - forwardingEvent: payload.event, - }); - break; case 'reply_to_event': // If currently viewed room does not match the room in which we wish to reply then change rooms // this can happen when performing a search across all rooms @@ -186,7 +179,6 @@ class RoomViewStore extends Store { roomAlias: payload.room_alias, initialEventId: payload.event_id, isInitialEventHighlighted: payload.highlighted, - forwardingEvent: null, roomLoading: false, roomLoadError: null, // should peek by default @@ -206,14 +198,6 @@ class RoomViewStore extends Store { newState.replyingToEvent = payload.replyingToEvent; } - if (this.state.forwardingEvent) { - dis.dispatch({ - action: 'send_event', - room_id: newState.roomId, - event: this.state.forwardingEvent, - }); - } - this.setState(newState); if (payload.auto_join) { @@ -419,11 +403,6 @@ class RoomViewStore extends Store { return this.state.joinError; } - // The mxEvent if one is about to be forwarded - public getForwardingEvent() { - return this.state.forwardingEvent; - } - // The mxEvent if one is currently being replied to/quoted public getQuotingEvent() { return this.state.replyingToEvent; From 44b143c8c3063be7ca2bf24e6cfdb81be9351c75 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Sat, 8 May 2021 21:17:05 -0400 Subject: [PATCH 0311/1449] Match requested avatar size to displayed size Reduces the blurriness of avatars in the EventTilePreview. Signed-off-by: Robin Townsend --- src/components/views/elements/EventTilePreview.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/elements/EventTilePreview.tsx b/src/components/views/elements/EventTilePreview.tsx index b15fbbed2b..95f9a97058 100644 --- a/src/components/views/elements/EventTilePreview.tsx +++ b/src/components/views/elements/EventTilePreview.tsx @@ -61,7 +61,7 @@ interface IState { message: string; } -const AVATAR_SIZE = 32; +const AVATAR_SIZE = 30; @replaceableComponent("views.elements.EventTilePreview") export default class EventTilePreview extends React.Component { From e46bc931781095447a1929938a5cb5bdbdb7de4d Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Sat, 8 May 2021 21:22:31 -0400 Subject: [PATCH 0312/1449] Fall back to MXID when no display name is present MemberAvatar requires a display name, or else it refuses to render. Signed-off-by: Robin Townsend --- src/components/views/elements/EventTilePreview.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/elements/EventTilePreview.tsx b/src/components/views/elements/EventTilePreview.tsx index 95f9a97058..6d2ea687de 100644 --- a/src/components/views/elements/EventTilePreview.tsx +++ b/src/components/views/elements/EventTilePreview.tsx @@ -101,7 +101,7 @@ export default class EventTilePreview extends React.Component { // Fake it more event.sender = { - name: this.props.displayName, + name: this.props.displayName || this.props.userId, userId: this.props.userId, getAvatarUrl: (..._) => { return Avatar.avatarUrlForUser( From 6f98aa06c4d3247f4561224f39bea210327f50a1 Mon Sep 17 00:00:00 2001 From: Jaiwanth Date: Sun, 9 May 2021 13:18:01 +0530 Subject: [PATCH 0313/1449] Save edited state when switching rooms Signed-off-by: Jaiwanth --- src/components/structures/MessagePanel.js | 11 ++++- .../views/rooms/EditMessageComposer.js | 45 +++++++++++++++++-- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index c93f07fa0f..555ee38d17 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -34,6 +34,7 @@ import IRCTimelineProfileResizer from "../views/elements/IRCTimelineProfileResiz import DMRoomMap from "../../utils/DMRoomMap"; import NewRoomIntro from "../views/rooms/NewRoomIntro"; import {replaceableComponent} from "../../utils/replaceableComponent"; +import defaultDispatcher from '../../dispatcher/dispatcher'; const CONTINUATION_MAX_INTERVAL = 5 * 60 * 1000; // 5 minutes const continuedTypes = ['m.sticker', 'm.room.message']; @@ -564,15 +565,23 @@ export default class MessagePanel extends React.Component { return ret; } + _wasEventBeingEdited = (mxEv) => { + return localStorage.getItem(`mx_edit_state_${mxEv.getRoomId()} + _${mxEv.getId()}`) !== null; + } + _getTilesForEvent(prevEvent, mxEv, last, nextEvent, nextEventWithTile) { const TileErrorBoundary = sdk.getComponent('messages.TileErrorBoundary'); const EventTile = sdk.getComponent('rooms.EventTile'); const DateSeparator = sdk.getComponent('messages.DateSeparator'); const ret = []; + if (!this.props.editState && this._wasEventBeingEdited(mxEv) ) { + defaultDispatcher.dispatch({action: "edit_event", event: mxEv}); + } + const isEditing = this.props.editState && this.props.editState.getEvent().getId() === mxEv.getId(); - // local echoes have a fake date, which could even be yesterday. Treat them // as 'today' for the date separators. let ts1 = mxEv.getTs(); diff --git a/src/components/views/rooms/EditMessageComposer.js b/src/components/views/rooms/EditMessageComposer.js index b006fe8c8d..dd87654438 100644 --- a/src/components/views/rooms/EditMessageComposer.js +++ b/src/components/views/rooms/EditMessageComposer.js @@ -34,6 +34,7 @@ import {Action} from "../../../dispatcher/actions"; import CountlyAnalytics from "../../../CountlyAnalytics"; import {getKeyBindingsManager, MessageComposerAction} from '../../../KeyBindingsManager'; import {replaceableComponent} from "../../../utils/replaceableComponent"; +import SendHistoryManager from '../../../SendHistoryManager'; function _isReply(mxEvent) { const relatesTo = mxEvent.getContent()["m.relates_to"]; @@ -120,6 +121,7 @@ export default class EditMessageComposer extends React.Component { saveDisabled: true, }; this._createEditorModel(); + window.addEventListener("beforeunload", this._saveStoredEditorState); } _setEditorRef = ref => { @@ -174,10 +176,43 @@ export default class EditMessageComposer extends React.Component { } _cancelEdit = () => { + this._clearStoredEditorState(); dis.dispatch({action: "edit_event", event: null}); dis.fire(Action.FocusComposer); } + get _shouldSaveStoredEditorState() { + return localStorage.getItem(`mx_edit_state_${this.props.editState.getEvent().getRoomId()} + _${this.props.editState.getEvent().event.event_id}`) !== null; + } + + _restoreStoredEditorState(partCreator) { + const json = localStorage.getItem(this._editorStateKey); + if (json) { + try { + const {parts: serializedParts} = JSON.parse(json); + const parts = serializedParts.map(p => partCreator.deserializePart(p)); + return parts; + } catch (e) { + console.error(e); + } + } + } + + get _editorStateKey() { + return `mx_edit_state_${this.props.editState.getEvent().getRoomId()} + _${this.props.editState.getEvent().event.event_id}`; + } + + _clearStoredEditorState() { + localStorage.removeItem(this._editorStateKey); + } + + _saveStoredEditorState() { + const item = SendHistoryManager.createItem(this.model); + localStorage.setItem(this._editorStateKey, JSON.stringify(item)); + } + _isContentModified(newContent) { // if nothing has changed then bail const oldContent = this.props.editState.getEvent().getContent(); @@ -195,13 +230,13 @@ export default class EditMessageComposer extends React.Component { const editedEvent = this.props.editState.getEvent(); const editContent = createEditContent(this.model, editedEvent); const newContent = editContent["m.new_content"]; - // If content is modified then send an updated event into the room if (this._isContentModified(newContent)) { const roomId = editedEvent.getRoomId(); this._cancelPreviousPendingEdit(); const prom = this.context.sendMessage(roomId, editContent); dis.dispatch({action: "message_sent"}); + this._clearStoredEditorState(); CountlyAnalytics.instance.trackSendMessage(startTime, prom, roomId, true, false, editContent); } @@ -235,6 +270,10 @@ export default class EditMessageComposer extends React.Component { // then when mounting the editor again with the same editor state, // it will set the cursor at the end. this.props.editState.setEditorState(caret, parts); + window.removeEventListener("beforeunload", this._saveStoredEditorState); + if (this._shouldSaveStoredEditorState) { + this._saveStoredEditorState(); + } } _createEditorModel() { @@ -247,10 +286,10 @@ export default class EditMessageComposer extends React.Component { // restore serialized parts from the state parts = editState.getSerializedParts().map(p => partCreator.deserializePart(p)); } else { - // otherwise, parse the body of the event - parts = parseEvent(editState.getEvent(), partCreator); + parts = this._restoreStoredEditorState(partCreator) || parseEvent(editState.getEvent(), partCreator); } this.model = new EditorModel(parts, partCreator); + this._saveStoredEditorState(); } _getInitialCaretPosition() { From 1f7704875013b70717fa0866a3db028319b2c972 Mon Sep 17 00:00:00 2001 From: Jaiwanth Date: Sun, 9 May 2021 16:12:04 +0530 Subject: [PATCH 0314/1449] Minor refactor --- src/components/views/rooms/EditMessageComposer.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/views/rooms/EditMessageComposer.js b/src/components/views/rooms/EditMessageComposer.js index dd87654438..46999bb793 100644 --- a/src/components/views/rooms/EditMessageComposer.js +++ b/src/components/views/rooms/EditMessageComposer.js @@ -182,8 +182,7 @@ export default class EditMessageComposer extends React.Component { } get _shouldSaveStoredEditorState() { - return localStorage.getItem(`mx_edit_state_${this.props.editState.getEvent().getRoomId()} - _${this.props.editState.getEvent().event.event_id}`) !== null; + return localStorage.getItem(this._editorStateKey) !== null; } _restoreStoredEditorState(partCreator) { From 219c983d191d9172e3c68aa11b1765f91ac5c6cd Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Sun, 9 May 2021 10:58:44 -0400 Subject: [PATCH 0315/1449] Use import instead of sdk.getComponent Signed-off-by: Robin Townsend --- src/components/views/context_menus/MessageContextMenu.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/context_menus/MessageContextMenu.js b/src/components/views/context_menus/MessageContextMenu.js index e069bba975..fc2c366b07 100644 --- a/src/components/views/context_menus/MessageContextMenu.js +++ b/src/components/views/context_menus/MessageContextMenu.js @@ -31,6 +31,7 @@ import { isContentActionable } from '../../../utils/EventUtils'; import {MenuItem} from "../../structures/ContextMenu"; import {EventType} from "matrix-js-sdk/src/@types/event"; import {replaceableComponent} from "../../../utils/replaceableComponent"; +import ForwardDialog from "../dialogs/ForwardDialog"; export function canCancel(eventStatus) { return eventStatus === EventStatus.QUEUED || eventStatus === EventStatus.NOT_SENT; @@ -154,7 +155,6 @@ export default class MessageContextMenu extends React.Component { }; onForwardClick = () => { - const ForwardDialog = sdk.getComponent("dialogs.ForwardDialog"); Modal.createTrackedDialog('Forward Message', '', ForwardDialog, { cli: MatrixClientPeg.get(), event: this.props.mxEvent, From c96888c9cba48dfb1d318b2cfb89cd699c6a8529 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Mon, 10 May 2021 00:38:01 -0400 Subject: [PATCH 0316/1449] Make ForwardDialog more readable Signed-off-by: Robin Townsend --- .../views/dialogs/ForwardDialog.tsx | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/components/views/dialogs/ForwardDialog.tsx b/src/components/views/dialogs/ForwardDialog.tsx index ce38a783b3..b1f558dfef 100644 --- a/src/components/views/dialogs/ForwardDialog.tsx +++ b/src/components/views/dialogs/ForwardDialog.tsx @@ -39,6 +39,7 @@ const AVATAR_SIZE = 30; interface IProps extends IDialogProps { cli: MatrixClient; + // The event to forward event: MatrixEvent; } @@ -116,7 +117,7 @@ const ForwardDialog: React.FC = ({ cli, event, onFinished }) => { }); mockEvent.sender = { name: profileInfo.displayname || userId, - userId: userId, + userId, getAvatarUrl: (..._) => { return avatarUrlForUser( { avatarUrl: profileInfo.avatar_url }, @@ -179,28 +180,28 @@ const ForwardDialog: React.FC = ({ cli, event, onFinished }) => { { rooms.length > 0 ? (

    { _t("Rooms") }

    - { rooms.map(room => { - return + cli.sendEvent(room.roomId, event.getType(), event.getContent())} - />; - }) } + />, + ) }
    ) : undefined } { dms.length > 0 ? (

    { _t("Direct Messages") }

    - { dms.map(room => { - return + cli.sendEvent(room.roomId, event.getType(), event.getContent())} - />; - }) } + />, + ) }
    - ) : null } + ) : undefined } { rooms.length + dms.length < 1 ? { _t("No results") } From 100efb1a90c92ac6a8771787cd2564f218507550 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Mon, 10 May 2021 00:40:54 -0400 Subject: [PATCH 0317/1449] Fix ForwardDialog crashing when rendering reply Signed-off-by: Robin Townsend --- src/components/views/context_menus/MessageContextMenu.js | 1 + src/components/views/dialogs/ForwardDialog.tsx | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/components/views/context_menus/MessageContextMenu.js b/src/components/views/context_menus/MessageContextMenu.js index fc2c366b07..002542bf88 100644 --- a/src/components/views/context_menus/MessageContextMenu.js +++ b/src/components/views/context_menus/MessageContextMenu.js @@ -158,6 +158,7 @@ export default class MessageContextMenu extends React.Component { Modal.createTrackedDialog('Forward Message', '', ForwardDialog, { cli: MatrixClientPeg.get(), event: this.props.mxEvent, + permalinkCreator: this.props.permalinkCreator, }, 'mx_Dialog_forwardmessage'); this.closeMenu(); }; diff --git a/src/components/views/dialogs/ForwardDialog.tsx b/src/components/views/dialogs/ForwardDialog.tsx index b1f558dfef..5cb5d68745 100644 --- a/src/components/views/dialogs/ForwardDialog.tsx +++ b/src/components/views/dialogs/ForwardDialog.tsx @@ -33,6 +33,7 @@ import RoomAvatar from "../avatars/RoomAvatar"; import AccessibleButton from "../elements/AccessibleButton"; import AutoHideScrollbar from "../../structures/AutoHideScrollbar"; import DMRoomMap from "../../../utils/DMRoomMap"; +import {RoomPermalinkCreator} from "../../../utils/permalinks/Permalinks"; import {sortRooms} from "../../../stores/room-list/algorithms/tag-sorting/RecentAlgorithm"; const AVATAR_SIZE = 30; @@ -41,6 +42,9 @@ interface IProps extends IDialogProps { cli: MatrixClient; // The event to forward event: MatrixEvent; + // We need a permalink creator for the source room to pass through to EventTile + // in case the event is a reply (even though the user can't get at the link) + permalinkCreator: RoomPermalinkCreator; } interface IEntryProps { @@ -97,7 +101,7 @@ const Entry: React.FC = ({ room, send }) => {
    ; }; -const ForwardDialog: React.FC = ({ cli, event, onFinished }) => { +const ForwardDialog: React.FC = ({ cli, event, permalinkCreator, onFinished }) => { const userId = cli.getUserId(); const [profileInfo, setProfileInfo] = useState({}); useEffect(() => { @@ -113,7 +117,7 @@ const ForwardDialog: React.FC = ({ cli, event, onFinished }) => { age: 97, }, event_id: "$9999999999999999999999999999999999999999999", - room_id: "!999999999999999999:example.org", + room_id: event.getRoomId(), }); mockEvent.sender = { name: profileInfo.displayname || userId, @@ -165,6 +169,7 @@ const ForwardDialog: React.FC = ({ cli, event, onFinished }) => { mxEvent={mockEvent} layout={previewLayout} enableFlair={SettingsStore.getValue(UIFeature.Flair)} + permalinkCreator={permalinkCreator} />
    From eb07f1fb86de32944b8a0375beec89abdeef63d0 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Mon, 10 May 2021 00:54:00 -0400 Subject: [PATCH 0318/1449] Test that ForwardDialog can render replies Previously ForwardDialog was not giving its EventTile message preview the information it needed to render a ReplyThread. This was a bit tricky to fix since we were pulling a fake event out of thin air, so this ensures it doesn't regress. Signed-off-by: Robin Townsend --- .../views/dialogs/ForwardDialog-test.js | 64 ++++++++++++++----- test/test-utils.js | 1 + 2 files changed, 49 insertions(+), 16 deletions(-) diff --git a/test/components/views/dialogs/ForwardDialog-test.js b/test/components/views/dialogs/ForwardDialog-test.js index cabcbb0325..af325ab8f0 100644 --- a/test/components/views/dialogs/ForwardDialog-test.js +++ b/test/components/views/dialogs/ForwardDialog-test.js @@ -24,44 +24,51 @@ import {act} from "react-dom/test-utils"; import * as TestUtils from "../../../test-utils"; import {MatrixClientPeg} from "../../../../src/MatrixClientPeg"; import DMRoomMap from "../../../../src/utils/DMRoomMap"; +import {RoomPermalinkCreator} from "../../../../src/utils/permalinks/Permalinks"; import ForwardDialog from "../../../../src/components/views/dialogs/ForwardDialog"; configure({ adapter: new Adapter() }); describe("ForwardDialog", () => { - let client; - let wrapper; - - const message = TestUtils.mkMessage({ - room: "!111111111111111111:example.org", + const sourceRoom = "!111111111111111111:example.org"; + const defaultMessage = TestUtils.mkMessage({ + room: sourceRoom, user: "@alice:example.org", msg: "Hello world!", event: true, }); + const defaultRooms = ["a", "A", "b"].map(name => TestUtils.mkStubRoom(name, name)); - beforeEach(async () => { - TestUtils.stubClient(); - DMRoomMap.makeShared(); - client = MatrixClientPeg.get(); - client.getVisibleRooms = jest.fn().mockReturnValue( - ["a", "A", "b"].map(name => TestUtils.mkStubRoom(name, name)), - ); - client.getUserId = jest.fn().mockReturnValue("@bob:example.org"); + const mountForwardDialog = async (message = defaultMessage, rooms = defaultRooms) => { + const client = MatrixClientPeg.get(); + client.getVisibleRooms = jest.fn().mockReturnValue(rooms); + let wrapper; await act(async () => { wrapper = mount( , ); // Wait one tick for our profile data to load so the state update happens within act await new Promise(resolve => setImmediate(resolve)); }); + + return wrapper; + }; + + beforeEach(() => { + TestUtils.stubClient(); + DMRoomMap.makeShared(); + MatrixClientPeg.get().getUserId = jest.fn().mockReturnValue("@bob:example.org"); }); - it("shows a preview with us as the sender", () => { + it("shows a preview with us as the sender", async () => { + const wrapper = await mountForwardDialog(); + const previewBody = wrapper.find(".mx_EventTile_body"); expect(previewBody.text()).toBe("Hello world!"); @@ -70,7 +77,9 @@ describe("ForwardDialog", () => { expect(previewAvatar.prop("title")).toBe("@bob:example.org"); }); - it("filters the rooms", () => { + it("filters the rooms", async () => { + const wrapper = await mountForwardDialog(); + const roomsBefore = wrapper.find(".mx_ForwardList_entry"); expect(roomsBefore).toHaveLength(3); @@ -83,10 +92,12 @@ describe("ForwardDialog", () => { }); it("tracks message sending progress across multiple rooms", async () => { + const wrapper = await mountForwardDialog(); + // Make sendEvent require manual resolution so we can see the sending state let finishSend; let cancelSend; - client.sendEvent = jest.fn(() => new Promise((resolve, reject) => { + MatrixClientPeg.get().sendEvent = jest.fn(() => new Promise((resolve, reject) => { finishSend = resolve; cancelSend = reject; })); @@ -121,4 +132,25 @@ describe("ForwardDialog", () => { }); expect(secondRoom.find(".mx_AccessibleButton").text()).toBe("Sent"); }); + + it("can render replies", async () => { + const replyMessage = TestUtils.mkEvent({ + type: "m.room.message", + room: "!111111111111111111:example.org", + user: "@alice:example.org", + content: { + msgtype: "m.text", + body: "> <@bob:example.org> Hi Alice!\n\nHi Bob!", + "m.relates_to": { + "m.in_reply_to": { + event_id: "$2222222222222222222222222222222222222222222", + }, + }, + }, + event: true, + }); + + const wrapper = await mountForwardDialog(replyMessage); + expect(wrapper.find("ReplyThread")).toBeTruthy(); + }); }); diff --git a/test/test-utils.js b/test/test-utils.js index 985e9f804b..8c9c62844a 100644 --- a/test/test-utils.js +++ b/test/test-utils.js @@ -236,6 +236,7 @@ export function mkStubRoom(roomId = null, name) { getPendingEvents: () => [], getLiveTimeline: () => stubTimeline, getUnfilteredTimelineSet: () => null, + findEventById: () => null, getAccountData: () => null, hasMembershipState: () => null, getVersion: () => '1', From 35cf0e1c7efbd4f627e8fcc00cd8f8b96daf1b8e Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Mon, 10 May 2021 01:02:12 -0400 Subject: [PATCH 0319/1449] Find components by name rather than class in ForwardDialog test It makes things shorter and more readable! Signed-off-by: Robin Townsend --- .../views/dialogs/ForwardDialog-test.js | 32 ++++++++----------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/test/components/views/dialogs/ForwardDialog-test.js b/test/components/views/dialogs/ForwardDialog-test.js index af325ab8f0..f181157d09 100644 --- a/test/components/views/dialogs/ForwardDialog-test.js +++ b/test/components/views/dialogs/ForwardDialog-test.js @@ -80,15 +80,13 @@ describe("ForwardDialog", () => { it("filters the rooms", async () => { const wrapper = await mountForwardDialog(); - const roomsBefore = wrapper.find(".mx_ForwardList_entry"); - expect(roomsBefore).toHaveLength(3); + expect(wrapper.find("Entry")).toHaveLength(3); - const searchInput = wrapper.find(".mx_SearchBox input"); + const searchInput = wrapper.find("SearchBox input"); searchInput.instance().value = "a"; searchInput.simulate("change"); - const roomsAfter = wrapper.find(".mx_ForwardList_entry"); - expect(roomsAfter).toHaveLength(2); + expect(wrapper.find("Entry")).toHaveLength(2); }); it("tracks message sending progress across multiple rooms", async () => { @@ -102,35 +100,31 @@ describe("ForwardDialog", () => { cancelSend = reject; })); - const firstRoom = wrapper.find(".mx_ForwardList_entry").first(); - expect(firstRoom.find(".mx_AccessibleButton").text()).toBe("Send"); + const firstButton = wrapper.find("Entry AccessibleButton").first(); + expect(firstButton.text()).toBe("Send"); - act(() => { - firstRoom.find(".mx_AccessibleButton").simulate("click"); - }); - expect(firstRoom.find(".mx_AccessibleButton").text()).toBe("Sending…"); + act(() => { firstButton.simulate("click"); }); + expect(firstButton.text()).toBe("Sending…"); await act(async () => { cancelSend(); // Wait one tick for the button to realize the send failed await new Promise(resolve => setImmediate(resolve)); }); - expect(firstRoom.find(".mx_AccessibleButton").text()).toBe("Failed to send"); + expect(firstButton.text()).toBe("Failed to send"); - const secondRoom = wrapper.find(".mx_ForwardList_entry").at(1); - expect(secondRoom.find(".mx_AccessibleButton").text()).toBe("Send"); + const secondButton = wrapper.find("Entry AccessibleButton").at(1); + expect(secondButton.text()).toBe("Send"); - act(() => { - secondRoom.find(".mx_AccessibleButton").simulate("click"); - }); - expect(secondRoom.find(".mx_AccessibleButton").text()).toBe("Sending…"); + act(() => { secondButton.simulate("click"); }); + expect(secondButton.text()).toBe("Sending…"); await act(async () => { finishSend(); // Wait one tick for the button to realize the send succeeded await new Promise(resolve => setImmediate(resolve)); }); - expect(secondRoom.find(".mx_AccessibleButton").text()).toBe("Sent"); + expect(secondButton.text()).toBe("Sent"); }); it("can render replies", async () => { From 09ba74a8514fd907e758f1af24c795fa78ce8643 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Mon, 10 May 2021 01:04:25 -0400 Subject: [PATCH 0320/1449] Disable forward buttons for rooms without send permissions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …and add a tooltip to explain why they can't accept forwarded messages. It was chosen to disable the buttons rather than hide the entries from the list, since hiding them without explanation could cause confusion. Signed-off-by: Robin Townsend --- .../views/dialogs/ForwardDialog.tsx | 76 ++++++++++++------- 1 file changed, 47 insertions(+), 29 deletions(-) diff --git a/src/components/views/dialogs/ForwardDialog.tsx b/src/components/views/dialogs/ForwardDialog.tsx index 5cb5d68745..fd10a88d93 100644 --- a/src/components/views/dialogs/ForwardDialog.tsx +++ b/src/components/views/dialogs/ForwardDialog.tsx @@ -31,6 +31,7 @@ import EventTile from "../rooms/EventTile"; import SearchBox from "../../structures/SearchBox"; import RoomAvatar from "../avatars/RoomAvatar"; import AccessibleButton from "../elements/AccessibleButton"; +import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; import AutoHideScrollbar from "../../structures/AutoHideScrollbar"; import DMRoomMap from "../../../utils/DMRoomMap"; import {RoomPermalinkCreator} from "../../../utils/permalinks/Permalinks"; @@ -63,41 +64,58 @@ enum SendState { const Entry: React.FC = ({ room, send }) => { const [sendState, setSendState] = useState(SendState.CanSend); - let label; - let className; - if (sendState === SendState.CanSend) { - label = _t("Send"); - className = "mx_ForwardList_canSend"; - } else if (sendState === SendState.Sending) { - label = _t("Sending…"); - className = "mx_ForwardList_sending"; - } else if (sendState === SendState.Sent) { - label = _t("Sent"); - className = "mx_ForwardList_sent"; + let button; + if (room.maySendMessage()) { + let label; + let className; + if (sendState === SendState.CanSend) { + label = _t("Send"); + className = "mx_ForwardList_canSend"; + } else if (sendState === SendState.Sending) { + label = _t("Sending…"); + className = "mx_ForwardList_sending"; + } else if (sendState === SendState.Sent) { + label = _t("Sent"); + className = "mx_ForwardList_sent"; + } else { + label = _t("Failed to send"); + className = "mx_ForwardList_sendFailed"; + } + + button = + { + setSendState(SendState.Sending); + try { + await send(); + setSendState(SendState.Sent); + } catch (e) { + setSendState(SendState.Failed); + } + }} + disabled={sendState !== SendState.CanSend} + > + { label } + ; } else { - label = _t("Failed to send"); - className = "mx_ForwardList_sendFailed"; + button = + {}} + disabled={true} + title={_t("You do not have permission to post to this room")} + > + { _t("Send") } + ; } return
    { room.name } - { - setSendState(SendState.Sending); - try { - await send(); - setSendState(SendState.Sent); - } catch (e) { - setSendState(SendState.Failed); - } - }} - disabled={sendState !== SendState.CanSend} - > - { label } - + { button }
    ; }; From eb779cd3d8db279e9cf91134b1aa5bbf4326662c Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Mon, 10 May 2021 01:07:42 -0400 Subject: [PATCH 0321/1449] Test that forward buttons are disabled for rooms without permission Signed-off-by: Robin Townsend --- test/components/views/dialogs/ForwardDialog-test.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/components/views/dialogs/ForwardDialog-test.js b/test/components/views/dialogs/ForwardDialog-test.js index f181157d09..706d47acdc 100644 --- a/test/components/views/dialogs/ForwardDialog-test.js +++ b/test/components/views/dialogs/ForwardDialog-test.js @@ -147,4 +147,17 @@ describe("ForwardDialog", () => { const wrapper = await mountForwardDialog(replyMessage); expect(wrapper.find("ReplyThread")).toBeTruthy(); }); + + it("disables buttons for rooms without send permissions", async () => { + const readOnlyRoom = TestUtils.mkStubRoom("a", "a"); + readOnlyRoom.maySendMessage = jest.fn().mockReturnValue(false); + const rooms = [readOnlyRoom, TestUtils.mkStubRoom("b", "b")]; + + const wrapper = await mountForwardDialog(undefined, rooms); + + const firstButton = wrapper.find("Entry AccessibleButton").first(); + expect(firstButton.prop("disabled")).toBe(true); + const secondButton = wrapper.find("Entry AccessibleButton").last(); + expect(secondButton.prop("disabled")).toBe(false); + }); }); From 5c10e1e5744e7c8b753304e4994c172f4ba493c3 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Mon, 10 May 2021 01:16:37 -0400 Subject: [PATCH 0322/1449] Fix lints Signed-off-by: Robin Townsend --- test/components/views/dialogs/ForwardDialog-test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/components/views/dialogs/ForwardDialog-test.js b/test/components/views/dialogs/ForwardDialog-test.js index 706d47acdc..2f062a84cc 100644 --- a/test/components/views/dialogs/ForwardDialog-test.js +++ b/test/components/views/dialogs/ForwardDialog-test.js @@ -133,8 +133,8 @@ describe("ForwardDialog", () => { room: "!111111111111111111:example.org", user: "@alice:example.org", content: { - msgtype: "m.text", - body: "> <@bob:example.org> Hi Alice!\n\nHi Bob!", + "msgtype": "m.text", + "body": "> <@bob:example.org> Hi Alice!\n\nHi Bob!", "m.relates_to": { "m.in_reply_to": { event_id: "$2222222222222222222222222222222222222222222", From 9a5a3b30ca004516c28dd713d2587942215a0bbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 6 May 2021 16:40:33 +0200 Subject: [PATCH 0323/1449] Don't try to use the event's metadata to calc the scale MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit That has lead to https://github.com/vector-im/element-web/issues/17184 Signed-off-by: Šimon Brandner --- src/components/views/elements/ImageView.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/components/views/elements/ImageView.tsx b/src/components/views/elements/ImageView.tsx index fcacae2d39..e4cc0b6973 100644 --- a/src/components/views/elements/ImageView.tsx +++ b/src/components/views/elements/ImageView.tsx @@ -108,8 +108,6 @@ export default class ImageView extends React.Component { window.addEventListener("resize", this.calculateZoom); // After the image loads for the first time we want to calculate the zoom this.image.current.addEventListener("load", this.calculateZoom); - // Try to precalculate the zoom from width and height props - this.calculateZoom(); } componentWillUnmount() { @@ -120,8 +118,8 @@ export default class ImageView extends React.Component { const image = this.image.current; const imageWrapper = this.imageWrapper.current; - const width = this.props.width || image.naturalWidth; - const height = this.props.height || image.naturalHeight; + const width = image.naturalWidth; + const height = image.naturalHeight; const zoomX = imageWrapper.clientWidth / width; const zoomY = imageWrapper.clientHeight / height; From 3b97e522468e08dd805d1be6565e0faee2482de7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 6 May 2021 16:41:09 +0200 Subject: [PATCH 0324/1449] Simplifie code a bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/elements/ImageView.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/components/views/elements/ImageView.tsx b/src/components/views/elements/ImageView.tsx index e4cc0b6973..e65fe2cc14 100644 --- a/src/components/views/elements/ImageView.tsx +++ b/src/components/views/elements/ImageView.tsx @@ -118,11 +118,8 @@ export default class ImageView extends React.Component { const image = this.image.current; const imageWrapper = this.imageWrapper.current; - const width = image.naturalWidth; - const height = image.naturalHeight; - - const zoomX = imageWrapper.clientWidth / width; - const zoomY = imageWrapper.clientHeight / height; + const zoomX = imageWrapper.clientWidth / image.naturalWidth; + const zoomY = imageWrapper.clientHeight / image.naturalHeight; // If the image is smaller in both dimensions set its the zoom to 1 to // display it in its original size From 3a75eb12265ac83b9d88549b1b7f593905e5912d Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 10 May 2021 14:39:10 +0100 Subject: [PATCH 0325/1449] Fix handling of enter/return in space creation menu --- .../views/spaces/SpaceBasicSettings.tsx | 50 ++++++++------- .../views/spaces/SpaceCreateMenu.tsx | 61 ++++++++++++++++--- src/i18n/strings/en_EN.json | 1 + 3 files changed, 83 insertions(+), 29 deletions(-) diff --git a/src/components/views/spaces/SpaceBasicSettings.tsx b/src/components/views/spaces/SpaceBasicSettings.tsx index bc378ab956..ec40f7bed8 100644 --- a/src/components/views/spaces/SpaceBasicSettings.tsx +++ b/src/components/views/spaces/SpaceBasicSettings.tsx @@ -32,17 +32,11 @@ interface IProps { setTopic(topic: string): void; } -const SpaceBasicSettings = ({ +export const SpaceAvatar = ({ avatarUrl, avatarDisabled = false, setAvatar, - name = "", - nameDisabled = false, - setName, - topic = "", - topicDisabled = false, - setTopic, -}: IProps) => { +}: Pick) => { const avatarUploadRef = useRef(); const [avatar, setAvatarDataUrl] = useState(avatarUrl); // avatar data url cache @@ -81,20 +75,34 @@ const SpaceBasicSettings = ({ } } + return
    + { avatarSection } + { + if (!e.target.files?.length) return; + const file = e.target.files[0]; + setAvatar(file); + const reader = new FileReader(); + reader.onload = (ev) => { + setAvatarDataUrl(ev.target.result as string); + }; + reader.readAsDataURL(file); + }} accept="image/*" /> +
    ; +}; + +const SpaceBasicSettings = ({ + avatarUrl, + avatarDisabled = false, + setAvatar, + name = "", + nameDisabled = false, + setName, + topic = "", + topicDisabled = false, + setTopic, +}: IProps) => { return
    -
    - { avatarSection } - { - if (!e.target.files?.length) return; - const file = e.target.files[0]; - setAvatar(file); - const reader = new FileReader(); - reader.onload = (ev) => { - setAvatarDataUrl(ev.target.result as string); - }; - reader.readAsDataURL(file); - }} accept="image/*" /> -
    + { return ( @@ -41,17 +43,39 @@ enum Visibility { Private, } +const spaceNameValidator = withValidation({ + rules: [ + { + key: "required", + test: async ({ value }) => !!value, + invalid: () => _t("Please enter a name for the space"), + }, + ], +}); + const SpaceCreateMenu = ({ onFinished }) => { const cli = useContext(MatrixClientContext); const [visibility, setVisibility] = useState(null); - const [name, setName] = useState(""); - const [avatar, setAvatar] = useState(null); - const [topic, setTopic] = useState(""); const [busy, setBusy] = useState(false); - const onSpaceCreateClick = async () => { + const [name, setName] = useState(""); + const spaceNameField = useRef(); + const [avatar, setAvatar] = useState(null); + const [topic, setTopic] = useState(""); + + const onSpaceCreateClick = async (e) => { + e.preventDefault(); if (busy) return; + setBusy(true); + // require & validate the space name field + if (!await spaceNameField.current.validate({ allowEmpty: false })) { + spaceNameField.current.focus(); + spaceNameField.current.validate({ allowEmpty: false, focused: true }); + setBusy(false); + return; + } + const initialState: IStateEvent[] = [ { type: EventType.RoomHistoryVisibility, @@ -146,9 +170,30 @@ const SpaceCreateMenu = ({ onFinished }) => { }

    - + + - + setName(ev.target.value)} + ref={spaceNameField} + onValidate={spaceNameValidator} + /> + + setTopic(ev.target.value)} + rows={3} + /> + + + { busy ? _t("Creating...") : _t("Create") } ; diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index dcad970300..26275c4325 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -996,6 +996,7 @@ "Upload": "Upload", "Name": "Name", "Description": "Description", + "Please enter a name for the space": "Please enter a name for the space", "Create a space": "Create a space", "Spaces are new ways to group rooms and people. To join an existing space you'll need an invite.": "Spaces are new ways to group rooms and people. To join an existing space you'll need an invite.", "Public": "Public", From a11c3a22c9cc0f29fed396cec1478323c841cf73 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Mon, 10 May 2021 14:55:31 +0100 Subject: [PATCH 0326/1449] Upgrade matrix-js-sdk to 10.1.0 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index f6471327cb..6c798d05f4 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ "katex": "^0.12.0", "linkifyjs": "^2.1.9", "lodash": "^4.17.20", - "matrix-js-sdk": "10.1.0-rc.1", + "matrix-js-sdk": "10.1.0", "matrix-widget-api": "^0.1.0-beta.13", "minimist": "^1.2.5", "opus-recorder": "^8.0.3", diff --git a/yarn.lock b/yarn.lock index c1e04a0686..b11fcb0d72 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5671,10 +5671,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@10.1.0-rc.1: - version "10.1.0-rc.1" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-10.1.0-rc.1.tgz#67b04cd30cb3b3c8ee7a3a2ead1db567a99e35c8" - integrity sha512-jpCnSqvNAsVIHv/FRVx1xV11IKcQCd6zUy4cHLDfUH/6GxFDtW/Fk446A7XDIJnNvstqmWBghk4X65hdsfq5OQ== +matrix-js-sdk@10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-10.1.0.tgz#11a78e0330530f78498847c52d390d2a599b029b" + integrity sha512-VR1bwSKOf7jZa9+0UoAsYvyvLsNGBhT/BdxHMgQKuwx34GwZucp3Tqg/Ng2oTK+0b991xkEk4nRvJoCKK++Ulg== dependencies: "@babel/runtime" "^7.12.5" another-json "^0.2.0" From 7f4c525d62be2efe1fe4ef5b964d1588c5e51c04 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Mon, 10 May 2021 14:57:35 +0100 Subject: [PATCH 0327/1449] Switch back to release version of `sanitize-html` The limit depth option has been available in a released version for a while now. --- package.json | 2 +- yarn.lock | 21 +++++++++++---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index be195e2e9e..d31a6eb284 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,7 @@ "react-transition-group": "^4.4.1", "resize-observer-polyfill": "^1.5.1", "rfc4648": "^1.4.0", - "sanitize-html": "github:apostrophecms/sanitize-html#3c7f93f2058f696f5359e3e58d464161647226db", + "sanitize-html": "^2.3.2", "tar-js": "^0.3.0", "text-encoding-utf-8": "^1.0.2", "url": "^0.11.0", diff --git a/yarn.lock b/yarn.lock index 297d3d8e9d..c47ed5476c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6307,6 +6307,11 @@ parse-json@^5.0.0: json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" +parse-srcset@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/parse-srcset/-/parse-srcset-1.0.2.tgz#f2bd221f6cc970a938d88556abc589caaaa2bde1" + integrity sha1-8r0iH2zJcKk42IVWq8WJyqqiveE= + parse5-htmlparser2-tree-adapter@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz#2cdf9ad823321140370d4dbf5d3e92c7c8ddc6e6" @@ -7248,17 +7253,18 @@ sane@^4.0.3: minimist "^1.1.1" walker "~1.0.5" -"sanitize-html@github:apostrophecms/sanitize-html#3c7f93f2058f696f5359e3e58d464161647226db": - version "2.0.0-rc.3" - resolved "https://codeload.github.com/apostrophecms/sanitize-html/tar.gz/3c7f93f2058f696f5359e3e58d464161647226db" +sanitize-html@^2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-2.3.3.tgz#3db382c9a621cce4c46d90f10c64f1e9da9e8353" + integrity sha512-DCFXPt7Di0c6JUnlT90eIgrjs6TsJl/8HYU3KLdmrVclFN4O0heTcVbJiMa23OKVr6aR051XYtsgd8EWwEBwUA== dependencies: deepmerge "^4.2.2" escape-string-regexp "^4.0.0" - htmlparser2 "^4.1.0" + htmlparser2 "^6.0.0" is-plain-object "^5.0.0" klona "^2.0.3" + parse-srcset "^1.0.2" postcss "^8.0.2" - srcset "^3.0.0" saxes@^5.0.0: version "5.0.1" @@ -7515,11 +7521,6 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= -srcset@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/srcset/-/srcset-3.0.0.tgz#8afd8b971362dfc129ae9c1a99b3897301ce6441" - integrity sha512-D59vF08Qzu/C4GAOXVgMTLfgryt5fyWo93FZyhEWANo0PokFz/iWdDe13mX3O5TRf6l8vMTqckAfR4zPiaH0yQ== - sshpk@^1.7.0: version "1.16.1" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" From a1572e9ea3e7fb0099a0dd8cebfc86de5ad77328 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Mon, 10 May 2021 15:02:07 +0100 Subject: [PATCH 0328/1449] Prepare changelog for v3.20.0 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc6c0b7f76..58d23e3413 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +Changes in [3.20.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.20.0) (2021-05-10) +===================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v3.20.0-rc.1...v3.20.0) + + * Upgrade to JS SDK 10.1.0 + * [Release] Don't use the event's metadata to calc the scale of an image + [\#6004](https://github.com/matrix-org/matrix-react-sdk/pull/6004) + Changes in [3.20.0-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.20.0-rc.1) (2021-05-04) =============================================================================================================== [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v3.19.0...v3.20.0-rc.1) From f68013524cf3dbd99068486214a78e9afdce0406 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Mon, 10 May 2021 15:02:08 +0100 Subject: [PATCH 0329/1449] v3.20.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6c798d05f4..e8fac14290 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "3.20.0-rc.1", + "version": "3.20.0", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From d0d2907a07782e1596171bee24b82ae609056efa Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Mon, 10 May 2021 15:19:46 +0100 Subject: [PATCH 0330/1449] Decrypt events ahead of storing them in the index --- src/indexing/EventIndex.js | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/src/indexing/EventIndex.js b/src/indexing/EventIndex.js index 1cb44f240d..e27687e784 100644 --- a/src/indexing/EventIndex.js +++ b/src/indexing/EventIndex.js @@ -38,7 +38,6 @@ export default class EventIndex extends EventEmitter { this._eventsPerCrawl = 100; this._crawler = null; this._currentCheckpoint = null; - this.liveEventsForIndex = new Set(); } async init() { @@ -188,16 +187,11 @@ export default class EventIndex extends EventEmitter { return; } - // If the event is not yet decrypted mark it for the - // Event.decrypted callback. if (ev.isBeingDecrypted()) { - const eventId = ev.getId(); - this.liveEventsForIndex.add(eventId); - } else { - // If the event is decrypted or is unencrypted add it to the - // index now. - await this.addLiveEventToIndex(ev); + await ev._decryptionPromise; } + + await this.addLiveEventToIndex(ev); } onRoomStateEvent = async (ev, state) => { @@ -219,7 +213,6 @@ export default class EventIndex extends EventEmitter { const eventId = ev.getId(); // If the event isn't in our live event set, ignore it. - if (!this.liveEventsForIndex.delete(eventId)) return; if (err) return; await this.addLiveEventToIndex(ev); } @@ -523,18 +516,18 @@ export default class EventIndex extends EventEmitter { } }); - const decryptionPromises = []; - - matrixEvents.forEach(ev => { - if (ev.isBeingDecrypted() || ev.isDecryptionFailure()) { - // TODO the decryption promise is a private property, this - // should either be made public or we should convert the - // event that gets fired when decryption is done into a - // promise using the once event emitter method: - // https://nodejs.org/api/events.html#events_events_once_emitter_name - decryptionPromises.push(ev._decryptionPromise); - } - }); + const decryptionPromises = matrixEvents + .filter(event => event.isEncrypted()) + .map(event => { + if (event.shouldAttemptDecryption()) { + return event.attemptDecryption(client._crypto, { + isRetry: true, + emit: false, + }); + } else { + return event._decryptionPromise; + } + }); // Let us wait for all the events to get decrypted. await Promise.all(decryptionPromises); From 82642f17fd8e36a81944c9a8a4a14addce80c02d Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Mon, 10 May 2021 15:22:30 +0100 Subject: [PATCH 0331/1449] Resetting package fields for development --- package.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index cb9a8aa887..172681dff3 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "bin": { "reskindex": "scripts/reskindex.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", @@ -197,6 +197,5 @@ "coverageReporters": [ "text" ] - }, - "typings": "./lib/index.d.ts" + } } From 1b372b17e039db98a9dba34ba90e25e5433b1aec Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Mon, 10 May 2021 15:23:03 +0100 Subject: [PATCH 0332/1449] 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 172681dff3..342591081f 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ "katex": "^0.12.0", "linkifyjs": "^2.1.9", "lodash": "^4.17.20", - "matrix-js-sdk": "10.1.0", + "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop", "matrix-widget-api": "^0.1.0-beta.13", "minimist": "^1.2.5", "opus-recorder": "^8.0.3", diff --git a/yarn.lock b/yarn.lock index c5477c30b0..0d9b2bdd3f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5676,10 +5676,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@10.1.0: +"matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop": version "10.1.0" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-10.1.0.tgz#11a78e0330530f78498847c52d390d2a599b029b" - integrity sha512-VR1bwSKOf7jZa9+0UoAsYvyvLsNGBhT/BdxHMgQKuwx34GwZucp3Tqg/Ng2oTK+0b991xkEk4nRvJoCKK++Ulg== + resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/2d73805ca3d8c5a140fe05e574f826696de1656a" dependencies: "@babel/runtime" "^7.12.5" another-json "^0.2.0" From f1a6f6fd7f015531d7ae3b03c001e2f18de596d6 Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Mon, 10 May 2021 15:36:59 +0100 Subject: [PATCH 0333/1449] make breadcrumb room events decryption more idiomatic --- src/components/structures/TimelinePanel.js | 1 - src/stores/BreadcrumbsStore.ts | 44 +++++++++++++--------- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index 63a52f7807..a3c1c56276 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -1142,7 +1142,6 @@ class TimelinePanel extends React.Component { _getEvents() { const events = this._timelineWindow.getEvents(); - // `slice` performs a shallow copy of the array // we want the last event to be decrypted first but displayed last // `reverse` is destructive and unfortunately mutates the "events" array diff --git a/src/stores/BreadcrumbsStore.ts b/src/stores/BreadcrumbsStore.ts index 5c49fef148..28f3151434 100644 --- a/src/stores/BreadcrumbsStore.ts +++ b/src/stores/BreadcrumbsStore.ts @@ -60,6 +60,33 @@ export class BreadcrumbsStore extends AsyncStoreWithClient { return this.matrixClient && this.matrixClient.getVisibleRooms().length >= 20; } + componentDidUpdate(prevProps, prevState) { + const prevRoomCount = (prevState.rooms?.length || 0); + const currentRoomCount = (this.state.rooms?.length || 0) + + /** + * Only decrypting the breadcrumb rooms events on app initialisation + * when room count transitions from 0 to the number of rooms it contains + */ + if (prevRoomCount === 0 && currentRoomCount > prevRoomCount) { + const client = MatrixClientPeg.get(); + /** + * Rooms in the breadcrumb have a good chance to be interacted with + * again by a user. Decrypting the messages ahead of time will help + * reduce content shift on first render + */ + this.state.rooms?.forEach(async room => { + const [cryptoEvent] = room.currentState.getStateEvents("m.room.encryption"); + if (cryptoEvent) { + if (!client.isRoomEncrypted(room.roomId)) { + await client._crypto.onCryptoEvent(cryptoEvent); + } + room?.decryptAllEvents(); + } + }); + } + } + protected async onAction(payload: ActionPayload) { if (!this.matrixClient) return; @@ -88,23 +115,6 @@ export class BreadcrumbsStore extends AsyncStoreWithClient { this.matrixClient.on("Room.myMembership", this.onMyMembership); this.matrixClient.on("Room", this.onRoom); - - const client = MatrixClientPeg.get(); - const breadcrumbs = client.store.getAccountData("im.vector.setting.breadcrumbs"); - const breadcrumbsRooms: string[] = breadcrumbs?.getContent().recent_rooms || []; - - breadcrumbsRooms.map(async roomId => { - const room = client.getRoom(roomId); - if (room) { - const [cryptoEvent] = room.currentState.getStateEvents("m.room.encryption"); - if (cryptoEvent) { - if (!client.isRoomEncrypted(roomId)) { - await client._crypto.onCryptoEvent(cryptoEvent); - } - return room?.decryptAllEvents(); - } - } - }); } protected async onNotReady() { From c96bb374ea6f8a3778f195d6a2e47d6b7eb62993 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 10 May 2021 16:06:23 +0100 Subject: [PATCH 0334/1449] Allow user to progress through space setup wizard using Enter/Return --- src/components/structures/SpaceRoomView.tsx | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx index 5db54815b7..6566ccf939 100644 --- a/src/components/structures/SpaceRoomView.tsx +++ b/src/components/structures/SpaceRoomView.tsx @@ -60,6 +60,7 @@ import IconizedContextMenu, { IconizedContextMenuOptionList, } from "../views/context_menus/IconizedContextMenu"; import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton"; +import {Key} from "../../Keyboard"; interface IProps { space: Room; @@ -367,6 +368,7 @@ const SpaceLanding = ({ space }) => { const SpaceSetupFirstRooms = ({ space, title, description, onFinished }) => { const [busy, setBusy] = useState(false); const [error, setError] = useState(""); + let onClick = onFinished; const numFields = 3; const placeholders = [_t("General"), _t("Random"), _t("Support")]; // TODO vary default prefills for "Just Me" spaces @@ -382,10 +384,17 @@ const SpaceSetupFirstRooms = ({ space, title, description, onFinished }) => { value={roomNames[i]} onChange={ev => setRoomName(i, ev.target.value)} autoFocus={i === 2} + onKeyDown={ev => { + if (ev.key === Key.ENTER) { + ev.preventDefault(); + onClick(); + } + }} />; }); const onNextClick = async () => { + if (busy) return; setError(""); setBusy(true); try { @@ -410,7 +419,6 @@ const SpaceSetupFirstRooms = ({ space, title, description, onFinished }) => { setBusy(false); }; - let onClick = onFinished; let buttonLabel = _t("Skip for now"); if (roomNames.some(name => name.trim())) { onClick = onNextClick; @@ -556,6 +564,7 @@ const validateEmailRules = withValidation({ const SpaceSetupPrivateInvite = ({ space, onFinished }) => { const [busy, setBusy] = useState(false); const [error, setError] = useState(""); + let onClick = onFinished; const numFields = 3; const fieldRefs: RefObject[] = [useRef(), useRef(), useRef()]; const [emailAddresses, setEmailAddress] = useStateArray(numFields, ""); @@ -572,10 +581,17 @@ const SpaceSetupPrivateInvite = ({ space, onFinished }) => { ref={fieldRefs[i]} onValidate={validateEmailRules} autoFocus={i === 0} + onKeyDown={ev => { + if (ev.key === Key.ENTER) { + ev.preventDefault(); + onClick(); + } + }} />; }); const onNextClick = async () => { + if (busy) return; setError(""); for (let i = 0; i < fieldRefs.length; i++) { const fieldRef = fieldRefs[i]; @@ -609,7 +625,6 @@ const SpaceSetupPrivateInvite = ({ space, onFinished }) => { setBusy(false); }; - let onClick = onFinished; let buttonLabel = _t("Skip for now"); if (emailAddresses.some(name => name.trim())) { onClick = onNextClick; From f41fc7e46c5ab0cf7ad345a5267c6ce0f9801ccd Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Mon, 10 May 2021 16:09:12 +0100 Subject: [PATCH 0335/1449] Upgrade `cheerio` and resolve type errors This helps resolve some type errors with `domhandler`. In addition, we convert to the new way of using `htmlparser2` with `cheerio`. --- package.json | 3 +- src/HtmlUtils.tsx | 7 ++- src/editor/serialize.ts | 11 ++-- yarn.lock | 123 +++++++++++++++++++++++++--------------- 4 files changed, 92 insertions(+), 52 deletions(-) diff --git a/package.json b/package.json index 342591081f..a03f02871e 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "blueimp-canvas-to-blob": "^3.28.0", "browser-encrypt-attachment": "^0.3.0", "browser-request": "^0.3.3", - "cheerio": "^1.0.0-rc.5", + "cheerio": "^1.0.0-rc.9", "classnames": "^2.2.6", "commonmark": "^0.29.3", "counterpart": "^0.18.6", @@ -75,6 +75,7 @@ "glob-to-regexp": "^0.4.1", "highlight.js": "^10.5.0", "html-entities": "^1.4.0", + "htmlparser2": "^6.1.0", "is-ip": "^3.1.0", "katex": "^0.12.0", "linkifyjs": "^2.1.9", diff --git a/src/HtmlUtils.tsx b/src/HtmlUtils.tsx index 6b2568d68c..c781efd8c6 100644 --- a/src/HtmlUtils.tsx +++ b/src/HtmlUtils.tsx @@ -31,6 +31,7 @@ import katex from 'katex'; import { AllHtmlEntities } from 'html-entities'; import SettingsStore from './settings/SettingsStore'; import cheerio from 'cheerio'; +import htmlparser2 from 'htmlparser2'; import {tryTransformPermalinkToLocalHref} from "./utils/permalinks/Permalinks"; import {SHORTCODE_TO_EMOJI, getEmojiFromUnicode} from "./emoji"; @@ -422,8 +423,9 @@ export function bodyToHtml(content: IContent, highlights: string[], opts: IOpts safeBody = sanitizeHtml(formattedBody, sanitizeParams); if (SettingsStore.getValue("feature_latex_maths")) { - const phtml = cheerio.load(safeBody, - { _useHtmlParser2: true, decodeEntities: false }) + const phtml = cheerio.load(htmlparser2.parseDocument(safeBody, { + decodeEntities: false, + })); // @ts-ignore - The types for `replaceWith` wrongly expect // Cheerio instance to be returned. phtml('div, span[data-mx-maths!=""]').replaceWith(function(i, e) { @@ -431,6 +433,7 @@ export function bodyToHtml(content: IContent, highlights: string[], opts: IOpts AllHtmlEntities.decode(phtml(e).attr('data-mx-maths')), { throwOnError: false, + // @ts-ignore - `e` can be an Element, not just a Node displayMode: e.name == 'div', output: "htmlAndMathml", }); diff --git a/src/editor/serialize.ts b/src/editor/serialize.ts index 7cf9d9bb9d..d8005bc162 100644 --- a/src/editor/serialize.ts +++ b/src/editor/serialize.ts @@ -22,6 +22,7 @@ import { AllHtmlEntities } from 'html-entities'; import SettingsStore from '../settings/SettingsStore'; import SdkConfig from '../SdkConfig'; import cheerio from 'cheerio'; +import htmlparser2 from 'htmlparser2'; export function mdSerialize(model: EditorModel) { return model.parts.reduce((html, part) => { @@ -116,14 +117,16 @@ export function htmlSerializeIfNeeded(model: EditorModel, {forceHTML = false} = const parser = new Markdown(md); if (!parser.isPlainText() || forceHTML) { // feed Markdown output to HTML parser - const phtml = cheerio.load(parser.toHTML(), - { _useHtmlParser2: true, decodeEntities: false }); + const phtml = cheerio.load(htmlparser2.parseDocument(parser.toHTML(), { + decodeEntities: false, + })); if (SettingsStore.getValue("feature_latex_maths")) { // original Markdown without LaTeX replacements const parserOrig = new Markdown(orig); - const phtmlOrig = cheerio.load(parserOrig.toHTML(), - { _useHtmlParser2: true, decodeEntities: false }); + const phtmlOrig = cheerio.load(htmlparser2.parseDocument(parserOrig.toHTML(), { + decodeEntities: false, + })); // since maths delimiters are handled before Markdown, // code blocks could contain mangled content. diff --git a/yarn.lock b/yarn.lock index 0d9b2bdd3f..3dbc55e0b9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2401,29 +2401,29 @@ chardet@^0.7.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== -cheerio-select-tmp@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/cheerio-select-tmp/-/cheerio-select-tmp-0.1.1.tgz#55bbef02a4771710195ad736d5e346763ca4e646" - integrity sha512-YYs5JvbpU19VYJyj+F7oYrIE2BOll1/hRU7rEy/5+v9BzkSo3bK81iAeeQEMI92vRIxz677m72UmJUiVwwgjfQ== +cheerio-select@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-1.4.0.tgz#3a16f21e37a2ef0f211d6d1aa4eff054bb22cdc9" + integrity sha512-sobR3Yqz27L553Qa7cK6rtJlMDbiKPdNywtR95Sj/YgfpLfy0u6CGJuaBKe5YE/vTc23SCRKxWSdlon/w6I/Ew== dependencies: - css-select "^3.1.2" - css-what "^4.0.0" - domelementtype "^2.1.0" - domhandler "^4.0.0" - domutils "^2.4.4" + css-select "^4.1.2" + css-what "^5.0.0" + domelementtype "^2.2.0" + domhandler "^4.2.0" + domutils "^2.6.0" -cheerio@^1.0.0-rc.3, cheerio@^1.0.0-rc.5: - version "1.0.0-rc.5" - resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.5.tgz#88907e1828674e8f9fee375188b27dadd4f0fa2f" - integrity sha512-yoqps/VCaZgN4pfXtenwHROTp8NG6/Hlt4Jpz2FEP0ZJQ+ZUkVDd0hAPDNKhj3nakpfPt/CNs57yEtxD1bXQiw== +cheerio@^1.0.0-rc.3, cheerio@^1.0.0-rc.9: + version "1.0.0-rc.9" + resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.9.tgz#a3ae6b7ce7af80675302ff836f628e7cb786a67f" + integrity sha512-QF6XVdrLONO6DXRF5iaolY+odmhj2CLj+xzNod7INPWMi/x9X4SOylH0S/vaPpX+AUU6t04s34SQNh7DbkuCng== dependencies: - cheerio-select-tmp "^0.1.0" - dom-serializer "~1.2.0" - domhandler "^4.0.0" - entities "~2.1.0" - htmlparser2 "^6.0.0" - parse5 "^6.0.0" - parse5-htmlparser2-tree-adapter "^6.0.0" + cheerio-select "^1.4.0" + dom-serializer "^1.3.1" + domhandler "^4.2.0" + htmlparser2 "^6.1.0" + parse5 "^6.0.1" + parse5-htmlparser2-tree-adapter "^6.0.1" + tslib "^2.2.0" chokidar@^3.4.0, chokidar@^3.5.1: version "3.5.1" @@ -2705,21 +2705,21 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2: shebang-command "^2.0.0" which "^2.0.1" -css-select@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-3.1.2.tgz#d52cbdc6fee379fba97fb0d3925abbd18af2d9d8" - integrity sha512-qmss1EihSuBNWNNhHjxzxSfJoFBM/lERB/Q4EnsJQQC62R2evJDW481091oAdOr9uh46/0n4nrg0It5cAnj1RA== +css-select@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.1.2.tgz#8b52b6714ed3a80d8221ec971c543f3b12653286" + integrity sha512-nu5ye2Hg/4ISq4XqdLY2bEatAcLIdt3OYGFc9Tm9n7VSlFBcfRv0gBNksHRgSdUDQGtN3XrZ94ztW+NfzkFSUw== dependencies: boolbase "^1.0.0" - css-what "^4.0.0" - domhandler "^4.0.0" - domutils "^2.4.3" + css-what "^5.0.0" + domhandler "^4.2.0" + domutils "^2.6.0" nth-check "^2.0.0" -css-what@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-4.0.0.tgz#35e73761cab2eeb3d3661126b23d7aa0e8432233" - integrity sha512-teijzG7kwYfNVsUh2H/YN62xW3KK9YhXEgSlbxMlcyjPNvdKJqFx5lrwlJgoFP1ZHlB89iGDlo/JyshKeRhv5A== +css-what@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.0.0.tgz#f0bf4f8bac07582722346ab243f6a35b512cfc47" + integrity sha512-qxyKHQvgKwzwDWC/rGbT821eJalfupxYW2qbSJSAtdSTimsr/MlaGONoNLllaUPZWf8QnbcKM/kPVYUQuEKAFA== cssesc@^3.0.0: version "3.0.0" @@ -2940,7 +2940,7 @@ dom-serializer@0: domelementtype "^2.0.1" entities "^2.0.0" -dom-serializer@^1.0.1, dom-serializer@~1.2.0: +dom-serializer@^1.0.1: version "1.2.0" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.2.0.tgz#3433d9136aeb3c627981daa385fc7f32d27c48f1" integrity sha512-n6kZFH/KlCrqs/1GHMOd5i2fd/beQHuehKdWvNNffbGHTr/almdhuVvTVFb3V7fglz+nC50fFusu3lY33h12pA== @@ -2949,15 +2949,24 @@ dom-serializer@^1.0.1, dom-serializer@~1.2.0: domhandler "^4.0.0" entities "^2.0.0" +dom-serializer@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.1.tgz#d845a1565d7c041a95e5dab62184ab41e3a519be" + integrity sha512-Pv2ZluG5ife96udGgEDovOOOA5UELkltfJpnIExPrAk1LTvecolUGn6lIaoLh86d83GiB86CjzciMd9BuRB71Q== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.0.0" + entities "^2.0.0" + domelementtype@1, domelementtype@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== -domelementtype@^2.0.1, domelementtype@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.1.0.tgz#a851c080a6d1c3d94344aed151d99f669edf585e" - integrity sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w== +domelementtype@^2.0.1, domelementtype@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57" + integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A== domexception@^2.0.1: version "2.0.1" @@ -2980,12 +2989,12 @@ domhandler@^3.0.0: dependencies: domelementtype "^2.0.1" -domhandler@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.0.0.tgz#01ea7821de996d85f69029e81fa873c21833098e" - integrity sha512-KPTbnGQ1JeEMQyO1iYXoagsI6so/C96HZiFyByU3T6iAzpXn8EGEvct6unm1ZGoed8ByO2oirxgwxBmqKF9haA== +domhandler@^4.0.0, domhandler@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.2.0.tgz#f9768a5f034be60a89a27c2e4d0f74eba0d8b059" + integrity sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA== dependencies: - domelementtype "^2.1.0" + domelementtype "^2.2.0" domutils@^1.5.1: version "1.7.0" @@ -2995,7 +3004,7 @@ domutils@^1.5.1: dom-serializer "0" domelementtype "1" -domutils@^2.0.0, domutils@^2.4.3, domutils@^2.4.4: +domutils@^2.0.0, domutils@^2.4.4: version "2.4.4" resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.4.4.tgz#282739c4b150d022d34699797369aad8d19bbbd3" integrity sha512-jBC0vOsECI4OMdD0GC9mGn7NXPLb+Qt6KW1YDQzeQYRUFKmNG8lh7mO5HiELfr+lLQE7loDVI4QcAxV80HS+RA== @@ -3004,6 +3013,15 @@ domutils@^2.0.0, domutils@^2.4.3, domutils@^2.4.4: domelementtype "^2.0.1" domhandler "^4.0.0" +domutils@^2.5.2, domutils@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.6.0.tgz#2e15c04185d43fb16ae7057cb76433c6edb938b7" + integrity sha512-y0BezHuy4MDYxh6OvolXYsH+1EMGmFbwv5FKW7ovwMG6zTPWqNPq3WF9ayZssFq+UlKdffGLbOEaghNdaOm1WA== + dependencies: + dom-serializer "^1.0.1" + domelementtype "^2.2.0" + domhandler "^4.2.0" + ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" @@ -3068,7 +3086,7 @@ entities@^1.1.1: resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== -entities@^2.0.0, entities@~2.1.0: +entities@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w== @@ -4298,6 +4316,16 @@ htmlparser2@^6.0.0: domutils "^2.4.4" entities "^2.0.0" +htmlparser2@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" + integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.0.0" + domutils "^2.5.2" + entities "^2.0.0" + http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" @@ -6312,7 +6340,7 @@ parse-srcset@^1.0.2: resolved "https://registry.yarnpkg.com/parse-srcset/-/parse-srcset-1.0.2.tgz#f2bd221f6cc970a938d88556abc589caaaa2bde1" integrity sha1-8r0iH2zJcKk42IVWq8WJyqqiveE= -parse5-htmlparser2-tree-adapter@^6.0.0: +parse5-htmlparser2-tree-adapter@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz#2cdf9ad823321140370d4dbf5d3e92c7c8ddc6e6" integrity sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA== @@ -6324,7 +6352,7 @@ parse5@5.1.1: resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== -parse5@^6.0.0, parse5@^6.0.1: +parse5@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== @@ -8005,6 +8033,11 @@ tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a" integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A== +tslib@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.2.0.tgz#fb2c475977e35e241311ede2693cee1ec6698f5c" + integrity sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w== + tsutils@^3.17.1: version "3.19.1" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.19.1.tgz#d8566e0c51c82f32f9c25a4d367cd62409a547a9" From bfba2b0b6f09b7d470a6274d07053d0d854f7cd0 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Mon, 10 May 2021 11:16:51 -0400 Subject: [PATCH 0336/1449] Push ForwardDialog scrollbar into the gutter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …to give more space between it and the buttons. Signed-off-by: Robin Townsend --- res/css/views/dialogs/_ForwardDialog.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/res/css/views/dialogs/_ForwardDialog.scss b/res/css/views/dialogs/_ForwardDialog.scss index a3aa08d04f..a447b93cae 100644 --- a/res/css/views/dialogs/_ForwardDialog.scss +++ b/res/css/views/dialogs/_ForwardDialog.scss @@ -48,6 +48,8 @@ limitations under the License. .mx_ForwardList_content { flex-grow: 1; + // Push the scrollbar into the gutter + margin-right: -6px; } .mx_ForwardList_noResults { @@ -56,6 +58,8 @@ limitations under the License. } .mx_ForwardList_section { + margin-right: 6px; + &:not(:first-child) { margin-top: 24px; } From 9c8e89ff796e74909a602158521aeb3bb501e40c Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Mon, 10 May 2021 16:55:27 +0100 Subject: [PATCH 0337/1449] Fix importing --- src/HtmlUtils.tsx | 2 +- src/editor/serialize.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/HtmlUtils.tsx b/src/HtmlUtils.tsx index c781efd8c6..f2c2652280 100644 --- a/src/HtmlUtils.tsx +++ b/src/HtmlUtils.tsx @@ -31,7 +31,7 @@ import katex from 'katex'; import { AllHtmlEntities } from 'html-entities'; import SettingsStore from './settings/SettingsStore'; import cheerio from 'cheerio'; -import htmlparser2 from 'htmlparser2'; +import * as htmlparser2 from 'htmlparser2'; import {tryTransformPermalinkToLocalHref} from "./utils/permalinks/Permalinks"; import {SHORTCODE_TO_EMOJI, getEmojiFromUnicode} from "./emoji"; diff --git a/src/editor/serialize.ts b/src/editor/serialize.ts index d8005bc162..5db53064d5 100644 --- a/src/editor/serialize.ts +++ b/src/editor/serialize.ts @@ -22,7 +22,7 @@ import { AllHtmlEntities } from 'html-entities'; import SettingsStore from '../settings/SettingsStore'; import SdkConfig from '../SdkConfig'; import cheerio from 'cheerio'; -import htmlparser2 from 'htmlparser2'; +import * as htmlparser2 from 'htmlparser2'; export function mdSerialize(model: EditorModel) { return model.parts.reduce((html, part) => { From c96f11db7d92daf76b7d8fed5551207fecf76eb7 Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Mon, 10 May 2021 17:22:33 +0100 Subject: [PATCH 0338/1449] appease linter --- src/indexing/EventIndex.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/indexing/EventIndex.js b/src/indexing/EventIndex.js index e27687e784..0193be3375 100644 --- a/src/indexing/EventIndex.js +++ b/src/indexing/EventIndex.js @@ -210,8 +210,6 @@ export default class EventIndex extends EventEmitter { * listener, if so queues it up to be added to the index. */ onEventDecrypted = async (ev, err) => { - const eventId = ev.getId(); - // If the event isn't in our live event set, ignore it. if (err) return; await this.addLiveEventToIndex(ev); From 7821e00bc6c2dc7d27b701e4a5733b0a6e9369b4 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Mon, 10 May 2021 17:36:33 +0100 Subject: [PATCH 0339/1449] Revert to internal option --- package.json | 1 - src/HtmlUtils.tsx | 8 +++++--- src/editor/serialize.ts | 15 ++++++++++----- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index a03f02871e..bd011ea6e2 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,6 @@ "glob-to-regexp": "^0.4.1", "highlight.js": "^10.5.0", "html-entities": "^1.4.0", - "htmlparser2": "^6.1.0", "is-ip": "^3.1.0", "katex": "^0.12.0", "linkifyjs": "^2.1.9", diff --git a/src/HtmlUtils.tsx b/src/HtmlUtils.tsx index f2c2652280..ef5ac383e3 100644 --- a/src/HtmlUtils.tsx +++ b/src/HtmlUtils.tsx @@ -31,7 +31,6 @@ import katex from 'katex'; import { AllHtmlEntities } from 'html-entities'; import SettingsStore from './settings/SettingsStore'; import cheerio from 'cheerio'; -import * as htmlparser2 from 'htmlparser2'; import {tryTransformPermalinkToLocalHref} from "./utils/permalinks/Permalinks"; import {SHORTCODE_TO_EMOJI, getEmojiFromUnicode} from "./emoji"; @@ -423,9 +422,12 @@ export function bodyToHtml(content: IContent, highlights: string[], opts: IOpts safeBody = sanitizeHtml(formattedBody, sanitizeParams); if (SettingsStore.getValue("feature_latex_maths")) { - const phtml = cheerio.load(htmlparser2.parseDocument(safeBody, { + const phtml = cheerio.load(safeBody, { + // @ts-ignore: The `_useHtmlParser2` internal option is the + // simplest way to both parse and render using `htmlparser2`. + _useHtmlParser2: true, decodeEntities: false, - })); + }); // @ts-ignore - The types for `replaceWith` wrongly expect // Cheerio instance to be returned. phtml('div, span[data-mx-maths!=""]').replaceWith(function(i, e) { diff --git a/src/editor/serialize.ts b/src/editor/serialize.ts index 5db53064d5..cfdb36c7a8 100644 --- a/src/editor/serialize.ts +++ b/src/editor/serialize.ts @@ -22,7 +22,6 @@ import { AllHtmlEntities } from 'html-entities'; import SettingsStore from '../settings/SettingsStore'; import SdkConfig from '../SdkConfig'; import cheerio from 'cheerio'; -import * as htmlparser2 from 'htmlparser2'; export function mdSerialize(model: EditorModel) { return model.parts.reduce((html, part) => { @@ -117,16 +116,22 @@ export function htmlSerializeIfNeeded(model: EditorModel, {forceHTML = false} = const parser = new Markdown(md); if (!parser.isPlainText() || forceHTML) { // feed Markdown output to HTML parser - const phtml = cheerio.load(htmlparser2.parseDocument(parser.toHTML(), { + const phtml = cheerio.load(parser.toHTML(), { + // @ts-ignore: The `_useHtmlParser2` internal option is the + // simplest way to both parse and render using `htmlparser2`. + _useHtmlParser2: true, decodeEntities: false, - })); + }); if (SettingsStore.getValue("feature_latex_maths")) { // original Markdown without LaTeX replacements const parserOrig = new Markdown(orig); - const phtmlOrig = cheerio.load(htmlparser2.parseDocument(parserOrig.toHTML(), { + const phtmlOrig = cheerio.load(parserOrig.toHTML(), { + // @ts-ignore: The `_useHtmlParser2` internal option is the + // simplest way to both parse and render using `htmlparser2`. + _useHtmlParser2: true, decodeEntities: false, - })); + }); // since maths delimiters are handled before Markdown, // code blocks could contain mangled content. From 3e68d735977ebb319879f60e7c8ccb663051b4e0 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Mon, 10 May 2021 17:43:10 +0100 Subject: [PATCH 0340/1449] Upgrade sanitize types --- package.json | 2 +- yarn.lock | 29 ++++++----------------------- 2 files changed, 7 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index 342591081f..5c1b32df87 100644 --- a/package.json +++ b/package.json @@ -137,7 +137,7 @@ "@types/react": "^16.9", "@types/react-dom": "^16.9.10", "@types/react-transition-group": "^4.4.0", - "@types/sanitize-html": "^1.27.0", + "@types/sanitize-html": "^2.3.1", "@types/zxcvbn": "^4.4.0", "@typescript-eslint/eslint-plugin": "^4.14.0", "@typescript-eslint/parser": "^4.14.0", diff --git a/yarn.lock b/yarn.lock index 0d9b2bdd3f..28d009f908 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1638,12 +1638,12 @@ "@types/prop-types" "*" csstype "^3.0.2" -"@types/sanitize-html@^1.27.0": - version "1.27.0" - resolved "https://registry.yarnpkg.com/@types/sanitize-html/-/sanitize-html-1.27.0.tgz#77702dc856f16efecc005014c1d2e45b1f2cbc56" - integrity sha512-j7Vnh3P7W4ZcoRsHNO2HpwA2m1d0c2+l39xqSQqH0+WlfcvKypgZp45eCC7NJ75ZyXPxNb2PSbIL6LtZ6E0Qbw== +"@types/sanitize-html@^2.3.1": + version "2.3.1" + resolved "https://registry.yarnpkg.com/@types/sanitize-html/-/sanitize-html-2.3.1.tgz#094d696b83b7394b016e96342bbffa6a028795ce" + integrity sha512-+UT/XRluJuCunRftwO6OzG6WOBgJ+J3sROIoSJWX+7PB2FtTJTEJLrHCcNwzCQc0r60bej3WAbaigK+VZtZCGw== dependencies: - htmlparser2 "^4.1.0" + htmlparser2 "^6.0.0" "@types/stack-utils@^1.0.1": version "1.0.1" @@ -2973,13 +2973,6 @@ domhandler@^2.3.0: dependencies: domelementtype "1" -domhandler@^3.0.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-3.3.0.tgz#6db7ea46e4617eb15cf875df68b2b8524ce0037a" - integrity sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA== - dependencies: - domelementtype "^2.0.1" - domhandler@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.0.0.tgz#01ea7821de996d85f69029e81fa873c21833098e" @@ -2995,7 +2988,7 @@ domutils@^1.5.1: dom-serializer "0" domelementtype "1" -domutils@^2.0.0, domutils@^2.4.3, domutils@^2.4.4: +domutils@^2.4.3, domutils@^2.4.4: version "2.4.4" resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.4.4.tgz#282739c4b150d022d34699797369aad8d19bbbd3" integrity sha512-jBC0vOsECI4OMdD0GC9mGn7NXPLb+Qt6KW1YDQzeQYRUFKmNG8lh7mO5HiELfr+lLQE7loDVI4QcAxV80HS+RA== @@ -4278,16 +4271,6 @@ htmlparser2@^3.10.0: inherits "^2.0.1" readable-stream "^3.1.1" -htmlparser2@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-4.1.0.tgz#9a4ef161f2e4625ebf7dfbe6c0a2f52d18a59e78" - integrity sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q== - dependencies: - domelementtype "^2.0.1" - domhandler "^3.0.0" - domutils "^2.0.0" - entities "^2.0.0" - htmlparser2@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.0.0.tgz#c2da005030390908ca4c91e5629e418e0665ac01" From 503301aa89e3a8378d9e48c95b37ec19ab4d5e89 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Mon, 10 May 2021 13:00:06 -0400 Subject: [PATCH 0341/1449] Make rooms in ForwardDialog clickable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …so that you can jump to a room easily once you've forwarded a message there. Signed-off-by: Robin Townsend --- res/css/views/dialogs/_ForwardDialog.scss | 29 ++++++---- .../views/dialogs/ForwardDialog.tsx | 53 ++++++++++++------- .../views/dialogs/ForwardDialog-test.js | 10 ++-- 3 files changed, 58 insertions(+), 34 deletions(-) diff --git a/res/css/views/dialogs/_ForwardDialog.scss b/res/css/views/dialogs/_ForwardDialog.scss index a447b93cae..30a4cfcacf 100644 --- a/res/css/views/dialogs/_ForwardDialog.scss +++ b/res/css/views/dialogs/_ForwardDialog.scss @@ -74,23 +74,30 @@ limitations under the License. .mx_ForwardList_entry { display: flex; + justify-content: space-between; margin-top: 12px; - .mx_BaseAvatar { + .mx_ForwardList_roomButton { + display: flex; margin-right: 12px; - } - - .mx_ForwardList_entry_name { - font-size: $font-15px; - line-height: 30px; flex-grow: 1; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - margin-right: 12px; + min-width: 0; + + .mx_BaseAvatar { + margin-right: 12px; + } + + .mx_ForwardList_entry_name { + font-size: $font-15px; + line-height: 30px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + margin-right: 12px; + } } - .mx_AccessibleButton { + .mx_ForwardList_sendButton { &.mx_ForwardList_sending, &.mx_ForwardList_sent { &::before { content: ''; diff --git a/src/components/views/dialogs/ForwardDialog.tsx b/src/components/views/dialogs/ForwardDialog.tsx index fd10a88d93..ed6973cd4a 100644 --- a/src/components/views/dialogs/ForwardDialog.tsx +++ b/src/components/views/dialogs/ForwardDialog.tsx @@ -21,6 +21,7 @@ import {Room} from "matrix-js-sdk/src/models/room"; import {MatrixClient} from "matrix-js-sdk/src/client"; import {_t} from "../../../languageHandler"; +import dis from "../../../dispatcher/dispatcher"; import SettingsStore from "../../../settings/SettingsStore"; import {UIFeature} from "../../../settings/UIFeature"; import {Layout} from "../../../settings/Layout"; @@ -50,8 +51,9 @@ interface IProps extends IDialogProps { interface IEntryProps { room: Room; - // Callback to forward the message to this room - send(): Promise; + event: MatrixEvent; + cli: MatrixClient; + onFinished(success: boolean): void; } enum SendState { @@ -61,9 +63,26 @@ enum SendState { Failed, } -const Entry: React.FC = ({ room, send }) => { +const Entry: React.FC = ({ room, event, cli, onFinished }) => { const [sendState, setSendState] = useState(SendState.CanSend); + const jumpToRoom = () => { + dis.dispatch({ + action: "view_room", + room_id: room.roomId, + }); + onFinished(true); + }; + const send = async () => { + setSendState(SendState.Sending); + try { + await cli.sendEvent(room.roomId, event.getType(), event.getContent()); + setSendState(SendState.Sent); + } catch (e) { + setSendState(SendState.Failed); + } + }; + let button; if (room.maySendMessage()) { let label; @@ -85,16 +104,8 @@ const Entry: React.FC = ({ room, send }) => { button = { - setSendState(SendState.Sending); - try { - await send(); - setSendState(SendState.Sent); - } catch (e) { - setSendState(SendState.Failed); - } - }} + className={`mx_ForwardList_sendButton ${className}`} + onClick={send} disabled={sendState !== SendState.CanSend} > { label } @@ -103,7 +114,7 @@ const Entry: React.FC = ({ room, send }) => { button = {}} disabled={true} title={_t("You do not have permission to post to this room")} @@ -113,8 +124,10 @@ const Entry: React.FC = ({ room, send }) => { } return
    - - { room.name } + + + { room.name } + { button }
    ; }; @@ -207,7 +220,9 @@ const ForwardDialog: React.FC = ({ cli, event, permalinkCreator, onFinis cli.sendEvent(room.roomId, event.getType(), event.getContent())} + event={event} + cli={cli} + onFinished={onFinished} />, ) }
    @@ -220,7 +235,9 @@ const ForwardDialog: React.FC = ({ cli, event, permalinkCreator, onFinis cli.sendEvent(room.roomId, event.getType(), event.getContent())} + event={event} + cli={cli} + onFinished={onFinished} />, ) }
    diff --git a/test/components/views/dialogs/ForwardDialog-test.js b/test/components/views/dialogs/ForwardDialog-test.js index 2f062a84cc..331ee9d131 100644 --- a/test/components/views/dialogs/ForwardDialog-test.js +++ b/test/components/views/dialogs/ForwardDialog-test.js @@ -100,7 +100,7 @@ describe("ForwardDialog", () => { cancelSend = reject; })); - const firstButton = wrapper.find("Entry AccessibleButton").first(); + const firstButton = wrapper.find("AccessibleButton.mx_ForwardList_sendButton").first(); expect(firstButton.text()).toBe("Send"); act(() => { firstButton.simulate("click"); }); @@ -113,8 +113,8 @@ describe("ForwardDialog", () => { }); expect(firstButton.text()).toBe("Failed to send"); - const secondButton = wrapper.find("Entry AccessibleButton").at(1); - expect(secondButton.text()).toBe("Send"); + const secondButton = wrapper.find("AccessibleButton.mx_ForwardList_sendButton").at(1); + expect(secondButton.render().text()).toBe("Send"); act(() => { secondButton.simulate("click"); }); expect(secondButton.text()).toBe("Sending…"); @@ -155,9 +155,9 @@ describe("ForwardDialog", () => { const wrapper = await mountForwardDialog(undefined, rooms); - const firstButton = wrapper.find("Entry AccessibleButton").first(); + const firstButton = wrapper.find("AccessibleButton.mx_ForwardList_sendButton").first(); expect(firstButton.prop("disabled")).toBe(true); - const secondButton = wrapper.find("Entry AccessibleButton").last(); + const secondButton = wrapper.find("AccessibleButton.mx_ForwardList_sendButton").last(); expect(secondButton.prop("disabled")).toBe(false); }); }); From 7efbd2d930cc93dffdabe10f84bc320f58cf23c5 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Mon, 10 May 2021 13:57:47 -0400 Subject: [PATCH 0342/1449] Hide unencrypted badge from ForwardDialog preview Signed-off-by: Robin Townsend --- res/css/views/dialogs/_ForwardDialog.scss | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/res/css/views/dialogs/_ForwardDialog.scss b/res/css/views/dialogs/_ForwardDialog.scss index 30a4cfcacf..9bd0bd2879 100644 --- a/res/css/views/dialogs/_ForwardDialog.scss +++ b/res/css/views/dialogs/_ForwardDialog.scss @@ -35,6 +35,12 @@ limitations under the License. .mx_EventTile_msgOption { display: none; } + + // When forwarding messages from encrypted rooms, EventTile will complain + // that our preview is unencrypted, which doesn't actually matter + .mx_EventTile_e2eIcon_unencrypted { + display: none; + } } .mx_ForwardList { From 379d19e2e0a7ae2ab21489ae7f1b7044049d103d Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 10 May 2021 19:56:30 -0600 Subject: [PATCH 0343/1449] Lint --- src/components/structures/MessagePanel.js | 9 ++++----- test/components/structures/MessagePanel-test.js | 9 +++------ 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index 0c61dd759c..e5e0065be8 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -544,7 +544,7 @@ export default class MessagePanel extends React.Component { } if (!grouper) { const wantTile = this._shouldShowEvent(mxEv); - const isGrouped =false; + const isGrouped = false; if (wantTile) { // make sure we unpack the array returned by _getTilesForEvent, // otherwise react will auto-generate keys and we will end up @@ -972,7 +972,7 @@ class CreationGrouper { const EventListSummary = sdk.getComponent('views.elements.EventListSummary'); const panel = this.panel; const ret = []; - const isGrouped=true; + const isGrouped = true; const createEvent = this.createEvent; const lastShownEvent = this.lastShownEvent; @@ -1085,7 +1085,7 @@ class RedactionGrouper { const DateSeparator = sdk.getComponent('messages.DateSeparator'); const EventListSummary = sdk.getComponent('views.elements.EventListSummary'); - const isGrouped=true; + const isGrouped = true; const panel = this.panel; const ret = []; const lastShownEvent = this.lastShownEvent; @@ -1102,7 +1102,6 @@ class RedactionGrouper { ); const senders = new Set(); - let eventTiles = this.events.map((e, i) => { senders.add(e.sender); const prevEvent = i === 0 ? this.prevEvent : this.events[i - 1]; @@ -1186,7 +1185,7 @@ class MemberGrouper { const DateSeparator = sdk.getComponent('messages.DateSeparator'); const MemberEventListSummary = sdk.getComponent('views.elements.MemberEventListSummary'); - const isGrouped=true; + const isGrouped = true; const panel = this.panel; const lastShownEvent = this.lastShownEvent; const ret = []; diff --git a/test/components/structures/MessagePanel-test.js b/test/components/structures/MessagePanel-test.js index 42819235dd..dc70e3f7f6 100644 --- a/test/components/structures/MessagePanel-test.js +++ b/test/components/structures/MessagePanel-test.js @@ -94,7 +94,7 @@ describe('MessagePanel', function() { return events; } - //Just to avoid breaking Dateseparator tests that might run at 00hrs + // Just to avoid breaking Dateseparator tests that might run at 00hrs function mkOneDayEvents() { const events = []; const ts0 = Date.parse('09 May 2004 00:12:00 GMT'); @@ -264,7 +264,6 @@ describe('MessagePanel', function() { }), ]; } - function isReadMarkerVisible(rmContainer) { return rmContainer && rmContainer.children.length > 0; } @@ -453,7 +452,7 @@ describe('MessagePanel', function() { }); it('should render Date separators for the events', function () { - const events = mkOneDayEvents() + const events = mkOneDayEvents(); const res = mount( Date: Mon, 10 May 2021 20:03:20 -0600 Subject: [PATCH 0344/1449] Update src/components/views/rooms/EditMessageComposer.js --- src/components/views/rooms/EditMessageComposer.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/views/rooms/EditMessageComposer.js b/src/components/views/rooms/EditMessageComposer.js index a12a6497ad..c0b60a3247 100644 --- a/src/components/views/rooms/EditMessageComposer.js +++ b/src/components/views/rooms/EditMessageComposer.js @@ -179,6 +179,7 @@ export default class EditMessageComposer extends React.Component { dis.dispatch({action: "edit_event", event: null}); dis.fire(Action.FocusComposer); } + _isSlashCommand() { const parts = this.model.parts; const firstPart = parts[0]; From 376befd38eb87dc9afd5eaed64b79a5fcdc5eba1 Mon Sep 17 00:00:00 2001 From: Jaiwanth Date: Tue, 11 May 2021 10:37:53 +0530 Subject: [PATCH 0345/1449] Update src/components/views/rooms/EditMessageComposer.js Co-authored-by: Travis Ralston --- src/components/views/rooms/EditMessageComposer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/EditMessageComposer.js b/src/components/views/rooms/EditMessageComposer.js index 46999bb793..81a26df56c 100644 --- a/src/components/views/rooms/EditMessageComposer.js +++ b/src/components/views/rooms/EditMessageComposer.js @@ -193,7 +193,7 @@ export default class EditMessageComposer extends React.Component { const parts = serializedParts.map(p => partCreator.deserializePart(p)); return parts; } catch (e) { - console.error(e); + console.error("Error parsing editing state: ", e); } } } From 965af1a6422f32b3f6bc8e5fc1e6e53c5deaa890 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 11 May 2021 08:08:02 +0200 Subject: [PATCH 0346/1449] Initial SpaceTreeLevelLayoutStore implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- .../views/spaces/SpaceTreeLevel.tsx | 15 +++------ src/stores/SpaceTreeLevelLayoutStore.ts | 32 +++++++++++++++++++ 2 files changed, 37 insertions(+), 10 deletions(-) create mode 100644 src/stores/SpaceTreeLevelLayoutStore.ts diff --git a/src/components/views/spaces/SpaceTreeLevel.tsx b/src/components/views/spaces/SpaceTreeLevel.tsx index 5614271398..df9ea5533b 100644 --- a/src/components/views/spaces/SpaceTreeLevel.tsx +++ b/src/components/views/spaces/SpaceTreeLevel.tsx @@ -20,6 +20,7 @@ import {Room} from "matrix-js-sdk/src/models/room"; import RoomAvatar from "../avatars/RoomAvatar"; import SpaceStore from "../../../stores/SpaceStore"; +import SpaceTreeLevelLayoutStore from "../../../stores/SpaceTreeLevelLayoutStore"; import NotificationBadge from "../rooms/NotificationBadge"; import {RovingAccessibleButton} from "../../../accessibility/roving/RovingAccessibleButton"; import {RovingAccessibleTooltipButton} from "../../../accessibility/roving/RovingAccessibleTooltipButton"; @@ -48,8 +49,6 @@ import {EventType} from "matrix-js-sdk/src/@types/event"; import {StaticNotificationState} from "../../../stores/notifications/StaticNotificationState"; import {NotificationColor} from "../../../stores/notifications/NotificationColor"; -const getSpaceCollapsedKey = (space: Room) => `mx_space_collapsed_${space.roomId}`; - interface IItemProps { space?: Room; activeSpaces: Room[]; @@ -70,13 +69,9 @@ export class SpaceItem extends React.PureComponent { constructor(props) { super(props); - const collapsedLocalStorage = localStorage.getItem(getSpaceCollapsedKey(props.space)); - // XXX: localStorage doesn't allow booleans - // default to collapsed for root items - const collapsed = collapsedLocalStorage ? collapsedLocalStorage === "true" : !props.isNested; - this.state = { - collapsed: collapsed, + // default to collapsed for root items + collapsed: SpaceTreeLevelLayoutStore.getSpaceCollapsedState(props.space, !props.isNested), contextMenuPosition: null, }; } @@ -86,8 +81,8 @@ export class SpaceItem extends React.PureComponent { this.props.onExpand(); } const newCollapsedState = !this.state.collapsed; - // XXX: localStorage doesn't allow booleans - localStorage.setItem(getSpaceCollapsedKey(this.props.space), newCollapsedState.toString()); + + SpaceTreeLevelLayoutStore.setSpaceCollapsedState(this.props.space, newCollapsedState); this.setState({collapsed: newCollapsedState}); // don't bubble up so encapsulating button for space // doesn't get triggered diff --git a/src/stores/SpaceTreeLevelLayoutStore.ts b/src/stores/SpaceTreeLevelLayoutStore.ts new file mode 100644 index 0000000000..2ba8a73fcb --- /dev/null +++ b/src/stores/SpaceTreeLevelLayoutStore.ts @@ -0,0 +1,32 @@ +/* +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. +*/ + +import {Room} from "matrix-js-sdk/src/models/room"; + +const getSpaceCollapsedKey = (space: Room) => `mx_space_collapsed_${space.roomId}`; + +export default class SpaceTreeLevelLayoutStore { + public static setSpaceCollapsedState(space: Room, collapsed: boolean) { + // XXX: localStorage doesn't allow booleans + localStorage.setItem(getSpaceCollapsedKey(space), collapsed.toString()); + } + + public static getSpaceCollapsedState(space: Room, fallback: boolean): boolean { + const collapsedLocalStorage = localStorage.getItem(getSpaceCollapsedKey(space)); + // XXX: localStorage doesn't allow booleans + return collapsedLocalStorage ? collapsedLocalStorage === "true" : fallback; + } +} From de04d82395f39fdf0352040d6ad257ec48b9bb83 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 11 May 2021 10:01:40 +0100 Subject: [PATCH 0347/1449] Switch to using forms for implicit submission --- res/css/structures/_SpaceRoomView.scss | 4 ++ src/components/structures/SpaceRoomView.tsx | 56 ++++++++++++--------- 2 files changed, 36 insertions(+), 24 deletions(-) diff --git a/res/css/structures/_SpaceRoomView.scss b/res/css/structures/_SpaceRoomView.scss index ff51e28b7b..6b71f42671 100644 --- a/res/css/structures/_SpaceRoomView.scss +++ b/res/css/structures/_SpaceRoomView.scss @@ -103,6 +103,10 @@ $SpaceRoomViewInnerWidth: 428px; padding: 8px 22px; margin-left: 16px; } + + input.mx_AccessibleButton { + border: none; // override default styles + } } .mx_Field { diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx index 6566ccf939..e3de90834e 100644 --- a/src/components/structures/SpaceRoomView.tsx +++ b/src/components/structures/SpaceRoomView.tsx @@ -368,7 +368,6 @@ const SpaceLanding = ({ space }) => { const SpaceSetupFirstRooms = ({ space, title, description, onFinished }) => { const [busy, setBusy] = useState(false); const [error, setError] = useState(""); - let onClick = onFinished; const numFields = 3; const placeholders = [_t("General"), _t("Random"), _t("Support")]; // TODO vary default prefills for "Just Me" spaces @@ -384,16 +383,11 @@ const SpaceSetupFirstRooms = ({ space, title, description, onFinished }) => { value={roomNames[i]} onChange={ev => setRoomName(i, ev.target.value)} autoFocus={i === 2} - onKeyDown={ev => { - if (ev.key === Key.ENTER) { - ev.preventDefault(); - onClick(); - } - }} />; }); - const onNextClick = async () => { + const onNextClick = async (ev) => { + ev.preventDefault(); if (busy) return; setError(""); setBusy(true); @@ -419,6 +413,10 @@ const SpaceSetupFirstRooms = ({ space, title, description, onFinished }) => { setBusy(false); }; + let onClick = (ev) => { + ev.preventDefault(); + onFinished(); + }; let buttonLabel = _t("Skip for now"); if (roomNames.some(name => name.trim())) { onClick = onNextClick; @@ -430,16 +428,20 @@ const SpaceSetupFirstRooms = ({ space, title, description, onFinished }) => {
    { description }
    { error &&
    { error }
    } - { fields } +
    + { fields } +
    - { buttonLabel } - + element="input" + type="submit" + form="mx_SpaceSetupFirstRooms" + value={buttonLabel} + />
    ; }; @@ -564,7 +566,6 @@ const validateEmailRules = withValidation({ const SpaceSetupPrivateInvite = ({ space, onFinished }) => { const [busy, setBusy] = useState(false); const [error, setError] = useState(""); - let onClick = onFinished; const numFields = 3; const fieldRefs: RefObject[] = [useRef(), useRef(), useRef()]; const [emailAddresses, setEmailAddress] = useStateArray(numFields, ""); @@ -581,16 +582,11 @@ const SpaceSetupPrivateInvite = ({ space, onFinished }) => { ref={fieldRefs[i]} onValidate={validateEmailRules} autoFocus={i === 0} - onKeyDown={ev => { - if (ev.key === Key.ENTER) { - ev.preventDefault(); - onClick(); - } - }} />; }); - const onNextClick = async () => { + const onNextClick = async (ev) => { + ev.preventDefault(); if (busy) return; setError(""); for (let i = 0; i < fieldRefs.length; i++) { @@ -625,6 +621,10 @@ const SpaceSetupPrivateInvite = ({ space, onFinished }) => { setBusy(false); }; + let onClick = (ev) => { + ev.preventDefault(); + onFinished(); + }; let buttonLabel = _t("Skip for now"); if (emailAddresses.some(name => name.trim())) { onClick = onNextClick; @@ -638,7 +638,9 @@ const SpaceSetupPrivateInvite = ({ space, onFinished }) => {
    { error &&
    { error }
    } - { fields } +
    + { fields } +
    {
    - - { buttonLabel } - +
    ; }; From be236309c52fb6f33bb8bf9441c1ee0405b36685 Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Tue, 11 May 2021 10:08:57 +0100 Subject: [PATCH 0348/1449] use arrayFastClone instead of slice --- src/components/structures/TimelinePanel.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index a3c1c56276..5012d91a5f 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -38,6 +38,7 @@ import {haveTileForEvent} from "../views/rooms/EventTile"; import {UIFeature} from "../../settings/UIFeature"; import {objectHasDiff} from "../../utils/objects"; import {replaceableComponent} from "../../utils/replaceableComponent"; +import { arrayFastClone } from "../../utils/arrays"; const PAGINATE_SIZE = 20; const INITIAL_SIZE = 20; @@ -1142,11 +1143,11 @@ class TimelinePanel extends React.Component { _getEvents() { const events = this._timelineWindow.getEvents(); - // `slice` performs a shallow copy of the array + // `arrayFastClone` performs a shallow copy of the array // we want the last event to be decrypted first but displayed last // `reverse` is destructive and unfortunately mutates the "events" array - events - .slice().reverse() + arrayFastClone(events) + .reverse() .forEach(event => { if (event.shouldAttemptDecryption()) { event.attemptDecryption(MatrixClientPeg.get()._crypto); From 23001cb10d37b797971724025a353d57ad4c2cb5 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 11 May 2021 10:11:51 +0100 Subject: [PATCH 0349/1449] remove unused import --- src/components/structures/SpaceRoomView.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx index e3de90834e..eb9b8665d8 100644 --- a/src/components/structures/SpaceRoomView.tsx +++ b/src/components/structures/SpaceRoomView.tsx @@ -60,7 +60,6 @@ import IconizedContextMenu, { IconizedContextMenuOptionList, } from "../views/context_menus/IconizedContextMenu"; import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton"; -import {Key} from "../../Keyboard"; interface IProps { space: Room; From 4115fd869512d4a9f585b9e78f207889449549da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 11 May 2021 11:13:13 +0200 Subject: [PATCH 0350/1449] Rewrite SpaceTreeLevelLayoutStore to save paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- .../views/spaces/SpaceTreeLevel.tsx | 14 +++++++++++-- src/stores/SpaceTreeLevelLayoutStore.ts | 21 ++++++++++++------- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/components/views/spaces/SpaceTreeLevel.tsx b/src/components/views/spaces/SpaceTreeLevel.tsx index df9ea5533b..52508e6320 100644 --- a/src/components/views/spaces/SpaceTreeLevel.tsx +++ b/src/components/views/spaces/SpaceTreeLevel.tsx @@ -69,9 +69,15 @@ export class SpaceItem extends React.PureComponent { constructor(props) { super(props); + const collapsed = SpaceTreeLevelLayoutStore.getSpaceCollapsedState( + props.space.roomId, + this.props.parents, + !props.isNested, + ); + this.state = { // default to collapsed for root items - collapsed: SpaceTreeLevelLayoutStore.getSpaceCollapsedState(props.space, !props.isNested), + collapsed: collapsed, contextMenuPosition: null, }; } @@ -82,7 +88,11 @@ export class SpaceItem extends React.PureComponent { } const newCollapsedState = !this.state.collapsed; - SpaceTreeLevelLayoutStore.setSpaceCollapsedState(this.props.space, newCollapsedState); + SpaceTreeLevelLayoutStore.setSpaceCollapsedState( + this.props.space.roomId, + this.props.parents, + newCollapsedState, + ); this.setState({collapsed: newCollapsedState}); // don't bubble up so encapsulating button for space // doesn't get triggered diff --git a/src/stores/SpaceTreeLevelLayoutStore.ts b/src/stores/SpaceTreeLevelLayoutStore.ts index 2ba8a73fcb..1250fee0b7 100644 --- a/src/stores/SpaceTreeLevelLayoutStore.ts +++ b/src/stores/SpaceTreeLevelLayoutStore.ts @@ -14,18 +14,25 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {Room} from "matrix-js-sdk/src/models/room"; - -const getSpaceCollapsedKey = (space: Room) => `mx_space_collapsed_${space.roomId}`; +const getSpaceCollapsedKey = (roomId: string, parents: Set): string => { + const separator = "/"; + let path = ""; + if (parents) { + for (const entry of parents.entries()) { + path += entry + separator; + } + } + return `mx_space_collapsed_${path + roomId}`; +}; export default class SpaceTreeLevelLayoutStore { - public static setSpaceCollapsedState(space: Room, collapsed: boolean) { + public static setSpaceCollapsedState(roomId: string, parents: Set, collapsed: boolean) { // XXX: localStorage doesn't allow booleans - localStorage.setItem(getSpaceCollapsedKey(space), collapsed.toString()); + localStorage.setItem(getSpaceCollapsedKey(roomId, parents), collapsed.toString()); } - public static getSpaceCollapsedState(space: Room, fallback: boolean): boolean { - const collapsedLocalStorage = localStorage.getItem(getSpaceCollapsedKey(space)); + public static getSpaceCollapsedState(roomId: string, parents: Set, fallback: boolean): boolean { + const collapsedLocalStorage = localStorage.getItem(getSpaceCollapsedKey(roomId, parents)); // XXX: localStorage doesn't allow booleans return collapsedLocalStorage ? collapsedLocalStorage === "true" : fallback; } From 1b877f2b7c08322e9cfda1de7d29456ec6764fde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 11 May 2021 11:16:14 +0200 Subject: [PATCH 0351/1449] Make SpaceTreeLevelLayoutStore into a singleton MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/spaces/SpaceTreeLevel.tsx | 4 ++-- src/stores/SpaceTreeLevelLayoutStore.ts | 13 +++++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/components/views/spaces/SpaceTreeLevel.tsx b/src/components/views/spaces/SpaceTreeLevel.tsx index 52508e6320..f799cb02ba 100644 --- a/src/components/views/spaces/SpaceTreeLevel.tsx +++ b/src/components/views/spaces/SpaceTreeLevel.tsx @@ -69,7 +69,7 @@ export class SpaceItem extends React.PureComponent { constructor(props) { super(props); - const collapsed = SpaceTreeLevelLayoutStore.getSpaceCollapsedState( + const collapsed = SpaceTreeLevelLayoutStore.instance.getSpaceCollapsedState( props.space.roomId, this.props.parents, !props.isNested, @@ -88,7 +88,7 @@ export class SpaceItem extends React.PureComponent { } const newCollapsedState = !this.state.collapsed; - SpaceTreeLevelLayoutStore.setSpaceCollapsedState( + SpaceTreeLevelLayoutStore.instance.setSpaceCollapsedState( this.props.space.roomId, this.props.parents, newCollapsedState, diff --git a/src/stores/SpaceTreeLevelLayoutStore.ts b/src/stores/SpaceTreeLevelLayoutStore.ts index 1250fee0b7..424e9f4012 100644 --- a/src/stores/SpaceTreeLevelLayoutStore.ts +++ b/src/stores/SpaceTreeLevelLayoutStore.ts @@ -26,12 +26,21 @@ const getSpaceCollapsedKey = (roomId: string, parents: Set): string => { }; export default class SpaceTreeLevelLayoutStore { - public static setSpaceCollapsedState(roomId: string, parents: Set, collapsed: boolean) { + private static internalInstance: SpaceTreeLevelLayoutStore; + + public static get instance(): SpaceTreeLevelLayoutStore { + if (!SpaceTreeLevelLayoutStore.internalInstance) { + SpaceTreeLevelLayoutStore.internalInstance = new SpaceTreeLevelLayoutStore(); + } + return SpaceTreeLevelLayoutStore.internalInstance; + } + + public setSpaceCollapsedState(roomId: string, parents: Set, collapsed: boolean) { // XXX: localStorage doesn't allow booleans localStorage.setItem(getSpaceCollapsedKey(roomId, parents), collapsed.toString()); } - public static getSpaceCollapsedState(roomId: string, parents: Set, fallback: boolean): boolean { + public getSpaceCollapsedState(roomId: string, parents: Set, fallback: boolean): boolean { const collapsedLocalStorage = localStorage.getItem(getSpaceCollapsedKey(roomId, parents)); // XXX: localStorage doesn't allow booleans return collapsedLocalStorage ? collapsedLocalStorage === "true" : fallback; From da1df705576a35ac5655e7a70c7f5278cdecdf8f Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Tue, 11 May 2021 10:18:53 +0100 Subject: [PATCH 0352/1449] Improve comments and explainer for new decryption approach --- src/components/structures/MatrixChat.tsx | 4 ++++ src/indexing/EventIndex.js | 6 ++++++ src/stores/BreadcrumbsStore.ts | 20 +++++++++----------- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index fa2ea1546a..691c2bd08c 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -906,6 +906,10 @@ export default class MatrixChat extends React.PureComponent { let presentedId = roomInfo.room_alias || roomInfo.room_id; const room = MatrixClientPeg.get().getRoom(roomInfo.room_id); if (room) { + // Not all timeline events are decrypted ahead of time anymore + // Only the critical ones for a typical UI are + // This will start the decryption process for all events when a + // user views a room room.decryptAllEvents(); const theAlias = Rooms.getDisplayAliasForRoom(room); if (theAlias) { diff --git a/src/indexing/EventIndex.js b/src/indexing/EventIndex.js index 0193be3375..857dc5b248 100644 --- a/src/indexing/EventIndex.js +++ b/src/indexing/EventIndex.js @@ -188,6 +188,7 @@ export default class EventIndex extends EventEmitter { } if (ev.isBeingDecrypted()) { + // XXX: Private member access await ev._decryptionPromise; } @@ -523,6 +524,11 @@ export default class EventIndex extends EventEmitter { emit: false, }); } else { + // TODO the decryption promise is a private property, this + // should either be made public or we should convert the + // event that gets fired when decryption is done into a + // promise using the once event emitter method: + // https://nodejs.org/api/events.html#events_events_once_emitter_name return event._decryptionPromise; } }); diff --git a/src/stores/BreadcrumbsStore.ts b/src/stores/BreadcrumbsStore.ts index edb8fc8e29..2d59bc7d02 100644 --- a/src/stores/BreadcrumbsStore.ts +++ b/src/stores/BreadcrumbsStore.ts @@ -16,13 +16,14 @@ limitations under the License. import SettingsStore from "../settings/SettingsStore"; import { Room } from "matrix-js-sdk/src/models/room"; +import { EventType } from "matrix-js-sdk/src/@types/event"; import { ActionPayload } from "../dispatcher/payloads"; import { AsyncStoreWithClient } from "./AsyncStoreWithClient"; import defaultDispatcher from "../dispatcher/dispatcher"; import { arrayHasDiff } from "../utils/arrays"; import { isNullOrUndefined } from "matrix-js-sdk/src/utils"; import { SettingLevel } from "../settings/SettingLevel"; -import {MatrixClientPeg} from '../MatrixClientPeg'; +import { MatrixClientPeg } from '../MatrixClientPeg'; const MAX_ROOMS = 20; // arbitrary const AUTOJOIN_WAIT_THRESHOLD_MS = 90000; // 90s, the time we wait for an autojoined room to show up @@ -64,21 +65,18 @@ export class BreadcrumbsStore extends AsyncStoreWithClient { const prevRoomCount = (prevState.rooms?.length || 0); const currentRoomCount = (this.state.rooms?.length || 0) - /** - * Only decrypting the breadcrumb rooms events on app initialisation - * when room count transitions from 0 to the number of rooms it contains - */ + // Only decrypting the breadcrumb rooms events on app initialisation + // when room count transitions from 0 to the number of rooms it contains if (prevRoomCount === 0 && currentRoomCount > prevRoomCount) { const client = MatrixClientPeg.get(); - /** - * Rooms in the breadcrumb have a good chance to be interacted with - * again by a user. Decrypting the messages ahead of time will help - * reduce content shift on first render - */ + // Rooms in the breadcrumb have a good chance to be interacted with + // again by a user. Decrypting the messages ahead of time will help + // reduce content shift on first render this.state.rooms?.forEach(async room => { - const [cryptoEvent] = room.currentState.getStateEvents("m.room.encryption"); + const [cryptoEvent] = room.currentState.getStateEvents(EventType.RoomEncryption); if (cryptoEvent) { if (!client.isRoomEncrypted(room.roomId)) { + // XXX: Private member access await client._crypto.onCryptoEvent(cryptoEvent); } room?.decryptAllEvents(); From 5b9b878808f6b8a22ee1ffc6a2e8b45877710b84 Mon Sep 17 00:00:00 2001 From: c-cal Date: Mon, 10 May 2021 10:33:18 +0000 Subject: [PATCH 0353/1449] Translated using Weblate (French) Currently translated at 100.0% (2931 of 2931 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/fr/ --- src/i18n/strings/fr.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index d8a9abd9b4..4aee15691b 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -3024,7 +3024,7 @@ "Use Command + F to search": "Utilisez Commande + F pour rechercher", "Show line numbers in code blocks": "Afficher les numéros de ligne dans les blocs de code", "Expand code blocks by default": "Développer les blocs de code par défaut", - "Show stickers button": "Afficher le bouton autocollants", + "Show stickers button": "Afficher le bouton des autocollants", "Use app": "Utiliser l’application", "Element Web is experimental on mobile. For a better experience and the latest features, use our free native app.": "Element Web est expérimental sur téléphone. Pour une meilleure expérience et bénéficier des dernières fonctionnalités, utilisez notre application native gratuite.", "Use app for a better experience": "Utilisez une application pour une meilleure expérience", From b0f23aa65bb6fda83e30689d674fdb60a19bcd25 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 11 May 2021 12:20:18 +0100 Subject: [PATCH 0354/1449] Improve permissions error when adding new server to room directory --- .../views/directory/NetworkDropdown.js | 30 ++++++++++--------- src/i18n/strings/en_EN.json | 1 + 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/components/views/directory/NetworkDropdown.js b/src/components/views/directory/NetworkDropdown.js index 2fabda1a74..e6ff6d9791 100644 --- a/src/components/views/directory/NetworkDropdown.js +++ b/src/components/views/directory/NetworkDropdown.js @@ -49,6 +49,18 @@ const inPlaceOf = (elementRect) => ({ }); const validServer = withValidation({ + deriveData: async ({ value }) => { + try { + // check if we can successfully load this server's room directory + await MatrixClientPeg.get().publicRooms({ + limit: 1, + server: value, + }); + return {}; + } catch (error) { + return { error }; + } + }, rules: [ { key: "required", @@ -57,21 +69,11 @@ const validServer = withValidation({ }, { key: "available", final: true, - test: async ({ value }) => { - try { - const opts = { - limit: 1, - server: value, - }; - // check if we can successfully load this server's room directory - await MatrixClientPeg.get().publicRooms(opts); - return true; - } catch (e) { - return false; - } - }, + test: async (_, { error }) => !error, valid: () => _t("Looks good"), - invalid: () => _t("Can't find this server or its room list"), + invalid: ({ error }) => error.errcode === "M_FORBIDDEN" + ? _t("You are not allowed to view this server's rooms list") + : _t("Can't find this server or its room list"), }, ], }); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index f60770acf6..430aa5a835 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2019,6 +2019,7 @@ "Home": "Home", "Enter a server name": "Enter a server name", "Looks good": "Looks good", + "You are not allowed to view this server's rooms list": "You are not allowed to view this server's rooms list", "Can't find this server or its room list": "Can't find this server or its room list", "Your server": "Your server", "Are you sure you want to remove %(serverName)s": "Are you sure you want to remove %(serverName)s", From 240753a84f0fdb6eb8db842fec4a578494132aac Mon Sep 17 00:00:00 2001 From: Jaiwanth Date: Tue, 11 May 2021 18:37:41 +0530 Subject: [PATCH 0355/1449] Check for a pending edit only once per render and clear any pending events while switching between edits --- src/components/structures/MessagePanel.js | 20 +++++++++------- .../views/rooms/EditMessageComposer.js | 24 ++++++++++++++----- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index 00f2c4c826..73a2a3c4b6 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -472,6 +472,10 @@ export default class MessagePanel extends React.Component { return {nextEvent, nextTile}; } + get _roomHasPendingEdit() { + return localStorage.getItem(`mx_edit_room_${this.props.room.roomId}`); + } + _getEventTiles() { this.eventNodes = {}; @@ -560,6 +564,13 @@ export default class MessagePanel extends React.Component { } } + if (!this.props.editState && this._roomHasPendingEdit) { + defaultDispatcher.dispatch({ + action: "edit_event", + event: this.props.room.findEventById(this._roomHasPendingEdit), + }); + } + if (grouper) { ret.push(...grouper.getTiles()); } @@ -567,21 +578,12 @@ export default class MessagePanel extends React.Component { return ret; } - _wasEventBeingEdited = (mxEv) => { - return localStorage.getItem(`mx_edit_state_${mxEv.getRoomId()} - _${mxEv.getId()}`) !== null; - } - _getTilesForEvent(prevEvent, mxEv, last, isGrouped=false, nextEvent, nextEventWithTile) { const TileErrorBoundary = sdk.getComponent('messages.TileErrorBoundary'); const EventTile = sdk.getComponent('rooms.EventTile'); const DateSeparator = sdk.getComponent('messages.DateSeparator'); const ret = []; - if (!this.props.editState && this._wasEventBeingEdited(mxEv) ) { - defaultDispatcher.dispatch({action: "edit_event", event: mxEv}); - } - const isEditing = this.props.editState && this.props.editState.getEvent().getId() === mxEv.getId(); // local echoes have a fake date, which could even be yesterday. Treat them diff --git a/src/components/views/rooms/EditMessageComposer.js b/src/components/views/rooms/EditMessageComposer.js index ceb49b32c6..897388d5d2 100644 --- a/src/components/views/rooms/EditMessageComposer.js +++ b/src/components/views/rooms/EditMessageComposer.js @@ -177,6 +177,14 @@ export default class EditMessageComposer extends React.Component { } } + get _editorRoomKey() { + return `mx_edit_room_${this._getRoom().roomId}`; + } + + get _editorStateKey() { + return `mx_edit_state_${this.props.editState.getEvent().getId()}`; + } + _cancelEdit = () => { this._clearStoredEditorState(); dis.dispatch({action: "edit_event", event: null}); @@ -184,7 +192,7 @@ export default class EditMessageComposer extends React.Component { } get _shouldSaveStoredEditorState() { - return localStorage.getItem(this._editorStateKey) !== null; + return localStorage.getItem(this._editorRoomKey) !== null; } _restoreStoredEditorState(partCreator) { @@ -200,17 +208,21 @@ export default class EditMessageComposer extends React.Component { } } - get _editorStateKey() { - return `mx_edit_state_${this.props.editState.getEvent().getRoomId()} - _${this.props.editState.getEvent().event.event_id}`; + _clearStoredEditorState() { + localStorage.removeItem(this._editorRoomKey); + localStorage.removeItem(this._editorStateKey); } - _clearStoredEditorState() { - localStorage.removeItem(this._editorStateKey); + _clearPreviousEdit() { + if (localStorage.getItem(this._editorRoomKey)) { + localStorage.removeItem(`mx_edit_state_${localStorage.getItem(this._editorRoomKey)}`); + } } _saveStoredEditorState() { const item = SendHistoryManager.createItem(this.model); + this._clearPreviousEdit(); + localStorage.setItem(this._editorRoomKey, this.props.editState.getEvent().getId()); localStorage.setItem(this._editorStateKey, JSON.stringify(item)); } From 6ece4ef2abb62a508410388888df2c06c6154608 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 11 May 2021 14:08:09 +0100 Subject: [PATCH 0356/1449] i18n --- 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 9b58b7713e..f9d8d8afc9 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2040,6 +2040,8 @@ "%(networkName)s rooms": "%(networkName)s rooms", "Matrix rooms": "Matrix rooms", "Filter your rooms and spaces": "Filter your rooms and spaces", + "Feeling experimental?": "Feeling experimental?", + "You can add existing spaces to a space.": "You can add existing spaces to a space.", "Direct Messages": "Direct Messages", "Space selection": "Space selection", "Add existing rooms": "Add existing rooms", From 006aa2d5b903d8331a5cd794205c4123d99651b6 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Tue, 11 May 2021 09:39:06 -0500 Subject: [PATCH 0357/1449] Catch another instance of unlabeled avatars. Signed-off-by: Nolan Darilek --- src/components/views/avatars/BaseAvatar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/avatars/BaseAvatar.tsx b/src/components/views/avatars/BaseAvatar.tsx index 5ecdd4ec5a..8ce05e0a55 100644 --- a/src/components/views/avatars/BaseAvatar.tsx +++ b/src/components/views/avatars/BaseAvatar.tsx @@ -179,7 +179,7 @@ const BaseAvatar = (props: IProps) => { width: toPx(width), height: toPx(height), }} - title={title} alt="" + title={title} alt={_t("Avatar")} inputRef={inputRef} {...otherProps} /> ); From bf4c8f048fc1619ae70ddb01d9e49b340af0df97 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 11 May 2021 15:58:19 +0100 Subject: [PATCH 0358/1449] Add feedback mechanism for beta features --- res/css/views/beta/_BetaCard.scss | 8 ++- src/components/views/beta/BetaCard.tsx | 34 +++++++-- .../views/dialogs/BetaFeedbackDialog.tsx | 69 +++++++++++++++++++ src/i18n/strings/en_EN.json | 10 +-- src/rageshake/submit-rageshake.ts | 18 +++++ src/settings/Settings.tsx | 7 +- 6 files changed, 131 insertions(+), 15 deletions(-) create mode 100644 src/components/views/dialogs/BetaFeedbackDialog.tsx diff --git a/res/css/views/beta/_BetaCard.scss b/res/css/views/beta/_BetaCard.scss index 05149b7f6c..3463a653fc 100644 --- a/res/css/views/beta/_BetaCard.scss +++ b/res/css/views/beta/_BetaCard.scss @@ -39,19 +39,21 @@ limitations under the License. font-size: $font-15px; line-height: $font-20px; color: $secondary-fg-color; + margin-bottom: 20px; } .mx_AccessibleButton { display: block; - margin: 20px 0; - padding: 12px 40px; - width: max-content; + margin: 12px 0; + padding: 7px 40px; + width: auto; } .mx_BetaCard_disclaimer { font-size: $font-12px; line-height: $font-15px; color: $secondary-fg-color; + margin-top: 20px; } } diff --git a/src/components/views/beta/BetaCard.tsx b/src/components/views/beta/BetaCard.tsx index 96b1fbabe5..c12b05d119 100644 --- a/src/components/views/beta/BetaCard.tsx +++ b/src/components/views/beta/BetaCard.tsx @@ -22,6 +22,9 @@ import AccessibleButton from "../elements/AccessibleButton"; import SettingsStore from "../../../settings/SettingsStore"; import {SettingLevel} from "../../../settings/SettingLevel"; import TextWithTooltip from "../elements/TextWithTooltip"; +import Modal from "../../../Modal"; +import BetaFeedbackDialog from "../dialogs/BetaFeedbackDialog"; +import SdkConfig from "../../../SdkConfig"; interface IProps { title?: string; @@ -63,9 +66,23 @@ const BetaCard = ({ title: titleOverride, featureId }: IProps) => { const info = SettingsStore.getBetaInfo(featureId); if (!info) return null; // Beta is invalid/disabled - const { title, caption, disclaimer, image } = info; + const { title, caption, disclaimer, image, feedbackLabel, feedbackSubheading } = info; const value = SettingsStore.getValue(featureId); + let feedbackButton; + if (value && feedbackLabel && feedbackSubheading && SdkConfig.get().bug_report_endpoint_url) { + feedbackButton = { + Modal.createTrackedDialog("Beta Feedback", featureId, BetaFeedbackDialog, { + featureId, + }); + }} + kind="primary" + > + { _t("Feedback") } + ; + } + return

    @@ -73,12 +90,15 @@ const BetaCard = ({ title: titleOverride, featureId }: IProps) => {

    { _t(caption) } - SettingsStore.setValue(featureId, null, SettingLevel.DEVICE, !value)} - kind="primary" - > - { value ? _t("Leave the beta") : _t("Join the beta") } - +
    + { feedbackButton } + SettingsStore.setValue(featureId, null, SettingLevel.DEVICE, !value)} + kind={feedbackButton ? "primary_outline" : "primary"} + > + { value ? _t("Leave the beta") : _t("Join the beta") } + +
    { disclaimer &&
    { disclaimer(value) }
    } diff --git a/src/components/views/dialogs/BetaFeedbackDialog.tsx b/src/components/views/dialogs/BetaFeedbackDialog.tsx new file mode 100644 index 0000000000..702adc8fb1 --- /dev/null +++ b/src/components/views/dialogs/BetaFeedbackDialog.tsx @@ -0,0 +1,69 @@ +/* +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 React, {useState} from "react"; + +import QuestionDialog from './QuestionDialog'; +import { _t } from '../../../languageHandler'; +import Field from "../elements/Field"; +import SdkConfig from "../../../SdkConfig"; +import {IDialogProps} from "./IDialogProps"; +import SettingsStore from "../../../settings/SettingsStore"; +import {submitFeedback} from "../../../rageshake/submit-rageshake"; + +interface IProps extends IDialogProps { + featureId: string; +} + +const BetaFeedbackDialog: React.FC = ({featureId, onFinished}) => { + const info = SettingsStore.getBetaInfo(featureId); + + const [comment, setComment] = useState(""); + + const sendFeedback = async (ok: boolean) => { + if (!ok) return onFinished(false); + + submitFeedback(SdkConfig.get().bug_report_endpoint_url, info.feedbackLabel, comment); + onFinished(true); + }; + + return ( + { _t(info.feedbackSubheading) } + + { + setComment(ev.target.value); + }} + /> + } + button={_t("Send feedback")} + buttonDisabled={!comment} + onFinished={sendFeedback} + />); +}; + +export default BetaFeedbackDialog; diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index f9d8d8afc9..0f1e8c8fbd 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -787,11 +787,12 @@ "Spaces prototype. Incompatible with Communities, Communities v2 and Custom Tags. Requires compatible homeserver for some features.": "Spaces prototype. Incompatible with Communities, Communities v2 and Custom Tags. Requires compatible homeserver for some features.", "Spaces": "Spaces", "Spaces are a new way to group rooms and people.": "Spaces are a new way to group rooms and people.", - "%(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "%(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.", + "If you leave, %(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "If you leave, %(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.", "Beta available for web, desktop and Android. Thank you for trying the beta.": "Beta available for web, desktop and Android. Thank you for trying the beta.", "%(brand)s will reload with Spaces enabled. Communities and custom tags will be hidden.": "%(brand)s will reload with Spaces enabled. Communities and custom tags will be hidden.", "You can leave the beta any time from settings or tapping on a beta badge, like the one above.": "You can leave the beta any time from settings or tapping on a beta badge, like the one above.", "Beta available for web, desktop and Android. Some features may be unavailable on your homeserver.": "Beta available for web, desktop and Android. Some features may be unavailable on your homeserver.", + "You’re using an early version of Spaces, your feedback will really help inform the next versions.": "You’re using an early version of Spaces, your feedback will really help inform the next versions.", "Show options to enable 'Do not disturb' mode": "Show options to enable 'Do not disturb' mode", "Send and receive voice messages (in development)": "Send and receive voice messages (in development)", "Render LaTeX maths in messages": "Render LaTeX maths in messages", @@ -2063,6 +2064,10 @@ "Invite anyway and never warn me again": "Invite anyway and never warn me again", "Invite anyway": "Invite anyway", "Close dialog": "Close dialog", + "Beta feedback": "Beta feedback", + "Add comment": "Add comment", + "Comment": "Comment", + "Send feedback": "Send feedback", "Please tell us what went wrong or, better, create a GitHub issue that describes the problem.": "Please tell us what went wrong or, better, create a GitHub issue that describes the problem.", "Preparing to send logs": "Preparing to send logs", "Logs sent": "Logs sent", @@ -2189,14 +2194,11 @@ "Rate %(brand)s": "Rate %(brand)s", "Tell us below how you feel about %(brand)s so far.": "Tell us below how you feel about %(brand)s so far.", "Please go into as much detail as you like, so we can track down the problem.": "Please go into as much detail as you like, so we can track down the problem.", - "Add comment": "Add comment", - "Comment": "Comment", "There are two ways you can provide feedback and help us improve %(brand)s.": "There are two ways you can provide feedback and help us improve %(brand)s.", "PRO TIP: If you start a bug, please submit debug logs to help us track down the problem.": "PRO TIP: If you start a bug, please submit debug logs to help us track down the problem.", "Feedback": "Feedback", "Report a bug": "Report a bug", "Please view existing bugs on Github first. No match? Start a new one.": "Please view existing bugs on Github first. No match? Start a new one.", - "Send feedback": "Send feedback", "Confirm abort of host creation": "Confirm abort of host creation", "Are you sure you wish to abort creation of the host? The process cannot be continued.": "Are you sure you wish to abort creation of the host? The process cannot be continued.", "Abort": "Abort", diff --git a/src/rageshake/submit-rageshake.ts b/src/rageshake/submit-rageshake.ts index 29856b1a86..9c4fe1f95b 100644 --- a/src/rageshake/submit-rageshake.ts +++ b/src/rageshake/submit-rageshake.ts @@ -28,6 +28,7 @@ import * as rageshake from './rageshake'; // polyfill textencoder if necessary import * as TextEncodingUtf8 from 'text-encoding-utf-8'; import SettingsStore from "../settings/SettingsStore"; +import SdkConfig from "../SdkConfig"; let TextEncoder = window.TextEncoder; if (!TextEncoder) { TextEncoder = TextEncodingUtf8.TextEncoder; @@ -268,6 +269,23 @@ function uint8ToString(buf: Buffer) { return out; } +export async function submitFeedback(endpoint: string, label: string, comment: string) { + let version = "UNKNOWN"; + try { + version = await PlatformPeg.get().getAppVersion(); + } catch (err) {} // PlatformPeg already logs this. + + const body = new FormData(); + body.append("label", label); + body.append("text", comment); + + body.append("app", "element-web"); + body.append("version", version); + body.append("platform", PlatformPeg.get().getHumanReadableName()); + + await _submitReport(SdkConfig.get().bug_report_endpoint_url, body, () => {}); +} + function _submitReport(endpoint: string, body: FormData, progressCallback: (string) => void) { return new Promise((resolve, reject) => { const req = new XMLHttpRequest(); diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx index 47e63376bb..4420ed1c5d 100644 --- a/src/settings/Settings.tsx +++ b/src/settings/Settings.tsx @@ -125,6 +125,8 @@ export interface ISetting { caption: string; // _td disclaimer?: (enabled: boolean) => ReactNode; image: string; // require(...) + feedbackSubheading?: string; + feedbackLabel?: string; }; } @@ -142,7 +144,7 @@ export const SETTINGS: {[setting: string]: ISetting} = { disclaimer: (enabled) => { if (enabled) { return <> -

    { _t("%(brand)s will reload with Spaces disabled. " + +

    { _t("If you leave, %(brand)s will reload with Spaces disabled. " + "Communities and custom tags will be visible again.", { brand: SdkConfig.get().brand, }) }

    @@ -162,6 +164,9 @@ export const SETTINGS: {[setting: string]: ISetting} = { ; }, image: require("../../res/img/betas/spaces.png"), + feedbackSubheading: _td("You’re using an early version of Spaces, " + + "your feedback will really help inform the next versions."), + feedbackLabel: "spaces-feedback", }, }, "feature_dnd": { From 965b0ab58d0dceebff227ce895fff498cba9a1d7 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 11 May 2021 16:28:00 +0100 Subject: [PATCH 0359/1449] Upgrade matrix-js-sdk to 11.0.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 d9ea440936..4f6de8ce5c 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,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": "11.0.0-rc.1", "matrix-widget-api": "^0.1.0-beta.13", "minimist": "^1.2.5", "opus-recorder": "^8.0.3", diff --git a/yarn.lock b/yarn.lock index 7712ac507a..4fe12f3768 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5669,9 +5669,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 "10.1.0" - resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/2d73805ca3d8c5a140fe05e574f826696de1656a" +matrix-js-sdk@11.0.0-rc.1: + version "11.0.0-rc.1" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-11.0.0-rc.1.tgz#a40fdc9e93a1a9e873dd867e5766a20ea780e1d8" + integrity sha512-zATTKWH4yrs6mKcLQNvhvwi1IRGUEx3xt3MPCFuSuQq23TMbnxhOZMMpUF6n19FpioHw9jbz7cPsdVKM2gpDLw== dependencies: "@babel/runtime" "^7.12.5" another-json "^0.2.0" From 657481156f33d456a0e53bf061adf2e36bcf4e4d Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 11 May 2021 16:36:52 +0100 Subject: [PATCH 0360/1449] Prepare changelog for v3.21.0-rc.1 --- CHANGELOG.md | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 58d23e3413..fe714b2b89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,89 @@ +Changes in [3.21.0-rc.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.21.0-rc.1) (2021-05-11) +=============================================================================================================== +[Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v3.20.0...v3.21.0-rc.1) + + * Upgrade to JS SDK 11.0.0-rc.1 + * Add disclaimer about subspaces being experimental in add existing dialog + [\#5978](https://github.com/matrix-org/matrix-react-sdk/pull/5978) + * Spaces Beta release + [\#5933](https://github.com/matrix-org/matrix-react-sdk/pull/5933) + * Improve permissions error when adding new server to room directory + [\#6009](https://github.com/matrix-org/matrix-react-sdk/pull/6009) + * Allow user to progress through space creation & setup using Enter + [\#6006](https://github.com/matrix-org/matrix-react-sdk/pull/6006) + * Upgrade sanitize types + [\#6008](https://github.com/matrix-org/matrix-react-sdk/pull/6008) + * Upgrade `cheerio` and resolve type errors + [\#6007](https://github.com/matrix-org/matrix-react-sdk/pull/6007) + * Add slash commands support to edit message composer + [\#5865](https://github.com/matrix-org/matrix-react-sdk/pull/5865) + * Fix the two todays problem + [\#5940](https://github.com/matrix-org/matrix-react-sdk/pull/5940) + * Switch the Home Space out for an All rooms space + [\#5969](https://github.com/matrix-org/matrix-react-sdk/pull/5969) + * Show device ID in UserInfo when there is no device name + [\#5985](https://github.com/matrix-org/matrix-react-sdk/pull/5985) + * Switch back to release version of `sanitize-html` + [\#6005](https://github.com/matrix-org/matrix-react-sdk/pull/6005) + * Bump hosted-git-info from 2.8.8 to 2.8.9 + [\#5998](https://github.com/matrix-org/matrix-react-sdk/pull/5998) + * Don't use the event's metadata to calc the scale of an image + [\#5982](https://github.com/matrix-org/matrix-react-sdk/pull/5982) + * Adjust MIME type of upload confirmation if needed + [\#5981](https://github.com/matrix-org/matrix-react-sdk/pull/5981) + * Forbid redaction of encryption events + [\#5991](https://github.com/matrix-org/matrix-react-sdk/pull/5991) + * Fix voice message playback being squished up against send button + [\#5988](https://github.com/matrix-org/matrix-react-sdk/pull/5988) + * Improve style of notification badges on the space panel + [\#5983](https://github.com/matrix-org/matrix-react-sdk/pull/5983) + * Add dev dependency for parse5 typings + [\#5990](https://github.com/matrix-org/matrix-react-sdk/pull/5990) + * Iterate Spaces admin UX around room management + [\#5977](https://github.com/matrix-org/matrix-react-sdk/pull/5977) + * Guard all isSpaceRoom calls behind the labs flag + [\#5979](https://github.com/matrix-org/matrix-react-sdk/pull/5979) + * Bump lodash from 4.17.20 to 4.17.21 + [\#5986](https://github.com/matrix-org/matrix-react-sdk/pull/5986) + * Bump lodash from 4.17.19 to 4.17.21 in /test/end-to-end-tests + [\#5987](https://github.com/matrix-org/matrix-react-sdk/pull/5987) + * Bump ua-parser-js from 0.7.23 to 0.7.28 + [\#5984](https://github.com/matrix-org/matrix-react-sdk/pull/5984) + * Update visual style of plain files in the timeline + [\#5971](https://github.com/matrix-org/matrix-react-sdk/pull/5971) + * Support for multiple streams (not MSC3077) + [\#5833](https://github.com/matrix-org/matrix-react-sdk/pull/5833) + * Update space ordering behaviour to match updates in MSC + [\#5963](https://github.com/matrix-org/matrix-react-sdk/pull/5963) + * Improve performance of search all spaces and space switching + [\#5976](https://github.com/matrix-org/matrix-react-sdk/pull/5976) + * Update colours and sizing for voice messages + [\#5970](https://github.com/matrix-org/matrix-react-sdk/pull/5970) + * Update link to Android SDK + [\#5973](https://github.com/matrix-org/matrix-react-sdk/pull/5973) + * Add cleanup functions for image view + [\#5962](https://github.com/matrix-org/matrix-react-sdk/pull/5962) + * Add a note about sharing your IP in P2P calls + [\#5961](https://github.com/matrix-org/matrix-react-sdk/pull/5961) + * Only aggregate DM notifications on the Space Panel in the Home Space + [\#5968](https://github.com/matrix-org/matrix-react-sdk/pull/5968) + * Add retry mechanism and progress bar to add existing to space dialog + [\#5975](https://github.com/matrix-org/matrix-react-sdk/pull/5975) + * Warn on access token reveal + [\#5755](https://github.com/matrix-org/matrix-react-sdk/pull/5755) + * Fix newly joined room appearing under the wrong space + [\#5945](https://github.com/matrix-org/matrix-react-sdk/pull/5945) + * Early rendering for voice messages in the timeline + [\#5955](https://github.com/matrix-org/matrix-react-sdk/pull/5955) + * Calculate the real waveform in the Playback class for voice messages + [\#5956](https://github.com/matrix-org/matrix-react-sdk/pull/5956) + * Don't recurse on arrayFastResample + [\#5957](https://github.com/matrix-org/matrix-react-sdk/pull/5957) + * Support a dark theme for voice messages + [\#5958](https://github.com/matrix-org/matrix-react-sdk/pull/5958) + * Handle no/blocked microphones in voice messages + [\#5959](https://github.com/matrix-org/matrix-react-sdk/pull/5959) + Changes in [3.20.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.20.0) (2021-05-10) ===================================================================================================== [Full Changelog](https://github.com/matrix-org/matrix-react-sdk/compare/v3.20.0-rc.1...v3.20.0) From 392505e7a1447a1bf1c5fd7acbc5eed0528fce68 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 11 May 2021 16:36:53 +0100 Subject: [PATCH 0361/1449] v3.21.0-rc.1 --- package.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 4f6de8ce5c..a7fd78b903 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "3.20.0", + "version": "3.21.0-rc.1", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { @@ -25,7 +25,7 @@ "bin": { "reskindex": "scripts/reskindex.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", @@ -197,5 +197,6 @@ "coverageReporters": [ "text" ] - } + }, + "typings": "./lib/index.d.ts" } From 7de626824eb3ce3a6fdad8d1dbc76b15e2f5fb08 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 11 May 2021 17:01:31 +0100 Subject: [PATCH 0362/1449] Sprinkle some more feedback prompts in the spaces beta --- res/css/structures/_SpaceRoomView.scss | 69 ++++++++++++++++++- .../structures/SpaceRoomDirectory.tsx | 2 +- src/components/structures/SpaceRoomView.tsx | 29 ++++++++ src/components/views/beta/BetaCard.tsx | 4 +- .../dialogs/AddExistingToSpaceDialog.tsx | 2 + .../views/dialogs/SpaceSettingsDialog.tsx | 3 + .../views/spaces/SpaceCreateMenu.tsx | 3 + src/i18n/strings/en_EN.json | 3 +- 8 files changed, 109 insertions(+), 6 deletions(-) diff --git a/res/css/structures/_SpaceRoomView.scss b/res/css/structures/_SpaceRoomView.scss index c4b3f9a8d3..3f8a2c5d58 100644 --- a/res/css/structures/_SpaceRoomView.scss +++ b/res/css/structures/_SpaceRoomView.scss @@ -93,6 +93,10 @@ $SpaceRoomViewInnerWidth: 428px; } } + &:not(.mx_SpaceRoomView_landing) .mx_SpaceFeedbackPrompt { + width: $SpaceRoomViewInnerWidth; + } + .mx_SpaceRoomView_buttons { display: block; margin-top: 44px; @@ -338,7 +342,7 @@ $SpaceRoomViewInnerWidth: 428px; } .mx_SpaceRoomView_privateScope { - .mx_AccessibleButton { + > .mx_AccessibleButton { @mixin SpacePillButton; } @@ -450,3 +454,66 @@ $SpaceRoomViewInnerWidth: 428px; } } } + +.mx_SpaceFeedbackPrompt { + margin-top: 18px; + margin-bottom: 12px; + + > hr { + border: none; + border-top: 1px solid $input-border-color; + margin-bottom: 12px; + } + + > div { + display: flex; + flex-direction: row; + font-size: $font-15px; + line-height: $font-24px; + + > span { + color: $secondary-fg-color; + position: relative; + padding-left: 32px; + font-size: inherit; + line-height: inherit; + margin-right: auto; + + &::before { + content: ''; + position: absolute; + left: 0; + top: 2px; + height: 20px; + width: 20px; + background-color: $secondary-fg-color; + mask-repeat: no-repeat; + mask-size: contain; + mask-image: url('$(res)/img/element-icons/room/room-summary.svg'); + mask-position: center; + } + } + + .mx_AccessibleButton_kind_link { + color: $accent-color-alt; + position: relative; + padding: 0 0 0 24px; + margin-left: 8px; + font-size: inherit; + line-height: inherit; + + &::before { + content: ''; + position: absolute; + left: 0; + height: 16px; + width: 16px; + background-color: $accent-color-alt; + mask-repeat: no-repeat; + mask-size: contain; + mask-image: url('$(res)/img/element-icons/chat-bubbles.svg'); + mask-position: center; + } + } + } +} diff --git a/src/components/structures/SpaceRoomDirectory.tsx b/src/components/structures/SpaceRoomDirectory.tsx index 74415cc58f..205f261293 100644 --- a/src/components/structures/SpaceRoomDirectory.tsx +++ b/src/components/structures/SpaceRoomDirectory.tsx @@ -574,7 +574,7 @@ export const SpaceHierarchy: React.FC = ({ return <> void }) => { + if (!SdkConfig.get().bug_report_endpoint_url) return null; + + return
    +
    +
    + { _t("Spaces are a beta feature.") } + { + if (onClick) onClick(); + Modal.createTrackedDialog("Beta Feedback", "feature_spaces", BetaFeedbackDialog, { + featureId: "feature_spaces", + }); + }}> + { _t("Feedback") } + +
    +
    ; +}; + const RoomMemberCount = ({ room, children }) => { const members = useRoomMembers(room); const count = members.length; @@ -398,6 +421,7 @@ const SpaceLanding = ({ space }) => {
    +
    { value={buttonLabel} />
    +
    ; }; @@ -555,6 +580,7 @@ const SpaceAddExistingRooms = ({ space, onFinished }) => { { buttonLabel }
    +
    ; }; @@ -574,6 +600,7 @@ const SpaceSetupPublicShare = ({ justCreatedOpts, space, onFinished }) => { { _t("Go to my first room") }
    +
    ; }; @@ -600,6 +627,7 @@ const SpaceSetupPrivateScope = ({ space, justCreatedOpts, onFinished }) => {

    { _t("Me and my teammates") }

    { _t("A private space for you and your teammates") }
    +
    ; }; @@ -721,6 +749,7 @@ const SpaceSetupPrivateInvite = ({ space, onFinished }) => { value={buttonLabel} />
    +
    ; }; diff --git a/src/components/views/beta/BetaCard.tsx b/src/components/views/beta/BetaCard.tsx index c12b05d119..821c448f4f 100644 --- a/src/components/views/beta/BetaCard.tsx +++ b/src/components/views/beta/BetaCard.tsx @@ -73,9 +73,7 @@ const BetaCard = ({ title: titleOverride, featureId }: IProps) => { if (value && feedbackLabel && feedbackSubheading && SdkConfig.get().bug_report_endpoint_url) { feedbackButton = { - Modal.createTrackedDialog("Beta Feedback", featureId, BetaFeedbackDialog, { - featureId, - }); + Modal.createTrackedDialog("Beta Feedback", featureId, BetaFeedbackDialog, { featureId }); }} kind="primary" > diff --git a/src/components/views/dialogs/AddExistingToSpaceDialog.tsx b/src/components/views/dialogs/AddExistingToSpaceDialog.tsx index ed7ae613bd..8ac68e99b7 100644 --- a/src/components/views/dialogs/AddExistingToSpaceDialog.tsx +++ b/src/components/views/dialogs/AddExistingToSpaceDialog.tsx @@ -36,6 +36,7 @@ import StyledCheckbox from "../elements/StyledCheckbox"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; import {sortRooms} from "../../../stores/room-list/algorithms/tag-sorting/RecentAlgorithm"; import ProgressBar from "../elements/ProgressBar"; +import {SpaceFeedbackPrompt} from "../../structures/SpaceRoomView"; interface IProps extends IDialogProps { matrixClient: MatrixClient; @@ -307,6 +308,7 @@ const AddExistingToSpaceDialog: React.FC = ({ matrixClient: cli, space,
    { footer }
    + onFinished(false)} /> ; }; diff --git a/src/components/views/dialogs/SpaceSettingsDialog.tsx b/src/components/views/dialogs/SpaceSettingsDialog.tsx index 83f5d7141b..dfee5d63e3 100644 --- a/src/components/views/dialogs/SpaceSettingsDialog.tsx +++ b/src/components/views/dialogs/SpaceSettingsDialog.tsx @@ -32,6 +32,7 @@ import Modal from "../../../Modal"; import defaultDispatcher from "../../../dispatcher/dispatcher"; import {allSettled} from "../../../utils/promise"; import {useDispatcher} from "../../../hooks/useDispatcher"; +import {SpaceFeedbackPrompt} from "../../structures/SpaceRoomView"; interface IProps extends IDialogProps { matrixClient: MatrixClient; @@ -111,6 +112,8 @@ const SpaceSettingsDialog: React.FC = ({ matrixClient: cli, space, onFin { error &&
    { error }
    } + onFinished(false)} /> + { return ( @@ -152,6 +153,8 @@ const SpaceCreateMenu = ({ onFinished }) => { />

    { _t("You can change this later") }

    + + ; } else { body = diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 0f1e8c8fbd..96cc245c7a 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2682,9 +2682,10 @@ "Mark as suggested": "Mark as suggested", "No results found": "No results found", "You may want to try a different search or check for typos.": "You may want to try a different search or check for typos.", - "Search names and description": "Search names and description", + "Search names and descriptions": "Search names and descriptions", "If you can't find the room you're looking for, ask for an invite or create a new room.": "If you can't find the room you're looking for, ask for an invite or create a new room.", "Create room": "Create room", + "Spaces are a beta feature.": "Spaces are a beta feature.", "Public space": "Public space", "Private space": "Private space", " invites you": " invites you", From b1cb2b1d9320af148aa22fb15e126d2fddf421b5 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 11 May 2021 10:19:09 -0600 Subject: [PATCH 0363/1449] Fix bad merge --- src/voice/Playback.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/voice/Playback.ts b/src/voice/Playback.ts index a9fcdf712a..5488ed6b84 100644 --- a/src/voice/Playback.ts +++ b/src/voice/Playback.ts @@ -16,7 +16,7 @@ limitations under the License. import EventEmitter from "events"; import {UPDATE_EVENT} from "../stores/AsyncStore"; -import {arrayRescale, arraySeed, arraySmoothingResample} from "../utils/arrays"; +import {arrayFastResample, arrayRescale, arraySeed, arraySmoothingResample} from "../utils/arrays"; import {SimpleObservable} from "matrix-widget-api"; import {IDestroyable} from "../utils/IDestroyable"; import {PlaybackClock} from "./PlaybackClock"; From 7396ce76e559bb4c3849d163847de708f31a7a92 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 11 May 2021 17:30:33 +0100 Subject: [PATCH 0364/1449] Tweak the feedbacks a tad --- res/css/_components.scss | 1 + res/css/structures/_SpaceRoomView.scss | 13 +++++- .../views/dialogs/_BetaFeedbackDialog.scss | 30 ++++++++++++ .../views/dialogs/BetaFeedbackDialog.tsx | 46 +++++++++++++++++-- src/i18n/strings/en_EN.json | 10 ++-- src/rageshake/submit-rageshake.ts | 4 +- 6 files changed, 93 insertions(+), 11 deletions(-) create mode 100644 res/css/views/dialogs/_BetaFeedbackDialog.scss diff --git a/res/css/_components.scss b/res/css/_components.scss index e6c55c0250..d8e5247f9d 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -63,6 +63,7 @@ @import "./views/dialogs/_AddExistingToSpaceDialog.scss"; @import "./views/dialogs/_AddressPickerDialog.scss"; @import "./views/dialogs/_Analytics.scss"; +@import "./views/dialogs/_BetaFeedbackDialog.scss"; @import "./views/dialogs/_BugReportDialog.scss"; @import "./views/dialogs/_ChangelogDialog.scss"; @import "./views/dialogs/_ChatCreateOrReuseChatDialog.scss"; diff --git a/res/css/structures/_SpaceRoomView.scss b/res/css/structures/_SpaceRoomView.scss index 3f8a2c5d58..503fe72414 100644 --- a/res/css/structures/_SpaceRoomView.scss +++ b/res/css/structures/_SpaceRoomView.scss @@ -339,6 +339,15 @@ $SpaceRoomViewInnerWidth: 428px; .mx_SearchBox { margin: 0 0 20px; } + + .mx_SpaceFeedbackPrompt { + margin-bottom: 16px; + + // hide the HR as we have our own + & + hr { + display: none; + } + } } .mx_SpaceRoomView_privateScope { @@ -495,7 +504,7 @@ $SpaceRoomViewInnerWidth: 428px; } .mx_AccessibleButton_kind_link { - color: $accent-color-alt; + color: $accent-color; position: relative; padding: 0 0 0 24px; margin-left: 8px; @@ -508,7 +517,7 @@ $SpaceRoomViewInnerWidth: 428px; left: 0; height: 16px; width: 16px; - background-color: $accent-color-alt; + background-color: $accent-color; mask-repeat: no-repeat; mask-size: contain; mask-image: url('$(res)/img/element-icons/chat-bubbles.svg'); diff --git a/res/css/views/dialogs/_BetaFeedbackDialog.scss b/res/css/views/dialogs/_BetaFeedbackDialog.scss new file mode 100644 index 0000000000..fe3df01986 --- /dev/null +++ b/res/css/views/dialogs/_BetaFeedbackDialog.scss @@ -0,0 +1,30 @@ +/* +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. +*/ + +.mx_BetaFeedbackDialog { + .mx_BetaFeedbackDialog_subheading { + color: $secondary-fg-color; + font-size: $font-14px; + line-height: $font-20px; + margin-bottom: 24px; + } + + .mx_AccessibleButton_kind_link { + padding: 0; + font-size: inherit; + line-height: inherit; + } +} diff --git a/src/components/views/dialogs/BetaFeedbackDialog.tsx b/src/components/views/dialogs/BetaFeedbackDialog.tsx index 702adc8fb1..119799c609 100644 --- a/src/components/views/dialogs/BetaFeedbackDialog.tsx +++ b/src/components/views/dialogs/BetaFeedbackDialog.tsx @@ -23,6 +23,13 @@ import SdkConfig from "../../../SdkConfig"; import {IDialogProps} from "./IDialogProps"; import SettingsStore from "../../../settings/SettingsStore"; import {submitFeedback} from "../../../rageshake/submit-rageshake"; +import StyledCheckbox from "../elements/StyledCheckbox"; +import Modal from "../../../Modal"; +import InfoDialog from "./InfoDialog"; +import AccessibleButton from "../elements/AccessibleButton"; +import defaultDispatcher from "../../../dispatcher/dispatcher"; +import {Action} from "../../../dispatcher/actions"; +import {USER_LABS_TAB} from "./UserSettingsDialog"; interface IProps extends IDialogProps { featureId: string; @@ -32,25 +39,47 @@ const BetaFeedbackDialog: React.FC = ({featureId, onFinished}) => { const info = SettingsStore.getBetaInfo(featureId); const [comment, setComment] = useState(""); + const [canContact, setCanContact] = useState(false); const sendFeedback = async (ok: boolean) => { if (!ok) return onFinished(false); - submitFeedback(SdkConfig.get().bug_report_endpoint_url, info.feedbackLabel, comment); + submitFeedback(SdkConfig.get().bug_report_endpoint_url, info.feedbackLabel, comment, canContact); onFinished(true); + + Modal.createTrackedDialog("Beta Dialog Sent", featureId, InfoDialog, { + title: _t("Beta feedback"), + description: _t("Thank you for your feedback, we really appreciate it."), + button: _t("Done"), + hasCloseButton: false, + fixedWidth: false, + }); }; return ( - { _t(info.feedbackSubheading) } +
    + { _t(info.feedbackSubheading) } + + { _t("Your platform and username will be noted to help us use your feedback as much as we can.")} + + { + onFinished(false); + defaultDispatcher.dispatch({ + action: Action.ViewUserSettings, + initialTabId: USER_LABS_TAB, + }); + }}> + { _t("To leave the beta, visit your settings.") } + +
    = ({featureId, onFinished}) => { setComment(ev.target.value); }} /> + + setCanContact((e.target as HTMLInputElement).checked)} + > + { _t("You may contact me if you have any follow up questions") } +
    } button={_t("Send feedback")} buttonDisabled={!comment} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 96cc245c7a..b5d402132e 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2065,8 +2065,11 @@ "Invite anyway": "Invite anyway", "Close dialog": "Close dialog", "Beta feedback": "Beta feedback", - "Add comment": "Add comment", - "Comment": "Comment", + "Thank you for your feedback, we really appreciate it.": "Thank you for your feedback, we really appreciate it.", + "Your platform and username will be noted to help us use your feedback as much as we can.": "Your platform and username will be noted to help us use your feedback as much as we can.", + "To leave the beta, visit your settings.": "To leave the beta, visit your settings.", + "Feedback": "Feedback", + "You may contact me if you have any follow up questions": "You may contact me if you have any follow up questions", "Send feedback": "Send feedback", "Please tell us what went wrong or, better, create a GitHub issue that describes the problem.": "Please tell us what went wrong or, better, create a GitHub issue that describes the problem.", "Preparing to send logs": "Preparing to send logs", @@ -2194,9 +2197,10 @@ "Rate %(brand)s": "Rate %(brand)s", "Tell us below how you feel about %(brand)s so far.": "Tell us below how you feel about %(brand)s so far.", "Please go into as much detail as you like, so we can track down the problem.": "Please go into as much detail as you like, so we can track down the problem.", + "Add comment": "Add comment", + "Comment": "Comment", "There are two ways you can provide feedback and help us improve %(brand)s.": "There are two ways you can provide feedback and help us improve %(brand)s.", "PRO TIP: If you start a bug, please submit debug logs to help us track down the problem.": "PRO TIP: If you start a bug, please submit debug logs to help us track down the problem.", - "Feedback": "Feedback", "Report a bug": "Report a bug", "Please view existing bugs on Github first. No match? Start a new one.": "Please view existing bugs on Github first. No match? Start a new one.", "Confirm abort of host creation": "Confirm abort of host creation", diff --git a/src/rageshake/submit-rageshake.ts b/src/rageshake/submit-rageshake.ts index 9c4fe1f95b..f46dd88fba 100644 --- a/src/rageshake/submit-rageshake.ts +++ b/src/rageshake/submit-rageshake.ts @@ -269,7 +269,7 @@ function uint8ToString(buf: Buffer) { return out; } -export async function submitFeedback(endpoint: string, label: string, comment: string) { +export async function submitFeedback(endpoint: string, label: string, comment: string, canContact = false) { let version = "UNKNOWN"; try { version = await PlatformPeg.get().getAppVersion(); @@ -278,10 +278,12 @@ export async function submitFeedback(endpoint: string, label: string, comment: s const body = new FormData(); body.append("label", label); body.append("text", comment); + body.append("can_contact", canContact ? "yes" : "no"); body.append("app", "element-web"); body.append("version", version); body.append("platform", PlatformPeg.get().getHumanReadableName()); + body.append("user_id", MatrixClientPeg.get()?.getUserId()); await _submitReport(SdkConfig.get().bug_report_endpoint_url, body, () => {}); } From 262fc40afb2867004a60dd4043794fb5f0cdac24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 12 May 2021 07:12:00 +0200 Subject: [PATCH 0365/1449] Move comment to the correct place MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/spaces/SpaceTreeLevel.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/views/spaces/SpaceTreeLevel.tsx b/src/components/views/spaces/SpaceTreeLevel.tsx index f799cb02ba..f0a0605584 100644 --- a/src/components/views/spaces/SpaceTreeLevel.tsx +++ b/src/components/views/spaces/SpaceTreeLevel.tsx @@ -72,11 +72,10 @@ export class SpaceItem extends React.PureComponent { const collapsed = SpaceTreeLevelLayoutStore.instance.getSpaceCollapsedState( props.space.roomId, this.props.parents, - !props.isNested, + !props.isNested, // default to collapsed for root items ); this.state = { - // default to collapsed for root items collapsed: collapsed, contextMenuPosition: null, }; From 2c2d95560b8a28633f703dcc088584099c2f49b8 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 12 May 2021 10:05:53 +0100 Subject: [PATCH 0366/1449] Linkify topics in space room directory results --- src/components/structures/SpaceRoomDirectory.tsx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/components/structures/SpaceRoomDirectory.tsx b/src/components/structures/SpaceRoomDirectory.tsx index 205f261293..5091131d49 100644 --- a/src/components/structures/SpaceRoomDirectory.tsx +++ b/src/components/structures/SpaceRoomDirectory.tsx @@ -41,6 +41,7 @@ import TextWithTooltip from "../views/elements/TextWithTooltip"; import {useStateToggle} from "../../hooks/useStateToggle"; import {getOrder} from "../../stores/SpaceStore"; import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton"; +import {linkifyElement} from "../../HtmlUtils"; interface IHierarchyProps { space: Room; @@ -172,7 +173,16 @@ const Tile: React.FC = ({ { suggestedSection }
    -
    +
    e && linkifyElement(e)} + onClick={ev => { + // prevent clicks on links from bubbling up to the room tile + if ((ev.target as HTMLElement).tagName === "A") { + ev.stopPropagation(); + } + }} + > { description }
    From 03bd30d1259ec7a2d121e59108eababd09941fc1 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 12 May 2021 10:48:06 +0100 Subject: [PATCH 0367/1449] Fix colours used for the back button in space create menu --- res/css/views/spaces/_SpaceCreateMenu.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/res/css/views/spaces/_SpaceCreateMenu.scss b/res/css/views/spaces/_SpaceCreateMenu.scss index ef15206d22..88b9d8f693 100644 --- a/res/css/views/spaces/_SpaceCreateMenu.scss +++ b/res/css/views/spaces/_SpaceCreateMenu.scss @@ -67,7 +67,7 @@ $spacePanelWidth: 71px; width: 28px; height: 28px; position: relative; - background-color: $theme-button-bg-color; + background-color: $roomlist-button-bg-color; border-radius: 14px; margin-bottom: 12px; @@ -78,7 +78,7 @@ $spacePanelWidth: 71px; width: 28px; top: 0; left: 0; - background-color: $muted-fg-color; + background-color: $tertiary-fg-color; transform: rotate(90deg); mask-repeat: no-repeat; mask-position: 2px 3px; From bd2917aa690cc639ed269f5112143372dbf241cd Mon Sep 17 00:00:00 2001 From: Germain Date: Wed, 12 May 2021 12:18:56 +0100 Subject: [PATCH 0368/1449] Add a limit option for autocomplete results (#6016) --- src/autocomplete/AutocompleteProvider.tsx | 7 ++++++- src/autocomplete/Autocompleter.ts | 15 ++++++++++++--- src/autocomplete/CommandProvider.tsx | 10 ++++++++-- src/autocomplete/CommunityProvider.tsx | 9 +++++++-- src/autocomplete/DuckDuckGoProvider.tsx | 10 ++++++++-- src/autocomplete/EmojiProvider.tsx | 9 +++++++-- src/autocomplete/NotifProvider.tsx | 7 ++++++- src/autocomplete/QueryMatcher.ts | 7 +++++-- src/autocomplete/RoomProvider.tsx | 9 +++++++-- src/autocomplete/UserProvider.tsx | 9 +++++++-- src/components/views/rooms/Autocomplete.tsx | 3 ++- 11 files changed, 75 insertions(+), 20 deletions(-) diff --git a/src/autocomplete/AutocompleteProvider.tsx b/src/autocomplete/AutocompleteProvider.tsx index a40ce7144d..2242fec914 100644 --- a/src/autocomplete/AutocompleteProvider.tsx +++ b/src/autocomplete/AutocompleteProvider.tsx @@ -93,7 +93,12 @@ export default class AutocompleteProvider { }; } - async getCompletions(query: string, selection: ISelectionRange, force = false): Promise { + async getCompletions( + query: string, + selection: ISelectionRange, + force = false, + limit = -1, + ): Promise { return []; } diff --git a/src/autocomplete/Autocompleter.ts b/src/autocomplete/Autocompleter.ts index 2615736e09..8618fc3a77 100644 --- a/src/autocomplete/Autocompleter.ts +++ b/src/autocomplete/Autocompleter.ts @@ -82,15 +82,24 @@ export default class Autocompleter { }); } - async getCompletions(query: string, selection: ISelectionRange, force = false): Promise { + async getCompletions( + query: string, + selection: ISelectionRange, + force = false, + limit = -1, + ): Promise { /* Note: This intentionally waits for all providers to return, otherwise, we run into a condition where new completions are displayed while the user is interacting with the list, which makes it difficult to predict whether an action will actually do what is intended */ // list of results from each provider, each being a list of completions or null if it times out - const completionsList: ICompletion[][] = await Promise.all(this.providers.map(provider => { - return timeout(provider.getCompletions(query, selection, force), null, PROVIDER_COMPLETION_TIMEOUT); + const completionsList: ICompletion[][] = await Promise.all(this.providers.map(async provider => { + return await timeout( + provider.getCompletions(query, selection, force, limit), + null, + PROVIDER_COMPLETION_TIMEOUT, + ); })); // map then filter to maintain the index for the map-operation, for this.providers to line up diff --git a/src/autocomplete/CommandProvider.tsx b/src/autocomplete/CommandProvider.tsx index c2d1290e08..9de25c0d84 100644 --- a/src/autocomplete/CommandProvider.tsx +++ b/src/autocomplete/CommandProvider.tsx @@ -38,7 +38,12 @@ export default class CommandProvider extends AutocompleteProvider { }); } - async getCompletions(query: string, selection: ISelectionRange, force?: boolean): Promise { + async getCompletions( + query: string, + selection: ISelectionRange, + force?: boolean, + limit = -1, + ): Promise { const {command, range} = this.getCurrentCommand(query, selection); if (!command) return []; @@ -55,10 +60,11 @@ export default class CommandProvider extends AutocompleteProvider { } else { if (query === '/') { // If they have just entered `/` show everything + // We exclude the limit on purpose to have a comprehensive list matches = Commands; } else { // otherwise fuzzy match against all of the fields - matches = this.matcher.match(command[1]); + matches = this.matcher.match(command[1], limit); } } diff --git a/src/autocomplete/CommunityProvider.tsx b/src/autocomplete/CommunityProvider.tsx index b7a4e0960e..c9358b0c61 100644 --- a/src/autocomplete/CommunityProvider.tsx +++ b/src/autocomplete/CommunityProvider.tsx @@ -50,7 +50,12 @@ export default class CommunityProvider extends AutocompleteProvider { }); } - async getCompletions(query: string, selection: ISelectionRange, force = false): Promise { + async getCompletions( + query: string, + selection: ISelectionRange, + force = false, + limit = -1, + ): Promise { const BaseAvatar = sdk.getComponent('views.avatars.BaseAvatar'); // Disable autocompletions when composing commands because of various issues @@ -81,7 +86,7 @@ export default class CommunityProvider extends AutocompleteProvider { this.matcher.setObjects(groups); const matchedString = command[0]; - completions = this.matcher.match(matchedString); + completions = this.matcher.match(matchedString, limit); completions = sortBy(completions, [ (c) => score(matchedString, c.groupId), (c) => c.groupId.length, diff --git a/src/autocomplete/DuckDuckGoProvider.tsx b/src/autocomplete/DuckDuckGoProvider.tsx index e63f7255dc..3ef9cc2f6f 100644 --- a/src/autocomplete/DuckDuckGoProvider.tsx +++ b/src/autocomplete/DuckDuckGoProvider.tsx @@ -36,7 +36,12 @@ export default class DuckDuckGoProvider extends AutocompleteProvider { + `&format=json&no_redirect=1&no_html=1&t=${encodeURIComponent(REFERRER)}`; } - async getCompletions(query: string, selection: ISelectionRange, force= false): Promise { + async getCompletions( + query: string, + selection: ISelectionRange, + force = false, + limit = -1, + ): Promise { const {command, range} = this.getCurrentCommand(query, selection); if (!query || !command) { return []; @@ -46,7 +51,8 @@ export default class DuckDuckGoProvider extends AutocompleteProvider { method: 'GET', }); const json = await response.json(); - const results = json.Results.map((result) => { + const maxLength = limit > -1 ? limit : json.Results.length; + const results = json.Results.slice(0, maxLength).map((result) => { return { completion: result.Text, component: ( diff --git a/src/autocomplete/EmojiProvider.tsx b/src/autocomplete/EmojiProvider.tsx index 705474f8d0..b7c4a5120a 100644 --- a/src/autocomplete/EmojiProvider.tsx +++ b/src/autocomplete/EmojiProvider.tsx @@ -84,7 +84,12 @@ export default class EmojiProvider extends AutocompleteProvider { }); } - async getCompletions(query: string, selection: ISelectionRange, force?: boolean): Promise { + async getCompletions( + query: string, + selection: ISelectionRange, + force?: boolean, + limit = -1, + ): Promise { if (!SettingsStore.getValue("MessageComposerInput.suggestEmoji")) { return []; // don't give any suggestions if the user doesn't want them } @@ -93,7 +98,7 @@ export default class EmojiProvider extends AutocompleteProvider { const {command, range} = this.getCurrentCommand(query, selection); if (command) { const matchedString = command[0]; - completions = this.matcher.match(matchedString); + completions = this.matcher.match(matchedString, limit); // Do second match with shouldMatchWordsOnly in order to match against 'name' completions = completions.concat(this.nameMatcher.match(matchedString)); diff --git a/src/autocomplete/NotifProvider.tsx b/src/autocomplete/NotifProvider.tsx index ef1823c0ca..0bc7ead097 100644 --- a/src/autocomplete/NotifProvider.tsx +++ b/src/autocomplete/NotifProvider.tsx @@ -33,7 +33,12 @@ export default class NotifProvider extends AutocompleteProvider { this.room = room; } - async getCompletions(query: string, selection: ISelectionRange, force= false): Promise { + async getCompletions( + query: string, + selection: ISelectionRange, + force = false, + limit = -1, + ): Promise { const RoomAvatar = sdk.getComponent('views.avatars.RoomAvatar'); const client = MatrixClientPeg.get(); diff --git a/src/autocomplete/QueryMatcher.ts b/src/autocomplete/QueryMatcher.ts index 91fbea4d6a..ea6e0882fd 100644 --- a/src/autocomplete/QueryMatcher.ts +++ b/src/autocomplete/QueryMatcher.ts @@ -87,7 +87,7 @@ export default class QueryMatcher { } } - match(query: string): T[] { + match(query: string, limit = -1): T[] { query = this.processQuery(query); if (this._options.shouldMatchWordsOnly) { query = query.replace(/[^\w]/g, ''); @@ -129,7 +129,10 @@ export default class QueryMatcher { }); // Now map the keys to the result objects. Also remove any duplicates. - return uniq(matches.map((match) => match.object)); + const dedupped = uniq(matches.map((match) => match.object)); + const maxLength = limit === -1 ? dedupped.length : limit; + + return dedupped.slice(0, maxLength); } private processQuery(query: string): string { diff --git a/src/autocomplete/RoomProvider.tsx b/src/autocomplete/RoomProvider.tsx index 74deacf61f..249c069080 100644 --- a/src/autocomplete/RoomProvider.tsx +++ b/src/autocomplete/RoomProvider.tsx @@ -58,7 +58,12 @@ export default class RoomProvider extends AutocompleteProvider { }); } - async getCompletions(query: string, selection: ISelectionRange, force = false): Promise { + async getCompletions( + query: string, + selection: ISelectionRange, + force = false, + limit = -1, + ): Promise { const RoomAvatar = sdk.getComponent('views.avatars.RoomAvatar'); const client = MatrixClientPeg.get(); @@ -90,7 +95,7 @@ export default class RoomProvider extends AutocompleteProvider { this.matcher.setObjects(matcherObjects); const matchedString = command[0]; - completions = this.matcher.match(matchedString); + completions = this.matcher.match(matchedString, limit); completions = sortBy(completions, [ (c) => score(matchedString, c.displayedAlias), (c) => c.displayedAlias.length, diff --git a/src/autocomplete/UserProvider.tsx b/src/autocomplete/UserProvider.tsx index 5f0cfc2df1..3cf43d0b84 100644 --- a/src/autocomplete/UserProvider.tsx +++ b/src/autocomplete/UserProvider.tsx @@ -102,7 +102,12 @@ export default class UserProvider extends AutocompleteProvider { this.users = null; }; - async getCompletions(rawQuery: string, selection: ISelectionRange, force = false): Promise { + async getCompletions( + rawQuery: string, + selection: ISelectionRange, + force = false, + limit = -1, + ): Promise { const MemberAvatar = sdk.getComponent('views.avatars.MemberAvatar'); // lazy-load user list into matcher @@ -118,7 +123,7 @@ export default class UserProvider extends AutocompleteProvider { if (fullMatch && fullMatch !== '@') { // Don't include the '@' in our search query - it's only used as a way to trigger completion const query = fullMatch.startsWith('@') ? fullMatch.substring(1) : fullMatch; - completions = this.matcher.match(query).map((user) => { + completions = this.matcher.match(query, limit).map((user) => { const displayName = (user.name || user.userId || ''); return { // Length of completion should equal length of text in decorator. draft-js diff --git a/src/components/views/rooms/Autocomplete.tsx b/src/components/views/rooms/Autocomplete.tsx index a4dcba11a3..7054741da4 100644 --- a/src/components/views/rooms/Autocomplete.tsx +++ b/src/components/views/rooms/Autocomplete.tsx @@ -26,6 +26,7 @@ import Autocompleter from '../../../autocomplete/Autocompleter'; import {replaceableComponent} from "../../../utils/replaceableComponent"; const COMPOSER_SELECTED = 0; +const MAX_PROVIDER_MATCHES = 20; export const generateCompletionDomId = (number) => `mx_Autocomplete_Completion_${number}`; @@ -136,7 +137,7 @@ export default class Autocomplete extends React.PureComponent { processQuery(query: string, selection: ISelectionRange) { return this.autocompleter.getCompletions( - query, selection, this.state.forceComplete, + query, selection, this.state.forceComplete, MAX_PROVIDER_MATCHES, ).then((completions) => { // Only ever process the completions for the most recent query being processed if (query !== this.queryRequested) { From 23869cdaa73a8bf47124aa67554820fbec502dbf Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Wed, 12 May 2021 12:32:39 +0100 Subject: [PATCH 0369/1449] Add missing space on beta feedback dialog --- src/components/views/dialogs/BetaFeedbackDialog.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/dialogs/BetaFeedbackDialog.tsx b/src/components/views/dialogs/BetaFeedbackDialog.tsx index 119799c609..6619f11b33 100644 --- a/src/components/views/dialogs/BetaFeedbackDialog.tsx +++ b/src/components/views/dialogs/BetaFeedbackDialog.tsx @@ -63,7 +63,7 @@ const BetaFeedbackDialog: React.FC = ({featureId, onFinished}) => { description={
    { _t(info.feedbackSubheading) } - +   { _t("Your platform and username will be noted to help us use your feedback as much as we can.")} { From 0717df71c22ae9ba2cddba4cefe1394fa95e9ab9 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Wed, 12 May 2021 12:32:39 +0100 Subject: [PATCH 0370/1449] Add missing space on beta feedback dialog --- src/components/views/dialogs/BetaFeedbackDialog.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/dialogs/BetaFeedbackDialog.tsx b/src/components/views/dialogs/BetaFeedbackDialog.tsx index 119799c609..6619f11b33 100644 --- a/src/components/views/dialogs/BetaFeedbackDialog.tsx +++ b/src/components/views/dialogs/BetaFeedbackDialog.tsx @@ -63,7 +63,7 @@ const BetaFeedbackDialog: React.FC = ({featureId, onFinished}) => { description={
    { _t(info.feedbackSubheading) } - +   { _t("Your platform and username will be noted to help us use your feedback as much as we can.")} { From 2c89be312af0cd69a8504556c4f5cb692b88b302 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 12 May 2021 13:30:00 +0100 Subject: [PATCH 0371/1449] Disable space fields whilst their form is busy --- src/components/structures/SpaceRoomView.tsx | 2 ++ src/components/views/dialogs/SpaceSettingsDialog.tsx | 6 +++--- src/components/views/spaces/SpaceCreateMenu.tsx | 4 +++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx index 004fa5d98f..ed0ae1afe7 100644 --- a/src/components/structures/SpaceRoomView.tsx +++ b/src/components/structures/SpaceRoomView.tsx @@ -451,6 +451,7 @@ const SpaceSetupFirstRooms = ({ space, title, description, onFinished }) => { value={roomNames[i]} onChange={ev => setRoomName(i, ev.target.value)} autoFocus={i === 2} + disabled={busy} />; }); @@ -658,6 +659,7 @@ const SpaceSetupPrivateInvite = ({ space, onFinished }) => { ref={fieldRefs[i]} onValidate={validateEmailRules} autoFocus={i === 0} + disabled={busy} />; }); diff --git a/src/components/views/dialogs/SpaceSettingsDialog.tsx b/src/components/views/dialogs/SpaceSettingsDialog.tsx index dfee5d63e3..dc6052650a 100644 --- a/src/components/views/dialogs/SpaceSettingsDialog.tsx +++ b/src/components/views/dialogs/SpaceSettingsDialog.tsx @@ -116,13 +116,13 @@ const SpaceSettingsDialog: React.FC = ({ matrixClient: cli, space, onFin diff --git a/src/components/views/spaces/SpaceCreateMenu.tsx b/src/components/views/spaces/SpaceCreateMenu.tsx index b461e2230e..0ebf511018 100644 --- a/src/components/views/spaces/SpaceCreateMenu.tsx +++ b/src/components/views/spaces/SpaceCreateMenu.tsx @@ -178,7 +178,7 @@ const SpaceCreateMenu = ({ onFinished }) => {

    - + { onChange={ev => setName(ev.target.value)} ref={spaceNameField} onValidate={spaceNameValidator} + disabled={busy} /> { value={topic} onChange={ev => setTopic(ev.target.value)} rows={3} + disabled={busy} /> From 607ca179716ce536a011bc2d8442aa05fd3c4279 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 12 May 2021 16:11:38 +0100 Subject: [PATCH 0372/1449] Iterate beta feedback dialog --- res/css/views/dialogs/_BetaFeedbackDialog.scss | 2 +- src/components/views/dialogs/BetaFeedbackDialog.tsx | 3 ++- src/i18n/strings/en_EN.json | 3 ++- src/settings/Settings.tsx | 4 ++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/res/css/views/dialogs/_BetaFeedbackDialog.scss b/res/css/views/dialogs/_BetaFeedbackDialog.scss index fe3df01986..9f5f6b512e 100644 --- a/res/css/views/dialogs/_BetaFeedbackDialog.scss +++ b/res/css/views/dialogs/_BetaFeedbackDialog.scss @@ -16,7 +16,7 @@ limitations under the License. .mx_BetaFeedbackDialog { .mx_BetaFeedbackDialog_subheading { - color: $secondary-fg-color; + color: $primary-fg-color; font-size: $font-14px; line-height: $font-20px; margin-bottom: 24px; diff --git a/src/components/views/dialogs/BetaFeedbackDialog.tsx b/src/components/views/dialogs/BetaFeedbackDialog.tsx index 6619f11b33..1ae50dd66f 100644 --- a/src/components/views/dialogs/BetaFeedbackDialog.tsx +++ b/src/components/views/dialogs/BetaFeedbackDialog.tsx @@ -59,7 +59,7 @@ const BetaFeedbackDialog: React.FC = ({featureId, onFinished}) => { return (
    { _t(info.feedbackSubheading) } @@ -87,6 +87,7 @@ const BetaFeedbackDialog: React.FC = ({featureId, onFinished}) => { onChange={(ev) => { setComment(ev.target.value); }} + autoFocus={true} /> ; }, image: require("../../res/img/betas/spaces.png"), - feedbackSubheading: _td("You’re using an early version of Spaces, " + - "your feedback will really help inform the next versions."), + feedbackSubheading: _td("Your feedback will help make spaces better. " + + "The more detail you can go into, the better."), feedbackLabel: "spaces-feedback", }, }, From 565e41c3dfb24b3a318ee46d4e41a9dd4fe60528 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 12 May 2021 17:04:24 +0100 Subject: [PATCH 0373/1449] Extract UntrustedDeviceDialog and fix e2ee icon --- res/css/_components.scss | 1 + .../views/dialogs/_UntrustedDeviceDialog.scss | 26 ++++++++ .../views/dialogs/UntrustedDeviceDialog.js | 61 +++++++++++++++++++ src/verification.js | 35 +---------- 4 files changed, 89 insertions(+), 34 deletions(-) create mode 100644 res/css/views/dialogs/_UntrustedDeviceDialog.scss create mode 100644 src/components/views/dialogs/UntrustedDeviceDialog.js diff --git a/res/css/_components.scss b/res/css/_components.scss index d8e5247f9d..c8985cbb51 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -98,6 +98,7 @@ @import "./views/dialogs/_SpaceSettingsDialog.scss"; @import "./views/dialogs/_TabbedIntegrationManagerDialog.scss"; @import "./views/dialogs/_TermsDialog.scss"; +@import "./views/dialogs/_UntrustedDeviceDialog.scss"; @import "./views/dialogs/_UploadConfirmDialog.scss"; @import "./views/dialogs/_UserSettingsDialog.scss"; @import "./views/dialogs/_WidgetCapabilitiesPromptDialog.scss"; diff --git a/res/css/views/dialogs/_UntrustedDeviceDialog.scss b/res/css/views/dialogs/_UntrustedDeviceDialog.scss new file mode 100644 index 0000000000..0ecd9d4f71 --- /dev/null +++ b/res/css/views/dialogs/_UntrustedDeviceDialog.scss @@ -0,0 +1,26 @@ +/* +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. +*/ + +.mx_UntrustedDeviceDialog { + .mx_Dialog_title { + display: flex; + align-items: center; + + .mx_E2EIcon { + margin-left: 0; + } + } +} diff --git a/src/components/views/dialogs/UntrustedDeviceDialog.js b/src/components/views/dialogs/UntrustedDeviceDialog.js new file mode 100644 index 0000000000..11cbef39a1 --- /dev/null +++ b/src/components/views/dialogs/UntrustedDeviceDialog.js @@ -0,0 +1,61 @@ +/* +Copyright 2019, 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 React from 'react'; + +import { _t } from '../../../languageHandler'; +import * as sdk from '../../../index'; +import {MatrixClientPeg} from '../../../MatrixClientPeg'; +import E2EIcon from "../rooms/E2EIcon"; + +function UntrustedDeviceDialog(props) { + const {device, user, onFinished} = props; + const BaseDialog = sdk.getComponent("dialogs.BaseDialog"); + const AccessibleButton = sdk.getComponent("elements.AccessibleButton"); + let askToVerifyText; + let newSessionText; + + if (MatrixClientPeg.get().getUserId() === user.userId) { + newSessionText = _t("You signed in to a new session without verifying it:"); + askToVerifyText = _t("Verify your other session using one of the options below."); + } else { + newSessionText = _t("%(name)s (%(userId)s) signed in to a new session without verifying it:", + {name: user.displayName, userId: user.userId}); + askToVerifyText = _t("Ask this user to verify their session, or manually verify it below."); + } + + return + + { _t("Not Trusted")} + } + > +
    +

    {newSessionText}

    +

    {device.getDisplayName()} ({device.deviceId})

    +

    {askToVerifyText}

    +
    +
    + onFinished("legacy")}>{_t("Manually Verify by Text")} + onFinished("sas")}>{_t("Interactively verify by Emoji")} + onFinished()}>{_t("Done")} +
    +
    ; +} + +export default UntrustedDeviceDialog; diff --git a/src/verification.js b/src/verification.js index 74e3897d3a..69577384a1 100644 --- a/src/verification.js +++ b/src/verification.js @@ -18,12 +18,12 @@ import {MatrixClientPeg} from './MatrixClientPeg'; import dis from "./dispatcher/dispatcher"; import Modal from './Modal'; import * as sdk from './index'; -import { _t } from './languageHandler'; import {RightPanelPhases} from "./stores/RightPanelStorePhases"; import {findDMForUser} from './createRoom'; import {accessSecretStorage} from './SecurityManager'; import {verificationMethods} from 'matrix-js-sdk/src/crypto'; import {Action} from './dispatcher/actions'; +import UntrustedDeviceDialog from "./components/views/dialogs/UntrustedDeviceDialog"; async function enable4SIfNeeded() { const cli = MatrixClientPeg.get(); @@ -39,39 +39,6 @@ async function enable4SIfNeeded() { return true; } -function UntrustedDeviceDialog(props) { - const {device, user, onFinished} = props; - const BaseDialog = sdk.getComponent("dialogs.BaseDialog"); - const AccessibleButton = sdk.getComponent("elements.AccessibleButton"); - let askToVerifyText; - let newSessionText; - - if (MatrixClientPeg.get().getUserId() === user.userId) { - newSessionText = _t("You signed in to a new session without verifying it:"); - askToVerifyText = _t("Verify your other session using one of the options below."); - } else { - newSessionText = _t("%(name)s (%(userId)s) signed in to a new session without verifying it:", - {name: user.displayName, userId: user.userId}); - askToVerifyText = _t("Ask this user to verify their session, or manually verify it below."); - } - - return -
    -

    {newSessionText}

    -

    {device.getDisplayName()} ({device.deviceId})

    -

    {askToVerifyText}

    -
    -
    - onFinished("legacy")}>{_t("Manually Verify by Text")} - onFinished("sas")}>{_t("Interactively verify by Emoji")} - onFinished()}>{_t("Done")} -
    -
    ; -} - export async function verifyDevice(user, device) { const cli = MatrixClientPeg.get(); if (cli.isGuest()) { From 5430f44c2746faa181a9f37264bdf69b186ceaaf Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 12 May 2021 17:08:44 +0100 Subject: [PATCH 0374/1449] Convert verification and UntrustedDeviceDialog to TS --- ...iceDialog.js => UntrustedDeviceDialog.tsx} | 38 ++++++++++++------- src/components/views/right_panel/UserInfo.tsx | 2 +- src/{verification.js => verification.ts} | 25 ++++++------ 3 files changed, 40 insertions(+), 25 deletions(-) rename src/components/views/dialogs/{UntrustedDeviceDialog.js => UntrustedDeviceDialog.tsx} (67%) rename src/{verification.js => verification.ts} (83%) diff --git a/src/components/views/dialogs/UntrustedDeviceDialog.js b/src/components/views/dialogs/UntrustedDeviceDialog.tsx similarity index 67% rename from src/components/views/dialogs/UntrustedDeviceDialog.js rename to src/components/views/dialogs/UntrustedDeviceDialog.tsx index 11cbef39a1..da1492e30d 100644 --- a/src/components/views/dialogs/UntrustedDeviceDialog.js +++ b/src/components/views/dialogs/UntrustedDeviceDialog.tsx @@ -1,5 +1,5 @@ /* -Copyright 2019, 2020 The Matrix.org Foundation C.I.C. +Copyright 2019, 2020, 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. @@ -14,17 +14,23 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React from 'react'; +import React from "react"; +import { User } from "matrix-js-sdk/src/models/user"; -import { _t } from '../../../languageHandler'; -import * as sdk from '../../../index'; -import {MatrixClientPeg} from '../../../MatrixClientPeg'; +import { _t } from "../../../languageHandler"; +import { MatrixClientPeg } from "../../../MatrixClientPeg"; import E2EIcon from "../rooms/E2EIcon"; +import AccessibleButton from "../elements/AccessibleButton"; +import BaseDialog from "./BaseDialog"; +import { IDialogProps } from "./IDialogProps"; +import { IDevice } from "../right_panel/UserInfo"; -function UntrustedDeviceDialog(props) { - const {device, user, onFinished} = props; - const BaseDialog = sdk.getComponent("dialogs.BaseDialog"); - const AccessibleButton = sdk.getComponent("elements.AccessibleButton"); +interface IProps extends IDialogProps { + user: User; + device: IDevice; +} + +const UntrustedDeviceDialog: React.FC = ({device, user, onFinished}) => { let askToVerifyText; let newSessionText; @@ -51,11 +57,17 @@ function UntrustedDeviceDialog(props) {

    {askToVerifyText}

    - onFinished("legacy")}>{_t("Manually Verify by Text")} - onFinished("sas")}>{_t("Interactively verify by Emoji")} - onFinished()}>{_t("Done")} + onFinished("legacy")}> + { _t("Manually Verify by Text") } + + onFinished("sas")}> + { _t("Interactively verify by Emoji") } + + onFinished(false)}> + { _t("Done") } +
    ; -} +}; export default UntrustedDeviceDialog; diff --git a/src/components/views/right_panel/UserInfo.tsx b/src/components/views/right_panel/UserInfo.tsx index faf8860cad..d5f67623a2 100644 --- a/src/components/views/right_panel/UserInfo.tsx +++ b/src/components/views/right_panel/UserInfo.tsx @@ -67,7 +67,7 @@ import RoomAvatar from "../avatars/RoomAvatar"; import RoomName from "../elements/RoomName"; import {mediaFromMxc} from "../../../customisations/Media"; -interface IDevice { +export interface IDevice { deviceId: string; ambiguous?: boolean; getDisplayName(): string; diff --git a/src/verification.js b/src/verification.ts similarity index 83% rename from src/verification.js rename to src/verification.ts index 69577384a1..acd9f6d2b2 100644 --- a/src/verification.js +++ b/src/verification.ts @@ -1,5 +1,5 @@ /* -Copyright 2019, 2020 The Matrix.org Foundation C.I.C. +Copyright 2019, 2020, 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. @@ -14,16 +14,19 @@ See the License for the specific language governing permissions and limitations under the License. */ -import {MatrixClientPeg} from './MatrixClientPeg'; +import { User } from "matrix-js-sdk/src/models/user"; + +import { MatrixClientPeg } from './MatrixClientPeg'; import dis from "./dispatcher/dispatcher"; import Modal from './Modal'; import * as sdk from './index'; -import {RightPanelPhases} from "./stores/RightPanelStorePhases"; -import {findDMForUser} from './createRoom'; -import {accessSecretStorage} from './SecurityManager'; -import {verificationMethods} from 'matrix-js-sdk/src/crypto'; -import {Action} from './dispatcher/actions'; +import { RightPanelPhases } from "./stores/RightPanelStorePhases"; +import { findDMForUser } from './createRoom'; +import { accessSecretStorage } from './SecurityManager'; +import { verificationMethods } from 'matrix-js-sdk/src/crypto'; +import { Action } from './dispatcher/actions'; import UntrustedDeviceDialog from "./components/views/dialogs/UntrustedDeviceDialog"; +import {IDevice} from "./components/views/right_panel/UserInfo"; async function enable4SIfNeeded() { const cli = MatrixClientPeg.get(); @@ -39,7 +42,7 @@ async function enable4SIfNeeded() { return true; } -export async function verifyDevice(user, device) { +export async function verifyDevice(user: User, device: IDevice) { const cli = MatrixClientPeg.get(); if (cli.isGuest()) { dis.dispatch({action: 'require_registration'}); @@ -82,7 +85,7 @@ export async function verifyDevice(user, device) { }); } -export async function legacyVerifyUser(user) { +export async function legacyVerifyUser(user: User) { const cli = MatrixClientPeg.get(); if (cli.isGuest()) { dis.dispatch({action: 'require_registration'}); @@ -102,7 +105,7 @@ export async function legacyVerifyUser(user) { }); } -export async function verifyUser(user) { +export async function verifyUser(user: User) { const cli = MatrixClientPeg.get(); if (cli.isGuest()) { dis.dispatch({action: 'require_registration'}); @@ -122,7 +125,7 @@ export async function verifyUser(user) { }); } -export function pendingVerificationRequestForUser(user) { +export function pendingVerificationRequestForUser(user: User) { const cli = MatrixClientPeg.get(); const dmRoom = findDMForUser(cli, user.userId); if (dmRoom) { From 236fcecf9cac5e97f5de92cc1458bffb6ac41878 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 12 May 2021 17:13:23 +0100 Subject: [PATCH 0375/1449] i18n --- src/i18n/strings/en_EN.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index da58680424..b977c2073a 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -578,14 +578,6 @@ "%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s", "Light": "Light", "Dark": "Dark", - "You signed in to a new session without verifying it:": "You signed in to a new session without verifying it:", - "Verify your other session using one of the options below.": "Verify your other session using one of the options below.", - "%(name)s (%(userId)s) signed in to a new session without verifying it:": "%(name)s (%(userId)s) signed in to a new session without verifying it:", - "Ask this user to verify their session, or manually verify it below.": "Ask this user to verify their session, or manually verify it below.", - "Not Trusted": "Not Trusted", - "Manually Verify by Text": "Manually Verify by Text", - "Interactively verify by Emoji": "Interactively verify by Emoji", - "Done": "Done", "%(displayName)s is typing …": "%(displayName)s is typing …", "%(names)s and %(count)s others are typing …|other": "%(names)s and %(count)s others are typing …", "%(names)s and %(count)s others are typing …|one": "%(names)s and one other is typing …", @@ -2066,6 +2058,7 @@ "Close dialog": "Close dialog", "Beta feedback": "Beta feedback", "Thank you for your feedback, we really appreciate it.": "Thank you for your feedback, we really appreciate it.", + "Done": "Done", "Your platform and username will be noted to help us use your feedback as much as we can.": "Your platform and username will be noted to help us use your feedback as much as we can.", "To leave the beta, visit your settings.": "To leave the beta, visit your settings.", "Feedback": "Feedback", @@ -2388,6 +2381,13 @@ "Summary": "Summary", "Document": "Document", "Next": "Next", + "You signed in to a new session without verifying it:": "You signed in to a new session without verifying it:", + "Verify your other session using one of the options below.": "Verify your other session using one of the options below.", + "%(name)s (%(userId)s) signed in to a new session without verifying it:": "%(name)s (%(userId)s) signed in to a new session without verifying it:", + "Ask this user to verify their session, or manually verify it below.": "Ask this user to verify their session, or manually verify it below.", + "Not Trusted": "Not Trusted", + "Manually Verify by Text": "Manually Verify by Text", + "Interactively verify by Emoji": "Interactively verify by Emoji", "Upload files (%(current)s of %(total)s)": "Upload files (%(current)s of %(total)s)", "Upload files": "Upload files", "Upload all": "Upload all", From 654ce95c743fe1151d59905d7f362c999e5a5a8d Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 12 May 2021 17:31:55 +0100 Subject: [PATCH 0376/1449] Progress from adding existing rooms to new space upon completion --- src/components/structures/SpaceRoomView.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx index ed0ae1afe7..828b2ff5fe 100644 --- a/src/components/structures/SpaceRoomView.tsx +++ b/src/components/structures/SpaceRoomView.tsx @@ -546,6 +546,7 @@ const SpaceAddExistingRooms = ({ space, onFinished }) => { } } setBusy(false); + onFinished(); }; buttonLabel = busy ? _t("Adding...") : _t("Add"); } From 3aef3b72b5a3897e6b99a5931ba09cc9b39c51ea Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 12 May 2021 14:08:32 -0600 Subject: [PATCH 0377/1449] Move language handling into languageHandler --- src/components/views/elements/LanguageDropdown.js | 9 ++------- src/languageHandler.tsx | 9 +++++++++ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/components/views/elements/LanguageDropdown.js b/src/components/views/elements/LanguageDropdown.js index b8734c5afb..9420061a74 100644 --- a/src/components/views/elements/LanguageDropdown.js +++ b/src/components/views/elements/LanguageDropdown.js @@ -58,13 +58,8 @@ export default class LanguageDropdown extends React.Component { // If no value is given, we start with the first // country selected, but our parent component // doesn't know this, therefore we do this. - const language = SettingsStore.getValue("language", null, /*excludeDefault:*/true); - if (language) { - this.props.onOptionChange(language); - } else { - const language = languageHandler.normalizeLanguageKey(languageHandler.getLanguageFromBrowser()); - this.props.onOptionChange(language); - } + const language = languageHandler.getUserLanguage(); + this.props.onOptionChange(language); } } diff --git a/src/languageHandler.tsx b/src/languageHandler.tsx index b61f57d4b3..f30e735f03 100644 --- a/src/languageHandler.tsx +++ b/src/languageHandler.tsx @@ -56,6 +56,15 @@ export function newTranslatableError(message: string) { return error; } +export function getUserLanguage(): string { + const language = SettingsStore.getValue("language", null, /*excludeDefault:*/true); + if (language) { + return language; + } else { + return normalizeLanguageKey(getLanguageFromBrowser()); + } +} + // Function which only purpose is to mark that a string is translatable // Does not actually do anything. It's helpful for automatic extraction of translatable strings export function _td(s: string): string { From f98eee318e5cb70bd51e0644c73d67741e560475 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 12 May 2021 14:10:02 -0600 Subject: [PATCH 0378/1449] Fill out fields for MSC2873 values As required by https://github.com/matrix-org/matrix-widget-api/pull/36 --- .../views/dialogs/ModalWidgetDialog.tsx | 9 +++++++-- src/identifiers.ts | 17 +++++++++++++++++ src/stores/widgets/StopGapWidget.ts | 7 ++++++- 3 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 src/identifiers.ts diff --git a/src/components/views/dialogs/ModalWidgetDialog.tsx b/src/components/views/dialogs/ModalWidgetDialog.tsx index 59eaab7b81..0c474b160c 100644 --- a/src/components/views/dialogs/ModalWidgetDialog.tsx +++ b/src/components/views/dialogs/ModalWidgetDialog.tsx @@ -1,5 +1,5 @@ /* -Copyright 2020 The Matrix.org Foundation C.I.C. +Copyright 2020, 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. @@ -16,7 +16,7 @@ limitations under the License. import * as React from 'react'; import BaseDialog from './BaseDialog'; -import { _t } from '../../../languageHandler'; +import { _t, getUserLanguage } from '../../../languageHandler'; import AccessibleButton from "../elements/AccessibleButton"; import { ClientWidgetApi, @@ -39,6 +39,8 @@ import {OwnProfileStore} from "../../../stores/OwnProfileStore"; import { arrayFastClone } from "../../../utils/arrays"; import { ElementWidget } from "../../../stores/widgets/StopGapWidget"; import {replaceableComponent} from "../../../utils/replaceableComponent"; +import {ELEMENT_CLIENT_ID} from "../../../identifiers"; +import SettingsStore from "../../../settings/SettingsStore"; interface IProps { widgetDefinition: IModalWidgetOpenRequestData; @@ -129,6 +131,9 @@ export default class ModalWidgetDialog extends React.PureComponent Date: Wed, 12 May 2021 20:26:30 +0000 Subject: [PATCH 0379/1449] Translated using Weblate (German) Currently translated at 99.3% (2939 of 2959 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/de/ --- src/i18n/strings/de_DE.json | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index a3d6027fba..23f6071efc 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -3293,5 +3293,34 @@ "Stop the recording": "Aufnahme stoppen", "%(count)s results in all spaces|one": "%(count)s Ergebnis in allen Bereichen", "%(count)s results in all spaces|other": "%(count)s Ergebnisse in allen Bereichen", - "You have no ignored users.": "Du ignorierst keine Benutzer." + "You have no ignored users.": "Du ignorierst keine Benutzer.", + "Error processing voice message": "Fehler beim Verarbeiten der Sprachnachricht", + "To join %(spaceName)s, turn on the Spaces beta": "Um %(spaceName)s beizutreten, aktiviere die Spaces Betaversion", + "To view %(spaceName)s, turn on the Spaces beta": "Um %(spaceName)s zu betreten, aktiviere die Spaces Betaversion", + "Select a room below first": "Wähle zuerst einen Raum aus", + "Communities are changing to Spaces": "Spaces ersetzen Communities", + "Join the beta": "Beta beitreten", + "Leave the beta": "Beta verlassen", + "Beta": "Beta", + "Tap for more info": "Klicke für mehr Infos", + "Spaces is a beta feature": "Spaces sind noch in der Entwicklung und möglicherweise instabil", + "Want to add a new room instead?": "Willst du einen neuen Raum hinzufügen?", + "Adding rooms... (%(progress)s out of %(count)s)|one": "Raum wird hinzugefügt...", + "Adding rooms... (%(progress)s out of %(count)s)|other": "Räume werden hinzugefügt... (%(progress)s von %(count)s)", + "You can add existing spaces to a space.": "Du kannst existierende Spaces zu einem Space hinzfügen.", + "Feeling experimental?": "Lust auf Experimente?", + "You are not allowed to view this server's rooms list": "Du darfst diese Raumliste nicht sehen", + "We didn't find a microphone on your device. Please check your settings and try again.": "Auf deinem Gerät kann kein Mikrofon gefunden werden. Bitte überprüfe deine Einstellungen und versuche es nochmal.", + "No microphone found": "Kein Mikrofon gefunden", + "We were unable to access your microphone. Please check your browser settings and try again.": "Fehler beim Zugriff auf dein Mikrofon. Überprüfe deine Browsereinstellungen und versuche es nochmal.", + "Unable to access your microphone": "Fehler beim Zugriff auf Mikrofon", + "Feeling experimental? Labs are the best way to get things early, test out new features and help shape them before they actually launch. Learn more.": "Lust auf ein paar Experimente? In den Laboreinstellungen kannst du zukünftige Features vor der Veröffentlichung testen und uns mit Feedback beim Verbessern helfen. Mehr Infos.", + "Please enter a name for the space": "Gib den Namen des Spaces ein", + "Connecting": "Verbinden", + "Allow Peer-to-Peer for 1:1 calls (if you enable this, the other party might be able to see your IP address)": "Direktverbindung für Direktanrufe aktivieren. Dadurch sieht dein Gegenüber möglicherweise deine IP-Adresse.", + "Beta available for web, desktop and Android. Some features may be unavailable on your homeserver.": "Die Betaversion ist verfügbar für Browser, Desktop und Android verfügbar. Je nach Homeserver sind einige Funktionen möglicherweise nicht verfügbar.", + "You can leave the beta any time from settings or tapping on a beta badge, like the one above.": "Du kannst die Betaversion jederzeit verlassen. Mache dies entweder in den Einstellungen oder klicke auf Beta-Icons wie dieses hier.", + "%(brand)s will reload with Spaces enabled. Communities and custom tags will be hidden.": "%(brand)s wird mit aktivierten Spaces neuladen. Danach kannst Communities und Custom Tags nicht verwenden.", + "Beta available for web, desktop and Android. Thank you for trying the beta.": "Die Betaversion ist für Browser, Desktop und Android verfügbar. Danke, dass Du die Betaversion testest.", + "%(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "%(brand)s wird mit deaktivierten Spaces neuladen und du kannst Communities und Custom Tags wieder verwenden können." } From bf9dd05b3c48f64e14d2a31762ea8c94d7ded609 Mon Sep 17 00:00:00 2001 From: iaiz Date: Wed, 12 May 2021 13:12:03 +0000 Subject: [PATCH 0380/1449] Translated using Weblate (Spanish) Currently translated at 99.8% (2956 of 2959 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/es/ --- src/i18n/strings/es.json | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/es.json b/src/i18n/strings/es.json index 3e4b7b52ce..86749e7b3f 100644 --- a/src/i18n/strings/es.json +++ b/src/i18n/strings/es.json @@ -3259,5 +3259,37 @@ "%(count)s results in all spaces|other": "%(count)s resultados en todos los espacios", "You have no ignored users.": "No has ignorado a nadie.", "Pause": "Pausar", - "Play": "Reproducir" + "Play": "Reproducir", + "This is an experimental feature. For now, new users receiving an invite will have to open the invite on to actually join.": "Esto es una funcionalidad experimental. Por ahora, los usuarios nuevos que reciban una invitación tendrán que abrirla en para unirse.", + "To view %(spaceName)s, turn on the Spaces beta": "Para ver %(spaceName)s, activa la beta de los espacios", + "To join %(spaceName)s, turn on the Spaces beta": "Para unirte a %(spaceName)s, activa la beta de los espacios", + "Select a room below first": "Selecciona una sala de abajo primero", + "Communities are changing to Spaces": "Las comunidades se van a convertir en espacios", + "Join the beta": "Unirse a la beta", + "Leave the beta": "Salir de la beta", + "Beta": "Beta", + "Tap for more info": "Pulsa para más información", + "Spaces is a beta feature": "Los espacios son una funcionalidad en beta", + "Want to add a new room instead?": "¿Quieres añadir una sala nueva en su lugar?", + "Adding rooms... (%(progress)s out of %(count)s)|other": "Añadiendo salas… (%(progress)s de %(count)s)", + "Adding rooms... (%(progress)s out of %(count)s)|one": "Añadiendo sala…", + "Not all selected were added": "No se han añadido todas las seleccionadas", + "You can add existing spaces to a space.": "Puedes añadir espacios ya existentes dentro de otros espacios.", + "Feeling experimental?": "¿Te animas a probar cosas nuevas?", + "You are not allowed to view this server's rooms list": "No tienes permiso para ver la lista de salas de este servidor", + "Error processing voice message": "Ha ocurrido un error al procesar el mensaje de voz", + "We didn't find a microphone on your device. Please check your settings and try again.": "No hemos encontrado un micrófono en tu dispositivo. Por favor, consulta tus ajustes e inténtalo de nuevo.", + "No microphone found": "No se ha encontrado ningún micrófono", + "We were unable to access your microphone. Please check your browser settings and try again.": "No hemos podido acceder a tu micrófono. Por favor, comprueba los ajustes de tu navegador e inténtalo de nuevo.", + "Unable to access your microphone": "No se ha podido acceder a tu micrófono", + "Your access token gives full access to your account. Do not share it with anyone.": "Tu token de acceso da acceso completo a tu cuenta. No lo compartas con nadie.", + "Access Token": "Token de acceso", + "Spaces are a new way to group rooms and people. To join an existing space you'll need an invite.": "Los espacios son una nueva forma de agrupar salas y personas. Para unirte a uno ya existente, necesitarás que te inviten a él.", + "Please enter a name for the space": "Por favor, elige un nombre para el espacio", + "Connecting": "Conectando", + "You can leave the beta any time from settings or tapping on a beta badge, like the one above.": "Puedes salirte de la beta en cualquier momento desde tus ajustes o pulsando sobre la etiqueta de beta, como la que hay arriba.", + "%(brand)s will reload with Spaces enabled. Communities and custom tags will be hidden.": "%(brand)s se volverá a cargar con los espacios activados. Las comunidades y etiquetas personalizadas se ocultarán.", + "Beta available for web, desktop and Android. Thank you for trying the beta.": "Versión beta disponible para web, escritorio y Android. Gracias por usar la beta.", + "%(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "%(brand)s volverá a cargarse con los espacios desactivados. Las comunidades y etiquetas personalizadas serán visibles de nuevo.", + "Spaces are a new way to group rooms and people.": "Los espacios son una nueva manera de agrupar salas y gente." } From 93ca9e689186ac5bf14f1e9bff7edb117a38d86f Mon Sep 17 00:00:00 2001 From: Thibault Martin Date: Wed, 12 May 2021 12:36:46 +0000 Subject: [PATCH 0381/1449] Translated using Weblate (French) Currently translated at 100.0% (2959 of 2959 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/fr/ --- src/i18n/strings/fr.json | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index 4aee15691b..4b36d5b7ed 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -3296,5 +3296,40 @@ "Stop the recording": "Arrêter l’enregistrement", "%(count)s results in all spaces|one": "%(count)s résultat dans tous les espaces", "%(count)s results in all spaces|other": "%(count)s résultats dans tous les espaces", - "You have no ignored users.": "Vous n’avez ignoré personne." + "You have no ignored users.": "Vous n’avez ignoré personne.", + "Your access token gives full access to your account. Do not share it with anyone.": "Votre jeton d’accès donne un accès intégral à votre compte. Ne le partagez avec personne.", + "This is an experimental feature. For now, new users receiving an invite will have to open the invite on to actually join.": "Ceci est une fonctionnalité expérimentale. Pour l’instant, les nouveaux utilisateurs recevant une invitation devront l’ouvrir sur pour poursuivre.", + "To join %(spaceName)s, turn on the Spaces beta": "Pour rejoindre %(spaceName)s, activez les espaces en bêta", + "To view %(spaceName)s, turn on the Spaces beta": "Pour visualiser %(spaceName)s, activez les espaces en bêta", + "Select a room below first": "Sélectionnez un salon ci-dessous d’abord", + "Communities are changing to Spaces": "Les communautés deviennent des espaces", + "Join the beta": "Rejoindre la bêta", + "Leave the beta": "Quitter la bêta", + "Beta": "Bêta", + "Tap for more info": "Appuyez pour plus d’information", + "Spaces is a beta feature": "Les espaces sont une fonctionnalité en bêta", + "Want to add a new room instead?": "Voulez-vous plutôt ajouter un nouveau salon ?", + "Adding rooms... (%(progress)s out of %(count)s)|one": "Ajout du salon…", + "Adding rooms... (%(progress)s out of %(count)s)|other": "Ajout des salons… (%(progress)s sur %(count)s)", + "Not all selected were added": "Toute la sélection n’a pas été ajoutée", + "You can add existing spaces to a space.": "Vous pouvez ajouter des espaces existants à un espace.", + "Feeling experimental?": "L’esprit aventurier ?", + "You are not allowed to view this server's rooms list": "Vous n’avez pas l’autorisation d’accéder à la liste des salons de ce serveur", + "Error processing voice message": "Erreur lors du traitement du message vocal", + "We didn't find a microphone on your device. Please check your settings and try again.": "Nous n’avons pas détecté de microphone sur votre appareil. Merci de vérifier vos paramètres et de réessayer.", + "No microphone found": "Aucun microphone détecté", + "We were unable to access your microphone. Please check your browser settings and try again.": "Nous n’avons pas pu accéder à votre microphone. Merci de vérifier les paramètres de votre navigateur et de réessayer.", + "Unable to access your microphone": "Impossible d’accéder à votre microphone", + "Feeling experimental? Labs are the best way to get things early, test out new features and help shape them before they actually launch. Learn more.": "L’esprit aventurier ? Les fonctionnalités expérimentales vous permettent de tester les nouveautés et aider à les polir avant leur lancement. En apprendre plus.", + "Access Token": "Jeton d’accès", + "Spaces are a new way to group rooms and people. To join an existing space you'll need an invite.": "Les espaces sont un nouveau moyen de grouper les salons et les personnes. Une invitation est nécessaire pour rejoindre un espace existant.", + "Please enter a name for the space": "Veuillez renseigner un nom pour l’espace", + "Connecting": "Connexion", + "Allow Peer-to-Peer for 1:1 calls (if you enable this, the other party might be able to see your IP address)": "Autoriser le pair-à-pair (p2p) pour les appels individuels (si activé, votre correspondant pourra voir votre adresse IP)", + "Beta available for web, desktop and Android. Some features may be unavailable on your homeserver.": "Bêta disponible pour l’application web, de bureau et Android. Certains fonctionnalités pourraient ne pas être disponibles sur votre serveur d’accueil.", + "You can leave the beta any time from settings or tapping on a beta badge, like the one above.": "Vous pouvez quitter la bêta n’importe quand à partir des paramètres, ou en appuyant sur le badge bêta comme celui ci-dessus.", + "%(brand)s will reload with Spaces enabled. Communities and custom tags will be hidden.": "%(brand)s va être redémarré avec les espaces activés. Les communautés et les étiquettes personnalisées seront cachés.", + "Beta available for web, desktop and Android. Thank you for trying the beta.": "Bêta disponible pour l’application web, de bureau et Android. Merci d’essayer la bêta.", + "%(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "%(brand)s va être redémarré avec les espaces désactivés. Les communautés et les étiquettes personnalisées seront de nouveau visibles.", + "Spaces are a new way to group rooms and people.": "Les espaces sont un nouveau moyen de regrouper les salons et les personnes." } From 61f90cdc45a7d32c9f95a6c5aeea0f893bfefee3 Mon Sep 17 00:00:00 2001 From: Szimszon Date: Tue, 11 May 2021 16:48:05 +0000 Subject: [PATCH 0382/1449] Translated using Weblate (Hungarian) Currently translated at 100.0% (2959 of 2959 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/hu/ --- src/i18n/strings/hu.json | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/hu.json b/src/i18n/strings/hu.json index 6b33ecb81e..0230ecf52a 100644 --- a/src/i18n/strings/hu.json +++ b/src/i18n/strings/hu.json @@ -3314,5 +3314,40 @@ "%(count)s results in all spaces|other": "%(count)s találat a terekben", "You have no ignored users.": "Nincs figyelmen kívül hagyott felhasználó.", "Play": "Lejátszás", - "Pause": "Szünet" + "Pause": "Szünet", + "This is an experimental feature. For now, new users receiving an invite will have to open the invite on to actually join.": "Ez egy kísérleti funkció Egyenlőre az a felhasználó aki meghívót kap a meghívóban lévő linkre kattintva tud csatlakozni.", + "To join %(spaceName)s, turn on the Spaces beta": "A csatlakozáshoz ide: %(spaceName)s először kapcsolja be a béta Tereket", + "To view %(spaceName)s, turn on the Spaces beta": "A %(spaceName)s megjelenítéséhez először kapcsolja be a béta Tereket", + "Select a room below first": "Először válasszon ki szobát alulról", + "Communities are changing to Spaces": "A közösségek Terek lesznek", + "Join the beta": "Csatlakozás béta lehetőségekhez", + "Leave the beta": "Béta kikapcsolása", + "Beta": "Béta", + "Tap for more info": "Koppints további információért", + "Spaces is a beta feature": "A terek béta állapotban van", + "Want to add a new room instead?": "Inkább új szobát adna hozzá?", + "Adding rooms... (%(progress)s out of %(count)s)|one": "Szobák hozzáadása…", + "Adding rooms... (%(progress)s out of %(count)s)|other": "Szobák hozzáadása… (%(progress)s ennyiből: %(count)s)", + "Not all selected were added": "Nem az összes kijelölt lett hozzáadva", + "You can add existing spaces to a space.": "Létező tereket adhat a térhez.", + "Feeling experimental?": "Kísérletezni szeretne?", + "You are not allowed to view this server's rooms list": "Nincs joga ennek a szervernek a szobalistáját megnézni", + "Error processing voice message": "Hiba a hangüzenet feldolgozásánál", + "We didn't find a microphone on your device. Please check your settings and try again.": "Nem található mikrofon. Ellenőrizze a beállításokat és próbálja újra.", + "No microphone found": "Nem található mikrofon", + "We were unable to access your microphone. Please check your browser settings and try again.": "Nem lehet a mikrofont használni. Ellenőrizze a böngésző beállításait és próbálja újra.", + "Unable to access your microphone": "A mikrofont nem lehet használni", + "Feeling experimental? Labs are the best way to get things early, test out new features and help shape them before they actually launch. Learn more.": "Kedve van kísérletezni? Labs az a hely ahol először hozzá lehet jutni az új dolgokhoz, kipróbálni új lehetőségeket és segíteni a fejlődésüket mielőtt mindenkihez eljut. Tudj meg többet.", + "Your access token gives full access to your account. Do not share it with anyone.": "A hozzáférési kulcs teljes elérést biztosít a fiókhoz. Soha ne ossza meg mással.", + "Access Token": "Elérési kulcs", + "Spaces are a new way to group rooms and people. To join an existing space you'll need an invite.": "A terek egy új lehetőség a szobák és emberek csoportosításához. Létező térhez meghívóval lehet csatlakozni.", + "Please enter a name for the space": "Kérem adjon meg egy nevet a térhez", + "Connecting": "Kapcsolás", + "Allow Peer-to-Peer for 1:1 calls (if you enable this, the other party might be able to see your IP address)": "Közvetlen hívás engedélyezése két fél között (ha ezt engedélyezi a másik fél láthatja az ön IP címét)", + "Beta available for web, desktop and Android. Some features may be unavailable on your homeserver.": "Béta verzió elérhető webre, asztali kliensre és Androidra. Bizonyos funkciók lehet, hogy nem elérhetők a matrix szerverén.", + "You can leave the beta any time from settings or tapping on a beta badge, like the one above.": "Bármikor elhagyhatja a béta változatot a beállításokban vagy a béta kitűzőre koppintva, mint alább.", + "%(brand)s will reload with Spaces enabled. Communities and custom tags will be hidden.": "%(brand)s a Terekkel lesz újra betöltve. A közösségek és egyedi címkék rejtve maradnak.", + "Beta available for web, desktop and Android. Thank you for trying the beta.": "Béta verzió elérhető webre, asztali kliensre és Androidra. Köszönjük, hogy kipróbálja.", + "Spaces are a new way to group rooms and people.": "Szobák és emberek csoportosításának új lehetősége a Terek használata.", + "%(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "%(brand)s a Terek nélkül lesz újra betöltve. A közösségek és egyedi címkék újra megjelennek." } From 7be918f52744ceb8dc60353683be3fe2b6099a7a Mon Sep 17 00:00:00 2001 From: jelv Date: Wed, 12 May 2021 12:29:48 +0000 Subject: [PATCH 0383/1449] Translated using Weblate (Dutch) Currently translated at 100.0% (2959 of 2959 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/nl/ --- src/i18n/strings/nl.json | 215 +++++++++++++++++++++++---------------- 1 file changed, 125 insertions(+), 90 deletions(-) diff --git a/src/i18n/strings/nl.json b/src/i18n/strings/nl.json index a30c949635..e12780ec10 100644 --- a/src/i18n/strings/nl.json +++ b/src/i18n/strings/nl.json @@ -59,7 +59,7 @@ "Close": "Sluiten", "Create new room": "Nieuw gesprek aanmaken", "Custom Server Options": "Aangepaste serverinstellingen", - "Dismiss": "Afwijzen", + "Dismiss": "Sluiten", "Error": "Fout", "Failed to forget room %(errCode)s": "Vergeten van gesprek is mislukt %(errCode)s", "Favourite": "Favoriet", @@ -177,7 +177,7 @@ "Hangup": "Ophangen", "Historical": "Historisch", "Home": "Thuis", - "Homeserver is": "Thuisserver is", + "Homeserver is": "Homeserver is", "Identity Server is": "Identiteitsserver is", "I have verified my email address": "Ik heb mijn e-mailadres geverifieerd", "Import": "Inlezen", @@ -193,7 +193,7 @@ "Invited": "Uitgenodigd", "Invites": "Uitnodigingen", "Invites user with given id to current room": "Nodigt de gebruiker met de gegeven ID uit in het huidige gesprek", - "Sign in with": "Aanmelden met", + "Sign in with": "Inloggen met", "Join as voice or video.": "Deelnemen met spraak of video.", "Join Room": "Gesprek toetreden", "%(targetName)s joined the room.": "%(targetName)s is tot het gesprek toegetreden.", @@ -240,7 +240,7 @@ "%(senderName)s sent an invitation to %(targetDisplayName)s to join the room.": "%(senderName)s heeft %(targetDisplayName)s in het gesprek uitgenodigd.", "Server error": "Serverfout", "Server may be unavailable, overloaded, or search timed out :(": "De server is misschien onbereikbaar of overbelast, of het zoeken duurde te lang :(", - "Server may be unavailable, overloaded, or you hit a bug.": "De server is misschien onbereikbaar of overbelast, of je bent een fout tegengekomen.", + "Server may be unavailable, overloaded, or you hit a bug.": "De server is misschien onbereikbaar of overbelast, of je bent een bug tegengekomen.", "Server unavailable, overloaded, or something else went wrong.": "De server is onbereikbaar of overbelast, of er is iets anders foutgegaan.", "Session ID": "Sessie-ID", "%(senderName)s kicked %(targetName)s.": "%(senderName)s heeft %(targetName)s het gesprek uitgestuurd.", @@ -250,8 +250,8 @@ "%(senderName)s set their display name to %(displayName)s.": "%(senderName)s heeft %(displayName)s als weergavenaam aangenomen.", "Show timestamps in 12 hour format (e.g. 2:30pm)": "Tijd in 12-uursformaat tonen (bv. 2:30pm)", "Signed Out": "Afgemeld", - "Sign in": "Aanmelden", - "Sign out": "Afmelden", + "Sign in": "Inloggen", + "Sign out": "Uitloggen", "%(count)s of your messages have not been sent.|other": "Enkele van uw berichten zijn niet verstuurd.", "Someone": "Iemand", "The phone number entered looks invalid": "Het ingevoerde telefoonnummer ziet er ongeldig uit", @@ -266,7 +266,7 @@ "This room": "Dit gesprek", "This room is not accessible by remote Matrix servers": "Dit gesprek is niet toegankelijk vanaf externe Matrix-servers", "To use it, just wait for autocomplete results to load and tab through them.": "Om het te gebruiken, wacht u tot de autoaanvullen resultaten geladen zijn en tabt u erdoorheen.", - "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "U heeft gepoogd een gegeven punt in de tijdslijn van dit gesprek te laden, maar u bent niet bevoegd het desbetreffende bericht te zien.", + "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "U probeert een punt in de tijdlijn van dit gesprek te laden, maar u heeft niet voldoende rechten om het bericht te lezen.", "Tried to load a specific point in this room's timeline, but was unable to find it.": "Geprobeerd een gegeven punt in de tijdslijn van dit gesprek te laden, maar kon dit niet vinden.", "Unable to add email address": "Kan e-mailadres niet toevoegen", "Unable to remove contact information": "Kan contactinformatie niet verwijderen", @@ -329,7 +329,7 @@ "Please select the destination room for this message": "Selecteer het bestemmingsgesprek voor dit bericht", "New Password": "Nieuw wachtwoord", "Start automatically after system login": "Automatisch starten na systeemlogin", - "Analytics": "Statistische gegevens", + "Analytics": "Gebruiksgegevens", "Options": "Opties", "%(brand)s collects anonymous analytics to allow us to improve the application.": "%(brand)s verzamelt anonieme analysegegevens die het mogelijk maken de toepassing te verbeteren.", "Passphrases must match": "Wachtwoorden moeten overeenkomen", @@ -628,10 +628,10 @@ "Room Notification": "Groepsgespreksmelding", "The information being sent to us to help make %(brand)s better includes:": "De informatie die naar ons wordt verstuurd om %(brand)s te verbeteren bevat:", "Where this page includes identifiable information, such as a room, user or group ID, that data is removed before being sent to the server.": "Waar deze pagina identificeerbare informatie bevat, zoals een gespreks-, gebruikers- of groeps-ID, zullen deze gegevens verwijderd worden voordat ze naar de server gestuurd worden.", - "The platform you're on": "Het platform dat je gebruikt", + "The platform you're on": "Het platform dat u gebruikt", "The version of %(brand)s": "De versie van %(brand)s", "Your language of choice": "De door jou gekozen taal", - "Which officially provided instance you are using, if any": "Welke officieel aangeboden instantie je eventueel gebruikt", + "Which officially provided instance you are using, if any": "Welke officieel aangeboden instantie u eventueel gebruikt", "Whether or not you're using the Richtext mode of the Rich Text Editor": "Of u de tekstverwerker al dan niet in de modus voor opgemaakte tekst gebruikt", "Your homeserver's URL": "De URL van je homeserver", "In reply to ": "Als antwoord op ", @@ -658,8 +658,8 @@ "Who can join this community?": "Wie kan er tot deze gemeenschap toetreden?", "Everyone": "Iedereen", "Leave this community": "Deze gemeenschap verlaten", - "If you've submitted a bug via GitHub, debug logs can help us track down the problem. Debug logs contain application usage data including your username, the IDs or aliases of the rooms or groups you have visited and the usernames of other users. They do not contain messages.": "Voor het oplossen van, via GitHub, gemelde problemen helpen foutopsporingslogboeken ons enorm. Deze bevatten wel gebruiksgegevens (waaronder uw gebruikersnaam, de ID’s of bijnamen van de gesprekken en groepen die u heeft bezocht, en de namen van andere gebruikers), maar geen berichten.", - "Submit debug logs": "Foutopsporingslogboeken indienen", + "If you've submitted a bug via GitHub, debug logs can help us track down the problem. Debug logs contain application usage data including your username, the IDs or aliases of the rooms or groups you have visited and the usernames of other users. They do not contain messages.": "Voor het oplossen van, via GitHub, gemelde bugs helpen foutenlogboeken ons enorm. Deze bevatten wel uw gebruiksgegevens, maar geen berichten. Het bevat onder meer uw gebruikersnaam, de ID’s of bijnamen van de gesprekken en groepen die u heeft bezocht en de namen van andere gebruikers.", + "Submit debug logs": "Foutenlogboek versturen", "Opens the Developer Tools dialog": "Opent het dialoogvenster met ontwikkelaarsgereedschap", "Fetching third party location failed": "Het ophalen van de locatie van de derde partij is mislukt", "I understand the risks and wish to continue": "Ik begrijp de risico’s en wil graag verdergaan", @@ -727,11 +727,11 @@ "All messages (noisy)": "Alle berichten (luid)", "Enable them now": "Deze nu inschakelen", "Toolbox": "Gereedschap", - "Collecting logs": "Logboeken worden verzameld", + "Collecting logs": "Logs worden verzameld", "You must specify an event type!": "U dient een gebeurtenistype op te geven!", "(HTTP status %(httpStatus)s)": "(HTTP-status %(httpStatus)s)", "Invite to this room": "Uitnodigen voor dit gesprek", - "Send logs": "Logboeken versturen", + "Send logs": "Logs versturen", "All messages": "Alle berichten", "Call invitation": "Oproep-uitnodiging", "Downloading update...": "Update wordt gedownload…", @@ -778,17 +778,17 @@ "Thank you!": "Bedankt!", "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "Met uw huidige browser kan de toepassing er volledig onjuist uitzien. Tevens is het mogelijk dat niet alle functies naar behoren werken. U kunt doorgaan als u het toch wilt proberen, maar bij problemen bent u volledig op uzelf aangewezen!", "Checking for an update...": "Bezig met controleren op updates…", - "Logs sent": "Logboeken verstuurd", - "Debug logs contain application usage data including your username, the IDs or aliases of the rooms or groups you have visited and the usernames of other users. They do not contain messages.": "Foutopsporingslogboeken bevatten gebruiksgegevens over de toepassing, inclusief uw gebruikersnaam, de ID’s of bijnamen van de gesprekken die u heeft bezocht, evenals de gebruikersnamen van andere gebruikers. Ze bevatten geen berichten.", - "Failed to send logs: ": "Versturen van logboeken mislukt: ", - "Preparing to send logs": "Logboeken worden voorbereid voor versturen", + "Logs sent": "Logs verstuurd", + "Debug logs contain application usage data including your username, the IDs or aliases of the rooms or groups you have visited and the usernames of other users. They do not contain messages.": "Foutenlogboeken bevatten gebruiksgegevens van de app inclusief uw gebruikersnaam, de ID’s of bijnamen van de gesprekken die u heeft bezocht, en de gebruikersnamen van andere gebruikers. Ze bevatten geen berichten.", + "Failed to send logs: ": "Versturen van logs mislukt: ", + "Preparing to send logs": "Logs voorbereiden voor versturen", "e.g. %(exampleValue)s": "bv. %(exampleValue)s", - "Every page you use in the app": "Iedere bladzijde die je in de toepassing gebruikt", + "Every page you use in the app": "Iedere bladzijde die u in de app gebruikt", "e.g. ": "bv. ", "Your device resolution": "De resolutie van je apparaat", "Missing roomId.": "roomId ontbreekt.", "Always show encryption icons": "Versleutelingspictogrammen altijd tonen", - "Send analytics data": "Statistische gegevens versturen", + "Send analytics data": "Gebruiksgegevens delen", "Enable widget screenshots on supported widgets": "Widget-schermafbeeldingen inschakelen op ondersteunde widgets", "Muted Users": "Gedempte gebruikers", "Popout widget": "Widget in nieuw venster openen", @@ -798,11 +798,11 @@ "Message visibility in Matrix is similar to email. Our forgetting your messages means that messages you have sent will not be shared with any new or unregistered users, but registered users who already have access to these messages will still have access to their copy.": "De zichtbaarheid van berichten in Matrix is zoals bij e-mails. Het vergeten van uw berichten betekent dat berichten die u heeft verstuurd niet meer gedeeld worden met nieuwe of ongeregistreerde gebruikers, maar geregistreerde gebruikers die al toegang hebben tot deze berichten zullen alsnog toegang hebben tot hun eigen kopie ervan.", "Please forget all messages I have sent when my account is deactivated (Warning: this will cause future users to see an incomplete view of conversations)": "Vergeet bij het sluiten van mijn account alle door mij verstuurde berichten (Let op: hierdoor zullen personen een onvolledig beeld krijgen van gesprekken)", "To continue, please enter your password:": "Voer uw wachtwoord in om verder te gaan:", - "Clear Storage and Sign Out": "Opslag wissen en afmelden", - "Send Logs": "Logboek versturen", + "Clear Storage and Sign Out": "Opslag wissen en uitloggen", + "Send Logs": "Logs versturen", "Refresh": "Herladen", "We encountered an error trying to restore your previous session.": "Het herstel van uw vorige sessie is mislukt.", - "Clearing your browser's storage may fix the problem, but will sign you out and cause any encrypted chat history to become unreadable.": "Het legen van de opslag van uw browser zal het probleem misschien verhelpen, maar zal u ook afmelden en uw gehele versleutelde gespreksgeschiedenis onleesbaar maken.", + "Clearing your browser's storage may fix the problem, but will sign you out and cause any encrypted chat history to become unreadable.": "Het legen van de opslag van uw browser zal het probleem misschien verhelpen, maar zal u ook uitloggen en uw gehele versleutelde gespreksgeschiedenis onleesbaar maken.", "Collapse Reply Thread": "Reactieketting dichtvouwen", "Can't leave Server Notices room": "Kan servermeldingsgesprek niet verlaten", "This room is used for important messages from the Homeserver, so you cannot leave it.": "Dit gesprek is bedoeld voor belangrijke berichten van de homeserver, dus u kunt het niet verlaten.", @@ -842,7 +842,7 @@ "Bulk options": "Bulkopties", "This homeserver has hit its Monthly Active User limit.": "Deze homeserver heeft zijn limiet voor maandelijks actieve gebruikers bereikt.", "This homeserver has exceeded one of its resource limits.": "Deze homeserver heeft één van zijn systeembronlimieten overschreden.", - "Whether or not you're logged in (we don't record your username)": "Of je al dan niet ingelogd bent (we slaan je gebruikersnaam niet op)", + "Whether or not you're logged in (we don't record your username)": "Of u al dan niet ingelogd bent (we slaan je gebruikersnaam niet op)", "The file '%(fileName)s' exceeds this homeserver's size limit for uploads": "Het bestand ‘%(fileName)s’ is groter dan de uploadlimiet van de homeserver", "Unable to load! Check your network connectivity and try again.": "Laden mislukt! Controleer je netwerktoegang en probeer het nogmaals.", "Failed to invite users to the room:": "Kon de volgende gebruikers hier niet uitnodigen:", @@ -1023,20 +1023,20 @@ "Profile picture": "Profielfoto", "Upgrade to your own domain": "Upgrade naar uw eigen domein", "Display Name": "Weergavenaam", - "Set a new account password...": "Stel een nieuw accountwachtwoord in…", + "Set a new account password...": "Stel een nieuw wachtwoord in…", "Email addresses": "E-mailadressen", "Phone numbers": "Telefoonnummers", "Language and region": "Taal en regio", "Theme": "Thema", "Account management": "Accountbeheer", - "Deactivating your account is a permanent action - be careful!": "Pas op! Het sluiten van uw account is onherroepelijk!", + "Deactivating your account is a permanent action - be careful!": "Pas op! Het sluiten van uw account kan niet teruggedraaid worden!", "General": "Algemeen", - "Legal": "Wettelijk", + "Legal": "Juridisch", "Credits": "Met dank aan", "For help with using %(brand)s, click here.": "Klik hier voor hulp bij het gebruiken van %(brand)s.", "For help with using %(brand)s, click here or start a chat with our bot using the button below.": "Klik hier voor hulp bij het gebruiken van %(brand)s, of begin een gesprek met onze robot met de knop hieronder.", - "Help & About": "Hulp & Info", - "Bug reporting": "Foutmeldingen", + "Help & About": "Hulp & info", + "Bug reporting": "Bug meldingen", "FAQ": "FAQ", "Versions": "Versies", "Preferences": "Instellingen", @@ -1046,10 +1046,10 @@ "Autocomplete delay (ms)": "Vertraging voor autoaanvullen (ms)", "Accept all %(invitedRooms)s invites": "Alle %(invitedRooms)s de uitnodigingen aannemen", "Key backup": "Sleutelback-up", - "Security & Privacy": "Veiligheid & Privacy", + "Security & Privacy": "Veiligheid & privacy", "Missing media permissions, click the button below to request.": "Mediatoestemmingen ontbreken, klik op de knop hieronder om deze aan te vragen.", "Request media permissions": "Mediatoestemmingen verzoeken", - "Voice & Video": "Spraak & Video", + "Voice & Video": "Spraak & video", "Room information": "Gespreksinformatie", "Internal room ID:": "Interne gespreks-ID:", "Room version": "Gespreksversie", @@ -1108,7 +1108,7 @@ "Unable to find profiles for the Matrix IDs listed below - would you like to invite them anyway?": "Kan geen profielen voor de Matrix-ID’s hieronder vinden - wilt u ze toch uitnodigen?", "Invite anyway and never warn me again": "Alsnog uitnodigen en mij nooit meer waarschuwen", "Invite anyway": "Alsnog uitnodigen", - "Before submitting logs, you must create a GitHub issue to describe your problem.": "Voor u logboeken indient, dient u uw probleem te melden op GitHub.", + "Before submitting logs, you must create a GitHub issue to describe your problem.": "Voordat u logs indient, dient u uw probleem te melden in een GitHub issue.", "Unable to load commit detail: %(msg)s": "Kan commitdetail niet laden: %(msg)s", "To avoid losing your chat history, you must export your room keys before logging out. You will need to go back to the newer version of %(brand)s to do this": "Om uw gespreksgeschiedenis niet te verliezen vóór het uitloggen dient u uw veiligheidssleutel te exporteren. Dat moet vanuit de nieuwere versie van %(brand)s", "Incompatible Database": "Incompatibele database", @@ -1125,7 +1125,7 @@ "I don't want my encrypted messages": "Ik wil mijn versleutelde berichten niet", "Manually export keys": "Sleutels handmatig wegschrijven", "You'll lose access to your encrypted messages": "U zult de toegang tot uw versleutelde berichten verliezen", - "Are you sure you want to sign out?": "Weet u zeker dat u zich wilt afmelden?", + "Are you sure you want to sign out?": "Weet u zeker dat u wilt uitloggen?", "If you run into any bugs or have feedback you'd like to share, please let us know on GitHub.": "Als u fouten zou tegenkomen of voorstellen zou hebben, laat het ons dan weten op GitHub.", "To help avoid duplicate issues, please view existing issues first (and add a +1) or create a new issue if you can't find it.": "Voorkom dubbele meldingen: doorzoek eerst de bestaande meldingen (en voeg desgewenst een +1 toe). Maak enkel een nieuwe melding aan indien u niets kunt vinden.", "Report bugs & give feedback": "Fouten melden & feedback geven", @@ -1193,7 +1193,7 @@ "Could not load user profile": "Kon gebruikersprofiel niet laden", "Your Matrix account on %(serverName)s": "Uw Matrix-account op %(serverName)s", "A verification email will be sent to your inbox to confirm setting your new password.": "Er is een verificatie-e-mail naar u gestuurd om het instellen van uw nieuwe wachtwoord te bevestigen.", - "Sign in instead": "Aanmelden", + "Sign in instead": "In plaats daarvan inloggen", "Your password has been reset.": "Uw wachtwoord is opnieuw ingesteld.", "Set a new password": "Stel een nieuw wachtwoord in", "Invalid homeserver discovery response": "Ongeldig homeserver-vindbaarheids-antwoord", @@ -1202,13 +1202,13 @@ "This homeserver does not support login using email address.": "Deze homeserver biedt geen ondersteuning voor inloggen met e-mailadres.", "Please contact your service administrator to continue using this service.": "Gelieve contact op te nemen met uw dienstbeheerder om deze dienst te blijven gebruiken.", "Failed to perform homeserver discovery": "Ontdekken van homeserver is mislukt", - "Sign in with single sign-on": "Aanmelden met eenmalige aanmelding", + "Sign in with single sign-on": "Inloggen met eenmalig inloggen", "Create account": "Account aanmaken", "Registration has been disabled on this homeserver.": "Registratie is uitgeschakeld op deze homeserver.", "Unable to query for supported registration methods.": "Kan ondersteunde registratiemethoden niet opvragen.", "Create your account": "Maak uw account aan", "Keep going...": "Doe verder…", - "For maximum security, this should be different from your account password.": "Voor maximale veiligheid zou dit moeten verschillen van uw accountwachtwoord.", + "For maximum security, this should be different from your account password.": "Voor maximale veiligheid moet dit verschillen van uw accountwachtwoord.", "That matches!": "Dat komt overeen!", "That doesn't match.": "Dat komt niet overeen.", "Go back to set it again.": "Ga terug om het opnieuw in te stellen.", @@ -1228,11 +1228,11 @@ "Don't ask again": "Niet opnieuw vragen", "New Recovery Method": "Nieuwe herstelmethode", "A new recovery passphrase and key for Secure Messages have been detected.": "Er zijn een nieuw herstelwachtwoord en een nieuwe herstelsleutel voor beveiligde berichten gedetecteerd.", - "If you didn't set the new recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings.": "Als u deze nieuwe herstelmethode niet heeft ingesteld, is het mogelijk dat een aanvaller toegang tot uw account probeert te krijgen. Wijzig onmiddellijk uw accountwachtwoord en stel in het instellingenmenu een nieuwe herstelmethode in.", + "If you didn't set the new recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings.": "Als u deze nieuwe herstelmethode niet heeft ingesteld, is het mogelijk dat een aanvaller toegang tot uw account probeert te krijgen. Wijzig onmiddellijk uw wachtwoord en stel bij instellingen een nieuwe herstelmethode in.", "Go to Settings": "Ga naar instellingen", "Set up Secure Messages": "Beveiligde berichten instellen", "Recovery Method Removed": "Herstelmethode verwijderd", - "If you didn't remove the recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings.": "Als u de herstelmethode niet heeft verwijderd, is het mogelijk dat er een aanvaller toegang tot uw account probeert te verkrijgen. Wijzig onmiddellijk uw accountwachtwoord en stel in het instellingenmenu een nieuwe herstelmethode in.", + "If you didn't remove the recovery method, an attacker may be trying to access your account. Change your account password and set a new recovery method immediately in Settings.": "Als u de herstelmethode niet heeft verwijderd, is het mogelijk dat er een aanvaller toegang tot uw account probeert te verkrijgen. Wijzig onmiddellijk uw wachtwoord en stel bij instellingen een nieuwe herstelmethode in.", "Warning: Upgrading a room will not automatically migrate room members to the new version of the room. We'll post a link to the new room in the old version of the room - room members will have to click this link to join the new room.": "Let op: gesprekken bijwerken voegt gespreksleden niet automatisch toe aan de nieuwe versie van het gesprek. Er komt in het oude gesprek een koppeling naar het nieuwe, waarop gespreksleden moeten klikken om aan het nieuwe gesprek deel te nemen.", "Adds a custom widget by URL to the room": "Voegt met een URL een aangepaste widget toe aan het gesprek", "Please supply a https:// or http:// widget URL": "Voer een https://- of http://-widget-URL in", @@ -1264,8 +1264,8 @@ "GitHub issue": "GitHub-melding", "Notes": "Opmerkingen", "If there is additional context that would help in analysing the issue, such as what you were doing at the time, room IDs, user IDs, etc., please include those things here.": "Gelieve alle verdere informatie die zou kunnen helpen het probleem te analyseren (wat u aan het doen was, relevante gespreks-ID’s, gebruikers-ID’s, enz.) bij te voegen.", - "Sign out and remove encryption keys?": "Afmelden en versleutelingssleutels verwijderen?", - "To help us prevent this in future, please send us logs.": "Gelieve ons logboeken te sturen om dit in de toekomst te helpen voorkomen.", + "Sign out and remove encryption keys?": "Uitloggen en versleutelingssleutels verwijderen?", + "To help us prevent this in future, please send us logs.": "Stuur ons uw logs om dit in de toekomst te helpen voorkomen.", "Missing session data": "Sessiegegevens ontbreken", "Some session data, including encrypted message keys, is missing. Sign out and sign in to fix this, restoring keys from backup.": "Sommige sessiegegevens, waaronder sleutels voor versleutelde berichten, ontbreken. Herstel de sleutels uit uw back-up door u af- en weer aan te melden.", "Your browser likely removed this data when running low on disk space.": "Uw browser heeft deze gegevens wellicht verwijderd toen de beschikbare opslagruimte vol was.", @@ -1297,7 +1297,7 @@ "Rejecting invite …": "Uitnodiging wordt geweigerd…", "Join the conversation with an account": "Neem deel aan het gesprek met een account", "Sign Up": "Registreren", - "Sign In": "Aanmelden", + "Sign In": "Inloggen", "You were kicked from %(roomName)s by %(memberName)s": "U bent uit %(roomName)s gezet door %(memberName)s", "Reason: %(reason)s": "Reden: %(reason)s", "Forget this room": "Dit gesprek vergeten", @@ -1315,7 +1315,7 @@ "%(roomName)s can't be previewed. Do you want to join it?": "%(roomName)s kan niet vooraf bekeken worden. Wilt u eraan deelnemen?", "This room doesn't exist. Are you sure you're at the right place?": "Dit gesprek bestaat niet. Weet u zeker dat u zich op de juiste plaats bevindt?", "Try again later, or ask a room admin to check if you have access.": "Probeer het later opnieuw, of vraag een gespreksbeheerder om te controleren of u wel toegang heeft.", - "%(errcode)s was returned while trying to access the room. If you think you're seeing this message in error, please submit a bug report.": "De foutcode %(errcode)s is weergegeven bij het toetreden van het gesprek. Als u meent dat u dit bericht foutief te zien krijgt, gelieve dan een foutmelding in te dienen.", + "%(errcode)s was returned while trying to access the room. If you think you're seeing this message in error, please submit a bug report.": "De foutcode %(errcode)s is weergegeven bij het toetreden van het gesprek. Als u meent dat u dit bericht foutief te zien krijgt, gelieve dan een bugmelding indienen.", "This room has already been upgraded.": "Dit gesprek is reeds geüpgraded.", "reacted with %(shortName)s": "heeft gereageerd met %(shortName)s", "edited": "bewerkt", @@ -1386,8 +1386,8 @@ "Resend edit": "Bewerking opnieuw versturen", "Resend %(unsentCount)s reaction(s)": "%(unsentCount)s reactie(s) opnieuw versturen", "Resend removal": "Verwijdering opnieuw versturen", - "Failed to re-authenticate due to a homeserver problem": "Opnieuw aanmelden is mislukt wegens een probleem met de homeserver", - "Failed to re-authenticate": "Opnieuw aanmelden is mislukt", + "Failed to re-authenticate due to a homeserver problem": "Opnieuw inloggen is mislukt wegens een probleem met de homeserver", + "Failed to re-authenticate": "Opnieuw inloggen is mislukt", "Enter your password to sign in and regain access to your account.": "Voer uw wachtwoord in om u aan te melden en toegang tot uw account te herkrijgen.", "Forgotten your password?": "Wachtwoord vergeten?", "You're signed out": "U bent afgemeld", @@ -1401,7 +1401,7 @@ "Service": "Dienst", "Summary": "Samenvatting", "Sign in and regain access to your account.": "Meld u aan en herkrijg toegang tot uw account.", - "You cannot sign in to your account. Please contact your homeserver admin for more information.": "U kunt zich niet aanmelden met uw account. Neem voor meer informatie contact op met de beheerder van uw homeserver.", + "You cannot sign in to your account. Please contact your homeserver admin for more information.": "U kunt niet inloggen met uw account. Neem voor meer informatie contact op met de beheerder van uw homeserver.", "This account has been deactivated.": "Deze account is gesloten.", "Messages": "Berichten", "Actions": "Acties", @@ -1478,11 +1478,11 @@ "No recent messages by %(user)s found": "Geen recente berichten door %(user)s gevonden", "Try scrolling up in the timeline to see if there are any earlier ones.": "Probeer omhoog te scrollen in de tijdslijn om te kijken of er eerdere zijn.", "Remove recent messages by %(user)s": "Recente berichten door %(user)s verwijderen", - "You are about to remove %(count)s messages by %(user)s. This cannot be undone. Do you wish to continue?|other": "U staat op het punt %(count)s berichten door %(user)s te verwijderen. Dit is onherroepelijk. Wilt u doorgaan?", + "You are about to remove %(count)s messages by %(user)s. This cannot be undone. Do you wish to continue?|other": "U staat op het punt %(count)s berichten van %(user)s te verwijderen. Dit kan niet teruggedraaid worden. Wilt u doorgaan?", "For a large amount of messages, this might take some time. Please don't refresh your client in the meantime.": "Bij een groot aantal berichten kan dit even duren. Herlaad uw cliënt niet gedurende deze tijd.", "Remove %(count)s messages|other": "%(count)s berichten verwijderen", "Deactivate user?": "Gebruiker deactiveren?", - "Deactivating this user will log them out and prevent them from logging back in. Additionally, they will leave all the rooms they are in. This action cannot be reversed. Are you sure you want to deactivate this user?": "Deze gebruiker deactiveren zal deze gebruiker uitloggen en verhinderen dat de gebruiker weer inlogt. Bovendien zal de gebruiker alle gesprekken waaraan de gebruiker deelneemt verlaten. Deze actie is onherroepelijk. Weet u zeker dat u deze gebruiker wilt deactiveren?", + "Deactivating this user will log them out and prevent them from logging back in. Additionally, they will leave all the rooms they are in. This action cannot be reversed. Are you sure you want to deactivate this user?": "Deze gebruiker deactiveren zal deze gebruiker uitloggen en verhinderen dat de gebruiker weer inlogt. Bovendien zal de gebruiker alle gesprekken waaraan de gebruiker deelneemt verlaten. Deze actie is niet terug te draaien. Weet u zeker dat u deze gebruiker wilt deactiveren?", "Deactivate user": "Gebruiker deactiveren", "Remove recent messages": "Recente berichten verwijderen", "Bold": "Vet", @@ -1523,7 +1523,7 @@ "%(count)s unread messages.|other": "%(count)s ongelezen berichten.", "Unread mentions.": "Ongelezen vermeldingen.", "Show image": "Afbeelding tonen", - "Please create a new issue on GitHub so that we can investigate this bug.": "Maak een nieuw rapport aan op GitHub opdat we dit probleem kunnen onderzoeken.", + "Please create a new issue on GitHub so that we can investigate this bug.": "Maak een nieuwe issue aan op GitHub zodat we deze bug kunnen onderzoeken.", "e.g. my-room": "bv. mijn-gesprek", "Close dialog": "Dialoog sluiten", "Please enter a name for the room": "Geef een naam voor het gesprek op", @@ -1549,7 +1549,7 @@ "Click the link in the email you received to verify and then click continue again.": "Open de koppeling in de ontvangen verificatie-e-mail, en klik dan op ‘Doorgaan’.", "%(creator)s created and configured the room.": "Gesprek gestart en ingesteld door %(creator)s.", "Setting up keys": "Sleutelconfiguratie", - "Verify this session": "Deze sessie verifiëren", + "Verify this session": "Verifieer deze sessie", "Encryption upgrade available": "Versleutelingsupgrade beschikbaar", "You can use /help to list available commands. Did you mean to send this as a message?": "Typ /help om alle opdrachten te zien. Was het uw bedoeling dit als bericht te sturen?", "Help": "Hulp", @@ -1621,7 +1621,7 @@ "Upgrade": "Upgraden", "Verify": "Verifiëren", "Later": "Later", - "Review": "Controle", + "Review": "Controleer", "Decline (%(counter)s)": "Afwijzen (%(counter)s)", "This bridge was provisioned by .": "Dank aan voor de brug.", "This bridge is managed by .": "Brug onderhouden door .", @@ -1636,14 +1636,14 @@ "Unable to load session list": "Kan sessielijst niet laden", "Delete %(count)s sessions|other": "%(count)s sessies verwijderen", "Delete %(count)s sessions|one": "%(count)s sessie verwijderen", - "Whether you're using %(brand)s on a device where touch is the primary input mechanism": "Of je %(brand)s op een apparaat gebruikt waarop een aanraakscherm de voornaamste invoermethode is", - "Whether you're using %(brand)s as an installed Progressive Web App": "Of je %(brand)s gebruikt als een geïnstalleerde Progressive-Web-App", + "Whether you're using %(brand)s on a device where touch is the primary input mechanism": "Of u %(brand)s op een apparaat gebruikt waarop een aanraakscherm de voornaamste invoermethode is", + "Whether you're using %(brand)s as an installed Progressive Web App": "Of u %(brand)s gebruikt als een geïnstalleerde Progressieve Web-App", "Your user agent": "Jouw gebruikersagent", "If you cancel now, you won't complete verifying the other user.": "Als u nu annuleert zult u de andere gebruiker niet verifiëren.", "If you cancel now, you won't complete verifying your other session.": "Als u nu annuleert zult u uw andere sessie niet verifiëren.", "Cancel entering passphrase?": "Wachtwoord annuleren?", "Show typing notifications": "Typmeldingen weergeven", - "Verify this session by completing one of the following:": "Verifieer deze sessie door een van het volgende te doen:", + "Verify this session by completing one of the following:": "Verifieer deze sessie door een van het volgende handelingen te doen:", "Scan this unique code": "Scan deze unieke code", "or": "of", "Compare unique emoji": "Vergelijk unieke emoji", @@ -1746,7 +1746,7 @@ "Clear notifications": "Meldingen wissen", "You should remove your personal data from identity server before disconnecting. Unfortunately, identity server is currently offline or cannot be reached.": "U moet uw persoonlijke informatie van de identiteitsserver verwijderen voordat u zich ontkoppelt. Helaas kan de identiteitsserver op dit moment niet worden bereikt. Mogelijk is hij offline.", "Your homeserver does not support cross-signing.": "Uw homeserver biedt geen ondersteuning voor kruiselings ondertekenen.", - "Homeserver feature support:": "Homeserver ondersteund deze functies:", + "Homeserver feature support:": "Homeserver functie ondersteuning:", "exists": "aanwezig", "Sign In or Create Account": "Meld u aan of maak een account aan", "Use your account or create a new one to continue.": "Gebruik uw bestaande account of maak een nieuwe aan om verder te gaan.", @@ -1872,10 +1872,10 @@ "More options": "Meer opties", "Language Dropdown": "Taalselectie", "Destroy cross-signing keys?": "Sleutels voor kruiselings ondertekenen verwijderen?", - "Deleting cross-signing keys is permanent. Anyone you have verified with will see security alerts. You almost certainly don't want to do this, unless you've lost every device you can cross-sign from.": "Het verwijderen van sleutels voor kruiselings ondertekenen is onherroepelijk. Iedereen waarmee u geverifieerd heeft zal beveiligingswaarschuwingen te zien krijgen. U wilt dit hoogstwaarschijnlijk niet doen, tenzij u alle apparaten heeft verloren waarmee u kruiselings kon ondertekenen.", + "Deleting cross-signing keys is permanent. Anyone you have verified with will see security alerts. You almost certainly don't want to do this, unless you've lost every device you can cross-sign from.": "Het verwijderen van sleutels voor kruiselings ondertekenen is niet terug te draaien. Iedereen waarmee u geverifieerd heeft zal beveiligingswaarschuwingen te zien krijgen. U wilt dit hoogstwaarschijnlijk niet doen, tenzij u alle apparaten heeft verloren waarmee u kruiselings kon ondertekenen.", "Clear cross-signing keys": "Sleutels voor kruiselings ondertekenen wissen", "Clear all data in this session?": "Alle gegevens in deze sessie verwijderen?", - "Clearing all data from this session is permanent. Encrypted messages will be lost unless their keys have been backed up.": "Het verwijderen van alle gegevens in deze sessie is onherroepelijk. Versleutelde berichten zullen verloren gaan, tenzij u een back-up van de sleutels heeft.", + "Clearing all data from this session is permanent. Encrypted messages will be lost unless their keys have been backed up.": "Het verwijderen van alle gegevens in deze sessie is niet terug te draaien. Versleutelde berichten zullen verloren gaan, tenzij u een back-up van de sleutels heeft.", "Verify session": "Sessie verifiëren", "Session name": "Sessienaam", "Session key": "Sessiesleutel", @@ -1909,7 +1909,7 @@ "Automatically invite users": "Gebruikers automatisch uitnodigen", "Upgrade private room": "Privégesprek upgraden", "Upgrade public room": "Openbaar gesprek upgraden", - "Upgrading a room is an advanced action and is usually recommended when a room is unstable due to bugs, missing features or security vulnerabilities.": "Het bijwerken van een gesprek is een gevorderde actie en wordt meestal aanbevolen wanneer een gesprek onstabiel is door fouten, ontbrekende functies of problemen met de beveiliging.", + "Upgrading a room is an advanced action and is usually recommended when a room is unstable due to bugs, missing features or security vulnerabilities.": "Het bijwerken van een gesprek is een gevorderde actie en wordt meestal aanbevolen wanneer een gesprek onstabiel is door bugs, ontbrekende functies of problemen met de beveiliging.", "This usually only affects how the room is processed on the server. If you're having problems with your %(brand)s, please report a bug.": "Dit heeft meestal enkel een invloed op de manier waarop het gesprek door de server verwerkt wordt. Als u problemen met uw %(brand)s ondervindt, dien dan een foutmelding in.", "You'll upgrade this room from to .": "U upgrade dit gesprek van naar .", "This will allow you to return to your account after signing out, and sign in on other sessions.": "Daardoor kunt u na afmelding terugkeren tot uw account, en u bij andere sessies aanmelden.", @@ -1927,7 +1927,7 @@ "Remove for me": "Verwijderen voor mezelf", "User Status": "Gebruikersstatus", "Country Dropdown": "Landselectie", - "Confirm your identity by entering your account password below.": "Bevestig uw identiteit door hieronder uw accountwachtwoord in te voeren.", + "Confirm your identity by entering your account password below.": "Bevestig uw identiteit door hieronder uw wachtwoord in te voeren.", "No identity server is configured so you cannot add an email address in order to reset your password in the future.": "Er is geen identiteitsserver geconfigureerd, dus u kunt geen e-mailadres toevoegen om in de toekomst een nieuw wachtwoord in te stellen.", "Jump to first unread room.": "Ga naar het eerste ongelezen gesprek.", "Jump to first invite.": "Ga naar de eerste uitnodiging.", @@ -1939,13 +1939,13 @@ "Changing your password will reset any end-to-end encryption keys on all of your sessions, making encrypted chat history unreadable. Set up Key Backup or export your room keys from another session before resetting your password.": "Door uw wachtwoord te wijzigen stelt u alle eind-tot-eind-versleutelingssleutels op al uw sessies opnieuw in, waardoor uw versleutelde gespreksgeschiedenis onleesbaar wordt. Stel uw sleutelback-up in of sla uw gesprekssleutels van een andere sessie op voor u een nieuw wachtwoord instelt.", "You have been logged out of all sessions and will no longer receive push notifications. To re-enable notifications, sign in again on each device.": "U bent uitgelogd bij al uw sessies en zult geen pushberichten meer ontvangen. Meld u op elk apparaat opnieuw aan om meldingen opnieuw in te schakelen.", "Regain access to your account and recover encryption keys stored in this session. Without them, you won’t be able to read all of your secure messages in any session.": "Ontvang toegang tot uw account en herstel de tijdens deze sessie opgeslagen versleutelingssleutels, zonder deze sleutels zijn sommige van uw versleutelde berichten in uw sessies onleesbaar.", - "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.": "Let op: uw persoonlijke gegevens (waaronder versleutelingssleutels) zijn nog steeds opgeslagen in deze sessie. Wis ze wanneer u klaar bent met deze sessie, of wanneer u zich wilt aanmelden met een andere account.", + "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.": "Let op: uw persoonlijke gegevens (waaronder versleutelingssleutels) zijn nog steeds opgeslagen in deze sessie. Wis ze wanneer u klaar bent met deze sessie, of wanneer u wilt inloggen met een andere account.", "Command Autocomplete": "Opdrachten autoaanvullen", "DuckDuckGo Results": "DuckDuckGo-resultaten", - "Enter your account password to confirm the upgrade:": "Voer uw accountwachtwoord in om het upgraden te bevestigen:", + "Enter your account password to confirm the upgrade:": "Voer uw wachtwoord in om het upgraden te bevestigen:", "Restore your key backup to upgrade your encryption": "Herstel uw sleutelback-up om uw versleuteling te upgraden", "Restore": "Herstellen", - "You'll need to authenticate with the server to confirm the upgrade.": "U zult zich moeten aanmelden bij de server om het upgraden te bevestigen.", + "You'll need to authenticate with the server to confirm the upgrade.": "U zult moeten inloggen bij de server om het upgraden te bevestigen.", "Upgrade this session to allow it to verify other sessions, granting them access to encrypted messages and marking them as trusted for other users.": "Upgrade deze sessie om er andere sessies mee te verifiëren, waardoor deze ook de toegang verkrijgen tot uw versleutelde berichten en deze voor andere gebruikers als vertrouwd gemarkeerd worden.", "Set up with a recovery key": "Instellen met een herstelsleutel", "Keep a copy of it somewhere secure, like a password manager or even a safe.": "Bewaar een kopie op een veilige plaats, zoals in een wachtwoordbeheerder of een kluis.", @@ -1970,7 +1970,7 @@ "To report a Matrix-related security issue, please read the Matrix.org Security Disclosure Policy.": "Bekijk eerst het beveiligingsopenbaarmakingsbeleid van Matrix.org als u een probleem met de beveiliging van Matrix wilt melden.", "Not currently indexing messages for any room.": "Er worden momenteel voor geen enkel gesprek berichten geïndexeerd.", "%(doneRooms)s out of %(totalRooms)s": "%(doneRooms)s van %(totalRooms)s", - "Where you’re logged in": "Waar u ingelogd bent", + "Where you’re logged in": "Waar u bent ingelogd", "Manage the names of and sign out of your sessions below or verify them in your User Profile.": "Beheer hieronder de namen van uw sessies en meld ze af. Of verifieer ze in uw gebruikersprofiel.", "Use Single Sign On to continue": "Ga verder met eenmalige aanmelding", "Confirm adding this email address by using Single Sign On to prove your identity.": "Bevestig je identiteit met je eenmalige aanmelding om dit e-mailadres toe te voegen.", @@ -1989,7 +1989,7 @@ "Command failed": "Opdracht mislukt", "Could not find user in room": "Kon die deelnemer aan het gesprek niet vinden", "Please supply a widget URL or embed code": "Gelieve een widgetURL of in te bedden code te geven", - "Send a bug report with logs": "Rapporteer een fout, met foutopsporingslogboek bijgesloten", + "Send a bug report with logs": "Stuur een bugrapport met logs", "%(senderDisplayName)s changed the room name from %(oldRoomName)s to %(newRoomName)s.": "%(senderDisplayName)s heeft het gesprek %(oldRoomName)s hernoemd tot %(newRoomName)s.", "%(senderName)s added the alternative addresses %(addresses)s for this room.|other": "%(senderName)s heeft dit gesprek de nevenadressen %(addresses)s toegekend.", "%(senderName)s added the alternative addresses %(addresses)s for this room.|one": "%(senderName)s heeft dit gesprek het nevenadres %(addresses)s toegekend.", @@ -2315,7 +2315,7 @@ "Your homeserver rejected your log in attempt. This could be due to things just taking too long. Please try again. If this continues, please contact your homeserver administrator.": "Uw homeserver wees uw inlogpoging af. Dit kan zijn doordat het te lang heeft geduurd. Probeer het opnieuw. Als dit probleem zich blijft voordoen, neem contact op met de beheerder van uw homeserver.", "Your homeserver was unreachable and was not able to log you in. Please try again. If this continues, please contact your homeserver administrator.": "Uw homeserver was onbereikbaar en kon u niet inloggen, probeer het opnieuw. Wanneer dit probleem zich blijft voordoen, neem contact op met de beheerder van uw homeserver.", "Try again": "Probeer opnieuw", - "We asked the browser to remember which homeserver you use to let you sign in, but unfortunately your browser has forgotten it. Go to the sign in page and try again.": "De browser is verzocht uw homeserver te onthouden die u gebruikt om zich aan te melden, maar is deze vergeten. Ga naar de aanmeldpagina en probeer het opnieuw.", + "We asked the browser to remember which homeserver you use to let you sign in, but unfortunately your browser has forgotten it. Go to the sign in page and try again.": "De browser is verzocht uw homeserver te onthouden die u gebruikt om in te loggen, maar helaas heeft de browser deze vergeten. Ga naar de inlog-pagina en probeer het opnieuw.", "We couldn't log you in": "We konden u niet inloggen", "Room Info": "Gespreksinfo", "Matrix.org is the biggest public homeserver in the world, so it’s a good place for many.": "Matrix.org is de grootste openbare homeserver van de wereld, dus het is een goede plek voor vele.", @@ -2416,8 +2416,8 @@ "sends snowfall": "Stuur sneeuwvlokken", "sends confetti": "verstuurt confetti", "sends fireworks": "Stuur vuurwerk", - "Downloading logs": "Logboeken downloaden", - "Uploading logs": "Logboeken versturen", + "Downloading logs": "Logs downloaden", + "Uploading logs": "Logs uploaden", "Use Ctrl + Enter to send a message": "Gebruik Ctrl + Enter om een bericht te sturen", "Use Command + Enter to send a message": "Gebruik Command (⌘) + Enter om een bericht te sturen", "Use Ctrl + F to search": "Ctrl + F om te zoeken gebruiken", @@ -2425,7 +2425,7 @@ "Use a more compact ‘Modern’ layout": "Compacte 'Modern'-layout inschakelen", "Use custom size": "Aangepaste lettergrootte gebruiken", "Font size": "Lettergrootte", - "Enable advanced debugging for the room list": "Geavanceerde foutopsporing voor de gesprekkenlijst inschakelen", + "Enable advanced debugging for the room list": "Geavanceerde bugopsporing voor de gesprekkenlijst inschakelen", "Render LaTeX maths in messages": "Weergeef LaTeX-wiskundenotatie in berichten", "Change notification settings": "Meldingsinstellingen wijzigen", "%(senderName)s: %(stickerName)s": "%(senderName)s: %(stickerName)s", @@ -2449,7 +2449,7 @@ "%(senderName)s has updated the widget layout": "%(senderName)s heeft de widget-indeling bijgewerkt", "%(senderName)s declined the call.": "%(senderName)s heeft de oproep afgewezen.", "(an error occurred)": "(een fout is opgetreden)", - "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.": "U heeft eerder een nieuwere versie van %(brand)s in deze sessie gebruikt. Om deze versie opnieuw met eind-tot-eind-versleuteling te gebruiken, zult u zich moeten afmelden en opnieuw aanmelden.", + "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.": "U heeft eerder een nieuwere versie van %(brand)s in deze sessie gebruikt. Om deze versie opnieuw met eind-tot-eind-versleuteling te gebruiken, zult u moeten uitloggen en opnieuw inloggen.", "Block anyone not part of %(serverName)s from ever joining this room.": "Weiger iedereen die geen deel uitmaakt van %(serverName)s aan dit gesprek deel te nemen.", "Create a room in %(communityName)s": "Een gesprek aanmaken in %(communityName)s", "Enable end-to-end encryption": "Eind-tot-eind-versleuteling inschakelen", @@ -2467,7 +2467,7 @@ "Show": "Toon", "People you know on %(brand)s": "Personen die u kent van %(brand)s", "Add another email": "Nog een e-mailadres toevoegen", - "Download logs": "Download logboeken", + "Download logs": "Logs downloaden", "Add a new server...": "Een nieuwe server toevoegen…", "Server name": "Servernaam", "Add a new server": "Een nieuwe server toevoegen", @@ -2479,8 +2479,8 @@ "Enter a server name": "Geef een servernaam", "Continue with %(provider)s": "Doorgaan met %(provider)s", "Homeserver": "Homeserver", - "You can use the custom server options to sign into other Matrix servers by specifying a different homeserver URL. This allows you to use Element with an existing Matrix account on a different homeserver.": "U kunt de aangepaste serverinstellingen gebruiken om u aan te melden bij andere Matrix-servers, door een andere homeserver-URL in te voeren. Dit laat u toe Element te gebruiken met een bestaande Matrix-account bij een andere homeserver.", - "Server Options": "Serverinstellingen", + "You can use the custom server options to sign into other Matrix servers by specifying a different homeserver URL. This allows you to use Element with an existing Matrix account on a different homeserver.": "U kunt de server opties wijzigen om in te loggen bij andere Matrix-servers, wijzig hiervoor de homeserver-URL. Hiermee kunt u Element gebruiken met een al bestaand Matrix-account van een andere homeserver.", + "Server Options": "Server opties", "This address is already in use": "Dit adres is al in gebruik", "This address is available to use": "Dit adres kan worden gebruikt", "Please provide a room address": "Geef een gespreksadres", @@ -2539,7 +2539,7 @@ "Invite by email": "Via e-mail uitnodigen", "Click the button below to confirm your identity.": "Druk op de knop hieronder om uw identiteit te bevestigen.", "Confirm to continue": "Bevestig om door te gaan", - "Report a bug": "Een fout rapporteren", + "Report a bug": "Een bug rapporteren", "Comment": "Opmerking", "Add comment": "Opmerking toevoegen", "Tell us below how you feel about %(brand)s so far.": "Vertel ons hoe %(brand)s u tot dusver bevalt.", @@ -2640,7 +2640,7 @@ "Use this when referencing your community to others. The community ID cannot be changed.": "Gebruik dit om anderen naar uw gemeenschap te verwijzen. De gemeenschaps-ID kan later niet meer veranderd worden.", "Please go into as much detail as you like, so we can track down the problem.": "Gebruik a.u.b. zoveel mogelijk details, zodat wij uw probleem kunnen vinden.", "There are two ways you can provide feedback and help us improve %(brand)s.": "U kunt op twee manieren feedback geven en ons helpen %(brand)s te verbeteren.", - "Please view existing bugs on Github first. No match? Start a new one.": "Bekijk eerst de bestaande problemen op Github. Maak een nieuwe aan wanneer u uw probleem niet heeft gevonden.", + "Please view existing bugs on Github first. No match? Start a new one.": "Bekijk eerst de bestaande bugs op GitHub. Maak een nieuwe aan wanneer u uw bugs niet heeft gevonden.", "Invite someone using their name, email address, username (like ) or share this room.": "Nodig iemand uit door gebruik te maken van hun naam, e-mailadres, gebruikersnaam (zoals ) of deel dit gesprek.", "Invite someone using their name, username (like ) or share this room.": "Nodig iemand uit door gebruik te maken van hun naam, gebruikersnaam (zoals ) of deel dit gesprek.", "Send feedback": "Feedback versturen", @@ -2738,13 +2738,13 @@ "Use Security Key or Phrase": "Gebruik veiligheidssleutel of -wachtwoord", "Decide where your account is hosted": "Kies waar uw account wordt gehost", "Host account on": "Host uw account op", - "Already have an account? Sign in here": "Heeft u al een account? Aanmelden", + "Already have an account? Sign in here": "Heeft u al een account? Inloggen", "%(ssoButtons)s Or %(usernamePassword)s": "%(ssoButtons)s of %(usernamePassword)s", "Continue with %(ssoButtons)s": "Ga verder met %(ssoButtons)s", "That username already exists, please try another.": "Die gebruikersnaam bestaat al, probeer een andere.", "New? Create account": "Nieuw? Maak een account aan", "If you've joined lots of rooms, this might take a while": "Als u zich bij veel gesprekken heeft aangesloten, kan dit een tijdje duren", - "Signing In...": "Aanmelden...", + "Signing In...": "Inloggen...", "Syncing...": "Synchroniseren...", "There was a problem communicating with the homeserver, please try again later.": "Er was een communicatieprobleem met de homeserver, probeer het later opnieuw.", "Community and user menu": "Gemeenschaps- en gebruikersmenu", @@ -2754,7 +2754,7 @@ "User settings": "Gebruikersinstellingen", "Security & privacy": "Veiligheid & privacy", "New here? Create an account": "Nieuw hier? Maak een account", - "Got an account? Sign in": "Heeft u een account? Aanmelden", + "Got an account? Sign in": "Heeft u een account? Inloggen", "Failed to find the general chat for this community": "De algemene chat voor deze gemeenschap werd niet gevonden", "Filter rooms and people": "Gespreken en personen filteren", "Explore rooms in %(communityName)s": "Ontdek de gesprekken van %(communityName)s", @@ -2774,8 +2774,8 @@ "Create community": "Gemeenschap aanmaken", "Attach files from chat or just drag and drop them anywhere in a room.": "Voeg bestanden toe vanuit het gesprek of sleep ze in een gesprek.", "No files visible in this room": "Geen bestanden zichtbaar in dit gesprek", - "Sign in with SSO": "Aanmelden met SSO", - "Use email to optionally be discoverable by existing contacts.": "Gebruik e-mail om optioneel ontdekt te worden door bestaande contacten.", + "Sign in with SSO": "Inloggen met SSO", + "Use email to optionally be discoverable by existing contacts.": "Gebruik e-mail ook om optioneel ontdekt te worden door bestaande contacten.", "Use email or phone to optionally be discoverable by existing contacts.": "Gebruik e-mail of telefoon om optioneel ontdekt te kunnen worden door bestaande contacten.", "Add an email to be able to reset your password.": "Voeg een e-mail toe om uw wachtwoord te kunnen resetten.", "Forgot password?": "Wachtwoord vergeten?", @@ -2852,7 +2852,7 @@ "Continuing temporarily allows the %(hostSignupBrand)s setup process to access your account to fetch verified email addresses. This data is not stored.": "Door tijdelijk door te gaan, krijgt het installatieproces van %(hostSignupBrand)s toegang tot uw account om geverifieerde e-mailadressen op te halen. Deze gegevens worden niet opgeslagen.", "Failed to connect to your homeserver. Please close this dialog and try again.": "Kan geen verbinding maken met uw homeserver. Sluit dit dialoogvenster en probeer het opnieuw.", "Are you sure you wish to abort creation of the host? The process cannot be continued.": "Weet u zeker dat u het aanmaken van de host wilt afbreken? Het proces kan niet worden voortgezet.", - "PRO TIP: If you start a bug, please submit debug logs to help us track down the problem.": "PRO TIP: Als u een bug start, stuur ons dan debug logs om ons te helpen het probleem op te sporen.", + "PRO TIP: If you start a bug, please submit debug logs to help us track down the problem.": "PRO TIP: Als u een nieuwe bug maakt, stuur ons dan uw foutenlogboek om ons te helpen het probleem op te sporen.", "There was an error updating your community. The server is unable to process your request.": "Er is een fout opgetreden bij het updaten van uw gemeenschap. De server is niet in staat om uw verzoek te verwerken.", "There was an error finding this widget.": "Er is een fout opgetreden bij het vinden van deze widget.", "Server did not return valid authentication information.": "Server heeft geen geldige verificatiegegevens teruggestuurd.", @@ -2889,7 +2889,7 @@ "Submit logs": "Logs versturen", "Messages in this room are end-to-end encrypted. When people join, you can verify them in their profile, just tap on their avatar.": "Berichten in dit gesprek zijn eind-tot-eind-versleuteld. Als personen deelnemen, kan u ze verifiëren in hun profiel, tik hiervoor op hun avatar.", "In encrypted rooms, verify all users to ensure it’s secure.": "Controleer alle gebruikers in versleutelde gesprekken om er zeker van te zijn dat het veilig is.", - "Verify all users in a room to ensure it's secure.": "Controleer alle gebruikers in een gesprek om er zeker van te zijn dat hij veilig is.", + "Verify all users in a room to ensure it's secure.": "Controleer alle gebruikers in een gesprek om er zeker van te zijn dat het veilig is.", "%(count)s people|one": "%(count)s persoon", "Add widgets, bridges & bots": "Widgets, bruggen & bots toevoegen", "Edit widgets, bridges & bots": "Widgets, bruggen & bots bewerken", @@ -2921,10 +2921,10 @@ "%(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 kan versleutelde berichten niet veilig lokaal opslaan in een webbrowser. Gebruik %(brand)s Desktop om versleutelde berichten in zoekresultaten te laten verschijnen.", "Securely cache encrypted messages locally for them to appear in search results, using %(size)s to store messages from %(rooms)s rooms.|one": "Veilig lokaal opslaan van versleutelde berichten zodat ze in de zoekresultaten verschijnen, gebruik %(size)s voor het opslaan van berichten uit %(rooms)s gesprek.", "Securely cache encrypted messages locally for them to appear in search results, using %(size)s to store messages from %(rooms)s rooms.|other": "Veilig lokaal opslaan van versleutelde berichten zodat ze in de zoekresultaten verschijnen, gebruik %(size)s voor het opslaan van berichten uit %(rooms)s gesprekken.", - "Individually verify each session used by a user to mark it as trusted, not trusting cross-signed devices.": "Elke sessie die door een gebruiker wordt gebruikt, afzonderlijk verifiëren om deze als vertrouwd aan te merken, waarbij geen vertrouwen wordt gesteld in kruiselings ondertekende apparaten.", - "User signing private key:": "Gebruiker ondertekening privésleutel:", - "Master private key:": "Hoofd privésleutel:", - "Self signing private key:": "Zelfondertekenende privésleutel:", + "Individually verify each session used by a user to mark it as trusted, not trusting cross-signed devices.": "Verifieer elke sessie die door een gebruiker wordt gebruikt afzonderlijk om deze te markeren als vertrouwd, niet vertrouwend op kruislings ondertekende apparaten.", + "User signing private key:": "Gebruikerondertekening-privésleutel:", + "Master private key:": "Hoofdprivésleutel:", + "Self signing private key:": "Zelfondertekening-privésleutel:", "Cross-signing is not set up.": "Kruiselings ondertekenen is niet ingesteld.", "Cross-signing is ready for use.": "Kruiselings ondertekenen is klaar voor gebruik.", "Your server isn't responding to some requests.": "Uw server reageert niet op sommige verzoeken.", @@ -2941,13 +2941,13 @@ "Minimize dialog": "Dialoog minimaliseren", "If you cancel now, you may lose encrypted messages & data if you lose access to your logins.": "Als u nu annuleert, kunt u versleutelde berichten en gegevens verliezen als u geen toegang meer heeft tot uw login.", "Confirm your identity by verifying this login from one of your other sessions, granting it access to encrypted messages.": "Bevestig uw identiteit door deze login te verifiëren vanuit een van uw andere sessies, waardoor u toegang krijgt tot uw versleutelde berichten.", - "Verify this login": "Controleer deze login", + "Verify this login": "Deze inlog verifiëren", "To continue, use Single Sign On to prove your identity.": "Om verder te gaan, gebruik uw eenmalige aanmelding om uw identiteit te bewijzen.", "Prepends ( ͡° ͜ʖ ͡°) to a plain-text message": "Plakt ( ͡° ͜ʖ ͡°) vóór een bericht zonder opmaak", "Prepends ┬──┬ ノ( ゜-゜ノ) to a plain-text message": "Plakt ┬──┬ ノ( ゜-゜ノ) vóór een bericht zonder opmaak", "Prepends (╯°□°)╯︵ ┻━┻ to a plain-text message": "Plakt (╯°□°)╯︵ ┻━┻ vóór een bericht zonder opmaak", "Liberate your communication": "Bevrijd uw communicatie", - "Create a Group Chat": "Maak een groepsgesprek aan", + "Create a Group Chat": "Maak een groepsgesprek", "Send a Direct Message": "Start een direct gesprek", "Welcome to %(appName)s": "Welkom bij %(appName)s", "Add a topic to help people know what it is about.": "Stel een gespreksonderwerp in zodat de personen weten waar het over gaat.", @@ -3024,7 +3024,7 @@ "Start audio stream": "Audio-stream starten", "Failed to start livestream": "Starten van livestream is mislukt", "Unable to start audio streaming.": "Kan audio-streaming niet starten.", - "Save Changes": "Wijzigingen Opslaan", + "Save Changes": "Wijzigingen opslaan", "Saving...": "Opslaan...", "View dev tools": "Bekijk dev tools", "Leave Space": "Space verlaten", @@ -3136,7 +3136,7 @@ "A new login is accessing your account: %(name)s (%(deviceID)s) at %(ip)s": "Een nieuwe login heeft toegang tot uw account: %(name)s (%(deviceID)s) op %(ip)s", "You have unverified logins": "U heeft ongeverifieerde logins", "Without verifying, you won’t have access to all your messages and may appear as untrusted to others.": "Zonder verifiëren heeft u geen toegang tot al uw berichten en kan u als onvertrouwd aangemerkt staan bij anderen.", - "Verify your identity to access encrypted messages and prove your identity to others.": "Verifeer uw identiteit om toegang te krijgen tot uw versleutelde berichten en uw identiteit te bewijzen voor anderen.", + "Verify your identity to access encrypted messages and prove your identity to others.": "Verifeer uw identiteit om toegang te krijgen tot uw versleutelde berichten en om uw identiteit te bewijzen voor anderen.", "Use another login": "Gebruik andere login", "Please choose a strong password": "Kies een sterk wachtwoord", "You can add more later too, including already existing ones.": "U kunt er later nog meer toevoegen, inclusief al bestaande gesprekken.", @@ -3170,7 +3170,7 @@ "Share decryption keys for room history when inviting users": "Deel ontsleutelsleutels voor de gespreksgeschiedenis wanneer u personen uitnodigd", "Send and receive voice messages (in development)": "Verstuur en ontvang audioberichten (in ontwikkeling)", "%(deviceId)s from %(ip)s": "%(deviceId)s van %(ip)s", - "Review to ensure your account is safe": "Controleer ze voor de zekerheid dat uw account veilig is", + "Review to ensure your account is safe": "Controleer ze zodat uw account veilig is", "Sends the given message as a spoiler": "Verstuurt het bericht als een spoiler", "You are the only person here. If you leave, no one will be able to join in the future, including you.": "U bent de enige persoon hier. Als u weggaat, zal niemand in de toekomst kunnen toetreden, u ook niet.", "If you reset everything, you will restart with no trusted sessions, no trusted users, and might not be able to see past messages.": "Als u alles reset, zult u opnieuw opstarten zonder vertrouwde sessies, zonder vertrouwde gebruikers, en zult u misschien geen vroegere berichten meer kunnen zien.", @@ -3205,5 +3205,40 @@ "%(count)s results in all spaces|other": "%(count)s resultaten in alle spaces", "You have no ignored users.": "U heeft geen gebruiker genegeerd.", "Play": "Afspelen", - "Pause": "Pauze" + "Pause": "Pauze", + "This is an experimental feature. For now, new users receiving an invite will have to open the invite on to actually join.": "Dit is een experimentele functie. Voorlopig moeten nieuwe personen die een uitnodiging krijgen de gebruiken om daadwerkelijk deel te nemen.", + "To join %(spaceName)s, turn on the Spaces beta": "Om aan %(spaceName)s deel te nemen moet u de Spaces beta inschakelen", + "To view %(spaceName)s, turn on the Spaces beta": "Om %(spaceName)s te bekijken moet u de Spaces beta inschakelen", + "Select a room below first": "Start met selecteren van een gesprek hieronder", + "Communities are changing to Spaces": "Gemeenschappen worden vervangen door Spaces", + "Join the beta": "Aan beta deelnemen", + "Leave the beta": "Beta verlaten", + "Beta": "Beta", + "Tap for more info": "Klik voor meer info", + "Spaces is a beta feature": "Spaces zijn in beta", + "Want to add a new room instead?": "Wilt u anders een nieuw gesprek toevoegen?", + "Adding rooms... (%(progress)s out of %(count)s)|one": "Gesprek toevoegen...", + "Adding rooms... (%(progress)s out of %(count)s)|other": "Gesprekken toevoegen... (%(progress)s van %(count)s)", + "Not all selected were added": "Niet alle geselecteerden zijn toegevoegd", + "You can add existing spaces to a space.": "U kunt bestaande spaces toevoegen aan een space.", + "Feeling experimental?": "Zin in een experiment?", + "You are not allowed to view this server's rooms list": "U heeft geen toegang tot deze server zijn gesprekkenlijst", + "Error processing voice message": "Fout bij verwerking spraakbericht", + "We didn't find a microphone on your device. Please check your settings and try again.": "We hebben geen microfoon gevonden op uw apparaat. Controleer uw instellingen en probeer het opnieuw.", + "No microphone found": "Geen microfoon gevonden", + "We were unable to access your microphone. Please check your browser settings and try again.": "We hebben geen toegang tot uw microfoon. Controleer uw browserinstellingen en probeer het opnieuw.", + "Unable to access your microphone": "Geen toegang tot uw microfoon", + "Feeling experimental? Labs are the best way to get things early, test out new features and help shape them before they actually launch. Learn more.": "Zin in een experiment? Labs is de beste manier om dingen vroeg te krijgen, nieuwe functies uit te testen en ze te helpen vormen voordat ze daadwerkelijk worden gelanceerd. Lees meer.", + "Your access token gives full access to your account. Do not share it with anyone.": "Uw toegangstoken geeft u toegang to uw account. Deel hem niet met anderen.", + "Access Token": "Toegangstoken", + "Spaces are a new way to group rooms and people. To join an existing space you'll need an invite.": "Spaces zijn de nieuwe manier om gesprekken en personen te groeperen. Om aan een bestaande space deel te nemen heeft u een uitnodiging nodig.", + "Please enter a name for the space": "Vul een naam in voor deze space", + "Connecting": "Verbinden", + "Allow Peer-to-Peer for 1:1 calls (if you enable this, the other party might be able to see your IP address)": "Peer-to-peer voor 1op1 oproepen toestaan (als u dit inschakelt kunnen andere personen mogelijk uw ipadres zien)", + "Beta available for web, desktop and Android. Some features may be unavailable on your homeserver.": "Beta beschikbaar voor web, desktop en Android. Sommige functies zijn nog niet beschikbaar op uw homeserver.", + "You can leave the beta any time from settings or tapping on a beta badge, like the one above.": "U kunt de beta elk moment verlaten via instellingen of door op de beta badge hierboven te klikken.", + "%(brand)s will reload with Spaces enabled. Communities and custom tags will be hidden.": "%(brand)s zal herladen met Spaces ingeschakeld. Gemeenschappen en labels worden verborgen.", + "Beta available for web, desktop and Android. Thank you for trying the beta.": "Beta beschikbaar voor web, desktop en Android. Bedankt dat u de beta wilt proberen.", + "%(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "%(brand)s zal herladen met Spaces uitgeschakeld. Gemeenschappen en labels zullen weer zichtbaar worden.", + "Spaces are a new way to group rooms and people.": "Spaces zijn de nieuwe manier om gesprekken en personen te groeperen." } From 9e981ae1189b6649fa643abed9cdde6894f9d19b Mon Sep 17 00:00:00 2001 From: Jeff Huang Date: Wed, 12 May 2021 02:44:24 +0000 Subject: [PATCH 0384/1449] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (2959 of 2959 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/zh_Hant/ --- src/i18n/strings/zh_Hant.json | 37 ++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index 2dff300c18..51ebb36dc0 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -3322,5 +3322,40 @@ "%(count)s results in all spaces|other": "所有空間中有 %(count)s 個結果", "You have no ignored users.": "您沒有忽略的使用者。", "Play": "播放", - "Pause": "暫停" + "Pause": "暫停", + "This is an experimental feature. For now, new users receiving an invite will have to open the invite on to actually join.": "這是實驗性功能。目前,收到邀請的新使用者必須在 上開啟邀請才能真的加入。", + "To join %(spaceName)s, turn on the Spaces beta": "要加入 %(spaceName)s,請開啟空間測試版", + "To view %(spaceName)s, turn on the Spaces beta": "要檢視 %(spaceName)s,開啟空間測試版", + "Select a room below first": "首先選取一個聊天室", + "Communities are changing to Spaces": "社群正在變更為空間", + "Join the beta": "加入測試版", + "Leave the beta": "離開測試版", + "Beta": "測試", + "Tap for more info": "點擊以取得更多資訊", + "Spaces is a beta feature": "空間為測試功能", + "Want to add a new room instead?": "想要新增新聊天室嗎?", + "Adding rooms... (%(progress)s out of %(count)s)|one": "正在新增聊天室……", + "Adding rooms... (%(progress)s out of %(count)s)|other": "正在新增聊天室……(%(count)s 中的第 %(progress)s 個)", + "Not all selected were added": "並非所有選定的都被新增了", + "You can add existing spaces to a space.": "您可以新增既有的空間至空間中。", + "Feeling experimental?": "想要來點實驗嗎?", + "You are not allowed to view this server's rooms list": "您不被允許檢視此伺服器的聊天室清單", + "Error processing voice message": "處理語音訊息時發生錯誤", + "We didn't find a microphone on your device. Please check your settings and try again.": "我們在您的裝置上找不到麥克風。請檢查您的設定並再試一次。", + "No microphone found": "找不到麥克風", + "We were unable to access your microphone. Please check your browser settings and try again.": "我們無法存取您的麥克風。請檢查您的瀏覽器設定並再試一次。", + "Unable to access your microphone": "無法存取您的麥克風", + "Feeling experimental? Labs are the best way to get things early, test out new features and help shape them before they actually launch. Learn more.": "想要來點實驗嗎?實驗室是儘早取得成果,測試新功能並在實際發佈前協助塑造它們的最佳方式。取得更多資訊。", + "Your access token gives full access to your account. Do not share it with anyone.": "您的存取權杖可給您帳號完整的存取權限。不要將其與任何人分享。", + "Access Token": "存取權杖", + "Spaces are a new way to group rooms and people. To join an existing space you'll need an invite.": "空間是將聊天室與人們分組的一種新方式。要加入既有的空間,您需要邀請。", + "Please enter a name for the space": "請輸入空間名稱", + "Connecting": "正在連線", + "Allow Peer-to-Peer for 1:1 calls (if you enable this, the other party might be able to see your IP address)": "允許在 1:1 通話中使用點對點通訊(若您啟用此功能,對方就能看到您的 IP 位置)", + "Beta available for web, desktop and Android. Some features may be unavailable on your homeserver.": "供網頁、桌面與 Android 使用的測試版。部份功能可能在您的家伺服器上不可用。", + "You can leave the beta any time from settings or tapping on a beta badge, like the one above.": "您可以隨時從設定中退出測試版,或是點擊測試版徽章,例如上面那個。", + "%(brand)s will reload with Spaces enabled. Communities and custom tags will be hidden.": "%(brand)s 將在啟用空間的情況下重新載入。社群與自訂標籤將會隱藏。", + "Beta available for web, desktop and Android. Thank you for trying the beta.": "測試版可用於網路、桌面與 Android。感謝您試用測試版。", + "%(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "%(brand)s 將在停用空間的情況下重新載入。社群與自訂標籤將再次可見。", + "Spaces are a new way to group rooms and people.": "空間是將聊天室與人們分組的一種新方式。" } From 3169f75e909ceb4d5d2d7c677efb07b9a1515d5d Mon Sep 17 00:00:00 2001 From: waclaw66 Date: Wed, 12 May 2021 08:21:58 +0000 Subject: [PATCH 0385/1449] Translated using Weblate (Czech) Currently translated at 100.0% (2959 of 2959 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 | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/cs.json b/src/i18n/strings/cs.json index c9dd63f637..6d4cb953cc 100644 --- a/src/i18n/strings/cs.json +++ b/src/i18n/strings/cs.json @@ -3236,5 +3236,40 @@ "Pause": "Pozastavit", "Enter your Security Phrase a second time to confirm it.": "Zadejte bezpečnostní frázi podruhé a potvrďte ji.", "Pick rooms or conversations to add. This is just a space for you, no one will be informed. You can add more later.": "Vyberte místnosti nebo konverzace, které chcete přidat. Toto je prostor pouze pro vás, nikdo nebude informován. Později můžete přidat další.", - "You have no ignored users.": "Nemáte žádné ignorované uživatele." + "You have no ignored users.": "Nemáte žádné ignorované uživatele.", + "This is an experimental feature. For now, new users receiving an invite will have to open the invite on to actually join.": "Jedná se o experimentální funkci. Noví uživatelé, kteří obdrží pozvánku, ji budou muset otevřít na , aby se mohli připojit.", + "To join %(spaceName)s, turn on the Spaces beta": "Pro připojení k %(spaceName)s, zapněte Prostory beta", + "To view %(spaceName)s, turn on the Spaces beta": "Pro zobrazení %(spaceName)s, zapněte Prostory beta", + "Select a room below first": "Nejprve si vyberte místnost níže", + "Communities are changing to Spaces": "Skupiny se mění na Prostory", + "Join the beta": "Připojit se k beta verzi", + "Leave the beta": "Opustit beta verzi", + "Beta": "Beta", + "Tap for more info": "Klepněte pro více informací", + "Spaces is a beta feature": "Prostory jsou beta verze", + "Want to add a new room instead?": "Chcete místo toho přidat novou místnost?", + "Adding rooms... (%(progress)s out of %(count)s)|one": "Přidávání místnosti...", + "Adding rooms... (%(progress)s out of %(count)s)|other": "Přidávání místností... (%(progress)s z %(count)s)", + "Not all selected were added": "Ne všechny vybrané byly přidány", + "You can add existing spaces to a space.": "Do prostoru můžete přidat existující prostory.", + "Feeling experimental?": "Chcete experimentovat?", + "You are not allowed to view this server's rooms list": "Namáte oprávnění zobrazit seznam místností tohoto serveru", + "Error processing voice message": "Chyba při zpracování hlasové zprávy", + "We didn't find a microphone on your device. Please check your settings and try again.": "Ve vašem zařízení nebyl nalezen žádný mikrofon. Zkontrolujte prosím nastavení a zkuste to znovu.", + "No microphone found": "Nebyl nalezen žádný mikrofon", + "We were unable to access your microphone. Please check your browser settings and try again.": "Nepodařilo se získat přístup k vašemu mikrofonu . Zkontrolujte prosím nastavení prohlížeče a zkuste to znovu.", + "Unable to access your microphone": "Nelze získat přístup k mikrofonu", + "Feeling experimental? Labs are the best way to get things early, test out new features and help shape them before they actually launch. Learn more.": "Chcete experimentovat? Laboratoře jsou nejlepším způsobem, jak získat novinky v raném stádiu, vyzkoušet nové funkce a pomoci je formovat ještě před jejich spuštěním. Zjistěte více.", + "Your access token gives full access to your account. Do not share it with anyone.": "Přístupový token vám umožní plný přístup k účtu. Nikomu ho nesdělujte.", + "Access Token": "Přístupový token", + "Spaces are a new way to group rooms and people. To join an existing space you'll need an invite.": "Prostory představují nový způsob seskupování místností a osob. Chcete-li se připojit k existujícímu prostoru, potřebujete pozvánku.", + "Please enter a name for the space": "Zadejte prosím název prostoru", + "Connecting": "Spojování", + "Allow Peer-to-Peer for 1:1 calls (if you enable this, the other party might be able to see your IP address)": "Povolit Peer-to-Peer pro hovory 1:1 (pokud tuto funkci povolíte, druhá strana může vidět vaši IP adresu)", + "Beta available for web, desktop and Android. Some features may be unavailable on your homeserver.": "Beta verze je k dispozici pro web, desktop a Android. Některé funkce mohou být na vašem domovském serveru nedostupné.", + "You can leave the beta any time from settings or tapping on a beta badge, like the one above.": "Beta verzi můžete kdykoli opustit v nastavení nebo klepnutím na štítek beta verze, jako je ten výše.", + "%(brand)s will reload with Spaces enabled. Communities and custom tags will be hidden.": "%(brand)s se znovu načte s povolenými Prostory. Skupiny a vlastní značky budou skryty.", + "Beta available for web, desktop and Android. Thank you for trying the beta.": "Beta verze je k dispozici pro web, desktop a Android. Děkujeme vám za vyzkoušení beta verze.", + "%(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "%(brand)s se znovu načte s vypnutými Prostory. Skupiny a vlastní značky budou opět viditelné.", + "Spaces are a new way to group rooms and people.": "Prostory představují nový způsob seskupování místností a osob." } From 68fcc259d0fbe6c44ef768c8811ee88bc782cb83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Tue, 11 May 2021 17:04:44 +0000 Subject: [PATCH 0386/1449] Translated using Weblate (Estonian) Currently translated at 100.0% (2959 of 2959 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/et/ --- src/i18n/strings/et.json | 43 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index fc42ad73dd..88480ceb6e 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -652,7 +652,7 @@ "A session's public name is visible to people you communicate with": "Sessiooni avalik nimi on nähtav neile, kellega sa suhtled", "%(brand)s collects anonymous analytics to allow us to improve the application.": "Võimaldamaks meil rakendust parandada kogub %(brand)s anonüümset teavet rakenduse kasutuse kohta.", "Privacy is important to us, so we don't collect any personal or identifiable data for our analytics.": "Privaatsus on meile oluline ning seega me ei kogu ei isiklikke ega isikustatavaid andmeid.", - "Learn more about how we use analytics.": "Loe lisaks kuidas me kasutama analüütikat.", + "Learn more about how we use analytics.": "Loe lisaks selles kohta, kuidas me kasutame analüütikat.", "No media permissions": "Meediaõigused puuduvad", "You may need to manually permit %(brand)s to access your microphone/webcam": "Sa võib-olla pead andma %(brand)s'ile loa mikrofoni ja veebikaamera kasutamiseks", "Missing media permissions, click the button below to request.": "Meediaga seotud õigused puuduvad. Nende nõutamiseks klõpsi järgnevat nuppu.", @@ -1202,8 +1202,8 @@ "eg: @bot:* or example.org": "näiteks: @bot:* või example.org", "Subscribed lists": "Tellitud loendid", "Subscribe": "Telli", - "Start automatically after system login": "Käivita automaatselt peale arvutisse sisselogimist", - "Always show the window menu bar": "Näita alati aknas menüüriba", + "Start automatically after system login": "Käivita Element automaatselt peale arvutisse sisselogimist", + "Always show the window menu bar": "Näita aknas alati menüüriba", "Preferences": "Eelistused", "Room list": "Jututubade loend", "Timeline": "Ajajoon", @@ -3297,5 +3297,40 @@ "%(count)s results in all spaces|other": "%(count)s tulemust kõikides kogukonnakeskustes", "You have no ignored users.": "Sa ei ole veel kedagi eiranud.", "Play": "Esita", - "Pause": "Peata" + "Pause": "Peata", + "Feeling experimental? Labs are the best way to get things early, test out new features and help shape them before they actually launch. Learn more.": "Kas sa tahaksid katsetada? Sa tutvud meie rakenduse uuendustega teistest varem ja võib-olla isegi saad mõjutada arenduse lõpptulemust. Lisateavet liad siit.", + "This is an experimental feature. For now, new users receiving an invite will have to open the invite on to actually join.": "See on katseline funktsionaalsus. Seetõttu uued kutse saanud kasutajad peavad tegelikuks liitumiseks avama kutse siin .", + "To join %(spaceName)s, turn on the Spaces beta": "%(spaceName)s kogukonnakeskusega liitumiseks lülita sisse vastav katseline funktsionaalsus", + "To view %(spaceName)s, turn on the Spaces beta": "%(spaceName)s kogukonnakeskuse vaatamiseks lülita sisse vastav katseline funktsionaalsus", + "Select a room below first": "Esmalt vali alljärgnevast üks jututuba", + "Communities are changing to Spaces": "Seniste kogukondade asemele tulevad kogukonnakeskused", + "Join the beta": "Hakka kasutama beetaversiooni", + "Leave the beta": "Lõpeta beetaversiooni kasutamine", + "Beta": "Beetaversioon", + "Tap for more info": "Lisateabe jaoks klõpsi", + "Spaces is a beta feature": "Kogukonnakeskused on veel katsetamisjärgus funktsionaalsus", + "Want to add a new room instead?": "Kas sa selle asemel soovid lisada jututuba?", + "Adding rooms... (%(progress)s out of %(count)s)|one": "Lisan jututuba...", + "Adding rooms... (%(progress)s out of %(count)s)|other": "Lisan jututubasid... (%(progress)s/%(count)s)", + "Not all selected were added": "Kõiki valituid me ei lisanud", + "You can add existing spaces to a space.": "Sa võid kogukonnakeskusele lisada ka teisi kogukonnakeskuseid.", + "Feeling experimental?": "Kas sa tahaksid natukene katsetada?", + "You are not allowed to view this server's rooms list": "Sul puuduvad õigused selle serveri jututubade loendi vaatamiseks", + "Error processing voice message": "Viga häälsõnumi töötlemisel", + "We didn't find a microphone on your device. Please check your settings and try again.": "Me ei suutnud sinu seadmest leida mikrofoni. Palun kontrolli seadistusi ja proovi siis uuesti.", + "No microphone found": "Mikrofoni ei leidu", + "We were unable to access your microphone. Please check your browser settings and try again.": "Meil puudub ligipääs sinu mikrofonile. Palun kontrolli oma veebibrauseri seadistusi ja proovi uuesti.", + "Unable to access your microphone": "Puudub ligipääs mikrofonile", + "Your access token gives full access to your account. Do not share it with anyone.": "Sinu pääsuluba annab täismahulise ligipääsu sinu kasutajakontole. Palun ära jaga seda teistega.", + "Access Token": "Pääsuluba", + "Spaces are a new way to group rooms and people. To join an existing space you'll need an invite.": "Kogukonnakeskused on uus viis inimeste ja jututubade ühendamiseks. Kogukonnakeskusega liitumiseks vajad sa kutset.", + "Please enter a name for the space": "Palun sisesta kogukonnakeskuse nimi", + "Connecting": "Kõne on ühendamisel", + "Allow Peer-to-Peer for 1:1 calls (if you enable this, the other party might be able to see your IP address)": "Kasuta võrdõigusvõrku 1:1 kõnede jaoks (kui sa P2P-võrgu sisse lülitad, siis teine osapool ilmselt näeb sinu IP-aadressi)", + "Beta available for web, desktop and Android. Some features may be unavailable on your homeserver.": "Rakenduse beetaversioon on saadaval veebirakendusena, töölauarakendusena ja Androidi jaoks. Kõik funtsionaalsused ei pruugi sinu koduserveri poolt olla toetatud.", + "You can leave the beta any time from settings or tapping on a beta badge, like the one above.": "Sa võid beetaversiooni kasutamise lõpetada niipea, kui tahad. Selleks klõpsi beeta-silti, mida näed siin samas ülal.", + "%(brand)s will reload with Spaces enabled. Communities and custom tags will be hidden.": "Käivitame %(brand)s uuesti nii, et kogukonnakeskused on kasutusel. Vana tüüpi kogukonnad ja kohandatud sildid on siis välja lülitatud.", + "%(brand)s will reload with Spaces disabled. Communities and custom tags will be visible again.": "Käivitame %(brand)s uuesti nii, et kogukonnakeskused ei ole kasutusel. Vana tüüpi kogukonnad ja kohandatud sildid saavad jälle olema kasutusel.", + "Beta available for web, desktop and Android. Thank you for trying the beta.": "Rakenduse beetaversioon on saadaval veebirakendusena, töölauarakendusena ja Androidi jaoks. Tänud, et oled huviline katsetama meie rakendust.", + "Spaces are a new way to group rooms and people.": "Kogukonnakeskused on uus viis jututubade ja inimeste ühendamiseks." } From 9beb2b8d789bcda4da0fc8bc0a788b8dfe8e5814 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 12 May 2021 21:15:17 -0600 Subject: [PATCH 0387/1449] Try putting room list handling behind a lock Some of the logs relating to room list corruption appear to be badly timed race conditions so we'll try to linearize them here. --- src/stores/room-list/algorithms/Algorithm.ts | 315 ++++++++++--------- src/utils/MultiLock.ts | 30 ++ 2 files changed, 193 insertions(+), 152 deletions(-) create mode 100644 src/utils/MultiLock.ts diff --git a/src/stores/room-list/algorithms/Algorithm.ts b/src/stores/room-list/algorithms/Algorithm.ts index 024c484c41..395591d321 100644 --- a/src/stores/room-list/algorithms/Algorithm.ts +++ b/src/stores/room-list/algorithms/Algorithm.ts @@ -34,6 +34,7 @@ import { OrderingAlgorithm } from "./list-ordering/OrderingAlgorithm"; import { getListAlgorithmInstance } from "./list-ordering"; import SettingsStore from "../../../settings/SettingsStore"; import { VisibilityProvider } from "../filters/VisibilityProvider"; +import {MultiLock} from "../../../utils/MultiLock"; /** * Fired when the Algorithm has determined a list has been updated. @@ -77,6 +78,7 @@ export class Algorithm extends EventEmitter { } = {}; private allowedByFilter: Map = new Map(); private allowedRoomsByFilters: Set = new Set(); + private handlerLock = new MultiLock(); /** * Set to true to suspend emissions of algorithm updates. @@ -679,191 +681,200 @@ export class Algorithm extends EventEmitter { public async handleRoomUpdate(room: Room, cause: RoomUpdateCause): Promise { if (SettingsStore.getValue("advancedRoomListLogging")) { // TODO: Remove debug: https://github.com/vector-im/element-web/issues/14602 - console.log(`Handle room update for ${room.roomId} called with cause ${cause}`); + console.log(`Acquiring lock for ${room.roomId} with cause ${cause}`); } - if (!this.algorithms) throw new Error("Not ready: no algorithms to determine tags from"); - - // Note: check the isSticky against the room ID just in case the reference is wrong - const isSticky = this._stickyRoom && this._stickyRoom.room && this._stickyRoom.room.roomId === room.roomId; - if (cause === RoomUpdateCause.NewRoom) { - const isForLastSticky = this._lastStickyRoom && this._lastStickyRoom.room === room; - const roomTags = this.roomIdsToTags[room.roomId]; - const hasTags = roomTags && roomTags.length > 0; - - // Don't change the cause if the last sticky room is being re-added. If we fail to - // pass the cause through as NewRoom, we'll fail to lie to the algorithm and thus - // lose the room. - if (hasTags && !isForLastSticky) { - console.warn(`${room.roomId} is reportedly new but is already known - assuming TagChange instead`); - cause = RoomUpdateCause.PossibleTagChange; + const release = await this.handlerLock.acquire(room.roomId); + try { + if (SettingsStore.getValue("advancedRoomListLogging")) { + // TODO: Remove debug: https://github.com/vector-im/element-web/issues/14602 + console.log(`Handle room update for ${room.roomId} called with cause ${cause}`); } + if (!this.algorithms) throw new Error("Not ready: no algorithms to determine tags from"); - // Check to see if the room is known first - let knownRoomRef = this.rooms.includes(room); - if (hasTags && !knownRoomRef) { - console.warn(`${room.roomId} might be a reference change - attempting to update reference`); - this.rooms = this.rooms.map(r => r.roomId === room.roomId ? room : r); - knownRoomRef = this.rooms.includes(room); - if (!knownRoomRef) { - console.warn(`${room.roomId} is still not referenced. It may be sticky.`); + // Note: check the isSticky against the room ID just in case the reference is wrong + const isSticky = this._stickyRoom && this._stickyRoom.room && this._stickyRoom.room.roomId === room.roomId; + if (cause === RoomUpdateCause.NewRoom) { + const isForLastSticky = this._lastStickyRoom && this._lastStickyRoom.room === room; + const roomTags = this.roomIdsToTags[room.roomId]; + const hasTags = roomTags && roomTags.length > 0; + + // Don't change the cause if the last sticky room is being re-added. If we fail to + // pass the cause through as NewRoom, we'll fail to lie to the algorithm and thus + // lose the room. + if (hasTags && !isForLastSticky) { + console.warn(`${room.roomId} is reportedly new but is already known - assuming TagChange instead`); + cause = RoomUpdateCause.PossibleTagChange; + } + + // Check to see if the room is known first + let knownRoomRef = this.rooms.includes(room); + if (hasTags && !knownRoomRef) { + console.warn(`${room.roomId} might be a reference change - attempting to update reference`); + this.rooms = this.rooms.map(r => r.roomId === room.roomId ? room : r); + knownRoomRef = this.rooms.includes(room); + if (!knownRoomRef) { + console.warn(`${room.roomId} is still not referenced. It may be sticky.`); + } + } + + // If we have tags for a room and don't have the room referenced, something went horribly + // wrong - the reference should have been updated above. + if (hasTags && !knownRoomRef && !isSticky) { + throw new Error(`${room.roomId} is missing from room array but is known - trying to find duplicate`); + } + + // Like above, update the reference to the sticky room if we need to + if (hasTags && isSticky) { + // Go directly in and set the sticky room's new reference, being careful not + // to trigger a sticky room update ourselves. + this._stickyRoom.room = room; + } + + // If after all that we're still a NewRoom update, add the room if applicable. + // We don't do this for the sticky room (because it causes duplication issues) + // or if we know about the reference (as it should be replaced). + if (cause === RoomUpdateCause.NewRoom && !isSticky && !knownRoomRef) { + this.rooms.push(room); } } - // If we have tags for a room and don't have the room referenced, something went horribly - // wrong - the reference should have been updated above. - if (hasTags && !knownRoomRef && !isSticky) { - throw new Error(`${room.roomId} is missing from room array but is known - trying to find duplicate`); - } + let didTagChange = false; + if (cause === RoomUpdateCause.PossibleTagChange) { + const oldTags = this.roomIdsToTags[room.roomId] || []; + const newTags = this.getTagsForRoom(room); + const diff = arrayDiff(oldTags, newTags); + if (diff.removed.length > 0 || diff.added.length > 0) { + for (const rmTag of diff.removed) { + if (SettingsStore.getValue("advancedRoomListLogging")) { + // TODO: Remove debug: https://github.com/vector-im/element-web/issues/14602 + console.log(`Removing ${room.roomId} from ${rmTag}`); + } + const algorithm: OrderingAlgorithm = this.algorithms[rmTag]; + if (!algorithm) throw new Error(`No algorithm for ${rmTag}`); + await algorithm.handleRoomUpdate(room, RoomUpdateCause.RoomRemoved); + this._cachedRooms[rmTag] = algorithm.orderedRooms; + this.recalculateFilteredRoomsForTag(rmTag); // update filter to re-sort the list + this.recalculateStickyRoom(rmTag); // update sticky room to make sure it moves if needed + } + for (const addTag of diff.added) { + if (SettingsStore.getValue("advancedRoomListLogging")) { + // TODO: Remove debug: https://github.com/vector-im/element-web/issues/14602 + console.log(`Adding ${room.roomId} to ${addTag}`); + } + const algorithm: OrderingAlgorithm = this.algorithms[addTag]; + if (!algorithm) throw new Error(`No algorithm for ${addTag}`); + await algorithm.handleRoomUpdate(room, RoomUpdateCause.NewRoom); + this._cachedRooms[addTag] = algorithm.orderedRooms; + } - // Like above, update the reference to the sticky room if we need to - if (hasTags && isSticky) { - // Go directly in and set the sticky room's new reference, being careful not - // to trigger a sticky room update ourselves. - this._stickyRoom.room = room; - } + // Update the tag map so we don't regen it in a moment + this.roomIdsToTags[room.roomId] = newTags; - // If after all that we're still a NewRoom update, add the room if applicable. - // We don't do this for the sticky room (because it causes duplication issues) - // or if we know about the reference (as it should be replaced). - if (cause === RoomUpdateCause.NewRoom && !isSticky && !knownRoomRef) { - this.rooms.push(room); - } - } - - let didTagChange = false; - if (cause === RoomUpdateCause.PossibleTagChange) { - const oldTags = this.roomIdsToTags[room.roomId] || []; - const newTags = this.getTagsForRoom(room); - const diff = arrayDiff(oldTags, newTags); - if (diff.removed.length > 0 || diff.added.length > 0) { - for (const rmTag of diff.removed) { if (SettingsStore.getValue("advancedRoomListLogging")) { // TODO: Remove debug: https://github.com/vector-im/element-web/issues/14602 - console.log(`Removing ${room.roomId} from ${rmTag}`); + console.log(`Changing update cause for ${room.roomId} to Timeline to sort rooms`); } - const algorithm: OrderingAlgorithm = this.algorithms[rmTag]; - if (!algorithm) throw new Error(`No algorithm for ${rmTag}`); - await algorithm.handleRoomUpdate(room, RoomUpdateCause.RoomRemoved); - this._cachedRooms[rmTag] = algorithm.orderedRooms; - this.recalculateFilteredRoomsForTag(rmTag); // update filter to re-sort the list - this.recalculateStickyRoom(rmTag); // update sticky room to make sure it moves if needed - } - for (const addTag of diff.added) { - if (SettingsStore.getValue("advancedRoomListLogging")) { - // TODO: Remove debug: https://github.com/vector-im/element-web/issues/14602 - console.log(`Adding ${room.roomId} to ${addTag}`); - } - const algorithm: OrderingAlgorithm = this.algorithms[addTag]; - if (!algorithm) throw new Error(`No algorithm for ${addTag}`); - await algorithm.handleRoomUpdate(room, RoomUpdateCause.NewRoom); - this._cachedRooms[addTag] = algorithm.orderedRooms; - } - - // Update the tag map so we don't regen it in a moment - this.roomIdsToTags[room.roomId] = newTags; - - if (SettingsStore.getValue("advancedRoomListLogging")) { - // TODO: Remove debug: https://github.com/vector-im/element-web/issues/14602 - console.log(`Changing update cause for ${room.roomId} to Timeline to sort rooms`); - } - cause = RoomUpdateCause.Timeline; - didTagChange = true; - } else { - if (SettingsStore.getValue("advancedRoomListLogging")) { - // TODO: Remove debug: https://github.com/vector-im/element-web/issues/14602 - console.log(`Received no-op update for ${room.roomId} - changing to Timeline update`); - } - cause = RoomUpdateCause.Timeline; - } - - if (didTagChange && isSticky) { - // Manually update the tag for the sticky room without triggering a sticky room - // update. The update will be handled implicitly by the sticky room handling and - // requires no changes on our part, if we're in the middle of a sticky room change. - if (this._lastStickyRoom) { - this._stickyRoom = { - room, - tag: this.roomIdsToTags[room.roomId][0], - position: 0, // right at the top as it changed tags - }; + cause = RoomUpdateCause.Timeline; + didTagChange = true; } else { - // We have to clear the lock as the sticky room change will trigger updates. - await this.setStickyRoom(room); + if (SettingsStore.getValue("advancedRoomListLogging")) { + // TODO: Remove debug: https://github.com/vector-im/element-web/issues/14602 + console.log(`Received no-op update for ${room.roomId} - changing to Timeline update`); + } + cause = RoomUpdateCause.Timeline; + } + + if (didTagChange && isSticky) { + // Manually update the tag for the sticky room without triggering a sticky room + // update. The update will be handled implicitly by the sticky room handling and + // requires no changes on our part, if we're in the middle of a sticky room change. + if (this._lastStickyRoom) { + this._stickyRoom = { + room, + tag: this.roomIdsToTags[room.roomId][0], + position: 0, // right at the top as it changed tags + }; + } else { + // We have to clear the lock as the sticky room change will trigger updates. + await this.setStickyRoom(room); + } } } - } - // If the update is for a room change which might be the sticky room, prevent it. We - // need to make sure that the causes (NewRoom and RoomRemoved) are still triggered though - // as the sticky room relies on this. - if (cause !== RoomUpdateCause.NewRoom && cause !== RoomUpdateCause.RoomRemoved) { - if (this.stickyRoom === room) { - if (SettingsStore.getValue("advancedRoomListLogging")) { - // TODO: Remove debug: https://github.com/vector-im/element-web/issues/14602 - console.warn(`[RoomListDebug] Received ${cause} update for sticky room ${room.roomId} - ignoring`); + // If the update is for a room change which might be the sticky room, prevent it. We + // need to make sure that the causes (NewRoom and RoomRemoved) are still triggered though + // as the sticky room relies on this. + if (cause !== RoomUpdateCause.NewRoom && cause !== RoomUpdateCause.RoomRemoved) { + if (this.stickyRoom === room) { + if (SettingsStore.getValue("advancedRoomListLogging")) { + // TODO: Remove debug: https://github.com/vector-im/element-web/issues/14602 + console.warn(`[RoomListDebug] Received ${cause} update for sticky room ${room.roomId} - ignoring`); + } + return false; } - return false; } - } - if (!this.roomIdsToTags[room.roomId]) { - if (CAUSES_REQUIRING_ROOM.includes(cause)) { + if (!this.roomIdsToTags[room.roomId]) { + if (CAUSES_REQUIRING_ROOM.includes(cause)) { + if (SettingsStore.getValue("advancedRoomListLogging")) { + // TODO: Remove debug: https://github.com/vector-im/element-web/issues/14602 + console.warn(`Skipping tag update for ${room.roomId} because we don't know about the room`); + } + return false; + } + if (SettingsStore.getValue("advancedRoomListLogging")) { // TODO: Remove debug: https://github.com/vector-im/element-web/issues/14602 - console.warn(`Skipping tag update for ${room.roomId} because we don't know about the room`); + console.log(`[RoomListDebug] Updating tags for room ${room.roomId} (${room.name})`); + } + + // Get the tags for the room and populate the cache + const roomTags = this.getTagsForRoom(room).filter(t => !isNullOrUndefined(this.cachedRooms[t])); + + // "This should never happen" condition - we specify DefaultTagID.Untagged in getTagsForRoom(), + // which means we should *always* have a tag to go off of. + if (!roomTags.length) throw new Error(`Tags cannot be determined for ${room.roomId}`); + + this.roomIdsToTags[room.roomId] = roomTags; + + if (SettingsStore.getValue("advancedRoomListLogging")) { + // TODO: Remove debug: https://github.com/vector-im/element-web/issues/14602 + console.log(`[RoomListDebug] Updated tags for ${room.roomId}:`, roomTags); } - return false; } if (SettingsStore.getValue("advancedRoomListLogging")) { // TODO: Remove debug: https://github.com/vector-im/element-web/issues/14602 - console.log(`[RoomListDebug] Updating tags for room ${room.roomId} (${room.name})`); + console.log(`[RoomListDebug] Reached algorithmic handling for ${room.roomId} and cause ${cause}`); } - // Get the tags for the room and populate the cache - const roomTags = this.getTagsForRoom(room).filter(t => !isNullOrUndefined(this.cachedRooms[t])); + const tags = this.roomIdsToTags[room.roomId]; + if (!tags) { + console.warn(`No tags known for "${room.name}" (${room.roomId})`); + return false; + } - // "This should never happen" condition - we specify DefaultTagID.Untagged in getTagsForRoom(), - // which means we should *always* have a tag to go off of. - if (!roomTags.length) throw new Error(`Tags cannot be determined for ${room.roomId}`); + let changed = didTagChange; + for (const tag of tags) { + const algorithm: OrderingAlgorithm = this.algorithms[tag]; + if (!algorithm) throw new Error(`No algorithm for ${tag}`); - this.roomIdsToTags[room.roomId] = roomTags; + await algorithm.handleRoomUpdate(room, cause); + this._cachedRooms[tag] = algorithm.orderedRooms; + + // Flag that we've done something + this.recalculateFilteredRoomsForTag(tag); // update filter to re-sort the list + this.recalculateStickyRoom(tag); // update sticky room to make sure it appears if needed + changed = true; + } if (SettingsStore.getValue("advancedRoomListLogging")) { // TODO: Remove debug: https://github.com/vector-im/element-web/issues/14602 - console.log(`[RoomListDebug] Updated tags for ${room.roomId}:`, roomTags); + console.log(`[RoomListDebug] Finished handling ${room.roomId} with cause ${cause} (changed=${changed})`); } + return changed; + } finally { + release(); } - - if (SettingsStore.getValue("advancedRoomListLogging")) { - // TODO: Remove debug: https://github.com/vector-im/element-web/issues/14602 - console.log(`[RoomListDebug] Reached algorithmic handling for ${room.roomId} and cause ${cause}`); - } - - const tags = this.roomIdsToTags[room.roomId]; - if (!tags) { - console.warn(`No tags known for "${room.name}" (${room.roomId})`); - return false; - } - - let changed = didTagChange; - for (const tag of tags) { - const algorithm: OrderingAlgorithm = this.algorithms[tag]; - if (!algorithm) throw new Error(`No algorithm for ${tag}`); - - await algorithm.handleRoomUpdate(room, cause); - this._cachedRooms[tag] = algorithm.orderedRooms; - - // Flag that we've done something - this.recalculateFilteredRoomsForTag(tag); // update filter to re-sort the list - this.recalculateStickyRoom(tag); // update sticky room to make sure it appears if needed - changed = true; - } - - if (SettingsStore.getValue("advancedRoomListLogging")) { - // TODO: Remove debug: https://github.com/vector-im/element-web/issues/14602 - console.log(`[RoomListDebug] Finished handling ${room.roomId} with cause ${cause} (changed=${changed})`); - } - return changed; } } diff --git a/src/utils/MultiLock.ts b/src/utils/MultiLock.ts new file mode 100644 index 0000000000..97cc30306a --- /dev/null +++ b/src/utils/MultiLock.ts @@ -0,0 +1,30 @@ +/* +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 {EnhancedMap} from "./maps"; +import AwaitLock from "await-lock"; + +export type DoneFn = () => void; + +export class MultiLock { + private locks = new EnhancedMap(); + + public async acquire(key: string): Promise { + const lock = this.locks.getOrCreate(key, new AwaitLock()); + await lock.acquireAsync(); + return () => lock.release(); + } +} From deab424c935fa9949ab0b9b8723b192ce072b0f4 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 12 May 2021 21:19:31 -0600 Subject: [PATCH 0388/1449] Appease the linter --- src/stores/room-list/algorithms/Algorithm.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/stores/room-list/algorithms/Algorithm.ts b/src/stores/room-list/algorithms/Algorithm.ts index 395591d321..207035ffce 100644 --- a/src/stores/room-list/algorithms/Algorithm.ts +++ b/src/stores/room-list/algorithms/Algorithm.ts @@ -720,7 +720,7 @@ export class Algorithm extends EventEmitter { // If we have tags for a room and don't have the room referenced, something went horribly // wrong - the reference should have been updated above. if (hasTags && !knownRoomRef && !isSticky) { - throw new Error(`${room.roomId} is missing from room array but is known - trying to find duplicate`); + throw new Error(`${room.roomId} is missing from room array but is known`); } // Like above, update the reference to the sticky room if we need to @@ -808,7 +808,9 @@ export class Algorithm extends EventEmitter { if (this.stickyRoom === room) { if (SettingsStore.getValue("advancedRoomListLogging")) { // TODO: Remove debug: https://github.com/vector-im/element-web/issues/14602 - console.warn(`[RoomListDebug] Received ${cause} update for sticky room ${room.roomId} - ignoring`); + console.warn( + `[RoomListDebug] Received ${cause} update for sticky room ${room.roomId} - ignoring`, + ); } return false; } @@ -870,7 +872,9 @@ export class Algorithm extends EventEmitter { if (SettingsStore.getValue("advancedRoomListLogging")) { // TODO: Remove debug: https://github.com/vector-im/element-web/issues/14602 - console.log(`[RoomListDebug] Finished handling ${room.roomId} with cause ${cause} (changed=${changed})`); + console.log( + `[RoomListDebug] Finished handling ${room.roomId} with cause ${cause} (changed=${changed})`, + ); } return changed; } finally { From 423c515708b7cbc50ad1139a50d259501057bd6b Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 13 May 2021 09:46:45 +0100 Subject: [PATCH 0389/1449] Consolidate AddExistingToSpace between Dialog and Just Me integrated flow --- .../dialogs/_AddExistingToSpaceDialog.scss | 168 +++++----- src/components/structures/SpaceRoomView.tsx | 59 +--- .../dialogs/AddExistingToSpaceDialog.tsx | 289 +++++++++--------- 3 files changed, 243 insertions(+), 273 deletions(-) diff --git a/res/css/views/dialogs/_AddExistingToSpaceDialog.scss b/res/css/views/dialogs/_AddExistingToSpaceDialog.scss index 91947be76a..575faf4a97 100644 --- a/res/css/views/dialogs/_AddExistingToSpaceDialog.scss +++ b/res/css/views/dialogs/_AddExistingToSpaceDialog.scss @@ -105,6 +105,90 @@ limitations under the License. mask-position: center; } } + + .mx_AddExistingToSpace_footer { + display: flex; + margin-top: 20px; + + > span { + flex-grow: 1; + font-size: $font-12px; + line-height: $font-15px; + color: $secondary-fg-color; + + .mx_ProgressBar { + height: 8px; + width: 100%; + + @mixin ProgressBarBorderRadius 8px; + } + + .mx_AddExistingToSpace_progressText { + margin-top: 8px; + font-size: $font-15px; + line-height: $font-24px; + color: $primary-fg-color; + } + + > * { + vertical-align: middle; + } + } + + .mx_AddExistingToSpace_error { + padding-left: 12px; + + > img { + align-self: center; + } + + .mx_AddExistingToSpace_errorHeading { + font-weight: $font-semi-bold; + font-size: $font-15px; + line-height: $font-18px; + color: $notice-primary-color; + } + + .mx_AddExistingToSpace_errorCaption { + margin-top: 4px; + font-size: $font-12px; + line-height: $font-15px; + color: $primary-fg-color; + } + } + + .mx_AccessibleButton { + display: inline-block; + align-self: center; + } + + .mx_AccessibleButton_kind_primary { + padding: 8px 36px; + } + + .mx_AddExistingToSpace_retryButton { + margin-left: 12px; + padding-left: 24px; + position: relative; + + &::before { + content: ''; + position: absolute; + background-color: $primary-fg-color; + mask-repeat: no-repeat; + mask-position: center; + mask-size: contain; + mask-image: url('$(res)/img/element-icons/retry.svg'); + width: 18px; + height: 18px; + left: 0; + } + } + + .mx_AccessibleButton_kind_link { + padding: 0; + } + } } .mx_AddExistingToSpaceDialog { @@ -189,88 +273,4 @@ limitations under the License. .mx_AddExistingToSpace { display: contents; } - - .mx_AddExistingToSpaceDialog_footer { - display: flex; - margin-top: 20px; - - > span { - flex-grow: 1; - font-size: $font-12px; - line-height: $font-15px; - color: $secondary-fg-color; - - .mx_ProgressBar { - height: 8px; - width: 100%; - - @mixin ProgressBarBorderRadius 8px; - } - - .mx_AddExistingToSpaceDialog_progressText { - margin-top: 8px; - font-size: $font-15px; - line-height: $font-24px; - color: $primary-fg-color; - } - - > * { - vertical-align: middle; - } - } - - .mx_AddExistingToSpaceDialog_error { - padding-left: 12px; - - > img { - align-self: center; - } - - .mx_AddExistingToSpaceDialog_errorHeading { - font-weight: $font-semi-bold; - font-size: $font-15px; - line-height: $font-18px; - color: $notice-primary-color; - } - - .mx_AddExistingToSpaceDialog_errorCaption { - margin-top: 4px; - font-size: $font-12px; - line-height: $font-15px; - color: $primary-fg-color; - } - } - - .mx_AccessibleButton { - display: inline-block; - align-self: center; - } - - .mx_AccessibleButton_kind_primary { - padding: 8px 36px; - } - - .mx_AddExistingToSpaceDialog_retryButton { - margin-left: 12px; - padding-left: 24px; - position: relative; - - &::before { - content: ''; - position: absolute; - background-color: $primary-fg-color; - mask-repeat: no-repeat; - mask-position: center; - mask-size: contain; - mask-image: url('$(res)/img/element-icons/retry.svg'); - width: 18px; - height: 18px; - left: 0; - } - } - - .mx_AccessibleButton_kind_link { - padding: 0; - } - } } diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx index 828b2ff5fe..4c4b076fdd 100644 --- a/src/components/structures/SpaceRoomView.tsx +++ b/src/components/structures/SpaceRoomView.tsx @@ -517,40 +517,6 @@ const SpaceSetupFirstRooms = ({ space, title, description, onFinished }) => { }; const SpaceAddExistingRooms = ({ space, onFinished }) => { - const [selectedToAdd, setSelectedToAdd] = useState(new Set()); - - const [busy, setBusy] = useState(false); - const [error, setError] = useState(""); - - let onClick = onFinished; - let buttonLabel = _t("Skip for now"); - if (selectedToAdd.size > 0) { - onClick = async () => { - setBusy(true); - - for (const room of selectedToAdd) { - const via = calculateRoomVia(room); - try { - await SpaceStore.instance.addRoomToSpace(space, room.roomId, via).catch(async e => { - if (e.errcode === "M_LIMIT_EXCEEDED") { - await sleep(e.data.retry_after_ms); - return SpaceStore.instance.addRoomToSpace(space, room.roomId, via); // retry - } - - throw e; - }); - } catch (e) { - console.error("Failed to add rooms to space", e); - setError(_t("Failed to add rooms to space")); - break; - } - } - setBusy(false); - onFinished(); - }; - buttonLabel = busy ? _t("Adding...") : _t("Add"); - } - return

    { _t("What do you want to organise?") }

    @@ -558,29 +524,18 @@ const SpaceAddExistingRooms = ({ space, onFinished }) => { "no one will be informed. You can add more later.") }
    - { error &&
    { error }
    } - { - if (checked) { - selectedToAdd.add(room); - } else { - selectedToAdd.delete(room); - } - setSelectedToAdd(new Set(selectedToAdd)); - }} + emptySelectionButton={ + + { _t("Skip for now") } + + } + onFinished={onFinished} />
    - - { buttonLabel } - +
    ; diff --git a/src/components/views/dialogs/AddExistingToSpaceDialog.tsx b/src/components/views/dialogs/AddExistingToSpaceDialog.tsx index 8ac68e99b7..c952614c9f 100644 --- a/src/components/views/dialogs/AddExistingToSpaceDialog.tsx +++ b/src/components/views/dialogs/AddExistingToSpaceDialog.tsx @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {useContext, useMemo, useState} from "react"; +import React, {ReactNode, useContext, useMemo, useState} from "react"; import classNames from "classnames"; import {Room} from "matrix-js-sdk/src/models/room"; import {MatrixClient} from "matrix-js-sdk/src/client"; @@ -58,14 +58,23 @@ const Entry = ({ room, checked, onChange }) => { interface IAddExistingToSpaceProps { space: Room; - selected: Set; - onChange(checked: boolean, room: Room): void; + footerPrompt?: ReactNode; + emptySelectionButton?: ReactNode; + onFinished(added: boolean): void; } -export const AddExistingToSpace: React.FC = ({ space, selected, onChange }) => { +export const AddExistingToSpace: React.FC = ({ + space, + footerPrompt, + emptySelectionButton, + onFinished, +}) => { const cli = useContext(MatrixClientContext); const visibleRooms = useMemo(() => sortRooms(cli.getVisibleRooms()), [cli]); + const [selectedToAdd, setSelectedToAdd] = useState(new Set()); + const [progress, setProgress] = useState(null); + const [error, setError] = useState(null); const [query, setQuery] = useState(""); const lcQuery = query.toLowerCase(); @@ -93,120 +102,6 @@ export const AddExistingToSpace: React.FC = ({ space, return arr; }, [[], [], []]); - return
    - - - { rooms.length > 0 ? ( -
    -

    { _t("Rooms") }

    - { rooms.map(room => { - return { - onChange(checked, room); - } : null} - />; - }) } -
    - ) : undefined } - - { spaces.length > 0 ? ( -
    -

    { _t("Spaces") }

    -
    -
    { _t("Feeling experimental?") }
    -
    { _t("You can add existing spaces to a space.") }
    -
    - { spaces.map(space => { - return { - onChange(checked, space); - } : null} - />; - }) } -
    - ) : null } - - { dms.length > 0 ? ( -
    -

    { _t("Direct Messages") }

    - { dms.map(room => { - return { - onChange(checked, room); - } : null} - />; - }) } -
    - ) : null } - - { spaces.length + rooms.length + dms.length < 1 ? - { _t("No results") } - : undefined } -
    -
    ; -}; - -const AddExistingToSpaceDialog: React.FC = ({ matrixClient: cli, space, onCreateRoomClick, onFinished }) => { - const [selectedSpace, setSelectedSpace] = useState(space); - const existingSubspaces = SpaceStore.instance.getChildSpaces(space.roomId); - const [selectedToAdd, setSelectedToAdd] = useState(new Set()); - - const [progress, setProgress] = useState(null); - const [error, setError] = useState(null); - - let spaceOptionSection; - if (existingSubspaces.length > 0) { - const options = [space, ...existingSubspaces].map((space) => { - const classes = classNames("mx_AddExistingToSpaceDialog_dropdownOption", { - mx_AddExistingToSpaceDialog_dropdownOptionActive: space === selectedSpace, - }); - return
    - - { space.name || getDisplayAliasForRoom(space) || space.roomId } -
    ; - }); - - spaceOptionSection = ( - { - setSelectedSpace(existingSubspaces.find(space => space.roomId === key) || space); - }} - value={selectedSpace.roomId} - label={_t("Space selection")} - > - { options } - - ); - } else { - spaceOptionSection =
    - { space.name || getDisplayAliasForRoom(space) || space.roomId } -
    ; - } - - const title = - -
    -

    { _t("Add existing rooms") }

    - { spaceOptionSection } -
    -
    ; - const addRooms = async () => { setError(null); setProgress(0); @@ -269,20 +164,145 @@ const AddExistingToSpaceDialog: React.FC = ({ matrixClient: cli, space,
    ; } else { + let button = emptySelectionButton; + if (!button || selectedToAdd.size > 0) { + button = + { _t("Add") } + ; + } + footer = <> -
    { _t("Want to add a new room instead?") }
    - onCreateRoomClick(cli, space)} kind="link"> - { _t("Create a new room") } - + { footerPrompt }
    - - { _t("Add") } - + { button } ; } + const onChange = !busy && !error ? (checked, room) => { + if (checked) { + selectedToAdd.add(room); + } else { + selectedToAdd.delete(room); + } + setSelectedToAdd(new Set(selectedToAdd)); + } : null; + + return
    + + + { rooms.length > 0 ? ( +
    +

    { _t("Rooms") }

    + { rooms.map(room => { + return { + onChange(checked, room); + } : null} + />; + }) } +
    + ) : undefined } + + { spaces.length > 0 ? ( +
    +

    { _t("Spaces") }

    +
    +
    { _t("Feeling experimental?") }
    +
    { _t("You can add existing spaces to a space.") }
    +
    + { spaces.map(space => { + return { + onChange(checked, space); + } : null} + />; + }) } +
    + ) : null } + + { dms.length > 0 ? ( +
    +

    { _t("Direct Messages") }

    + { dms.map(room => { + return { + onChange(checked, room); + } : null} + />; + }) } +
    + ) : null } + + { spaces.length + rooms.length + dms.length < 1 ? + { _t("No results") } + : undefined } +
    + +
    + { footer } +
    +
    ; +}; + +const AddExistingToSpaceDialog: React.FC = ({ matrixClient: cli, space, onCreateRoomClick, onFinished }) => { + const [selectedSpace, setSelectedSpace] = useState(space); + const existingSubspaces = SpaceStore.instance.getChildSpaces(space.roomId); + + let spaceOptionSection; + if (existingSubspaces.length > 0) { + const options = [space, ...existingSubspaces].map((space) => { + const classes = classNames("mx_AddExistingToSpaceDialog_dropdownOption", { + mx_AddExistingToSpaceDialog_dropdownOptionActive: space === selectedSpace, + }); + return
    + + { space.name || getDisplayAliasForRoom(space) || space.roomId } +
    ; + }); + + spaceOptionSection = ( + { + setSelectedSpace(existingSubspaces.find(space => space.roomId === key) || space); + }} + value={selectedSpace.roomId} + label={_t("Space selection")} + > + { options } + + ); + } else { + spaceOptionSection =
    + { space.name || getDisplayAliasForRoom(space) || space.roomId } +
    ; + } + + const title = + +
    +

    { _t("Add existing rooms") }

    + { spaceOptionSection } +
    +
    ; + return = ({ matrixClient: cli, space, { - if (checked) { - selectedToAdd.add(room); - } else { - selectedToAdd.delete(room); - } - setSelectedToAdd(new Set(selectedToAdd)); - } : null} + onFinished={onFinished} + footerPrompt={<> +
    { _t("Want to add a new room instead?") }
    + onCreateRoomClick(cli, space)} kind="link"> + { _t("Create a new room") } + + } />
    -
    - { footer } -
    onFinished(false)} />
    ; }; From dd04b479a1c751da456c8d55236e6c661ce45e36 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 13 May 2021 10:20:27 +0100 Subject: [PATCH 0390/1449] Wrap decodeURIComponent in try-catch to protect against malformed URIs --- src/linkify-matrix.js | 14 +++++++++----- src/utils/permalinks/Permalinks.ts | 11 ++++++++--- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/linkify-matrix.js b/src/linkify-matrix.js index 84a131f23a..feda257d8b 100644 --- a/src/linkify-matrix.js +++ b/src/linkify-matrix.js @@ -254,11 +254,15 @@ matrixLinkify.options = { target: function(href, type) { if (type === 'url') { - const transformed = tryTransformPermalinkToLocalHref(href); - if (transformed !== href || decodeURIComponent(href).match(matrixLinkify.ELEMENT_URL_PATTERN)) { - return null; - } else { - return '_blank'; + try { + const transformed = tryTransformPermalinkToLocalHref(href); + if (transformed !== href || decodeURIComponent(href).match(matrixLinkify.ELEMENT_URL_PATTERN)) { + return null; + } else { + return '_blank'; + } + } catch (e) { + // malformed URI } } return null; diff --git a/src/utils/permalinks/Permalinks.ts b/src/utils/permalinks/Permalinks.ts index 015ecca22e..d87c826cc2 100644 --- a/src/utils/permalinks/Permalinks.ts +++ b/src/utils/permalinks/Permalinks.ts @@ -346,9 +346,14 @@ export function tryTransformPermalinkToLocalHref(permalink: string): string { return permalink; } - const m = decodeURIComponent(permalink).match(matrixLinkify.ELEMENT_URL_PATTERN); - if (m) { - return m[1]; + try { + const m = decodeURIComponent(permalink).match(matrixLinkify.ELEMENT_URL_PATTERN); + if (m) { + return m[1]; + } + } catch (e) { + // Not a valid URI + return permalink; } // A bit of a hack to convert permalinks of unknown origin to Element links From 3af0138e9d1ee380bea09e8a837ffe718443c09b Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 13 May 2021 10:28:35 +0100 Subject: [PATCH 0391/1449] Update emoji icons to new style --- res/css/views/messages/_MessageActionBar.scss | 1 + res/img/element-icons/room/composer/emoji.svg | 10 +++++----- res/img/element-icons/room/message-bar/emoji.svg | 6 ++---- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/res/css/views/messages/_MessageActionBar.scss b/res/css/views/messages/_MessageActionBar.scss index 3ecbef0d1f..d41ac3a4ba 100644 --- a/res/css/views/messages/_MessageActionBar.scss +++ b/res/css/views/messages/_MessageActionBar.scss @@ -85,6 +85,7 @@ limitations under the License. left: 0; height: 100%; width: 100%; + mask-size: 18px; mask-repeat: no-repeat; mask-position: center; background-color: $message-action-bar-fg-color; diff --git a/res/img/element-icons/room/composer/emoji.svg b/res/img/element-icons/room/composer/emoji.svg index 9613d9edd9..b02cb69364 100644 --- a/res/img/element-icons/room/composer/emoji.svg +++ b/res/img/element-icons/room/composer/emoji.svg @@ -1,7 +1,7 @@ - - - - - + + + + + diff --git a/res/img/element-icons/room/message-bar/emoji.svg b/res/img/element-icons/room/message-bar/emoji.svg index 697f656b8a..07fee5b834 100644 --- a/res/img/element-icons/room/message-bar/emoji.svg +++ b/res/img/element-icons/room/message-bar/emoji.svg @@ -1,5 +1,3 @@ - - - - + + From b5fa4d88bf5005b5d45bf25ce2207eb570301e17 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 13 May 2021 10:56:51 +0100 Subject: [PATCH 0392/1449] Add extra add reactions button to encourage more diverse reactions to content --- res/css/views/messages/_ReactionsRow.scss | 20 ++++++++++ src/components/views/messages/ReactionsRow.js | 40 ++++++++++++++++++- src/i18n/strings/en_EN.json | 1 + 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/res/css/views/messages/_ReactionsRow.scss b/res/css/views/messages/_ReactionsRow.scss index 2f5695e1fb..e86d23dc7c 100644 --- a/res/css/views/messages/_ReactionsRow.scss +++ b/res/css/views/messages/_ReactionsRow.scss @@ -17,6 +17,26 @@ limitations under the License. .mx_ReactionsRow { margin: 6px 0; color: $primary-fg-color; + + .mx_ReactionsRow_addReactionButton { + position: relative; + display: inline-block; + width: 16px; + height: 16px; + vertical-align: sub; + + &::before { + content: ''; + position: absolute; + height: 100%; + width: 100%; + mask-size: cover; + mask-repeat: no-repeat; + mask-position: center; + background-color: $tertiary-fg-color; + mask-image: url('$(res)/img/element-icons/room/message-bar/emoji.svg'); + } + } } .mx_ReactionsRow_showAll { diff --git a/src/components/views/messages/ReactionsRow.js b/src/components/views/messages/ReactionsRow.js index d5c8ea2ac9..22f12709a7 100644 --- a/src/components/views/messages/ReactionsRow.js +++ b/src/components/views/messages/ReactionsRow.js @@ -16,16 +16,44 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; +import { EventType } from "matrix-js-sdk/src/@types/event"; import * as sdk from '../../../index'; import { _t } from '../../../languageHandler'; import { isContentActionable } from '../../../utils/EventUtils'; import {MatrixClientPeg} from '../../../MatrixClientPeg'; import {replaceableComponent} from "../../../utils/replaceableComponent"; +import {ContextMenuTooltipButton} from "../../../accessibility/context_menu/ContextMenuTooltipButton"; +import {aboveLeftOf, ContextMenu, useContextMenu} from "../../structures/ContextMenu"; // The maximum number of reactions to initially show on a message. const MAX_ITEMS_WHEN_LIMITED = 8; +const ReactButton = ({ mxEvent, reactions }) => { + const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu(); + + let contextMenu; + if (menuDisplayed) { + const buttonRect = button.current.getBoundingClientRect(); + const ReactionPicker = sdk.getComponent('emojipicker.ReactionPicker'); + contextMenu = + + ; + } + + return + + + { contextMenu } + ; +}; + @replaceableComponent("views.messages.ReactionsRow") export default class ReactionsRow extends React.PureComponent { static propTypes = { @@ -151,13 +179,21 @@ export default class ReactionsRow extends React.PureComponent { ; } + const cli = MatrixClientPeg.get(); + + let addReactionButton; + if (cli.getRoom(mxEvent.getRoomId()).currentState.maySendEvent(EventType.Reaction, cli.getUserId())) { + addReactionButton = ; + } + return
    - {items} - {showAllButton} + { items } + { addReactionButton } + { showAllButton }
    ; } } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index dbe712c691..b9e52a8356 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1864,6 +1864,7 @@ "You sent a verification request": "You sent a verification request", "Error decrypting video": "Error decrypting video", "Error processing voice message": "Error processing voice message", + "Add reaction": "Add reaction", "Show all": "Show all", "Reactions": "Reactions", " reacted with %(content)s": " reacted with %(content)s", From 2f28de8472b08ae01440db111b7ddcd937433735 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 13 May 2021 13:22:50 +0100 Subject: [PATCH 0393/1449] Show alternative button during space creation wizard if user opted to create 0 rooms --- src/components/structures/SpaceRoomView.tsx | 17 ++++++++++------- src/i18n/strings/en_EN.json | 1 + 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx index ed0ae1afe7..583caf4b1e 100644 --- a/src/components/structures/SpaceRoomView.tsx +++ b/src/components/structures/SpaceRoomView.tsx @@ -78,6 +78,7 @@ interface IProps { interface IState { phase: Phase; + createdRooms?: boolean; // internal state for the creation wizard showRightPanel: boolean; myMembership: string; } @@ -461,7 +462,8 @@ const SpaceSetupFirstRooms = ({ space, title, description, onFinished }) => { setError(""); setBusy(true); try { - await Promise.all(roomNames.map(name => name.trim()).filter(Boolean).map(name => { + const filteredRoomNames = roomNames.map(name => name.trim()).filter(Boolean); + await Promise.all(filteredRoomNames.map(name => { return createRoom({ createOpts: { preset: space.getJoinRule() === "public" ? Preset.PublicChat : Preset.PrivateChat, @@ -474,7 +476,7 @@ const SpaceSetupFirstRooms = ({ space, title, description, onFinished }) => { parentSpace: space, }); })); - onFinished(); + onFinished(filteredRoomNames.length > 0); } catch (e) { console.error("Failed to create initial space rooms", e); setError(_t("Failed to create initial space rooms")); @@ -484,7 +486,7 @@ const SpaceSetupFirstRooms = ({ space, title, description, onFinished }) => { let onClick = (ev) => { ev.preventDefault(); - onFinished(); + onFinished(false); }; let buttonLabel = _t("Skip for now"); if (roomNames.some(name => name.trim())) { @@ -585,7 +587,7 @@ const SpaceAddExistingRooms = ({ space, onFinished }) => {
    ; }; -const SpaceSetupPublicShare = ({ justCreatedOpts, space, onFinished }) => { +const SpaceSetupPublicShare = ({ justCreatedOpts, space, onFinished, createdRooms }) => { return

    { _t("Share %(name)s", { name: justCreatedOpts?.createOpts?.name || space.name, @@ -598,7 +600,7 @@ const SpaceSetupPublicShare = ({ justCreatedOpts, space, onFinished }) => {
    - { _t("Go to my first room") } + { createdRooms ? _t("Go to my first room") : _t("Go to my space") }
    @@ -891,13 +893,14 @@ export default class SpaceRoomView extends React.PureComponent { _t("Let's create a room for each of them.") + "\n" + _t("You can add more later too, including already existing ones.") } - onFinished={() => this.setState({ phase: Phase.PublicShare })} + onFinished={(createdRooms: boolean) => this.setState({ phase: Phase.PublicShare, createdRooms })} />; case Phase.PublicShare: return ; case Phase.PrivateScope: @@ -919,7 +922,7 @@ export default class SpaceRoomView extends React.PureComponent { title={_t("What projects are you working on?")} description={_t("We'll create rooms for each of them. " + "You can add more later too, including already existing ones.")} - onFinished={() => this.setState({ phase: Phase.Landing })} + onFinished={(createdRooms: boolean) => this.setState({ phase: Phase.Landing, createdRooms })} />; case Phase.PrivateExistingRooms: return Date: Thu, 13 May 2021 13:32:38 +0100 Subject: [PATCH 0394/1449] Tweak alignment of reactions row, move add reaction to right and only show on hover --- res/css/views/messages/_ReactionsRow.scss | 11 ++++++++--- res/css/views/messages/_ReactionsRowButton.scss | 5 +++-- src/components/views/messages/ReactionsRow.js | 2 +- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/res/css/views/messages/_ReactionsRow.scss b/res/css/views/messages/_ReactionsRow.scss index e86d23dc7c..15d251bd68 100644 --- a/res/css/views/messages/_ReactionsRow.scss +++ b/res/css/views/messages/_ReactionsRow.scss @@ -20,10 +20,11 @@ limitations under the License. .mx_ReactionsRow_addReactionButton { position: relative; - display: inline-block; + display: none; width: 16px; height: 16px; - vertical-align: sub; + vertical-align: middle; + margin-left: 6px; &::before { content: ''; @@ -39,12 +40,16 @@ limitations under the License. } } +.mx_EventTile:hover .mx_ReactionsRow_addReactionButton { + display: inline-block; +} + .mx_ReactionsRow_showAll { text-decoration: none; font-size: $font-10px; font-weight: 600; margin-left: 6px; - vertical-align: top; + vertical-align: middle; &:hover, &:link, diff --git a/res/css/views/messages/_ReactionsRowButton.scss b/res/css/views/messages/_ReactionsRowButton.scss index c132fa5a0f..766fea2f8f 100644 --- a/res/css/views/messages/_ReactionsRowButton.scss +++ b/res/css/views/messages/_ReactionsRowButton.scss @@ -16,14 +16,15 @@ limitations under the License. .mx_ReactionsRowButton { display: inline-flex; - line-height: $font-21px; + line-height: $font-20px; margin-right: 6px; - padding: 0 6px; + padding: 1px 6px; border: 1px solid $reaction-row-button-border-color; border-radius: 10px; background-color: $reaction-row-button-bg-color; cursor: pointer; user-select: none; + vertical-align: middle; &:hover { border-color: $reaction-row-button-hover-border-color; diff --git a/src/components/views/messages/ReactionsRow.js b/src/components/views/messages/ReactionsRow.js index 22f12709a7..2a67519d6b 100644 --- a/src/components/views/messages/ReactionsRow.js +++ b/src/components/views/messages/ReactionsRow.js @@ -192,8 +192,8 @@ export default class ReactionsRow extends React.PureComponent { aria-label={_t("Reactions")} > { items } - { addReactionButton } { showAllButton } + { addReactionButton }

    ; } } From 87ae47bd6114d660735bba82a71c4fc0883b5314 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 13 May 2021 13:59:10 +0100 Subject: [PATCH 0395/1449] tweak reactions row some more, third try lucky --- res/css/views/messages/_ReactionsRow.scss | 36 ++++++++++++------- src/components/views/messages/ReactionsRow.js | 5 ++- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/res/css/views/messages/_ReactionsRow.scss b/res/css/views/messages/_ReactionsRow.scss index 15d251bd68..f1c19f45a9 100644 --- a/res/css/views/messages/_ReactionsRow.scss +++ b/res/css/views/messages/_ReactionsRow.scss @@ -20,23 +20,33 @@ limitations under the License. .mx_ReactionsRow_addReactionButton { position: relative; - display: none; - width: 16px; - height: 16px; + display: none; // show on hover of the .mx_EventTile + width: 24px; + height: 24px; vertical-align: middle; - margin-left: 6px; + margin-left: 4px; &::before { content: ''; position: absolute; height: 100%; width: 100%; - mask-size: cover; + mask-size: 16px; mask-repeat: no-repeat; mask-position: center; background-color: $tertiary-fg-color; mask-image: url('$(res)/img/element-icons/room/message-bar/emoji.svg'); } + + &.mx_ReactionsRow_addReactionButton_active { + display: inline-block; // keep showing whilst the context menu is shown + } + + &:hover, &.mx_ReactionsRow_addReactionButton_active { + &::before { + background-color: $primary-fg-color; + } + } } } @@ -46,14 +56,16 @@ limitations under the License. .mx_ReactionsRow_showAll { text-decoration: none; - font-size: $font-10px; - font-weight: 600; - margin-left: 6px; + font-size: $font-12px; + line-height: $font-20px; + margin-left: 4px; vertical-align: middle; - &:hover, - &:link, - &:visited { - color: $accent-color; + &:link, &:visited { + color: $tertiary-fg-color + } + + &:hover { + color: $primary-fg-color; } } diff --git a/src/components/views/messages/ReactionsRow.js b/src/components/views/messages/ReactionsRow.js index 2a67519d6b..a7997c0e32 100644 --- a/src/components/views/messages/ReactionsRow.js +++ b/src/components/views/messages/ReactionsRow.js @@ -17,6 +17,7 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; import { EventType } from "matrix-js-sdk/src/@types/event"; +import classNames from "classnames"; import * as sdk from '../../../index'; import { _t } from '../../../languageHandler'; @@ -43,7 +44,9 @@ const ReactButton = ({ mxEvent, reactions }) => { return Date: Thu, 13 May 2021 14:13:00 +0100 Subject: [PATCH 0396/1449] Convert to Typescript and move from ClientPeg to Context --- res/css/views/messages/_ReactionsRow.scss | 2 +- .../{ReactionsRow.js => ReactionsRow.tsx} | 55 ++++++++------- ...onsRowButton.js => ReactionsRowButton.tsx} | 70 ++++++++++--------- ...oltip.js => ReactionsRowButtonTooltip.tsx} | 37 +++++----- 4 files changed, 87 insertions(+), 77 deletions(-) rename src/components/views/messages/{ReactionsRow.js => ReactionsRow.tsx} (82%) rename src/components/views/messages/{ReactionsRowButton.js => ReactionsRowButton.tsx} (73%) rename src/components/views/messages/{ReactionsRowButtonTooltip.js => ReactionsRowButtonTooltip.tsx} (74%) diff --git a/res/css/views/messages/_ReactionsRow.scss b/res/css/views/messages/_ReactionsRow.scss index f1c19f45a9..244439bf74 100644 --- a/res/css/views/messages/_ReactionsRow.scss +++ b/res/css/views/messages/_ReactionsRow.scss @@ -62,7 +62,7 @@ limitations under the License. vertical-align: middle; &:link, &:visited { - color: $tertiary-fg-color + color: $tertiary-fg-color; } &:hover { diff --git a/src/components/views/messages/ReactionsRow.js b/src/components/views/messages/ReactionsRow.tsx similarity index 82% rename from src/components/views/messages/ReactionsRow.js rename to src/components/views/messages/ReactionsRow.tsx index a7997c0e32..e1fcbe5364 100644 --- a/src/components/views/messages/ReactionsRow.js +++ b/src/components/views/messages/ReactionsRow.tsx @@ -1,5 +1,5 @@ /* -Copyright 2019 New Vector Ltd +Copyright 2019, 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. @@ -14,29 +14,30 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React from 'react'; -import PropTypes from 'prop-types'; -import { EventType } from "matrix-js-sdk/src/@types/event"; +import React from "react"; import classNames from "classnames"; +import { EventType } from "matrix-js-sdk/src/@types/event"; +import { MatrixEvent } from "matrix-js-sdk/src/models/event"; +import { Relations } from "matrix-js-sdk/src/models/relations"; -import * as sdk from '../../../index'; import { _t } from '../../../languageHandler'; import { isContentActionable } from '../../../utils/EventUtils'; -import {MatrixClientPeg} from '../../../MatrixClientPeg'; -import {replaceableComponent} from "../../../utils/replaceableComponent"; -import {ContextMenuTooltipButton} from "../../../accessibility/context_menu/ContextMenuTooltipButton"; -import {aboveLeftOf, ContextMenu, useContextMenu} from "../../structures/ContextMenu"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; +import { ContextMenuTooltipButton } from "../../../accessibility/context_menu/ContextMenuTooltipButton"; +import { aboveLeftOf, ContextMenu, useContextMenu } from "../../structures/ContextMenu"; +import ReactionPicker from "../emojipicker/ReactionPicker"; +import ReactionsRowButton from "./ReactionsRowButton"; +import MatrixClientContext from "../../../contexts/MatrixClientContext"; // The maximum number of reactions to initially show on a message. const MAX_ITEMS_WHEN_LIMITED = 8; -const ReactButton = ({ mxEvent, reactions }) => { +const ReactButton = ({ mxEvent, reactions }: IProps) => { const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu(); let contextMenu; if (menuDisplayed) { const buttonRect = button.current.getBoundingClientRect(); - const ReactionPicker = sdk.getComponent('emojipicker.ReactionPicker'); contextMenu = ; @@ -57,17 +58,24 @@ const ReactButton = ({ mxEvent, reactions }) => { ; }; -@replaceableComponent("views.messages.ReactionsRow") -export default class ReactionsRow extends React.PureComponent { - static propTypes = { - // The event we're displaying reactions for - mxEvent: PropTypes.object.isRequired, - // The Relations model from the JS SDK for reactions to `mxEvent` - reactions: PropTypes.object, - } +interface IProps { + // The event we're displaying reactions for + mxEvent: MatrixEvent; + // The Relations model from the JS SDK for reactions to `mxEvent` + reactions?: Relations; +} - constructor(props) { - super(props); +interface IState { + myReactions: MatrixEvent[]; + showAll: boolean; +} + +@replaceableComponent("views.messages.ReactionsRow") +export default class ReactionsRow extends React.PureComponent { + static contextType = MatrixClientContext; + + constructor(props, context) { + super(props, context); if (props.reactions) { props.reactions.on("Relations.add", this.onReactionsChange); @@ -123,7 +131,7 @@ export default class ReactionsRow extends React.PureComponent { if (!reactions) { return null; } - const userId = MatrixClientPeg.get().getUserId(); + const userId = this.context.getUserId(); const myReactions = reactions.getAnnotationsBySender()[userId]; if (!myReactions) { return null; @@ -145,7 +153,6 @@ export default class ReactionsRow extends React.PureComponent { return null; } - const ReactionsRowButton = sdk.getComponent('messages.ReactionsRowButton'); let items = reactions.getSortedAnnotationsByKey().map(([content, events]) => { const count = events.size; if (!count) { @@ -182,7 +189,7 @@ export default class ReactionsRow extends React.PureComponent { ; } - const cli = MatrixClientPeg.get(); + const cli = this.context; let addReactionButton; if (cli.getRoom(mxEvent.getRoomId()).currentState.maySendEvent(EventType.Reaction, cli.getUserId())) { diff --git a/src/components/views/messages/ReactionsRowButton.js b/src/components/views/messages/ReactionsRowButton.tsx similarity index 73% rename from src/components/views/messages/ReactionsRowButton.js rename to src/components/views/messages/ReactionsRowButton.tsx index b37a949e57..393c6bca88 100644 --- a/src/components/views/messages/ReactionsRowButton.js +++ b/src/components/views/messages/ReactionsRowButton.tsx @@ -1,5 +1,5 @@ /* -Copyright 2019 New Vector Ltd +Copyright 2019, 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. @@ -14,49 +14,54 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React from 'react'; -import PropTypes from 'prop-types'; -import classNames from 'classnames'; +import React from "react"; +import classNames from "classnames"; +import { MatrixEvent } from "matrix-js-sdk/src/models/event"; -import {MatrixClientPeg} from '../../../MatrixClientPeg'; -import * as sdk from '../../../index'; import { _t } from '../../../languageHandler'; import { formatCommaSeparatedList } from '../../../utils/FormattingUtils'; import dis from "../../../dispatcher/dispatcher"; -import {replaceableComponent} from "../../../utils/replaceableComponent"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; +import ReactionsRowButtonTooltip from "./ReactionsRowButtonTooltip"; +import AccessibleButton from "../elements/AccessibleButton"; +import MatrixClientContext from "../../../contexts/MatrixClientContext"; + +interface IProps { + // The event we're displaying reactions for + mxEvent: MatrixEvent; + // The reaction content / key / emoji + content: string; + // The count of votes for this key + count: number; + // A Set of Martix reaction events for this key + reactionEvents: Set; + // A possible Matrix event if the current user has voted for this type + myReactionEvent?: MatrixEvent; +} + +interface IState { + tooltipRendered: boolean; + tooltipVisible: boolean; +} @replaceableComponent("views.messages.ReactionsRowButton") -export default class ReactionsRowButton extends React.PureComponent { - static propTypes = { - // The event we're displaying reactions for - mxEvent: PropTypes.object.isRequired, - // The reaction content / key / emoji - content: PropTypes.string.isRequired, - // The count of votes for this key - count: PropTypes.number.isRequired, - // A Set of Martix reaction events for this key - reactionEvents: PropTypes.object.isRequired, - // A possible Matrix event if the current user has voted for this type - myReactionEvent: PropTypes.object, - } +export default class ReactionsRowButton extends React.PureComponent { + static contextType = MatrixClientContext; - constructor(props) { - super(props); + state = { + tooltipRendered: false, + tooltipVisible: false, + }; - this.state = { - tooltipVisible: false, - }; - } - - onClick = (ev) => { + onClick = () => { const { mxEvent, myReactionEvent, content } = this.props; if (myReactionEvent) { - MatrixClientPeg.get().redactEvent( + this.context.redactEvent( mxEvent.getRoomId(), myReactionEvent.getId(), ); } else { - MatrixClientPeg.get().sendEvent(mxEvent.getRoomId(), "m.reaction", { + this.context.sendEvent(mxEvent.getRoomId(), "m.reaction", { "m.relates_to": { "rel_type": "m.annotation", "event_id": mxEvent.getId(), @@ -83,8 +88,6 @@ export default class ReactionsRowButton extends React.PureComponent { } render() { - const ReactionsRowButtonTooltip = - sdk.getComponent('messages.ReactionsRowButtonTooltip'); const { mxEvent, content, count, reactionEvents, myReactionEvent } = this.props; const classes = classNames({ @@ -102,7 +105,7 @@ export default class ReactionsRowButton extends React.PureComponent { />; } - const room = MatrixClientPeg.get().getRoom(mxEvent.getRoomId()); + const room = this.context.getRoom(mxEvent.getRoomId()); let label; if (room) { const senders = []; @@ -130,7 +133,6 @@ export default class ReactionsRowButton extends React.PureComponent { ); } const isPeeking = room.getMyMembership() !== "join"; - const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); return ; + visible: boolean; +} @replaceableComponent("views.messages.ReactionsRowButtonTooltip") -export default class ReactionsRowButtonTooltip extends React.PureComponent { - static propTypes = { - // The event we're displaying reactions for - mxEvent: PropTypes.object.isRequired, - // The reaction content / key / emoji - content: PropTypes.string.isRequired, - // A Set of Martix reaction events for this key - reactionEvents: PropTypes.object.isRequired, - visible: PropTypes.bool.isRequired, - } +export default class ReactionsRowButtonTooltip extends React.PureComponent { + static contextType = MatrixClientContext; render() { - const Tooltip = sdk.getComponent('elements.Tooltip'); const { content, reactionEvents, mxEvent, visible } = this.props; - const room = MatrixClientPeg.get().getRoom(mxEvent.getRoomId()); + const room = this.context.getRoom(mxEvent.getRoomId()); let tooltipLabel; if (room) { const senders = []; From a41d76b588cd619a17770102457dbc57243e1e2f Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 13 May 2021 14:14:01 +0100 Subject: [PATCH 0397/1449] fix typos --- src/components/views/messages/ReactionsRowButton.tsx | 2 +- src/components/views/messages/ReactionsRowButtonTooltip.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/messages/ReactionsRowButton.tsx b/src/components/views/messages/ReactionsRowButton.tsx index 393c6bca88..d163f1ad30 100644 --- a/src/components/views/messages/ReactionsRowButton.tsx +++ b/src/components/views/messages/ReactionsRowButton.tsx @@ -33,7 +33,7 @@ interface IProps { content: string; // The count of votes for this key count: number; - // A Set of Martix reaction events for this key + // A Set of Matrix reaction events for this key reactionEvents: Set; // A possible Matrix event if the current user has voted for this type myReactionEvent?: MatrixEvent; diff --git a/src/components/views/messages/ReactionsRowButtonTooltip.tsx b/src/components/views/messages/ReactionsRowButtonTooltip.tsx index d9e8a45b28..e60174530a 100644 --- a/src/components/views/messages/ReactionsRowButtonTooltip.tsx +++ b/src/components/views/messages/ReactionsRowButtonTooltip.tsx @@ -29,7 +29,7 @@ interface IProps { mxEvent: MatrixEvent; // The reaction content / key / emoji content: string; - // A Set of Martix reaction events for this key + // A Set of Matrix reaction events for this key reactionEvents: Set; visible: boolean; } From f6e8d38b872d6fd2d3a811d949ac955c04478871 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 13 May 2021 14:23:10 +0100 Subject: [PATCH 0398/1449] Remove redundant `tag` prop --- src/components/views/avatars/DecoratedRoomAvatar.tsx | 2 -- src/components/views/rooms/RoomBreadcrumbs.tsx | 1 - src/components/views/rooms/RoomHeader.js | 1 - src/components/views/rooms/RoomTile.tsx | 1 - 4 files changed, 5 deletions(-) diff --git a/src/components/views/avatars/DecoratedRoomAvatar.tsx b/src/components/views/avatars/DecoratedRoomAvatar.tsx index e95022687a..f15538eabf 100644 --- a/src/components/views/avatars/DecoratedRoomAvatar.tsx +++ b/src/components/views/avatars/DecoratedRoomAvatar.tsx @@ -20,7 +20,6 @@ import { Room } from "matrix-js-sdk/src/models/room"; import { User } from "matrix-js-sdk/src/models/user"; import { MatrixEvent } from "matrix-js-sdk/src/models/event"; -import { TagID } from '../../../stores/room-list/models'; import RoomAvatar from "./RoomAvatar"; import NotificationBadge from '../rooms/NotificationBadge'; import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNotificationStateStore"; @@ -35,7 +34,6 @@ import {replaceableComponent} from "../../../utils/replaceableComponent"; interface IProps { room: Room; avatarSize: number; - tag: TagID; displayBadge?: boolean; forceCount?: boolean; oobData?: object; diff --git a/src/components/views/rooms/RoomBreadcrumbs.tsx b/src/components/views/rooms/RoomBreadcrumbs.tsx index ea0ff233da..c061b79541 100644 --- a/src/components/views/rooms/RoomBreadcrumbs.tsx +++ b/src/components/views/rooms/RoomBreadcrumbs.tsx @@ -98,7 +98,6 @@ export default class RoomBreadcrumbs extends React.PureComponent diff --git a/src/components/views/rooms/RoomHeader.js b/src/components/views/rooms/RoomHeader.js index f856f7f6ef..84248f14c2 100644 --- a/src/components/views/rooms/RoomHeader.js +++ b/src/components/views/rooms/RoomHeader.js @@ -177,7 +177,6 @@ export default class RoomHeader extends React.Component { roomAvatar = ; diff --git a/src/components/views/rooms/RoomTile.tsx b/src/components/views/rooms/RoomTile.tsx index 7303f36489..edd644fd65 100644 --- a/src/components/views/rooms/RoomTile.tsx +++ b/src/components/views/rooms/RoomTile.tsx @@ -576,7 +576,6 @@ export default class RoomTile extends React.PureComponent { const roomAvatar = ; From 6aa477f0f52eeb875c251962f588a83a34f66404 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 13 May 2021 14:23:28 +0100 Subject: [PATCH 0399/1449] Decorate room avatars with publicity in add existing to space flow --- res/css/views/dialogs/_AddExistingToSpaceDialog.scss | 7 ++++++- src/components/views/dialogs/AddExistingToSpaceDialog.tsx | 6 +++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/res/css/views/dialogs/_AddExistingToSpaceDialog.scss b/res/css/views/dialogs/_AddExistingToSpaceDialog.scss index 91947be76a..c2960ae62b 100644 --- a/res/css/views/dialogs/_AddExistingToSpaceDialog.scss +++ b/res/css/views/dialogs/_AddExistingToSpaceDialog.scss @@ -54,7 +54,8 @@ limitations under the License. display: flex; margin-top: 12px; - .mx_BaseAvatar { + // we can't target .mx_BaseAvatar here as it'll break the decorated avatar styling + .mx_DecoratedRoomAvatar { margin-right: 12px; } @@ -75,6 +76,10 @@ limitations under the License. } .mx_AddExistingToSpace_section_spaces { + .mx_BaseAvatar { + margin-right: 12px; + } + .mx_BaseAvatar_image { border-radius: 8px; } diff --git a/src/components/views/dialogs/AddExistingToSpaceDialog.tsx b/src/components/views/dialogs/AddExistingToSpaceDialog.tsx index 8ac68e99b7..487eb36713 100644 --- a/src/components/views/dialogs/AddExistingToSpaceDialog.tsx +++ b/src/components/views/dialogs/AddExistingToSpaceDialog.tsx @@ -37,6 +37,7 @@ import MatrixClientContext from "../../../contexts/MatrixClientContext"; import {sortRooms} from "../../../stores/room-list/algorithms/tag-sorting/RecentAlgorithm"; import ProgressBar from "../elements/ProgressBar"; import {SpaceFeedbackPrompt} from "../../structures/SpaceRoomView"; +import DecoratedRoomAvatar from "../avatars/DecoratedRoomAvatar"; interface IProps extends IDialogProps { matrixClient: MatrixClient; @@ -46,7 +47,10 @@ interface IProps extends IDialogProps { const Entry = ({ room, checked, onChange }) => { return