From c3eb517700f35eb501b3557ff2561f249a2e4ef8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sat, 5 Jun 2021 08:22:43 +0200 Subject: [PATCH 001/143] Use fallback avatar only for DMs with 2 people MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/Avatar.ts | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/Avatar.ts b/src/Avatar.ts index a6499c688e..5b033feb8f 100644 --- a/src/Avatar.ts +++ b/src/Avatar.ts @@ -146,15 +146,11 @@ export function avatarUrlForRoom(room: Room, width: number, height: number, resi // space rooms cannot be DMs so skip the rest if (SettingsStore.getValue("feature_spaces") && room.isSpaceRoom()) return null; - let otherMember = null; const otherUserId = DMRoomMap.shared().getUserIdForRoomId(room.roomId); - if (otherUserId) { - otherMember = room.getMember(otherUserId); - } else { - // if the room is not marked as a 1:1, but only has max 2 members - // then still try to show any avatar (pref. other member) - otherMember = room.getAvatarFallbackMember(); - } + if (!otherUserId) return null; + + // If there are only two members in the DM use the avatar of the other member + const otherMember = room.getAvatarFallbackMember(otherUserId); if (otherMember?.getMxcAvatarUrl()) { return mediaFromMxc(otherMember.getMxcAvatarUrl()).getThumbnailOfSourceHttp(width, height, resizeMethod); } From 4b2a9a6bf77471f261f98084fb3b61e8caedf257 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sat, 5 Jun 2021 08:33:14 +0200 Subject: [PATCH 002/143] Remove mistaken param MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/Avatar.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Avatar.ts b/src/Avatar.ts index 5b033feb8f..79f9bb699b 100644 --- a/src/Avatar.ts +++ b/src/Avatar.ts @@ -146,11 +146,10 @@ export function avatarUrlForRoom(room: Room, width: number, height: number, resi // space rooms cannot be DMs so skip the rest if (SettingsStore.getValue("feature_spaces") && room.isSpaceRoom()) return null; - const otherUserId = DMRoomMap.shared().getUserIdForRoomId(room.roomId); - if (!otherUserId) return null; + if (!DMRoomMap.shared().getUserIdForRoomId(room.roomId)) return null; // If there are only two members in the DM use the avatar of the other member - const otherMember = room.getAvatarFallbackMember(otherUserId); + const otherMember = room.getAvatarFallbackMember(); if (otherMember?.getMxcAvatarUrl()) { return mediaFromMxc(otherMember.getMxcAvatarUrl()).getThumbnailOfSourceHttp(width, height, resizeMethod); } From 87622fb8eaccf0ce0b59799b050b095c8e354857 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Sat, 5 Jun 2021 08:34:32 +0200 Subject: [PATCH 003/143] Add a comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/Avatar.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Avatar.ts b/src/Avatar.ts index 79f9bb699b..e6b47f8a7f 100644 --- a/src/Avatar.ts +++ b/src/Avatar.ts @@ -146,6 +146,7 @@ export function avatarUrlForRoom(room: Room, width: number, height: number, resi // space rooms cannot be DMs so skip the rest if (SettingsStore.getValue("feature_spaces") && room.isSpaceRoom()) return null; + // If the room is not a DM don't fallback to a member avatar if (!DMRoomMap.shared().getUserIdForRoomId(room.roomId)) return null; // If there are only two members in the DM use the avatar of the other member From 171874ae30ca36513c01a5ac74596dba33bc6826 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 2 Jul 2021 16:31:37 +0100 Subject: [PATCH 004/143] Use FocusLock around ContextMenus to simplify focus management --- src/components/structures/ContextMenu.tsx | 27 +++++++------------ .../views/spaces/SpaceCreateMenu.tsx | 23 +++++++--------- 2 files changed, 20 insertions(+), 30 deletions(-) diff --git a/src/components/structures/ContextMenu.tsx b/src/components/structures/ContextMenu.tsx index 407dc6f04c..9bc9c0a8b2 100644 --- a/src/components/structures/ContextMenu.tsx +++ b/src/components/structures/ContextMenu.tsx @@ -19,6 +19,7 @@ limitations under the License. import React, { CSSProperties, RefObject, useRef, useState } from "react"; import ReactDOM from "react-dom"; import classNames from "classnames"; +import FocusLock from "react-focus-lock"; import { Key } from "../../Keyboard"; import { Writeable } from "../../@types/common"; @@ -44,6 +45,7 @@ function getOrCreateContainer(): HTMLDivElement { } const ARIA_MENU_ITEM_ROLES = new Set(["menuitem", "menuitemcheckbox", "menuitemradio"]); +const ARIA_MENU_ITEM_SELECTOR = '[role^="menuitem"], [role^="menuitemcheckbox"], [role^="menuitemradio"]'; interface IPosition { top?: number; @@ -95,8 +97,6 @@ interface IState { // this will allow the ContextMenu to manage its own focus using arrow keys as per the ARIA guidelines. @replaceableComponent("structures.ContextMenu") export class ContextMenu extends React.PureComponent { - private initialFocus: HTMLElement; - static defaultProps = { hasBackground: true, managed: true, @@ -107,24 +107,15 @@ export class ContextMenu extends React.PureComponent { this.state = { contextMenuElem: null, }; - - // persist what had focus when we got initialized so we can return it after - this.initialFocus = document.activeElement as HTMLElement; } - componentWillUnmount() { - // return focus to the thing which had it before us - this.initialFocus.focus(); - } - - private collectContextMenuRect = (element) => { + private collectContextMenuRect = (element: HTMLDivElement) => { // We don't need to clean up when unmounting, so ignore if (!element) return; - let first = element.querySelector('[role^="menuitem"]'); - if (!first) { - first = element.querySelector('[tab-index]'); - } + const first = element.querySelector(ARIA_MENU_ITEM_SELECTOR) + || element.querySelector('[tab-index]'); + if (first) { first.focus(); } @@ -381,8 +372,10 @@ export class ContextMenu extends React.PureComponent { ref={this.collectContextMenuRect} role={this.props.managed ? "menu" : undefined} > - { chevron } - { props.children } + + { chevron } + { props.children } + { background } diff --git a/src/components/views/spaces/SpaceCreateMenu.tsx b/src/components/views/spaces/SpaceCreateMenu.tsx index 4bb61d7ccb..11f68698ee 100644 --- a/src/components/views/spaces/SpaceCreateMenu.tsx +++ b/src/components/views/spaces/SpaceCreateMenu.tsx @@ -17,7 +17,8 @@ limitations under the License. import React, { useContext, useRef, 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 { Preset } from "matrix-js-sdk/src/@types/partials"; +import { ICreateRoomStateEvent } from "matrix-js-sdk/src/@types/requests"; import { _t } from "../../../languageHandler"; import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; @@ -33,8 +34,6 @@ import { UserTab } from "../dialogs/UserSettingsDialog"; import Field from "../elements/Field"; import withValidation from "../elements/Validation"; import { SpaceFeedbackPrompt } from "../../structures/SpaceRoomView"; -import { Preset } from "matrix-js-sdk/src/@types/partials"; -import { ICreateRoomStateEvent } from "matrix-js-sdk/src/@types/requests"; import RoomAliasField from "../elements/RoomAliasField"; const SpaceCreateMenuType = ({ title, description, className, onClick }) => { @@ -250,16 +249,14 @@ const SpaceCreateMenu = ({ onFinished }) => { wrapperClassName="mx_SpaceCreateMenu_wrapper" managed={false} > - - { - onFinished(); - defaultDispatcher.dispatch({ - action: Action.ViewUserSettings, - initialTabId: UserTab.Labs, - }); - }} /> - { body } - + { + onFinished(); + defaultDispatcher.dispatch({ + action: Action.ViewUserSettings, + initialTabId: UserTab.Labs, + }); + }} /> + { body } ; }; From 1858c63c4af98c9f976a818bd3cf20b7a184e3b3 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 17 Sep 2021 15:34:49 +0100 Subject: [PATCH 005/143] Allow options to cascade kicks/bans throughout spaces --- res/css/_components.scss | 5 +- .../_ConfirmSpaceUserActionDialog.scss | 66 ++++++++ .../dialogs/_ConfirmUserActionDialog.scss | 2 +- res/css/views/dialogs/_LeaveSpaceDialog.scss | 22 +-- .../views/spaces/_SpaceChildrenPicker.scss | 35 ++++ .../dialogs/ConfirmSpaceUserActionDialog.tsx | 86 ++++++++++ .../views/dialogs/ConfirmUserActionDialog.tsx | 26 +-- .../views/dialogs/LeaveSpaceDialog.tsx | 123 ++------------ src/components/views/right_panel/UserInfo.tsx | 100 +++++++++--- .../views/spaces/SpaceChildrenPicker.tsx | 150 ++++++++++++++++++ src/i18n/strings/en_EN.json | 17 +- src/utils/space.tsx | 26 +-- 12 files changed, 481 insertions(+), 177 deletions(-) create mode 100644 res/css/views/dialogs/_ConfirmSpaceUserActionDialog.scss create mode 100644 res/css/views/spaces/_SpaceChildrenPicker.scss create mode 100644 src/components/views/dialogs/ConfirmSpaceUserActionDialog.tsx create mode 100644 src/components/views/spaces/SpaceChildrenPicker.tsx diff --git a/res/css/_components.scss b/res/css/_components.scss index ffaec43b68..adbe67b20e 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -1,8 +1,10 @@ // autogenerated by rethemendex.sh +@import "./_animations.scss"; @import "./_common.scss"; @import "./_font-sizes.scss"; @import "./_font-weights.scss"; @import "./structures/_AutoHideScrollbar.scss"; +@import "./structures/_BackdropPanel.scss"; @import "./structures/_CompatibilityPage.scss"; @import "./structures/_ContextualMenu.scss"; @import "./structures/_CreateRoom.scss"; @@ -17,7 +19,6 @@ @import "./structures/_LeftPanelWidget.scss"; @import "./structures/_MainSplit.scss"; @import "./structures/_MatrixChat.scss"; -@import "./structures/_BackdropPanel.scss"; @import "./structures/_MyGroups.scss"; @import "./structures/_NonUrgentToastContainer.scss"; @import "./structures/_NotificationPanel.scss"; @@ -72,6 +73,7 @@ @import "./views/dialogs/_ChangelogDialog.scss"; @import "./views/dialogs/_ChatCreateOrReuseChatDialog.scss"; @import "./views/dialogs/_CommunityPrototypeInviteDialog.scss"; +@import "./views/dialogs/_ConfirmSpaceUserActionDialog.scss"; @import "./views/dialogs/_ConfirmUserActionDialog.scss"; @import "./views/dialogs/_CreateCommunityPrototypeDialog.scss"; @import "./views/dialogs/_CreateGroupDialog.scss"; @@ -266,6 +268,7 @@ @import "./views/settings/tabs/user/_SecurityUserSettingsTab.scss"; @import "./views/settings/tabs/user/_VoiceUserSettingsTab.scss"; @import "./views/spaces/_SpaceBasicSettings.scss"; +@import "./views/spaces/_SpaceChildrenPicker.scss"; @import "./views/spaces/_SpaceCreateMenu.scss"; @import "./views/spaces/_SpacePublicShare.scss"; @import "./views/terms/_InlineTermsAgreement.scss"; diff --git a/res/css/views/dialogs/_ConfirmSpaceUserActionDialog.scss b/res/css/views/dialogs/_ConfirmSpaceUserActionDialog.scss new file mode 100644 index 0000000000..3b21ea74de --- /dev/null +++ b/res/css/views/dialogs/_ConfirmSpaceUserActionDialog.scss @@ -0,0 +1,66 @@ +/* +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_ConfirmSpaceUserActionDialog_wrapper { + .mx_Dialog { + display: flex; + flex-direction: column; + padding: 24px 32px; + } +} + +.mx_ConfirmSpaceUserActionDialog { + width: 440px; + display: flex; + flex-direction: column; + flex-wrap: nowrap; + height: 520px; + + .mx_Dialog_content { + margin: 12px 0; + flex-grow: 1; + overflow-y: auto; + } + + .mx_ConfirmUserActionDialog_reasonField { + margin-bottom: 12px; + } + + .mx_ConfirmSpaceUserActionDialog_warning { + position: relative; + border-radius: 8px; + padding: 12px 8px 12px 42px; + background-color: $header-panel-bg-color; + + font-size: $font-12px; + line-height: $font-15px; + color: $secondary-content; + + &::before { + content: ''; + position: absolute; + left: 10px; + top: calc(50% - 8px); // vertical centering + height: 16px; + width: 16px; + background-color: $secondary-content; + mask-repeat: no-repeat; + mask-size: contain; + mask-image: url('$(res)/img/element-icons/room/room-summary.svg'); + mask-position: center; + } + } +} diff --git a/res/css/views/dialogs/_ConfirmUserActionDialog.scss b/res/css/views/dialogs/_ConfirmUserActionDialog.scss index 5ac0f07b14..777c9fdfd9 100644 --- a/res/css/views/dialogs/_ConfirmUserActionDialog.scss +++ b/res/css/views/dialogs/_ConfirmUserActionDialog.scss @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -.mx_ConfirmUserActionDialog .mx_Dialog_content { +.mx_ConfirmUserActionDialog .mx_Dialog_content .mx_ConfirmUserActionDialog_user { min-height: 48px; margin-bottom: 24px; } diff --git a/res/css/views/dialogs/_LeaveSpaceDialog.scss b/res/css/views/dialogs/_LeaveSpaceDialog.scss index 0d85a87faf..c0f24871c6 100644 --- a/res/css/views/dialogs/_LeaveSpaceDialog.scss +++ b/res/css/views/dialogs/_LeaveSpaceDialog.scss @@ -27,33 +27,13 @@ limitations under the License. display: flex; flex-direction: column; flex-wrap: nowrap; - max-height: 520px; + height: 520px; .mx_Dialog_content { flex-grow: 1; margin: 0; overflow-y: auto; - .mx_RadioButton + .mx_RadioButton { - margin-top: 16px; - } - - .mx_SearchBox { - // To match the space around the title - margin: 0 0 15px 0; - flex-grow: 0; - border-radius: 8px; - } - - .mx_LeaveSpaceDialog_noResults { - display: block; - margin-top: 24px; - } - - .mx_LeaveSpaceDialog_section { - margin: 16px 0; - } - .mx_LeaveSpaceDialog_section_warning { position: relative; border-radius: 8px; diff --git a/res/css/views/spaces/_SpaceChildrenPicker.scss b/res/css/views/spaces/_SpaceChildrenPicker.scss new file mode 100644 index 0000000000..e0fa6ef26d --- /dev/null +++ b/res/css/views/spaces/_SpaceChildrenPicker.scss @@ -0,0 +1,35 @@ +/* +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_SpaceChildrenPicker { + margin: 16px 0; + + .mx_RadioButton + .mx_RadioButton { + margin-top: 16px; + } + + .mx_SearchBox { + // To match the space around the title + margin: 0 0 15px 0; + flex-grow: 0; + border-radius: 8px; + } + + .mx_SpaceChildrenPicker_noResults { + display: block; + margin-top: 24px; + } +} diff --git a/src/components/views/dialogs/ConfirmSpaceUserActionDialog.tsx b/src/components/views/dialogs/ConfirmSpaceUserActionDialog.tsx new file mode 100644 index 0000000000..4059682ade --- /dev/null +++ b/src/components/views/dialogs/ConfirmSpaceUserActionDialog.tsx @@ -0,0 +1,86 @@ +/* +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, { ComponentProps, useMemo, useState } from 'react'; +import ConfirmUserActionDialog from "./ConfirmUserActionDialog"; +import SpaceStore from "../../../stores/SpaceStore"; +import { Room } from "matrix-js-sdk/src/models/room"; +import SpaceChildrenPicker from "../spaces/SpaceChildrenPicker"; +import { _t } from '../../../languageHandler'; + +type BaseProps = ComponentProps; +interface IProps extends Omit { + space: Room; + allLabel: string; + specificLabel: string; + noneLabel?: string; + onFinished(success: boolean, reason?: string, rooms?: Room[]): void; + spaceChildFilter?(child: Room): boolean; +} + +const ConfirmSpaceUserActionDialog: React.FC = ({ + space, + spaceChildFilter, + allLabel, + specificLabel, + noneLabel, + onFinished, + ...props +}) => { + const spaceChildren = useMemo(() => { + const children = SpaceStore.instance.getChildren(space.roomId); + if (spaceChildFilter) { + return children.filter(spaceChildFilter); + } + return children; + }, [space.roomId, spaceChildFilter]); + + const [roomsToLeave, setRoomsToLeave] = useState([]); + const selectedRooms = useMemo(() => new Set(roomsToLeave), [roomsToLeave]); + + let warning: JSX.Element; + if (!spaceChildren.length) { + warning =
+ { _t("You’re not an admin of anything they’re a member of in , " + + "so banning won’t remove them from any rooms or spaces in .", {}, { + SpaceName: () => { space.name }, + }) } +
; + } + + return ( + { + onFinished(success, reason, roomsToLeave); + }} + className="mx_ConfirmSpaceUserActionDialog" + > + { warning } + + + ); +}; + +export default ConfirmSpaceUserActionDialog; diff --git a/src/components/views/dialogs/ConfirmUserActionDialog.tsx b/src/components/views/dialogs/ConfirmUserActionDialog.tsx index 7099556ac6..7468f400c6 100644 --- a/src/components/views/dialogs/ConfirmUserActionDialog.tsx +++ b/src/components/views/dialogs/ConfirmUserActionDialog.tsx @@ -14,9 +14,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React from 'react'; +import React, { ReactNode } from 'react'; import { MatrixClient } from 'matrix-js-sdk/src/client'; import { RoomMember } from "matrix-js-sdk/src/models/room-member"; +import classNames from "classnames"; + import { _t } from '../../../languageHandler'; import { GroupMemberType } from '../../../groups'; import { replaceableComponent } from "../../../utils/replaceableComponent"; @@ -28,9 +30,9 @@ import DialogButtons from "../elements/DialogButtons"; interface IProps { // matrix-js-sdk (room) member object. Supply either this or 'groupMember' - member: RoomMember; + member?: RoomMember; // group member object. Supply either this or 'member' - groupMember: GroupMemberType; + groupMember?: GroupMemberType; // needed if a group member is specified matrixClient?: MatrixClient; action: string; // eg. 'Ban' @@ -41,6 +43,8 @@ interface IProps { // be the string entered. askReason?: boolean; danger?: boolean; + children?: ReactNode; + className?: string; onFinished: (success: boolean, reason?: string) => void; } @@ -105,19 +109,23 @@ export default class ConfirmUserActionDialog extends React.Component { return (
-
- { avatar } +
+
+ { avatar } +
+
{ name }
+
{ userId }
-
{ name }
-
{ userId }
+ + { reasonBox } + { this.props.children }
- { reasonBox } { - const [query, setQuery] = useState(""); - const lcQuery = query.toLowerCase().trim(); - - const filteredRooms = useMemo(() => { - if (!lcQuery) { - return rooms; - } - - const matcher = new QueryMatcher(rooms, { - keys: ["name"], - funcs: [r => [r.getCanonicalAlias(), ...r.getAltAliases()].filter(Boolean)], - shouldMatchWordsOnly: false, - }); - - return matcher.match(lcQuery); - }, [rooms, lcQuery]); - - return
- - - { filteredRooms.map(room => { - return { - onChange(checked, room); - }} - />; - }) } - { filteredRooms.length < 1 ? - { _t("No results") } - : undefined } - -
; -}; - -const LeaveRoomsPicker = ({ space, spaceChildren, roomsToLeave, setRoomsToLeave }) => { - const selected = useMemo(() => new Set(roomsToLeave), [roomsToLeave]); - const [state, setState] = useState(RoomsToLeave.None); - - useEffect(() => { - if (state === RoomsToLeave.All) { - setRoomsToLeave(spaceChildren); - } else { - setRoomsToLeave([]); - } - }, [setRoomsToLeave, state, spaceChildren]); - - return
- - - { state === RoomsToLeave.Specific && ( - { - if (selected) { - setRoomsToLeave([room, ...roomsToLeave]); - } else { - setRoomsToLeave(roomsToLeave.filter(r => r !== room)); - } - }} - /> - ) } -
; -}; +import SpaceChildrenPicker from "../spaces/SpaceChildrenPicker"; interface IProps { space: Room; @@ -139,6 +38,7 @@ const isOnlyAdmin = (room: Room): boolean => { const LeaveSpaceDialog: React.FC = ({ space, onFinished }) => { const spaceChildren = useMemo(() => SpaceStore.instance.getChildren(space.roomId), [space.roomId]); const [roomsToLeave, setRoomsToLeave] = useState([]); + const selectedRooms = useMemo(() => new Set(roomsToLeave), [roomsToLeave]); let rejoinWarning; if (space.getJoinRule() !== JoinRule.Public) { @@ -173,12 +73,17 @@ const LeaveSpaceDialog: React.FC = ({ space, onFinished }) => { { rejoinWarning }

- { spaceChildren.length > 0 && } + { spaceChildren.length > 0 && ( + + ) } { onlyAdminWarning &&
{ onlyAdminWarning } diff --git a/src/components/views/right_panel/UserInfo.tsx b/src/components/views/right_panel/UserInfo.tsx index f1807985ae..3a12c6478f 100644 --- a/src/components/views/right_panel/UserInfo.tsx +++ b/src/components/views/right_panel/UserInfo.tsx @@ -70,6 +70,8 @@ import { mediaFromMxc } from "../../../customisations/Media"; import UIStore from "../../../stores/UIStore"; import { ComposerInsertPayload } from "../../../dispatcher/payloads/ComposerInsertPayload"; import SpaceStore from "../../../stores/SpaceStore"; +import ConfirmSpaceUserActionDialog from "../dialogs/ConfirmSpaceUserActionDialog"; +import { bulkSpaceBehaviour } from "../../../utils/space"; export interface IDevice { deviceId: string; @@ -530,7 +532,7 @@ interface IBaseProps { stopUpdating(): void; } -const RoomKickButton: React.FC = ({ member, startUpdating, stopUpdating }) => { +const RoomKickButton = ({ room, member, startUpdating, stopUpdating }: Omit) => { const cli = useContext(MatrixClientContext); // check if user can be kicked/disinvited @@ -540,21 +542,35 @@ const RoomKickButton: React.FC = ({ member, startUpdating, stopUpdat const { finished } = Modal.createTrackedDialog( 'Confirm User Action Dialog', 'onKick', - ConfirmUserActionDialog, + room.isSpaceRoom() ? ConfirmSpaceUserActionDialog : ConfirmUserActionDialog, { member, action: member.membership === "invite" ? _t("Disinvite") : _t("Kick"), title: member.membership === "invite" ? _t("Disinvite this user?") : _t("Kick this user?"), askReason: member.membership === "join", danger: true, + // space-specific props + space: room, + spaceChildFilter: (child: Room) => { + // Return true if the target member is not banned and we have sufficient PL to ban them + const myMember = child.getMember(cli.credentials.userId); + const theirMember = child.getMember(member.userId); + return myMember && theirMember && theirMember.membership === member.membership && + myMember.powerLevel > theirMember.powerLevel && + child.currentState.hasSufficientPowerLevelFor("kick", myMember.powerLevel); + }, + allLabel: _t("Kick them from everything I'm able to"), + specificLabel: _t("Kick them from specific things I'm able to"), }, + room.isSpaceRoom() ? "mx_ConfirmSpaceUserActionDialog_wrapper" : undefined, ); - const [proceed, reason] = await finished; + const [proceed, reason, rooms = []] = await finished; if (!proceed) return; startUpdating(); - cli.kick(member.roomId, member.userId, reason || undefined).then(() => { + + bulkSpaceBehaviour(room, rooms, room => cli.kick(room.roomId, member.userId, reason || undefined)).then(() => { // NO-OP; rely on the m.room.member event coming down else we could // get out of sync if we force setState here! console.log("Kick success"); @@ -654,34 +670,64 @@ const RedactMessagesButton: React.FC = ({ member }) => { ; }; -const BanToggleButton: React.FC = ({ member, startUpdating, stopUpdating }) => { +const BanToggleButton = ({ room, member, startUpdating, stopUpdating }: Omit) => { const cli = useContext(MatrixClientContext); + const isBanned = member.membership === "ban"; const onBanOrUnban = async () => { const { finished } = Modal.createTrackedDialog( 'Confirm User Action Dialog', 'onBanOrUnban', - ConfirmUserActionDialog, + room.isSpaceRoom() ? ConfirmSpaceUserActionDialog : ConfirmUserActionDialog, { member, - action: member.membership === 'ban' ? _t("Unban") : _t("Ban"), - title: member.membership === 'ban' ? _t("Unban this user?") : _t("Ban this user?"), - askReason: member.membership !== 'ban', - danger: member.membership !== 'ban', + action: isBanned ? _t("Unban") : _t("Ban"), + title: isBanned ? _t("Unban this user?") : _t("Ban this user?"), + askReason: !isBanned, + danger: !isBanned, + // space-specific props + space: room, + spaceChildFilter: isBanned + ? (child: Room) => { + // Return true if the target member is banned and we have sufficient PL to unban + const myMember = child.getMember(cli.credentials.userId); + const theirMember = child.getMember(member.userId); + return myMember && theirMember && theirMember.membership === "ban" && + myMember.powerLevel > theirMember.powerLevel && + child.currentState.hasSufficientPowerLevelFor("ban", myMember.powerLevel); + } + : (child: Room) => { + // Return true if the target member isn't banned and we have sufficient PL to ban + const myMember = child.getMember(cli.credentials.userId); + const theirMember = child.getMember(member.userId); + return myMember && theirMember && theirMember.membership !== "ban" && + myMember.powerLevel > theirMember.powerLevel && + child.currentState.hasSufficientPowerLevelFor("ban", myMember.powerLevel); + }, + allLabel: isBanned + ? _t("Unban them from everything I'm able to") + : _t("Ban them from everything I'm able to"), + specificLabel: isBanned + ? _t("Unban them from specific things I'm able to") + : _t("Ban them from specific things I'm able to"), }, + room.isSpaceRoom() ? "mx_ConfirmSpaceUserActionDialog_wrapper" : undefined, ); - const [proceed, reason] = await finished; + const [proceed, reason, rooms = []] = await finished; if (!proceed) return; startUpdating(); - let promise; - if (member.membership === 'ban') { - promise = cli.unban(member.roomId, member.userId); - } else { - promise = cli.ban(member.roomId, member.userId, reason || undefined); - } - promise.then(() => { + + const fn = (roomId: string) => { + if (isBanned) { + return cli.unban(roomId, member.userId); + } else { + return cli.ban(roomId, member.userId, reason || undefined); + } + }; + + bulkSpaceBehaviour(room, rooms, room => fn(room.roomId)).then(() => { // NO-OP; rely on the m.room.member event coming down else we could // get out of sync if we force setState here! console.log("Ban success"); @@ -697,12 +743,12 @@ const BanToggleButton: React.FC = ({ member, startUpdating, stopUpda }; let label = _t("Ban"); - if (member.membership === 'ban') { + if (isBanned) { label = _t("Unban"); } const classes = classNames("mx_UserInfo_field", { - mx_UserInfo_destructive: member.membership !== 'ban', + mx_UserInfo_destructive: !isBanned, }); return @@ -816,7 +862,12 @@ const RoomAdminToolsContainer: React.FC = ({ const canAffectUser = member.powerLevel < me.powerLevel || isMe; if (canAffectUser && me.powerLevel >= kickPowerLevel) { - kickButton = ; + kickButton = ; } if (me.powerLevel >= redactPowerLevel && (!SpaceStore.spacesEnabled || !room.isSpaceRoom())) { redactButton = ( @@ -824,7 +875,12 @@ const RoomAdminToolsContainer: React.FC = ({ ); } if (canAffectUser && me.powerLevel >= banPowerLevel) { - banButton = ; + banButton = ; } if (canAffectUser && me.powerLevel >= editPowerLevel && !room.isSpaceRoom()) { muteButton = ( diff --git a/src/components/views/spaces/SpaceChildrenPicker.tsx b/src/components/views/spaces/SpaceChildrenPicker.tsx new file mode 100644 index 0000000000..7b9e5534ca --- /dev/null +++ b/src/components/views/spaces/SpaceChildrenPicker.tsx @@ -0,0 +1,150 @@ +/* +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, { useEffect, useMemo, useState } from "react"; +import { Room } from "matrix-js-sdk/src/models/room"; + +import { _t } from "../../../languageHandler"; +import StyledRadioGroup from "../elements/StyledRadioGroup"; +import QueryMatcher from "../../../autocomplete/QueryMatcher"; +import SearchBox from "../../structures/SearchBox"; +import AutoHideScrollbar from "../../structures/AutoHideScrollbar"; +import { Entry } from "../dialogs/AddExistingToSpaceDialog"; + +enum Target { + All = "All", + Specific = "Specific", + None = "None", +} + +interface ISpecificChildrenPickerProps { + filterPlaceholder: string; + rooms: Room[]; + selected: Set; + onChange(selected: boolean, room: Room): void; +} + +const SpecificChildrenPicker = ({ filterPlaceholder, rooms, selected, onChange }: ISpecificChildrenPickerProps) => { + const [query, setQuery] = useState(""); + const lcQuery = query.toLowerCase().trim(); + + const filteredRooms = useMemo(() => { + if (!lcQuery) { + return rooms; + } + + const matcher = new QueryMatcher(rooms, { + keys: ["name"], + funcs: [r => [r.getCanonicalAlias(), ...r.getAltAliases()].filter(Boolean)], + shouldMatchWordsOnly: false, + }); + + return matcher.match(lcQuery); + }, [rooms, lcQuery]); + + return
+ + + { filteredRooms.map(room => { + return { + onChange(checked, room); + }} + />; + }) } + { filteredRooms.length < 1 ? + { _t("No results") } + : undefined } + +
; +}; + +interface IProps { + space: Room; + spaceChildren: Room[]; + selected: Set; + noneLabel?: string; + allLabel: string; + specificLabel: string; + onChange(rooms: Room[]): void; +} + +const SpaceChildrenPicker = ({ + space, + spaceChildren, + selected, + onChange, + noneLabel, + allLabel, + specificLabel, +}: IProps) => { + const [state, setState] = useState(noneLabel ? Target.None : Target.All); + + useEffect(() => { + if (state === Target.All) { + onChange(spaceChildren); + } else { + onChange([]); + } + }, [onChange, state, spaceChildren]); + + return <> +
+ d.label)} + /> +
+ + { state === Target.Specific && ( + { + if (isSelected) { + onChange([room, ...selected]); + } else { + onChange([...selected].filter(r => r !== room)); + } + }} + /> + ) } + ; +}; + +export default SpaceChildrenPicker; diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 28d0b2914b..5195b08f56 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1018,6 +1018,8 @@ "Upload": "Upload", "Name": "Name", "Description": "Description", + "No results": "No results", + "Search %(spaceName)s": "Search %(spaceName)s", "Please enter a name for the space": "Please enter a name for the space", "Spaces are a new feature.": "Spaces are a new feature.", "Spaces feedback": "Spaces feedback", @@ -1847,6 +1849,8 @@ "Kick": "Kick", "Disinvite this user?": "Disinvite this user?", "Kick this user?": "Kick this user?", + "Kick them from everything I'm able to": "Kick them from everything I'm able to", + "Kick them from specific things I'm able to": "Kick them from specific things I'm able to", "Failed to kick": "Failed to kick", "No recent messages by %(user)s found": "No recent messages by %(user)s found", "Try scrolling up in the timeline to see if there are any earlier ones.": "Try scrolling up in the timeline to see if there are any earlier ones.", @@ -1860,6 +1864,10 @@ "Ban": "Ban", "Unban this user?": "Unban this user?", "Ban this user?": "Ban this user?", + "Unban them from everything I'm able to": "Unban them from everything I'm able to", + "Ban them from everything I'm able to": "Ban them from everything I'm able to", + "Unban them from specific things I'm able to": "Unban them from specific things I'm able to", + "Ban them from specific things I'm able to": "Ban them from specific things I'm able to", "Failed to ban user": "Failed to ban user", "Failed to mute user": "Failed to mute user", "Unmute": "Unmute", @@ -2050,7 +2058,6 @@ "Application window": "Application window", "Share content": "Share content", "Join": "Join", - "No results": "No results", "Please create a new issue on GitHub so that we can investigate this bug.": "Please create a new issue on GitHub so that we can investigate this bug.", "collapse": "collapse", "expand": "expand", @@ -2217,6 +2224,7 @@ "Confirm Removal": "Confirm Removal", "Are you sure you wish to remove (delete) this event? Note that if you delete a room name or topic change, it could undo the change.": "Are you sure you wish to remove (delete) this event? Note that if you delete a room name or topic change, it could undo the change.", "Reason (optional)": "Reason (optional)", + "You’re not an admin of anything they’re a member of in , so banning won’t remove them from any rooms or spaces in .": "You’re not an admin of anything they’re a member of in , so banning won’t remove them from any rooms or spaces in .", "Clear all data in this session?": "Clear all data in this session?", "Clearing all data from this session is permanent. Encrypted messages will be lost unless their keys have been backed up.": "Clearing all data from this session is permanent. Encrypted messages will be lost unless their keys have been backed up.", "Clear all data": "Clear all data", @@ -2430,15 +2438,14 @@ "Clear cache and resync": "Clear cache and resync", "%(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 whilst we resynchronise with the server!", "Updating %(brand)s": "Updating %(brand)s", - "Don't leave any": "Don't leave any", - "Leave all rooms and spaces": "Leave all rooms and spaces", - "Leave specific rooms and spaces": "Leave specific rooms and spaces", - "Search %(spaceName)s": "Search %(spaceName)s", "You won't be able to rejoin unless you are re-invited.": "You won't be able to rejoin unless you are re-invited.", "You're the only admin of this space. Leaving it will mean no one has control over it.": "You're the only admin of this space. Leaving it will mean no one has control over it.", "You're the only admin of some of the rooms or spaces you wish to leave. Leaving them will leave them without any admins.": "You're the only admin of some of the rooms or spaces you wish to leave. Leaving them will leave them without any admins.", "Leave %(spaceName)s": "Leave %(spaceName)s", "Are you sure you want to leave ?": "Are you sure you want to leave ?", + "Don't leave any": "Don't leave any", + "Leave all rooms and spaces": "Leave all rooms and spaces", + "Leave specific rooms and spaces": "Leave specific rooms and spaces", "Leave space": "Leave space", "Encrypted messages are secured with end-to-end encryption. Only you and the recipient(s) have the keys to read these messages.": "Encrypted messages are secured with end-to-end encryption. Only you and the recipient(s) have the keys to read these messages.", "Start using Key Backup": "Start using Key Backup", diff --git a/src/utils/space.tsx b/src/utils/space.tsx index 5bbae369e7..aba9883ae7 100644 --- a/src/utils/space.tsx +++ b/src/utils/space.tsx @@ -155,20 +155,28 @@ export const showCreateNewSubspace = (space: Room): void => { ); }; +export const bulkSpaceBehaviour = async ( + space: Room, + children: Room[], + fn: (room: Room) => Promise, +): Promise => { + const modal = Modal.createDialog(Spinner, null, "mx_Dialog_spinner"); + try { + for (const room of children) { + await fn(room); + } + await fn(space); + } finally { + modal.close(); + } +}; + export const leaveSpace = (space: Room) => { Modal.createTrackedDialog("Leave Space", "", LeaveSpaceDialog, { space, onFinished: async (leave: boolean, rooms: Room[]) => { if (!leave) return; - const modal = Modal.createDialog(Spinner, null, "mx_Dialog_spinner"); - try { - for (const room of rooms) { - await leaveRoomBehaviour(room.roomId); - } - await leaveRoomBehaviour(space.roomId); - } finally { - modal.close(); - } + await bulkSpaceBehaviour(space, rooms, room => leaveRoomBehaviour(room.roomId)); dis.dispatch({ action: "after_leave_room", From d6159523373b4073cf77412d0dd85cae9c85bd64 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 17 Sep 2021 16:02:12 +0100 Subject: [PATCH 006/143] Add fallback warning --- .../views/dialogs/ConfirmSpaceUserActionDialog.tsx | 6 ++++++ src/components/views/right_panel/UserInfo.tsx | 13 +++++++++++++ src/i18n/strings/en_EN.json | 3 +++ 3 files changed, 22 insertions(+) diff --git a/src/components/views/dialogs/ConfirmSpaceUserActionDialog.tsx b/src/components/views/dialogs/ConfirmSpaceUserActionDialog.tsx index 4059682ade..9e014b86fd 100644 --- a/src/components/views/dialogs/ConfirmSpaceUserActionDialog.tsx +++ b/src/components/views/dialogs/ConfirmSpaceUserActionDialog.tsx @@ -27,6 +27,7 @@ interface IProps extends Omit = ({ allLabel, specificLabel, noneLabel, + warningMessage, onFinished, ...props }) => { @@ -59,6 +61,10 @@ const ConfirmSpaceUserActionDialog: React.FC = ({ SpaceName: () => { space.name }, }) }
; + } else if (warningMessage) { + warning =
+ { warningMessage } +
; } return ( diff --git a/src/components/views/right_panel/UserInfo.tsx b/src/components/views/right_panel/UserInfo.tsx index 3a12c6478f..9b394fea39 100644 --- a/src/components/views/right_panel/UserInfo.tsx +++ b/src/components/views/right_panel/UserInfo.tsx @@ -561,6 +561,10 @@ const RoomKickButton = ({ room, member, startUpdating, stopUpdating }: Omit, " + + "they'll still be able to access it after you kick them.", {}, { + SpaceName: () => { room.name }, + }), }, room.isSpaceRoom() ? "mx_ConfirmSpaceUserActionDialog_wrapper" : undefined, ); @@ -710,6 +714,15 @@ const BanToggleButton = ({ room, member, startUpdating, stopUpdating }: Omit, " + + "they won’t be unbanned from it.", {}, { + SpaceName: () => { room.name }, + }) + : _t("If you're not an admin of a room or space in , " + + "they'll still be able to access it after you ban them.", {}, { + SpaceName: () => { room.name }, + }), }, room.isSpaceRoom() ? "mx_ConfirmSpaceUserActionDialog_wrapper" : undefined, ); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 5195b08f56..d0bb4366fd 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1851,6 +1851,7 @@ "Kick this user?": "Kick this user?", "Kick them from everything I'm able to": "Kick them from everything I'm able to", "Kick them from specific things I'm able to": "Kick them from specific things I'm able to", + "If you're not an admin of a room or space in , they'll still be able to access it after you kick them.": "If you're not an admin of a room or space in , they'll still be able to access it after you kick them.", "Failed to kick": "Failed to kick", "No recent messages by %(user)s found": "No recent messages by %(user)s found", "Try scrolling up in the timeline to see if there are any earlier ones.": "Try scrolling up in the timeline to see if there are any earlier ones.", @@ -1868,6 +1869,8 @@ "Ban them from everything I'm able to": "Ban them from everything I'm able to", "Unban them from specific things I'm able to": "Unban them from specific things I'm able to", "Ban them from specific things I'm able to": "Ban them from specific things I'm able to", + "If you’re not an admin of a room or space in , they won’t be unbanned from it.": "If you’re not an admin of a room or space in , they won’t be unbanned from it.", + "If you're not an admin of a room or space in , they'll still be able to access it after you ban them.": "If you're not an admin of a room or space in , they'll still be able to access it after you ban them.", "Failed to ban user": "Failed to ban user", "Failed to mute user": "Failed to mute user", "Unmute": "Unmute", From b257393d74d5fc6c0b731e6696f136e906af6542 Mon Sep 17 00:00:00 2001 From: William Lachance Date: Sun, 19 Sep 2021 07:48:35 -0400 Subject: [PATCH 007/143] Make placeholder more grey when no input (fixes #17243) The placeholder is actually the label in this case. --- res/css/views/auth/_AuthBody.scss | 4 ---- res/css/views/elements/_Field.scss | 1 - 2 files changed, 5 deletions(-) diff --git a/res/css/views/auth/_AuthBody.scss b/res/css/views/auth/_AuthBody.scss index 90dca32e48..3c2736459a 100644 --- a/res/css/views/auth/_AuthBody.scss +++ b/res/css/views/auth/_AuthBody.scss @@ -58,10 +58,6 @@ limitations under the License. background-color: $authpage-body-bg-color; } - .mx_Field label { - color: $authpage-primary-color; - } - .mx_Field_labelAlwaysTopLeft label, .mx_Field select + label /* Always show a select's label on top to not collide with the value */, .mx_Field input:focus + label, diff --git a/res/css/views/elements/_Field.scss b/res/css/views/elements/_Field.scss index 71d37a015d..37d335b76d 100644 --- a/res/css/views/elements/_Field.scss +++ b/res/css/views/elements/_Field.scss @@ -100,7 +100,6 @@ limitations under the License. color 0.25s ease-out 0.1s, transform 0.25s ease-out 0.1s, background-color 0.25s ease-out 0.1s; - color: $primary-content; background-color: transparent; font-size: $font-14px; transform: translateY(0); From 18415e435ca6da9f9c2c3f853e5b973b06737f0e Mon Sep 17 00:00:00 2001 From: Jeff Huang Date: Wed, 22 Sep 2021 04:01:36 +0000 Subject: [PATCH 008/143] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (3166 of 3166 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 | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index 9d644d424b..d4da600284 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -3160,5 +3160,12 @@ "To join a space you'll need an invite.": "若要加入空間,您必須被邀請。", "You can also make Spaces from communities.": "您也可以從社群建立空間。", "Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.": "為此工作階段暫時顯示社群而非空間。對此功能的支援將在不久的將來移除。這將會重新載入 Element。", - "Display Communities instead of Spaces": "顯示社群而非空間" + "Display Communities instead of Spaces": "顯示社群而非空間", + "Would you like to leave the rooms in this space?": "您想要離開此空間中的聊天室嗎?", + "You are about to leave .": "您將要離開 。", + "Leave some rooms": "離開部份聊天室", + "Leave all rooms": "離開所有聊天室", + "Don't leave any rooms": "不要離開任何聊天室", + "%(reactors)s reacted with %(content)s": "%(reactors)s 使用了 %(content)s 反應", + "Joining space …": "正在加入空間……" } From 66cd3970ae2fc8d80dcb6b5ffdebc7cf1154288f Mon Sep 17 00:00:00 2001 From: Kim Tae Kyeong Date: Wed, 22 Sep 2021 00:40:13 +0000 Subject: [PATCH 009/143] Translated using Weblate (Korean) Currently translated at 44.9% (1424 of 3166 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/ko/ --- src/i18n/strings/ko.json | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/i18n/strings/ko.json b/src/i18n/strings/ko.json index a675a151b0..5843fe8969 100644 --- a/src/i18n/strings/ko.json +++ b/src/i18n/strings/ko.json @@ -271,7 +271,7 @@ "This process allows you to export the keys for messages you have received in encrypted rooms to a local file. You will then be able to import the file into another Matrix client in the future, so that client will also be able to decrypt these messages.": "이 과정으로 암호화한 방에서 받은 메시지의 키를 로컬 파일로 내보낼 수 있습니다. 그런 다음 나중에 다른 Matrix 클라이언트에서 파일을 가져와서, 해당 클라이언트에서도 이 메시지를 복호화할 수 있도록 할 수 있습니다.", "The exported file will allow anyone who can read it to decrypt any encrypted messages that you can see, so you should be careful to keep it secure. To help with this, you should enter a passphrase below, which will be used to encrypt the exported data. It will only be possible to import the data by using the same passphrase.": "내보낸 파일이 있으면 누구든 암호화한 메시지를 복호화해서 읽을 수 있으므로, 보안에 신경을 써야 합니다. 이런 이유로 내보낸 파일을 암호화하도록 아래에 암호를 입력하는 것을 추천합니다. 같은 암호를 사용해야 데이터를 불러올 수 있을 것입니다.", "This process allows you to import encryption keys that you had previously exported from another Matrix client. You will then be able to decrypt any messages that the other client could decrypt.": "이 과정으로 다른 Matrix 클라이언트에서 내보낸 암호화 키를 가져올 수 있습니다. 그런 다음 이전 클라이언트에서 복호화할 수 있는 모든 메시지를 복호화할 수 있습니다.", - "The export file will be protected with a passphrase. You should enter the passphrase here, to decrypt the file.": "내보낸 파일이 암호로 보호되어 있습니다. 파일을 복호화하려면, 여기에 암호를 입력해야 합니다.", + "The export file will be protected with a passphrase. You should enter the passphrase here, to decrypt the file.": "내보낸 파일이 암호로 보호되어 있습니다. 파일을 복호화하려면, 여기에 암호를 입력해야 합니다.", "Are you sure you wish to remove (delete) this event? Note that if you delete a room name or topic change, it could undo the change.": "이 이벤트를 감추길(삭제하길) 원하세요? 방 이름을 삭제하거나 주제를 바꾸면, 다시 생길 수도 있습니다.", "Unable to restore session": "세션을 복구할 수 없음", "If you have previously used a more recent version of %(brand)s, your session may be incompatible with this version. Close this window and return to the more recent version.": "이전에 최근 버전의 %(brand)s을 썼다면, 세션이 이 버전과 맞지 않을 것입니다. 창을 닫고 최근 버전으로 돌아가세요.", @@ -840,7 +840,7 @@ "There was an error joining the room": "방에 참가하는 동안 오류가 발생했습니다", "Sorry, your homeserver is too old to participate in this room.": "죄송합니다, 이 방에 참여하기엔 홈서버가 너무 오래됬습니다.", "Custom user status messages": "맞춤 사용자 상태 메시지", - "Group & filter rooms by custom tags (refresh to apply changes)": "맞춤 태그로 방을 그룹 & 필터\n(변경 사항을 적용하려면 새로고침)", + "Group & filter rooms by custom tags (refresh to apply changes)": "맞춤 태그로 방을 그룹 & 필터 (변경 사항을 적용하려면 새로고침)", "You do not have the required permissions to use this command.": "이 명령어를 사용하기 위해 필요한 권한이 없습니다.", "Render simple counters in room header": "방 헤더에 간단한 카운터 표현", "Enable Emoji suggestions while typing": "입력 중 이모지 제안 켜기", @@ -1414,10 +1414,13 @@ "Create Account": "계정 만들기", "Integration manager": "통합 관리자", "Using this widget may share data with %(widgetDomain)s & your integration manager.": "이 위젯을 사용하면 %(widgetDomain)s & 통합 관리자와 데이터를 공유합니다.", - "Identity server is": "ID 서버:", + "Identity server is": "ID 서버는", "Identity server": "ID 서버", "Identity server (%(server)s)": "ID 서버 (%(server)s)", "Could not connect to identity server": "ID 서버에 연결할 수 없음", "Not a valid identity server (status code %(code)s)": "올바르지 않은 ID 서버 (상태 코드 %(code)s)", - "Identity server URL must be HTTPS": "ID 서버 URL은 HTTPS이어야 함" + "Identity server URL must be HTTPS": "ID 서버 URL은 HTTPS이어야 함", + "Appearance": "모습", + "Appearance Settings only affect this %(brand)s session.": "모습 설정은 이 %(brand)s 세션에만 영향을 끼칩니다.", + "Customise your appearance": "모습 개인화하기" } From f15951f35fbbe9b4b2d64349de83be05ca65427e Mon Sep 17 00:00:00 2001 From: waclaw66 Date: Wed, 22 Sep 2021 05:05:11 +0000 Subject: [PATCH 010/143] Translated using Weblate (Czech) Currently translated at 100.0% (3166 of 3166 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 | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/i18n/strings/cs.json b/src/i18n/strings/cs.json index 6ef1a3dd1e..bf6c2c08f3 100644 --- a/src/i18n/strings/cs.json +++ b/src/i18n/strings/cs.json @@ -2901,7 +2901,7 @@ "e.g. my-space": "např. můj-prostor", "Silence call": "Ztlumit zvonění", "Sound on": "Zvuk zapnutý", - "Show all rooms in Home": "Zobrazit všechny místnosti na domácí obrazovce", + "Show all rooms in Home": "Zobrazit všechny místnosti na úvodní obrazovce", "Report to moderators prototype. In rooms that support moderation, the `report` button will let you report abuse to room moderators": "Prototyp Nahlášování moderátorům. V místnostech, které podporují moderování, vám tlačítko `nahlásit` umožní nahlásit zneužití moderátorům místnosti", "%(senderName)s changed the pinned messages for the room.": "%(senderName)s změnil(a) připnuté zprávy v místnosti.", "%(senderName)s kicked %(targetName)s": "%(senderName)s vykopl(a) uživatele %(targetName)s", @@ -3056,7 +3056,7 @@ "Want to add a new space instead?": "Chcete místo toho přidat nový prostor?", "Decrypting": "Dešifrování", "Show all rooms": "Zobrazit všechny místnosti", - "All rooms you're in will appear in Home.": "Všechny místnosti, ve kterých se nacházíte, se zobrazí na domovské obrazovce.", + "All rooms you're in will appear in Home.": "Všechny místnosti, ve kterých se nacházíte, se zobrazí na úvodní obrazovce.", "Send pseudonymous analytics data": "Odeslat pseudonymní analytická data", "Missed call": "Zmeškaný hovor", "Call declined": "Hovor odmítnut", @@ -3162,5 +3162,10 @@ "Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.": "Dočasně zobrazit skupiny místo prostorů pro tuto relaci. Podpora bude v blízké budoucnosti odstraněna. Toto provede přenačtení Elementu.", "Display Communities instead of Spaces": "Zobrazit skupiny místo prostorů", "Joining space …": "Připojování k prostoru…", - "%(reactors)s reacted with %(content)s": "%(reactors)s reagoval(a) na %(content)s" + "%(reactors)s reacted with %(content)s": "%(reactors)s reagoval(a) na %(content)s", + "Would you like to leave the rooms in this space?": "Chcete odejít z místností v tomto prostoru?", + "You are about to leave .": "Odcházíte z .", + "Leave some rooms": "Odejít z některých místností", + "Don't leave any rooms": "Neodcházet z žádné místnosti", + "Leave all rooms": "Odejít ze všech místností" } From 350f93191a2ddbed82f0b269faf14d84d2354208 Mon Sep 17 00:00:00 2001 From: XoseM Date: Wed, 22 Sep 2021 04:47:33 +0000 Subject: [PATCH 011/143] Translated using Weblate (Galician) Currently translated at 100.0% (3166 of 3166 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 | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/gl.json b/src/i18n/strings/gl.json index 82c01da943..875a3ff2d2 100644 --- a/src/i18n/strings/gl.json +++ b/src/i18n/strings/gl.json @@ -3157,5 +3157,12 @@ "To join a space you'll need an invite.": "Para unirte a un espazo precisas un convite.", "You can also make Spaces from communities.": "Tamén podes crear Espazos a partir de comunidades.", "Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.": "De xeito temporal, mostrar comunidades no lugar de Espazos durante esta sesión. Esta función vai ser eliminada en próximas versións. Reiniciará Element.", - "Display Communities instead of Spaces": "Mostrar Comunidades no lugar de Espazos" + "Display Communities instead of Spaces": "Mostrar Comunidades no lugar de Espazos", + "Would you like to leave the rooms in this space?": "Queres sair destas salas neste espazo?", + "You are about to leave .": "Vas saír de .", + "Leave some rooms": "Sair de algunhas salas", + "Leave all rooms": "Sair de tódalas salas", + "Don't leave any rooms": "Non saír de ningunha sala", + "%(reactors)s reacted with %(content)s": "%(reactors)s reaccionou con %(content)s", + "Joining space …": "Uníndote ao espazo…" } From 8a8b8a156e210673e26cf2eb99d90cca0d0713a7 Mon Sep 17 00:00:00 2001 From: iaiz Date: Wed, 22 Sep 2021 11:01:21 +0000 Subject: [PATCH 012/143] Translated using Weblate (Spanish) Currently translated at 99.7% (3158 of 3166 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 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/es.json b/src/i18n/strings/es.json index d5568f003c..a4761610a9 100644 --- a/src/i18n/strings/es.json +++ b/src/i18n/strings/es.json @@ -3151,5 +3151,10 @@ "To join a space you'll need an invite.": "Para unirte a un espacio, necesitas que te inviten a él.", "You can also make Spaces from communities.": "También puedes crear espacios a partir de comunidades.", "Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.": "Ver temporalmente comunidades en vez de espacios durante esta sesión. Esta opción desaparecerá en el futuro. Element se recargará.", - "Display Communities instead of Spaces": "Ver comunidades en vez de espacios" + "Display Communities instead of Spaces": "Ver comunidades en vez de espacios", + "Don't leave any rooms": "No salir de ninguna sala", + "Leave all rooms": "Salir de todas las salas", + "Leave some rooms": "Salir de algunas salas", + "Would you like to leave the rooms in this space?": "¿Quieres salir también de las salas del espacio?", + "You are about to leave .": "Estás a punto de salirte de ." } From 0c59389ae101e8d4e6df1c32c52934506bf1bc39 Mon Sep 17 00:00:00 2001 From: LinAGKar Date: Thu, 23 Sep 2021 07:12:25 +0000 Subject: [PATCH 013/143] Translated using Weblate (Swedish) Currently translated at 100.0% (3166 of 3166 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 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/sv.json b/src/i18n/strings/sv.json index ea2e06e381..50ff9f5056 100644 --- a/src/i18n/strings/sv.json +++ b/src/i18n/strings/sv.json @@ -3159,5 +3159,10 @@ "To join a space you'll need an invite.": "För att gå med i ett utrymme så behöver du en inbjudan.", "You can also make Spaces from communities.": "Du kan också göra utrymmen av gemenskaper.", "Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.": "Visa tillfälligt gemenskaper istället för utrymmen för den här sessionen. Stöd för detta kommer snart att tas bort. Detta kommer att ladda om Element.", - "Display Communities instead of Spaces": "Visa gemenskaper istället för utrymmen" + "Display Communities instead of Spaces": "Visa gemenskaper istället för utrymmen", + "Would you like to leave the rooms in this space?": "Vill du lämna rummen i det här utrymmet?", + "You are about to leave .": "Du kommer att lämna .", + "Leave some rooms": "Lämna vissa rum", + "Leave all rooms": "Lämna alla rum", + "Don't leave any rooms": "Lämna inga rum" } From 7dbdeacd2bfd6b05482df713eba75b5881d89c10 Mon Sep 17 00:00:00 2001 From: Wiktor Przybylski Date: Fri, 24 Sep 2021 06:06:36 +0000 Subject: [PATCH 014/143] Translated using Weblate (Polish) Currently translated at 65.6% (2078 of 3166 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/pl/ --- src/i18n/strings/pl.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/pl.json b/src/i18n/strings/pl.json index 174f77d955..88d8b53afc 100644 --- a/src/i18n/strings/pl.json +++ b/src/i18n/strings/pl.json @@ -1068,7 +1068,7 @@ "Find a room… (e.g. %(exampleRoom)s)": "Znajdź pokój… (np. %(exampleRoom)s)", "If you can't find the room you're looking for, ask for an invite or Create a new room.": "Jeżeli nie możesz znaleźć szukanego pokoju, poproś o zaproszenie albo stwórz nowy pokój.", "Show typing notifications": "Pokazuj powiadomienia o pisaniu", - "Match system theme": "Dopasuj do motywu systemego", + "Match system theme": "Dopasuj do motywu systemowego", "They match": "Pasują do siebie", "They don't match": "Nie pasują do siebie", "Upload": "Prześlij", From 5c7f5dae6fc0f3ceedee053fbef26b0afe38c357 Mon Sep 17 00:00:00 2001 From: Hubert Jasudowicz Date: Thu, 23 Sep 2021 14:33:01 +0000 Subject: [PATCH 015/143] Translated using Weblate (Polish) Currently translated at 65.6% (2078 of 3166 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/pl/ --- src/i18n/strings/pl.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/pl.json b/src/i18n/strings/pl.json index 88d8b53afc..d82e55daf0 100644 --- a/src/i18n/strings/pl.json +++ b/src/i18n/strings/pl.json @@ -933,7 +933,7 @@ "Show hidden events in timeline": "Pokaż ukryte wydarzenia na linii czasowej", "Allow fallback call assist server turn.matrix.org when your homeserver does not offer one (your IP address would be shared during a call)": "Pozwól na awaryjny serwer wspomagania połączeń turn.matrix.org, gdy Twój serwer domowy takiego nie oferuje (Twój adres IP będzie udostępniony podczas połączenia)", "Messages containing my username": "Wiadomości zawierające moją nazwę użytkownika", - "Encrypted messages in one-to-one chats": "Zaszyforwane wiadomości w rozmowach jeden-do-jednego", + "Encrypted messages in one-to-one chats": "Zaszyfrowane wiadomości w rozmowach jeden-do-jednego", "Encrypted messages in group chats": "Zaszyfrowane wiadomości w rozmowach grupowych", "When rooms are upgraded": "Kiedy pokoje są uaktualniane", "The other party cancelled the verification.": "Druga strona anulowała weryfikację.", From 8694d88177713840b1d0848245e3f8bc8bd63486 Mon Sep 17 00:00:00 2001 From: random Date: Thu, 23 Sep 2021 09:24:33 +0000 Subject: [PATCH 016/143] Translated using Weblate (Italian) Currently translated at 99.9% (3165 of 3166 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 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/it.json b/src/i18n/strings/it.json index 6cf5ff1e07..6792e62c9f 100644 --- a/src/i18n/strings/it.json +++ b/src/i18n/strings/it.json @@ -3161,5 +3161,10 @@ "Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.": "Mostra temporaneamente le comunità invece degli spazi per questa sessione. Il supporto per questa azione verrà rimosso nel breve termine. Element verrà ricaricato.", "Display Communities instead of Spaces": "Mostra le comunità invece degli spazi", "%(reactors)s reacted with %(content)s": "%(reactors)s ha reagito con %(content)s", - "Joining space …": "Ingresso nello spazio …" + "Joining space …": "Ingresso nello spazio …", + "Would you like to leave the rooms in this space?": "Vuoi uscire dalle stanze di questo spazio?", + "You are about to leave .": "Stai per uscire da .", + "Leave some rooms": "Esci da alcune stanze", + "Leave all rooms": "Esci da tutte le stanze", + "Don't leave any rooms": "Non uscire da alcuna stanza" } From 6dbe61de2b94343b717809d3559d8632bd33667a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Wed, 22 Sep 2021 19:46:36 +0000 Subject: [PATCH 017/143] Translated using Weblate (Estonian) Currently translated at 99.9% (3165 of 3166 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 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index cb158ad4cf..b4f58e04da 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -3158,5 +3158,10 @@ "Before you upgrade": "Enne uuendamist", "To join a space you'll need an invite.": "Kogukonnakeskusega liitumiseks vajad kutset.", "%(reactors)s reacted with %(content)s": "%(reactors)s kasutajat reageeris järgnevalt: %(content)s", - "Joining space …": "Liitun kohukonnakeskusega…" + "Joining space …": "Liitun kohukonnakeskusega…", + "Would you like to leave the rooms in this space?": "Kas sa soovid lahkuda ka selle kogukonna jututubadest?", + "You are about to leave .": "Sa oled lahkumas kogukonnast.", + "Leave some rooms": "Lahku mõnedest jututubadest", + "Leave all rooms": "Lahku kõikidest jututubadest", + "Don't leave any rooms": "Ära lahku ühestki jututoast" } From c21533f7afe774a6a3ab8478323e8a97099eca8e Mon Sep 17 00:00:00 2001 From: jelv Date: Sat, 25 Sep 2021 08:06:29 +0000 Subject: [PATCH 018/143] Translated using Weblate (Dutch) Currently translated at 100.0% (3166 of 3166 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 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/nl.json b/src/i18n/strings/nl.json index 8fe877544c..950eaa68a2 100644 --- a/src/i18n/strings/nl.json +++ b/src/i18n/strings/nl.json @@ -1271,7 +1271,7 @@ "Find a room…": "Zoek een gesprek…", "Find a room… (e.g. %(exampleRoom)s)": "Zoek een gesprek… (bv. %(exampleRoom)s)", "If you can't find the room you're looking for, ask for an invite or Create a new room.": "Als u de kamer niet kunt vinden is het mogelijk privé, vraag dan om een uitnodiging of maak een nieuwe kamer aan.", - "Explore rooms": "Ontdek kamers", + "Explore rooms": "Kamers ontdekken", "Show previews/thumbnails for images": "Miniaturen voor afbeeldingen tonen", "Clear cache and reload": "Cache wissen en herladen", "You are about to remove %(count)s messages by %(user)s. This cannot be undone. Do you wish to continue?|one": "U staat op het punt 1 bericht door %(user)s te verwijderen. Dit kan niet ongedaan gemaakt worden. Wilt u doorgaan?", @@ -2345,7 +2345,7 @@ "Page Down": "Page Down", "Esc": "Esc", "Enter": "Enter", - "Space": "Spatie", + "Space": "Ruimte", "Ctrl": "Ctrl", "Super": "Super", "Shift": "Shift", From 4f8c2ecaa2adee822a78c658da936598dfac54fa Mon Sep 17 00:00:00 2001 From: Tirifto Date: Sat, 25 Sep 2021 13:39:30 +0000 Subject: [PATCH 019/143] Translated using Weblate (Esperanto) Currently translated at 98.6% (3123 of 3166 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 | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/eo.json b/src/i18n/strings/eo.json index 86ffb94251..fd3631c297 100644 --- a/src/i18n/strings/eo.json +++ b/src/i18n/strings/eo.json @@ -3099,5 +3099,30 @@ "What kind of Space do you want to create?": "Kian aron volas vi krei?", "All rooms you're in will appear in Home.": "Ĉiuj ĉambroj, kie vi estas, aperos en la ĉefpaĝo.", "Show all rooms in Home": "Montri ĉiujn ĉambrojn en ĉefpaĝo", - "%(senderName)s pinned a message to this room. See all pinned messages.": "%(senderName)s fiksis mesaĝon al ĉi tiu ĉambro. Vidu ĉiujn fiksitajn mesaĝojn." + "%(senderName)s pinned a message to this room. See all pinned messages.": "%(senderName)s fiksis mesaĝon al ĉi tiu ĉambro. Vidu ĉiujn fiksitajn mesaĝojn.", + "To avoid these issues, create a new encrypted room for the conversation you plan to have.": "Por eviti tiujn problemojn, kreu novan ĉifritan ĉambron por la planata interparolo.", + "It's not recommended to add encryption to public rooms.Anyone can find and join public rooms, so anyone can read messages in them. You'll get none of the benefits of encryption, and you won't be able to turn it off later. Encrypting messages in a public room will make receiving and sending messages slower.": "Ne rekomendate estas aldoni ĉifradon al publikaj ĉambroj. Ĉiu ajn povas trovi publikajn ĉambrojn kaj aliĝi, do ĉiu ajn povas legi ties mesaĝojn. Vi havos neniujn avantaĝojn de ĉifrado, kaj vi ne povos ĝin malŝalti pli poste. Ĉifrado en publikaj ĉambroj malrapidigos ricevadon kaj sendadon de mesaĝoj.", + "Are you sure you want to add encryption to this public room?": "Ĉu vi certas, ke vi volas aldoni ĉifradon al ĉi tiu publika ĉambro?", + "Select the roles required to change various parts of the space": "Elekti rolojn bezonatajn por ŝanĝado de diversaj partoj de la aro", + "Change description": "Ŝanĝi priskribon", + "Change main address for the space": "Ŝanĝi ĉefadreson de aro", + "Change space name": "Ŝanĝi nomon de aro", + "Change space avatar": "Ŝanĝi bildon de aro", + "Upgrade anyway": "Tamen gradaltigi", + "This room is in some spaces you’re not an admin of. In those spaces, the old room will still be shown, but people will be prompted to join the new one.": "Ĉi tiu ĉambro estas en iuj aroj, kiujn vi ne administras. En tiuj aroj, la malnova ĉambro aperos, sed tie oni ricevos avizon aliĝi al la nova.", + "Before you upgrade": "Antaŭ ol vi gradaltigos", + "Anyone in can find and join. You can select other spaces too.": "Ĉiu en povas trovi kaj aliĝi. Vi povas elekti ankaŭ aliajn arojn.", + "Currently, %(count)s spaces have access|one": "Nun, aro povas aliri", + "& %(count)s more|one": "kaj %(count)s pli", + "To join a space you'll need an invite.": "Por aliĝi al aro, vi bezonas inviton.", + "You can also make Spaces from communities.": "Vi ankaŭ povas krei Arojn el komunumoj.", + "Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.": "Provizore montri komunumojn anstataŭ arojn por tiu ĉi salutaĵo. Subteno de tio ĉi baldaŭ malaperos. Ĉi tio re-enlegos Elementon.", + "Display Communities instead of Spaces": "Montri komunumojn anstataŭ arojn", + "Autoplay videos": "Memage ludi filmojn", + "Autoplay GIFs": "Memage ludi GIF-ojn", + "Multiple integration managers (requires manual setup)": "Pluraj kunigiloj (bezonas permanan agordon)", + "Threaded messaging": "Mesaĝaj fadenoj", + "%(senderName)s unpinned a message from this room. See all pinned messages.": "%(senderName)s malfiksis mesaĝon de ĉi tiu ĉambro. Vidu ĉiujn fiksitajn mesaĝojn.", + "%(senderName)s unpinned a message from this room. See all pinned messages.": "%(senderName)s malfiksis mesaĝon de ĉi tiu ĉambro. Vidu ĉiujn fiksitajn mesaĝojn.", + "%(senderName)s pinned a message to this room. See all pinned messages.": "%(senderName)s fiksis mesaĝon al ĉi tiu ĉambro. Vidu ĉiujn fiksitajn mesaĝojn." } From 97fb55bd37cc63b0342cb7c3dccb85b59b6abc45 Mon Sep 17 00:00:00 2001 From: Linerly Date: Sat, 25 Sep 2021 00:32:07 +0000 Subject: [PATCH 020/143] Translated using Weblate (Indonesian) Currently translated at 6.8% (216 of 3166 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/id/ --- src/i18n/strings/id.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/id.json b/src/i18n/strings/id.json index c0dc0b926a..c96a10ea2a 100644 --- a/src/i18n/strings/id.json +++ b/src/i18n/strings/id.json @@ -199,7 +199,7 @@ "The version of %(brand)s": "Versi %(brand)s", "Your language of choice": "Pilihan bahasamu", "Your homeserver's URL": "URL Homeserver Anda", - "e.g. %(exampleValue)s": "", + "e.g. %(exampleValue)s": "mis. %(exampleValue)s", "Every page you use in the app": "Setiap halaman yang digunakan di app", "e.g. ": "e.g. ", "Your device resolution": "Resolusi perangkat Anda", @@ -214,5 +214,5 @@ "Explore rooms": "Jelajahi ruang", "Sign In": "Masuk", "Create Account": "Buat Akun", - "Identity server": "Server Identitas" + "Identity server": "Server identitas" } From a3a1820064ee1a20e21a7729e27672d9ea91a7b0 Mon Sep 17 00:00:00 2001 From: Tirifto Date: Mon, 27 Sep 2021 00:56:13 +0000 Subject: [PATCH 021/143] Translated using Weblate (Esperanto) Currently translated at 99.6% (3155 of 3166 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 | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/eo.json b/src/i18n/strings/eo.json index fd3631c297..a109b102e6 100644 --- a/src/i18n/strings/eo.json +++ b/src/i18n/strings/eo.json @@ -3124,5 +3124,37 @@ "Threaded messaging": "Mesaĝaj fadenoj", "%(senderName)s unpinned a message from this room. See all pinned messages.": "%(senderName)s malfiksis mesaĝon de ĉi tiu ĉambro. Vidu ĉiujn fiksitajn mesaĝojn.", "%(senderName)s unpinned a message from this room. See all pinned messages.": "%(senderName)s malfiksis mesaĝon de ĉi tiu ĉambro. Vidu ĉiujn fiksitajn mesaĝojn.", - "%(senderName)s pinned a message to this room. See all pinned messages.": "%(senderName)s fiksis mesaĝon al ĉi tiu ĉambro. Vidu ĉiujn fiksitajn mesaĝojn." + "%(senderName)s pinned a message to this room. See all pinned messages.": "%(senderName)s fiksis mesaĝon al ĉi tiu ĉambro. Vidu ĉiujn fiksitajn mesaĝojn.", + "To join this Space, hide communities in your preferences": "Por aliĝi al ĉi tiu aro, kaŝu komunumojn per viaj agordoj", + "To view this Space, hide communities in your preferences": "Por vidi ĉi tiun aron, kaŝu komunumojn per viaj agordoj", + "Rooms and spaces": "Ĉambroj kaj aroj", + "Results": "Rezultoj", + "To join %(communityName)s, swap to communities in your preferences": "Por aliĝi al %(communityName)s, ŝaltu komunumojn en viaj agordoj", + "To view %(communityName)s, swap to communities in your preferences": "Por vidi komunumon %(communityName)s, ŝaltu komunumojn en viaj agordoj", + "Private community": "Privata komunumo", + "Public community": "Publika komunumo", + "Forward": "Plusendi", + "Would you like to leave the rooms in this space?": "Ĉu vi volus foriri de la ĉambroj en ĉi tiu aro?", + "You are about to leave .": "Vi foriros de .", + "Leave some rooms": "Foriri de iuj ĉambroj", + "Leave all rooms": "Foriri de ĉiuj ĉambroj", + "Don't leave any rooms": "Foriru de neniuj ĉambroj", + "%(reactors)s reacted with %(content)s": "%(reactors)s reagis per %(content)s", + "Thread": "Fadeno", + "Some encryption parameters have been changed.": "Ŝanĝiĝis iuj parametroj de ĉifrado.", + "Role in ": "Rolo en ", + "Message": "Mesaĝo", + "Show threads": "Montri fadenojn", + "Joining space …": "Aliĝante al aro…", + "Explore %(spaceName)s": "Esplori aron %(spaceName)s", + "Message didn't send. Click for info.": "Mesaĝo ne sendiĝis. Klaku por akiri informojn.", + "Send a sticker": "Sendi glumarkon", + "Reply to thread…": "Respondi al fadeno…", + "Reply to encrypted thread…": "Respondi al ĉifrita fadeno…", + "Add emoji": "Aldoni bildosignon", + "To avoid these issues, create a new public room for the conversation you plan to have.": "Por eviti ĉi tiujn problemojn, kreu novan publikan ĉambron por la dezirata interparolo.", + "It's not recommended to make encrypted rooms public. It will mean anyone can find and join the room, so anyone can read messages. You'll get none of the benefits of encryption. Encrypting messages in a public room will make receiving and sending messages slower.": "Publikigo de ĉifrataj ĉambroj estas malrekomendata. Ĝi implicas, ke ĉiu povos trovi la ĉambron kaj aliĝi al ĝi, kaj ĉiu do povos legi mesaĝojn. Vi havos neniujn avantaĝojn de ĉifrado. Ĉifrado de mesaĝoj en publika ĉambro malrapidigos iliajn ricevadon kaj sendadon.", + "Are you sure you want to make this encrypted room public?": "Ĉu vi certas, ke vi volas publikigi ĉi tiun ĉifratan ĉambron?", + "Unknown failure": "Nekonata malsukceso", + "Failed to update the join rules": "Malsukcesis ĝisdatigi regulojn pri aliĝo" } From 0928a2fcee3705f50d1a727393c6e7f8c6b2a79f Mon Sep 17 00:00:00 2001 From: Andrejs Date: Sun, 26 Sep 2021 15:37:19 +0000 Subject: [PATCH 022/143] Translated using Weblate (Latvian) Currently translated at 60.6% (1921 of 3166 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/lv/ --- src/i18n/strings/lv.json | 298 +++++++++++++++++++++++++++------------ 1 file changed, 211 insertions(+), 87 deletions(-) diff --git a/src/i18n/strings/lv.json b/src/i18n/strings/lv.json index 30a455ad50..d8e2a21638 100644 --- a/src/i18n/strings/lv.json +++ b/src/i18n/strings/lv.json @@ -12,7 +12,7 @@ "Microphone": "Mikrofons", "Camera": "Kamera", "Advanced": "Papildu", - "Always show message timestamps": "Vienmēr rādīt ziņojumu laika zīmogu", + "Always show message timestamps": "Vienmēr rādīt ziņas laika zīmogu", "Authentication": "Autentifikācija", "%(items)s and %(lastItem)s": "%(items)s un %(lastItem)s", "A new password must be entered.": "Nepieciešams ievadīt jauno paroli.", @@ -23,7 +23,7 @@ "Are you sure you want to reject the invitation?": "Vai tiešām vēlaties noraidīt šo uzaicinājumu?", "Attachment": "Pielikums", "Ban": "Liegt pieeju", - "Banned users": "Lietotāji, kuriem liegta pieeju", + "Banned users": "Lietotāji, kuriem liegta pieeja", "Bans user with given id": "Liedz pieeju lietotājam ar norādīto id", "Can't connect to homeserver - please check your connectivity, ensure your homeserver's SSL certificate is trusted, and that a browser extension is not blocking requests.": "Neizdodas savienoties ar bāzes serveri. Pārbaudi tīkla savienojumu un pārliecinies, ka bāzes servera SSL sertifikāts ir uzticams, kā arī pārlūkā instalētie paplašinājumi nebloķē pieprasījumus.", "Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or enable unsafe scripts.": "Neizdodas savienoties ar bāzes serveri izmantojot HTTP protokolu, kad pārlūka adreses laukā norādīts HTTPS protokols. Tā vietā izmanto HTTPS vai iespējo nedrošos skriptus.", @@ -32,7 +32,7 @@ "%(senderDisplayName)s changed the room name to %(roomName)s.": "%(senderDisplayName)s nomainīja istabas nosaukumu uz %(roomName)s.", "%(senderDisplayName)s removed the room name.": "%(senderDisplayName)s dzēsa istabas nosaukumu.", "%(senderDisplayName)s changed the topic to \"%(topic)s\".": "%(senderDisplayName)s nomainīja istabas tematu uz \"%(topic)s\".", - "Changes your display nickname": "Nomaina jūsu parādāmo vārdu", + "Changes your display nickname": "Maina jūsu parādāmo vārdu", "Close": "Aizvērt", "Command error": "Komandas kļūda", "Commands": "Komandas", @@ -47,7 +47,7 @@ "Decrypt %(text)s": "Atšifrēt %(text)s", "Deops user with given id": "Atceļ operatora statusu lietotājam ar norādīto Id", "Default": "Noklusējuma", - "Disinvite": "Atsaukt", + "Disinvite": "Atsaukt uzaicinājumu", "Displays action": "Parāda darbību", "Download %(text)s": "Lejupielādēt: %(text)s", "Email": "Epasts", @@ -75,12 +75,12 @@ "Failed to set display name": "Neizdevās iestatīt parādāmo vārdu", "Failed to unban": "Neizdevās atbanot/atbloķēt (atcelt pieejas liegumu)", "Failed to upload profile picture!": "Neizdevās augšupielādēt profila attēlu!", - "Failed to verify email address: make sure you clicked the link in the email": "Neizdevās apstiprināt epasta adresi. Pārbaudi, vai Tu esi noklikšķinājis/usi saiti epasta ziņā", + "Failed to verify email address: make sure you clicked the link in the email": "Neizdevās apstiprināt epasta adresi. Pārbaudi, vai esat noklikšķinājis/usi saiti epasta ziņā", "Failure to create room": "Neizdevās izveidot istabu", "Favourite": "Izlase", "Favourites": "Izlase", - "Filter room members": "Filtrēt istabas biedrus", - "Forget room": "\"Aizmirst\" istabu", + "Filter room members": "Atfiltrēt istabas dalībniekus", + "Forget room": "Aizmirst istabu", "For security, this session has been signed out. Please sign in again.": "Drošības nolūkos šī sesija ir pārtraukta. Lūdzu, pieraksties par jaunu.", "%(userId)s from %(fromPowerLevel)s to %(toPowerLevel)s": "%(userId)s no %(fromPowerLevel)s uz %(toPowerLevel)s", "Hangup": "Beigt zvanu", @@ -107,9 +107,9 @@ "Leave room": "Pamest istabu", "Logout": "Izrakstīties", "Low priority": "Zema prioritāte", - "%(senderName)s made future room history visible to all room members, from the point they are invited.": "%(senderName)s padarīja istabas ziņu turpmāko vēsturi redzamu visiem istabas biedriem no brīža, kad tie tika uzaicināti.", - "%(senderName)s made future room history visible to all room members, from the point they joined.": "%(senderName)s padarīja istabas ziņu turpmāko vēsturi redzamu visiem istabas biedriem ar brīdi, kad tie pievienojās.", - "%(senderName)s made future room history visible to all room members.": "%(senderName)s padarīja istabas ziņu turpmāko vēsturi redzamu visiem istabas biedriem.", + "%(senderName)s made future room history visible to all room members, from the point they are invited.": "%(senderName)s padarīja istabas ziņu turpmāko vēsturi redzamu visiem istabas dalībniekiem no brīža, kad tie tika uzaicināti.", + "%(senderName)s made future room history visible to all room members, from the point they joined.": "%(senderName)s padarīja istabas ziņu turpmāko vēsturi redzamu visiem istabas dalībniekiem ar brīdi, kad tie pievienojās.", + "%(senderName)s made future room history visible to all room members.": "%(senderName)s padarīja istabas ziņu turpmāko vēsturi redzamu visiem istabas dalībniekiem.", "%(senderName)s made future room history visible to anyone.": "%(senderName)s padarīja istabas ziņu turpmāko vēsturi redzamu ikvienam.", "%(senderName)s made future room history visible to unknown (%(visibility)s).": "%(senderName)s padarīja istabas ziņu turpmāko vēsturi redzamu nepazīstamajiem (%(visibility)s).", "Missing room_id in request": "Iztrūkstošs room_id pieprasījumā", @@ -193,7 +193,7 @@ "This phone number is already in use": "Šis telefona numurs jau tiek izmantots", "This room": "Šajā istabā", "This room is not accessible by remote Matrix servers": "Šī istaba nav pieejama no citiem Matrix serveriem", - "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Notika mēģinājums ielādēt šīs istabas specifisku laikpaziņojumu sadaļu, bet Tev nav atļaujas skatīt šo ziņu.", + "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Notika mēģinājums specifisku posmu šīs istabas laika skalā, bet jums nav atļaujas skatīt konkrēto ziņu.", "Tried to load a specific point in this room's timeline, but was unable to find it.": "Mēģinājums ielādēt šīs istabas čata vēstures izvēlēto posmu neizdevās, jo tas netika atrasts.", "Unable to add email address": "Neizdevās pievienot epasta adresi", "Unable to remove contact information": "Neizdevās dzēst kontaktinformāciju", @@ -206,7 +206,7 @@ "Create new room": "Izveidot jaunu istabu", "Dismiss": "Aizvērt/atcelt", "You have enabled URL previews by default.": "URL priekšskatījumi pēc noklusējuma jums iriespējoti .", - "Upload avatar": "Augšupielādēt avataru (profila attēlu)", + "Upload avatar": "Augšupielādēt avataru", "Upload Failed": "Augšupielāde (nosūtīšana) neizdevās", "Upload file": "Augšupielādēt failu", "Upload new:": "Augšupielādēt jaunu:", @@ -312,7 +312,7 @@ "Create": "Izveidot", "Featured Rooms:": "Ieteiktās istabas:", "Featured Users:": "Ieteiktie lietotāji:", - "Automatically replace plain text Emoji": "Automātiski aizvietot tekstu ar emocīšiem (emoji)", + "Automatically replace plain text Emoji": "Automātiski aizstāt vienkāršā teksta emocijzīmes", "Failed to upload image": "Neizdevās augšupielādēt attēlu", "%(widgetName)s widget added by %(senderName)s": "%(senderName)s pievienoja %(widgetName)s vidžetu", "%(widgetName)s widget removed by %(senderName)s": "%(senderName)s dzēsa vidžetu %(widgetName)s", @@ -322,7 +322,7 @@ "Send": "Sūtīt", "Leave": "Pamest", "Unnamed room": "Nenosaukta istaba", - "Guests can join": "Var pievienoties viesi", + "Guests can join": "Viesi var pievienoties", "The platform you're on": "Izmantotā operētājsistēma", "The version of %(brand)s": "%(brand)s versija", "Your language of choice": "Izvēlētā valoda", @@ -335,10 +335,10 @@ "%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s": "%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s", "Who would you like to add to this community?": "Kurus cilvēkus Tu vēlētos pievienot šai kopienai?", "Warning: any person you add to a community will be publicly visible to anyone who knows the community ID": "Brīdinājums: ikviens, kurš tiek pievienots kopienai būs publiski redzams visiem, kuri zin kopienas Id", - "Invite new community members": "Uzaicināt jaunus kopienas biedrus", + "Invite new community members": "Uzaicināt jaunus kopienas dalībniekus", "Invite to Community": "Uzaicināt kopienā", "Which rooms would you like to add to this community?": "Kuras istabas vēlies pievienot šai kopienai?", - "Show these rooms to non-members on the community page and room list?": "Vai ne-biedriem rādīt kopienas lapā un istabu sarakstā šīs istabas?", + "Show these rooms to non-members on the community page and room list?": "Vai rādīt šis istabas kopienas lapā un istabu sarakstā tiem, kas nav dalībnieki?", "Add rooms to the community": "Pievienot istabas kopienai", "Add to community": "Pievienot kopienai", "Failed to invite the following users to %(groupId)s:": "Neizdevās uzaicināt sekojošus lietotājus grupā %(groupId)s:", @@ -384,10 +384,10 @@ "World readable": "Pieejama ikvienam un no visurienes", "Failed to remove tag %(tagName)s from room": "Neizdevās istabai noņemt birku %(tagName)s", "Failed to add tag %(tagName)s to room": "Neizdevās istabai pievienot birku %(tagName)s", - "Banned by %(displayName)s": "%(displayName)s liedzis piekļuvi", - "Members only (since the point in time of selecting this option)": "Tikai biedri (no šī parametra iestatīšanas brīža)", - "Members only (since they were invited)": "Tikai biedri (no to uzaicināšanas brīža)", - "Members only (since they joined)": "Tikai biedri (kopš pievienošanās)", + "Banned by %(displayName)s": "%(displayName)s liedzis pieeju", + "Members only (since the point in time of selecting this option)": "Tikai dalībnieki (no šī parametra iestatīšanas brīža)", + "Members only (since they were invited)": "Tikai dalībnieki (no to uzaicināšanas brīža)", + "Members only (since they joined)": "Tikai dalībnieki (kopš pievienošanās)", "Invalid community ID": "Nederīgs kopienas Id", "'%(groupId)s' is not a valid community ID": "'%(groupId)s' nav derīgs kopienas Id", "Flair": "Noskaņa", @@ -400,11 +400,11 @@ "Failed to copy": "Nokopēt neizdevās", "A text message has been sent to %(msisdn)s": "Teksta ziņa tika nosūtīta uz %(msisdn)s", "Remove from community": "Dzēst no kopienas", - "Disinvite this user from community?": "Atcelt šim lietotājam nosūtīto uzaicinājumu pievienoties kopienai?", + "Disinvite this user from community?": "Atsaukt šim lietotājam nosūtīto uzaicinājumu pievienoties kopienai?", "Remove this user from community?": "Izdzēst šo lietotāju no kopienas?", "Failed to withdraw invitation": "Neizdevās atcelt uzaicinājumu", "Failed to remove user from community": "Neizdevās izdzēst lietotāju no kopienas", - "Filter community members": "Kopienas biedru filtrs", + "Filter community members": "Kopienas dalībnieku filtrs", "Are you sure you want to remove '%(roomName)s' from %(groupId)s?": "Vai tiešām vēlaties dzēst '%(roomName)s' no %(groupId)s?", "Removing a room from the community will also remove it from the community page.": "Dzēšot istabu no kopienas tā tiks dzēsta arī no kopienas lapas.", "Failed to remove room from community": "Neizdevās dzēst istabu no kopienas", @@ -526,8 +526,8 @@ "Unable to reject invite": "Neizdevās noraidīt uzaicinājumu", "Leave %(groupName)s?": "Pamest %(groupName)s?", "%(inviter)s has invited you to join this community": "%(inviter)s uzaicināja jūs pievienoties šai kopienai", - "You are an administrator of this community": "Tu esi šīs kopienas administrators", - "You are a member of this community": "Tu esi šīs kopienas biedrs", + "You are an administrator of this community": "Jūs esat šīs kopienas administrators", + "You are a member of this community": "Jūs esat šīs kopienas dalībnieks", "Long Description (HTML)": "Garais apraksts (HTML)", "Community %(groupId)s not found": "Kopiena %(groupId)s nav atrasta", "Your Communities": "Jūsu kopienas", @@ -546,7 +546,7 @@ "Update": "Atjaunināt", "What's New": "Kas jauns", "On": "Ieslēgt", - "Changelog": "Izmaiņu saraksts (vēsture)", + "Changelog": "Izmaiņu vēsture", "Waiting for response from server": "Tiek gaidīta atbilde no servera", "Send Custom Event": "Sūtīt individuālu notikumu", "Failed to send logs: ": "Neizdevās nosūtīt logfailus: ", @@ -560,7 +560,7 @@ "Source URL": "Avota URL adrese", "Messages sent by bot": "Botu nosūtītās ziņas", "Filter results": "Filtrēt rezultātus", - "Members": "Biedri", + "Members": "Dalībnieki", "No update available.": "Nav atjauninājumu.", "Resend": "Nosūtīt atkārtoti", "Collecting app version information": "Tiek iegūta programmas versijas informācija", @@ -842,7 +842,7 @@ "Interactively verify by Emoji": "Abpusēji verificēt ar emocijzīmēm", "Manually Verify by Text": "Manuāli verificēt ar tekstu", "%(senderName)s revoked the invitation for %(targetDisplayName)s to join the room.": "%(senderName)s atsauca uzaicinājumu %(targetDisplayName)s pievienoties istabai.", - "%(senderName)s changed the addresses for this room.": "%(senderName)s izmainīja istabas adreses.", + "%(senderName)s changed the addresses for this room.": "%(senderName)s nomainīja istabas adreses.", "%(senderName)s removed the main address for this room.": "%(senderName)s dzēsa galveno adresi šai istabai.", "%(senderName)s set the main address for this room to %(address)s.": "%(senderName)s iestatīja istabas galveno adresi kā %(address)s.", "Afghanistan": "Afganistāna", @@ -920,7 +920,7 @@ "Phone numbers": "Tālruņa numuri", "Email Address": "Epasta adrese", "Email addresses": "Epasta adreses", - "Change topic": "Mainīt tematu", + "Change topic": "Nomainīt tematu", "Change room avatar": "Mainīt istabas avataru", "Change main address for the room": "Mainīt istabas galveno adresi", "%(senderName)s changed the main and alternative addresses for this room.": "%(senderName)s nomainīja istabas galveno un alternatīvo adresi.", @@ -932,7 +932,7 @@ "Invite users": "Uzaicināt lietotājus", "Send messages": "Sūtīt ziņas", "Default role": "Noklusējuma loma", - "Changes to who can read history will only apply to future messages in this room. The visibility of existing history will be unchanged.": "Izmaiņas attiecībā uz to, kas var lasīt vēsturi, attieksies tikai uz nākamajiem ziņojumiem šajā istabā. Esošās vēstures redzamība nemainīsies.", + "Changes to who can read history will only apply to future messages in this room. The visibility of existing history will be unchanged.": "Izmaiņas attiecībā uz to, kas var lasīt vēsturi, attieksies tikai uz nākamajiem ziņām šajā istabā. Esošās vēstures redzamība nemainīsies.", "Never send encrypted messages to unverified sessions in this room from this session": "Nesūtīt šifrētas ziņas no šīs sesijas neverificētām sesijām šajā istabā", "Encrypted": "Šifrēts", "Enable room encryption": "Iespējot istabas šifrēšanu", @@ -1053,7 +1053,7 @@ "Reject & Ignore user": "Noraidīt un ignorēt lietotāju", "Do you want to chat with %(user)s?": "Vai vēlaties sarakstīties ar %(user)s?", "This homeserver doesn't offer any login flows which are supported by this client.": "Šis bāzes serveris neatbalsta nevienu pierakstīšanās metodi, kuru atbalstītu šis klients.", - "Explore rooms": "Pārlūkot telpas", + "Explore rooms": "Pārlūkot istabas", "Confirm Security Phrase": "Apstipriniet slepeno frāzi", "Safeguard against losing access to encrypted messages & data by backing up encryption keys on your server.": "Nodrošinieties pret piekļuves zaudēšanu šifrētām ziņām un datiem, dublējot šifrēšanas atslēgas savā serverī.", "Use a secret phrase only you know, and optionally save a Security Key to use for backup.": "Izmantojiet tikai jums zināmu slepeno frāzi un pēc izvēles saglabājiet drošības atslēgu, lai to izmantotu dublēšanai.", @@ -1113,7 +1113,7 @@ "The homeserver may be unavailable or overloaded.": "Iespējams, bāzes serveris nav pieejams vai ir pārslogots.", "%(brand)s failed to get the public room list.": "%(brand)s neizdevās iegūt publisko istabu sarakstu.", "%(brand)s failed to get the protocol list from the homeserver. The homeserver may be too old to support third party networks.": "%(brand)s neizdevās iegūt protokolu sarakstu no bāzes servera. Iespējams, bāzes serveris ir pārāk vecs, lai atbalstītu trešo pušu tīklus.", - "Add a photo so people know it's you.": "Pievienot foto, lai cilvēki zina, ka tas esi tu.", + "Add a photo so people know it's you.": "Pievienot foto, lai cilvēki zina, ka tas esat jūs.", "Great, that'll help people know it's you": "Lieliski, tas ļaus cilvēkiem tevi atpazīt", "This homeserver does not support communities": "Šis bāzes serveris neatbalsta kopienas", "Everyone": "Jebkurš", @@ -1148,7 +1148,7 @@ "Bulk options": "Lielapjoma opcijas", "Clear cache and reload": "Notīrīt kešatmiņu un pārlādēt", "Versions": "Versijas", - "Keyboard Shortcuts": "Klaviatūras saīsnes", + "Keyboard Shortcuts": "Īsinājumtaustiņi", "FAQ": "BUJ", "For help with using %(brand)s, click here.": "Palīdzībai %(brand)s izmantošanā, spiediet šeit.", "Account management": "Konta pārvaldība", @@ -1388,38 +1388,38 @@ "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.": "Jūs varat ierakstīties, taču dažas funkcijas nebūs pieejamas, kamēr nebūs pieejams identitāšu serveris. Ja arī turpmāk redzat šo brīdinājumu, lūdzu, pārbaudiet konfigurāciju vai sazinieties ar servera administratoru.", "Cannot reach identity server": "Neizdodas sasniegt identitāšu serveri", "Ask your %(brand)s admin to check your config for incorrect or duplicate entries.": "Paprasiet %(brand)s administratoram pārbaudīt, vai jūsu konfigurācijas failā nav nepareizu vai dublējošos ierakstu.", - "See %(msgtype)s messages posted to your active room": "Redzēt jūsu aktīvajā telpā izliktās %(msgtype)s ziņas", - "See %(msgtype)s messages posted to this room": "Redzēt šajā telpā izliktās %(msgtype)s ziņas", + "See %(msgtype)s messages posted to your active room": "Apskatīt %(msgtype)s ziņas, kas publicētas jūsu aktīvajā istabā", + "See %(msgtype)s messages posted to this room": "Apskatīt %(msgtype)s ziņas, kas publicētas šajā istabā", "Send %(msgtype)s messages as you in your active room": "Sūtīt %(msgtype)s ziņas savā vārdā savā aktīvajā telpā", "Send %(msgtype)s messages as you in this room": "Sūtīt %(msgtype)s ziņas savā vārdā šajā telpā", "See general files posted to your active room": "Redzēt jūsu aktīvajā telpā izliktos failus", "See general files posted to this room": "Redzēt šajā telpā izliktos failus", - "Send general files as you in your active room": "Sūtīt failus savā vārdā jūsu aktīvajā telpā", - "Send general files as you in this room": "Sūtīt failus savā vārdā šajā telpā", + "Send general files as you in your active room": "Sūtīt failus savā vārdā jūsu aktīvajā istabā", + "Send general files as you in this room": "Sūtīt failus savā vārdā šajā istabā", "See videos posted to your active room": "Redzēt video, kuri izlikti jūsu aktīvajā telpā", "See videos posted to this room": "Redzēt video, kuri izlikti šajā telpā", - "Send videos as you in your active room": "Sūtīt video savā vārdā savā aktīvajā telpā", - "Send videos as you in this room": "Sūtīt video savā vārdā šajā telpā", + "Send videos as you in your active room": "Sūtīt video savā vārdā savā aktīvajā istabā", + "Send videos as you in this room": "Sūtīt video savā vārdā šajā istabā", "See images posted to your active room": "Redzēt attēlus, kuri izlikti jūsu aktīvajā telpā", "See images posted to this room": "Redzēt attēlus, kuri izlikti šajā telpā", - "Send images as you in your active room": "Sūtīt attēlus savā vārdā savā aktīvajā telpā", - "Send images as you in this room": "Sūtīt attēlus savā vārdā šajā telpā", + "Send images as you in your active room": "Sūtīt attēlus savā vārdā savā aktīvajā istabā", + "Send images as you in this room": "Sūtīt attēlus savā vārdā šajā istabā", "See emotes posted to your active room": "Redzēt emocijas, kuras izvietotas jūsu aktīvajā telpā", "See emotes posted to this room": "Redzēt emocijas, kuras izvietotas šajā telpā", - "Send emotes as you in your active room": "Nosūtīt emocijas savā vārdā uz savu aktīvo telpu", - "Send emotes as you in this room": "Nosūtīt emocijas savā vārdā uz šo telpu", + "Send emotes as you in your active room": "Nosūtīt emocijas savā vārdā uz savu aktīvo istabu", + "Send emotes as you in this room": "Nosūtīt emocijas savā vārdā uz šo istabu", "See text messages posted to your active room": "Redzēt teksta ziņas, kuras izvietotas jūsu aktīvajā telpā", "See text messages posted to this room": "Redzēt teksta ziņas, kas izvietotas šajā telpā", - "Send text messages as you in your active room": "Sūtīt teksta ziņas savā vārdā jūsu aktīvajā telpā", - "Send text messages as you in this room": "Sūtīt teksta ziņas savā vārdā šajā telpā", + "Send text messages as you in your active room": "Sūtīt teksta ziņas savā vārdā jūsu aktīvajā istabā", + "Send text messages as you in this room": "Sūtīt teksta ziņas savā vārdā šajā istabā", "See messages posted to your active room": "Redzēt ziņas, kas izvietotas jūsu aktīvajā telpā", "See messages posted to this room": "Redzēt ziņas, kas izvietotas šajā telpā", - "Send messages as you in your active room": "Sūtiet ziņas savā vārdā jūsu aktīvajā telpā", - "Send messages as you in this room": "Sūtīt ziņas savā vārdā šajā telpā", + "Send messages as you in your active room": "Sūtiet ziņas savā vārdā jūsu aktīvajā istabā", + "Send messages as you in this room": "Sūtīt ziņas savā vārdā šajā istabā", "The %(capability)s capability": "%(capability)s iespējas", - "See %(eventType)s events posted to your active room": "Redzēt, kad %(eventType)s notikumi izvietoti jūsu aktīvajā telpā", + "See %(eventType)s events posted to your active room": "Apskatīt %(eventType)s notikumus jūsu aktīvajā istabā", "Send %(eventType)s events as you in your active room": "Sūtīt %(eventType)s notikumus savā vārdā savā aktīvajā telpā", - "See %(eventType)s events posted to this room": "Redzēt %(eventType)s notikumus, kas izvietoti šajā telpā", + "See %(eventType)s events posted to this room": "Apskatīt %(eventType)s notikumus šajā istabā", "Send %(eventType)s events as you in this room": "Sūtiet %(eventType)s notikumus jūsu vārdā šajā telpā", "with state key %(stateKey)s": "ar stāvokļa/statusa atslēgu %(stateKey)s", "with an empty state key": "ar tukšu stāvokļa/statusa atslēgu", @@ -1428,23 +1428,23 @@ "See when a sticker is posted in this room": "Redzēt, kad šajā telpā parādās stikers", "Send stickers to this room as you": "Nosūtīt stikerus savā vārdā uz šo telpu", "See when people join, leave, or are invited to your active room": "Redzēt, kad cilvēki ienāk/pievienojas, pamet/atvienojas vai ir uzaicināti uz jūsu aktīvo telpu", - "Kick, ban, or invite people to this room, and make you leave": "Izspert, liegt vai uzaicināt cilvēkus uz šo telpu un likt jums aiziet", - "Kick, ban, or invite people to your active room, and make you leave": "Izspert, liegt vai uzaicināt cilvēkus uz jūsu aktīvo telpu un likt jums aiziet", + "Kick, ban, or invite people to this room, and make you leave": "Padzīt, liegt pieeju vai uzaicināt cilvēkus uz šo istabu un likt jums aiziet", + "Kick, ban, or invite people to your active room, and make you leave": "Padzīt, liegt pieeju vai uzaicināt cilvēkus uz jūsu aktīvo istabu un likt jums aiziet", "See when people join, leave, or are invited to this room": "Redzēt, kad cilvēki ienāk/pievienojas, pamet/atvienojas vai ir uzaicināti uz šo telpu", "See when the avatar changes in your active room": "Redzēt, kad notiek jūsu aktīvās istabas avatara izmaiņas", - "Change the avatar of your active room": "Mainīt jūsu aktīvās telpas avataru", + "Change the avatar of your active room": "Nomainīt jūsu aktīvās istabas avataru", "See when the avatar changes in this room": "Redzēt, kad notiek šīs istabas avatara izmaiņas", - "Change the avatar of this room": "Mainīt šīs istabas avataru", + "Change the avatar of this room": "Nomainīt šīs istabas avataru", "See when the name changes in your active room": "Redzēt, kad notiek aktīvās telpas nosaukuma izmaiņas", - "Change the name of your active room": "Mainīt jūsu aktīvās telpas nosaukumu", + "Change the name of your active room": "Nomainīt jūsu aktīvās istabas nosaukumu", "See when the name changes in this room": "Redzēt, kad mainās šīs telpas nosaukums", - "Change the name of this room": "Mainīt šīs telpas nosaukumu", + "Change the name of this room": "Nomainīt šīs istabas nosaukumu", "See when the topic changes in this room": "Redzēt, kad mainās šīs telpas temats", "See when the topic changes in your active room": "Redzēt, kad mainās pašreizējā tērziņa temats", "Change the topic of your active room": "Nomainīt jūsu aktīvās istabas tematu", - "Change the topic of this room": "Nomainīt šīs telpas tematu", - "Change which room, message, or user you're viewing": "Nomainīt telpu, ziņu vai lietotāju, kurš ir fokusā (kuru jūs skatiet)", - "Change which room you're viewing": "Nomainīt telpu, kuru jūs skatiet", + "Change the topic of this room": "Nomainīt šīs istabas tematu", + "Change which room, message, or user you're viewing": "Nomainīt istabu, ziņu vai lietotāju, kuru jūs skatiet", + "Change which room you're viewing": "Nomainīt istabu, kuru jūs skatiet", "Send stickers into your active room": "Iesūtīt stikerus jūsu aktīvajā telpā", "Send stickers into this room": "Šajā telpā iesūtīt stikerus", "Remain on your screen while running": "Darbības laikā paliek uz ekrāna", @@ -1452,21 +1452,21 @@ "Dark": "Tumša", "Light": "Gaiša", "%(senderName)s updated a ban rule that was matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s pārjaunoja lieguma noteikumu šablonu %(oldGlob)s uz šablonu %(newGlob)s dēļ %(reason)s", - "%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s aizstāja noteikumu, kas piekļuvi liedza serveriem, kas atbilst pazīmei %(oldGlob)s, ar atbilstošu pazīmei %(newGlob)s dēļ %(reason)s", - "%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s aizstāja noteikumu, kurš liedza %(oldGlob)s pazīmei atbilstošas telpas ar jaunu noteikumu, kurš liedz %(newGlob)s dēļ %(reason)s", - "%(senderName)s changed a rule that was banning users matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s aizstāja noteikumu, kurš aizliedza lietotājus %(oldGlob)s ar jaunu noteikumu, kurš aizliedz %(newGlob)s dēļ %(reason)s", + "%(senderName)s changed a rule that was banning servers matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s aizstāja noteikumu, kas liedza pieeju serveriem, kas atbilst pazīmei %(oldGlob)s, ar atbilstošu pazīmei %(newGlob)s dēļ %(reason)s", + "%(senderName)s changed a rule that was banning rooms matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s izmainīja noteikumu, kurš liedz pieeju istabām, kas atbilst %(oldGlob)s pazīmei pret %(newGlob)s dēļ %(reason)s", + "%(senderName)s changed a rule that was banning users matching %(oldGlob)s to matching %(newGlob)s for %(reason)s": "%(senderName)s aizstāja noteikumu, kurš liedza pieeju lietotājiem %(oldGlob)s ar jaunu noteikumu, kurš aizliedz %(newGlob)s dēļ %(reason)s", "%(senderName)s has updated the widget layout": "%(senderName)s ir aktualizējis vidžeta/logrīka izkārtojumu", - "%(senderName)s changed the pinned messages for the room.": "%(senderName)s mainīja telpas piekabinātās ziņas.", - "%(senderDisplayName)s upgraded this room.": "%(senderDisplayName)s modernizēja šo telpu.", - "%(senderName)s kicked %(targetName)s": "%(senderName)s izspēra %(targetName)s", - "%(senderName)s kicked %(targetName)s: %(reason)s": "%(senderName)s izspēra %(targetName)s: %(reason)s", + "%(senderName)s changed the pinned messages for the room.": "%(senderName)s nomainīja piespraustās ziņas šai istabai.", + "%(senderDisplayName)s upgraded this room.": "%(senderDisplayName)s atjaunināja šo istabu.", + "%(senderName)s kicked %(targetName)s": "%(senderName)s padzina %(targetName)s", + "%(senderName)s kicked %(targetName)s: %(reason)s": "%(senderName)s padzina %(targetName)s: %(reason)s", "%(senderName)s withdrew %(targetName)s's invitation": "%(senderName)s atsauca %(targetName)s paredzēto uzaicinājumu", "%(senderName)s withdrew %(targetName)s's invitation: %(reason)s": "%(senderName)s atsauca %(targetName)s paredzēto uzaicinājumu: %(reason)s", "%(senderName)s unbanned %(targetName)s": "%(senderName)s noņēma liegumu/atbanoja %(targetName)s", - "%(targetName)s left the room": "%(targetName)s pameta/atvienojās no telpas", - "%(targetName)s left the room: %(reason)s": "%(targetName)s pameta/atvienojās no telpas: %(reason)s", + "%(targetName)s left the room": "%(targetName)s pameta istabu", + "%(targetName)s left the room: %(reason)s": "%(targetName)s pameta istabu: %(reason)s", "%(targetName)s rejected the invitation": "%(targetName)s noraidīja uzaicinājumu", - "%(targetName)s joined the room": "%(targetName)s ienāca (pievienojās) telpā", + "%(targetName)s joined the room": "%(targetName)s pievienojās istabai", "%(senderName)s made no change": "%(senderName)s neizdarīja izmaiņas", "%(senderName)s set a profile picture": "%(senderName)s iestatīja profila attēlu", "%(senderName)s changed their profile picture": "%(senderName)s nomainīja savu profila attēlu", @@ -1474,13 +1474,13 @@ "%(senderName)s removed their display name (%(oldDisplayName)s)": "%(senderName)s dzēsa savu redzamo vārdu (%(oldDisplayName)s)", "%(senderName)s set their display name to %(displayName)s": "%(senderName)s iestatīja %(displayName)s kā savu redzamo vārdu", "%(oldDisplayName)s changed their display name to %(displayName)s": "%(oldDisplayName)s nomainīja savu redzamo vārdu uz %(displayName)s", - "%(senderName)s banned %(targetName)s": "%(senderName)s aizliedza/nobanoja %(targetName)s", - "%(senderName)s banned %(targetName)s: %(reason)s": "%(senderName)s aizliedza/nobanoja %(targetName)s: %(reason)s", + "%(senderName)s banned %(targetName)s": "%(senderName)s liedza pieeju %(targetName)s", + "%(senderName)s banned %(targetName)s: %(reason)s": "%(senderName)s liedza pieeju %(targetName)s: %(reason)s", "%(senderName)s invited %(targetName)s": "%(senderName)s uzaicināja %(targetName)s", "%(targetName)s accepted an invitation": "%(targetName)s pieņēma uzaicinājumu", "%(targetName)s accepted the invitation for %(displayName)s": "%(targetName)s pieņēma uzaicinājumu uz %(displayName)s", - "Converts the DM to a room": "Pārvērst DM par telpu", - "Converts the room to a DM": "Pārvērst telpu par DM", + "Converts the DM to a room": "Pārveido DM par istabu", + "Converts the room to a DM": "Pārveido istabu par DM", "Places the call in the current room on hold": "Iepauzē sarunu šajā telpā", "Takes the call in the current room off hold": "Šajā telpā iepauzētās sarunas atpauzēšana", "Sends a message to the given user": "Nosūtīt ziņu dotajam lietotājam", @@ -1490,28 +1490,28 @@ "Displays list of commands with usages and descriptions": "Parāda komandu sarakstu ar pielietojumiem un aprakstiem", "Sends the given emote coloured as a rainbow": "Nosūta šo emociju iekrāsotu varavīksnes krāsās", "Sends the given message coloured as a rainbow": "Nosūta šo ziņu iekrāsotu varavīksnes krāsās", - "Forces the current outbound group session in an encrypted room to be discarded": "Piespiedu kārtā atmet/izbeidz pašreizējo izejošo grupas sesiju šifrētajā telpā", + "Forces the current outbound group session in an encrypted room to be discarded": "Piespiedu kārtā pārtrauc pašreizējo izejošo grupas sesiju šifrētajā istabā", "The signing key you provided matches the signing key you received from %(userId)s's session %(deviceId)s. Session marked as verified.": "Jūsu iesniegtā parakstīšanas atslēga atbilst parakstīšanas atslēgai, kuru saņēmāt no %(userId)s sesijas %(deviceId)s. Sesija atzīmēta kā verificēta.", "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!": "BRĪDINĀJUMS: ATSLĒGU VERIFIKĀCIJA NEIZDEVĀS! Parakstīšanas atslēga lietotājam %(userId)s un sesijai %(deviceId)s ir \"%(fprint)s\", kura neatbilst norādītajai atslēgai \"%(fingerprint)s\". Tas var nozīmēt, ka jūsu saziņa tiek pārtverta!", "Verifies a user, session, and pubkey tuple": "Verificē lietotāju, sesiju un publiskās atslēgas", "WARNING: Session already verified, but keys do NOT MATCH!": "BRĪDINĀJUMS: Sesija jau ir verificēta, bet atslēgas NESAKRĪT!", "Unknown (user, session) pair:": "Nezināms (lietotājs, sesija) pāris:", - "You cannot modify widgets in this room.": "Jūs šajā telpā nevarat mainīt vidžetus/logrīkus.", + "You cannot modify widgets in this room.": "Jūs nevarat mainīt vidžetus/logrīkus šajā istabā.", "Please supply a https:// or http:// widget URL": "Lūdzu ievadiet logrīka URL https:// vai http:// formā", "Please supply a widget URL or embed code": "Ievadiet vidžeta/logrīka URL vai ievietojiet kodu", - "Adds a custom widget by URL to the room": "Pievieno telpai individuālu/pielāgotu logrīku/vidžetu ar URL-adresi", + "Adds a custom widget by URL to the room": "Pievieno istabai pielāgotu logrīku/vidžetu ar URL-adresi", "Command failed": "Neizdevās izpildīt komandu", - "Joins room with given address": "Pievienojas telpai ar šādu adresi", + "Joins room with given address": "Pievienojas istabai ar šādu adresi", "Use an identity server to invite by email. Manage in Settings.": "Izmantojiet identitātes serveri, lai uzaicinātu pa e-pastu. Pārvaldība pieejama Iestatījumos.", "Use an identity server to invite by email. Click continue to use the default identity server (%(defaultIdentityServerName)s) or manage in Settings.": "Izmantojiet identitātes serveri, lai uzaicinātu pa e-pastu. Noklikšķiniet uz Turpināt, lai izmantotu noklusējuma identitātes serveri (%(defaultIdentityServerName)s) vai nomainītu to Iestatījumos.", "Use an identity server": "Izmantot identitāšu serveri", - "Sets the room name": "Iestata telpas nosaukumu", - "Gets or sets the room topic": "Nolasa vai iestata telpas tematu", - "Changes your avatar in all rooms": "Maina jūsu avataru visām telpām", - "Changes your avatar in this current room only": "Maina jūsu avataru tikai šajā telpā", - "Changes the avatar of the current room": "Maina šīs telpas avataru", - "Changes your display nickname in the current room only": "Maina rādāmo pseidonīmu/segvārdu tikai šai telpai", - "Upgrades a room to a new version": "Modernizē telpu uz Jauno versiju", + "Sets the room name": "Iestata istabas nosaukumu", + "Gets or sets the room topic": "Nolasa vai iestata istabas tematu", + "Changes your avatar in all rooms": "Maina jūsu avataru visās istabās", + "Changes your avatar in this current room only": "Maina jūsu avataru tikai šajā istabā", + "Changes the avatar of the current room": "Maina šīs istabas avataru", + "Changes your display nickname in the current room only": "Maina jūsu parādāmo vārdu tikai šajā istabā", + "Upgrades a room to a new version": "Atjaunina istabu uz jaunu versiju", "Sends a message as html, without interpreting it as markdown": "Nosūta ziņu kā HTML, to neinterpretējot kā Markdown", "Sends a message as plain text, without interpreting it as markdown": "Nosūta ziņu kā vienkāršu tekstu, to neinterpretējot kā Markdown", "Prepends ( ͡° ͜ʖ ͡°) to a plain-text message": "Pievieno ( ͡° ͜ʖ ͡°) pirms vienkārša teksta ziņas", @@ -1783,17 +1783,141 @@ "The call could not be established": "Savienojums nevarēja tikt izveidots", "The user you called is busy.": "Lietotājs, kuram zvanāt, ir aizņemts.", "User Busy": "Lietotājs aizņemts", - "Your user agent": "Jūsu lietotāja-aģents", + "Your user agent": "Jūsu lietotāja aģents", "Whether you're using %(brand)s as an installed Progressive Web App": "Vai izmantojiet %(brand)s kā instalētu progresīvo tīmekļa lietotni", "Whether you're using %(brand)s on a device where touch is the primary input mechanism": "Vai izmantojat %(brand)s ierīcē, kurā skārnienjūtīgs ekrāns ir galvenais ievades mehānisms", - "This room is used for important messages from the Homeserver, so you cannot leave it.": "Šī telpa tiek izmantota svarīgiem ziņojumiem no bāzes servera, tāpēc jūs nevarat to atstāt.", - "Can't leave Server Notices room": "Nevar iziet no servera Paziņojumu telpas", - "Unexpected server error trying to leave the room": "Mēģinot atstāt telpu radās negaidīta servera kļūme", + "This room is used for important messages from the Homeserver, so you cannot leave it.": "Šī istaba tiek izmantota svarīgiem ziņojumiem no bāzes servera, tāpēc jūs nevarat to pamest.", + "Can't leave Server Notices room": "Nevar pamest Server Notices istabu", + "Unexpected server error trying to leave the room": "Mēģinot pamest istabu radās negaidīta servera kļūme", "Unable to connect to Homeserver. Retrying...": "Nevar izveidot savienojumu ar bāzes/mājas serveri. Mēģinam vēlreiz ...", "Please contact your service administrator to continue using the service.": "Lūdzu sazinieties ar savu administratoru, lai turpinātu izmantot pakalpojumu.", "This homeserver has exceeded one of its resource limits.": "Šis bāzes/mājas serveris ir pārsniedzis vienu no tā resursu ierobežojumiem.", "This homeserver has been blocked by its administrator.": "Šo bāzes/mājas serveri ir bloķējis tā administrators.", "This homeserver has hit its Monthly Active User limit.": "Šis bāzes/mājas serveris ir sasniedzis ikmēneša aktīvo lietotāju ierobežojumu.", "Unexpected error resolving identity server configuration": "Negaidīta kļūda identitātes servera konfigurācijā", - "Unexpected error resolving homeserver configuration": "Negaidīta kļūme mājas servera konfigurācijā" + "Unexpected error resolving homeserver configuration": "Negaidīta kļūme mājas servera konfigurācijā", + "Cancel All": "Atcelt visu", + "Reporting this message will send its unique 'event ID' to the administrator of your homeserver. If messages in this room are encrypted, your homeserver administrator will not be able to read the message text or view any files or images.": "Iesniedzot ziņojumu par konkrēto ziņu, tās unikālais notikuma ID tiks nosūtīts jūsu bāzes servera administratoram. Ja ziņas šajā istabā ir šifrētas, jūsu bāzes servera administrators nevarēs lasīt ziņas tekstu vai skatīt failus un attēlus.", + "Sending": "Sūta", + "Adding...": "Pievienošana…", + "Can't load this message": "Nevar ielādēt šo ziņu", + "Send voice message": "Sūtīt balss ziņu", + "Sending your message...": "Sūta jūsu ziņu…", + "Address": "Adrese", + "%(sharerName)s is presenting": "%(sharerName)s prezentē", + "Group & filter rooms by custom tags (refresh to apply changes)": "Grupēt un filtrēt istabas pēc pielāgotiem tagiem (atsvaidzināt, lai piemērotu izmaiņas)", + "Hey you. You're the best!": "Sveiks! Tu esi labākais!", + "Inviting...": "Uzaicina…", + "Share %(name)s": "Dalīties ar %(name)s", + "Try different words or check for typos. Some results may not be visible as they're private and you need an invite to join them.": "Izmēģiniet citus vārdus vai pārbaudiet drukas kļūdas. Daži rezultāti var nebūt redzami, jo tie ir privāti un ir nepieciešams uzaicinājums, lai pievienotos.", + "No results for \"%(query)s\"": "Meklējumam \"%(query)s\" nav rezultātu", + "Explore Public Rooms": "Pārlūkot publiskas istabas", + "Show preview": "Rādīt priekšskatījumu", + "View source": "Skatīt pirmkodu", + "Forward": "Pārsūtīt", + "Forgotten or lost all recovery methods? Reset all": "Aizmirsāt vai pazaudējāt visas atkopšanās iespējas? Atiestatiet visu", + "Share Community": "Dalīties ar kopienu", + "Link to most recent message": "Saite uz jaunāko ziņu", + "Share Room": "Dalīties ar istabu", + "Report Content to Your Homeserver Administrator": "Ziņojums par saturu bāzes servera administratoram", + "Send report": "Nosūtīt ziņojumu", + "Report the entire room": "Ziņot par visu istabu", + "Leave all rooms": "Pamest visas istabas", + "Invited people will be able to read old messages.": "Uzaicinātie cilvēki varēs lasīt vecās ziņas.", + "Or send invite link": "Vai nosūtiet uzaicinājuma saiti", + "If you can't see who you’re looking for, send them your invite link below.": "Ja neredzat meklēto, nosūtiet savu uzaicinājuma saiti zemāk.", + "Some suggestions may be hidden for privacy.": "Daži ieteikumi var būt slēpti dēļ privātuma.", + "Search for rooms or people": "Meklēt istabas vai cilvēkus", + "Message preview": "Ziņas priekšskatījums", + "Forward message": "Pārsūtīt ziņu", + "Public room": "Publiska istaba", + "Private room (invite only)": "Privāta istaba (tikai ar ielūgumiem)", + "Only people invited will be able to find and join this room.": "Tikai uzaicinātās cilvēki varēs atrast un pievienoties šai istabai.", + "Anyone will be able to find and join this room.": "Ikviens varēs atrast un pievienoties šai istabai.", + "You can change this at any time from room settings.": "Jūs to varat mainīt istabas iestatījumos jebkurā laikā.", + "Private rooms can be found and joined by invitation only. Public rooms can be found and joined by anyone in this community.": "Privātas istabas var atrast un tām pievienoties tikai pēc uzaicinājuma. Publiskas istabas atrast un tām pievienoties var ikviens no šis kopienas.", + "Show": "Rādīt", + "Search for rooms": "Meklēt istabas", + "Server name": "Servera nosaukums", + "Enter the name of a new server you want to explore.": "Ievadiet nosaukumu jaunam serverim, kuru vēlaties pārlūkot.", + "%(severalUsers)schanged the pinned messages for the room %(count)s times.|other": "%(severalUsers)smainīja piespraustās ziņas istabā %(count)s reizes.", + "Zoom in": "Pietuvināt", + "Zoom out": "Attālināt", + "Join": "Pievienoties", + "Share content": "Dalīties ar saturu", + "Your theme": "Jūsu tēma", + "Your user ID": "Jūsu lietotāja ID", + "Show all": "Rādīt visu", + "Show image": "Rādīt attēlu", + "Call back": "Atzvanīt", + "Call declined": "Zvans noraidīts", + "Copy Room Link": "Kopēt istabas saiti", + "Invite People": "Uzaicināt cilvēkus", + "Forget Room": "Aizmirst istabu", + "Join the discussion": "Pievienoties diskusijai", + "Forget this room": "Aizmirst šo istabu", + "Joining room …": "Pievienošanās istabai…", + "Explore %(spaceName)s": "Pālūkot %(spaceName)s", + "Explore public rooms": "Pārlūkot publiskas istabas", + "Explore community rooms": "Pārlūkot kopienas istabas", + "Enable encryption in settings.": "Iespējot šifrēšanu iestatījumos.", + "%(seconds)ss left": "%(seconds)s sekundes atlikušas", + "Show %(count)s other previews|one": "Rādīt %(count)s citu priekšskatījumu", + "Show %(count)s other previews|other": "Rādīt %(count)s citus priekšskatījumus", + "Share": "Dalīties", + "Access": "Piekļuve", + "People with supported clients will be able to join the room without having a registered account.": "Cilvēki ar atbalstītām lietotnēm varēs pievienoties istabai bez reģistrēta konta.", + "Decide who can join %(roomName)s.": "Nosakiet, kas var pievienoties %(roomName)s.", + "Select the roles required to change various parts of the room": "Izvēlieties lomas, kas nepieciešamas, lai mainītu dažādus istabas parametrus", + "Timeline": "Laika skala", + "Code blocks": "Koda bloki", + "Displaying time": "Laika attēlošana", + "To view all keyboard shortcuts, click here.": "Lai apskatītu visus īsinājumtaustiņus, noklikšķiniet šeit.", + "Keyboard shortcuts": "Īsinājumtaustiņi", + "Theme": "Tēma", + "Custom theme URL": "Pielāgotas tēmas URL", + "Theme added!": "Tēma pievienota!", + "Enter a new identity server": "Ievadiet jaunu identitāšu serveri", + "Mentions & keywords": "Pieminēšana un atslēgvārdi", + "New keyword": "Jauns atslēgvārds", + "Keyword": "Atslēgvārds", + "Enable for this account": "Iespējot šim kontam", + "Messages containing keywords": "Ziņas, kas satur atslēgvārdus", + "Anyone can find and join.": "Ikviens var atrast un pievienoties.", + "Only invited people can join.": "Tikai uzaicināti cilvēki var pievienoties.", + "Private (invite only)": "Privāta (tikai ar ielūgumiem)", + "Expand": "Izvērst", + "Decide who can view and join %(spaceName)s.": "Nosakiet, kas var skatīt un pievienoties %(spaceName)s.", + "Enable guest access": "Iespējot piekļuvi viesiem", + "Invite people": "Uzaicināt cilvēkus", + "Show all rooms": "Rādīt visas istabas", + "Creating...": "Izveidošana…", + "Public": "Publiska", + "Corn": "Kukurūza", + "Show previews/thumbnails for images": "Rādīt attēlu priekšskatījumus/sīktēlus", + "Show hidden events in timeline": "Rādīt slēptos notikumus laika skalā", + "Show developer tools": "Rādīt izstrādātāja rīkus", + "Match system theme": "Pielāgoties sistēmas tēmai", + "Surround selected text when typing special characters": "Iekļaut iezīmēto tekstu, rakstot speciālās rakstzīmes", + "Use Ctrl + Enter to send a message": "Lietot Ctrl + Enter ziņas nosūtīšanai", + "Use Command + Enter to send a message": "Lietot Command + Enter ziņas nosūtīšanai", + "Use Ctrl + F to search timeline": "Lietot Ctrl + F meklēšanai laika skalā", + "Use Command + F to search timeline": "Lietot Command + F meklēšanai laika skalā", + "Enable big emoji in chat": "Iespējot lielas emocijzīmes čatā", + "Jump to the bottom of the timeline when you send a message": "Nosūtot ziņu, pāriet uz laika skalas beigām", + "Show line numbers in code blocks": "Rādīt rindu numurus koda blokos", + "Expand code blocks by default": "Izvērst koda blokus pēc noklusējuma", + "Autoplay videos": "Automātski atskaņot videoklipus", + "Autoplay GIFs": "Automātiski atskaņot GIF", + "Show read receipts sent by other users": "Rādīt izlasīšanas apliecinājumus no citiem lietotājiem", + "Show a placeholder for removed messages": "Rādīt dzēstu ziņu vietturus", + "Use custom size": "Izmantot pielāgotu izmēru", + "Font size": "Šrifta izmērs", + "Call ended": "Zvans beidzās", + "Guest": "Viesis", + "Dates are often easy to guess": "Datumi bieži vien ir viegli uzminami", + "%(senderName)s unpinned a message from this room. See all pinned messages.": "%(senderName)s noņēma piespraustu ziņu šajā istabā. Skatīt visas piespraustās ziņas.", + "%(senderName)s unpinned a message from this room. See all pinned messages.": "%(senderName)s noņēma piespraustu ziņu šajā istabā. Skatīt visas piespraustās ziņas.", + "%(senderName)s pinned a message to this room. See all pinned messages.": "%(senderName)s piesprauda ziņu šajā istabā. Skatīt visas piespraustās ziņas.", + "%(senderName)s pinned a message to this room. See all pinned messages.": "%(senderName)s piesprauda ziņu šajā istabā. Skatīt visas piespraustās ziņas." } From 9c8f98172bf7c8d8fb74cd0f31dc3c566f068a1d Mon Sep 17 00:00:00 2001 From: random Date: Mon, 27 Sep 2021 10:19:58 +0000 Subject: [PATCH 023/143] Translated using Weblate (Italian) Currently translated at 99.9% (3165 of 3166 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 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/i18n/strings/it.json b/src/i18n/strings/it.json index 6792e62c9f..022149e3c6 100644 --- a/src/i18n/strings/it.json +++ b/src/i18n/strings/it.json @@ -1218,14 +1218,14 @@ "Do not use an identity server": "Non usare un server di identità", "You do not have the required permissions to use this command.": "Non hai l'autorizzazione necessaria per usare questo comando.", "Use an identity server": "Usa un server di identità", - "Use an identity server to invite by email. Click continue to use the default identity server (%(defaultIdentityServerName)s) or manage in Settings.": "Usa un server di identità per invitare via email. Clicca \"Continua\" per usare quello predefinito (%(defaultIdentityServerName)s) o gestiscilo nelle impostazioni.", + "Use an identity server to invite by email. Click continue to use the default identity server (%(defaultIdentityServerName)s) or manage in Settings.": "Usa un server d'identità per invitare via email. Clicca \"Continua\" per usare quello predefinito (%(defaultIdentityServerName)s) o gestiscilo nelle impostazioni.", "Use an identity server to invite by email. Manage in Settings.": "Usa un server di identità per invitare via email. Gestisci nelle impostazioni.", "Upgrade the room": "Aggiorna la stanza", "Enable room encryption": "Attiva la crittografia della stanza", "Deactivate user?": "Disattivare l'utente?", "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?": "Disattivare questo utente lo disconnetterà e ne impedirà nuovi accessi. In aggiunta, abbandonerà tutte le stanze in cui è presente. Questa azione non può essere annullata. Sei sicuro di volere disattivare questo utente?", "Deactivate user": "Disattiva utente", - "Use an identity server to invite by email. Use the default (%(defaultIdentityServerName)s) or manage in Settings.": "Usa un server di identità per invitare via email. Usa quello predefinito (%(defaultIdentityServerName)s) o gestiscilo nelle impostazioni.", + "Use an identity server to invite by email. Use the default (%(defaultIdentityServerName)s) or manage in Settings.": "Usa un server d'identità per invitare via email. Usa quello predefinito (%(defaultIdentityServerName)s) o gestiscilo nelle impostazioni.", "Use an identity server to invite by email. Manage in Settings.": "Usa un server di identità per invitare via email. Gestisci nelle impostazioni.", "Sends a message as plain text, without interpreting it as markdown": "Invia un messaggio in testo semplice, senza interpretarlo come markdown", "Error changing power level": "Errore cambiando il livello di poteri", @@ -1236,11 +1236,11 @@ "This invite to %(roomName)s was sent to %(email)s": "Questo invito per %(roomName)s è stato inviato a %(email)s", "Use an identity server in Settings to receive invites directly in %(brand)s.": "Usa un server di identià nelle impostazioni per ricevere inviti direttamente in %(brand)s.", "Share this email in Settings to receive invites directly in %(brand)s.": "Condividi questa email nelle impostazioni per ricevere inviti direttamente in %(brand)s.", - "Change identity server": "Cambia Identity Server", - "Disconnect from the identity server and connect to instead?": "Disconnettersi dall'Identity Server e connettesi invece a ?", - "Disconnect identity server": "Disconnetti dall'Identity Server", - "You are still sharing your personal data on the identity server .": "Stai ancora fornendo le tue informazioni personali sull'Identity Server .", - "We recommend that you remove your email addresses and phone numbers from the identity server before disconnecting.": "Ti suggeriamo di rimuovere il tuo indirizzo email e numero di telefono dall'Identity Server prima di disconnetterti.", + "Change identity server": "Cambia server d'identità", + "Disconnect from the identity server and connect to instead?": "Disconnettersi dal server d'identità e connettesi invece a ?", + "Disconnect identity server": "Disconnetti dal server d'identità", + "You are still sharing your personal data on the identity server .": "Stai ancora fornendo le tue informazioni personali sul server d'identità .", + "We recommend that you remove your email addresses and phone numbers from the identity server before disconnecting.": "Ti suggeriamo di rimuovere il tuo indirizzo email e numero di telefono dal server d'identità prima di disconnetterti.", "Disconnect anyway": "Disconnetti comunque", "Error changing power level requirement": "Errore nella modifica del livello dei permessi", "An error occurred changing the room's power level requirements. Ensure you have sufficient permissions and try again.": "C'é stato un errore nel cambio di libelli dei permessi. Assicurati di avere i permessi necessari e riprova.", From 9f492fb4ff8c91ba7208f0b0fdaafed6770316c7 Mon Sep 17 00:00:00 2001 From: Glandos Date: Mon, 27 Sep 2021 12:14:10 +0000 Subject: [PATCH 024/143] Translated using Weblate (French) Currently translated at 99.9% (3165 of 3168 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 | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index 6b6bc98a9e..8af2e8cee1 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -3162,5 +3162,12 @@ "To join a space you'll need an invite.": "Vous avez besoin d’une invitation pour rejoindre un espace.", "You can also make Spaces from communities.": "Vous pouvez également créer des espaces à partir de communautés.", "Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.": "Montre temporairement les communautés au lieu des espaces pour cette session. Il ne sera plus possible de le faire dans un futur proche. Cela va recharger Element.", - "Display Communities instead of Spaces": "Afficher les communautés au lieu des espaces" + "Display Communities instead of Spaces": "Afficher les communautés au lieu des espaces", + "Would you like to leave the rooms in this space?": "Voulez-vous quitter les salons de cet espace ?", + "You are about to leave .": "Vous êtes sur le point de quitter .", + "Leave some rooms": "Quitter certains salons", + "Leave all rooms": "Quitter tous les salons", + "Don't leave any rooms": "Ne quitter aucun salon", + "Expand quotes │ ⇧+click": "Développer les citations │ ⇧+clic", + "Collapse quotes │ ⇧+click": "Réduire les citations │ ⇧+clic" } From 866c9334bc7b416a1b5453798c9c2d4bfb42815b Mon Sep 17 00:00:00 2001 From: sr093906 Date: Mon, 27 Sep 2021 10:38:43 +0000 Subject: [PATCH 025/143] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (3168 of 3168 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/zh_Hans/ --- src/i18n/strings/zh_Hans.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/zh_Hans.json b/src/i18n/strings/zh_Hans.json index 7ed706b61a..62e24c3091 100644 --- a/src/i18n/strings/zh_Hans.json +++ b/src/i18n/strings/zh_Hans.json @@ -3164,5 +3164,7 @@ "You are about to leave .": "你即将离开 。", "Leave some rooms": "离开一些聊天室", "Leave all rooms": "离开所有聊天室", - "Don't leave any rooms": "不离开任何聊天室" + "Don't leave any rooms": "不离开任何聊天室", + "Collapse quotes │ ⇧+click": "折叠引号│ ⇧+click", + "Expand quotes │ ⇧+click": "展开引号│ ⇧+click" } From d2a1507f41c6929e262313e22708c2aa297027c0 Mon Sep 17 00:00:00 2001 From: waclaw66 Date: Mon, 27 Sep 2021 10:58:13 +0000 Subject: [PATCH 026/143] Translated using Weblate (Czech) Currently translated at 100.0% (3168 of 3168 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 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/cs.json b/src/i18n/strings/cs.json index bf6c2c08f3..be6a78588b 100644 --- a/src/i18n/strings/cs.json +++ b/src/i18n/strings/cs.json @@ -3167,5 +3167,7 @@ "You are about to leave .": "Odcházíte z .", "Leave some rooms": "Odejít z některých místností", "Don't leave any rooms": "Neodcházet z žádné místnosti", - "Leave all rooms": "Odejít ze všech místností" + "Leave all rooms": "Odejít ze všech místností", + "Expand quotes │ ⇧+click": "Rozbalit uvozovky │ ⇧+kliknutí", + "Collapse quotes │ ⇧+click": "Sbalit uvozovky │ ⇧+kliknutí" } From a66cc7a3bbb35b37afc03aa2b58bef6a82ca5a65 Mon Sep 17 00:00:00 2001 From: Besnik Bleta Date: Mon, 27 Sep 2021 10:42:46 +0000 Subject: [PATCH 027/143] Translated using Weblate (Albanian) Currently translated at 99.7% (3161 of 3168 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/sq/ --- src/i18n/strings/sq.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/sq.json b/src/i18n/strings/sq.json index 4bfd16b802..618dd71163 100644 --- a/src/i18n/strings/sq.json +++ b/src/i18n/strings/sq.json @@ -3161,5 +3161,7 @@ "You are about to leave .": "Ju ndan një hap nga braktisja e .", "Leave some rooms": "Braktis disa dhoma", "Leave all rooms": "Braktisi krejt dhomat", - "Don't leave any rooms": "Mos braktis ndonjë dhomë" + "Don't leave any rooms": "Mos braktis ndonjë dhomë", + "Expand quotes │ ⇧+click": "Hapi citimet │ ⇧+klikim", + "Collapse quotes │ ⇧+click": "Tkurri citimet │ ⇧+klikim" } From cd8a0b8aec552c080a718c17ba3a737c610ed5b3 Mon Sep 17 00:00:00 2001 From: Andrew Ferrazzutti Date: Tue, 28 Sep 2021 03:42:19 -0400 Subject: [PATCH 028/143] If public room creation fails, retry without publishing it (#19194) Signed-off-by: Andrew Ferrazzutti --- src/createRoom.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/createRoom.ts b/src/createRoom.ts index 25e7257289..746fd63815 100644 --- a/src/createRoom.ts +++ b/src/createRoom.ts @@ -221,6 +221,14 @@ export default async function createRoom(opts: IOpts): Promise { let roomId; return client.createRoom(createOpts).finally(function() { if (modal) modal.close(); + }).catch(function(err) { + if (err.httpStatus === 403 && err.errcode == "M_UNKNOWN") { + console.warn("Failed to publish room, try again without publishing it"); + createOpts.visibility = Visibility.Private; + return client.createRoom(createOpts); + } else { + return Promise.reject(err); + } }).then(function(res) { roomId = res.room_id; if (opts.dmUserId) { From e892984abd4e43028250b48cda5e8f9d536c1475 Mon Sep 17 00:00:00 2001 From: iaiz Date: Tue, 28 Sep 2021 12:54:05 +0000 Subject: [PATCH 029/143] Translated using Weblate (Spanish) Currently translated at 99.8% (3163 of 3168 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 | 363 ++++++++++++++++++++------------------- 1 file changed, 184 insertions(+), 179 deletions(-) diff --git a/src/i18n/strings/es.json b/src/i18n/strings/es.json index a4761610a9..b88bd56886 100644 --- a/src/i18n/strings/es.json +++ b/src/i18n/strings/es.json @@ -2,7 +2,7 @@ "Account": "Cuenta", "Admin": "Admin", "Advanced": "Avanzado", - "Always show message timestamps": "Siempre mostrar las marcas temporales de mensajes", + "Always show message timestamps": "Mostrar siempre la fecha y hora de envío junto a los mensajes", "Authentication": "Autenticación", "%(items)s and %(lastItem)s": "%(items)s y %(lastItem)s", "and %(count)s others...|other": "y otros %(count)s…", @@ -16,7 +16,7 @@ "Banned users": "Usuarios vetados", "Bans user with given id": "Veta al usuario con la ID dada", "Can't connect to homeserver via HTTP when an HTTPS URL is in your browser bar. Either use HTTPS or enable unsafe scripts.": "No se ha podido conectar al servidor base a través de HTTP, cuando es necesario un enlace HTTPS en la barra de direcciones de tu navegador. Ya sea usando HTTPS o activando los scripts inseguros.", - "Change Password": "Cambiar contraseña", + "Change Password": "Cambiar la contraseña", "%(senderName)s changed the power level of %(powerLevelDiffText)s.": "%(senderName)s ha cambiado el nivel de acceso de %(powerLevelDiffText)s.", "%(senderDisplayName)s changed the room name to %(roomName)s.": "%(senderDisplayName)s cambió el nombre de la sala a %(roomName)s.", "%(senderDisplayName)s changed the topic to \"%(topic)s\".": "%(senderDisplayName)s cambió el tema a \"%(topic)s\".", @@ -43,7 +43,7 @@ "Export E2E room keys": "Exportar claves de salas con cifrado de extremo a extremo", "Failed to ban user": "Bloqueo del usuario falló", "Failed to change password. Is your password correct?": "No se ha podido cambiar la contraseña. ¿Has escrito tu contraseña actual correctamente?", - "Failed to change power level": "Falló al cambiar de nivel de acceso", + "Failed to change power level": "Fallo al cambiar de nivel de acceso", "Failed to forget room %(errCode)s": "No se pudo olvidar la sala %(errCode)s", "Failed to join room": "No se ha podido entrar a la sala", "Failed to kick": "No se ha podido echar", @@ -84,8 +84,8 @@ "Accept": "Aceptar", "Add": "Añadir", "Admin Tools": "Herramientas de administración", - "No Microphones detected": "No se ha detectado un micrófono", - "No Webcams detected": "No se ha detectado una cámara", + "No Microphones detected": "Micrófono no detectado", + "No Webcams detected": "Cámara no detectada", "Default Device": "Dispositivo por defecto", "Microphone": "Micrófono", "Camera": "Cámara", @@ -95,7 +95,7 @@ "Decline": "Rechazar", "Enter passphrase": "Introducir frase de contraseña", "Export": "Exportar", - "Failed to upload profile picture!": "¡No se pudo subir la imagen de perfil!", + "Failed to upload profile picture!": "¡No se ha podido enviar la imagen de perfil!", "Home": "Inicio", "Import": "Importar", "Incorrect username and/or password.": "Nombre de usuario y/o contraseña incorrectos.", @@ -121,7 +121,7 @@ "File to import": "Fichero a importar", "You must join the room to see its files": "Debes unirte a la sala para ver sus archivos", "Reject all %(invitedRooms)s invites": "Rechazar todas las invitaciones a %(invitedRooms)s", - "Failed to invite": "No se pudo invitar", + "Failed to invite": "No se ha podido invitar", "Unknown error": "Error desconocido", "Incorrect password": "Contraseña incorrecta", "Unable to restore session": "No se puede recuperar la sesión", @@ -187,7 +187,7 @@ "%(brand)s was not given permission to send notifications - please try again": "No le has dado permiso a %(brand)s para enviar notificaciones. Por favor, inténtalo de nuevo", "%(brand)s version:": "Versión de %(brand)s:", "Room %(roomId)s not visible": "La sala %(roomId)s no es visible", - "Show timestamps in 12 hour format (e.g. 2:30pm)": "Mostrar marcas temporales en formato de 12 horas (ej. 2:30pm)", + "Show timestamps in 12 hour format (e.g. 2:30pm)": "Mostrar las horas con el modelo de 12 horas (ej.: 2:30pm)", "This email address is already in use": "Esta dirección de correo electrónico ya está en uso", "This email address was not found": "No se ha encontrado la dirección de correo electrónico", "The email address linked to your account must be entered.": "Debes ingresar la dirección de correo electrónico vinculada a tu cuenta.", @@ -196,7 +196,7 @@ "This doesn't appear to be a valid email address": "Esto no parece un e-mail váido", "This phone number is already in use": "Este número de teléfono ya está en uso", "This room": "Esta sala", - "This room is not accessible by remote Matrix servers": "Esta sala no es accesible por otros servidores Matrix", + "This room is not accessible by remote Matrix servers": "Esta sala no es accesible desde otros servidores de Matrix", "Cancel": "Cancelar", "Dismiss": "Omitir", "powered by Matrix": "con el poder de Matrix", @@ -221,10 +221,10 @@ "Uploading %(filename)s and %(count)s others|zero": "Subiendo %(filename)s", "Uploading %(filename)s and %(count)s others|one": "Subiendo %(filename)s y otros %(count)s", "Uploading %(filename)s and %(count)s others|other": "Subiendo %(filename)s y otros %(count)s", - "Upload avatar": "Subir avatar", + "Upload avatar": "Adjuntar avatar", "Upload Failed": "Subida fallida", - "Upload file": "Subir archivo", - "Upload new:": "Subir nuevo:", + "Upload file": "Enviar un archivo", + "Upload new:": "Enviar uno nuevo:", "Usage": "Uso", "Users": "Usuarios", "Verification Pending": "Verificación Pendiente", @@ -237,7 +237,7 @@ "You are not in this room.": "No estás en esta sala.", "You do not have permission to do that in this room.": "No tienes permiso para realizar esa acción en esta sala.", "You cannot place a call with yourself.": "No puedes llamarte a ti mismo.", - "Publish this room to the public in %(domain)s's room directory?": "¿Quieres que la sala aparezca en el directorio de salas de %(domain)s?", + "Publish this room to the public in %(domain)s's room directory?": "¿Quieres incluir esta sala en la lista pública de salas de %(domain)s?", "AM": "AM", "PM": "PM", "Unmute": "Dejar de silenciar", @@ -247,7 +247,7 @@ "You have disabled URL previews by default.": "Has desactivado la vista previa de URLs por defecto.", "You have enabled URL previews by default.": "Has activado las vista previa de URLs por defecto.", "You must register to use this functionality": "Regístrate para usar esta funcionalidad", - "You need to be able to invite users to do that.": "Debes ser capaz de invitar usuarios para realizar esa acción.", + "You need to be able to invite users to do that.": "Debes tener permisos para invitar usuarios para hacer eso.", "You need to be logged in.": "Necesitas haber iniciado sesión.", "Your email address does not appear to be associated with a Matrix ID on this Homeserver.": "Tu dirección de correo electrónico no parece estar asociada a una ID de Matrix en este servidor base.", "You seem to be in a call, are you sure you want to quit?": "Parece estar en medio de una llamada, ¿esta seguro que desea salir?", @@ -260,20 +260,20 @@ "Thu": "jue.", "Fri": "vie.", "Sat": "sáb.", - "Jan": "Ene", - "Feb": "Feb", - "Mar": "Mar", - "Apr": "Abr", - "May": "May", - "Jun": "Jun", - "Jul": "Jul", - "Aug": "Ago", + "Jan": "en.", + "Feb": "febr.", + "Mar": "mzo.", + "Apr": "abr.", + "May": "my.", + "Jun": "jun.", + "Jul": "jul.", + "Aug": "ag.", "Add rooms to this community": "Añadir salas a esta comunidad", "Call Failed": "Llamada fallida", - "Sep": "Sep", - "Oct": "Oct", - "Nov": "Nov", - "Dec": "Dic", + "Sep": "sept.", + "Oct": "oct.", + "Nov": "nov.", + "Dec": "dic.", "Warning": "Advertencia", "Online": "En línea", "Submit debug logs": "Enviar registros de depuración", @@ -354,7 +354,7 @@ "You cannot delete this message. (%(code)s)": "No puedes eliminar este mensaje. (%(code)s)", "Thursday": "Jueves", "Logs sent": "Registros enviados", - "Back": "Atrás", + "Back": "Volver", "Reply": "Responder", "Show message in desktop notification": "Mostrar mensaje en las notificaciones de escritorio", "Unable to join network": "No se puede unir a la red", @@ -384,7 +384,7 @@ "You do not have permission to start a conference call in this room": "No tienes permiso para iniciar una llamada de conferencia en esta sala", "%(weekDayName)s %(time)s": "%(weekDayName)s a las %(time)s", "%(weekDayName)s, %(monthName)s %(day)s %(time)s": "%(weekDayName)s %(day)s de %(monthName)s a las %(time)s", - "%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s": "%(weekDayName)s %(day)s de %(monthName)s del %(fullYear)s", + "%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s": "%(weekDayName)s %(day)s de %(monthName)s de %(fullYear)s", "%(weekDayName)s, %(monthName)s %(day)s %(fullYear)s %(time)s": "%(weekDayName)s %(day)s de %(monthName)s del %(fullYear)s a las %(time)s", "Show these rooms to non-members on the community page and room list?": "¿Mostrar estas salas a los que no son miembros en la página de la comunidad y la lista de salas?", "Add rooms to the community": "Añadir salas a la comunidad", @@ -409,17 +409,17 @@ "Your browser does not support the required cryptography extensions": "Su navegador no soporta las extensiones de criptografía requeridas", "Not a valid %(brand)s keyfile": "No es un archivo de claves de %(brand)s válido", "Message Pinning": "Mensajes anclados", - "Automatically replace plain text Emoji": "Reemplazar automáticamente texto por Emojis", - "Mirror local video feed": "Invertir horizontalmente el vídeo local (espejo)", - "Send analytics data": "Enviar datos de análisis de estadísticas", - "Enable inline URL previews by default": "Activar vistas previas de URLs en línea por defecto", - "Enable URL previews for this room (only affects you)": "Activar vista previa de URLs en esta sala (solo para ti)", - "Enable URL previews by default for participants in this room": "Activar vista previa de URLs por defecto para los participantes en esta sala", + "Automatically replace plain text Emoji": "Sustituir automáticamente caritas de texto por sus emojis equivalentes", + "Mirror local video feed": "Invertir el vídeo local horizontalmente (espejo)", + "Send analytics data": "Enviar datos estadísticos de uso", + "Enable inline URL previews by default": "Activar la vista previa de URLs en línea por defecto", + "Enable URL previews for this room (only affects you)": "Activar la vista previa de URLs en esta sala (solo para ti)", + "Enable URL previews by default for participants in this room": "Activar la vista previa de URLs por defecto para los participantes de esta sala", "Enable widget screenshots on supported widgets": "Activar capturas de pantalla de widget en los widgets soportados", - "Drop file here to upload": "Soltar aquí el fichero a subir", - "This event could not be displayed": "No se pudo mostrar este evento", + "Drop file here to upload": "Suelta aquí el archivo para enviarlo", + "This event could not be displayed": "No se ha podido mostrar este evento", "Key request sent.": "Solicitud de clave enviada.", - "Disinvite this user?": "¿Dejar de invitar a este usuario?", + "Disinvite this user?": "¿Borrar la invitación a este usuario?", "Kick this user?": "¿Echar a este usuario?", "Unban this user?": "¿Quitarle el veto a este usuario?", "Ban this user?": "¿Vetar a este usuario?", @@ -450,7 +450,7 @@ "Replying": "Respondiendo", "(~%(count)s results)|other": "(~%(count)s resultados)", "(~%(count)s results)|one": "(~%(count)s resultado)", - "Share room": "Compartir sala", + "Share room": "Compartir la sala", "Banned by %(displayName)s": "Vetado por %(displayName)s", "Muted Users": "Usuarios silenciados", "Members only (since the point in time of selecting this option)": "Solo participantes (desde el momento en que se selecciona esta opción)", @@ -558,7 +558,7 @@ "%(oneUser)schanged their avatar %(count)s times|one": "%(oneUser)s cambió su avatar", "%(items)s and %(count)s others|other": "%(items)s y otros %(count)s", "%(items)s and %(count)s others|one": "%(items)s y otro más", - "collapse": "colapsar", + "collapse": "encoger", "expand": "expandir", "Unable to load event that was replied to, it either does not exist or you do not have permission to view it.": "No se pudo cargar el evento al que se respondió, bien porque no existe o no tiene permiso para verlo.", "In reply to ": "Respondiendo a ", @@ -571,7 +571,7 @@ "Confirm Removal": "Confirmar eliminación", "Are you sure you wish to remove (delete) this event? Note that if you delete a room name or topic change, it could undo the change.": "¿Seguro que quieres eliminar este evento? Ten en cuenta que, si borras un cambio de nombre o asunto de sala, podrías deshacer el cambio.", "Community IDs cannot be empty.": "Las IDs de comunidad no pueden estar vacías.", - "Community IDs may only contain characters a-z, 0-9, or '=_-./'": "Las IDs de comunidad solo pueden contener caracteres de la «a» a la «z» excluyendo la «ñ», dígitos o «=_-./»", + "Community IDs may only contain characters a-z, 0-9, or '=_-./'": "Las IDs de comunidad solo pueden contener caracteres sin acento de la «a» a la «z» (quitando la «ñ»), dígitos o los caracteres «=_-./»", "Something went wrong whilst creating your community": "Algo fue mal mientras se creaba la comunidad", "Create Community": "Crear Comunidad", "Community Name": "Nombre de Comunidad", @@ -590,15 +590,15 @@ "We encountered an error trying to restore your previous session.": "Encontramos un error al intentar restaurar su sesión anterior.", "If you have previously used a more recent version of %(brand)s, your session may be incompatible with this version. Close this window and return to the more recent version.": "Si ha usado anteriormente una versión más reciente de %(brand)s, su sesión puede ser incompatible con ésta. Cierre la ventana y vuelva a la versión más reciente.", "Clearing your browser's storage may fix the problem, but will sign you out and cause any encrypted chat history to become unreadable.": "Limpiando el almacenamiento del navegador puede arreglar el problema, pero le desconectará y cualquier historial de conversación cifrado se volverá ilegible.", - "Share Room": "Compartir sala", - "Link to most recent message": "Enlazar a mensaje más reciente", + "Share Room": "Compartir la sala", + "Link to most recent message": "Enlazar al mensaje más reciente", "Share User": "Compartir usuario", "Share Community": "Compartir Comunidad", - "Share Room Message": "Compartir el mensaje de la sala", - "Link to selected message": "Enlazar a mensaje seleccionado", + "Share Room Message": "Compartir un mensaje de esta sala", + "Link to selected message": "Enlazar al mensaje seleccionado", "Unable to reject invite": "No se pudo rechazar la invitación", "Add rooms to the community summary": "Añadir salas al resumen de la comunidad", - "Which rooms would you like to add to this summary?": "¿Cuáles salas quieres añadir a este resumen?", + "Which rooms would you like to add to this summary?": "¿Qué salas quieres añadir al resumen?", "Add to summary": "Añadir al resumen", "Failed to add the following rooms to the summary of %(groupId)s:": "Falló la agregación de las salas siguientes al resumen de %(groupId)s:", "Add a Room": "Añadir una sala", @@ -652,11 +652,11 @@ "Sent messages will be stored until your connection has returned.": "Los mensajes enviados se almacenarán hasta que vuelva la conexión.", "Room": "Sala", "Clear filter": "Borrar filtro", - "%(brand)s collects anonymous analytics to allow us to improve the application.": "%(brand)s recopila análisis de estadísticas anónimas para permitirnos mejorar la aplicación.", - "Privacy is important to us, so we don't collect any personal or identifiable data for our analytics.": "La privacidad es importante para nosotros, por lo que no se recopila información personal o identificable en los análisis de estadísticas.", + "%(brand)s collects anonymous analytics to allow us to improve the application.": "%(brand)s recoge información sobre cómo usas la aplicación para ayudarnos a mejorarla.", + "Privacy is important to us, so we don't collect any personal or identifiable data for our analytics.": "La privacidad nos importa, por lo que incluimos tus datos personales o que te puedan identificar para en las estadísticas.", "Learn more about how we use analytics.": "Más información sobre el uso de los análisis de estadísticas.", "Check for update": "Comprobar actualizaciones", - "Start automatically after system login": "Ejecutar automáticamente después de iniciar sesión en el sistema", + "Start automatically after system login": "Abrir automáticamente después de iniciar sesión en el sistema", "No Audio Outputs detected": "No se han detectado salidas de sonido", "Audio Output": "Salida de sonido", "An email has been sent to %(emailAddress)s. Once you've followed the link it contains, click below.": "Se envió un correo electrónico a %(emailAddress)s. Una vez hayas seguido el enlace que contiene, haz clic a continuación.", @@ -759,15 +759,15 @@ "Custom user status messages": "Mensajes de estado de usuario personalizados", "Group & filter rooms by custom tags (refresh to apply changes)": "Agrupa y filtra salas por etiquetas personalizadas (refresca para aplicar cambios)", "Render simple counters in room header": "Muestra contadores simples en la cabecera de la sala", - "Enable Emoji suggestions while typing": "Activar sugerencias de emojis al escribir", - "Show a placeholder for removed messages": "Mostrar una marca para los mensaje borrados", + "Enable Emoji suggestions while typing": "Sugerir emojis mientras escribes", + "Show a placeholder for removed messages": "Dejar un indicador cuando se borre un mensaje", "Show join/leave messages (invites/kicks/bans unaffected)": "Mostrar mensajes de entrada/salida (no afecta a invitaciones/expulsiones/baneos)", "Show avatar changes": "Mostrar cambios de avatar", "Show display name changes": "Muestra cambios en los nombres", "Show avatars in user and room mentions": "Mostrar avatares en menciones a usuarios y salas", "Enable big emoji in chat": "Activar emojis grandes en el chat", "Send typing notifications": "Enviar notificaciones de tecleo", - "Prompt before sending invites to potentially invalid matrix IDs": "Pedir confirmación antes de enviar invitaciones a IDs de matrix que parezcan inválidas", + "Prompt before sending invites to potentially invalid matrix IDs": "Preguntarme antes de enviar invitaciones a IDs de matrix que no parezcan válidas", "Show developer tools": "Mostrar herramientas de desarrollo", "Messages containing my username": "Mensajes que contengan mi nombre", "Messages containing @room": "Mensajes que contengan @room", @@ -845,12 +845,12 @@ "No": "No", "We've sent you an email to verify your address. Please follow the instructions there and then click the button below.": "Te hemos enviado un mensaje para verificar tu dirección de correo. Por favor, sigue las instrucciones y después haz clic el botón de abajo.", "Email Address": "Dirección de correo", - "Delete Backup": "Borrar copia", + "Delete Backup": "Borrar copia de seguridad", "Are you sure? You will lose your encrypted messages if your keys are not backed up properly.": "¿Estás seguro? Perderás tus mensajes cifrados si las claves no se copian adecuadamente.", "Encrypted messages are secured with end-to-end encryption. Only you and the recipient(s) have the keys to read these messages.": "Los mensajes cifrados son seguros con el cifrado punto a punto. Solo tú y el/los destinatario/s tiene/n las claves para leer estos mensajes.", "Unable to load key backup status": "No se pudo cargar el estado de la copia de la clave", - "Restore from Backup": "Restaurar desde copia", - "Back up your keys before signing out to avoid losing them.": "Haz copia de tus claves antes de salir para evitar perderlas.", + "Restore from Backup": "Restaurar una copia de seguridad", + "Back up your keys before signing out to avoid losing them.": "Haz copia de seguridad de tus claves antes de cerrar sesión para evitar perderlas.", "Backing up %(sessionsRemaining)s keys...": "Haciendo copia de %(sessionsRemaining)s claves…", "All keys backed up": "Se han copiado todas las claves", "Start using Key Backup": "Comenzar a usar la copia de claves", @@ -858,12 +858,12 @@ "Verification code": "Código de verificación", "Phone Number": "Número de teléfono", "Profile picture": "Foto de perfil", - "Display Name": "Nombre a mostrar", + "Display Name": "Nombre público", "Internal room ID:": "ID de sala Interna:", "Open Devtools": "Abrir devtools", "General": "General", - "Room Addresses": "Direcciones de sala", - "Set a new account password...": "Cambiar la contraseña de tu cuenta…", + "Room Addresses": "Direcciones de la sala", + "Set a new account password...": "Cambia la contraseña de tu cuenta…", "Account management": "Gestión de la cuenta", "Deactivating your account is a permanent action - be careful!": "Desactivar tu cuenta es permanente. ¡Cuidado!", "Credits": "Créditos", @@ -881,7 +881,7 @@ "Changes to who can read history will only apply to future messages in this room. The visibility of existing history will be unchanged.": "Los cambios que se hagan sobre quién puede leer el historial se aplicarán solo a nuevos mensajes. La visibilidad del historial actual no cambiará.", "Security & Privacy": "Seguridad y privacidad", "Encryption": "Cifrado", - "Once enabled, encryption cannot be disabled.": "Una vez activado, el cifrado no se puede desactivar.", + "Once enabled, encryption cannot be disabled.": "Una vez actives el cifrado ya no podrás desactivarlo.", "Encrypted": "Cifrado", "Ignored users": "Usuarios ignorados", "Bulk options": "Opciones generales", @@ -896,13 +896,13 @@ "That doesn't look like a valid email address": "No parece ser una dirección de correo válida", "The following users may not exist": "Puede que estos usuarios no existan", "Unable to find profiles for the Matrix IDs listed below - would you like to invite them anyway?": "No se pudieron encontrar perfiles para los IDs Matrix listados a continuación, ¿Quieres invitarles igualmente?", - "Invite anyway and never warn me again": "Invitar igualmente y no preguntarme más", + "Invite anyway and never warn me again": "Invitar igualmente, y no preguntar más en el futuro", "Invite anyway": "Invitar igualmente", "Before submitting logs, you must create a GitHub issue to describe your problem.": "Antes de enviar logs, debes crear un GitHub issue para describir el problema.", "Unable to load commit detail: %(msg)s": "No se pudo cargar el detalle del commit: %(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": "Para evitar perder tu historial de chat, debes exportar las claves de la sala antes de salir. Debes volver a la versión actual de %(brand)s para esto", "Incompatible Database": "Base de datos incompatible", - "Continue With Encryption Disabled": "Seguir con cifrado desactivado", + "Continue With Encryption Disabled": "Seguir con el cifrado desactivado", "Verify this user to mark them as trusted. Trusting users gives you extra peace of mind when using end-to-end encrypted messages.": "Verifica a este usuario para marcarlo como de confianza. Confiar en usuarios aporta tranquilidad en los mensajes cifrados de extremo a extremo.", "Waiting for partner to confirm...": "Esperando que confirme la otra parte…", "Incoming Verification Request": "Petición de verificación entrante", @@ -915,7 +915,7 @@ "Whether or not you're logged in (we don't record your username)": "Si has iniciado sesión o no (no guardamos tu nombre de usuario)", "Whether or not you're using the 'breadcrumbs' feature (avatars above the room list)": "Si estás usando o no las «migas de pan» (iconos sobre la lista de salas)", "Replying With Files": "Respondiendo con archivos", - "At this time it is not possible to reply with a file. Would you like to upload this file without replying?": "En este momento no es posible responder con un archivo. ¿Te gustaría subir el archivo sin responder?", + "At this time it is not possible to reply with a file. Would you like to upload this file without replying?": "Todavía no es posible responder incluyendo un archivo. ¿Quieres enviar el archivo sin responder directamente?", "The file '%(fileName)s' failed to upload.": "La subida del archivo «%(fileName)s ha fallado.", "The server does not support the room version specified.": "El servidor no soporta la versión de sala especificada.", "Name or Matrix ID": "Nombre o ID de Matrix", @@ -960,7 +960,7 @@ "Changes the avatar of the current room": "Cambia la imagen de la sala actual", "Use an identity server": "Usar un servidor de identidad", "Use an identity server to invite by email. Click continue to use the default identity server (%(defaultIdentityServerName)s) or manage in Settings.": "Usar un servidor de identidad para invitar por correo. Presiona continuar par usar el servidor de identidad por defecto (%(defaultIdentityServerName)s) o adminístralo en Ajustes.", - "Use an identity server to invite by email. Manage in Settings.": "Usar un servidor de identidad para invitar por correo. Gestiónalo en ajustes.", + "Use an identity server to invite by email. Manage in Settings.": "Usa un servidor de identidad para invitar por correo. Puedes configurarlo en tus ajustes.", "Adds a custom widget by URL to the room": "Añade un widget personalizado por URL a la sala", "Please supply a https:// or http:// widget URL": "Por favor provisiona un URL de widget de http:// o https://", "You cannot modify widgets in this room.": "No puedes modificar widgets en esta sala.", @@ -1023,13 +1023,13 @@ "Upgrade": "Actualizar", "Verify": "Verificar", "Later": "Más tarde", - "Upload": "Subir", - "Show less": "Mostrar menos", - "Show more": "Mostrar más", + "Upload": "Enviar", + "Show less": "Ver menos", + "Show more": "Ver más", "Changing password will currently reset any end-to-end encryption keys on all sessions, making encrypted chat history unreadable, unless you first export your room keys and re-import them afterwards. In future this will be improved.": "Cambiar la contraseña reiniciará cualquier clave de cifrado end-to-end en todas las sesiones, haciendo el historial de conversaciones encriptado ilegible, a no ser que primero exportes tus claves de sala y después las reimportes. En un futuro esto será mejorado.", "in memory": "en memoria", "not found": "no encontrado", - "You are currently using to discover and be discoverable by existing contacts you know. You can change your identity server below.": "Estás usando actualmente para descubrir y ser descubierto por contactos existentes que conoces. Puedes cambiar tu servidor de identidad más abajo.", + "You are currently using to discover and be discoverable by existing contacts you know. You can change your identity server below.": "Estás usando actualmente para descubrir y ser descubierto por contactos existentes que conoces. Puedes cambiar tu servidor de identidad más abajo.", "If you don't want to use to discover and be discoverable by existing contacts you know, enter another identity server below.": "Si no quieres usar para descubrir y ser descubierto por contactos existentes que conoces, introduce otro servidor de identidad más abajo.", "You are not currently using an identity server. To discover and be discoverable by existing contacts you know, add one below.": "No estás usando un servidor de identidad ahora mismo. Para descubrir y ser descubierto por contactos existentes que conoces, introduce uno más abajo.", "Disconnecting from your identity server will mean you won't be discoverable by other users and you won't be able to invite others by email or phone.": "Desconectarte de tu servidor de identidad significa que no podrás ser descubierto por otros usuarios y no podrás invitar a otros por email o teléfono.", @@ -1038,7 +1038,7 @@ "Enter a new identity server": "Introducir un servidor de identidad nuevo", "Change": "Cambiar", "Manage integrations": "Gestor de integraciones", - "Something went wrong trying to invite the users.": "Algo salió mal al intentar invitar a los usuarios.", + "Something went wrong trying to invite the users.": "Algo ha salido mal al intentar invitar a los usuarios.", "We couldn't invite those users. Please check the users you want to invite and try again.": "No se pudo invitar a esos usuarios. Por favor, revisa los usuarios que quieres invitar e inténtalo de nuevo.", "Failed to find the following users": "No se encontró a los siguientes usuarios", "The following users might not exist or are invalid, and cannot be invited: %(csvNames)s": "Puede que los siguientes usuarios no existan o sean inválidos, y no pueden ser invitados: %(csvNames)s", @@ -1079,14 +1079,14 @@ "Summary": "Resumen", "Document": "Documento", "Next": "Siguiente", - "Upload files (%(current)s of %(total)s)": "Subir archivos (%(current)s de %(total)s)", - "Upload files": "Subir archivos", - "Upload all": "Subir todo", - "This file is too large to upload. The file size limit is %(limit)s but this file is %(sizeOfThisFile)s.": "Este archivo es demasiado grande para subirse. El limite de tamaño de archivo es %(limit)s pero el archivo es %(sizeOfThisFile)s.", + "Upload files (%(current)s of %(total)s)": "Enviar archivos (%(current)s de %(total)s)", + "Upload files": "Enviar archivos", + "Upload all": "Enviar todo", + "This file is too large to upload. The file size limit is %(limit)s but this file is %(sizeOfThisFile)s.": "Este archivo es demasiado grande para enviarse. El tamaño máximo es %(limit)s pero el archivo pesa %(sizeOfThisFile)s.", "These files are too large to upload. The file size limit is %(limit)s.": "Estos archivos son demasiado grandes para ser subidos. El límite de tamaño de archivos es %(limit)s.", "Some files are too large to be uploaded. The file size limit is %(limit)s.": "Algunos archivos son demasiado grandes para ser subidos. El límite de tamaño de archivos es %(limit)s.", - "Upload %(count)s other files|other": "Subir %(count)s otros archivos", - "Upload %(count)s other files|one": "Subir %(count)s otro archivo", + "Upload %(count)s other files|other": "Enviar otros %(count)s archivos", + "Upload %(count)s other files|one": "Enviar %(count)s archivo más", "Cancel All": "Cancelar todo", "Upload Error": "Error de subida", "Remember my selection for this widget": "Recordar mi selección para este widget", @@ -1140,7 +1140,7 @@ "%(num)s hours from now": "dentro de %(num)s horas", "about a day from now": "dentro de un día", "%(num)s days from now": "dentro de %(num)s días", - "Show typing notifications": "Mostrar notificaciones de escritura", + "Show typing notifications": "Mostrar un indicador cuando alguien más esté escribiendo en la sala", "Never send encrypted messages to unverified sessions from this session": "No enviar nunca mensajes cifrados a sesiones sin verificar desde esta sesión", "Never send encrypted messages to unverified sessions in this room from this session": "No enviar nunca mensajes cifrados a sesiones sin verificar en esta sala desde esta sesión", "Enable message search in encrypted rooms": "Activar la búsqueda de mensajes en salas cifradas", @@ -1168,17 +1168,17 @@ "this room": "esta sala", "View older messages in %(roomName)s.": "Ver mensajes más antiguos en %(roomName)s.", "Sounds": "Sonidos", - "Notification sound": "Sonido de notificación", + "Notification sound": "Sonido para las notificaciones", "Set a new custom sound": "Usar un nuevo sonido personalizado", "Browse": "Seleccionar", - "Change room avatar": "Cambiar avatar de sala", - "Change room name": "Cambiar nombre de sala", - "Change main address for the room": "Cambiar la dirección principal para la sala", - "Change history visibility": "Cambiar visibilidad del historial", - "Change permissions": "Cambiar permisos", - "Change topic": "Cambiar tema", + "Change room avatar": "Cambiar el avatar de la sala", + "Change room name": "Cambiar el nombre de sala", + "Change main address for the room": "Cambiar la dirección principal de la sala", + "Change history visibility": "Cambiar la visibilidad del historial", + "Change permissions": "Cambiar los permisos", + "Change topic": "Cambiar el tema", "Upgrade the room": "Actualizar la sala", - "Enable room encryption": "Activar el cifrado de sala", + "Enable room encryption": "Activar cifrado para la sala", "Modify widgets": "Modificar widgets", "Error changing power level requirement": "Error al cambiar el requerimiento de nivel de poder", "An error occurred changing the room's power level requirements. Ensure you have sufficient permissions and try again.": "Ocurrió un error cambiando los requerimientos de nivel de poder de la sala. Asegúrate de tener los permisos suficientes e inténtalo de nuevo.", @@ -1189,10 +1189,10 @@ "Invite users": "Invitar usuarios", "Change settings": "Cambiar la configuración", "Kick users": "Echar usuarios", - "Ban users": "Bloquear a usuarios", - "Notify everyone": "Notificar a todos", + "Ban users": "Vetar usuarios", + "Notify everyone": "Notificar a todo el mundo", "Send %(eventType)s events": "Enviar eventos %(eventType)s", - "Select the roles required to change various parts of the room": "Selecciona los roles requeridos para cambiar varias partes de la sala", + "Select the roles required to change various parts of the room": "Elige los roles que los usuarios deben tener para poder cambiar los distintos ajustes de la sala", "Enable encryption?": "¿Activar cifrado?", "Your email address hasn't been verified yet": "Tu dirección de email no ha sido verificada", "Verify the link in your inbox": "Verifica el enlace en tu bandeja de entrada", @@ -1206,7 +1206,7 @@ "Enable desktop notifications for this session": "Activa las notificaciones de escritorio para esta sesión", "Enable audible notifications for this session": "Activar notificaciones sonoras para esta sesión", "Checking server": "Comprobando servidor", - "Change identity server": "Cambiar servidor de identidad", + "Change identity server": "Cambiar el servidor de identidad", "Disconnect from the identity server and connect to instead?": "¿Desconectarse del servidor de identidad y conectarse a ?", "Terms of service not accepted or the identity server is invalid.": "Términos de servicio no aceptados o el servidor de identidad es inválido.", "The identity server you have chosen does not have any terms of service.": "El servidor de identidad que has elegido no tiene ningún término de servicio.", @@ -1255,11 +1255,11 @@ "Interactively verify by Emoji": "Verificar interactivamente con emojis", "Done": "Listo", "Support adding custom themes": "Soporta la adición de temas personalizados", - "Show info about bridges in room settings": "Mostrar información sobre puentes en la configuración de salas", + "Show info about bridges in room settings": "Incluir información sobre puentes en la configuración de las salas", "Order rooms by name": "Ordenar las salas por nombre", - "Show rooms with unread notifications first": "Mostrar primero las salas con notificaciones no leídas", - "Show shortcuts to recently viewed rooms above the room list": "Mostrar atajos a las salas recientemente vistas por encima de la lista de salas", - "Allow fallback call assist server turn.matrix.org when your homeserver does not offer one (your IP address would be shared during a call)": "Permitir el servidor de respaldo de asistencia de llamadas turn.matrix.org cuando tu servidor base no lo ofrezca (tu dirección IP se compartiría durante una llamada)", + "Show rooms with unread notifications first": "Colocar primero las salas con notificaciones no leídas", + "Show shortcuts to recently viewed rooms above the room list": "Incluir encima de la lista de salas unos atajos a las últimas salas que hayas visto", + "Allow fallback call assist server turn.matrix.org when your homeserver does not offer one (your IP address would be shared during a call)": "Permitir el servidor de respaldo de asistencia de llamadas turn.matrix.org cuando tu servidor base no lo ofrezca (tu dirección IP se compartirá durante las llamadas)", "Manually verify all remote sessions": "Verificar manualmente todas las sesiones remotas", "Confirm the emoji below are displayed on both sessions, in the same order:": "Confirma que los emojis de abajo son los mismos y tienen el mismo orden en los dos sitios:", "Verify this session by confirming the following number appears on its screen.": "Verifica esta sesión confirmando que el siguiente número aparece en su pantalla.", @@ -1278,7 +1278,7 @@ "cached locally": "almacenado localmente", "not found locally": "no encontrado localmente", "User signing private key:": "Usuario firmando llave privada:", - "Homeserver feature support:": "Características apoyadas por servidor local:", + "Homeserver feature support:": "Características compatibles con tu servidor base:", "exists": "existe", "Your homeserver does not support session management.": "Su servidor local no soporta la gestión de sesiones.", "Confirm deleting these sessions by using Single Sign On to prove your identity.|other": "Confirme eliminar estas sesiones, probando su identidad con el Registro Único.", @@ -1293,9 +1293,9 @@ "%(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.": "A %(brand)s le faltan algunos componentes necesarios para el almacenamiento seguro de mensajes cifrados a nivel local. Si quieres experimentar con esta característica, construye un Escritorio %(brand)s personalizado con componentes de búsqueda añadidos.", "This session is not backing up your keys, but you do have an existing backup you can restore from and add to going forward.": "Esta sesión no ha creado una copia de seguridad de tus llaves, pero tienes una copia de seguridad existente de la que puedes restaurar y añadir para proceder.", "Connect this session to key backup before signing out to avoid losing any keys that may only be on this session.": "Conecte esta sesión a la copia de seguridad de las claves antes de firmar y así evitar perder las claves que sólo existen en esta sesión.", - "Connect this session to Key Backup": "Conecte esta sesión a la copia de respaldo de tu clave", + "Connect this session to Key Backup": "Conecta esta sesión a la copia de respaldo de tu clave", "Backup has a valid signature from this user": "La copia de seguridad tiene una firma válida de este usuario", - "Backup has a invalid signature from this user": "La copia de seguridad tiene una firma inválida de este usuario", + "Backup has a invalid signature from this user": "La copia de seguridad tiene una firma no válida de este usuario", "Backup has a signature from unknown user with ID %(deviceId)s": "La copia de seguridad tiene una firma desconocida del usuario con ID %(deviceId)s", "Backup has a signature from unknown session with ID %(deviceId)s": "La copia de seguridad tiene una firma de desconocido de la sesión con ID %(deviceId)s", "Backup has a valid signature from this session": "La copia de seguridad tiene una firma válida de esta sesión", @@ -1331,7 +1331,7 @@ "If this isn't what you want, please use a different tool to ignore users.": "Si esto no es lo que quieres, por favor usa una herramienta diferente para ignorar usuarios.", "Subscribe": "Suscribir", "Always show the window menu bar": "Siempre mostrar la barra de menú de la ventana", - "Show tray icon and minimize window to it on close": "Mostrar el icono en el Área de Notificación y minimizar la ventana al cerrarla", + "Show tray icon and minimize window to it on close": "Mostrar un icono en el área de notificaciones y guardar la ventana minimizada ahí al cerrarla", "Composer": "Editor", "Timeline": "Línea de tiempo", "Read Marker lifetime (ms)": "Permanencia del marcador de lectura (en ms)", @@ -1342,7 +1342,7 @@ "Cross-signing": "Firma cruzada", "Where you’re logged in": "Sesiones", "Manage the names of and sign out of your sessions below or verify them in your User Profile.": "Gestiona los nombres de sus sesiones y ciérralas abajo o verifícalas en tu perfil de usuario.", - "A session's public name is visible to people you communicate with": "El nombre público de una sesión es visible para las personas con las que te comunicas", + "A session's public name is visible to people you communicate with": "El nombre público de tus sesiones lo puede ver cualquiera con quien te comuniques", "This room is bridging messages to the following platforms. Learn more.": "Esta sala está haciendo puente con las siguientes plataformas. Aprende más.", "This room isn’t bridging messages to any platforms. Learn more.": "Esta sala no está haciendo puente con ninguna plataforma. Aprende más", "Bridges": "Puentes", @@ -1355,7 +1355,7 @@ "Discovery options will appear once you have added an email above.": "Las opciones de descubrimiento aparecerán una vez que haya añadido un correo electrónico arriba.", "Unable to revoke sharing for phone number": "No se logró revocar el intercambio de un número de teléfono", "Unable to share phone number": "No se logró compartir el número de teléfono", - "Please enter verification code sent via text.": "Por favor, introduce el código de verificación enviado por SMS.", + "Please enter verification code sent via text.": "Por favor, escribe el código de verificación que te hemos enviado por SMS.", "Discovery options will appear once you have added a phone number above.": "Las opciones de descubrimiento aparecerán una vez que haya añadido un número de teléfono arriba.", "Remove %(phone)s?": "¿Eliminar %(phone)s?", "A text message has been sent to +%(msisdn)s. Please enter the verification code it contains.": "Se ha enviado un mensaje de texto a +%(msisdn)s. Por favor, escribe el código de verificación que contiene.", @@ -1380,21 +1380,21 @@ "e.g. my-room": "p.ej. mi-sala", "Some characters not allowed": "Algunos caracteres no están permitidos", "Sign in with single sign-on": "Ingresar con un Registro Único", - "Enter a server name": "Introduce un nombre de servidor", + "Enter a server name": "Escribe un nombre de servidor", "Looks good": "Se ve bien", "Can't find this server or its room list": "No se ha podido encontrar este servidor o su lista de salas", "All rooms": "Todas las salas", - "Your server": "Tu", + "Your server": "Tu servidor", "Are you sure you want to remove %(serverName)s": "¿Estás seguro de querer eliminar %(serverName)s?", "Remove server": "Quitar servidor", "Matrix": "Matrix", "Add a new server": "Añadir un nuevo servidor", - "Enter the name of a new server you want to explore.": "Introduce el nombre de un nuevo servidor que quieras explorar.", + "Enter the name of a new server you want to explore.": "Escribe el nombre de un nuevo servidor que quieras explorar.", "Server name": "Nombre del servidor", "Add a new server...": "Añadir otro servidor…", "%(networkName)s rooms": "%(networkName)s sala", "Matrix rooms": "Salas de Matrix", - "Use an identity server to invite by email. Use the default (%(defaultIdentityServerName)s) or manage in Settings.": "Usar un servidor de identidad para invitar vía correo electrónico. . Usar (%(defaultIdentityServerName)s)o seleccione en Ajustes.", + "Use an identity server to invite by email. Use the default (%(defaultIdentityServerName)s) or manage in Settings.": "Usar un servidor de identidad para invitar a través de correo electrónico. . Usar (%(defaultIdentityServerName)s)o seleccione en Ajustes.", "Use an identity server to invite by email. Manage in Settings.": "Utilice un servidor de identidad para invitar por correo electrónico. Gestionar en Ajustes.", "Close dialog": "Cerrar diálogo", "Please tell us what went wrong or, better, create a GitHub issue that describes the problem.": "Por favor, cuéntanos qué ha ido mal o, mejor aún, cree una incidencia en GitHub que describa el problema.", @@ -1575,12 +1575,12 @@ "You cancelled verification.": "Has cancelado la verificación.", "Verification cancelled": "Verificación cancelada", "Compare emoji": "Comparar emoji", - "Encryption enabled": "Cifrado activado", - "Encryption not enabled": "Cifrado no activado", + "Encryption enabled": "El cifrado está activado", + "Encryption not enabled": "El cifrado no está activado", "The encryption used by this room isn't supported.": "El cifrado usado por esta sala no es compatible.", "React": "Reaccionar", "Message Actions": "Acciones de mensaje", - "Show image": "Mostrar imagen", + "Show image": "Ver imagen", "You have ignored this user, so their message is hidden. Show anyways.": "Ha ignorado a esta cuenta, así que su mensaje está oculto. Ver de todos modos.", "You verified %(name)s": "Has verificado a %(name)s", "You cancelled verifying %(name)s": "Has cancelado la verificación de %(name)s", @@ -1595,12 +1595,12 @@ "Declining …": "Declinando…", "%(name)s wants to verify": "%(name)s quiere verificar", "You sent a verification request": "Has enviado solicitud de verificación", - "Show all": "Mostrar todo", + "Show all": "Ver todo", "Reactions": "Reacciones", "reacted with %(shortName)s": " reaccionó con %(shortName)s", "Message deleted": "Mensaje eliminado", "Message deleted by %(name)s": "Mensaje eliminado por %(name)s", - "Edited at %(date)s. Click to view edits.": "Editado el día %(date)s. Haz clic para ver las ediciones.", + "Edited at %(date)s. Click to view edits.": "Última vez editado: %(date)s. Haz clic para ver los cambios.", "edited": "editado", "Can't load this message": "No se ha podido cargar este mensaje", "Submit logs": "Enviar registros", @@ -1632,7 +1632,7 @@ "Rotate Left": "Girar a la izquierda", "Upload completed": "Subida completada", "Cancelled signature upload": "Subida de firma cancelada", - "Unable to upload": "No se puede subir", + "Unable to upload": "No se ha podido enviar", "Signature upload success": "Subida de firma exitosa", "Signature upload failed": "Subida de firma ha fallado", "Confirm by comparing the following with the User Settings in your other session:": "Confirme comparando lo siguiente con los ajustes de usuario de su otra sesión:", @@ -1652,13 +1652,13 @@ "Failed to decrypt %(failedCount)s sessions!": "¡Error al descifrar %(failedCount)s sesiones!", "Successfully restored %(sessionCount)s keys": "%(sessionCount)s claves restauradas con éxito", "Warning: you should only set up key backup from a trusted computer.": "Advertencia: deberías configurar la copia de seguridad de claves solamente usando un ordenador de confianza.", - "Warning: You should only set up key backup from a trusted computer.": "Advertencia: Configurar la copia de seguridad de claves solamente usando un ordenador de confianza.", + "Warning: You should only set up key backup from a trusted computer.": "Advertencia: Configura la copia de seguridad de claves solo si estás usando un ordenador de confianza.", "Resend %(unsentCount)s reaction(s)": "Reenviar %(unsentCount)s reacción(es)", "Report Content": "Reportar contenido", "Notification settings": "Notificaciones", "Clear status": "Borrar estado", "Update status": "Actualizar estado", - "Set status": "Cambiar estado", + "Set status": "Cambiar el estado", "Set a new status...": "Elegir un nuevo estado…", "Hide": "Ocultar", "Remove for everyone": "Eliminar para todos", @@ -1694,7 +1694,7 @@ "Liberate your communication": "Libera tu comunicación", "Send a Direct Message": "Envía un mensaje directo", "Explore Public Rooms": "Explora las salas públicas", - "Create a Group Chat": "Crea una conversación grupal", + "Create a Group Chat": "Crea un grupo", "Filter": "Filtrar", "%(creator)s created and configured the room.": "Sala creada y configurada por %(creator)s.", "%(brand)s failed to get the protocol list from the homeserver. The homeserver may be too old to support third party networks.": "%(brand)s no ha posido obtener la lista de protocolo del servidor base. El servidor base puede ser demasiado viejo para admitir redes de terceros.", @@ -1707,7 +1707,7 @@ "If you can't find the room you're looking for, ask for an invite or Create a new room.": "Si no encuentras la sala que buscas, pide que te inviten a ella o crea una nueva.", "Explore rooms": "Explorar salas", "Jump to first invite.": "Salte a la primera invitación.", - "Add room": "Añadir sala", + "Add room": "Añadir una sala", "Guest": "Invitado", "Could not load user profile": "No se pudo cargar el perfil de usuario", "Verify this login": "Verifica este inicio de sesión", @@ -1767,7 +1767,7 @@ "Font size": "Tamaño del texto", "Use custom size": "Usar un tamaño personalizado", "Use a more compact ‘Modern’ layout": "Usar un diseño más «moderno y compacto»", - "Use a system font": "Usar una fuente del sistema", + "Use a system font": "Usar un tipo de letra del sistema", "System font name": "Nombre de la fuente", "Enable experimental, compact IRC style layout": "Activar el diseño experimental de IRC compacto", "Uploading logs": "Subiendo registros", @@ -1775,7 +1775,7 @@ "Waiting for your other session to verify…": "Esperando a tu otra sesión confirme…", "Your server isn't responding to some requests.": "Tú servidor no esta respondiendo a ciertas solicitudes.", "New version available. Update now.": "Nueva versión disponible. Actualizar ahora.", - "Hey you. You're the best!": "Oye, tú. ¡Eres genial!", + "Hey you. You're the best!": "Oye, tú… ¡eres genial!", "Size must be a number": "El tamaño debe ser un dígito", "Custom font size can only be between %(min)s pt and %(max)s pt": "El tamaño de la fuente solo puede estar entre los valores %(min)s y %(max)s", "Use between %(min)s pt and %(max)s pt": "Utiliza un valor entre %(min)s y %(max)s", @@ -1785,7 +1785,7 @@ "Customise your appearance": "Personaliza la apariencia", "Appearance Settings only affect this %(brand)s session.": "Cambiar las opciones de apariencia solo afecta a esta sesión de %(brand)s.", "Please verify the room ID or address and try again.": "Por favor, verifica la ID o dirección de esta sala e inténtalo de nuevo.", - "Your server admin has disabled end-to-end encryption by default in private rooms & Direct Messages.": "El administrador del servidor base ha desactivado el cifrado de extremo a extremo en salas privadas y mensajes directos.", + "Your server admin has disabled end-to-end encryption by default in private rooms & Direct Messages.": "El administrador de tu servidor base ha desactivado el cifrado de extremo a extremo en salas privadas y mensajes directos.", "To link to this room, please add an address.": "Para obtener un enlace a esta sala, añade una dirección.", "The authenticity of this encrypted message can't be guaranteed on this device.": "La autenticidad de este mensaje cifrado no puede ser garantizada en este dispositivo.", "No recently visited rooms": "No hay salas visitadas recientemente", @@ -1804,7 +1804,7 @@ "Cross-signing is not set up.": "La firma cruzada no está configurada.", "Master private key:": "Clave privada maestra:", "%(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 no puede almacenar en caché de forma segura mensajes cifrados localmente mientras se ejecuta en un navegador web. Usa %(brand)s Escritorio para que los mensajes cifrados aparezcan en los resultados de búsqueda.", - "Backup version:": "Versión de respaldo:", + "Backup version:": "Versión de la copia de seguridad:", "Algorithm:": "Algoritmo:", "Backup key stored:": "Clave de respaldo almacenada:", "Backup key cached:": "Clave de respaldo almacenada en caché:", @@ -1814,22 +1814,22 @@ "Room ID or address of ban list": "ID de sala o dirección de la lista de prohibición", "Secure Backup": "Copia de seguridad segura", "Privacy": "Privacidad", - "Emoji picker": "Selector de emoji", + "Emoji picker": "Elegir emoji", "Explore community rooms": "Explore las salas comunitarias", "Custom Tag": "Etiqueta personalizada", "%(count)s results|one": "%(count)s resultado", "Appearance": "Apariencia", - "Show rooms with unread messages first": "Mostrar primero las salas con mensajes no leídos", - "Show previews of messages": "Mostrar vistas previas de mensajes", + "Show rooms with unread messages first": "Colocar al principio las salas con mensajes sin leer", + "Show previews of messages": "Incluir una vista previa del último mensaje", "Sort by": "Ordenar por", "Activity": "Actividad", "A-Z": "A-Z", - "List options": "Opciones de lista", - "Show %(count)s more|other": "Mostrar %(count)s más", - "Show %(count)s more|one": "Mostrar %(count)s más", + "List options": "Opciones de la lista", + "Show %(count)s more|other": "Ver %(count)s más", + "Show %(count)s more|one": "Ver %(count)s más", "Use default": "Usar valor por defecto", "Mentions & Keywords": "Menciones y palabras clave", - "Notification options": "Opciones de notificación", + "Notification options": "Ajustes de notificaciones", "Forget Room": "Olvidar sala", "Favourited": "Favorecido", "Leave Room": "Salir de la sala", @@ -1849,7 +1849,7 @@ "You've successfully verified your device!": "¡Ha verificado correctamente su dispositivo!", "Take a picture": "Toma una foto", "Message deleted on %(date)s": "Mensaje eliminado el %(date)s", - "Edited at %(date)s": "Editado el %(date)s", + "Edited at %(date)s": "Última vez editado: %(date)s", "Click to view edits": "Haz clic para ver las ediciones", "Categories": "Categorías", "Information": "Información", @@ -1868,13 +1868,13 @@ "There was an error creating your community. The name may be taken or the server is unable to process your request.": "Ha ocurrido un error al crear la comunidad. El nombre puede que ya esté siendo usado o el servidor no puede procesar la solicitud.", "Community ID: +:%(domain)s": "ID de comunidad: +:%(domain)s", "Use this when referencing your community to others. The community ID cannot be changed.": "Usa esto cuando hagas referencia a tu comunidad con otras. El ID de la comunidad no se puede cambiar.", - "You can change this later if needed.": "Puede cambiar esto más tarde si es necesario.", + "You can change this later if needed.": "Puedes cambiar esto más adelante si hace falta.", "What's the name of your community or team?": "¿Cuál es el nombre de tu comunidad o equipo?", "Enter name": "Introduce un nombre", "Add image (optional)": "Añadir imagen (opcional)", "An image will help people identify your community.": "Una imagen ayudará a las personas a identificar su comunidad.", "Private rooms can be found and joined by invitation only. Public rooms can be found and joined by anyone in this community.": "Las salas privadas solo se pueden encontrar y unirse con invitación. Cualquier persona de esta comunidad puede encontrar salas públicas y unirse a ellas.", - "You might enable this if the room will only be used for collaborating with internal teams on your homeserver. This cannot be changed later.": "Puedes activar esto si la sala solo se usará para colaborar con equipos internos en tu servidor base. No se puede cambiar después.", + "You might enable this if the room will only be used for collaborating with internal teams on your homeserver. This cannot be changed later.": "Puedes activar esto si la sala solo se usará para colaborar con equipos internos en tu servidor base. No se podrá cambiar después.", "You might disable this if the room will be used for collaborating with external teams who have their own homeserver. This cannot be changed later.": "Puedes desactivar esto si la sala se utilizará para colaborar con equipos externos que tengan su propio servidor base. Esto no se puede cambiar después.", "Create a room in %(communityName)s": "Crea una sala en %(communityName)s", "Block anyone not part of %(serverName)s from ever joining this room.": "Evita que cualquier persona que no sea parte de %(serverName)s se una a esta sala.", @@ -1965,11 +1965,11 @@ "Restore": "Restaurar", "You'll need to authenticate with the server to confirm the upgrade.": "Deberá autenticarse con el servidor para confirmar la actualización.", "Upgrade this session to allow it to verify other sessions, granting them access to encrypted messages and marking them as trusted for other users.": "Actualice esta sesión para permitirle verificar otras sesiones, otorgándoles acceso a mensajes cifrados y marcándolos como confiables para otros usuarios.", - "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.": "Ingrese una frase de seguridad que solo usted conozca, ya que se usa para proteger sus datos. Para estar seguro, no debe volver a utilizar la contraseña de su cuenta.", + "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.": "Elige una frase de seguridad que solo tú conozcas, ya que se usa para proteger tus datos. Para que sea todavía más segura, no vuelvas a usar la contraseña de tu cuenta.", "That matches!": "¡Eso combina!", "Use a different passphrase?": "¿Utiliza una frase de contraseña diferente?", "That doesn't match.": "No coincide.", - "Go back to set it again.": "Regrese para configurarlo nuevamente.", + "Go back to set it again.": "Volver y ponerlo de nuevo.", "Store your Security Key somewhere safe, like a password manager or a safe, as it’s used to safeguard your encrypted data.": "Guarde su llave de seguridad en un lugar seguro, como un administrador de contraseñas o una caja fuerte, ya que se usa para proteger sus datos cifrados.", "Download": "Descargar", "Unable to query secret storage status": "No se puede consultar el estado del almacenamiento secreto", @@ -1985,12 +1985,12 @@ "For maximum security, this should be different from your account password.": "Para mayor seguridad, esta debe ser diferente a la contraseña de su cuenta.", "Keep a copy of it somewhere secure, like a password manager or even a safe.": "Guarde una copia en un lugar seguro, como un administrador de contraseñas o incluso una caja fuerte.", "Print it and store it somewhere safe": "Imprímelo y guárdalo en un lugar seguro", - "Save it on a USB key or backup drive": "Guárdelo en una llave USB o unidad de respaldo", + "Save it on a USB key or backup drive": "Guárdalo en un USB o disco de copias de seguridad", "Copy it to your personal cloud storage": "Cópielo a su almacenamiento personal en la nube", "Your keys are being backed up (the first backup could take a few minutes).": "Se está realizando una copia de seguridad de sus claves (la primera copia de seguridad puede tardar unos minutos).", "Without setting up Secure Message Recovery, you won't be able to restore your encrypted message history if you log out or use another session.": "Sin configurar Secure Message Recovery, no podrás restaurar tu historial de mensajes encriptados si cierras sesión o usas otra sesión.", "Set up Secure Message Recovery": "Configurar la recuperación segura de mensajes", - "Starting backup...": "Empezando copia de seguridad…", + "Starting backup...": "Empezando la copia de seguridad…", "Success!": "¡Éxito!", "Create key backup": "Crear copia de seguridad de claves", "Unable to create key backup": "No se puede crear una copia de seguridad de la clave", @@ -2023,13 +2023,13 @@ "Toggle Bold": "Alternar negrita", "Toggle Italics": "Alternar cursiva", "Toggle Quote": "Alternar cita", - "New line": "Nueva línea", + "New line": "Insertar salto de línea", "Navigate recent messages to edit": "Navegar entre mensajes recientes para editar", "Jump to start/end of the composer": "Saltar al inicio o final del editor", "Navigate composer history": "Navegar por el historial del editor", "Cancel replying to a message": "Cancelar responder al mensaje", - "Toggle microphone mute": "Alternar silencio del micrófono", - "Toggle video on/off": "Activar/desactivar vídeo", + "Toggle microphone mute": "Activar o desactivar tu micrófono", + "Toggle video on/off": "Activar o desactivar tu cámara", "Scroll up/down in the timeline": "Desplazarse hacia arriba o hacia abajo en la línea de tiempo", "Dismiss read marker and jump to bottom": "Descartar el marcador de lectura y saltar al final", "Jump to oldest unread message": "Ir al mensaje no leído más antiguo", @@ -2037,7 +2037,7 @@ "Jump to room search": "Ir a la búsqueda de salas", "Navigate up/down in the room list": "Navegar hacia arriba/abajo en la lista de salas", "Select room from the room list": "Seleccionar sala de la lista de salas", - "Collapse room list section": "Contraer la sección de lista de salas", + "Collapse room list section": "Encoger la sección de lista de salas", "Expand room list section": "Expandir la sección de la lista de salas", "Clear room list filter field": "Borrar campo de filtro de lista de salas", "Previous/next unread room or DM": "Sala o mensaje directo anterior/siguiente sin leer", @@ -2081,7 +2081,7 @@ "There was an error looking up the phone number": "Ha ocurrido un error al buscar el número de teléfono", "Unable to look up phone number": "No se ha podido buscar el número de teléfono", "Fill Screen": "Llenar pantalla", - "Show stickers button": "Mostrar botón de pegatinas", + "Show stickers button": "Incluir el botón de pegatinas", "See emotes posted to this room": "Ver los emoticonos publicados en esta sala", "Send emotes as you in this room": "Enviar emoticonos en tu nombre a esta sala", "Send messages as you in this room": "Enviar mensajes en tu nombre a esta sala", @@ -2361,21 +2361,21 @@ "Video conference started by %(senderName)s": "Videoconferencia iniciada por %(senderName)s", "Video conference updated by %(senderName)s": "Videoconferencia actualizada por %(senderName)s", "You held the call Resume": "Has puesto la llamada en espera Recuperar", - "You held the call Switch": "Has puesto la llamada en espera Cambiar", + "You held the call Switch": "Has puesto esta llamada en espera Volver", "Reason (optional)": "Motivo (opcional)", "Homeserver": "Servidor base", "Server Options": "Opciones del servidor", "Messages here are end-to-end encrypted. Verify %(displayName)s in their profile - tap on their avatar.": "Estos mensajes se cifran de extremo a extremo. Verifica a %(displayName)s en su perfil - toca su imagen.", "Start a new chat": "Empezar una nueva conversación", "Open dial pad": "Abrir teclado numérico", - "This is the start of .": "Este es el inicio de .", + "This is the start of .": "Aquí empieza .", "Add a photo, so people can easily spot your room.": "Añade una imagen para que la gente reconozca la sala fácilmente.", "%(displayName)s created this room.": "%(displayName)s creó esta sala.", "You created this room.": "Creaste esta sala.", - "Add a topic to help people know what it is about.": "Escribe un asunto para que la gente sepa de qué va esta sala.", + "Add a topic to help people know what it is about.": "Añade un asunto para que la gente sepa de qué va la sala.", "Topic: %(topic)s ": "Tema: %(topic)s ", "Topic: %(topic)s (edit)": "Tema: %(topic)s (cambiar)", - "Remove messages sent by others": "Eliminar mensajes mandados por otros", + "Remove messages sent by others": "Eliminar los mensajes enviados por otras personas", "Back up your encryption keys with your account data in case you lose access to your sessions. Your keys will be secured with a unique Security Key.": "Haz una copia de seguridad de tus claves de cifrado con los datos de tu cuenta por si pierdes acceso a tus sesiones. Las clave serán aseguradas con una clave de seguridad única.", "The operation could not be completed": "No se ha podido completar la operación", "Failed to save your profile": "No se ha podido guardar tu perfil", @@ -2392,7 +2392,7 @@ "Sends the given message with fireworks": "Envía el mensaje con fuegos artificiales", "sends confetti": "envía confeti", "Sends the given message with confetti": "Envía el mensaje con confeti", - "Use Ctrl + Enter to send a message": "Usa Control + Intro para enviar un mensaje", + "Use Ctrl + Enter to send a message": "Hacer que para enviar un mensaje haya que pulsar Control + Intro", "Use Command + Enter to send a message": "Usa Comando + Intro para enviar un mensje", "Render LaTeX maths in messages": "Mostrar matemáticas en los mensajes usando LaTeX", "%(senderName)s ended the call": "%(senderName)s ha terminado la llamada", @@ -2624,7 +2624,7 @@ "Sending your message...": "Enviando tu mensaje…", "Creating...": "Creando…", "You will not be able to undo this change as you are demoting yourself, if you are the last privileged user in the space it will be impossible to regain privileges.": "No podrás deshacer esto, ya que te estás quitando tus permisos. Si eres la última persona con permisos en este usuario, no será posible recuperarlos.", - "Jump to the bottom of the timeline when you send a message": "Saltar abajo del todo cuando envíes un mensaje", + "Jump to the bottom of the timeline when you send a message": "Saltar abajo del todo al enviar un mensaje", "Welcome to ": "Te damos la bienvenida a ", "Already in call": "Ya en una llamada", "Original event source": "Fuente original del evento", @@ -2643,7 +2643,7 @@ "Random": "Al azar", "%(count)s members|one": "%(count)s miembro", "%(count)s members|other": "%(count)s miembros", - "Your server does not support showing space hierarchies.": "Este servidor no soporta mostrar jerarquías de espacios.", + "Your server does not support showing space hierarchies.": "Este servidor no es compatible con la función de las jerarquías de espacios.", "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.": "Tu mensaje no ha sido enviado porque este servidor base ha sido bloqueado por su administración. Por favor, ponte en contacto con ellos para continuar usando el servicio.", "Are you sure you want to leave the space '%(spaceName)s'?": "¿Salir del espacio «%(spaceName)s»?", "This space is not public. You will not be able to rejoin without an invite.": "Este espacio es privado. No podrás volverte a unir sin una invitación.", @@ -2655,11 +2655,11 @@ "Edit settings relating to your space.": "Editar ajustes relacionados con tu espacio.", "Space settings": "Ajustes del espacio", "Failed to save space settings.": "No se han podido guardar los ajustes del espacio.", - "Invite someone using their name, email address, username (like ) or share this space.": "Invita a más gente usando su nombre, correo electrónico, nombre de usuario (ej.: ) o compartiendo este espacio.", - "Invite someone using their name, username (like ) or share this space.": "Invita a más gente usando su nombre, nombre de usuario (ej.: ) o compartiendo este espacio.", + "Invite someone using their name, email address, username (like ) or share this space.": "Invita a más gente usando su nombre, correo electrónico, nombre de usuario (ej.: ) o compartiendo el enlace a este espacio.", + "Invite someone using their name, username (like ) or share this space.": "Invita a más gente usando su nombre, nombre de usuario (ej.: ) o compartiendo el enlace a este espacio.", "Unnamed Space": "Espacio sin nombre", "Invite to %(spaceName)s": "Invitar a %(spaceName)s", - "Create a new room": "Crear una nueva sala", + "Create a new room": "Crear una sala nueva", "Spaces": "Espacios", "Space selection": "Selección de espacio", "Empty room": "Sala vacía", @@ -2668,22 +2668,22 @@ "Add existing room": "Añadir sala ya existente", "You do not have permissions to create new rooms in this space": "No tienes permisos para crear nuevas salas en este espacio", "Send message": "Enviar mensaje", - "Invite to this space": "Invitar a este espacio", + "Invite to this space": "Invitar al espacio", "Your message was sent": "Mensaje enviado", - "Spell check dictionaries": "Diccionarios de comprobación de ortografía", + "Spell check dictionaries": "Diccionarios del corrector de ortografía", "Space options": "Opciones del espacio", "Leave space": "Salir del espacio", - "Invite people": "Invitar a gente", + "Invite people": "Invitar gente", "Share your public space": "Comparte tu espacio público", "Share invite link": "Compartir enlace de invitación", "Click to copy": "Haz clic para copiar", - "Collapse space panel": "Colapsar panel del espacio", - "Expand space panel": "Expandir panel del espacio", + "Collapse space panel": "Encoger panel de los espacios", + "Expand space panel": "Expandir panel de los espacios", "Your private space": "Tu espacio privado", "Your public space": "Tu espacio público", - "Invite only, best for yourself or teams": "Solo con invitación, mejor para ti o para equipos", + "Invite only, best for yourself or teams": "Acceso por invitación, mejor para equipos o solo tú", "Private": "Privado", - "Open space for anyone, best for communities": "Espacio abierto para todo el mundo, la mejor opción para comunidades", + "Open space for anyone, best for communities": "Abierto para todo el mundo, la mejor opción para comunidades", "Public": "Público", "Create a space": "Crear un espacio", "Delete": "Borrar", @@ -2717,7 +2717,7 @@ "%(count)s messages deleted.|other": "%(count)s mensajes eliminados.", "Invite to %(roomName)s": "Invitar a %(roomName)s", "Edit devices": "Editar dispositivos", - "Invite People": "Invitar a gente", + "Invite People": "Invitar gente", "Invite with email or username": "Invitar correos electrónicos o nombres de usuario", "You can change these anytime.": "Puedes cambiar todo esto en cualquier momento.", "Add some details to help people recognise it.": "Añade algún detalle para ayudar a que la gente lo reconozca.", @@ -2730,13 +2730,13 @@ "Invited people will be able to read old messages.": "Las personas invitadas podrán leer mensajes antiguos.", "We couldn't create your DM.": "No hemos podido crear tu mensaje directo.", "Adding...": "Añadiendo...", - "Add existing rooms": "Añadir salas existentes", + "Add existing rooms": "Añadir salas que ya existan", "%(count)s people you know have already joined|one": "%(count)s persona que ya conoces se ha unido", "%(count)s people you know have already joined|other": "%(count)s personas que ya conoces se han unido", "Accept on your other login…": "Acepta en otro sitio donde hayas iniciado sesión…", "Quick actions": "Acciones rápidas", "Invite to just this room": "Invitar solo a esta sala", - "Warn before quitting": "Avisar antes de salir", + "Warn before quitting": "Pedir confirmación antes de salir", "Manage & explore rooms": "Gestionar y explorar salas", "unknown person": "persona desconocida", "%(deviceId)s from %(ip)s": "%(deviceId)s desde %(ip)s", @@ -2798,8 +2798,8 @@ "Not all selected were added": "No se han añadido todas las seleccionadas", "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 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, revisa tus ajustes e inténtalo de nuevo.", + "No microphone found": "Micrófono no detectado", "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.", @@ -2812,7 +2812,7 @@ "You may contact me if you have any follow up questions": "Os podéis poner en contacto conmigo si tenéis alguna pregunta", "To leave the beta, visit your settings.": "Para salir de la beta, ve a tus ajustes.", "Your platform and username will be noted to help us use your feedback as much as we can.": "Tu nombre de usuario y plataforma serán adjuntados, para que podamos interpretar tus comentarios lo mejor posible.", - "%(featureName)s beta feedback": "Comentarios sobre la funcionalidad beta %(featureName)s", + "%(featureName)s beta feedback": "Danos tu opinión sobre la funcionalidad beta de %(featureName)s", "Thank you for your feedback, we really appreciate it.": "Muchas gracias por tus comentarios.", "Add reaction": "Reaccionar", "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.": "¿Te apetece probar cosas nuevas? Los experimentos son la mejor manera de conseguir acceso anticipado a nuevas funcionalidades, probarlas y ayudar a mejorarlas antes de su lanzamiento. Más información.", @@ -2820,10 +2820,10 @@ "Go to my space": "Ir a mi espacio", "sends space invaders": "enviar space invaders", "Sends the given message with a space themed effect": "Envía un mensaje con efectos espaciales", - "Allow Peer-to-Peer for 1:1 calls (if you enable this, the other party might be able to see your IP address)": "Permitir conexión directa (peer-to-peer) en las llamadas individuales (si lo activas, la otra persona podría ver tu dirección IP)", + "Allow Peer-to-Peer for 1:1 calls (if you enable this, the other party might be able to see your IP address)": "Permitir conexiones directas (peer-to-peer) en las llamadas individuales (si lo activas, la otra persona podría llegar a ver tu dirección IP)", "See when people join, leave, or are invited to your active room": "Ver cuando alguien se una, salga o se le invite a tu sala activa", - "Kick, ban, or invite people to this room, and make you leave": "Expulsar, vetar o invitar personas a esta sala, y hacerte salir de ella", - "Kick, ban, or invite people to your active room, and make you leave": "Expulsar, vetar o invitar a gente a tu sala activa, o hacerte salir", + "Kick, ban, or invite people to this room, and make you leave": "Echar, vetar o invitar personas a esta sala, y hacerte salir de ella", + "Kick, ban, or invite people to your active room, and make you leave": "Echar, vetar o invitar gente a tu sala activa, o hacerte salir de la sala", "See when people join, leave, or are invited to this room": "Ver cuando alguien se une, sale o se le invita a la sala", "Try different words or check for typos. Some results may not be visible as they're private and you need an invite to join them.": "Prueba con sinónimos o revisa si te has equivocado al escribir. Puede que algunos resultados no sean visibles si son privados y necesites que te inviten para verlos.", "Currently joining %(count)s rooms|one": "Entrando en %(count)s sala", @@ -2846,10 +2846,10 @@ "Error loading Widget": "Error al cargar el widget", "Pinned messages": "Mensajes fijados", "If you have permissions, open the menu on any message and select Pin to stick them here.": "Si tienes permisos, abre el menú de cualquier mensaje y selecciona Fijar para colocarlo aquí.", - "Nothing pinned, yet": "Nada fijado, todavía", + "Nothing pinned, yet": "Ningún mensaje fijado… todavía", "%(senderName)s removed their display name (%(oldDisplayName)s)": "%(senderName)s se ha quitado el nombre personalizado (%(oldDisplayName)s)", "%(senderName)s set their display name to %(displayName)s": "%(senderName)s ha elegido %(displayName)s como su nombre", - "%(senderName)s changed the pinned messages for the room.": "%(senderName)s ha cambiado los mensajes fijados de la sala.", + "%(senderName)s changed the pinned messages for the room.": "%(senderName)s cambió los mensajes fijados de la sala.", "%(senderName)s kicked %(targetName)s": "%(senderName)s ha echado a %(targetName)s", "%(senderName)s kicked %(targetName)s: %(reason)s": "%(senderName)s ha echado a %(targetName)s: %(reason)s", "Disagree": "No estoy de acuerdo", @@ -2888,7 +2888,7 @@ "Published addresses can be used by anyone on any server to join your space.": "Los espacios publicados pueden usarse por cualquiera, independientemente de su servidor base.", "This space has no local addresses": "Este espacio no tiene direcciones locales", "Space information": "Información del espacio", - "Collapse": "Colapsar", + "Collapse": "Encoger", "Expand": "Expandir", "Recommended for public spaces.": "Recomendado para espacios públicos.", "Allow people to preview your space before they join.": "Permitir que se pueda ver una vista previa del espacio antes de unirse a él.", @@ -2905,7 +2905,7 @@ "e.g. my-space": "ej.: mi-espacio", "Silence call": "Silenciar llamada", "Sound on": "Sonido activado", - "Show all rooms in Home": "Mostrar todas las salas en la pantalla de inicio", + "Show all rooms in Home": "Incluir todas las salas en Inicio", "Report to moderators prototype. In rooms that support moderation, the `report` button will let you report abuse to room moderators": "Prototipo de reportes a los moderadores. En las salas que lo permitan, verás el botón «reportar», que te permitirá avisar de mensajes abusivos a los moderadores de la sala", "%(senderName)s withdrew %(targetName)s's invitation": "%(senderName)s ha anulado la invitación a %(targetName)s", "%(senderName)s withdrew %(targetName)s's invitation: %(reason)s": "%(senderName)s ha anulado la invitación a %(targetName)s: %(reason)s", @@ -2965,14 +2965,14 @@ "Image": "Imagen", "Sticker": "Pegatina", "The call is in an unknown state!": "¡La llamada está en un estado desconocido!", - "Call back": "Devolver", + "Call back": "Devolver llamada", "No answer": "Sin respuesta", "An unknown error occurred": "Ha ocurrido un error desconocido", "Connection failed": "Ha fallado la conexión", "Copy Room Link": "Copiar enlace a la sala", - "Displaying time": "Mostrando la hora", + "Displaying time": "Fecha y hora", "IRC": "IRC", - "Use Ctrl + F to search timeline": "Usa Control + F para buscar dentro de la conversación", + "Use Ctrl + F to search timeline": "Activar el atajo Control + F, que permite buscar dentro de una conversación", "Please note upgrading will make a new version of the room. All current messages will stay in this archived room.": "Ten en cuenta que actualizar crea una nueva versión de la sala. Todos los mensajes hasta ahora quedarán archivados aquí, en esta sala.", "Automatically invite members from this room to the new one": "Invitar a la nueva sala automáticamente a los miembros que tiene ahora", "These are likely ones other room admins are a part of.": "Otros administradores de la sala estarán dentro.", @@ -3010,21 +3010,21 @@ "Your camera is turned off": "Tu cámara está apagada", "%(sharerName)s is presenting": "%(sharerName)s está presentando", "You are presenting": "Estás presentando", - "All rooms you're in will appear in Home.": "En la página de inicio aparecerán todas las salas a las que te hayas unido.", + "All rooms you're in will appear in Home.": "Elige si quieres que en Inicio aparezcan todas las salas a las que te hayas unido.", "To help space members find and join a private room, go to that room's Security & Privacy settings.": "Para ayudar a los miembros de tus espacios a encontrar y unirse a salas privadas, ve a los ajustes seguridad y privacidad de la sala en cuestión.", "Help space members find private rooms": "Ayuda a los miembros de tus espacios a encontrar salas privadas", "Help people in spaces to find and join private rooms": "Ayuda a la gente en tus espacios a encontrar y unirse a salas privadas", "New in the Spaces beta": "Novedades en la beta de los espacios", "We're working on this, but just want to let you know.": "Todavía estamos trabajando en esto, pero queríamos enseñártelo.", "Search for rooms or spaces": "Buscar salas o espacios", - "Add space": "Añadir espacio", + "Add space": "Añadir un espacio", "Spaces you know that contain this room": "Espacios que conoces que contienen esta sala", "Search spaces": "Buscar espacios", "Select spaces": "Elegir espacios", "Leave %(spaceName)s": "Salir de %(spaceName)s", "You're the only admin of some of the rooms or spaces you wish to leave. Leaving them will leave them without any admins.": "Eres la única persona con permisos de administración en algunos de los espacios de los que quieres irte. Al salir de ellos, nadie podrá gestionarlos.", - "You're the only admin of this space. Leaving it will mean no one has control over it.": "Eres la única persona con permisos de administración en el espacio. Al salir, nadie podrá gestionarlo.", - "You won't be able to rejoin unless you are re-invited.": "No podrás volverte a unir hasta que te vuelvan a invitar.", + "You're the only admin of this space. Leaving it will mean no one has control over it.": "Eres la única persona con permisos de administración en este espacio. Cuando salgas, nadie más podrá gestionarlo.", + "You won't be able to rejoin unless you are re-invited.": "No te podrás unir de nuevo hasta que te inviten otra vez a él.", "Search %(spaceName)s": "Buscar en %(spaceName)s", "Want to add an existing space instead?": "¿Quieres añadir un espacio que ya exista?", "Private space (invite only)": "Espacio privado (solo por invitación)", @@ -3057,7 +3057,7 @@ "Missed call": "Llamada perdida", "Call declined": "Llamada rechazada", "Stop recording": "Dejar de grabar", - "Send voice message": "Enviar mensaje de voz", + "Send voice message": "Enviar un mensaje de voz", "Olm version:": "Versión de Olm:", "Mute the microphone": "Silenciar el micrófono", "Unmute the microphone": "Activar el micrófono", @@ -3092,8 +3092,8 @@ "To create a Space from another community, just pick the community in Preferences.": "Para crear un espacio a partir de otra comunidad, escoge la comunidad en ajustes.", "Debug logs contain application usage data including your username, the IDs or aliases of the rooms or groups you have visited, which UI elements you last interacted with, and the usernames of other users. They do not contain messages.": "Los registros de depuración contienen datos de uso de la aplicación como tu nombre de usuario, las IDs o los nombres de las salas o grupos que has visitado, con qué elementos de la interfaz has interactuado recientemente, y nombres de usuario de otras personas. No incluyen mensajes.", "To avoid these issues, create a new public room for the conversation you plan to have.": "Para evitar estos problemas, crea una nueva sala pública para la conversación que planees tener.", - "%(severalUsers)schanged the pinned messages for the room %(count)s times.|other": "%(severalUsers)s han cambiado los mensajes anclados de la sala %(count)s veces.", - "%(oneUser)schanged the pinned messages for the room %(count)s times.|other": "%(oneUser)s han cambiado los mensajes anclados de la sala %(count)s veces.", + "%(severalUsers)schanged the pinned messages for the room %(count)s times.|other": "%(severalUsers)s han cambiado los mensajes fijados de la sala %(count)s veces.", + "%(oneUser)schanged the pinned messages for the room %(count)s times.|other": "%(oneUser)s han cambiado los mensajes fijados de la sala %(count)s veces.", "Cross-signing is ready but keys are not backed up.": "La firma cruzada está lista, pero no hay copia de seguridad de las claves.", "Rooms and spaces": "Salas y espacios", "Results": "Resultados", @@ -3122,13 +3122,13 @@ "The above, but in as well": "Lo de arriba, pero también en ", "Autoplay videos": "Reproducir automáticamente los vídeos", "Autoplay GIFs": "Reproducir automáticamente los GIFs", - "%(senderName)s pinned a message to this room. See all pinned messages.": "%(senderName)s ha anclado un mensaje en esta sala. Mira todos los mensajes anclados.", - "%(senderName)s pinned a message to this room. See all pinned messages.": "%(senderName)s ha anclado un mensaje en esta sala. Mira todos los mensajes anclados.", + "%(senderName)s pinned a message to this room. See all pinned messages.": "%(senderName)s ha fijado un mensaje en esta sala. Mira todos los mensajes fijados.", + "%(senderName)s pinned a message to this room. See all pinned messages.": "%(senderName)s ha fijado un mensaje en esta sala. Mira todos los mensajes fijados.", "Some encryption parameters have been changed.": "Algunos parámetros del cifrado han cambiado.", "Role in ": "Rol en ", "Currently, %(count)s spaces have access|one": "Ahora mismo, un espacio tiene acceso", "& %(count)s more|one": "y %(count)s más", - "Select the roles required to change various parts of the space": "Selecciona los roles necesarios para cambiar varios ajustes del espacio", + "Select the roles required to change various parts of the space": "Elige los roles que los usuarios deben tener para poder cambiar los distintos ajustes del espacio", "Failed to update the join rules": "Fallo al actualizar las reglas para unirse", "Anyone in can find and join. You can select other spaces too.": "Cualquiera en puede encontrar y unirse. También puedes seleccionar otros espacios.", "Explore %(spaceName)s": "Explorar %(spaceName)s", @@ -3139,8 +3139,8 @@ "Unknown failure": "Fallo desconocido", "Change space avatar": "Cambiar la imagen del espacio", "Change space name": "Cambiar el nombre del espacio", - "Change main address for the space": "Cambiar dirección principal del espacio", - "Change description": "Cambiar descripción", + "Change main address for the space": "Cambiar la dirección principal del espacio", + "Change description": "Cambiar la descripción", "Private community": "Comunidad privada", "Public community": "Comunidad pública", "Message": "Mensaje", @@ -3156,5 +3156,10 @@ "Leave all rooms": "Salir de todas las salas", "Leave some rooms": "Salir de algunas salas", "Would you like to leave the rooms in this space?": "¿Quieres salir también de las salas del espacio?", - "You are about to leave .": "Estás a punto de salirte de ." + "You are about to leave .": "Estás a punto de salirte de .", + "Collapse quotes │ ⇧+click": "Encoger citas │ ⇧+click", + "%(senderName)s unpinned a message from this room. See all pinned messages.": "%(senderName)s ha dejado de fijar un mensaje de esta sala. Ver todos los mensajes fijados.", + "%(senderName)s unpinned a message from this room. See all pinned messages.": "%(senderName)s ha dejado de fijar un mensaje de esta sala. Ver todos los mensajes fijados.", + "%(reactors)s reacted with %(content)s": "%(reactors)s han reaccionado con %(content)s", + "Expand quotes │ ⇧+click": "Expandir citas │ ⇧+clic" } From d5a6339c8d2392ce5cdf093e00d7622c90a6abb9 Mon Sep 17 00:00:00 2001 From: Jeff Huang Date: Tue, 28 Sep 2021 01:47:22 +0000 Subject: [PATCH 030/143] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (3168 of 3168 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 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index d4da600284..006cf630ac 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -3167,5 +3167,7 @@ "Leave all rooms": "離開所有聊天室", "Don't leave any rooms": "不要離開任何聊天室", "%(reactors)s reacted with %(content)s": "%(reactors)s 使用了 %(content)s 反應", - "Joining space …": "正在加入空間……" + "Joining space …": "正在加入空間……", + "Expand quotes │ ⇧+click": "展開引用 │ ⇧+點擊", + "Collapse quotes │ ⇧+click": "折疊引用 │ ⇧+點擊" } From 0a41385c78c1b52481c064e0d8dd921ae86ca1ba Mon Sep 17 00:00:00 2001 From: Andrejs Date: Tue, 28 Sep 2021 05:44:35 +0000 Subject: [PATCH 031/143] Translated using Weblate (Latvian) Currently translated at 60.6% (1921 of 3168 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/lv/ --- src/i18n/strings/lv.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/lv.json b/src/i18n/strings/lv.json index d8e2a21638..a242fb0f49 100644 --- a/src/i18n/strings/lv.json +++ b/src/i18n/strings/lv.json @@ -204,7 +204,7 @@ "Unnamed Room": "Istaba bez nosaukuma", "Cancel": "Atcelt", "Create new room": "Izveidot jaunu istabu", - "Dismiss": "Aizvērt/atcelt", + "Dismiss": "Aizvērt", "You have enabled URL previews by default.": "URL priekšskatījumi pēc noklusējuma jums iriespējoti .", "Upload avatar": "Augšupielādēt avataru", "Upload Failed": "Augšupielāde (nosūtīšana) neizdevās", From 0b8b3c49bc1b7312c989ea5b2978bb5f8b11a47d Mon Sep 17 00:00:00 2001 From: XoseM Date: Tue, 28 Sep 2021 05:49:26 +0000 Subject: [PATCH 032/143] Translated using Weblate (Galician) Currently translated at 100.0% (3168 of 3168 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 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/gl.json b/src/i18n/strings/gl.json index 875a3ff2d2..63fc7d4804 100644 --- a/src/i18n/strings/gl.json +++ b/src/i18n/strings/gl.json @@ -3164,5 +3164,7 @@ "Leave all rooms": "Sair de tódalas salas", "Don't leave any rooms": "Non saír de ningunha sala", "%(reactors)s reacted with %(content)s": "%(reactors)s reaccionou con %(content)s", - "Joining space …": "Uníndote ao espazo…" + "Joining space …": "Uníndote ao espazo…", + "Expand quotes │ ⇧+click": "Despregar citas | ⇧+click", + "Collapse quotes │ ⇧+click": "Pechar citas | ⇧+click" } From 3df7f3790b61e17a02170610c6c1659473fa49c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Mon, 27 Sep 2021 21:57:39 +0000 Subject: [PATCH 033/143] Translated using Weblate (Estonian) Currently translated at 99.9% (3167 of 3168 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 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index b4f58e04da..81e8fc3b6c 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -2705,7 +2705,7 @@ "Invite by username": "Kutsu kasutajanime alusel", "What projects are you working on?": "Mis ettevõtmistega sa tegeled?", "Decrypted event source": "Sündmuse dekrüptitud lähtekood", - "Original event source": "Algse sündmuse lähtekood", + "Original event source": "Sündmuse töötlemata lähtekood", "Failed to remove some rooms. Try again later": "Mõnede jututubade eemaldamine ei õnnestunud. Proovi hiljem uuesti", "Removing...": "Eemaldan...", "Mark as not suggested": "Eemalda soovitus", @@ -3163,5 +3163,7 @@ "You are about to leave .": "Sa oled lahkumas kogukonnast.", "Leave some rooms": "Lahku mõnedest jututubadest", "Leave all rooms": "Lahku kõikidest jututubadest", - "Don't leave any rooms": "Ära lahku ühestki jututoast" + "Don't leave any rooms": "Ära lahku ühestki jututoast", + "Expand quotes │ ⇧+click": "Näita tsitaate │ ⇧+click", + "Collapse quotes │ ⇧+click": "Ahenda tsitaadid │ ⇧+click" } From 0bc0dbac17201cdd0599f8a5a739b92381a82103 Mon Sep 17 00:00:00 2001 From: Szimszon Date: Tue, 28 Sep 2021 13:11:37 +0000 Subject: [PATCH 034/143] Translated using Weblate (Hungarian) Currently translated at 100.0% (3168 of 3168 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 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/hu.json b/src/i18n/strings/hu.json index a547f99c74..4957bc6efa 100644 --- a/src/i18n/strings/hu.json +++ b/src/i18n/strings/hu.json @@ -3164,5 +3164,7 @@ "You are about to leave .": "Éppen el akarja hagyni teret.", "Leave some rooms": "Kilépés néhány szobából", "Leave all rooms": "Kilépés minden szobából", - "Don't leave any rooms": "Ne lépjen ki egy szobából sem" + "Don't leave any rooms": "Ne lépjen ki egy szobából sem", + "Expand quotes │ ⇧+click": "Idézetek megnyitása │ ⇧+kattintás", + "Collapse quotes │ ⇧+click": "Idézetek bezárása│ ⇧+kattintás" } From f4353ea7a4e1d5d6a8ba4c3fb2ab128f14372a4b Mon Sep 17 00:00:00 2001 From: Nikita Epifanov Date: Tue, 28 Sep 2021 13:12:36 +0000 Subject: [PATCH 035/143] Translated using Weblate (Russian) Currently translated at 98.2% (3114 of 3168 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/ru/ --- src/i18n/strings/ru.json | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index 40d6935a82..a06dd2f72f 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -3138,5 +3138,29 @@ "%(senderName)s unpinned a message from this room. See all pinned messages.": "%(senderName)s открепляет сообщение из этой комнаты. Просмотрите все прикрепленые сообщения.", "%(senderName)s unpinned a message from this room. See all pinned messages.": "%(senderName)s открепляет сообщение из этой комнаты. Просмотрите все прикрепленые сообщения.", "%(senderName)s pinned a message to this room. See all pinned messages.": "%(senderName)s прикрепляет сообщение в этой комнате. Просмотрите все прикрепленные сообщения.", - "%(senderName)s pinned a message to this room. See all pinned messages.": "%(senderName)s прикрепляет сообщение в этой комнате. Просмотрите все прикрепленые сообщения." + "%(senderName)s pinned a message to this room. See all pinned messages.": "%(senderName)s прикрепляет сообщение в этой комнате. Просмотрите все прикрепленые сообщения.", + "To join this Space, hide communities in your preferences": "Чтобы присоединиться к этому пространству, скройте сообщества в ваших настройках", + "To view this Space, hide communities in your preferences": "Чтобы просмотреть это пространство, скройте сообщества в ваших настройках", + "To join %(communityName)s, swap to communities in your preferences": "Чтобы присоединиться к %(communityName)s, переключитесь на сообщества в ваших настройках", + "To view %(communityName)s, swap to communities in your preferences": "Для просмотра %(communityName)s, переключитесь на сообщества в ваших настройках", + "Private community": "Приватное сообщество", + "Public community": "Публичное сообщество", + "Leave some rooms": "Покинуть несколько комнат", + "Leave all rooms": "Покинуть все комнаты", + "Don't leave any rooms": "Не покидать ни одну комнату", + "Would you like to leave the rooms in this space?": "Хотите ли вы покинуть комнаты в этом пространстве?", + "You are about to leave .": "Вы собираетесь покинуть .", + "%(reactors)s reacted with %(content)s": "%(reactors)s отреагировали %(content)s", + "Expand quotes │ ⇧+click": "Развернуть цитаты │ ⇧+нажатие", + "Collapse quotes │ ⇧+click": "Свернуть цитаты │ ⇧+нажатие", + "Message": "Сообщение", + "Joining space …": "Присоединение к пространству…", + "Message didn't send. Click for info.": "Сообщение не отправлено. Нажмите для получения информации.", + "Upgrade anyway": "Обновить в любом случае", + "This room is in some spaces you’re not an admin of. In those spaces, the old room will still be shown, but people will be prompted to join the new one.": "Эта комната находится в некоторых пространствах, администратором которых вы не являетесь. В этих пространствах старая комната будет по-прежнему отображаться, но людям будет предложено присоединиться к новой.", + "Before you upgrade": "Перед обновлением", + "To join a space you'll need an invite.": "Чтобы присоединиться к пространству, вам нужно получить приглашение.", + "Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.": "Временно показывать сообщества вместо пространств для этой сессии. Поддержка этого будет удалена в ближайшем будущем. Это перезагрузит Element.", + "Display Communities instead of Spaces": "Показывать сообщества вместо пространств", + "You can also make Spaces from communities.": "Вы также можете создать пространство из сообщества." } From 2ac2358d9354ce9c1825431d92cb0fddb5e3961f Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 28 Sep 2021 16:22:05 +0100 Subject: [PATCH 036/143] Fix avatar getting chopped off --- res/css/views/dialogs/_ConfirmUserActionDialog.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/css/views/dialogs/_ConfirmUserActionDialog.scss b/res/css/views/dialogs/_ConfirmUserActionDialog.scss index 777c9fdfd9..fd286720c4 100644 --- a/res/css/views/dialogs/_ConfirmUserActionDialog.scss +++ b/res/css/views/dialogs/_ConfirmUserActionDialog.scss @@ -22,10 +22,10 @@ limitations under the License. .mx_ConfirmUserActionDialog_avatar { float: left; margin-right: 20px; - margin-top: -2px; } .mx_ConfirmUserActionDialog_name { + padding-top: 2px; font-size: $font-18px; } From 0f8069ac35521e90b3c412606a68a1452e4d5ce4 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 28 Sep 2021 16:22:27 +0100 Subject: [PATCH 037/143] Switch ConfirmUserActionDialog over to using a Field --- .../dialogs/_ConfirmUserActionDialog.scss | 12 ----- .../views/dialogs/ConfirmUserActionDialog.tsx | 50 +++++++++++++------ 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/res/css/views/dialogs/_ConfirmUserActionDialog.scss b/res/css/views/dialogs/_ConfirmUserActionDialog.scss index fd286720c4..cdcb2b4587 100644 --- a/res/css/views/dialogs/_ConfirmUserActionDialog.scss +++ b/res/css/views/dialogs/_ConfirmUserActionDialog.scss @@ -37,16 +37,4 @@ limitations under the License. font-size: $font-14px; color: $primary-content; background-color: $background; - - border-radius: 3px; - border: solid 1px $input-border-color; - line-height: $font-36px; - padding-left: 16px; - padding-right: 16px; - padding-top: 1px; - padding-bottom: 1px; - - margin-bottom: 24px; - - width: 90%; } diff --git a/src/components/views/dialogs/ConfirmUserActionDialog.tsx b/src/components/views/dialogs/ConfirmUserActionDialog.tsx index 7468f400c6..2f4e511675 100644 --- a/src/components/views/dialogs/ConfirmUserActionDialog.tsx +++ b/src/components/views/dialogs/ConfirmUserActionDialog.tsx @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, { ReactNode } from 'react'; +import React, { ChangeEvent, ReactNode } from 'react'; import { MatrixClient } from 'matrix-js-sdk/src/client'; import { RoomMember } from "matrix-js-sdk/src/models/room-member"; import classNames from "classnames"; @@ -27,6 +27,7 @@ import MemberAvatar from '../avatars/MemberAvatar'; import BaseAvatar from '../avatars/BaseAvatar'; import BaseDialog from "./BaseDialog"; import DialogButtons from "../elements/DialogButtons"; +import Field from '../elements/Field'; interface IProps { // matrix-js-sdk (room) member object. Supply either this or 'groupMember' @@ -48,6 +49,10 @@ interface IProps { onFinished: (success: boolean, reason?: string) => void; } +interface IState { + reason: string; +} + /* * A dialog for confirming an operation on another user. * Takes a user ID and a verb, displays the target user prominently @@ -57,37 +62,50 @@ interface IProps { * Also tweaks the style for 'dangerous' actions (albeit only with colour) */ @replaceableComponent("views.dialogs.ConfirmUserActionDialog") -export default class ConfirmUserActionDialog extends React.Component { - private reasonField: React.RefObject = React.createRef(); - +export default class ConfirmUserActionDialog extends React.Component { static defaultProps = { danger: false, askReason: false, }; - public onOk = (): void => { - this.props.onFinished(true, this.reasonField.current?.value); + constructor(props: IProps) { + super(props); + + this.state = { + reason: "", + }; + } + + private onOk = (): void => { + this.props.onFinished(true, this.state.reason); }; - public onCancel = (): void => { + private onCancel = (): void => { this.props.onFinished(false); }; + private onReasonChange = (ev: ChangeEvent) => { + this.setState({ + reason: ev.target.value, + }); + }; + public render() { const confirmButtonClass = this.props.danger ? 'danger' : ''; let reasonBox; if (this.props.askReason) { reasonBox = ( -
-
- -
-
+
+ + ); } From 886f8d31fb523a9b42db07fcaae03a7795c071c6 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 28 Sep 2021 16:23:42 +0100 Subject: [PATCH 038/143] Iterate title on confirm space action dialog --- src/components/views/right_panel/UserInfo.tsx | 34 +++++++++++++++++-- src/i18n/strings/en_EN.json | 10 ++++-- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/components/views/right_panel/UserInfo.tsx b/src/components/views/right_panel/UserInfo.tsx index 091581a6f8..605b47f027 100644 --- a/src/components/views/right_panel/UserInfo.tsx +++ b/src/components/views/right_panel/UserInfo.tsx @@ -541,6 +541,21 @@ const RoomKickButton = ({ room, member, startUpdating, stopUpdating }: Omit { + let title: string; + if (room.isSpaceRoom()) { + if (member.membership === "invite") { + title = _t("Disinvite this user from %(spaceName)s?", { spaceName: room.name }); + } else { + title = _t("Kick this user from %(spaceName)s?", { spaceName: room.name }); + } + } else { + if (member.membership === "invite") { + title = _t("Disinvite this user?"); + } else { + title = _t("Kick this user?"); + } + } + const { finished } = Modal.createTrackedDialog( 'Confirm User Action Dialog', 'onKick', @@ -548,7 +563,7 @@ const RoomKickButton = ({ room, member, startUpdating, stopUpdating }: Omit { + let title: string; + if (room.isSpaceRoom()) { + if (isBanned) { + title = _t("Unban this user from %(spaceName)s?", { spaceName: room.name }); + } else { + title = _t("Ban this user from %(spaceName)s?", { spaceName: room.name }); + } + } else { + if (isBanned) { + title = _t("Unban this user?"); + } else { + title = _t("Ban this user?"); + } + } + const { finished } = Modal.createTrackedDialog( 'Confirm User Action Dialog', 'onBanOrUnban', @@ -688,7 +718,7 @@ const BanToggleButton = ({ room, member, startUpdating, stopUpdating }: Omit, they'll still be able to access it after you kick them.": "If you're not an admin of a room or space in , they'll still be able to access it after you kick them.", @@ -1862,9 +1864,11 @@ "Remove %(count)s messages|other": "Remove %(count)s messages", "Remove %(count)s messages|one": "Remove 1 message", "Remove recent messages": "Remove recent messages", - "Ban": "Ban", + "Unban this user from %(spaceName)s?": "Unban this user from %(spaceName)s?", + "Ban this user from %(spaceName)s?": "Ban this user from %(spaceName)s?", "Unban this user?": "Unban this user?", "Ban this user?": "Ban this user?", + "Ban": "Ban", "Unban them from everything I'm able to": "Unban them from everything I'm able to", "Ban them from everything I'm able to": "Ban them from everything I'm able to", "Unban them from specific things I'm able to": "Unban them from specific things I'm able to", From e24924e3d6da7553b412a5746a327f3f42d77283 Mon Sep 17 00:00:00 2001 From: libexus Date: Tue, 28 Sep 2021 16:34:53 +0000 Subject: [PATCH 039/143] Translated using Weblate (German) Currently translated at 99.1% (3141 of 3168 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 | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 61f6239929..a85a662dd3 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -3134,5 +3134,26 @@ "Joining space …": "Space beitreten…", "To join a space you'll need an invite.": "Um einem Space beizutreten brauchst du eine Einladung.", "Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.": "In dieser Sitzung temporär Communities statt Spaces anzeigen. Unterstützung hierfür wird in naher Zukunft entfernt. Dies wird Element neu laden.", - "Display Communities instead of Spaces": "Communities statt Spaces anzeigen" + "Display Communities instead of Spaces": "Communities statt Spaces anzeigen", + "To join this Space, hide communities in your preferences": "Deaktiviere Communities in den Einstellungen, um diesen Space beizutreten.", + "To view this Space, hide communities in your preferences": "Deaktiviere Communities in den Einstellungen, um diesen Space anzuzeigen.", + "To join %(communityName)s, swap to communities in your preferences": "Um %(communityName)s beizutreten, aktiviere Communities in den Einstellungen", + "To view %(communityName)s, swap to communities in your preferences": "Um %(communityName)s anzuzeigen, aktiviere Communities in den Einstellungen", + "Private community": "Private Community", + "Public community": "Öffentliche Community", + "You are about to leave .": "Du bist dabei, zu verlassen.", + "Leave some rooms": "Zu verlassende Räume auswählen", + "Leave all rooms": "Alle Räume verlassen", + "Don't leave any rooms": "Räume nicht verlassen", + "%(reactors)s reacted with %(content)s": "%(reactors)s hat mit %(content)s reagiert", + "Some encryption parameters have been changed.": "Einige Verschlüsselungsoptionen wurden geändert.", + "Message": "Nachricht", + "Message didn't send. Click for info.": "Nachricht nicht gesendet. Klicke für Details.", + "To avoid these issues, create a new public room for the conversation you plan to have.": "Erstelle einen neuen Raum für deine Konversation, um diese Probleme zu umgehen.", + "It's not recommended to make encrypted rooms public. It will mean anyone can find and join the room, so anyone can read messages. You'll get none of the benefits of encryption. Encrypting messages in a public room will make receiving and sending messages slower.": "Es ist nicht sinnvoll, verschlüsselte Räume öffentlich zu machen. Da jeder den Raum betreten kann, kann auch jeder Nachrichten lesen, was die Verschlüsselung sinnlos macht. Außerdem wird das Senden und Empfangen von Nachrichten langsamer werden.", + "Select the roles required to change various parts of the space": "Wähle, von wem folgende Aktionen ausgeführt werden können", + "Upgrade anyway": "Trotzdem upgraden", + "This room is in some spaces you’re not an admin of. In those spaces, the old room will still be shown, but people will be prompted to join the new one.": "Dieser Raum ist in einigen Spaces, in denen du nicht Admin bist. Daher wird dort noch der alte Raum angezeigt, die Leute werden aber auf den neuen Raum hingewiesen.", + "Before you upgrade": "Bevor du upgradest", + "You can also make Spaces from communities.": "Du kannst Spaces auch aus Communities erstellen." } From d91116134d760e343dbc16ead403185739c25351 Mon Sep 17 00:00:00 2001 From: jelv Date: Tue, 28 Sep 2021 19:11:51 +0000 Subject: [PATCH 040/143] Translated using Weblate (Dutch) Currently translated at 100.0% (3168 of 3168 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 | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/i18n/strings/nl.json b/src/i18n/strings/nl.json index 950eaa68a2..cf289f40de 100644 --- a/src/i18n/strings/nl.json +++ b/src/i18n/strings/nl.json @@ -3035,7 +3035,7 @@ "Search for rooms or spaces": "Kamers of ruimtes zoeken", "Add space": "Ruimte toevoegen", "Leave %(spaceName)s": "%(spaceName)s verlaten", - "You're the only admin of some of the rooms or spaces you wish to leave. Leaving them will leave them without any admins.": "U bent de enige beheerder van sommige kamers of spaces die u wilt verlaten. Door deze te verlaten hebben ze geen beheerder meer.", + "You're the only admin of some of the rooms or spaces you wish to leave. Leaving them will leave them without any admins.": "U bent de enige beheerder van sommige kamers of ruimtes die u wilt verlaten. Door deze te verlaten hebben ze geen beheerder meer.", "You're the only admin of this space. Leaving it will mean no one has control over it.": "U bent de enige beheerder van deze ruimte. Door het te verlaten zal er niemand meer controle over hebben.", "You won't be able to rejoin unless you are re-invited.": "U kunt niet opnieuw deelnemen behalve als u opnieuw wordt uitgenodigd.", "Search %(spaceName)s": "Zoek %(spaceName)s", @@ -3094,7 +3094,7 @@ "A link to the Space will be put in your community description.": "In de gemeenschapsomschrijving zal een link naar deze ruimte worden geplaatst.", "Create Space from community": "Ruimte van gemeenschap maken", "Failed to migrate community": "Omzetten van de gemeenschap is mislukt", - "To create a Space from another community, just pick the community in Preferences.": "Om een Space te maken van een gemeenschap kiest u de gemeenschap in Instellingen.", + "To create a Space from another community, just pick the community in Preferences.": "Om een ruimte te maken van een gemeenschap kiest u de gemeenschap in Instellingen.", " has been made and everyone who was a part of the community has been invited to it.": " is gemaakt en iedereen die lid was van de gemeenschap is ervoor uitgenodigd.", "Space created": "Ruimte aangemaakt", "To view Spaces, hide communities in Preferences": "Om ruimtes te zien, verberg gemeenschappen in uw Instellingen", @@ -3164,5 +3164,7 @@ "You are about to leave .": "U staat op het punt te verlaten.", "Leave some rooms": "Sommige kamers verlaten", "Leave all rooms": "Alle kamers verlaten", - "Don't leave any rooms": "Geen kamers verlaten" + "Don't leave any rooms": "Geen kamers verlaten", + "Expand quotes │ ⇧+click": "Quotes uitvouwen │ ⇧+click", + "Collapse quotes │ ⇧+click": "Quotes invouwen │ ⇧+click" } From e135d0e0b362c8809aa20599e1ea94ecb0bb446d Mon Sep 17 00:00:00 2001 From: random Date: Tue, 28 Sep 2021 15:50:33 +0000 Subject: [PATCH 041/143] Translated using Weblate (Italian) Currently translated at 99.9% (3167 of 3168 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 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/it.json b/src/i18n/strings/it.json index 022149e3c6..b12554e256 100644 --- a/src/i18n/strings/it.json +++ b/src/i18n/strings/it.json @@ -3166,5 +3166,7 @@ "You are about to leave .": "Stai per uscire da .", "Leave some rooms": "Esci da alcune stanze", "Leave all rooms": "Esci da tutte le stanze", - "Don't leave any rooms": "Non uscire da alcuna stanza" + "Don't leave any rooms": "Non uscire da alcuna stanza", + "Expand quotes │ ⇧+click": "Espandi le menzioni │ ⇧+clic", + "Collapse quotes │ ⇧+click": "Riduci le menzioni │ ⇧+clic" } From c9915421f883b9829b0ebf67e0909ec579ad8d6c Mon Sep 17 00:00:00 2001 From: jelv Date: Wed, 29 Sep 2021 10:34:23 +0000 Subject: [PATCH 042/143] Translated using Weblate (Dutch) Currently translated at 100.0% (3168 of 3168 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 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/i18n/strings/nl.json b/src/i18n/strings/nl.json index cf289f40de..f13b8e77f9 100644 --- a/src/i18n/strings/nl.json +++ b/src/i18n/strings/nl.json @@ -902,7 +902,7 @@ "Select the roles required to change various parts of the room": "Selecteer de vereiste rollen om verschillende delen van het gesprek te wijzigen", "Enable encryption?": "Versleuteling inschakelen?", "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.": "Kamerversleuteling is onomkeerbaar. Berichten in versleutelde kamers zijn niet leesbaar voor de server; enkel voor de deelnemers. Veel robots en bruggen werken niet correct in versleutelde kamers. Lees meer over versleuteling.", - "Changes to who can read history will only apply to future messages in this room. The visibility of existing history will be unchanged.": "Wijzigingen aan wie de geschiedenis kan lezen gelden enkel voor toekomstige berichten in dit gesprek. De zichtbaarheid van de bestaande geschiedenis blijft ongewijzigd.", + "Changes to who can read history will only apply to future messages in this room. The visibility of existing history will be unchanged.": "Wijzigingen aan de leesregels van de geschiedenis gelden alleen voor toekomstige berichten in deze kamer. De zichtbaarheid van de bestaande geschiedenis blijft ongewijzigd.", "Encryption": "Versleuteling", "Once enabled, encryption cannot be disabled.": "Eenmaal ingeschakeld kan versleuteling niet meer worden uitgeschakeld.", "Encrypted": "Versleuteld", @@ -2977,7 +2977,7 @@ "Connection failed": "Verbinding mislukt", "Could not connect media": "Mediaverbinding mislukt", "Spaces with access": "Ruimtes met toegang", - "Anyone in a space can find and join. Edit which spaces can access here.": "Iedereen in een ruimte kan zoeken en deelnemen. Wijzig hier welke ruimtes toegang hebben.", + "Anyone in a space can find and join. Edit which spaces can access here.": "Iedereen in een ruimte kan hem vinden en deelnemen. Wijzig hier welke ruimtes toegang hebben.", "Currently, %(count)s spaces have access|other": "Momenteel hebben %(count)s ruimtes toegang", "& %(count)s more|other": "& %(count)s meer", "Upgrade required": "Upgrade noodzakelijk", @@ -2997,7 +2997,7 @@ "People with supported clients will be able to join the room without having a registered account.": "Personen met geschikte apps zullen aan de kamer kunnen deelnemen zonder een account te hebben.", "Decide who can join %(roomName)s.": "Kies wie kan deelnemen aan %(roomName)s.", "Space members": "Ruimte leden", - "Anyone in a space can find and join. You can select multiple spaces.": "Iedereen in een ruimte kan zoeken en deelnemen. U kunt meerdere ruimtes selecteren.", + "Anyone in a space can find and join. You can select multiple spaces.": "Iedereen in een ruimte kan hem vinden en deelnemen. U kunt meerdere ruimtes selecteren.", "Visible to space members": "Zichtbaar voor ruimte leden", "Public room": "Openbaar gesprek", "Private room (invite only)": "Privégesprek (alleen op uitnodiging)", @@ -3142,7 +3142,7 @@ "Change main address for the space": "Hoofdadres van ruimte wijzigen", "Change space name": "Ruimtenaam wijzigen", "Change space avatar": "Ruimte-afbeelding wijzigen", - "Anyone in can find and join. You can select other spaces too.": "Iedereen in kan zoeken en deelnemen. U kunt ook andere ruimtes selecteren.", + "Anyone in can find and join. You can select other spaces too.": "Iedereen in kan hem vinden en deelnemen. U kunt ook andere ruimtes selecteren.", "Message didn't send. Click for info.": "Bericht is niet verstuur. Klik voor meer info.", "To join %(communityName)s, swap to communities in your preferences": "Om aan %(communityName)s deel te nemen, wissel naar gemeenschappen in uw instellingen", "To view %(communityName)s, swap to communities in your preferences": "Om %(communityName)s te bekijken, wissel naar gemeenschappen in uw instellingen", From d6cab320e9b34f7a7eb9f0ea3a77fbbb7bd460e5 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 29 Sep 2021 14:04:02 +0100 Subject: [PATCH 043/143] Fix space invite edge cases --- src/components/structures/MatrixChat.tsx | 11 +++++++++-- src/components/structures/SpaceRoomView.tsx | 7 ++++--- src/components/views/rooms/MemberList.tsx | 7 ++++++- src/components/views/rooms/RoomList.tsx | 11 ++++++++--- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index b6d2e21918..8390f05b97 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -111,6 +111,7 @@ import { PosthogAnalytics } from '../../PosthogAnalytics'; import { initSentry } from "../../sentry"; import { logger } from "matrix-js-sdk/src/logger"; +import { showSpaceInvite } from "../../utils/space"; /** constants for MatrixChat.state.view */ export enum Views { @@ -741,9 +742,15 @@ export default class MatrixChat extends React.PureComponent { case 'view_create_chat': showStartChatInviteDialog(payload.initialText || ""); break; - case 'view_invite': - showRoomInviteDialog(payload.roomId); + case 'view_invite': { + const room = MatrixClientPeg.get().getRoom(payload.roomId); + if (room?.isSpaceRoom()) { + showSpaceInvite(room); + } else { + showRoomInviteDialog(payload.roomId); + } break; + } case 'view_last_screen': // This function does what we want, despite the name. The idea is that it shows // the last room we were looking at or some reasonable default/guess. We don't diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx index 270db21408..5f7a24f013 100644 --- a/src/components/structures/SpaceRoomView.tsx +++ b/src/components/structures/SpaceRoomView.tsx @@ -52,6 +52,7 @@ import { showAddExistingRooms, showCreateNewRoom, showCreateNewSubspace, + showSpaceInvite, showSpaceSettings, } from "../../utils/space"; import SpaceHierarchy, { showRoom } from "./SpaceHierarchy"; @@ -405,19 +406,19 @@ const SpaceLandingAddButton = ({ space }) => { ; }; -const SpaceLanding = ({ space }) => { +const SpaceLanding = ({ space }: { space: Room }) => { const cli = useContext(MatrixClientContext); const myMembership = useMyRoomMembership(space); const userId = cli.getUserId(); let inviteButton; - if (myMembership === "join" && space.canInvite(userId)) { + if ((myMembership === "join" && space.canInvite(userId)) || space.getJoinRule() === JoinRule.Public) { inviteButton = ( { - showRoomInviteDialog(space.roomId); + showSpaceInvite(space); }} > { _t("Invite") } diff --git a/src/components/views/rooms/MemberList.tsx b/src/components/views/rooms/MemberList.tsx index df4f2d21fa..593bbe472b 100644 --- a/src/components/views/rooms/MemberList.tsx +++ b/src/components/views/rooms/MemberList.tsx @@ -44,6 +44,7 @@ import MemberTile from "./MemberTile"; import BaseAvatar from '../avatars/BaseAvatar'; import { throttle } from 'lodash'; import SpaceStore from "../../../stores/SpaceStore"; +import { JoinRule } from "matrix-js-sdk/src/@types/partials"; const getSearchQueryLSKey = (roomId: string) => `mx_MemberList_searchQuarry_${roomId}`; @@ -169,7 +170,11 @@ export default class MemberList extends React.Component { private get canInvite(): boolean { const cli = MatrixClientPeg.get(); const room = cli.getRoom(this.props.roomId); - return room && room.canInvite(cli.getUserId()); + + return ( + room?.canInvite(cli.getUserId()) || + (room?.isSpaceRoom() && room.getJoinRule() === JoinRule.Public) + ); } private getMembersState(members: Array): IState { diff --git a/src/components/views/rooms/RoomList.tsx b/src/components/views/rooms/RoomList.tsx index 5ae2939c74..888ae93b1b 100644 --- a/src/components/views/rooms/RoomList.tsx +++ b/src/components/views/rooms/RoomList.tsx @@ -49,6 +49,7 @@ import { showAddExistingRooms, showCreateNewRoom, showSpaceInvite } from "../../ import { replaceableComponent } from "../../../utils/replaceableComponent"; import RoomAvatar from "../avatars/RoomAvatar"; import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; +import { JoinRule } from "matrix-js-sdk/src/@types/partials"; interface IProps { onKeyDown: (ev: React.KeyboardEvent) => void; @@ -521,19 +522,23 @@ export default class RoomList extends React.PureComponent {
; } else if ( - this.props.activeSpace?.canInvite(userId) || this.props.activeSpace?.getMyMembership() === "join" + this.props.activeSpace?.canInvite(userId) || + this.props.activeSpace?.getMyMembership() === "join" || + this.props.activeSpace?.getJoinRule() === JoinRule.Public ) { const spaceName = this.props.activeSpace.name; + const canInvite = this.props.activeSpace?.canInvite(userId) || + this.props.activeSpace?.getJoinRule() === JoinRule.Public; explorePrompt =
{ _t("Quick actions") }
- { this.props.activeSpace.canInvite(userId) && { _t("Invite people") } } - { this.props.activeSpace.getMyMembership() === "join" && Date: Wed, 29 Sep 2021 16:05:03 +0100 Subject: [PATCH 044/143] Update copy --- .../dialogs/ConfirmSpaceUserActionDialog.tsx | 11 +---- src/components/views/right_panel/UserInfo.tsx | 44 ++++--------------- src/i18n/strings/en_EN.json | 18 +++----- 3 files changed, 17 insertions(+), 56 deletions(-) diff --git a/src/components/views/dialogs/ConfirmSpaceUserActionDialog.tsx b/src/components/views/dialogs/ConfirmSpaceUserActionDialog.tsx index 9e014b86fd..1c5dd3fafa 100644 --- a/src/components/views/dialogs/ConfirmSpaceUserActionDialog.tsx +++ b/src/components/views/dialogs/ConfirmSpaceUserActionDialog.tsx @@ -15,11 +15,11 @@ limitations under the License. */ import React, { ComponentProps, useMemo, useState } from 'react'; + import ConfirmUserActionDialog from "./ConfirmUserActionDialog"; import SpaceStore from "../../../stores/SpaceStore"; import { Room } from "matrix-js-sdk/src/models/room"; import SpaceChildrenPicker from "../spaces/SpaceChildrenPicker"; -import { _t } from '../../../languageHandler'; type BaseProps = ComponentProps; interface IProps extends Omit { @@ -54,14 +54,7 @@ const ConfirmSpaceUserActionDialog: React.FC = ({ const selectedRooms = useMemo(() => new Set(roomsToLeave), [roomsToLeave]); let warning: JSX.Element; - if (!spaceChildren.length) { - warning =
- { _t("You’re not an admin of anything they’re a member of in , " + - "so banning won’t remove them from any rooms or spaces in .", {}, { - SpaceName: () => { space.name }, - }) } -
; - } else if (warningMessage) { + if (warningMessage) { warning =
{ warningMessage }
; diff --git a/src/components/views/right_panel/UserInfo.tsx b/src/components/views/right_panel/UserInfo.tsx index 605b47f027..edb78fc167 100644 --- a/src/components/views/right_panel/UserInfo.tsx +++ b/src/components/views/right_panel/UserInfo.tsx @@ -541,21 +541,6 @@ const RoomKickButton = ({ room, member, startUpdating, stopUpdating }: Omit { - let title: string; - if (room.isSpaceRoom()) { - if (member.membership === "invite") { - title = _t("Disinvite this user from %(spaceName)s?", { spaceName: room.name }); - } else { - title = _t("Kick this user from %(spaceName)s?", { spaceName: room.name }); - } - } else { - if (member.membership === "invite") { - title = _t("Disinvite this user?"); - } else { - title = _t("Kick this user?"); - } - } - const { finished } = Modal.createTrackedDialog( 'Confirm User Action Dialog', 'onKick', @@ -563,7 +548,9 @@ const RoomKickButton = ({ room, member, startUpdating, stopUpdating }: Omit, " + - "they'll still be able to access it after you kick them.", {}, { + "they'll still be able to access whatever you're not an admin of.", {}, { SpaceName: () => { room.name }, }), }, @@ -696,21 +683,6 @@ const BanToggleButton = ({ room, member, startUpdating, stopUpdating }: Omit { - let title: string; - if (room.isSpaceRoom()) { - if (isBanned) { - title = _t("Unban this user from %(spaceName)s?", { spaceName: room.name }); - } else { - title = _t("Ban this user from %(spaceName)s?", { spaceName: room.name }); - } - } else { - if (isBanned) { - title = _t("Unban this user?"); - } else { - title = _t("Ban this user?"); - } - } - const { finished } = Modal.createTrackedDialog( 'Confirm User Action Dialog', 'onBanOrUnban', @@ -718,7 +690,9 @@ const BanToggleButton = ({ room, member, startUpdating, stopUpdating }: Omit, " + - "they won’t be unbanned from it.", {}, { + "they still won't be able to access whatever you're not an admin of.", {}, { SpaceName: () => { room.name }, }) : _t("If you're not an admin of a room or space in , " + - "they'll still be able to access it after you ban them.", {}, { + "they'll still be able to access whatever you're not an admin of.", {}, { SpaceName: () => { room.name }, }), }, diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index e986139eb8..07757b9c8b 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1845,15 +1845,13 @@ "You will not be able to undo this change as you are demoting yourself, if you are the last privileged user in the space it will be impossible to regain privileges.": "You will not be able to undo this change as you are demoting yourself, if you are the last privileged user in the space it will be impossible to regain privileges.", "You will not be able to undo this change as you are demoting yourself, if you are the last privileged user in the room it will be impossible to regain privileges.": "You will not be able to undo this change as you are demoting yourself, if you are the last privileged user in the room it will be impossible to regain privileges.", "Demote": "Demote", - "Disinvite this user from %(spaceName)s?": "Disinvite this user from %(spaceName)s?", - "Kick this user from %(spaceName)s?": "Kick this user from %(spaceName)s?", - "Disinvite this user?": "Disinvite this user?", - "Kick this user?": "Kick this user?", "Disinvite": "Disinvite", "Kick": "Kick", + "Disinvite from %(roomName)s": "Disinvite from %(roomName)s", + "Kick from %(roomName)s": "Kick from %(roomName)s", "Kick them from everything I'm able to": "Kick them from everything I'm able to", "Kick them from specific things I'm able to": "Kick them from specific things I'm able to", - "If you're not an admin of a room or space in , they'll still be able to access it after you kick them.": "If you're not an admin of a room or space in , they'll still be able to access it after you kick them.", + "If you're not an admin of a room or space in , they'll still be able to access whatever you're not an admin of.": "If you're not an admin of a room or space in , they'll still be able to access whatever you're not an admin of.", "Failed to kick": "Failed to kick", "No recent messages by %(user)s found": "No recent messages by %(user)s found", "Try scrolling up in the timeline to see if there are any earlier ones.": "Try scrolling up in the timeline to see if there are any earlier ones.", @@ -1864,17 +1862,14 @@ "Remove %(count)s messages|other": "Remove %(count)s messages", "Remove %(count)s messages|one": "Remove 1 message", "Remove recent messages": "Remove recent messages", - "Unban this user from %(spaceName)s?": "Unban this user from %(spaceName)s?", - "Ban this user from %(spaceName)s?": "Ban this user from %(spaceName)s?", - "Unban this user?": "Unban this user?", - "Ban this user?": "Ban this user?", "Ban": "Ban", + "Unban from %(roomName)s": "Unban from %(roomName)s", + "Ban from %(roomName)s": "Ban from %(roomName)s", "Unban them from everything I'm able to": "Unban them from everything I'm able to", "Ban them from everything I'm able to": "Ban them from everything I'm able to", "Unban them from specific things I'm able to": "Unban them from specific things I'm able to", "Ban them from specific things I'm able to": "Ban them from specific things I'm able to", - "If you’re not an admin of a room or space in , they won’t be unbanned from it.": "If you’re not an admin of a room or space in , they won’t be unbanned from it.", - "If you're not an admin of a room or space in , they'll still be able to access it after you ban them.": "If you're not an admin of a room or space in , they'll still be able to access it after you ban them.", + "If you’re not an admin of a room or space in , they still won't be able to access whatever you're not an admin of.": "If you’re not an admin of a room or space in , they still won't be able to access whatever you're not an admin of.", "Failed to ban user": "Failed to ban user", "Failed to mute user": "Failed to mute user", "Unmute": "Unmute", @@ -2233,7 +2228,6 @@ "Confirm Removal": "Confirm Removal", "Are you sure you wish to remove (delete) this event? Note that if you delete a room name or topic change, it could undo the change.": "Are you sure you wish to remove (delete) this event? Note that if you delete a room name or topic change, it could undo the change.", "Reason (optional)": "Reason (optional)", - "You’re not an admin of anything they’re a member of in , so banning won’t remove them from any rooms or spaces in .": "You’re not an admin of anything they’re a member of in , so banning won’t remove them from any rooms or spaces in .", "Clear all data in this session?": "Clear all data in this session?", "Clearing all data from this session is permanent. Encrypted messages will be lost unless their keys have been backed up.": "Clearing all data from this session is permanent. Encrypted messages will be lost unless their keys have been backed up.", "Clear all data": "Clear all data", From 71851d80758c76c0cbfe33ecb2e256f0f116bc6b Mon Sep 17 00:00:00 2001 From: Andrew Ferrazzutti Date: Wed, 29 Sep 2021 19:00:14 -0400 Subject: [PATCH 045/143] Check error message for room publish failure Signed-off-by: Andrew Ferrazzutti --- src/createRoom.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/createRoom.ts b/src/createRoom.ts index 746fd63815..0d8172c558 100644 --- a/src/createRoom.ts +++ b/src/createRoom.ts @@ -222,7 +222,7 @@ export default async function createRoom(opts: IOpts): Promise { return client.createRoom(createOpts).finally(function() { if (modal) modal.close(); }).catch(function(err) { - if (err.httpStatus === 403 && err.errcode == "M_UNKNOWN") { + if (err.httpStatus === 403 && err.errcode === "M_UNKNOWN" && err.data.error === "Not allowed to publish room") { console.warn("Failed to publish room, try again without publishing it"); createOpts.visibility = Visibility.Private; return client.createRoom(createOpts); From 6454aa7a95ec4d387b3bd84aa6d3ac98ca80b073 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 30 Sep 2021 11:46:05 +0100 Subject: [PATCH 046/143] Update copy --- src/components/views/right_panel/UserInfo.tsx | 15 +++------------ src/i18n/strings/en_EN.json | 4 ++-- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/src/components/views/right_panel/UserInfo.tsx b/src/components/views/right_panel/UserInfo.tsx index edb78fc167..ee81664a47 100644 --- a/src/components/views/right_panel/UserInfo.tsx +++ b/src/components/views/right_panel/UserInfo.tsx @@ -565,10 +565,7 @@ const RoomKickButton = ({ room, member, startUpdating, stopUpdating }: Omit, " + - "they'll still be able to access whatever you're not an admin of.", {}, { - SpaceName: () => { room.name }, - }), + warningMessage: _t("They'll still be able to access whatever you're not an admin of."), }, room.isSpaceRoom() ? "mx_ConfirmSpaceUserActionDialog_wrapper" : undefined, ); @@ -721,14 +718,8 @@ const BanToggleButton = ({ room, member, startUpdating, stopUpdating }: Omit, " + - "they still won't be able to access whatever you're not an admin of.", {}, { - SpaceName: () => { room.name }, - }) - : _t("If you're not an admin of a room or space in , " + - "they'll still be able to access whatever you're not an admin of.", {}, { - SpaceName: () => { room.name }, - }), + ? _t("They won't be able to access whatever you're not an admin of.") + : _t("They'll still be able to access whatever you're not an admin of."), }, room.isSpaceRoom() ? "mx_ConfirmSpaceUserActionDialog_wrapper" : undefined, ); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 07757b9c8b..01189adbe1 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1851,7 +1851,7 @@ "Kick from %(roomName)s": "Kick from %(roomName)s", "Kick them from everything I'm able to": "Kick them from everything I'm able to", "Kick them from specific things I'm able to": "Kick them from specific things I'm able to", - "If you're not an admin of a room or space in , they'll still be able to access whatever you're not an admin of.": "If you're not an admin of a room or space in , they'll still be able to access whatever you're not an admin of.", + "They'll still be able to access whatever you're not an admin of.": "They'll still be able to access whatever you're not an admin of.", "Failed to kick": "Failed to kick", "No recent messages by %(user)s found": "No recent messages by %(user)s found", "Try scrolling up in the timeline to see if there are any earlier ones.": "Try scrolling up in the timeline to see if there are any earlier ones.", @@ -1869,7 +1869,7 @@ "Ban them from everything I'm able to": "Ban them from everything I'm able to", "Unban them from specific things I'm able to": "Unban them from specific things I'm able to", "Ban them from specific things I'm able to": "Ban them from specific things I'm able to", - "If you’re not an admin of a room or space in , they still won't be able to access whatever you're not an admin of.": "If you’re not an admin of a room or space in , they still won't be able to access whatever you're not an admin of.", + "They won't be able to access whatever you're not an admin of.": "They won't be able to access whatever you're not an admin of.", "Failed to ban user": "Failed to ban user", "Failed to mute user": "Failed to mute user", "Unmute": "Unmute", From d068cee54c808d6a7826808810b8ee0dc10eeea7 Mon Sep 17 00:00:00 2001 From: Ihor Hordiichuk Date: Thu, 30 Sep 2021 02:48:53 +0000 Subject: [PATCH 047/143] Translated using Weblate (Ukrainian) Currently translated at 66.6% (2108 of 3163 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/uk/ --- src/i18n/strings/uk.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/uk.json b/src/i18n/strings/uk.json index cccfb83610..896431d3e6 100644 --- a/src/i18n/strings/uk.json +++ b/src/i18n/strings/uk.json @@ -42,7 +42,7 @@ "Anyone": "Кожний", "Are you sure?": "Ви впевнені?", "Are you sure you want to leave the room '%(roomName)s'?": "Ви впевнені, що хочете вийти з «%(roomName)s»?", - "Are you sure you want to reject the invitation?": "Ви впевнені, що ви хочете відхилити запрошення?", + "Are you sure you want to reject the invitation?": "Ви впевнені, що хочете відхилити запрошення?", "Attachment": "Прикріплення", "Ban": "Заблокувати", "Banned users": "Заблоковані користувачі", From c81c01978e7141efb296be6d3458a9d80e5a112b Mon Sep 17 00:00:00 2001 From: waclaw66 Date: Thu, 30 Sep 2021 07:55:30 +0000 Subject: [PATCH 048/143] Translated using Weblate (Czech) Currently translated at 100.0% (3163 of 3163 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 be6a78588b..64a0306ab3 100644 --- a/src/i18n/strings/cs.json +++ b/src/i18n/strings/cs.json @@ -3158,7 +3158,7 @@ "This room is in some spaces you’re not an admin of. In those spaces, the old room will still be shown, but people will be prompted to join the new one.": "Tato místnost se nachází v některých prostorech, jejichž nejste správcem. V těchto prostorech bude stará místnost stále zobrazena, ale lidé budou vyzváni, aby se připojili k nové místnosti.", "Before you upgrade": "Než provedete aktualizaci", "To join a space you'll need an invite.": "Pro připojení k prostoru potřebujete pozvánku.", - "You can also make Spaces from communities.": "Můžete také vytvořit prostory ze skupin.", + "You can also make Spaces from communities.": "Prostory můžete vytvořit také ze skupin.", "Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.": "Dočasně zobrazit skupiny místo prostorů pro tuto relaci. Podpora bude v blízké budoucnosti odstraněna. Toto provede přenačtení Elementu.", "Display Communities instead of Spaces": "Zobrazit skupiny místo prostorů", "Joining space …": "Připojování k prostoru…", From 8ac77c498f76f871648aad0a4c4589a5a61fc1ed Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 30 Sep 2021 13:43:59 +0100 Subject: [PATCH 049/143] Add progress bar to Community to Space migration tool and invite-one-by-one to workaround Synapse ratelimits --- .../dialogs/_AddExistingToSpaceDialog.scss | 2 +- .../_CreateSpaceFromCommunityDialog.scss | 1 + src/RoomInvite.tsx | 13 ++-- .../CreateSpaceFromCommunityDialog.tsx | 71 ++++++++++++++++--- src/i18n/strings/en_EN.json | 2 + src/utils/MultiInviter.ts | 4 +- 6 files changed, 78 insertions(+), 15 deletions(-) diff --git a/res/css/views/dialogs/_AddExistingToSpaceDialog.scss b/res/css/views/dialogs/_AddExistingToSpaceDialog.scss index 444b29c9bf..8b19f506f5 100644 --- a/res/css/views/dialogs/_AddExistingToSpaceDialog.scss +++ b/res/css/views/dialogs/_AddExistingToSpaceDialog.scss @@ -75,7 +75,7 @@ limitations under the License. @mixin ProgressBarBorderRadius 8px; } - .mx_AddExistingToSpace_progressText { + .mx_AddExistingToSpaceDialog_progressText { margin-top: 8px; font-size: $font-15px; line-height: $font-24px; diff --git a/res/css/views/dialogs/_CreateSpaceFromCommunityDialog.scss b/res/css/views/dialogs/_CreateSpaceFromCommunityDialog.scss index 6ff328f6ab..f1af24cc5f 100644 --- a/res/css/views/dialogs/_CreateSpaceFromCommunityDialog.scss +++ b/res/css/views/dialogs/_CreateSpaceFromCommunityDialog.scss @@ -74,6 +74,7 @@ limitations under the License. font-size: $font-12px; line-height: $font-15px; color: $secondary-content; + margin-top: -13px; // match height of buttons to prevent height changing .mx_ProgressBar { height: 8px; diff --git a/src/RoomInvite.tsx b/src/RoomInvite.tsx index 7d093f4092..5c9d96f509 100644 --- a/src/RoomInvite.tsx +++ b/src/RoomInvite.tsx @@ -42,10 +42,15 @@ export interface IInviteResult { * * @param {string} roomId The ID of the room to invite to * @param {string[]} addresses Array of strings of addresses to invite. May be matrix IDs or 3pids. + * @param {function} progressCallback optional callback, fired after each invite. * @returns {Promise} Promise */ -export function inviteMultipleToRoom(roomId: string, addresses: string[]): Promise { - const inviter = new MultiInviter(roomId); +export function inviteMultipleToRoom( + roomId: string, + addresses: string[], + progressCallback?: () => void, +): Promise { + const inviter = new MultiInviter(roomId, progressCallback); return inviter.invite(addresses).then(states => Promise.resolve({ states, inviter })); } @@ -104,8 +109,8 @@ export function isValid3pidInvite(event: MatrixEvent): boolean { return true; } -export function inviteUsersToRoom(roomId: string, userIds: string[]): Promise { - return inviteMultipleToRoom(roomId, userIds).then((result) => { +export function inviteUsersToRoom(roomId: string, userIds: string[], progressCallback?: () => void): Promise { + return inviteMultipleToRoom(roomId, userIds, progressCallback).then((result) => { const room = MatrixClientPeg.get().getRoom(roomId); showAnyInviteErrors(result.states, room, result.inviter); }).catch((err) => { diff --git a/src/components/views/dialogs/CreateSpaceFromCommunityDialog.tsx b/src/components/views/dialogs/CreateSpaceFromCommunityDialog.tsx index e74082427f..c7706c115c 100644 --- a/src/components/views/dialogs/CreateSpaceFromCommunityDialog.tsx +++ b/src/components/views/dialogs/CreateSpaceFromCommunityDialog.tsx @@ -39,6 +39,8 @@ import dis from "../../../dispatcher/dispatcher"; import { Action } from "../../../dispatcher/actions"; import { UserTab } from "./UserSettingsDialog"; import TagOrderActions from "../../../actions/TagOrderActions"; +import { inviteUsersToRoom } from "../../../RoomInvite"; +import ProgressBar from "../elements/ProgressBar"; interface IProps { matrixClient: MatrixClient; @@ -90,10 +92,22 @@ export interface IGroupSummary { } /* eslint-enable camelcase */ +enum Progress { + NotStarted, + ValidatingInputs, + FetchingData, + CreatingSpace, + InvitingUsers, + // anything beyond here is inviting user n - 4 +} + const CreateSpaceFromCommunityDialog: React.FC = ({ matrixClient: cli, groupId, onFinished }) => { const [loading, setLoading] = useState(true); const [error, setError] = useState(null); - const [busy, setBusy] = useState(false); + + const [progress, setProgress] = useState(Progress.NotStarted); + const [numInvites, setNumInvites] = useState(0); + const busy = progress > 0; const [avatar, setAvatar] = useState(null); // undefined means to remove avatar const [name, setName] = useState(""); @@ -122,30 +136,34 @@ const CreateSpaceFromCommunityDialog: React.FC = ({ matrixClient: cli, g if (busy) return; setError(null); - setBusy(true); + setProgress(Progress.ValidatingInputs); // require & validate the space name field if (!(await spaceNameField.current.validate({ allowEmpty: false }))) { - setBusy(false); + setProgress(0); spaceNameField.current.focus(); spaceNameField.current.validate({ allowEmpty: false, focused: true }); return; } // validate the space name alias field but do not require it if (joinRule === JoinRule.Public && !(await spaceAliasField.current.validate({ allowEmpty: true }))) { - setBusy(false); + setProgress(0); spaceAliasField.current.focus(); spaceAliasField.current.validate({ allowEmpty: true, focused: true }); return; } try { + setProgress(Progress.FetchingData); + const [rooms, members, invitedMembers] = await Promise.all([ cli.getGroupRooms(groupId).then(parseRoomsResponse) as Promise, cli.getGroupUsers(groupId).then(parseMembersResponse) as Promise, cli.getGroupInvitedUsers(groupId).then(parseMembersResponse) as Promise, ]); + setNumInvites(members.length + invitedMembers.length); + const viaMap = new Map(); for (const { roomId, canonicalAlias } of rooms) { const room = cli.getRoom(roomId); @@ -167,6 +185,8 @@ const CreateSpaceFromCommunityDialog: React.FC = ({ matrixClient: cli, g } } + setProgress(Progress.CreatingSpace); + const spaceAvatar = avatar !== undefined ? avatar : groupSummary.profile.avatar_url; const roomId = await createSpace(name, joinRule === JoinRule.Public, alias, topic, spaceAvatar, { creation_content: { @@ -179,11 +199,16 @@ const CreateSpaceFromCommunityDialog: React.FC = ({ matrixClient: cli, g via: viaMap.get(roomId) || [], }, })), - invite: [...members, ...invitedMembers].map(m => m.userId).filter(m => m !== cli.getUserId()), + // we do not specify the inviters here because Synapse applies a limit and this may cause it to trip }, { andView: false, }); + setProgress(Progress.InvitingUsers); + + const userIds = [...members, ...invitedMembers].map(m => m.userId).filter(m => m !== cli.getUserId()); + await inviteUsersToRoom(roomId, userIds, () => setProgress(p => p + 1)); + // eagerly remove it from the community panel dis.dispatch(TagOrderActions.removeTag(cli, groupId)); @@ -250,7 +275,7 @@ const CreateSpaceFromCommunityDialog: React.FC = ({ matrixClient: cli, g setError(e); } - setBusy(false); + setProgress(Progress.NotStarted); }; let footer; @@ -267,13 +292,41 @@ const CreateSpaceFromCommunityDialog: React.FC = ({ matrixClient: cli, g { _t("Retry") } ; + } else if (busy) { + let description: string; + switch (progress) { + case Progress.ValidatingInputs: + case Progress.FetchingData: + description = _t("Fetching data..."); + break; + case Progress.CreatingSpace: + description = _t("Creating Space..."); + break; + case Progress.InvitingUsers: + default: + description = _t("Adding rooms... (%(progress)s out of %(count)s)", { + count: numInvites, + progress, + }); + break; + } + + footer = + Progress.FetchingData ? progress : 0} + max={numInvites + Progress.InvitingUsers} + /> +
+ { description } +
+
; } else { footer = <> - onFinished()}> + onFinished()}> { _t("Cancel") } - - { busy ? _t("Creating...") : _t("Create Space") } + + { _t("Create Space") } ; } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 9f245b8dab..8fc5fd0afd 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2280,6 +2280,8 @@ " has been made and everyone who was a part of the community has been invited to it.": " has been made and everyone who was a part of the community has been invited to it.", "To create a Space from another community, just pick the community in Preferences.": "To create a Space from another community, just pick the community in Preferences.", "Failed to migrate community": "Failed to migrate community", + "Fetching data...": "Fetching data...", + "Creating Space...": "Creating Space...", "Create Space from community": "Create Space from community", "A link to the Space will be put in your community description.": "A link to the Space will be put in your community description.", "All rooms will be added and all community members will be invited.": "All rooms will be added and all community members will be invited.", diff --git a/src/utils/MultiInviter.ts b/src/utils/MultiInviter.ts index 5b79a2ff93..abf72c97ff 100644 --- a/src/utils/MultiInviter.ts +++ b/src/utils/MultiInviter.ts @@ -62,8 +62,9 @@ export default class MultiInviter { /** * @param {string} targetId The ID of the room or group to invite to + * @param {function} progressCallback optional callback, fired after each invite. */ - constructor(targetId: string) { + constructor(targetId: string, private readonly progressCallback?: () => void) { if (targetId[0] === '+') { this.roomId = null; this.groupId = targetId; @@ -181,6 +182,7 @@ export default class MultiInviter { delete this.errors[address]; resolve(); + this.progressCallback?.(); }).catch((err) => { if (this.canceled) { return; From 6268f5deb0d95604972a586c6accd16cab9fc7b8 Mon Sep 17 00:00:00 2001 From: Szimszon Date: Thu, 30 Sep 2021 14:27:54 +0000 Subject: [PATCH 050/143] Translated using Weblate (Hungarian) Currently translated at 99.7% (3191 of 3198 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 | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/hu.json b/src/i18n/strings/hu.json index 4957bc6efa..c561759db9 100644 --- a/src/i18n/strings/hu.json +++ b/src/i18n/strings/hu.json @@ -3166,5 +3166,33 @@ "Leave all rooms": "Kilépés minden szobából", "Don't leave any rooms": "Ne lépjen ki egy szobából sem", "Expand quotes │ ⇧+click": "Idézetek megnyitása │ ⇧+kattintás", - "Collapse quotes │ ⇧+click": "Idézetek bezárása│ ⇧+kattintás" + "Collapse quotes │ ⇧+click": "Idézetek bezárása│ ⇧+kattintás", + "Include Attachments": "Csatolmányokkal együtt", + "Size Limit": "Méret korlát", + "Format": "Formátum", + "Export Chat": "Beszélgetés kimentése", + "Exporting your data": "Adatai kimentése", + "Stop": "Állj", + "The export was cancelled successfully": "Az exportálás sikeresen félbeszakítva", + "Export Successful": "Exportálás sikeres", + "MB": "MB", + "Number of messages": "Üzenetek száma", + "In reply to this message": "Válasz erre az üzenetre", + "Export chat": "Beszélgetés kimentése", + "File Attached": "Fájl csatolva", + "Error fetching file": "Fájl letöltés hiba", + "Topic: %(topic)s": "Téma: %(topic)s", + "%(creatorName)s created this room.": "%(creatorName)s hozta létre ezt a szobát.", + "Media omitted - file size limit exceeded": "Média fájl kihagyva - fájl méret korlát túllépés", + "Media omitted": "Média nélkül", + "Current Timeline": "Aktuális idővonal", + "Specify a number of messages": "Üzenetek számának megadása", + "From the beginning": "Az elejétől", + "Plain Text": "Sima szöveg", + "JSON": "JSON", + "HTML": "HTML", + "Are you sure you want to exit during this export?": "Biztos, hogy kilép az exportálás közben?", + "%(senderDisplayName)s sent a sticker.": "%(senderDisplayName)s matricát küldött.", + "%(senderDisplayName)s changed the room avatar.": "%(senderDisplayName)s megváltoztatta a szoba avatar képét.", + "%(date)s at %(time)s": "%(date)s %(time)s" } From 32c4ae53ebfa4ec1523643ca906ab0e990ff5de1 Mon Sep 17 00:00:00 2001 From: sr093906 Date: Thu, 30 Sep 2021 13:01:02 +0000 Subject: [PATCH 051/143] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (3198 of 3198 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/zh_Hans/ --- src/i18n/strings/zh_Hans.json | 37 ++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/zh_Hans.json b/src/i18n/strings/zh_Hans.json index 62e24c3091..7084e9f649 100644 --- a/src/i18n/strings/zh_Hans.json +++ b/src/i18n/strings/zh_Hans.json @@ -3166,5 +3166,40 @@ "Leave all rooms": "离开所有聊天室", "Don't leave any rooms": "不离开任何聊天室", "Collapse quotes │ ⇧+click": "折叠引号│ ⇧+click", - "Expand quotes │ ⇧+click": "展开引号│ ⇧+click" + "Expand quotes │ ⇧+click": "展开引号│ ⇧+click", + "Number of messages can only be a number between %(min)s and %(max)s": "消息数只能是一个介于 %(min)s 和 %(max)s 之间的整数", + "Include Attachments": "包括附件", + "Size Limit": "大小限制", + "Format": "格式", + "Select from the options below to export chats from your timeline": "从下面的选项中选择以从时间轴导出聊天记录", + "Export Chat": "导出聊天", + "Exporting your data": "导出你的数据", + "Stop": "停止", + "Are you sure you want to stop exporting your data? If you do, you'll need to start over.": "您确定要停止导出数据吗?如果你这样做了,你需要重新开始。", + "Your export was successful. Find it in your Downloads folder.": "导出成功了。你可以在下载文件夹中找到导出文件。", + "The export was cancelled successfully": "成功取消了导出", + "Export Successful": "成功导出", + "MB": "MB", + "Number of messages": "消息数", + "Size can only be a number between %(min)s MB and %(max)s MB": "大小只能是 %(min)sMB 和 %(max)sMB 之间的一个数字", + "Enter a number between %(min)s and %(max)s": "输入一个 %(min)s 和 %(max)s 之间的数字", + "In reply to this message": "回复此消息", + "Export chat": "导出聊天", + "File Attached": "已附加文件", + "Error fetching file": "获取文件出错", + "Topic: %(topic)s": "话题:%(topic)s", + "This is the start of export of . Exported by at %(exportDate)s.": "这是 导出的开始。导出人 ,导出日期 %(exportDate)s。", + "%(creatorName)s created this room.": "%(creatorName)s 创建了此聊天室。", + "Media omitted - file size limit exceeded": "省略了媒体文件 - 超出了文件大小限制", + "Media omitted": "省略了媒体文件", + "Current Timeline": "当前时间线", + "Specify a number of messages": "指定消息数", + "From the beginning": "从开头", + "Plain Text": "纯文本", + "JSON": "JSON", + "HTML": "HTML", + "Are you sure you want to exit during this export?": "您确定要在导出未完成时退出吗?", + "%(senderDisplayName)s sent a sticker.": "%(senderDisplayName)s 发送了一张贴纸。", + "%(senderDisplayName)s changed the room avatar.": "%(senderDisplayName)s 更改了聊天室头像。", + "%(date)s at %(time)s": "%(date)s 的 %(time)s" } From 140d11f959a12f47939807c7110e391170cab64a Mon Sep 17 00:00:00 2001 From: waclaw66 Date: Thu, 30 Sep 2021 12:29:06 +0000 Subject: [PATCH 052/143] Translated using Weblate (Czech) Currently translated at 100.0% (3198 of 3198 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 64a0306ab3..2b225077d8 100644 --- a/src/i18n/strings/cs.json +++ b/src/i18n/strings/cs.json @@ -3169,5 +3169,40 @@ "Don't leave any rooms": "Neodcházet z žádné místnosti", "Leave all rooms": "Odejít ze všech místností", "Expand quotes │ ⇧+click": "Rozbalit uvozovky │ ⇧+kliknutí", - "Collapse quotes │ ⇧+click": "Sbalit uvozovky │ ⇧+kliknutí" + "Collapse quotes │ ⇧+click": "Sbalit uvozovky │ ⇧+kliknutí", + "Include Attachments": "Zahrnout přílohy", + "Size Limit": "Omezení velikosti", + "Format": "Formát", + "Select from the options below to export chats from your timeline": "Vyberte jednu z níže uvedených možností pro export chatů z časové osy", + "Export Chat": "Exportovat chat", + "Exporting your data": "Exportování dat", + "Stop": "Zastavit", + "Are you sure you want to stop exporting your data? If you do, you'll need to start over.": "Opravdu chcete ukončit export dat? Pokud ano, budete muset začít znovu.", + "Your export was successful. Find it in your Downloads folder.": "Váš export proběhl úspěšně. Najdete jej ve složce pro stažené soubory.", + "The export was cancelled successfully": "Export byl úspěšně zrušen", + "Export Successful": "Export proběhl úspěšně", + "MB": "MB", + "Number of messages": "Počet zpráv", + "Number of messages can only be a number between %(min)s and %(max)s": "Počet zpráv může být pouze číslo mezi %(min)s a %(max)s", + "Size can only be a number between %(min)s MB and %(max)s MB": "Velikost může být pouze číslo mezi %(min)s MB a %(max)s MB", + "Enter a number between %(min)s and %(max)s": "Zadejte číslo mezi %(min)s a %(max)s", + "In reply to this message": "V odpovědi na tuto zprávu", + "Export chat": "Exportovat chat", + "File Attached": "Přiložený soubor", + "Error fetching file": "Chyba při načítání souboru", + "Topic: %(topic)s": "Téma: %(topic)s", + "This is the start of export of . Exported by at %(exportDate)s.": "Toto je začátek exportu . Exportováno pomocí v %(exportDate)s.", + "%(creatorName)s created this room.": "%(creatorName)s vytvořil(a) tuto místnost.", + "Media omitted - file size limit exceeded": "Vynechaná média - překročen limit velikosti souboru", + "Media omitted": "Vynechaná média", + "Current Timeline": "Aktuální časová osa", + "Specify a number of messages": "Zadejte počet zpráv", + "From the beginning": "Od začátku", + "Plain Text": "Prostý text", + "JSON": "JSON", + "HTML": "HTML", + "Are you sure you want to exit during this export?": "Opravdu chcete skončit během tohoto exportu?", + "%(senderDisplayName)s sent a sticker.": "%(senderDisplayName)s poslal(a) nálepku.", + "%(senderDisplayName)s changed the room avatar.": "%(senderDisplayName)s změnil(a) avatar místnosti.", + "%(date)s at %(time)s": "%(date)s v %(time)s" } From 1ddee2f85526d85225fc23cc133c09c10f309079 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Thu, 30 Sep 2021 16:16:35 +0000 Subject: [PATCH 053/143] Translated using Weblate (Estonian) Currently translated at 99.9% (3197 of 3198 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 | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index 81e8fc3b6c..9fa345f435 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -3165,5 +3165,40 @@ "Leave all rooms": "Lahku kõikidest jututubadest", "Don't leave any rooms": "Ära lahku ühestki jututoast", "Expand quotes │ ⇧+click": "Näita tsitaate │ ⇧+click", - "Collapse quotes │ ⇧+click": "Ahenda tsitaadid │ ⇧+click" + "Collapse quotes │ ⇧+click": "Ahenda tsitaadid │ ⇧+click", + "Media omitted": "Osa meediat jäi eksportimata", + "Media omitted - file size limit exceeded": "Osa meediat jäi vahele failisuuruse piirangu tõttu", + "Include Attachments": "Kaasa manused", + "Size Limit": "Andmemahu piir", + "Format": "Vorming", + "Select from the options below to export chats from your timeline": "Kui soovid oma ajajoonelt mõnda vestlust eksportida, siis vali tingimused alljärgnevalt", + "Export Chat": "Ekspordi vestlus", + "Exporting your data": "Ekspordin sinu andmeid", + "Stop": "Peata", + "Are you sure you want to stop exporting your data? If you do, you'll need to start over.": "Kas sa oled kindel, et soovid oma andmete eksporti katkestada? Kui nii toimid, siis pead hiljem uuesti alustama.", + "Your export was successful. Find it in your Downloads folder.": "Sinu andmete eksport õnnestus. Faili leiad tavapärasest allalaadimiste kaustast.", + "The export was cancelled successfully": "Ekspordi tühistamine õnnestus", + "Export Successful": "Eksport õnnestus", + "MB": "MB", + "Number of messages": "Sõnumite arv", + "Number of messages can only be a number between %(min)s and %(max)s": "Sõnumite arv saab olla ainult number%(min)s ja %(max)s vahemikust", + "Size can only be a number between %(min)s MB and %(max)s MB": "Suurus saab olla number %(min)s MB ja %(max)s MB vahemikust", + "Enter a number between %(min)s and %(max)s": "Sisesta number %(min)s ja %(max)s vahemikust", + "In reply to this message": "Vastuseks sellele sõnumile", + "Export chat": "Ekspordi vestlus", + "File Attached": "Fail on manustatud", + "Error fetching file": "Viga faili laadimisel", + "Topic: %(topic)s": "Teema: %(topic)s", + "This is the start of export of . Exported by at %(exportDate)s.": "See on jututoast eksporditud andmekogu. Viited: , %(exportDate)s.", + "%(creatorName)s created this room.": "%(creatorName)s lõi selle jututoa.", + "Current Timeline": "Praegune ajajoon", + "Specify a number of messages": "Määra sõnumite arv", + "From the beginning": "Algusest alates", + "Plain Text": "Vormindamata tekst", + "JSON": "JSON", + "HTML": "HTML", + "Are you sure you want to exit during this export?": "Kas sa oled kindel, et soovid lõpetada tegevuse selle ekspordi ajal?", + "%(senderDisplayName)s sent a sticker.": "%(senderDisplayName)s saatis kleepsu.", + "%(senderDisplayName)s changed the room avatar.": "%(senderDisplayName)s muutis jututoa tunnuspilti.", + "%(date)s at %(time)s": "%(date)s %(time)s" } From 017b2e0444210f1d47e0720af8b21805a62b7454 Mon Sep 17 00:00:00 2001 From: Andrew Ferrazzutti Date: Fri, 1 Oct 2021 01:42:25 -0400 Subject: [PATCH 054/143] Comment that the room publish failure check is Synapse-specific Signed-off-by: Andrew Ferrazzutti --- src/createRoom.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/createRoom.ts b/src/createRoom.ts index 0d8172c558..7f915bd051 100644 --- a/src/createRoom.ts +++ b/src/createRoom.ts @@ -222,6 +222,10 @@ export default async function createRoom(opts: IOpts): Promise { return client.createRoom(createOpts).finally(function() { if (modal) modal.close(); }).catch(function(err) { + // NB This checks for the Synapse-specific error condition of a room creation + // having been denied because the requesting user wanted to publish the room, + // but the server denies them that permission (via room_list_publication_rules). + // The check below responds by retrying without publishing the room. if (err.httpStatus === 403 && err.errcode === "M_UNKNOWN" && err.data.error === "Not allowed to publish room") { console.warn("Failed to publish room, try again without publishing it"); createOpts.visibility = Visibility.Private; From 5f751569ae3aeb5ec24f7c6761d1f3fc5d79480c Mon Sep 17 00:00:00 2001 From: Jeff Huang Date: Fri, 1 Oct 2021 01:36:24 +0000 Subject: [PATCH 055/143] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (3198 of 3198 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 006cf630ac..798f7a99c2 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -3169,5 +3169,40 @@ "%(reactors)s reacted with %(content)s": "%(reactors)s 使用了 %(content)s 反應", "Joining space …": "正在加入空間……", "Expand quotes │ ⇧+click": "展開引用 │ ⇧+點擊", - "Collapse quotes │ ⇧+click": "折疊引用 │ ⇧+點擊" + "Collapse quotes │ ⇧+click": "折疊引用 │ ⇧+點擊", + "Include Attachments": "包含附件", + "Size Limit": "大小限制", + "Format": "格式", + "Select from the options below to export chats from your timeline": "從下面的選項中選擇以從您的時間軸匯出聊天", + "Export Chat": "匯出聊天", + "Exporting your data": "正在匯出您的資料", + "Stop": "停止", + "Are you sure you want to stop exporting your data? If you do, you'll need to start over.": "您確定您要停止匯出您的資料嗎?若您這麼做,您就必須重新開始。", + "Your export was successful. Find it in your Downloads folder.": "您匯出成功。請在您的下載資料夾中尋找它。", + "The export was cancelled successfully": "匯出已成功取消", + "Export Successful": "匯出成功", + "MB": "MB", + "Number of messages": "訊息數", + "Number of messages can only be a number between %(min)s and %(max)s": "訊息數只能是 %(min)s MB 至 %(max)s MB 間的數字", + "Size can only be a number between %(min)s MB and %(max)s MB": "大小只能是 %(min)s MB 至 %(max)s MB 間的數字", + "Enter a number between %(min)s and %(max)s": "輸入介於 %(min)s 至 %(max)s 間的數字", + "In reply to this message": "回覆此訊息", + "Export chat": "匯出聊天", + "File Attached": "已附加檔案", + "Error fetching file": "擷取檔案錯誤", + "Topic: %(topic)s": "主題:%(topic)s", + "This is the start of export of . Exported by at %(exportDate)s.": "這是 匯出的開始。由 於 %(exportDate)s 匯出。", + "%(creatorName)s created this room.": "%(creatorName)s 建立了此聊天室。", + "Media omitted - file size limit exceeded": "媒體省略 - 超過檔案大小限制", + "Media omitted": "媒體省略", + "Current Timeline": "目前時間軸", + "Specify a number of messages": "指定訊息數量", + "From the beginning": "從一開始", + "Plain Text": "純文字", + "JSON": "JSON", + "HTML": "HTML", + "Are you sure you want to exit during this export?": "您確定您要從此匯出流程中退出嗎?", + "%(senderDisplayName)s sent a sticker.": "%(senderDisplayName)s 傳送了貼圖。", + "%(senderDisplayName)s changed the room avatar.": "%(senderDisplayName)s 變更了聊天室大頭照。", + "%(date)s at %(time)s": "%(date)s 於 %(time)s" } From fa0586af9ddf79a62a77170517f28e383e2e48f2 Mon Sep 17 00:00:00 2001 From: Ihor Hordiichuk Date: Thu, 30 Sep 2021 23:45:40 +0000 Subject: [PATCH 056/143] Translated using Weblate (Ukrainian) Currently translated at 66.3% (2121 of 3198 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/uk/ --- src/i18n/strings/uk.json | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/uk.json b/src/i18n/strings/uk.json index 896431d3e6..8627e34ec1 100644 --- a/src/i18n/strings/uk.json +++ b/src/i18n/strings/uk.json @@ -2110,5 +2110,18 @@ "There was an error finding this widget.": "Сталася помилка під час пошуку розширення.", "Active Widgets": "Активні розширення", "Verification Requests": "Запит перевірки", - "There was a problem communicating with the server. Please try again.": "Виникла проблема зв'язку з сервером. Повторіть спробу." + "There was a problem communicating with the server. Please try again.": "Виникла проблема зв'язку з сервером. Повторіть спробу.", + "You're not currently a member of any communities.": "Ви не приєдналися до жодної групи.", + "Loading...": "Завантаження...", + "Failed to load group members": "Не вдалося завантажити учасників групи", + "Can't load this message": "Не вдалося завантажити це повідомлення", + "Click here to see older messages.": "Клацніть тут, щоб переглянути давніші повідомлення.", + "%(senderDisplayName)s removed the room avatar.": "%(senderDisplayName)s вилучає аватар кімнати.", + "reacted with %(shortName)s": "реагує на %(shortName)s", + "%(reactors)s reacted with %(content)s": "%(reactors)s реагує на %(content)s", + "Reactions": "Реакції", + "Add reaction": "Додати реакцію", + "%(senderDisplayName)s sent a sticker.": "%(senderDisplayName)s надсилає наліпку.", + "%(senderDisplayName)s changed the room avatar.": "%(senderDisplayName)s змінює аватар кімнати.", + "%(date)s at %(time)s": "%(date)s о %(time)s" } From 5a1234b69dc4510e5f3a8389fb489e63b9076092 Mon Sep 17 00:00:00 2001 From: Besnik Bleta Date: Fri, 1 Oct 2021 08:18:55 +0000 Subject: [PATCH 057/143] Translated using Weblate (Albanian) Currently translated at 99.7% (3191 of 3198 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/sq/ --- src/i18n/strings/sq.json | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/sq.json b/src/i18n/strings/sq.json index 618dd71163..9aad3d737f 100644 --- a/src/i18n/strings/sq.json +++ b/src/i18n/strings/sq.json @@ -3163,5 +3163,40 @@ "Leave all rooms": "Braktisi krejt dhomat", "Don't leave any rooms": "Mos braktis ndonjë dhomë", "Expand quotes │ ⇧+click": "Hapi citimet │ ⇧+klikim", - "Collapse quotes │ ⇧+click": "Tkurri citimet │ ⇧+klikim" + "Collapse quotes │ ⇧+click": "Tkurri citimet │ ⇧+klikim", + "Format": "Format", + "MB": "MB", + "JSON": "JSON", + "HTML": "HTML", + "Include Attachments": "Përfshi Bashkëngjitje", + "Size Limit": "Kufi Madhësie", + "Select from the options below to export chats from your timeline": "Që të eksportohen fjalosje prej rrjedhës tuaj kohore, përzgjidhni prej mundësive më poshtë", + "Export Chat": "Eksportoni Fjalosje", + "Exporting your data": "Eksportim i të dhënave tuaja", + "Stop": "Ndale", + "Are you sure you want to stop exporting your data? If you do, you'll need to start over.": "Jeni i sigurt se doni të ndalet eksportimi i të dhënave tuaja? Nëse po, do t’ju duhet t’ia filloni nga e para.", + "Your export was successful. Find it in your Downloads folder.": "Eksportimi juaj qe i suksesshëm. E keni te dosja juaj Shkarkime.", + "The export was cancelled successfully": "Eksportimi u anulua me sukses", + "Export Successful": "Eksportim i Suksesshëm", + "Number of messages": "Numër mesazhesh", + "Number of messages can only be a number between %(min)s and %(max)s": "Numri i mesazheve mund të jetë vetëm një numër mes %(min)s dhe %(max)s", + "Size can only be a number between %(min)s MB and %(max)s MB": "Madhësia mund të jetë vetëm një numër mes %(min)s MB dhe %(max)s MB", + "Enter a number between %(min)s and %(max)s": "Jepni një numër mes %(min)s dhe %(max)s", + "In reply to this message": "Në përgjigje të këtij mesazhi", + "Export chat": "Eksportoni fjalosje", + "File Attached": "Kartelë Bashkëngjitur", + "Error fetching file": "Gabim në sjellje kartele", + "Topic: %(topic)s": "Temë: %(topic)s", + "This is the start of export of . Exported by at %(exportDate)s.": "Ky është fillimi i eksportimit të . Eksportuar nga më %(exportDate)s.", + "%(creatorName)s created this room.": "%(creatorName)s krijoi këtë dhomë.", + "Media omitted - file size limit exceeded": "U la jashtë media - u tejkalua kufi madhësie kartele", + "Media omitted": "U la jashtë media", + "Current Timeline": "Rrjedhë Kohore e Tanishme", + "Specify a number of messages": "Përcaktoni një numër mesazhesh", + "From the beginning": "Që nga fillimi", + "Plain Text": "Tekst i Thjeshtë", + "Are you sure you want to exit during this export?": "Jeni i sigurt se doni të dilet gjatë këtij eksportimi?", + "%(senderDisplayName)s sent a sticker.": "%(senderDisplayName)s dërgoi një ngjitës.", + "%(senderDisplayName)s changed the room avatar.": "%(senderDisplayName)s ndryshoi avatarin e dhomës.", + "%(date)s at %(time)s": "%(date)s më %(time)s" } From 226131409f3854cc3bfbc7eecef42b3bb07ea270 Mon Sep 17 00:00:00 2001 From: Andy Balaam Date: Fri, 1 Oct 2021 14:54:26 +0100 Subject: [PATCH 058/143] Unit tests for room avatars in DM and non-DM rooms Signed-off-by: Andy Balaam --- .../views/rooms/RoomHeader-test.tsx | 252 ++++++++++++++++++ test/test-utils.js | 14 +- 2 files changed, 262 insertions(+), 4 deletions(-) create mode 100644 test/components/views/rooms/RoomHeader-test.tsx diff --git a/test/components/views/rooms/RoomHeader-test.tsx b/test/components/views/rooms/RoomHeader-test.tsx new file mode 100644 index 0000000000..6696c8bd9c --- /dev/null +++ b/test/components/views/rooms/RoomHeader-test.tsx @@ -0,0 +1,252 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; + +import "../../../skinned-sdk"; + +import * as TestUtils from '../../../test-utils'; + +import { MatrixClientPeg } from '../../../../src/MatrixClientPeg'; + +import DMRoomMap from '../../../../src/utils/DMRoomMap'; +import RoomHeader from '../../../../src/components/views/rooms/RoomHeader'; + +import { Room, PendingEventOrdering, MatrixEvent, MatrixClient } from 'matrix-js-sdk'; +import { SearchScope } from '../../../../src/components/views/rooms/SearchBar'; +import { E2EStatus } from '../../../../src/utils/ShieldUtils'; +import { PlaceCallType } from '../../../../src/CallHandler'; +import { mkEvent } from '../../../test-utils'; + +describe('RoomHeader', () => { + test('shows the room avatar in a room with only ourselves', () => { + // When we render a non-DM room with 1 person in it + const room = createRoom({ name: "X Room", isDm: false, users: [] }); + const rendered = render(room); + + // Then the room's avatar is the initial of its name + const initial = findSpan(rendered, ".mx_BaseAvatar_initial"); + expect(initial.innerHTML).toEqual("X"); + + // And there is no image avatar (because it's not set on this room) + const image = findImg(rendered, ".mx_BaseAvatar_image"); + expect(image.src).toEqual("data:image/png;base64,00"); + }); + + test('shows the room avatar in a room with 2 people', () => { + // When we render a non-DM room with 2 people in it + const room = createRoom( + { name: "Y Room", isDm: false, users: ["other"] }); + const rendered = render(room); + + // Then the room's avatar is the initial of its name + const initial = findSpan(rendered, ".mx_BaseAvatar_initial"); + expect(initial.innerHTML).toEqual("Y"); + + // And there is no image avatar (because it's not set on this room) + const image = findImg(rendered, ".mx_BaseAvatar_image"); + expect(image.src).toEqual("data:image/png;base64,00"); + }); + + test('shows the room avatar in a room with >2 people', () => { + // When we render a non-DM room with 3 people in it + const room = createRoom( + { name: "Z Room", isDm: false, users: ["other1", "other2"] }); + const rendered = render(room); + + // Then the room's avatar is the initial of its name + const initial = findSpan(rendered, ".mx_BaseAvatar_initial"); + expect(initial.innerHTML).toEqual("Z"); + + // And there is no image avatar (because it's not set on this room) + const image = findImg(rendered, ".mx_BaseAvatar_image"); + expect(image.src).toEqual("data:image/png;base64,00"); + }); + + test('shows the room avatar in a DM with only ourselves', () => { + // When we render a non-DM room with 1 person in it + const room = createRoom({ name: "Z Room", isDm: true, users: [] }); + const rendered = render(room); + + // Then the room's avatar is the initial of its name + const initial = findSpan(rendered, ".mx_BaseAvatar_initial"); + expect(initial.innerHTML).toEqual("Z"); + + // And there is no image avatar (because it's not set on this room) + const image = findImg(rendered, ".mx_BaseAvatar_image"); + expect(image.src).toEqual("data:image/png;base64,00"); + }); + + test('shows the user avatar in a DM with 2 people', () => { + // Note: this is the interesting case - this is the ONLY + // time we should use the user's avatar. + + // When we render a DM room with only 2 people in it + const room = createRoom( + { name: "Y Room", isDm: true, users: ["other"] }); + const rendered = render(room); + + // Then we use the other user's avatar as our room's image avatar + const image = findImg(rendered, ".mx_BaseAvatar_image"); + expect(image.src).toEqual( + "http://this.is.a.url/example.org/other"); + + // And there is no initial avatar + expect( + rendered.querySelectorAll(".mx_BaseAvatar_initial"), + ).toHaveLength(0); + }); + + test('shows the room avatar in a DM with >2 people', () => { + // When we render a DM room with 3 people in it + const room = createRoom({ + name: "Z Room", isDm: true, users: ["other1", "other2"] }); + const rendered = render(room); + + // Then the room's avatar is the initial of its name + const initial = findSpan(rendered, ".mx_BaseAvatar_initial"); + expect(initial.innerHTML).toEqual("Z"); + + // And there is no image avatar (because it's not set on this room) + const image = findImg(rendered, ".mx_BaseAvatar_image"); + expect(image.src).toEqual("data:image/png;base64,00"); + }); +}); + +interface IRoomCreationInfo { + name: string; + isDm: boolean; + users: string[]; +} + +function createRoom(info: IRoomCreationInfo) { + TestUtils.stubClient(); + const client: MatrixClient = MatrixClientPeg.get(); + + const roomId = '!1234567890:domain'; + const userId = client.getUserId(); + if (info.isDm) { + client.getAccountData = (eventType) => { + expect(eventType).toEqual("m.direct"); + return mkDirectEvent(roomId, userId, info.users); + }; + } + + DMRoomMap.makeShared().start(); + + const room = new Room(roomId, client, userId, { + pendingEventOrdering: PendingEventOrdering.Detached, + }); + + const otherJoinEvents = []; + for (const otherUserId of info.users) { + otherJoinEvents.push(mkJoinEvent(roomId, otherUserId)); + } + + room.currentState.setStateEvents([ + mkCreationEvent(roomId, userId), + mkNameEvent(roomId, userId, info.name), + mkJoinEvent(roomId, userId), + ...otherJoinEvents, + ]); + room.recalculate(); + + return room; +} + +function render(room: Room): HTMLDivElement { + const parentDiv = document.createElement('div'); + document.body.appendChild(parentDiv); + ReactDOM.render( + ( + {}} + onSearchClick={() => {}} + onForgetClick={() => {}} + onCallPlaced={(_type: PlaceCallType) => {}} + onAppsClick={() => {}} + e2eStatus={E2EStatus.Normal} + appsShown={true} + searchInfo={{ + searchTerm: "", + searchScope: SearchScope.Room, + searchCount: 0, + }} + /> + ), + parentDiv, + ); + return parentDiv; +} + +function mkCreationEvent(roomId: string, userId: string): MatrixEvent { + return mkEvent({ + event: true, + type: "m.room.create", + room: roomId, + user: userId, + content: { + creator: userId, + room_version: "5", + predecessor: { + room_id: "!prevroom", + event_id: "$someevent", + }, + }, + }); +} + +function mkNameEvent( + roomId: string, userId: string, name: string, +): MatrixEvent { + return mkEvent({ + event: true, + type: "m.room.name", + room: roomId, + user: userId, + content: { name }, + }); +} + +function mkJoinEvent(roomId: string, userId: string) { + const ret = mkEvent({ + event: true, + type: "m.room.member", + room: roomId, + user: userId, + content: { + "membership": "join", + "avatar_url": "mxc://example.org/" + userId, + }, + }); + ret.event.state_key = userId; + return ret; +} + +function mkDirectEvent( + roomId: string, userId: string, otherUsers: string[], +): MatrixEvent { + const content = {}; + for (const otherUserId of otherUsers) { + content[otherUserId] = [roomId]; + } + return mkEvent({ + event: true, + type: "m.direct", + room: roomId, + user: userId, + content, + }); +} + +function findSpan(parent: HTMLElement, selector: string): HTMLSpanElement { + const els = parent.querySelectorAll(selector); + expect(els.length).toEqual(1); + return els[0] as HTMLSpanElement; +} + +function findImg(parent: HTMLElement, selector: string): HTMLImageElement { + const els = parent.querySelectorAll(selector); + expect(els.length).toEqual(1); + return els[0] as HTMLImageElement; +} diff --git a/test/test-utils.js b/test/test-utils.js index c06149991f..2091a6e0ed 100644 --- a/test/test-utils.js +++ b/test/test-utils.js @@ -47,6 +47,8 @@ export function createTestClient() { getIdentityServerUrl: jest.fn(), getDomain: jest.fn().mockReturnValue("matrix.rog"), getUserId: jest.fn().mockReturnValue("@userId:matrix.rog"), + getUser: jest.fn().mockReturnValue({ on: jest.fn() }), + credentials: { userId: "@userId:matrix.rog" }, getPushActionsForEvent: jest.fn(), getRoom: jest.fn().mockImplementation(mkStubRoom), @@ -76,7 +78,7 @@ export function createTestClient() { content: {}, }); }, - mxcUrlToHttp: (mxc) => 'http://this.is.a.url/', + mxcUrlToHttp: (mxc) => `http://this.is.a.url/${mxc.substring(6)}`, setAccountData: jest.fn(), setRoomAccountData: jest.fn(), sendTyping: jest.fn().mockResolvedValue({}), @@ -93,12 +95,14 @@ export function createTestClient() { sessionStore: { store: { getItem: jest.fn(), + setItem: jest.fn(), }, }, pushRules: {}, decryptEventIfNeeded: () => Promise.resolve(), isUserIgnored: jest.fn().mockReturnValue(false), getCapabilities: jest.fn().mockResolvedValue({}), + supportsExperimentalThreads: () => false, }; } @@ -130,9 +134,11 @@ export function mkEvent(opts) { }; if (opts.skey) { event.state_key = opts.skey; - } else if (["m.room.name", "m.room.topic", "m.room.create", "m.room.join_rules", - "m.room.power_levels", "m.room.topic", "m.room.history_visibility", "m.room.encryption", - "com.example.state"].indexOf(opts.type) !== -1) { + } else if ([ + "m.room.name", "m.room.topic", "m.room.create", "m.room.join_rules", + "m.room.power_levels", "m.room.topic", "m.room.history_visibility", + "m.room.encryption", "m.room.member", "com.example.state", + ].indexOf(opts.type) !== -1) { event.state_key = ""; } return opts.event ? new MatrixEvent(event) : event; From 073c5307f83459c32a0607d127795fc98bb182f8 Mon Sep 17 00:00:00 2001 From: Andrew Ferrazzutti Date: Sun, 3 Oct 2021 02:33:25 -0400 Subject: [PATCH 059/143] Close modal after re-attempt of room creation, not before Signed-off-by: Andrew Ferrazzutti --- src/createRoom.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/createRoom.ts b/src/createRoom.ts index 7f915bd051..daf8594e23 100644 --- a/src/createRoom.ts +++ b/src/createRoom.ts @@ -219,9 +219,7 @@ export default async function createRoom(opts: IOpts): Promise { if (opts.spinner) modal = Modal.createDialog(Spinner, null, 'mx_Dialog_spinner'); let roomId; - return client.createRoom(createOpts).finally(function() { - if (modal) modal.close(); - }).catch(function(err) { + return client.createRoom(createOpts).catch(function(err) { // NB This checks for the Synapse-specific error condition of a room creation // having been denied because the requesting user wanted to publish the room, // but the server denies them that permission (via room_list_publication_rules). @@ -233,6 +231,8 @@ export default async function createRoom(opts: IOpts): Promise { } else { return Promise.reject(err); } + }).finally(function() { + if (modal) modal.close(); }).then(function(res) { roomId = res.room_id; if (opts.dmUserId) { From 51eac4ed9686635f3d3c739b1236fa11151483af Mon Sep 17 00:00:00 2001 From: jelv Date: Sat, 2 Oct 2021 06:49:47 +0000 Subject: [PATCH 060/143] Translated using Weblate (Dutch) Currently translated at 98.9% (3166 of 3198 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 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/nl.json b/src/i18n/strings/nl.json index f13b8e77f9..0b9fb7641f 100644 --- a/src/i18n/strings/nl.json +++ b/src/i18n/strings/nl.json @@ -3166,5 +3166,8 @@ "Leave all rooms": "Alle kamers verlaten", "Don't leave any rooms": "Geen kamers verlaten", "Expand quotes │ ⇧+click": "Quotes uitvouwen │ ⇧+click", - "Collapse quotes │ ⇧+click": "Quotes invouwen │ ⇧+click" + "Collapse quotes │ ⇧+click": "Quotes invouwen │ ⇧+click", + "%(senderDisplayName)s sent a sticker.": "%(senderDisplayName)s Verstuurde een sticker.", + "%(senderDisplayName)s changed the room avatar.": "%(senderDisplayName)s veranderde de kamerafbeelding.", + "%(date)s at %(time)s": "%(date)s om %(time)s" } From 65e67003f332dbffe6d936d6ca0d5cc8f723b674 Mon Sep 17 00:00:00 2001 From: Andrew Ferrazzutti Date: Sat, 2 Oct 2021 00:52:17 -0400 Subject: [PATCH 061/143] Allow hiding "Sign Up" in the guest preview bar Hide the button when "UIFeature.registration" is set to false in Element's config.json. Fixes https://github.com/vector-im/element-web/issues/19264 Signed-off-by: Andrew Ferrazzutti --- src/components/views/rooms/RoomPreviewBar.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/RoomPreviewBar.tsx b/src/components/views/rooms/RoomPreviewBar.tsx index 2acefc93d6..82437a5c14 100644 --- a/src/components/views/rooms/RoomPreviewBar.tsx +++ b/src/components/views/rooms/RoomPreviewBar.tsx @@ -35,6 +35,8 @@ import InviteReason from "../elements/InviteReason"; import { IOOBData } from "../../../stores/ThreepidInviteStore"; import Spinner from "../elements/Spinner"; import AccessibleButton from "../elements/AccessibleButton"; +import { UIFeature } from "../../../settings/UIFeature"; +import SettingsStore from "../../../settings/SettingsStore"; const MemberEventHtmlReasonField = "io.element.html_reason"; @@ -339,8 +341,10 @@ export default class RoomPreviewBar extends React.Component { } case MessageCase.NotLoggedIn: { title = _t("Join the conversation with an account"); - primaryActionLabel = _t("Sign Up"); - primaryActionHandler = this.onRegisterClick; + if (SettingsStore.getValue(UIFeature.Registration)) { + primaryActionLabel = _t("Sign Up"); + primaryActionHandler = this.onRegisterClick; + } secondaryActionLabel = _t("Sign In"); secondaryActionHandler = this.onLoginClick; if (this.props.previewLoading) { From a076bee7647e90e88be4a88241b8c1109f3decbd Mon Sep 17 00:00:00 2001 From: ColonisationCaptain <52425971+ColonisationCaptain@users.noreply.github.com> Date: Sun, 3 Oct 2021 19:51:46 +0100 Subject: [PATCH 062/143] Decrease profile button touch target --- res/css/views/settings/_ProfileSettings.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/res/css/views/settings/_ProfileSettings.scss b/res/css/views/settings/_ProfileSettings.scss index 63a5fa7edf..35e517b5ac 100644 --- a/res/css/views/settings/_ProfileSettings.scss +++ b/res/css/views/settings/_ProfileSettings.scss @@ -67,5 +67,7 @@ limitations under the License. > .mx_AccessibleButton_kind_link { padding-left: 0; // to align with left side + padding-right: 0; + margin-right: 10px; } } From e8dba59b42ff6cfc55ba6d97d6d1675dc228a964 Mon Sep 17 00:00:00 2001 From: Andy Balaam Date: Mon, 4 Oct 2021 11:41:09 +0100 Subject: [PATCH 063/143] =?UTF-8?q?Fix=20review=20comments=20from=20=C5=A0?= =?UTF-8?q?imon=20Brandner.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename test->it; Rename users->userIds; Un-break a line. Signed-off-by: Andy Balaam --- .../views/rooms/RoomHeader-test.tsx | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/test/components/views/rooms/RoomHeader-test.tsx b/test/components/views/rooms/RoomHeader-test.tsx index 6696c8bd9c..859107416e 100644 --- a/test/components/views/rooms/RoomHeader-test.tsx +++ b/test/components/views/rooms/RoomHeader-test.tsx @@ -17,9 +17,9 @@ import { PlaceCallType } from '../../../../src/CallHandler'; import { mkEvent } from '../../../test-utils'; describe('RoomHeader', () => { - test('shows the room avatar in a room with only ourselves', () => { + it('shows the room avatar in a room with only ourselves', () => { // When we render a non-DM room with 1 person in it - const room = createRoom({ name: "X Room", isDm: false, users: [] }); + const room = createRoom({ name: "X Room", isDm: false, userIds: [] }); const rendered = render(room); // Then the room's avatar is the initial of its name @@ -31,10 +31,10 @@ describe('RoomHeader', () => { expect(image.src).toEqual("data:image/png;base64,00"); }); - test('shows the room avatar in a room with 2 people', () => { + it('shows the room avatar in a room with 2 people', () => { // When we render a non-DM room with 2 people in it const room = createRoom( - { name: "Y Room", isDm: false, users: ["other"] }); + { name: "Y Room", isDm: false, userIds: ["other"] }); const rendered = render(room); // Then the room's avatar is the initial of its name @@ -46,10 +46,10 @@ describe('RoomHeader', () => { expect(image.src).toEqual("data:image/png;base64,00"); }); - test('shows the room avatar in a room with >2 people', () => { + it('shows the room avatar in a room with >2 people', () => { // When we render a non-DM room with 3 people in it const room = createRoom( - { name: "Z Room", isDm: false, users: ["other1", "other2"] }); + { name: "Z Room", isDm: false, userIds: ["other1", "other2"] }); const rendered = render(room); // Then the room's avatar is the initial of its name @@ -61,9 +61,9 @@ describe('RoomHeader', () => { expect(image.src).toEqual("data:image/png;base64,00"); }); - test('shows the room avatar in a DM with only ourselves', () => { + it('shows the room avatar in a DM with only ourselves', () => { // When we render a non-DM room with 1 person in it - const room = createRoom({ name: "Z Room", isDm: true, users: [] }); + const room = createRoom({ name: "Z Room", isDm: true, userIds: [] }); const rendered = render(room); // Then the room's avatar is the initial of its name @@ -75,13 +75,12 @@ describe('RoomHeader', () => { expect(image.src).toEqual("data:image/png;base64,00"); }); - test('shows the user avatar in a DM with 2 people', () => { + it('shows the user avatar in a DM with 2 people', () => { // Note: this is the interesting case - this is the ONLY // time we should use the user's avatar. // When we render a DM room with only 2 people in it - const room = createRoom( - { name: "Y Room", isDm: true, users: ["other"] }); + const room = createRoom({ name: "Y Room", isDm: true, userIds: ["other"] }); const rendered = render(room); // Then we use the other user's avatar as our room's image avatar @@ -95,10 +94,10 @@ describe('RoomHeader', () => { ).toHaveLength(0); }); - test('shows the room avatar in a DM with >2 people', () => { + it('shows the room avatar in a DM with >2 people', () => { // When we render a DM room with 3 people in it const room = createRoom({ - name: "Z Room", isDm: true, users: ["other1", "other2"] }); + name: "Z Room", isDm: true, userIds: ["other1", "other2"] }); const rendered = render(room); // Then the room's avatar is the initial of its name @@ -114,7 +113,7 @@ describe('RoomHeader', () => { interface IRoomCreationInfo { name: string; isDm: boolean; - users: string[]; + userIds: string[]; } function createRoom(info: IRoomCreationInfo) { @@ -126,7 +125,7 @@ function createRoom(info: IRoomCreationInfo) { if (info.isDm) { client.getAccountData = (eventType) => { expect(eventType).toEqual("m.direct"); - return mkDirectEvent(roomId, userId, info.users); + return mkDirectEvent(roomId, userId, info.userIds); }; } @@ -137,7 +136,7 @@ function createRoom(info: IRoomCreationInfo) { }); const otherJoinEvents = []; - for (const otherUserId of info.users) { + for (const otherUserId of info.userIds) { otherJoinEvents.push(mkJoinEvent(roomId, otherUserId)); } From 2d02bb691be95ceec3b4e4258424fcded5d52887 Mon Sep 17 00:00:00 2001 From: iaiz Date: Mon, 4 Oct 2021 10:32:46 +0000 Subject: [PATCH 064/143] Translated using Weblate (Spanish) Currently translated at 99.5% (3183 of 3198 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 | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/i18n/strings/es.json b/src/i18n/strings/es.json index b88bd56886..a508a9e40f 100644 --- a/src/i18n/strings/es.json +++ b/src/i18n/strings/es.json @@ -655,7 +655,7 @@ "%(brand)s collects anonymous analytics to allow us to improve the application.": "%(brand)s recoge información sobre cómo usas la aplicación para ayudarnos a mejorarla.", "Privacy is important to us, so we don't collect any personal or identifiable data for our analytics.": "La privacidad nos importa, por lo que incluimos tus datos personales o que te puedan identificar para en las estadísticas.", "Learn more about how we use analytics.": "Más información sobre el uso de los análisis de estadísticas.", - "Check for update": "Comprobar actualizaciones", + "Check for update": "Comprobar si hay actualizaciones", "Start automatically after system login": "Abrir automáticamente después de iniciar sesión en el sistema", "No Audio Outputs detected": "No se han detectado salidas de sonido", "Audio Output": "Salida de sonido", @@ -3161,5 +3161,30 @@ "%(senderName)s unpinned a message from this room. See all pinned messages.": "%(senderName)s ha dejado de fijar un mensaje de esta sala. Ver todos los mensajes fijados.", "%(senderName)s unpinned a message from this room. See all pinned messages.": "%(senderName)s ha dejado de fijar un mensaje de esta sala. Ver todos los mensajes fijados.", "%(reactors)s reacted with %(content)s": "%(reactors)s han reaccionado con %(content)s", - "Expand quotes │ ⇧+click": "Expandir citas │ ⇧+clic" + "Expand quotes │ ⇧+click": "Expandir citas │ ⇧+clic", + "This is the start of export of . Exported by at %(exportDate)s.": "Aquí empieza la exportación de . Exportado por el %(exportDate)s.", + "Media omitted - file size limit exceeded": "Archivo omitido - supera el límite de tamaño", + "Media omitted": "Archivo omitido", + "Exporting your data": "Exportando tus datos", + "Export Chat": "Exportar conversación", + "Include Attachments": "Incluir archivos adjuntos", + "Size Limit": "Límite de tamaño", + "Format": "Formato", + "Stop": "Parar", + "MB": "MB", + "In reply to this message": "En respuesta a este mensaje", + "Export chat": "Exportar conversación", + "File Attached": "Archivo adjunto", + "Error fetching file": "Error al recuperar el archivo", + "Topic: %(topic)s": "Tema:", + "%(creatorName)s created this room.": "%(creatorName)s creó esta sala.", + "Current Timeline": "Línea de tiempo actual", + "Specify a number of messages": "Indica una cantidad de mensajes", + "From the beginning": "Desde el principio", + "Plain Text": "Texto", + "JSON": "JSON", + "HTML": "HTML", + "Are you sure you want to exit during this export?": "¿Seguro que quieres salir durante la exportación?", + "%(senderDisplayName)s changed the room avatar.": "%(senderDisplayName)s cambió la imagen de la sala.", + "%(senderDisplayName)s sent a sticker.": "%(senderDisplayName)s envió una pegatina." } From 287f4ae2f2c16ffad87db3d9d393cea2a6cae190 Mon Sep 17 00:00:00 2001 From: jelv Date: Sun, 3 Oct 2021 13:12:17 +0000 Subject: [PATCH 065/143] Translated using Weblate (Dutch) Currently translated at 100.0% (3198 of 3198 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 | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/nl.json b/src/i18n/strings/nl.json index 0b9fb7641f..cce71ac8f2 100644 --- a/src/i18n/strings/nl.json +++ b/src/i18n/strings/nl.json @@ -3169,5 +3169,37 @@ "Collapse quotes │ ⇧+click": "Quotes invouwen │ ⇧+click", "%(senderDisplayName)s sent a sticker.": "%(senderDisplayName)s Verstuurde een sticker.", "%(senderDisplayName)s changed the room avatar.": "%(senderDisplayName)s veranderde de kamerafbeelding.", - "%(date)s at %(time)s": "%(date)s om %(time)s" + "%(date)s at %(time)s": "%(date)s om %(time)s", + "Include Attachments": "Bijlages toevoegen", + "Size Limit": "Bestandsgrootte", + "Format": "Formaat", + "Select from the options below to export chats from your timeline": "Selecteer met welke opties u uw chats wilt exporteren van uw tijdlijn", + "Export Chat": "Chat exporteren", + "Exporting your data": "Uw data aan het exporteren", + "Stop": "Stop", + "Are you sure you want to stop exporting your data? If you do, you'll need to start over.": "Weet u zeker dat u wilt stoppen terwijl u uw data exporteert? Als u dit doet moet u later opnieuw beginnen.", + "Your export was successful. Find it in your Downloads folder.": "Uw export was succesvol. U vindt hem in uw Downloads-map.", + "The export was cancelled successfully": "De export was succesvol geannulleerd", + "Export Successful": "Export succesvol", + "MB": "MB", + "Number of messages": "Berichten aantal", + "Number of messages can only be a number between %(min)s and %(max)s": "Aantal berichten moet een getal zijn tussen %(min)s en %(max)s", + "Size can only be a number between %(min)s MB and %(max)s MB": "Bestand moet een grootte hebben tussen %(min)s MB en %(max)s MB", + "Enter a number between %(min)s and %(max)s": "Voer een nummer tussen %(min)s en %(max)s in", + "In reply to this message": "In antwoord op dit bericht", + "Export chat": "Chat exporteren", + "File Attached": "Bijgevoegd bestand", + "Error fetching file": "Fout bij bestand opvragen", + "Topic: %(topic)s": "Onderwerp: %(topic)s", + "This is the start of export of . Exported by at %(exportDate)s.": "Dit is de start van de export van . Geëxporteerd door op %(exportDate)s.", + "%(creatorName)s created this room.": "%(creatorName)s heeft deze kamer gemaakt.", + "Media omitted - file size limit exceeded": "Media weggelaten - limiet bestandsgrootte overschreden", + "Media omitted": "Media weglaten", + "Current Timeline": "Huidige tijdlijn", + "Specify a number of messages": "Kies het aantal berichten", + "From the beginning": "Van het begin", + "Plain Text": "Platte tekst", + "JSON": "JSON", + "HTML": "HTML", + "Are you sure you want to exit during this export?": "Weet u zeker dat u wilt afsluiten tijdens een export?" } From dbd3829d3f28ddcfe684c7c3b9d5a41b5c3df3d4 Mon Sep 17 00:00:00 2001 From: Nikita Epifanov Date: Mon, 4 Oct 2021 09:35:12 +0000 Subject: [PATCH 066/143] Translated using Weblate (Russian) Currently translated at 98.2% (3141 of 3198 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/ru/ --- src/i18n/strings/ru.json | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index a06dd2f72f..d2766949fb 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -3162,5 +3162,38 @@ "To join a space you'll need an invite.": "Чтобы присоединиться к пространству, вам нужно получить приглашение.", "Temporarily show communities instead of Spaces for this session. Support for this will be removed in the near future. This will reload Element.": "Временно показывать сообщества вместо пространств для этой сессии. Поддержка этого будет удалена в ближайшем будущем. Это перезагрузит Element.", "Display Communities instead of Spaces": "Показывать сообщества вместо пространств", - "You can also make Spaces from communities.": "Вы также можете создать пространство из сообщества." + "You can also make Spaces from communities.": "Вы также можете создать пространство из сообщества.", + "Include Attachments": "Включить вложения", + "Size Limit": "Ограничение по размеру", + "Format": "Формат", + "Export Chat": "Экспорт чата", + "Exporting your data": "Экспорт ваших данных", + "Stop": "Стоп", + "Are you sure you want to stop exporting your data? If you do, you'll need to start over.": "Вы уверены, что хотите прекратить экспорт данных? Если да, то вам придется начать все сначала.", + "Your export was successful. Find it in your Downloads folder.": "Ваш экспорт звершен. Найдите его в папке \"Загрузки\".", + "The export was cancelled successfully": "Экспорт был отменен", + "Export Successful": "Экспорт завершен", + "MB": "Мб", + "Number of messages": "Количество сообщений", + "Number of messages can only be a number between %(min)s and %(max)s": "Количество сообщений может быть только числом между %(min)s и %(max)s", + "Size can only be a number between %(min)s MB and %(max)s MB": "Размер может быть только числом между %(min)s Мб и %(max)s Мб", + "Enter a number between %(min)s and %(max)s": "Введите число между %(min)s и %(max)s", + "In reply to this message": "В ответ на это сообщение", + "Export chat": "Экспорт чата", + "File Attached": "Файл прикреплен", + "Error fetching file": "Ошибка при получении файла", + "Topic: %(topic)s": "Тема: %(topic)s", + "This is the start of export of . Exported by at %(exportDate)s.": "Это начало экспорта . Экспортировано в %(exportDate)s.", + "%(creatorName)s created this room.": "%(creatorName)s создал(а) эту комнату.", + "Media omitted - file size limit exceeded": "Медиа пропущены - превышен лимит размера файла", + "Media omitted": "Медиа пропущены", + "Specify a number of messages": "Укажите количество сообщений", + "From the beginning": "С начала", + "Plain Text": "Текст", + "JSON": "JSON", + "HTML": "HTML", + "Are you sure you want to exit during this export?": "Вы уверены, что хотите выйти во время экспорта?", + "%(senderDisplayName)s sent a sticker.": "%(senderDisplayName)s отправил(а) стикер.", + "%(senderDisplayName)s changed the room avatar.": "%(senderDisplayName)s сменил(а) аватар комнаты.", + "%(date)s at %(time)s": "%(date)s в %(time)s" } From 27cd1f73bc41f35deeea8b5fe6b9ae389eb79ed3 Mon Sep 17 00:00:00 2001 From: Ihor Hordiichuk Date: Sun, 3 Oct 2021 21:01:53 +0000 Subject: [PATCH 067/143] Translated using Weblate (Ukrainian) Currently translated at 66.7% (2134 of 3198 strings) Translation: Element Web/matrix-react-sdk Translate-URL: https://translate.element.io/projects/element-web/matrix-react-sdk/uk/ --- src/i18n/strings/uk.json | 73 +++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 30 deletions(-) diff --git a/src/i18n/strings/uk.json b/src/i18n/strings/uk.json index 8627e34ec1..4fe75dd2ff 100644 --- a/src/i18n/strings/uk.json +++ b/src/i18n/strings/uk.json @@ -511,12 +511,12 @@ "Command failed": "Не вдалося виконати команду", "Could not find user in room": "Не вдалося знайти користувача в кімнаті", "Please supply a widget URL or embed code": "Вкажіть URL або код вбудовування розширення", - "Verifies a user, session, and pubkey tuple": "Звіряє користувача, сеанс та кортеж відкритого ключа", + "Verifies a user, session, and pubkey tuple": "Звіряє користувача, сеанс та супровід відкритого ключа", "Unknown (user, session) pair:": "Невідома пара (користувача, сеансу):", - "Session already verified!": "Сеанс вже підтверджений!", - "WARNING: Session already verified, but keys do NOT MATCH!": "УВАГА: Сеанс вже підтверджений, проте ключі НЕ ЗБІГАЮТЬСЯ!", - "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!": "УВАГА: НЕ ВДАЛОСЯ ЗДІЙСНИТИ ЗВІРЯННЯ КЛЮЧА! Ключем для %(userId)s та сеансу %(deviceId)s є \"%(fprint)s\", що не відповідає наданому ключу \"%(fingerprint)s\". Це може означати, що ваші повідомлення перехоплюють!", - "The signing key you provided matches the signing key you received from %(userId)s's session %(deviceId)s. Session marked as verified.": "Наданий вами ключ підпису збігається з ключем підпису, що ви отримали від сеансу %(deviceId)s %(userId)s. Сеанс позначено як звірений.", + "Session already verified!": "Сеанс вже звірено!", + "WARNING: Session already verified, but keys do NOT MATCH!": "УВАГА: Сеанс вже звірено, проте ключі НЕ ЗБІГАЮТЬСЯ!", + "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!": "УВАГА: НЕ ВДАЛОСЯ ЗВІРИТИ КЛЮЧ! Ключем для %(userId)s та сеансу %(deviceId)s є «%(fprint)s», що не збігається з наданим ключем «%(fingerprint)s». Це може означати, що ваші повідомлення перехоплюють!", + "The signing key you provided matches the signing key you received from %(userId)s's session %(deviceId)s. Session marked as verified.": "Наданий вами ключ підпису збігається з ключем підпису, що ви отримали від сеансу %(deviceId)s %(userId)s. Сеанс позначено звіреним.", "Sends the given emote coloured as a rainbow": "Надсилає вказаний смайлик, розфарбований веселкою", "Displays list of commands with usages and descriptions": "Відбиває перелік команд із прикладами вжитку та описом", "Displays information about a user": "Показує відомості про користувача", @@ -559,10 +559,10 @@ "%(senderName)s created a rule banning servers matching %(glob)s for %(reason)s": "%(senderName)s створює правило блокування серверів зі збігом з %(glob)s через %(reason)s", "Light": "Світла", "Dark": "Темна", - "You signed in to a new session without verifying it:": "Ви увійшли в новий сеанс, не підтвердивши його:", - "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) починає новий сеанс без його підтвердження:", - "Ask this user to verify their session, or manually verify it below.": "Попросіть цього користувача підтвердити сеанс, або підтвердьте його власноруч унизу.", + "You signed in to a new session without verifying it:": "Ви увійшли в новий сеанс, не звіривши його:", + "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) починає новий сеанс без його звірення:", + "Ask this user to verify their session, or manually verify it below.": "Попросіть цього користувача звірити сеанс, або звірте його власноруч унизу.", "Not Trusted": "Не довірений", "Manually Verify by Text": "Ручна перевірка за допомогою тексту", "Interactively verify by Emoji": "Інтерактивно звірити за допомогою емодзі", @@ -907,7 +907,7 @@ "Upgrade public room": "Поліпшити відкриту кімнату", "Restore your key backup to upgrade your encryption": "Відновіть резервну копію вашого ключа, щоб поліпшити шифрування", "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.": "Оновіть цей сеанс, щоб уможливити звірення інших сеансів, надаючи їм доступ до зашифрованих повідомлень та позначаючи їх довіреними для інших користувачів.", "Upgrade your encryption": "Поліпшити ваше шифрування", "Show a placeholder for removed messages": "Показувати замісну позначку замість видалених повідомлень", "Show join/leave messages (invites/kicks/bans unaffected)": "Показувати повідомлення про приєднання/вихід (не впливає на запрошення/викидання/блокування)", @@ -971,11 +971,11 @@ "Verify this user by confirming the following emoji appear on their screen.": "Звірте цього користувача підтвердженням того, що наступні емодзі з'являються на його екрані.", "Emoji picker": "Обирач емодзі", "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.": "Сеанс, який ви намагаєтесь звірити, не підтримує сканування QR-коду або звіряння за допомогою емодзі, що є підтримувані %(brand)s. Спробуйте використати інший клієнт.", - "If you can't scan the code above, verify by comparing unique emoji.": "Якщо ви не можете відсканувати вищезазначений код, звірте порівнянням унікальних емодзі.", + "If you can't scan the code above, verify by comparing unique emoji.": "Якщо ви не можете сканувати зазначений код, звірте порівнянням унікальних емодзі.", "Verify by comparing unique emoji.": "Звірити порівнянням унікальних емодзі.", "Verify by emoji": "Звірити за допомогою емодзі", "Compare emoji": "Порівняти емодзі", - "Your new session is now verified. It has access to your encrypted messages, and other users will see it as trusted.": "Ваш новий сеанс тепер є звірений. Він має доступ до ваших зашифрованих повідомлень, а інші користувачі бачитимуть його як довірений.", + "Your new session is now verified. It has access to your encrypted messages, and other users will see it as trusted.": "Ваш новий сеанс звірено. Він має доступ до ваших зашифрованих повідомлень, а інші користувачі бачитимуть його довіреним.", "Emoji": "Емодзі", "Emoji Autocomplete": "Самодоповнення емодзі", "%(senderName)s created a ban rule matching %(glob)s for %(reason)s": "%(senderName)s створює правило блокування зі збігом з %(glob)s через %(reason)s", @@ -1355,11 +1355,11 @@ "%(severalUsers)sjoined %(count)s times|other": "%(severalUsers)sприєдналися %(count)s разів", "Members only (since they joined)": "Лише учасники (від часу приєднання)", "This room is not accessible by remote Matrix servers": "Ця кімната недоступна для віддалених серверів Matrix", - "Manually verify all remote sessions": "Перевірити всі сеанси власноруч", + "Manually verify all remote sessions": "Звірити всі сеанси власноруч", "Explore rooms": "Каталог кімнат", "Session key:": "Ключ сеансу:", "Hide sessions": "Сховати сеанси", - "Hide verified sessions": "Сховати підтверджені сеанси", + "Hide verified sessions": "Сховати звірені сеанси", "Session ID:": "ID сеансу:", "Click the button below to confirm setting up encryption.": "Клацніть на кнопку внизу, щоб підтвердити налаштування шифрування.", "Confirm encryption setup": "Підтвердити налаштування шифрування", @@ -1377,7 +1377,7 @@ "Try again": "Спробувати ще раз", "%(creator)s created this DM.": "%(creator)s створює цю приватну розмову.", "Share Link to User": "Поділитися посиланням на користувача", - "Messages here are end-to-end encrypted. Verify %(displayName)s in their profile - tap on their avatar.": "Повідомлення тут захищено наскрізним шифруванням. Підтвердьте %(displayName)s у їхньому профілі — натиснувши на їх аватар.", + "Messages here are end-to-end encrypted. Verify %(displayName)s in their profile - tap on their avatar.": "Повідомлення тут захищено наскрізним шифруванням. Звірте %(displayName)s у їхньому профілі — натиснувши на їх аватар.", "In reply to ": "У відповідь на ", "The user you called is busy.": "Користувач, якого ви викликаєте, зайнятий.", "User Busy": "Користувач зайнятий", @@ -1419,7 +1419,7 @@ "Not trusted": "Не довірений", "Trusted": "Довірений", "This backup is trusted because it has been restored on this session": "Ця резервна копія довірена, оскільки її було відновлено у цьому сеансі", - "Individually verify each session used by a user to mark it as trusted, not trusting cross-signed devices.": "Індивідуально перевіряйте кожен сеанс, який використовується користувачем, щоб позначити його довіреним, не довіряючи пристроям перехресного підписування.", + "Individually verify each session used by a user to mark it as trusted, not trusting cross-signed devices.": "Індивідуально звіряйте кожен сеанс, який використовується користувачем, щоб позначити його довіреним, не довіряючи пристроям перехресного підписування.", "To be secure, do this in person or use a trusted way to communicate.": "Для забезпечення безпеки зробіть це особисто або скористайтесь надійним способом зв'язку.", "You can change this at any time from room settings.": "Ви завжди можете змінити це у налаштуваннях кімнати.", "Room settings": "Налаштування кімнати", @@ -1623,12 +1623,12 @@ "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.": "Ваш домашній сервер був недоступний і вхід не виконано. Повторіть спробу. Якщо це триватиме й далі, зверніться до адміністратора свого домашнього сервера.", "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.": "Ми попросили переглядач запам’ятати, який домашній сервер ви використовуєте, щоб дозволити вам увійти, але, на жаль, ваш переглядач забув його. Перейдіть на сторінку входу та повторіть спробу.", - "You've successfully verified %(deviceName)s (%(deviceId)s)!": "Ви успішно підтвердили %(deviceName)s (%(deviceId)s)!", - "You've successfully verified your device!": "Ви успішно підтвердили свій пристрій!", - "You've successfully verified %(displayName)s!": "Ви успішно підтвердили %(displayName)s!", + "You've successfully verified %(deviceName)s (%(deviceId)s)!": "Ви успішно звірили %(deviceName)s (%(deviceId)s)!", + "You've successfully verified your device!": "Ви успішно звірили свій пристрій!", + "You've successfully verified %(displayName)s!": "Ви успішно звірили %(displayName)s!", "Almost there! Is %(displayName)s showing the same shield?": "Майже готово! Ваш %(displayName)s показує той самий щит?", "Almost there! Is your other session showing the same shield?": "Майже готово! Ваш інший сеанс показує той самий щит?", - "Verify by scanning": "Підтвердити скануванням", + "Verify by scanning": "Звірити скануванням", "Remove recent messages by %(user)s": "Вилучити останні повідомлення від %(user)s", "Remove recent messages": "Видалити останні повідомлення", "Edit devices": "Керувати пристроями", @@ -1638,11 +1638,11 @@ "Server Options": "Опції сервера", "Verify your identity to access encrypted messages and prove your identity to others.": "Підтвердьте свою особу, щоб отримати доступ до зашифрованих повідомлень і довести свою справжність іншим.", "Allow this widget to verify your identity": "Дозволити цьому розширенню перевіряти вашу особу", - "Verify this login": "Підтвердити цей вхід", - "Verify other login": "Підтвердити інший вхід", + "Verify this login": "Звірити цей вхід", + "Verify other login": "Звірити інший вхід", "Use another login": "Інший обліковий запис", "Use Security Key": "Використати ключ безпеки", - "Without verifying, you won’t have access to all your messages and may appear as untrusted to others.": "Без підтвердження ви не матимете доступу до всіх своїх повідомлень, а інші бачитимуть вас ненадійними.", + "Without verifying, you won’t have access to all your messages and may appear as untrusted to others.": "Без звірки ви не матимете доступу до всіх своїх повідомлень, а інші бачитимуть вас недовіреними.", "New? Create account": "Вперше тут? Створіть обліковий запис", "Forgotten your password?": "Забули свій пароль?", "Forgot password?": "Забули пароль?", @@ -1659,8 +1659,8 @@ "%(senderName)s unpinned a message from this room. See all pinned messages.": "%(senderName)s відкріплює повідомлення з цієї кімнати. Перегляньте всі прикріплені повідомлення.", "%(senderName)s pinned a message to this room. See all pinned messages.": "%(senderName)s прикріплює повідомлення до цієї кімнати. Перегляньте всі прикріплені повідомлення.", "%(senderName)s pinned a message to this room. See all pinned messages.": "%(senderName)s прикріплює повідомлення до цієї кімнати. Перегляньте всі прикріплені повідомлення.", - "Verify this user by confirming the following number appears on their screen.": "Перевірте цього користувача, підтвердивши, що на екрані з'явилося таке число.", - "Verify this session by confirming the following number appears on its screen.": "Перевірте цей сеанс, підтвердивши, що на екрані з'явилося це число.", + "Verify this user by confirming the following number appears on their screen.": "Звірте справжність цього користувача, підтвердивши, що на екрані з'явилося таке число.", + "Verify this session by confirming the following number appears on its screen.": "Звірте цей сеанс, підтвердивши, що на екрані з'явилося це число.", "They don't match": "Вони не збігаються", "They match": "Вони збігаються", "Return to call": "Повернутися до виклику", @@ -1692,7 +1692,7 @@ "Enable desktop notifications": "Увімкнути сповіщення стільниці", "Don't miss a reply": "Не пропустіть відповідей", "Review to ensure your account is safe": "Перевірте, щоб переконатися, що ваш обліковий запис у безпеці", - "You have unverified logins": "У вас є не підтверджені сеанси", + "You have unverified logins": "У вас є незвірені сеанси", "Error leaving room": "Помилка під час виходу з кімнати", "This homeserver has been blocked by its administrator.": "Цей домашній сервер заблокований адміністратором.", "See when the name changes in your active room": "Бачити, коли зміниться назва активної кімнати", @@ -1726,7 +1726,7 @@ "Start sharing your screen": "Почати показ екрана", "Start the camera": "Запустити камеру", "Scan this unique code": "Скануйте цей унікальний код", - "Verify this session by completing one of the following:": "Підтвердьте цей сеанс одним із запропонованих способів:", + "Verify this session by completing one of the following:": "Звірте цей сеанс одним із запропонованих способів:", "Leave %(groupName)s?": "Вийти з %(groupName)s?", "Leave Community": "Вийти зі спільноти", "Add a User": "Додати користувача", @@ -1900,7 +1900,7 @@ "Community Autocomplete": "Автозаповнення спільноти", "Command Autocomplete": "Команда автозаповнення", "Commands": "Команди", - "Your new session is now verified. Other users will see it as trusted.": "Тепер ваша новий сеанс тепер підтверджено. Інші користувачі побачать її довіреною.", + "Your new session is now verified. Other users will see it as trusted.": "Ваш новий сеанс звірено. Інші користувачі побачать його довіреним.", "Registration Successful": "Реєстрацію успішно виконано", "You can now close this window or log in to your new account.": "Тепер можете закрити це вікно або увійти до свого нового облікового запису.", "Log in to your new account.": "Увійти до нового облікового запису.", @@ -1908,7 +1908,7 @@ "Set a new password": "Установити новий пароль", "Return to login screen": "Повернутися на сторінку входу", "Send Reset Email": "Надіслати електронного листа скидання пароля", - "Session verified": "Сеанс підтверджено", + "Session verified": "Сеанс звірено", "User settings": "Користувацькі налаштування", "Community settings": "Налаштування спільноти", "Switch theme": "Змінити тему", @@ -2123,5 +2123,18 @@ "Add reaction": "Додати реакцію", "%(senderDisplayName)s sent a sticker.": "%(senderDisplayName)s надсилає наліпку.", "%(senderDisplayName)s changed the room avatar.": "%(senderDisplayName)s змінює аватар кімнати.", - "%(date)s at %(time)s": "%(date)s о %(time)s" + "%(date)s at %(time)s": "%(date)s о %(time)s", + "Manually export keys": "Експорт ключів власноруч", + "Don't leave any rooms": "Не виходити з будь-якої кімнати", + "Updating %(brand)s": "Оновлення %(brand)s", + "Clear cache and resync": "Очистити кеш і повторно синхронізувати", + "Incompatible local cache": "Несумісний локальний кеш", + "Signature upload failed": "Не вдалося вивантажити підпис", + "Signature upload success": "Підпис успішно вивантажено", + "Unable to upload": "Не вдалося вивантажити", + "Cancelled signature upload": "Вивантаження підпису скасовано", + "Upload completed": "Вивантаження виконано", + "Search %(spaceName)s": "Пошук %(spaceName)s", + "Leave some rooms": "Вийте з кількох кімнат", + "Leave all rooms": "Вийти з кімнати" } From 7fc4f54ae74002012fdc36a041eb773c373dd642 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Mon, 4 Oct 2021 12:01:31 +0100 Subject: [PATCH 068/143] Upgrade matrix-js-sdk to 14.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 46ff26bf32..8be5283117 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,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": "14.0.0-rc.1", "matrix-widget-api": "^0.1.0-beta.16", "minimist": "^1.2.5", "opus-recorder": "^8.0.3", diff --git a/yarn.lock b/yarn.lock index ec2d9e08ea..0b17dc1284 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5862,9 +5862,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 "13.0.0" - resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/2515d07c8fc3bf5e1afc8352e3e330cca30dde85" +matrix-js-sdk@14.0.0-rc.1: + version "14.0.0-rc.1" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-14.0.0-rc.1.tgz#1cb3dfd2949d3a4414986f8ab0a92575f5fff0d1" + integrity sha512-idDBJRGOOdn9yOQWoZxwLSWv2xn7jF3IJ7W5UCmOZ0EKYmH7C1VlKAfvkGDpxdbrNCRs84SUvqJqImAuQoV4Gw== dependencies: "@babel/runtime" "^7.12.5" another-json "^0.2.0" From c0258187a28e1de5b2903c4924541cdef12d7bc7 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Mon, 4 Oct 2021 12:03:40 +0100 Subject: [PATCH 069/143] Prepare changelog for v3.32.0-rc.1 --- CHANGELOG.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c28d72a3eb..327890d4da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,29 @@ +Changes in [3.32.0-rc.1](https://github.com/vector-im/element-desktop/releases/tag/v3.32.0-rc.1) (2021-10-04) +============================================================================================================= + +## ✨ Features + * Decrease profile button touch target ([\#6900](https://github.com/matrix-org/matrix-react-sdk/pull/6900)). Contributed by [ColonisationCaptain](https://github.com/ColonisationCaptain). + * Don't let click events propagate out of context menus ([\#6892](https://github.com/matrix-org/matrix-react-sdk/pull/6892)). + * Allow closing Dropdown via its chevron ([\#6885](https://github.com/matrix-org/matrix-react-sdk/pull/6885)). Fixes vector-im/element-web#19030 and vector-im/element-web#19030. + * Improve AUX panel behaviour ([\#6699](https://github.com/matrix-org/matrix-react-sdk/pull/6699)). Fixes vector-im/element-web#18787 and vector-im/element-web#18787. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * A nicer opening animation for the Image View ([\#6454](https://github.com/matrix-org/matrix-react-sdk/pull/6454)). Fixes vector-im/element-web#18186 and vector-im/element-web#18186. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + +## 🐛 Bug Fixes + * Fix leaving space via other client leaving you in undefined-land ([\#6891](https://github.com/matrix-org/matrix-react-sdk/pull/6891)). Fixes vector-im/element-web#18455 and vector-im/element-web#18455. + * Handle newer voice message encrypted event format for chat export ([\#6893](https://github.com/matrix-org/matrix-react-sdk/pull/6893)). Contributed by [jaiwanth-v](https://github.com/jaiwanth-v). + * Fix pagination when filtering space hierarchy ([\#6876](https://github.com/matrix-org/matrix-react-sdk/pull/6876)). Fixes vector-im/element-web#19235 and vector-im/element-web#19235. + * Fix spaces null-guard breaking the dispatcher settings watching ([\#6886](https://github.com/matrix-org/matrix-react-sdk/pull/6886)). Fixes vector-im/element-web#19223 and vector-im/element-web#19223. + * Fix space children without specific `order` being sorted after those with one ([\#6878](https://github.com/matrix-org/matrix-react-sdk/pull/6878)). Fixes vector-im/element-web#19192 and vector-im/element-web#19192. + * Ensure that sub-spaces aren't considered for notification badges ([\#6881](https://github.com/matrix-org/matrix-react-sdk/pull/6881)). Fixes vector-im/element-web#18975 and vector-im/element-web#18975. + * Fix timeline autoscroll with non-standard DPI settings. ([\#6880](https://github.com/matrix-org/matrix-react-sdk/pull/6880)). Fixes vector-im/element-web#18984 and vector-im/element-web#18984. + * Pluck out JoinRuleSettings styles so they apply in space settings too ([\#6879](https://github.com/matrix-org/matrix-react-sdk/pull/6879)). Fixes vector-im/element-web#19164 and vector-im/element-web#19164. + * Null guard around the matrixClient in SpaceStore ([\#6874](https://github.com/matrix-org/matrix-react-sdk/pull/6874)). + * Fix issue (https ([\#6871](https://github.com/matrix-org/matrix-react-sdk/pull/6871)). Fixes vector-im/element-web#19138 and vector-im/element-web#19138. Contributed by [psrpinto](https://github.com/psrpinto). + * Fix pills being cut off in message bubble layout ([\#6865](https://github.com/matrix-org/matrix-react-sdk/pull/6865)). Fixes vector-im/element-web#18627 and vector-im/element-web#18627. Contributed by [robintown](https://github.com/robintown). + * Fix space admin check false positive on multiple admins ([\#6824](https://github.com/matrix-org/matrix-react-sdk/pull/6824)). + * Fix the User View ([\#6860](https://github.com/matrix-org/matrix-react-sdk/pull/6860)). Fixes vector-im/element-web#19158 and vector-im/element-web#19158. + * Fix spacing for message composer buttons ([\#6852](https://github.com/matrix-org/matrix-react-sdk/pull/6852)). Fixes vector-im/element-web#18999 and vector-im/element-web#18999. + Changes in [3.31.0](https://github.com/vector-im/element-desktop/releases/tag/v3.31.0) (2021-09-27) =================================================================================================== From 425eeada6fd6cfca6d714a602e96ff87225490b9 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Mon, 4 Oct 2021 12:03:41 +0100 Subject: [PATCH 070/143] v3.32.0-rc.1 --- package.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 8be5283117..40633b9723 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "3.31.0", + "version": "3.32.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.ts", + "main": "./lib/index.ts", "matrix_src_main": "./src/index.ts", "matrix_lib_main": "./lib/index.ts", "matrix_lib_typings": "./lib/index.d.ts", @@ -215,5 +215,6 @@ "coverageReporters": [ "text" ] - } + }, + "typings": "./lib/index.d.ts" } From c670d95e2791da7eaf96abb05d2dbfb2f397d017 Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Mon, 4 Oct 2021 12:30:26 +0100 Subject: [PATCH 071/143] Update dependencies --- yarn.lock | 782 +++++++++++++++++++++++++++--------------------------- 1 file changed, 387 insertions(+), 395 deletions(-) diff --git a/yarn.lock b/yarn.lock index ec2d9e08ea..84d82220f4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3,9 +3,11 @@ "@actions/core@^1.4.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@actions/core/-/core-1.5.0.tgz#885b864700001a1b9a6fba247833a036e75ad9d3" - integrity sha512-eDOLH1Nq9zh+PJlYLqEMkS/jLQxhksPNmUGNBHfa4G+tQmnIhzpctxmchETtVGyBOvXgOVVpYuE40+eS4cUnwQ== + version "1.6.0" + resolved "https://registry.yarnpkg.com/@actions/core/-/core-1.6.0.tgz#0568e47039bfb6a9170393a73f3b7eb3b22462cb" + integrity sha512-NB1UAZomZlCV/LmJqkLhNTqtKfFXJZAUPcfl/zqG7EfsQdeUJtaWO98SGbuQ3pydJ3fHl2CvI/51OKYlCYYcaw== + dependencies: + "@actions/http-client" "^1.0.11" "@actions/github@^5.0.0": version "5.0.0" @@ -25,9 +27,9 @@ tunnel "0.0.6" "@babel/cli@^7.12.10": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.15.4.tgz#00e21e192b738dec7900c8bb36270e377217c0a4" - integrity sha512-9RhhQ7tgKRcSO/jI3rNLxalLSk30cHqeM8bb+nGOJTyYBDpkoXw/A9QHZ2SYjlslAt4tr90pZQGIEobwWHSIDw== + version "7.15.7" + resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.15.7.tgz#62658abedb786d09c1f70229224b11a65440d7a1" + integrity sha512-YW5wOprO2LzMjoWZ5ZG6jfbY9JnkDxuHDwvnrThnuYtByorova/I0HNXJedrUfwuXFQfYOjcqDA4PU3qlZGZjg== dependencies: commander "^4.0.1" convert-source-map "^1.1.0" @@ -37,7 +39,7 @@ slash "^2.0.0" source-map "^0.5.0" optionalDependencies: - "@nicolo-ribaudo/chokidar-2" "2.1.8-no-fsevents.2" + "@nicolo-ribaudo/chokidar-2" "2.1.8-no-fsevents.3" chokidar "^3.4.0" "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.14.5": @@ -74,9 +76,9 @@ source-map "^0.5.0" "@babel/eslint-parser@^7.12.10": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.15.4.tgz#46385943726291fb3e8db99522c8099b15684387" - integrity sha512-hPMIAmGNbmQzXJIo2P43Zj9UhRmGev5f9nqdBFOWNGDGh6XKmjby79woBvg6y0Jur6yRfQBneDbUQ8ZVc1krFw== + version "7.15.7" + resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.15.7.tgz#2dc3d0ff0ea22bb1e08d93b4eeb1149bf1c75f2d" + integrity sha512-yJkHyomClm6A2Xzb8pdAo4HzYMSXFn1O5zrCYvbFP0yQFvHueLedV8WiEno8yJOKStjUXzBZzJFeWQ7b3YMsqQ== dependencies: eslint-scope "^5.1.1" eslint-visitor-keys "^2.1.0" @@ -202,18 +204,18 @@ "@babel/types" "^7.15.4" "@babel/helper-module-transforms@^7.14.5", "@babel/helper-module-transforms@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.15.4.tgz#962cc629a7f7f9a082dd62d0307fa75fe8788d7c" - integrity sha512-9fHHSGE9zTC++KuXLZcB5FKgvlV83Ox+NLUmQTawovwlJ85+QMhk1CnVk406CQVj97LaWod6KVjl2Sfgw9Aktw== + version "7.15.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.15.7.tgz#7da80c8cbc1f02655d83f8b79d25866afe50d226" + integrity sha512-ZNqjjQG/AuFfekFTY+7nY4RgBSklgTu970c7Rj3m/JOhIu5KPBUuTA9AY6zaKcUvk4g6EbDXdBnhi35FAssdSw== dependencies: "@babel/helper-module-imports" "^7.15.4" "@babel/helper-replace-supers" "^7.15.4" "@babel/helper-simple-access" "^7.15.4" "@babel/helper-split-export-declaration" "^7.15.4" - "@babel/helper-validator-identifier" "^7.14.9" + "@babel/helper-validator-identifier" "^7.15.7" "@babel/template" "^7.15.4" "@babel/traverse" "^7.15.4" - "@babel/types" "^7.15.4" + "@babel/types" "^7.15.6" "@babel/helper-optimise-call-expression@^7.15.4": version "7.15.4" @@ -267,10 +269,10 @@ dependencies: "@babel/types" "^7.15.4" -"@babel/helper-validator-identifier@^7.14.5", "@babel/helper-validator-identifier@^7.14.9": - version "7.14.9" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz#6654d171b2024f6d8ee151bf2509699919131d48" - integrity sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g== +"@babel/helper-validator-identifier@^7.14.5", "@babel/helper-validator-identifier@^7.14.9", "@babel/helper-validator-identifier@^7.15.7": + version "7.15.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" + integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== "@babel/helper-validator-option@^7.14.5": version "7.14.5" @@ -306,9 +308,9 @@ js-tokens "^4.0.0" "@babel/parser@^7.1.0", "@babel/parser@^7.12.11", "@babel/parser@^7.13.16", "@babel/parser@^7.15.4", "@babel/parser@^7.15.5": - version "7.15.6" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.6.tgz#043b9aa3c303c0722e5377fef9197f4cf1796549" - integrity sha512-S/TSCcsRuCkmpUuoWijua0Snt+f3ewU/8spLo+4AXJCZfT0bVCzLD5MuOKdrx0mlAptbKzn5AdgEIIKXxXkz9Q== + version "7.15.7" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.7.tgz#0c3ed4a2eb07b165dfa85b3cc45c727334c4edae" + integrity sha512-rycZXvQ+xS9QyIcJ9HXeDWf1uxqlbVFAUq0Rq0dbc50Zb/+wUe/ehyfzGfm9KZZF0kBejYgxltBXocP+gKdL2g== "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.15.4": version "7.15.4" @@ -1308,22 +1310,10 @@ version "3.2.3" resolved "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.3.tgz#cc332fdd25c08ef0e40f4d33fc3f822a0f98b6f4" -"@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.2": - version "2.1.8-no-fsevents.2" - resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.2.tgz#e324c0a247a5567192dd7180647709d7e2faf94b" - integrity sha512-Fb8WxUFOBQVl+CX4MWet5o7eCc6Pj04rXIwVKZ6h1NnqTo45eOQW6aWyhG25NIODvWFwTDMwBsYxrQ3imxpetg== - dependencies: - anymatch "^2.0.0" - async-each "^1.0.1" - braces "^2.3.2" - glob-parent "^5.1.2" - inherits "^2.0.3" - is-binary-path "^1.0.0" - is-glob "^4.0.0" - normalize-path "^3.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.2.1" - upath "^1.1.1" +"@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.3": + version "2.1.8-no-fsevents.3" + resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz#323d72dd25103d0c4fbdce89dadf574a787b1f9b" + integrity sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ== "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -1347,9 +1337,9 @@ fastq "^1.6.0" "@octokit/auth-token@^2.4.4": - version "2.4.5" - resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.4.5.tgz#568ccfb8cb46f36441fac094ce34f7a875b197f3" - integrity sha512-BpGYsPgJt05M7/L/5FoE1PiAbdxXFZkX/3kDYcsvd1v6UhlnE5e96dTDr0ezX/EFwciQxf3cNV0loipsURU+WA== + version "2.5.0" + resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.5.0.tgz#27c37ea26c205f28443402477ffd261311f21e36" + integrity sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g== dependencies: "@octokit/types" "^6.0.3" @@ -1384,29 +1374,29 @@ "@octokit/types" "^6.0.3" universal-user-agent "^6.0.0" -"@octokit/openapi-types@^10.2.2": - version "10.2.2" - resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-10.2.2.tgz#6c1c839d7d169feabaf1d2a69c79439c75d979cd" - integrity sha512-EVcXQ+ZrC04cg17AMg1ofocWMxHDn17cB66ZHgYc0eUwjFtxS0oBzkyw2VqIrHBwVgtfoYrq1WMQfQmMjUwthw== +"@octokit/openapi-types@^10.6.4": + version "10.6.4" + resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-10.6.4.tgz#c8b5b1f5c60ab7c62858abe2ef57bc709f426a30" + integrity sha512-JVmwWzYTIs6jACYOwD6zu5rdrqGIYsiAsLzTCxdrWIPNKNVjEF6vPTL20shmgJ4qZsq7WPBcLXLsaQD+NLChfg== -"@octokit/plugin-paginate-rest@^2.13.3", "@octokit/plugin-paginate-rest@^2.16.0": - version "2.16.3" - resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.16.3.tgz#6dbf74a12a53e04da6ca731d4c93f20c0b5c6fe9" - integrity sha512-kdc65UEsqze/9fCISq6BxLzeB9qf0vKvKojIfzgwf4tEF+Wy6c9dXnPFE6vgpoDFB1Z5Jek5WFVU6vL1w22+Iw== +"@octokit/plugin-paginate-rest@^2.13.3", "@octokit/plugin-paginate-rest@^2.16.4": + version "2.16.7" + resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.16.7.tgz#d25b6e650ba5a007002986f5fda66958d44e70a4" + integrity sha512-TMlyVhMPx6La1Ud4PSY4YxqAvb9YPEMs/7R1nBSbsw4wNqG73aBqls0r0dRRCWe5Pm0ZUGS9a94N46iAxlOR8A== dependencies: - "@octokit/types" "^6.28.1" + "@octokit/types" "^6.31.3" "@octokit/plugin-request-log@^1.0.4": version "1.0.4" resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz#5e50ed7083a613816b1e4a28aeec5fb7f1462e85" integrity sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA== -"@octokit/plugin-rest-endpoint-methods@^5.1.1", "@octokit/plugin-rest-endpoint-methods@^5.9.0": - version "5.10.4" - resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.10.4.tgz#97e85eb7375e30b9bf193894670f9da205e79408" - integrity sha512-Dh+EAMCYR9RUHwQChH94Skl0lM8Fh99auT8ggck/xTzjJrwVzvsd0YH68oRPqp/HxICzmUjLfaQ9sy1o1sfIiA== +"@octokit/plugin-rest-endpoint-methods@5.11.4", "@octokit/plugin-rest-endpoint-methods@^5.1.1": + version "5.11.4" + resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.11.4.tgz#221dedcbdc45d6bfa54228d469e8c34acb4e0e34" + integrity sha512-iS+GYTijrPUiEiLoDsGJhrbXIvOPfm2+schvr+FxNMs7PeE9Nl4bAMhE8ftfNX3Z1xLxSKwEZh0O7GbWurX5HQ== dependencies: - "@octokit/types" "^6.28.1" + "@octokit/types" "^6.31.2" deprecation "^2.3.1" "@octokit/request-error@^2.0.5", "@octokit/request-error@^2.1.0": @@ -1419,9 +1409,9 @@ once "^1.4.0" "@octokit/request@^5.6.0": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.6.1.tgz#f97aff075c37ab1d427c49082fefeef0dba2d8ce" - integrity sha512-Ls2cfs1OfXaOKzkcxnqw5MR6drMA/zWX/LIS/p8Yjdz7QKTPQLMsB3R+OvoxE6XnXeXEE2X7xe4G4l4X0gRiKQ== + version "5.6.2" + resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.6.2.tgz#1aa74d5da7b9e04ac60ef232edd9a7438dcf32d8" + integrity sha512-je66CvSEVf0jCpRISxkUcCa0UkxmFs6eGDRSbfJtAVwbLH5ceqF+YEyC8lj8ystKyZTy8adWr0qmkY52EfOeLA== dependencies: "@octokit/endpoint" "^6.0.1" "@octokit/request-error" "^2.1.0" @@ -1431,21 +1421,21 @@ universal-user-agent "^6.0.0" "@octokit/rest@^18.6.7": - version "18.10.0" - resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-18.10.0.tgz#8a0add9611253e0e31d3ed5b4bc941a3795a7648" - integrity sha512-esHR5OKy38bccL/sajHqZudZCvmv4yjovMJzyXlphaUo7xykmtOdILGJ3aAm0mFHmMLmPFmDMJXf39cAjNJsrw== + version "18.11.4" + resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-18.11.4.tgz#9fb6d826244554fbf8c110b9064018d7198eec51" + integrity sha512-QplypCyYxqMK05JdMSm/bDWZO8VWWaBdzQ9tbF9rEV9rIEiICh+v6q+Vu/Y5hdze8JJaxfUC+PBC7vrnEkZvZg== dependencies: "@octokit/core" "^3.5.1" - "@octokit/plugin-paginate-rest" "^2.16.0" + "@octokit/plugin-paginate-rest" "^2.16.4" "@octokit/plugin-request-log" "^1.0.4" - "@octokit/plugin-rest-endpoint-methods" "^5.9.0" + "@octokit/plugin-rest-endpoint-methods" "5.11.4" -"@octokit/types@^6.0.3", "@octokit/types@^6.16.1", "@octokit/types@^6.28.1": - version "6.28.1" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.28.1.tgz#ab990d1fe952226055e81c7650480e6bacfb877c" - integrity sha512-XlxDoQLFO5JnFZgKVQTYTvXRsQFfr/GwDUU108NJ9R5yFPkA2qXhTJjYuul3vE4eLXP40FA2nysOu2zd6boE+w== +"@octokit/types@^6.0.3", "@octokit/types@^6.16.1", "@octokit/types@^6.31.2", "@octokit/types@^6.31.3": + version "6.31.3" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.31.3.tgz#14c2961baea853b2bf148d892256357a936343f8" + integrity sha512-IUG3uMpsLHrtEL6sCVXbxCgnbKcgpkS4K7gVEytLDvYYalkK3XcuMCHK1YPD8xJglSJAOAbL4MgXp47rS9G49w== dependencies: - "@octokit/openapi-types" "^10.2.2" + "@octokit/openapi-types" "^10.6.4" "@peculiar/asn1-schema@^2.0.32", "@peculiar/asn1-schema@^2.0.38": version "2.0.38" @@ -1476,66 +1466,66 @@ webcrypto-core "^1.2.0" "@sentry/browser@^6.11.0": - version "6.12.0" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-6.12.0.tgz#970cd68fa117a1e1336fdb373e3b1fa76cd63e2d" - integrity sha512-wsJi1NLOmfwtPNYxEC50dpDcVY7sdYckzwfqz1/zHrede1mtxpqSw+7iP4bHADOJXuF+ObYYTHND0v38GSXznQ== + version "6.13.2" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-6.13.2.tgz#8b731ecf8c3cdd92a4b6893a26f975fd5844056d" + integrity sha512-bkFXK4vAp2UX/4rQY0pj2Iky55Gnwr79CtveoeeMshoLy5iDgZ8gvnLNAz7om4B9OQk1u7NzLEa4IXAmHTUyag== dependencies: - "@sentry/core" "6.12.0" - "@sentry/types" "6.12.0" - "@sentry/utils" "6.12.0" + "@sentry/core" "6.13.2" + "@sentry/types" "6.13.2" + "@sentry/utils" "6.13.2" tslib "^1.9.3" -"@sentry/core@6.12.0": - version "6.12.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-6.12.0.tgz#bc7c5f0785b6a392d9ad47bd9b1fae3f5389996c" - integrity sha512-mU/zdjlzFHzdXDZCPZm8OeCw7c9xsbL49Mq0TrY0KJjLt4CJBkiq5SDTGfRsenBLgTedYhe5Z/J8Z+xVVq+MfQ== +"@sentry/core@6.13.2": + version "6.13.2" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-6.13.2.tgz#2ce164f81667aa89cd116f807d772b4718434583" + integrity sha512-snXNNFLwlS7yYxKTX4DBXebvJK+6ikBWN6noQ1CHowvM3ReFBlrdrs0Z0SsSFEzXm2S4q7f6HHbm66GSQZ/8FQ== dependencies: - "@sentry/hub" "6.12.0" - "@sentry/minimal" "6.12.0" - "@sentry/types" "6.12.0" - "@sentry/utils" "6.12.0" + "@sentry/hub" "6.13.2" + "@sentry/minimal" "6.13.2" + "@sentry/types" "6.13.2" + "@sentry/utils" "6.13.2" tslib "^1.9.3" -"@sentry/hub@6.12.0": - version "6.12.0" - resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-6.12.0.tgz#29e323ab6a95e178fb14fffb684aa0e09707197f" - integrity sha512-yR/UQVU+ukr42bSYpeqvb989SowIXlKBanU0cqLFDmv5LPCnaQB8PGeXwJAwWhQgx44PARhmB82S6Xor8gYNxg== +"@sentry/hub@6.13.2": + version "6.13.2" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-6.13.2.tgz#ebc66fd55c96c7686a53ffd3521b6a63f883bb79" + integrity sha512-sppSuJdNMiMC/vFm/dQowCBh11uTrmvks00fc190YWgxHshodJwXMdpc+pN61VSOmy2QA4MbQ5aMAgHzPzel3A== dependencies: - "@sentry/types" "6.12.0" - "@sentry/utils" "6.12.0" + "@sentry/types" "6.13.2" + "@sentry/utils" "6.13.2" tslib "^1.9.3" -"@sentry/minimal@6.12.0": - version "6.12.0" - resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-6.12.0.tgz#cbe20e95056cedb9709d7d5b2119ef95206a9f8c" - integrity sha512-r3C54Q1KN+xIqUvcgX9DlcoWE7ezWvFk2pSu1Ojx9De81hVqR9u5T3sdSAP2Xma+um0zr6coOtDJG4WtYlOtsw== +"@sentry/minimal@6.13.2": + version "6.13.2" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-6.13.2.tgz#de3ecc62b9463bf56ccdbcf4c75f7ea1aeeebc11" + integrity sha512-6iJfEvHzzpGBHDfLxSHcGObh73XU1OSQKWjuhDOe7UQDyI4BQmTfcXAC+Fr8sm8C/tIsmpVi/XJhs8cubFdSMw== dependencies: - "@sentry/hub" "6.12.0" - "@sentry/types" "6.12.0" + "@sentry/hub" "6.13.2" + "@sentry/types" "6.13.2" tslib "^1.9.3" "@sentry/tracing@^6.11.0": - version "6.12.0" - resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-6.12.0.tgz#a05c8985ee7fed7310b029b147d8f9f14f2a2e67" - integrity sha512-u10QHNknPBzbWSUUNMkvuH53sQd5NaBo6YdNPj4p5b7sE7445Sh0PwBpRbY3ZiUUiwyxV59fx9UQ4yVnPGxZQA== + version "6.13.2" + resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-6.13.2.tgz#512389ba459f48ae75e14f1528ab062dc46e4956" + integrity sha512-bHJz+C/nd6biWTNcYAu91JeRilsvVgaye4POkdzWSmD0XoLWHVMrpCQobGpXe7onkp2noU3YQjhqgtBqPHtnpw== dependencies: - "@sentry/hub" "6.12.0" - "@sentry/minimal" "6.12.0" - "@sentry/types" "6.12.0" - "@sentry/utils" "6.12.0" + "@sentry/hub" "6.13.2" + "@sentry/minimal" "6.13.2" + "@sentry/types" "6.13.2" + "@sentry/utils" "6.13.2" tslib "^1.9.3" -"@sentry/types@6.12.0", "@sentry/types@^6.10.0": - version "6.12.0" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.12.0.tgz#b7395688a79403c6df8d8bb8d81deb8222519853" - integrity sha512-urtgLzE4EDMAYQHYdkgC0Ei9QvLajodK1ntg71bGn0Pm84QUpaqpPDfHRU+i6jLeteyC7kWwa5O5W1m/jrjGXA== +"@sentry/types@6.13.2", "@sentry/types@^6.10.0": + version "6.13.2" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.13.2.tgz#8388d5b92ea8608936e7aae842801dc90e0184e6" + integrity sha512-6WjGj/VjjN8LZDtqJH5ikeB1o39rO1gYS6anBxiS3d0sXNBb3Ux0pNNDFoBxQpOhmdDHXYS57MEptX9EV82gmg== -"@sentry/utils@6.12.0": - version "6.12.0" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.12.0.tgz#3de261e8d11bdfdc7add64a3065d43517802e975" - integrity sha512-oRHQ7TH5TSsJqoP9Gqq25Jvn9LKexXfAh/OoKwjMhYCGKGhqpDNUIZVgl9DWsGw5A5N5xnQyLOxDfyRV5RshdA== +"@sentry/utils@6.13.2": + version "6.13.2" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.13.2.tgz#fb8010e7b67cc8c084d8067d64ef25289269cda5" + integrity sha512-foF4PbxqPMWNbuqdXkdoOmKm3quu3PP7Q7j/0pXkri4DtCuvF/lKY92mbY0V9rHS/phCoj+3/Se5JvM2ymh2/w== dependencies: - "@sentry/types" "6.12.0" + "@sentry/types" "6.13.2" tslib "^1.9.3" "@sinonjs/commons@^1.7.0": @@ -1718,9 +1708,9 @@ pretty-format "^26.0.0" "@types/json-schema@^7.0.7", "@types/json-schema@^7.0.8": - version "7.0.8" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.8.tgz#edf1bf1dbf4e04413ca8e5b17b3b7d7d54b59818" - integrity sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg== + version "7.0.9" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" + integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== "@types/linkifyjs@^2.1.3": version "2.1.4" @@ -1730,9 +1720,9 @@ "@types/react" "*" "@types/lodash@^4.14.168": - version "4.14.172" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.172.tgz#aad774c28e7bfd7a67de25408e03ee5a8c3d028a" - integrity sha512-/BHF5HAx3em7/KkzVKm3LrsD6HZAXuXO1AJZQ3cRRBZj4oHZDviWPYu0aEplAqDFNHZPW6d3G7KN+ONcCCC7pw== + version "4.14.175" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.175.tgz#b78dfa959192b01fae0ad90e166478769b215f45" + integrity sha512-XmdEOrKQ8a1Y/yxQFOMbC47G/V2VDO1GvMRnl4O75M4GW/abC5tnfzadQYkqEveqRM1dEJGFFegfPNA2vvx2iw== "@types/mdast@^3.0.0": version "3.0.10" @@ -1752,14 +1742,14 @@ integrity sha512-jhMOZSS0UGYTS9pqvt6q3wtT3uvOSve5piTEmTMx3zzTuBLvSIMxSIBIc3d5lajVD5h4xc41AMZD2M5orN3PxA== "@types/node@*": - version "16.9.1" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.9.1.tgz#0611b37db4246c937feef529ddcc018cf8e35708" - integrity sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g== + version "16.10.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.10.2.tgz#5764ca9aa94470adb4e1185fe2e9f19458992b2e" + integrity sha512-zCclL4/rx+W5SQTzFs9wyvvyCwoK9QtBpratqz2IYJ3O8Umrn0m3nsTv0wQBk9sRGpvUe9CwPDrQFB10f1FIjQ== "@types/node@^14.14.22": - version "14.17.16" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.16.tgz#2b9252bd4fdf0393696190cd9550901dd967c777" - integrity sha512-WiFf2izl01P1CpeY8WqFAeKWwByMueBEkND38EcN8N68qb0aDG3oIS1P5MhAX5kUdr469qRyqsY/MjanLjsFbQ== + version "14.17.20" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.20.tgz#74cc80438fd0467dc4377ee5bbad89a886df3c10" + integrity sha512-gI5Sl30tmhXsqkNvopFydP7ASc4c2cLfGNQrVKN3X90ADFWFsPEsotm/8JHSUJQKTHbwowAHtcJPeyVhtKv0TQ== "@types/normalize-package-data@^2.4.0": version "2.4.1" @@ -1782,9 +1772,9 @@ integrity sha512-ARATsLdrGPUnaBvxLhUlnltcMgn7pQG312S8ccdYlnyijabrX9RN/KN/iGj9Am96CoW8e/K9628BA7Bv4XHdrA== "@types/prettier@^2.0.0": - version "2.3.2" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.3.2.tgz#fc8c2825e4ed2142473b4a81064e6e081463d1b3" - integrity sha512-eI5Yrz3Qv4KPUa/nSIAi0h+qX0XyewOliug5F2QAtuRg6Kjg6jfmxe1GIwoIRhZspD1A0RP8ANrPwvEXXtRFog== + version "2.4.1" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.4.1.tgz#e1303048d5389563e130f5bdd89d37a99acb75eb" + integrity sha512-Fo79ojj3vdEZOHg3wR9ksAMRz4P3S5fDB5e/YWZiFnyFQI1WY2Vftu9XoXVVtJfxB7Bpce/QTqWSSntkz2Znrw== "@types/prop-types@*": version "15.7.4" @@ -1823,9 +1813,9 @@ redux "^4.0.0" "@types/react-transition-group@^4.4.0": - version "4.4.2" - resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.2.tgz#38890fd9db68bf1f2252b99a942998dc7877c5b3" - integrity sha512-KibDWL6nshuOJ0fu8ll7QnV/LVTo3PzQ9aCPnRUYPfX7eZohHwLIdNHj7pftanREzHNP4/nJa8oeM73uSiavMQ== + version "4.4.3" + resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.3.tgz#b0994da0a7023d67dbb4a8910a62112bc00d5688" + integrity sha512-fUx5muOWSYP8Bw2BUQ9M9RK9+W1XBK/7FLJ8PTQpnpTEkn0ccyMffyEQvan4C3h53gHdx7KE5Qrxi/LnUGQtdg== dependencies: "@types/react" "*" @@ -1888,72 +1878,73 @@ integrity sha512-3NoqvZC2W5gAC5DZbTpCeJ251vGQmgcWIHQJGq2J240HY6ErQ9aWKkwfoKJlHLx+A83WPNTZ9+3cd2ILxbvr1w== "@typescript-eslint/eslint-plugin@^4.17.0": - version "4.31.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.31.1.tgz#e938603a136f01dcabeece069da5fb2e331d4498" - integrity sha512-UDqhWmd5i0TvPLmbK5xY3UZB0zEGseF+DHPghZ37Sb83Qd3p8ujhvAtkU4OF46Ka5Pm5kWvFIx0cCTBFKo0alA== + version "4.32.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.32.0.tgz#46d2370ae9311092f2a6f7246d28357daf2d4e89" + integrity sha512-+OWTuWRSbWI1KDK8iEyG/6uK2rTm3kpS38wuVifGUTDB6kjEuNrzBI1MUtxnkneuWG/23QehABe2zHHrj+4yuA== dependencies: - "@typescript-eslint/experimental-utils" "4.31.1" - "@typescript-eslint/scope-manager" "4.31.1" + "@typescript-eslint/experimental-utils" "4.32.0" + "@typescript-eslint/scope-manager" "4.32.0" debug "^4.3.1" functional-red-black-tree "^1.0.1" + ignore "^5.1.8" regexpp "^3.1.0" semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/experimental-utils@4.31.1": - version "4.31.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.31.1.tgz#0c900f832f270b88e13e51753647b02d08371ce5" - integrity sha512-NtoPsqmcSsWty0mcL5nTZXMf7Ei0Xr2MT8jWjXMVgRK0/1qeQ2jZzLFUh4QtyJ4+/lPUyMw5cSfeeME+Zrtp9Q== +"@typescript-eslint/experimental-utils@4.32.0": + version "4.32.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.32.0.tgz#53a8267d16ca5a79134739129871966c56a59dc4" + integrity sha512-WLoXcc+cQufxRYjTWr4kFt0DyEv6hDgSaFqYhIzQZ05cF+kXfqXdUh+//kgquPJVUBbL3oQGKQxwPbLxHRqm6A== dependencies: "@types/json-schema" "^7.0.7" - "@typescript-eslint/scope-manager" "4.31.1" - "@typescript-eslint/types" "4.31.1" - "@typescript-eslint/typescript-estree" "4.31.1" + "@typescript-eslint/scope-manager" "4.32.0" + "@typescript-eslint/types" "4.32.0" + "@typescript-eslint/typescript-estree" "4.32.0" eslint-scope "^5.1.1" eslint-utils "^3.0.0" "@typescript-eslint/parser@^4.17.0": - version "4.31.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.31.1.tgz#8f9a2672033e6f6d33b1c0260eebdc0ddf539064" - integrity sha512-dnVZDB6FhpIby6yVbHkwTKkn2ypjVIfAR9nh+kYsA/ZL0JlTsd22BiDjouotisY3Irmd3OW1qlk9EI5R8GrvRQ== + version "4.32.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.32.0.tgz#751ecca0e2fecd3d44484a9b3049ffc1871616e5" + integrity sha512-lhtYqQ2iEPV5JqV7K+uOVlPePjClj4dOw7K4/Z1F2yvjIUvyr13yJnDzkK6uon4BjHYuHy3EG0c2Z9jEhFk56w== dependencies: - "@typescript-eslint/scope-manager" "4.31.1" - "@typescript-eslint/types" "4.31.1" - "@typescript-eslint/typescript-estree" "4.31.1" + "@typescript-eslint/scope-manager" "4.32.0" + "@typescript-eslint/types" "4.32.0" + "@typescript-eslint/typescript-estree" "4.32.0" debug "^4.3.1" -"@typescript-eslint/scope-manager@4.31.1": - version "4.31.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.31.1.tgz#0c21e8501f608d6a25c842fcf59541ef4f1ab561" - integrity sha512-N1Uhn6SqNtU2XpFSkD4oA+F0PfKdWHyr4bTX0xTj8NRx1314gBDRL1LUuZd5+L3oP+wo6hCbZpaa1in6SwMcVQ== +"@typescript-eslint/scope-manager@4.32.0": + version "4.32.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.32.0.tgz#e03c8668f8b954072b3f944d5b799c0c9225a7d5" + integrity sha512-DK+fMSHdM216C0OM/KR1lHXjP1CNtVIhJ54kQxfOE6x8UGFAjha8cXgDMBEIYS2XCYjjCtvTkjQYwL3uvGOo0w== dependencies: - "@typescript-eslint/types" "4.31.1" - "@typescript-eslint/visitor-keys" "4.31.1" + "@typescript-eslint/types" "4.32.0" + "@typescript-eslint/visitor-keys" "4.32.0" -"@typescript-eslint/types@4.31.1": - version "4.31.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.31.1.tgz#5f255b695627a13401d2fdba5f7138bc79450d66" - integrity sha512-kixltt51ZJGKENNW88IY5MYqTBA8FR0Md8QdGbJD2pKZ+D5IvxjTYDNtJPDxFBiXmka2aJsITdB1BtO1fsgmsQ== +"@typescript-eslint/types@4.32.0": + version "4.32.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.32.0.tgz#52c633c18da47aee09449144bf59565ab36df00d" + integrity sha512-LE7Z7BAv0E2UvqzogssGf1x7GPpUalgG07nGCBYb1oK4mFsOiFC/VrSMKbZQzFJdN2JL5XYmsx7C7FX9p9ns0w== -"@typescript-eslint/typescript-estree@4.31.1": - version "4.31.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.31.1.tgz#4a04d5232cf1031232b7124a9c0310b577a62d17" - integrity sha512-EGHkbsUvjFrvRnusk6yFGqrqMBTue5E5ROnS5puj3laGQPasVUgwhrxfcgkdHNFECHAewpvELE1Gjv0XO3mdWg== +"@typescript-eslint/typescript-estree@4.32.0": + version "4.32.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.32.0.tgz#db00ccc41ccedc8d7367ea3f50c6994b8efa9f3b" + integrity sha512-tRYCgJ3g1UjMw1cGG8Yn1KzOzNlQ6u1h9AmEtPhb5V5a1TmiHWcRyF/Ic+91M4f43QeChyYlVTcf3DvDTZR9vw== dependencies: - "@typescript-eslint/types" "4.31.1" - "@typescript-eslint/visitor-keys" "4.31.1" + "@typescript-eslint/types" "4.32.0" + "@typescript-eslint/visitor-keys" "4.32.0" debug "^4.3.1" globby "^11.0.3" is-glob "^4.0.1" semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/visitor-keys@4.31.1": - version "4.31.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.31.1.tgz#f2e7a14c7f20c4ae07d7fc3c5878c4441a1da9cc" - integrity sha512-PCncP8hEqKw6SOJY+3St4LVtoZpPPn+Zlpm7KW5xnviMhdqcsBty4Lsg4J/VECpJjw1CkROaZhH4B8M1OfnXTQ== +"@typescript-eslint/visitor-keys@4.32.0": + version "4.32.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.32.0.tgz#455ba8b51242f2722a497ffae29313f33b14cb7f" + integrity sha512-e7NE0qz8W+atzv3Cy9qaQ7BTLwWsm084Z0c4nIO2l3Bp6u9WIgdqCgyPyV5oSPDMIW3b20H59OOCmVk3jw3Ptw== dependencies: - "@typescript-eslint/types" "4.31.1" + "@typescript-eslint/types" "4.32.0" eslint-visitor-keys "^2.0.0" "@wojtekmaj/enzyme-adapter-react-17@^0.6.1": @@ -2087,7 +2078,7 @@ ansi-regex@^4.1.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== -ansi-regex@^5.0.0: +ansi-regex@^5.0.0, ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== @@ -2149,7 +2140,7 @@ arr-union@^3.1.0: resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= -array-includes@^3.1.2, array-includes@^3.1.3: +array-includes@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.3.tgz#c7f619b382ad2afaf5326cddfdc0afc61af7690a" integrity sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A== @@ -2171,34 +2162,33 @@ array-unique@^0.3.2: integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= array.prototype.filter@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array.prototype.filter/-/array.prototype.filter-1.0.0.tgz#24d63e38983cdc6bf023a3c574b2f2a3f384c301" - integrity sha512-TfO1gz+tLm+Bswq0FBOXPqAchtCr2Rn48T8dLJoRFl8NoEosjZmzptmuo1X8aZBzZcqsR1W8U761tjACJtngTQ== + version "1.0.1" + resolved "https://registry.yarnpkg.com/array.prototype.filter/-/array.prototype.filter-1.0.1.tgz#20688792acdb97a09488eaaee9eebbf3966aae21" + integrity sha512-Dk3Ty7N42Odk7PjU/Ci3zT4pLj20YvuVnneG/58ICM6bt4Ij5kZaJTVQ9TSaWaIECX2sFyz4KItkVZqHNnciqw== dependencies: call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.18.0" + es-abstract "^1.19.0" es-array-method-boxes-properly "^1.0.0" - is-string "^1.0.5" + is-string "^1.0.7" array.prototype.flat@^1.2.3: - version "1.2.4" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz#6ef638b43312bd401b4c6199fdec7e2dc9e9a123" - integrity sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg== + version "1.2.5" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz#07e0975d84bbc7c48cd1879d609e682598d33e13" + integrity sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg== dependencies: - call-bind "^1.0.0" + call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.18.0-next.1" + es-abstract "^1.19.0" array.prototype.flatmap@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.4.tgz#94cfd47cc1556ec0747d97f7c7738c58122004c9" - integrity sha512-r9Z0zYoxqHz60vvQbWEdXIEtCwHF0yxaWfno9qzXeNHvfyl3BZqygmGzb84dsubyaXLH4husF+NFgMSdpZhk2Q== + version "1.2.5" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.5.tgz#908dc82d8a406930fdf38598d51e7411d18d4446" + integrity sha512-08u6rVyi1Lj7oqWbS9nUxliETrtIROT4XGTA4D/LWGten6E3ocm7cy9SIrmNHOL5XVbVuckUp3X6Xyg8/zpvHA== dependencies: call-bind "^1.0.0" define-properties "^1.1.3" - es-abstract "^1.18.0-next.1" - function-bind "^1.1.1" + es-abstract "^1.19.0" arrify@^1.0.1: version "1.0.1" @@ -2239,11 +2229,6 @@ astral-regex@^2.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== -async-each@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" - integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -2255,13 +2240,13 @@ atob@^2.1.2: integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== autoprefixer@^9.8.6: - version "9.8.6" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.6.tgz#3b73594ca1bf9266320c5acf1588d74dea74210f" - integrity sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg== + version "9.8.7" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.7.tgz#e3c12de18a800af1a1a8155fbc01dc7de29ea184" + integrity sha512-7Hg99B1eTH5+LgmUBUSmov1Z3bsggQJS7v3IMGo6wcScnbRuvtMc871J9J+4bSbIqa9LSX/zypFXJ8sXHpMJeQ== dependencies: browserslist "^4.12.0" caniuse-lite "^1.0.30001109" - colorette "^1.2.1" + nanocolors "^0.2.8" normalize-range "^0.1.2" num2fraction "^1.2.2" postcss "^7.0.32" @@ -2339,12 +2324,12 @@ babel-plugin-polyfill-corejs2@^0.2.2: semver "^6.1.1" babel-plugin-polyfill-corejs3@^0.2.2: - version "0.2.4" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.4.tgz#68cb81316b0e8d9d721a92e0009ec6ecd4cd2ca9" - integrity sha512-z3HnJE5TY/j4EFEa/qpQMSbcUJZ5JQi+3UFjXzn6pQCmIKc5Ug5j98SuYyH+m4xQnvKlMDIW4plLfgyVnd0IcQ== + version "0.2.5" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.5.tgz#2779846a16a1652244ae268b1e906ada107faf92" + integrity sha512-ninF5MQNwAX9Z7c9ED+H2pGt1mXdP4TqzlHKyPIYmJIYz0N+++uwdM7RnJukklhzJ54Q84vA4ZJkgs7lu5vqcw== dependencies: "@babel/helper-define-polyfill-provider" "^0.2.2" - core-js-compat "^3.14.0" + core-js-compat "^3.16.2" babel-plugin-polyfill-regenerator@^0.2.2: version "0.2.2" @@ -2436,11 +2421,6 @@ big.js@^5.2.2: resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== -binary-extensions@^1.0.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" - integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== - binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" @@ -2469,7 +2449,7 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^2.3.1, braces@^2.3.2: +braces@^2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== @@ -2507,16 +2487,16 @@ browser-request@^0.3.3: resolved "https://registry.yarnpkg.com/browser-request/-/browser-request-0.3.3.tgz#9ece5b5aca89a29932242e18bf933def9876cc17" integrity sha1-ns5bWsqJopkyJC4Yv5M975h2zBc= -browserslist@^4.12.0, browserslist@^4.16.6, browserslist@^4.17.0: - version "4.17.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.0.tgz#1fcd81ec75b41d6d4994fb0831b92ac18c01649c" - integrity sha512-g2BJ2a0nEYvEFQC208q8mVAhfNwpZ5Mu8BwgtCdZKO3qx98HChmeg448fPdUzld8aFmfLgVh7yymqV+q1lJZ5g== +browserslist@^4.12.0, browserslist@^4.16.6, browserslist@^4.17.1: + version "4.17.2" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.2.tgz#aa15dbd2fab399a399fe4df601bb09363c5458a6" + integrity sha512-jSDZyqJmkKMEMi7SZAgX5UltFdR5NAO43vY0AwTpu4X3sGH7GLLQ83KiUomgrnvZRCeW0yPPnKqnxPqQOER9zQ== dependencies: - caniuse-lite "^1.0.30001254" - colorette "^1.3.0" - electron-to-chromium "^1.3.830" + caniuse-lite "^1.0.30001261" + electron-to-chromium "^1.3.854" escalade "^3.1.1" - node-releases "^1.1.75" + nanocolors "^0.2.12" + node-releases "^1.1.76" bs58@^4.0.1: version "4.0.1" @@ -2610,10 +2590,10 @@ camelcase@^6.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== -caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001254: - version "1.0.30001257" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001257.tgz#150aaf649a48bee531104cfeda57f92ce587f6e5" - integrity sha512-JN49KplOgHSXpIsVSF+LUyhD8PUp6xPpAXeRrrcBh4KBeP7W864jHn6RvzJgDlrReyeVjMFJL3PLpPvKIxlIHA== +caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001261: + version "1.0.30001264" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001264.tgz#88f625a60efb6724c7c62ac698bc8dbd9757e55b" + integrity sha512-Ftfqqfcs/ePiUmyaySsQ4PUsdcYyXG2rfoBVsk3iY1ahHaJEw65vfb7Suzqm+cEkwwPIv/XWkg27iCpRavH4zA== capture-exit@^2.0.0: version "2.0.0" @@ -2833,11 +2813,6 @@ color-name@^1.1.4, color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -colorette@^1.2.1, colorette@^1.2.2, colorette@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" - integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== - combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" @@ -2912,12 +2887,12 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= -core-js-compat@^3.14.0, core-js-compat@^3.16.0: - version "3.17.3" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.17.3.tgz#b39c8e4dec71ecdc735c653ce5233466e561324e" - integrity sha512-+in61CKYs4hQERiADCJsdgewpdl/X0GhEX77pjKgbeibXviIt2oxEjTc8O2fqHX8mDdBrDvX8MYD/RYsBv4OiA== +core-js-compat@^3.16.0, core-js-compat@^3.16.2: + version "3.18.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.18.1.tgz#01942a0877caf9c6e5007c027183cf0bdae6a191" + integrity sha512-XJMYx58zo4W0kLPmIingVZA10+7TuKrMLPt83+EzDmxFJQUMcTVVmQ+n5JP4r6Z14qSzhQBRi3NSWoeVyKKXUg== dependencies: - browserslist "^4.17.0" + browserslist "^4.17.1" semver "7.0.0" core-js@^1.0.0: @@ -3069,9 +3044,9 @@ data-urls@^2.0.0: whatwg-url "^8.0.0" date-fns@^2.0.1: - version "2.23.0" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.23.0.tgz#4e886c941659af0cf7b30fafdd1eaa37e88788a9" - integrity sha512-5ycpauovVyAk0kXNZz6ZoB9AYMZB4DObse7P3BPWmyEjXNORTI8EJ6X0uaSAq4sCHzM1uajzrkr6HnsLQpxGXA== + version "2.24.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.24.0.tgz#7d86dc0d93c87b76b63d213b4413337cfd1c105d" + integrity sha512-6ujwvwgPID6zbI0o7UbURi2vlLDR9uP26+tW6Lg+Ji3w7dd0i3DOcjcClLjLPranT60SSEFBwdSyYwn/ZkPIuw== date-names@^0.1.11: version "0.1.13" @@ -3301,10 +3276,10 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -electron-to-chromium@^1.3.830: - version "1.3.839" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.839.tgz#27a5b21468e9fefb0e328a029403617f20acec9c" - integrity sha512-0O7uPs9LJNjQ/U5mW78qW8gXv9H6Ba3DHZ5/yt8aBsvomOWDkV3MddT7enUYvLQEUVOURjWmgJJWVZ3K98tIwQ== +electron-to-chromium@^1.3.854: + version "1.3.857" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.857.tgz#dcc239ff8a12b6e4b501e6a5ad20fd0d5a3210f9" + integrity sha512-a5kIr2lajm4bJ5E4D3fp8Y/BRB0Dx2VOcCRE5Gtb679mXIME/OFhWler8Gy2ksrf8gFX+EFCSIGA33FB3gqYpg== emittery@^0.7.1: version "0.7.2" @@ -3415,10 +3390,10 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.18.0, es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2, es-abstract@^1.18.2, es-abstract@^1.18.5, es-abstract@^1.18.6: - version "1.18.6" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.6.tgz#2c44e3ea7a6255039164d26559777a6d978cb456" - integrity sha512-kAeIT4cku5eNLNuUKhlmtuk1/TRZvQoYccn6TO0cSVdf1kzB0T7+dYuVK9MWM7l+/53W2Q8M7N2c6MQvhXFcUQ== +es-abstract@^1.18.0-next.2, es-abstract@^1.18.2, es-abstract@^1.18.5, es-abstract@^1.19.0, es-abstract@^1.19.1: + version "1.19.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3" + integrity sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w== dependencies: call-bind "^1.0.2" es-to-primitive "^1.2.1" @@ -3431,7 +3406,9 @@ es-abstract@^1.18.0, es-abstract@^1.18.0-next.1, es-abstract@^1.18.0-next.2, es- is-callable "^1.2.4" is-negative-zero "^2.0.1" is-regex "^1.1.4" + is-shared-array-buffer "^1.0.1" is-string "^1.0.7" + is-weakref "^1.0.1" object-inspect "^1.11.0" object-keys "^1.1.1" object.assign "^4.1.2" @@ -3555,22 +3532,23 @@ eslint-plugin-react-hooks@^4.2.0: integrity sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ== eslint-plugin-react@^7.22.0: - version "7.25.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.25.1.tgz#9286b7cd9bf917d40309760f403e53016eda8331" - integrity sha512-P4j9K1dHoFXxDNP05AtixcJEvIT6ht8FhYKsrkY0MPCPaUMYijhpWwNiRDZVtA8KFuZOkGSeft6QwH8KuVpJug== + version "7.26.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.26.1.tgz#41bcfe3e39e6a5ac040971c1af94437c80daa40e" + integrity sha512-Lug0+NOFXeOE+ORZ5pbsh6mSKjBKXDXItUD2sQoT+5Yl0eoT82DqnXeTMfUare4QVCn9QwXbfzO/dBLjLXwVjQ== dependencies: array-includes "^3.1.3" array.prototype.flatmap "^1.2.4" doctrine "^2.1.0" estraverse "^5.2.0" - has "^1.0.3" jsx-ast-utils "^2.4.1 || ^3.0.0" minimatch "^3.0.4" object.entries "^1.1.4" object.fromentries "^2.0.4" + object.hasown "^1.0.0" object.values "^1.1.4" prop-types "^15.7.2" resolve "^2.0.0-next.3" + semver "^6.3.0" string.prototype.matchall "^4.0.5" eslint-rule-composer@^0.3.0: @@ -3800,9 +3778,9 @@ expect@^26.6.2: jest-regex-util "^26.0.0" ext@^1.1.2: - version "1.5.0" - resolved "https://registry.yarnpkg.com/ext/-/ext-1.5.0.tgz#e93b97ae0cb23f8370380f6107d2d2b7887687ad" - integrity sha512-+ONcYoWj/SoQwUofMr94aGu05Ou4FepKi7N7b+O8T4jVfyIsZQV1/xeS8jpaBzF0csAk0KLXoHCxU7cKYZjo1Q== + version "1.6.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.6.0.tgz#3871d50641e874cc172e2b53f919842d19db4c52" + integrity sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg== dependencies: type "^2.5.0" @@ -4092,13 +4070,13 @@ function-bind@^1.1.1: integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== function.prototype.name@^1.1.0, function.prototype.name@^1.1.2, function.prototype.name@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.4.tgz#e4ea839b9d3672ae99d0efd9f38d9191c5eaac83" - integrity sha512-iqy1pIotY/RmhdFZygSSlW0wko2yxkSCKqsuv4pr8QESohpYyG/Z7B/XXvPRKTJS//960rgguE5mSRUsDdaJrQ== + version "1.1.5" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" + integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== dependencies: call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.18.0-next.2" + es-abstract "^1.19.0" functions-have-names "^1.2.2" functional-red-black-tree@^1.0.1: @@ -4192,9 +4170,9 @@ glob-to-regexp@^0.4.1: integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: - version "7.1.7" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" - integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -4255,7 +4233,7 @@ gonzales-pe@^4.3.0: dependencies: minimist "^1.2.5" -graceful-fs@^4.1.11, graceful-fs@^4.2.4: +graceful-fs@^4.2.4: version "4.2.8" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== @@ -4508,9 +4486,9 @@ import-lazy@^4.0.0: integrity sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw== import-local@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.2.tgz#a8cfd0431d1de4a2199703d003e3e62364fa6db6" - integrity sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA== + version "3.0.3" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.3.tgz#4d51c2c495ca9393da259ec66b62e022920211e0" + integrity sha512-bE9iaUY3CXH8Cwfan/abDKAxe1KGT9kyGsBPqf6DMK/z0a2OzAsrukeYNgIH6cH5Xr452jb1TUL8rSfCLjZ9uA== dependencies: pkg-dir "^4.2.0" resolve-cwd "^3.0.0" @@ -4621,13 +4599,6 @@ is-bigint@^1.0.1, is-bigint@^1.0.3: dependencies: has-bigints "^1.0.1" -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= - dependencies: - binary-extensions "^1.0.0" - is-binary-path@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" @@ -4666,9 +4637,9 @@ is-ci@^2.0.0: ci-info "^2.0.0" is-core-module@^2.2.0, is-core-module@^2.5.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.6.0.tgz#d7553b2526fe59b92ba3e40c8df757ec8a709e19" - integrity sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ== + version "2.7.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.7.0.tgz#3c0ef7d31b4acfc574f80c58409d568a836848e3" + integrity sha512-ByY+tjCciCr+9nLryBYcSD50EOGWt95c7tIsKTG1J2ixKKXPvF7Ej3AVd+UfDydAJom3biBGDBALaO79ktwgEQ== dependencies: has "^1.0.3" @@ -4793,9 +4764,9 @@ is-generator-function@^1.0.10: has-tostringtag "^1.0.0" is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" - integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: is-extglob "^2.1.1" @@ -4890,6 +4861,11 @@ is-set@^2.0.1, is-set@^2.0.2: resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.2.tgz#90755fa4c2562dc1c5d4024760d6119b94ca18ec" integrity sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g== +is-shared-array-buffer@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz#97b0c85fbdacb59c9c446fe653b82cf2b5b7cfe6" + integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA== + is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" @@ -5010,9 +4986,9 @@ isstream@~0.1.2: integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= istanbul-lib-coverage@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" - integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== + version "3.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.1.tgz#e8900b3ed6069759229cf30f7067388d148aeb5e" + integrity sha512-GvCYYTxaCPqwMjobtVcVKvSHtAGe48MNhGjpK8LtVF8K0ISX7hCKl85LgtuaSneWVyQmaGcW3iXVV3GaZSLpmQ== istanbul-lib-instrument@^4.0.0, istanbul-lib-instrument@^4.0.3: version "4.0.3" @@ -5607,17 +5583,17 @@ jsprim@^1.2.2: verror "1.10.0" "jsx-ast-utils@^2.4.1 || ^3.0.0": - version "3.2.0" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz#41108d2cec408c3453c1bbe8a4aae9e1e2bd8f82" - integrity sha512-EIsmt3O3ljsU6sot/J4E1zDRxfBNrhjyf/OKjlydwgEimQuznlM4Wv7U+ueONJMyEn1WRE0K8dhi3dVAXYT24Q== + version "3.2.1" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.2.1.tgz#720b97bfe7d901b927d87c3773637ae8ea48781b" + integrity sha512-uP5vu8xfy2F9A6LGC22KO7e2/vGTS1MhP+18f++ZNlf0Ohaxbc9nIEwHAsejlJKyzfZzU5UIhe5ItYkitcZnZA== dependencies: - array-includes "^3.1.2" + array-includes "^3.1.3" object.assign "^4.1.2" jszip@^3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.7.0.tgz#9b8b995a4e7c9024653ce743e902076a82fdf4e6" - integrity sha512-Y2OlFIzrDOPWUnpU0LORIcDn2xN7rC9yKffFM/7pGhQuhO+SUhfm2trkJ/S5amjFvem0Y+1EALz/MEPkvHXVNw== + version "3.7.1" + resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.7.1.tgz#bd63401221c15625a1228c556ca8a68da6fda3d9" + integrity sha512-ghL0tz1XG9ZEmRMcEN2vt7xabrDdqHHeykgARpmZ0BiIctWxM47Vt63ZO2dnp4QYt/xJVLLy5Zv1l/xRdh2byg== dependencies: lie "~3.3.0" pako "~1.0.2" @@ -5846,9 +5822,9 @@ map-obj@^1.0.0: integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= map-obj@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.2.1.tgz#e4ea399dbc979ae735c83c863dd31bdf364277b7" - integrity sha512-+WA2/1sPmDj1dlvvJmB5G6JKfY9dpn7EVBUL06+y6PoljPkh+6V1QihwxNkbcGxCRjt2b0F9K0taiCuo7MbdFQ== + version "4.3.0" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a" + integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ== map-visit@^1.0.0: version "1.0.0" @@ -5864,7 +5840,7 @@ mathml-tag-names@^2.1.3: "matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop": version "13.0.0" - resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/2515d07c8fc3bf5e1afc8352e3e330cca30dde85" + resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/a7a08fd760e6e99c4cc631fca42e6f06af9d594e" dependencies: "@babel/runtime" "^7.12.5" another-json "^0.2.0" @@ -5994,7 +5970,7 @@ micromark@~2.11.0: debug "^4.0.0" parse-entities "^2.0.0" -micromatch@^3.1.10, micromatch@^3.1.4: +micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== @@ -6021,17 +5997,17 @@ micromatch@^4.0.2, micromatch@^4.0.4: braces "^3.0.1" picomatch "^2.2.3" -mime-db@1.49.0: - version "1.49.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.49.0.tgz#f3dfde60c99e9cf3bc9701d687778f537001cbed" - integrity sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA== +mime-db@1.50.0: + version "1.50.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.50.0.tgz#abd4ac94e98d3c0e185016c67ab45d5fde40c11f" + integrity sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A== mime-types@^2.1.12, mime-types@~2.1.19: - version "2.1.32" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.32.tgz#1d00e89e7de7fe02008db61001d9e02852670fd5" - integrity sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A== + version "2.1.33" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.33.tgz#1fa12a904472fafd068e48d9e8401f74d3f70edb" + integrity sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g== dependencies: - mime-db "1.49.0" + mime-db "1.50.0" mimic-fn@^2.1.0: version "2.1.0" @@ -6094,10 +6070,15 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -nanoid@^3.1.23: - version "3.1.25" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.25.tgz#09ca32747c0e543f0e1814b7d3793477f9c8e152" - integrity sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q== +nanocolors@^0.2.12, nanocolors@^0.2.2, nanocolors@^0.2.8: + version "0.2.12" + resolved "https://registry.yarnpkg.com/nanocolors/-/nanocolors-0.2.12.tgz#4d05932e70116078673ea4cc6699a1c56cc77777" + integrity sha512-SFNdALvzW+rVlzqexid6epYdt8H9Zol7xDoQarioEFcFN0JHo4CYNztAxmtfgGTVRCmFlEOqqhBpoFGKqSAMug== + +nanoid@^3.1.25: + version "3.1.28" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.28.tgz#3c01bac14cb6c5680569014cc65a2f26424c6bd4" + integrity sha512-gSu9VZ2HtmoKYe/lmyPFES5nknFrHa+/DT9muUFWFMi6Jh9E1I7bkvlQ8xxf1Kos9pi9o8lBnIOkatMhKX/YUw== nanomatch@^1.2.9: version "1.2.13" @@ -6160,9 +6141,11 @@ node-fetch@^1.0.1: is-stream "^1.0.1" node-fetch@^2.6.1: - version "2.6.2" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.2.tgz#986996818b73785e47b1965cc34eb093a1d464d0" - integrity sha512-aLoxToI6RfZ+0NOjmWAgn9+LEd30YCkJKFSyWacNZdEKTit/ZMcKjGkTRo8uWEsnIb/hfKecNPEbln02PdWbcA== + version "2.6.5" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.5.tgz#42735537d7f080a7e5f78b6c549b7146be1742fd" + integrity sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ== + dependencies: + whatwg-url "^5.0.0" node-int64@^0.4.0: version "0.4.0" @@ -6186,10 +6169,10 @@ node-notifier@^8.0.0: uuid "^8.3.0" which "^2.0.2" -node-releases@^1.1.75: - version "1.1.75" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.75.tgz#6dd8c876b9897a1b8e5a02de26afa79bb54ebbfe" - integrity sha512-Qe5OUajvqrqDSy6wrWFmMwfJ0jVgwiw4T3KqmbTcZ62qW0gQkheXYhcFM1+lOVcGUoRxcEcfyvFMAnDgaF1VWw== +node-releases@^1.1.76: + version "1.1.77" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.77.tgz#50b0cfede855dd374e7585bf228ff34e57c1c32e" + integrity sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ== normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: version "2.5.0" @@ -6319,33 +6302,40 @@ object.assign@^4.1.0, object.assign@^4.1.2: object-keys "^1.1.1" object.entries@^1.1.1, object.entries@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.4.tgz#43ccf9a50bc5fd5b649d45ab1a579f24e088cafd" - integrity sha512-h4LWKWE+wKQGhtMjZEBud7uLGhqyLwj8fpHOarZhD2uY3C9cRtk57VQ89ke3moByLXMedqs3XCHzyb4AmA2DjA== + version "1.1.5" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.5.tgz#e1acdd17c4de2cd96d5a08487cfb9db84d881861" + integrity sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g== dependencies: call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.18.2" + es-abstract "^1.19.1" object.fromentries@^2.0.0, object.fromentries@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.4.tgz#26e1ba5c4571c5c6f0890cef4473066456a120b8" - integrity sha512-EsFBshs5RUUpQEY1D4q/m59kMfz4YJvxuNCJcv/jWwOJr34EaVnG11ZrZa0UHB3wnzV1wx8m58T4hQL8IuNXlQ== + version "2.0.5" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.5.tgz#7b37b205109c21e741e605727fe8b0ad5fa08251" + integrity sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw== dependencies: call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.18.0-next.2" - has "^1.0.3" + es-abstract "^1.19.1" object.getprototypeof@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/object.getprototypeof/-/object.getprototypeof-1.0.2.tgz#a993d88ca63d68f9c328186dd17d76d4188b3624" - integrity sha512-7KoF7BcUJi6YZ+7g9XqbaJzxsmp4jSjUw8TkOSdN/GF9ZAhDM/ssERDddC+WR556niTKtCk9HtwwsbnaEeWNlg== + version "1.0.3" + resolved "https://registry.yarnpkg.com/object.getprototypeof/-/object.getprototypeof-1.0.3.tgz#92e0c2320ffd3990f3378c9c3489929af31a190f" + integrity sha512-EP3J0rXZA4OuvSl98wYa0hY5zHUJo2kGrp2eYDro0yCe3yrKm7xtXDgbpT+YPK2RzdtdvJtm0IfaAyXeehQR0w== dependencies: call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.18.6" - reflect.getprototypeof "^1.0.0" + es-abstract "^1.19.1" + reflect.getprototypeof "^1.0.2" + +object.hasown@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.0.tgz#7232ed266f34d197d15cac5880232f7a4790afe5" + integrity sha512-MhjYRfj3GBlhSkDHo6QmvgjRLXQ2zndabdf3nX0yTyZK9rPfxb6uRpAac8HXNLy1GpqWtZ81Qh4v3uOls2sRAg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.19.1" object.pick@^1.3.0: version "1.3.0" @@ -6355,13 +6345,13 @@ object.pick@^1.3.0: isobject "^3.0.1" object.values@^1.1.0, object.values@^1.1.1, object.values@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.4.tgz#0d273762833e816b693a637d30073e7051535b30" - integrity sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg== + version "1.1.5" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.5.tgz#959f63e3ce9ef108720333082131e4a459b716ac" + integrity sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg== dependencies: call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.18.2" + es-abstract "^1.19.1" once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" @@ -6682,21 +6672,20 @@ postcss-value-parser@^4.1.0: integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== postcss@^7.0.14, postcss@^7.0.2, postcss@^7.0.21, postcss@^7.0.26, postcss@^7.0.32, postcss@^7.0.35, postcss@^7.0.6: - version "7.0.36" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.36.tgz#056f8cffa939662a8f5905950c07d5285644dfcb" - integrity sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw== + version "7.0.38" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.38.tgz#5365a9c5126643d977046ad239f60eadda2491d6" + integrity sha512-wNrSHWjHDQJR/IZL5IKGxRtFgrYNaAA/UrkW2WqbtZO6uxSLMxMN+s2iqUMwnAWm3fMROlDYZB41dr0Mt7vBwQ== dependencies: - chalk "^2.4.2" + nanocolors "^0.2.2" source-map "^0.6.1" - supports-color "^6.1.0" postcss@^8.0.2: - version "8.3.6" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.6.tgz#2730dd76a97969f37f53b9a6096197be311cc4ea" - integrity sha512-wG1cc/JhRgdqB6WHEuyLTedf3KIRuD0hG6ldkFEZNCjRxiC+3i6kkWUUbiJQayP28iwG35cEmAbe98585BYV0A== + version "8.3.8" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.8.tgz#9ebe2a127396b4b4570ae9f7770e7fb83db2bac1" + integrity sha512-GT5bTjjZnwDifajzczOC+r3FI3Cu+PgPvrsjhQdRqa2kTJ4968/X9CUce9xttIB0xOs5c6xf0TCWZo/y9lF6bA== dependencies: - colorette "^1.2.2" - nanoid "^3.1.23" + nanocolors "^0.2.2" + nanoid "^3.1.25" source-map-js "^0.6.2" posthog-js@1.12.2: @@ -6789,11 +6778,11 @@ punycode@^2.1.0, punycode@^2.1.1: integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== pvtsutils@^1.1.6, pvtsutils@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/pvtsutils/-/pvtsutils-1.2.0.tgz#619e4767093d23cd600482600c16f4c36d3025bb" - integrity sha512-IDefMJEQl7HX0FP2hIKJFnAR11klP1js2ixCrOaMhe3kXFK6RQ2ABUCuwWaaD4ib0hSbh2fGTICvWJJhDfNecA== + version "1.2.1" + resolved "https://registry.yarnpkg.com/pvtsutils/-/pvtsutils-1.2.1.tgz#8212e846ca9afb21e40cebb0691755649f9f498a" + integrity sha512-Q867jEr30lBR2YSFFLZ0/XsEvpweqH6Kj096wmlRAFXrdRGPCNq2iz9B5Tk085EZ+OBZyYAVA5UhPkjSHGrUzQ== dependencies: - tslib "^2.2.0" + tslib "^2.3.1" pvutils@latest: version "1.0.17" @@ -7012,7 +7001,16 @@ read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" -readable-stream@^2.0.2, readable-stream@~2.3.6: +readable-stream@^3.1.1: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -7025,24 +7023,6 @@ readable-stream@^2.0.2, readable-stream@~2.3.6: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.1.1: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readdirp@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" - integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== - dependencies: - graceful-fs "^4.1.11" - micromatch "^3.1.10" - readable-stream "^2.0.2" - readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -7065,14 +7045,14 @@ redux@^4.0.0, redux@^4.0.4: dependencies: "@babel/runtime" "^7.9.2" -reflect.getprototypeof@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.1.tgz#f113f15e19d103d60b8d52ce7e0d45867efdddfc" - integrity sha512-z0FhUSaxXxnFQi+YyGfAvUJjCGPPwe0AO51LU/HtRLj/+a4LROrmSD6eYA3zr6aAK6GSbl8BCh/m5SAqUdAgTg== +reflect.getprototypeof@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.2.tgz#dd231808828913fd2198e151eb3e213d9dddf708" + integrity sha512-C1+ANgX50UkWlntmOJ8SD1VTuk28+7X1ackBdfXzLQG5+bmriEMHvBaor9YlotCfBHo277q/YWd/JKEOzr5Dxg== dependencies: call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.18.6" + es-abstract "^1.19.1" get-intrinsic "^1.1.1" which-builtin-type "^1.1.1" @@ -7493,9 +7473,9 @@ side-channel@^1.0.4: object-inspect "^1.9.0" signal-exit@^3.0.0, signal-exit@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" - integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== + version "3.0.5" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.5.tgz#9e3e8cc0c75a99472b44321033a7702e7738252f" + integrity sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ== sisteransi@^1.0.5: version "1.0.5" @@ -7567,7 +7547,7 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@^0.5.16, source-map-support@^0.5.20, source-map-support@^0.5.6: +source-map-support@^0.5.16, source-map-support@^0.5.6: version "0.5.20" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9" integrity sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw== @@ -7671,12 +7651,11 @@ stack-utils@^1.0.1: escape-string-regexp "^2.0.0" stack-utils@^2.0.2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.4.tgz#bf967ae2813d3d2d1e1f59a4408676495c8112ab" - integrity sha512-ERg+H//lSSYlZhBIUu+wJnqg30AbyBbpZlIhcshpn7BNzpoRODZgfyr9J+8ERf3ooC6af3u7Lcl01nleau7MrA== + version "2.0.5" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5" + integrity sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA== dependencies: escape-string-regexp "^2.0.0" - source-map-support "^0.5.20" static-extend@^0.1.1: version "0.1.2" @@ -7703,14 +7682,14 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" - integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== dependencies: emoji-regex "^8.0.0" is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.0" + strip-ansi "^6.0.1" string.prototype.matchall@^4.0.5: version "4.0.5" @@ -7732,13 +7711,13 @@ string.prototype.repeat@^0.2.0: integrity sha1-q6Nt4I3O5qWjN9SbLqHaGyj8Ds8= string.prototype.trim@^1.2.1: - version "1.2.4" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.4.tgz#6014689baf5efaf106ad031a5fa45157666ed1bd" - integrity sha512-hWCk/iqf7lp0/AgTF7/ddO1IWtSNPASjlzCicV5irAVdE1grjsneK26YG6xACMBEdCvO8fUST0UzDMh/2Qy+9Q== + version "1.2.5" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.5.tgz#a587bcc8bfad8cb9829a577f5de30dd170c1682c" + integrity sha512-Lnh17webJVsD6ECeovpVN17RlAKjmz4rF9S+8Y45CkMc/ufVpTkU3vZIyIC7sllQ1FCvObZnnCdNs/HXTUOTlg== dependencies: call-bind "^1.0.2" define-properties "^1.1.3" - es-abstract "^1.18.0-next.2" + es-abstract "^1.19.1" string.prototype.trimend@^1.0.4: version "1.0.4" @@ -7777,12 +7756,12 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" -strip-ansi@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" - integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: - ansi-regex "^5.0.0" + ansi-regex "^5.0.1" strip-bom@^4.0.0: version "4.0.0" @@ -7940,16 +7919,16 @@ symbol-tree@^3.2.4: integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== table@^6.0.4, table@^6.6.0: - version "6.7.1" - resolved "https://registry.yarnpkg.com/table/-/table-6.7.1.tgz#ee05592b7143831a8c94f3cee6aae4c1ccef33e2" - integrity sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg== + version "6.7.2" + resolved "https://registry.yarnpkg.com/table/-/table-6.7.2.tgz#a8d39b9f5966693ca8b0feba270a78722cbaf3b0" + integrity sha512-UFZK67uvyNivLeQbVtkiUs8Uuuxv24aSL4/Vil2PJVtMgU8Lx0CYkP12uCGa3kjyQzOSgV1+z9Wkb82fCGsO0g== dependencies: ajv "^8.0.1" lodash.clonedeep "^4.5.0" lodash.truncate "^4.4.2" slice-ansi "^4.0.0" - string-width "^4.2.0" - strip-ansi "^6.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" tar-js@^0.3.0: version "0.3.0" @@ -8067,6 +8046,11 @@ tr46@^2.1.0: dependencies: punycode "^2.1.1" +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + tree-kill@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" @@ -8279,11 +8263,6 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" -upath@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" - integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== - uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -8406,9 +8385,9 @@ w3c-xmlserializer@^2.0.0: xml-name-validator "^3.0.0" walk@^2.3.14: - version "2.3.14" - resolved "https://registry.yarnpkg.com/walk/-/walk-2.3.14.tgz#60ec8631cfd23276ae1e7363ce11d626452e1ef3" - integrity sha512-5skcWAUmySj6hkBdH6B6+3ddMjVQYH5Qy9QGbPmN8kVmLteXk+yVXg+yfk1nbX30EYakahLrr8iPcCxJQSCBeg== + version "2.3.15" + resolved "https://registry.yarnpkg.com/walk/-/walk-2.3.15.tgz#1b4611e959d656426bc521e2da5db3acecae2424" + integrity sha512-4eRTBZljBfIISK1Vnt69Gvr2w/wc3U6Vtrw7qiN5iqYJPH7LElcYh/iU4XWhdCy2dZqv1ToMyYlybDylfG/5Vg== dependencies: foreachasync "^3.0.0" @@ -8430,6 +8409,11 @@ webcrypto-core@^1.2.0: pvtsutils "^1.2.0" tslib "^2.3.1" +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + webidl-conversions@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" @@ -8467,6 +8451,14 @@ whatwg-mimetype@^2.3.0: resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + whatwg-url@^8.0.0, whatwg-url@^8.5.0: version "8.7.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77" @@ -8683,9 +8675,9 @@ yargs@^15.4.1: yargs-parser "^18.1.2" yargs@^17.0.1: - version "17.1.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.1.1.tgz#c2a8091564bdb196f7c0a67c1d12e5b85b8067ba" - integrity sha512-c2k48R0PwKIqKhPMWjeiF6y2xY/gPMUlro0sgxqXpbOIohWiLNXWslsootttv7E1e73QPAMQSg5FeySbVcpsPQ== + version "17.2.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.2.1.tgz#e2c95b9796a0e1f7f3bf4427863b42e0418191ea" + integrity sha512-XfR8du6ua4K6uLGm5S6fA+FIJom/MdJcFNVY8geLlp2v8GYbOXD4EB1tPNZsRn4vBzKGMgb5DRZMeWuFc2GO8Q== dependencies: cliui "^7.0.2" escalade "^3.1.1" From 9a16b4636fc912e2c728189d4cafc3726768fcdd Mon Sep 17 00:00:00 2001 From: Faye Duxovni Date: Wed, 8 Sep 2021 13:55:31 -0400 Subject: [PATCH 072/143] Make cross-signing dialog clearer and more context-aware - Don't show loading spinners while waiting for user action - When checking if there are other devices we can verify against, only look for devices that are actually cross-signed. - Adjust displayed options depending on whether other devices and/or recovery keys exist, and add an option to reset cross-signing keys if necessary. - Various minor clarifying adjustments to UI styling/text Signed-off-by: Faye Duxovni --- res/css/_components.scss | 1 + .../structures/auth/_CompleteSecurity.scss | 13 ++ .../structures/auth/_SetupEncryptionBody.scss | 24 +++ .../structures/auth/CompleteSecurity.tsx | 35 +++- .../structures/auth/SetupEncryptionBody.tsx | 150 +++++++++++++----- .../views/right_panel/EncryptionInfo.tsx | 18 ++- .../verification/VerificationShowSas.tsx | 32 ++-- src/i18n/strings/en_EN.json | 20 ++- src/stores/SetupEncryptionStore.ts | 73 +++++++-- 9 files changed, 278 insertions(+), 88 deletions(-) create mode 100644 res/css/structures/auth/_SetupEncryptionBody.scss diff --git a/res/css/_components.scss b/res/css/_components.scss index ffaec43b68..fa5538e692 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -38,6 +38,7 @@ @import "./structures/_ViewSource.scss"; @import "./structures/auth/_CompleteSecurity.scss"; @import "./structures/auth/_Login.scss"; +@import "./structures/auth/_SetupEncryptionBody.scss"; @import "./views/audio_messages/_AudioPlayer.scss"; @import "./views/audio_messages/_PlayPauseButton.scss"; @import "./views/audio_messages/_PlaybackContainer.scss"; diff --git a/res/css/structures/auth/_CompleteSecurity.scss b/res/css/structures/auth/_CompleteSecurity.scss index 80e7aaada0..566507211c 100644 --- a/res/css/structures/auth/_CompleteSecurity.scss +++ b/res/css/structures/auth/_CompleteSecurity.scss @@ -33,6 +33,19 @@ limitations under the License. margin: 0 auto; } +.mx_CompleteSecurity_skip { + mask: url('$(res)/img/feather-customised/cancel.svg'); + mask-repeat: no-repeat; + mask-position: center; + mask-size: cover; + width: 18px; + height: 18px; + background-color: $dialog-close-fg-color; + cursor: pointer; + position: absolute; + right: 24px; +} + .mx_CompleteSecurity_body { font-size: $font-15px; } diff --git a/res/css/structures/auth/_SetupEncryptionBody.scss b/res/css/structures/auth/_SetupEncryptionBody.scss new file mode 100644 index 0000000000..24ee114544 --- /dev/null +++ b/res/css/structures/auth/_SetupEncryptionBody.scss @@ -0,0 +1,24 @@ +/* +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_SetupEncryptionBody_reset { + color: $light-fg-color; + margin-top: $font-14px; + + a.mx_SetupEncryptionBody_reset_link:is(:link, :hover, :visited) { + color: $warning-color; + } +} diff --git a/src/components/structures/auth/CompleteSecurity.tsx b/src/components/structures/auth/CompleteSecurity.tsx index 8c3d5e80a0..1e46f0e657 100644 --- a/src/components/structures/auth/CompleteSecurity.tsx +++ b/src/components/structures/auth/CompleteSecurity.tsx @@ -20,6 +20,7 @@ import * as sdk from '../../../index'; import { SetupEncryptionStore, Phase } from '../../../stores/SetupEncryptionStore'; import SetupEncryptionBody from "./SetupEncryptionBody"; import { replaceableComponent } from "../../../utils/replaceableComponent"; +import AccessibleButton from '../../views/elements/AccessibleButton'; interface IProps { onFinished: () => void; @@ -27,6 +28,7 @@ interface IProps { interface IState { phase: Phase; + lostKeys: boolean; } @replaceableComponent("structures.auth.CompleteSecurity") @@ -36,12 +38,17 @@ export default class CompleteSecurity extends React.Component { const store = SetupEncryptionStore.sharedInstance(); store.on("update", this.onStoreUpdate); store.start(); - this.state = { phase: store.phase }; + this.state = { phase: store.phase, lostKeys: store.lostKeys() }; } private onStoreUpdate = (): void => { const store = SetupEncryptionStore.sharedInstance(); - this.setState({ phase: store.phase }); + this.setState({ phase: store.phase, lostKeys: store.lostKeys() }); + }; + + private onSkipClick = (): void => { + const store = SetupEncryptionStore.sharedInstance(); + store.skip(); }; public componentWillUnmount(): void { @@ -53,15 +60,20 @@ export default class CompleteSecurity extends React.Component { public render() { const AuthPage = sdk.getComponent("auth.AuthPage"); const CompleteSecurityBody = sdk.getComponent("auth.CompleteSecurityBody"); - const { phase } = this.state; + const { phase, lostKeys } = this.state; let icon; let title; if (phase === Phase.Loading) { return null; } else if (phase === Phase.Intro) { - icon = ; - title = _t("Verify this login"); + if (lostKeys) { + icon = ; + title = _t("Unable to verify this login"); + } else { + icon = ; + title = _t("Verify this login"); + } } else if (phase === Phase.Done) { icon = ; title = _t("Session verified"); @@ -71,16 +83,29 @@ export default class CompleteSecurity extends React.Component { } else if (phase === Phase.Busy) { icon = ; title = _t("Verify this login"); + } else if (phase === Phase.ConfirmReset) { + icon = ; + title = _t("Really reset verification keys?"); + } else if (phase === Phase.Finished) { + // SetupEncryptionBody will take care of calling onFinished, we don't need to do anything } else { throw new Error(`Unknown phase ${phase}`); } + let skipButton; + if (phase === Phase.Intro || phase === Phase.ConfirmReset) { + skipButton = ( + + ); + } + return (

{ icon } { title } + { skipButton }

diff --git a/src/components/structures/auth/SetupEncryptionBody.tsx b/src/components/structures/auth/SetupEncryptionBody.tsx index 87d74a5a79..e2b1aebcfd 100644 --- a/src/components/structures/auth/SetupEncryptionBody.tsx +++ b/src/components/structures/auth/SetupEncryptionBody.tsx @@ -46,6 +46,7 @@ interface IState { phase: Phase; verificationRequest: VerificationRequest; backupInfo: IKeyBackupInfo; + lostKeys: boolean; } @replaceableComponent("structures.auth.SetupEncryptionBody") @@ -62,6 +63,7 @@ export default class SetupEncryptionBody extends React.Component // Because of the latter, it lives in the state. verificationRequest: store.verificationRequest, backupInfo: store.backupInfo, + lostKeys: store.lostKeys(), }; } @@ -75,6 +77,7 @@ export default class SetupEncryptionBody extends React.Component phase: store.phase, verificationRequest: store.verificationRequest, backupInfo: store.backupInfo, + lostKeys: store.lostKeys(), }); }; @@ -105,11 +108,6 @@ export default class SetupEncryptionBody extends React.Component }); }; - private onSkipClick = () => { - const store = SetupEncryptionStore.sharedInstance(); - store.skip(); - }; - private onSkipConfirmClick = () => { const store = SetupEncryptionStore.sharedInstance(); store.skipConfirm(); @@ -120,6 +118,22 @@ export default class SetupEncryptionBody extends React.Component store.returnAfterSkip(); }; + private onResetClick = (ev: React.MouseEvent) => { + ev.preventDefault(); + const store = SetupEncryptionStore.sharedInstance(); + store.reset(); + }; + + private onResetConfirmClick = () => { + const store = SetupEncryptionStore.sharedInstance(); + store.resetConfirm(); + }; + + private onResetBackClick = () => { + const store = SetupEncryptionStore.sharedInstance(); + store.returnAfterReset(); + }; + private onDoneClick = () => { const store = SetupEncryptionStore.sharedInstance(); store.done(); @@ -132,6 +146,7 @@ export default class SetupEncryptionBody extends React.Component public render() { const { phase, + lostKeys, } = this.state; if (this.state.verificationRequest) { @@ -143,43 +158,67 @@ export default class SetupEncryptionBody extends React.Component isRoomEncrypted={false} />; } else if (phase === Phase.Intro) { - const store = SetupEncryptionStore.sharedInstance(); - let recoveryKeyPrompt; - if (store.keyInfo && keyHasPassphrase(store.keyInfo)) { - recoveryKeyPrompt = _t("Use Security Key or Phrase"); - } else if (store.keyInfo) { - recoveryKeyPrompt = _t("Use Security Key"); - } + if (lostKeys) { + return ( +
+

{ _t( + "It looks like you don't have a Security Key or any other devices you can " + + "verify against. This device will not be able to access old encrypted messages. " + + "In order to verify your identity on this device, you'll need to reset " + + "your verification keys.", + ) }

- let useRecoveryKeyButton; - if (recoveryKeyPrompt) { - useRecoveryKeyButton = - { recoveryKeyPrompt } - ; - } - - let verifyButton; - if (store.hasDevicesToVerifyAgainst) { - verifyButton = - { _t("Use another login") } - ; - } - - return ( -
-

{ _t( - "Verify your identity to access encrypted messages and prove your identity to others.", - ) }

- -
- { verifyButton } - { useRecoveryKeyButton } - - { _t("Skip") } - +
+ + { _t("Proceed with reset") } + +
-
- ); + ); + } else { + const store = SetupEncryptionStore.sharedInstance(); + let recoveryKeyPrompt; + if (store.keyInfo && keyHasPassphrase(store.keyInfo)) { + recoveryKeyPrompt = _t("Verify with Security Key or Phrase"); + } else if (store.keyInfo) { + recoveryKeyPrompt = _t("Verify with Security Key"); + } + + let useRecoveryKeyButton; + if (recoveryKeyPrompt) { + useRecoveryKeyButton = + { recoveryKeyPrompt } + ; + } + + let verifyButton; + if (store.hasDevicesToVerifyAgainst) { + verifyButton = + { _t("Verify with another login") } + ; + } + + return ( +
+

{ _t( + "Verify your identity to access encrypted messages and prove your identity to others.", + ) }

+ +
+ { verifyButton } + { useRecoveryKeyButton } +
+
+ { _t("Forgotten or lost all recovery methods? Reset all", null, { + a: (sub) => { sub }, + }) } +
+
+ ); + } } else if (phase === Phase.Done) { let message; if (this.state.backupInfo) { @@ -215,14 +254,13 @@ export default class SetupEncryptionBody extends React.Component ) }

- { _t("Skip") } + { _t("I'll verify later") } { _t("Go Back") } @@ -230,6 +268,30 @@ export default class SetupEncryptionBody extends React.Component
); + } else if (phase === Phase.ConfirmReset) { + return ( +
+

{ _t( + "Resetting your verification keys cannot be undone. After resetting, " + + "you won't have access to old encrypted messages, and any friends who " + + "have previously verified you will see security warnings until you " + + "re-verify with them.", + ) }

+

{ _t( + "Please only proceed if you're sure you've lost all of your other " + + "devices and your security key.", + ) }

+ +
+ + { _t("Proceed with reset") } + + + { _t("Go Back") } + +
+
+ ); } else if (phase === Phase.Busy || phase === Phase.Loading) { return ; } else { diff --git a/src/components/views/right_panel/EncryptionInfo.tsx b/src/components/views/right_panel/EncryptionInfo.tsx index 34aeb8b88a..c9a4b3b84c 100644 --- a/src/components/views/right_panel/EncryptionInfo.tsx +++ b/src/components/views/right_panel/EncryptionInfo.tsx @@ -49,16 +49,18 @@ const EncryptionInfo: React.FC = ({ isSelfVerification, }: IProps) => { let content: JSX.Element; - if (waitingForOtherParty || waitingForNetwork) { + if (waitingForOtherParty && isSelfVerification) { + content = ( +
+ { _t("To proceed, please accept the verification request on your other login.") } +
+ ); + } else if (waitingForOtherParty || waitingForNetwork) { let text: string; if (waitingForOtherParty) { - if (isSelfVerification) { - text = _t("Accept on your other login…"); - } else { - text = _t("Waiting for %(displayName)s to accept…", { - displayName: (member as User).displayName || (member as RoomMember).name || member.userId, - }); - } + text = _t("Waiting for %(displayName)s to accept…", { + displayName: (member as User).displayName || (member as RoomMember).name || member.userId, + }); } else { text = _t("Accepting…"); } diff --git a/src/components/views/verification/VerificationShowSas.tsx b/src/components/views/verification/VerificationShowSas.tsx index 2b9ea5da96..609255a565 100644 --- a/src/components/views/verification/VerificationShowSas.tsx +++ b/src/components/views/verification/VerificationShowSas.tsx @@ -121,24 +121,24 @@ export default class VerificationShowSas extends React.Component } let confirm; - if (this.state.pending || this.state.cancelling) { + if (this.state.pending && this.props.isSelf) { + let text; + // device shouldn't be null in this situation but it can be, eg. if the device is + // logged out during verification + if (this.props.device) { + text = _t("Waiting for you to verify on your other session, %(deviceName)s (%(deviceId)s)…", { + deviceName: this.props.device ? this.props.device.getDisplayName() : '', + deviceId: this.props.device ? this.props.device.deviceId : '', + }); + } else { + text = _t("Waiting for you to verify on your other session…"); + } + confirm =

{ text }

; + } else if (this.state.pending || this.state.cancelling) { let text; if (this.state.pending) { - if (this.props.isSelf) { - // device shouldn't be null in this situation but it can be, eg. if the device is - // logged out during verification - if (this.props.device) { - text = _t("Waiting for your other session, %(deviceName)s (%(deviceId)s), to verify…", { - deviceName: this.props.device ? this.props.device.getDisplayName() : '', - deviceId: this.props.device ? this.props.device.deviceId : '', - }); - } else { - text = _t("Waiting for your other session to verify…"); - } - } else { - const { displayName } = this.props; - text = _t("Waiting for %(displayName)s to verify…", { displayName }); - } + const { displayName } = this.props; + text = _t("Waiting for %(displayName)s to verify…", { displayName }); } else { text = _t("Cancelling…"); } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index b5d90f6671..71f13d87b4 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -938,8 +938,8 @@ "Verify this session by confirming the following number appears on its screen.": "Verify this session by confirming the following number appears on its screen.", "Verify this user by confirming the following number appears on their screen.": "Verify this user by confirming the following number appears on their screen.", "Unable to find a supported verification method.": "Unable to find a supported verification method.", - "Waiting for your other session, %(deviceName)s (%(deviceId)s), to verify…": "Waiting for your other session, %(deviceName)s (%(deviceId)s), to verify…", - "Waiting for your other session to verify…": "Waiting for your other session to verify…", + "Waiting for you to verify on your other session, %(deviceName)s (%(deviceId)s)…": "Waiting for you to verify on your other session, %(deviceName)s (%(deviceId)s)…", + "Waiting for you to verify on your other session…": "Waiting for you to verify on your other session…", "Waiting for %(displayName)s to verify…": "Waiting for %(displayName)s to verify…", "Cancelling…": "Cancelling…", "They match": "They match", @@ -1791,7 +1791,7 @@ "In encrypted rooms, like this one, URL previews are disabled by default to ensure that your homeserver (where the previews are generated) cannot gather information about links you see in this room.": "In encrypted rooms, like this one, URL previews are disabled by default to ensure that your homeserver (where the previews are generated) cannot gather information about links you see in this room.", "When someone puts a URL in their message, a URL preview can be shown to give more information about that link such as the title, description, and an image from the website.": "When someone puts a URL in their message, a URL preview can be shown to give more information about that link such as the title, description, and an image from the website.", "Back": "Back", - "Accept on your other login…": "Accept on your other login…", + "To proceed, please accept the verification request on your other login.": "To proceed, please accept the verification request on your other login.", "Waiting for %(displayName)s to accept…": "Waiting for %(displayName)s to accept…", "Accepting…": "Accepting…", "Start Verification": "Start Verification", @@ -2949,8 +2949,11 @@ "Could not load user profile": "Could not load user profile", "Decrypted event source": "Decrypted event source", "Original event source": "Original event source", + "Unable to verify this login": "Unable to verify this login", "Verify this login": "Verify this login", "Session verified": "Session verified", + "Really reset verification keys?": "Really reset verification keys?", + "Skip verification for now": "Skip verification for now", "Failed to send email": "Failed to send email", "The email address linked to your account must be entered.": "The email address linked to your account must be entered.", "A new password must be entered.": "A new password must be entered.", @@ -3004,13 +3007,18 @@ "Create account": "Create account", "Host account on": "Host account on", "Decide where your account is hosted": "Decide where your account is hosted", - "Use Security Key or Phrase": "Use Security Key or Phrase", - "Use Security Key": "Use Security Key", - "Use another login": "Use another login", + "It looks like you don't have a Security Key or any other devices you can verify against. This device will not be able to access old encrypted messages. In order to verify your identity on this device, you'll need to reset your verification keys.": "It looks like you don't have a Security Key or any other devices you can verify against. This device will not be able to access old encrypted messages. In order to verify your identity on this device, you'll need to reset your verification keys.", + "Proceed with reset": "Proceed with reset", + "Verify with Security Key or Phrase": "Verify with Security Key or Phrase", + "Verify with Security Key": "Verify with Security Key", + "Verify with another login": "Verify with another login", "Verify your identity to access encrypted messages and prove your identity to others.": "Verify your identity to access encrypted messages and prove your identity to others.", "Your new session is now verified. It has access to your encrypted messages, and other users will see it as trusted.": "Your new session is now verified. It has access to your encrypted messages, and other users will see it as trusted.", "Your new session is now verified. Other users will see it as trusted.": "Your new session is now verified. Other users will see it as trusted.", "Without verifying, you won’t have access to all your messages and may appear as untrusted to others.": "Without verifying, you won’t have access to all your messages and may appear as untrusted to others.", + "I'll verify later": "I'll verify later", + "Resetting your verification keys cannot be undone. After resetting, you won't have access to old encrypted messages, and any friends who have previously verified you will see security warnings until you re-verify with them.": "Resetting your verification keys cannot be undone. After resetting, you won't have access to old encrypted messages, and any friends who have previously verified you will see security warnings until you re-verify with them.", + "Please only proceed if you're sure you've lost all of your other devices and your security key.": "Please only proceed if you're sure you've lost all of your other devices and your security key.", "Failed to re-authenticate due to a homeserver problem": "Failed to re-authenticate due to a homeserver problem", "Incorrect password": "Incorrect password", "Failed to re-authenticate": "Failed to re-authenticate", diff --git a/src/stores/SetupEncryptionStore.ts b/src/stores/SetupEncryptionStore.ts index 14119af576..e3d4d42591 100644 --- a/src/stores/SetupEncryptionStore.ts +++ b/src/stores/SetupEncryptionStore.ts @@ -22,6 +22,9 @@ import { PHASE_DONE as VERIF_PHASE_DONE } from "matrix-js-sdk/src/crypto/verific import { MatrixClientPeg } from '../MatrixClientPeg'; import { accessSecretStorage, AccessCancelledError } from '../SecurityManager'; +import Modal from '../Modal'; +import InteractiveAuthDialog from '../components/views/dialogs/InteractiveAuthDialog'; +import { _t } from '../languageHandler'; import { logger } from "matrix-js-sdk/src/logger"; @@ -32,6 +35,7 @@ export enum Phase { Done = 3, // final done stage, but still showing UX ConfirmSkip = 4, Finished = 5, // UX can be closed + ConfirmReset = 6, } export class SetupEncryptionStore extends EventEmitter { @@ -103,20 +107,23 @@ export class SetupEncryptionStore extends EventEmitter { this.keyInfo = keys[this.keyId]; } - // do we have any other devices which are E2EE which we can verify against? + // do we have any other verified devices which are E2EE which we can verify against? const dehydratedDevice = await cli.getDehydratedDevice(); - this.hasDevicesToVerifyAgainst = cli.getStoredDevicesForUser(cli.getUserId()).some( + const ownUserId = cli.getUserId(); + const crossSigningInfo = cli.getStoredCrossSigningForUser(ownUserId); + this.hasDevicesToVerifyAgainst = cli.getStoredDevicesForUser(ownUserId).some( device => device.getIdentityKey() && - (!dehydratedDevice || (device.deviceId != dehydratedDevice.device_id)), + (!dehydratedDevice || (device.deviceId != dehydratedDevice.device_id)) && + crossSigningInfo.checkDeviceTrust( + crossSigningInfo, + device, + false, + true, + ).isCrossSigningVerified(), ); - if (!this.hasDevicesToVerifyAgainst && !this.keyInfo) { - // skip before we can even render anything. - this.phase = Phase.Finished; - } else { - this.phase = Phase.Intro; - } + this.phase = Phase.Intro; this.emit("update"); } @@ -208,6 +215,50 @@ export class SetupEncryptionStore extends EventEmitter { this.emit("update"); } + public reset(): void { + this.phase = Phase.ConfirmReset; + this.emit("update"); + } + + public async resetConfirm(): Promise { + try { + // If we've gotten here, the user presumably lost their + // secret storage key if they had one. Start by resetting + // secret storage and setting up a new recovery key, then + // create new cross-signing keys once that succeeds. + await accessSecretStorage(async () => { + const cli = MatrixClientPeg.get(); + await cli.bootstrapCrossSigning({ + authUploadDeviceSigningKeys: async (makeRequest) => { + const { finished } = Modal.createTrackedDialog( + 'Cross-signing keys dialog', '', InteractiveAuthDialog, + { + title: _t("Setting up keys"), + matrixClient: cli, + makeRequest, + }, + ); + const [confirmed] = await finished; + if (!confirmed) { + throw new Error("Cross-signing key upload auth canceled"); + } + }, + setupNewCrossSigning: true, + }); + this.phase = Phase.Finished; + }, true); + } catch (e) { + console.error("Error resetting cross-signing", e); + this.phase = Phase.Intro; + } + this.emit("update"); + } + + public returnAfterReset(): void { + this.phase = Phase.Intro; + this.emit("update"); + } + public done(): void { this.phase = Phase.Finished; this.emit("update"); @@ -226,4 +277,8 @@ export class SetupEncryptionStore extends EventEmitter { request.on("change", this.onVerificationRequestChange); this.emit("update"); } + + public lostKeys(): boolean { + return !this.hasDevicesToVerifyAgainst && !this.keyInfo; + } } From fa800796c78978d74634c549c074ef70b3395e4f Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 6 Oct 2021 09:41:57 +0100 Subject: [PATCH 073/143] Respect tombstones in locally known rooms for Space children --- src/components/structures/SpaceHierarchy.tsx | 43 ++++++++++++++++---- src/stores/SpaceStore.ts | 31 ++++++++++++-- 2 files changed, 61 insertions(+), 13 deletions(-) diff --git a/src/components/structures/SpaceHierarchy.tsx b/src/components/structures/SpaceHierarchy.tsx index ed87b04c8a..8e1a472984 100644 --- a/src/components/structures/SpaceHierarchy.tsx +++ b/src/components/structures/SpaceHierarchy.tsx @@ -15,17 +15,17 @@ limitations under the License. */ import React, { + Dispatch, + KeyboardEvent, + KeyboardEventHandler, ReactNode, + SetStateAction, useCallback, + useContext, useEffect, useMemo, useRef, useState, - KeyboardEvent, - KeyboardEventHandler, - useContext, - SetStateAction, - Dispatch, } from "react"; import { Room } from "matrix-js-sdk/src/models/room"; import { RoomHierarchy } from "matrix-js-sdk/src/room-hierarchy"; @@ -33,7 +33,8 @@ import { EventType, RoomType } from "matrix-js-sdk/src/@types/event"; import { IHierarchyRelation, IHierarchyRoom } from "matrix-js-sdk/src/@types/spaces"; import { MatrixClient } from "matrix-js-sdk/src/matrix"; import classNames from "classnames"; -import { sortBy } from "lodash"; +import { sortBy, uniqBy } from "lodash"; +import { GuestAccess, HistoryVisibility } from "matrix-js-sdk/src/@types/partials"; import dis from "../../dispatcher/dispatcher"; import defaultDispatcher from "../../dispatcher/dispatcher"; @@ -48,7 +49,7 @@ import { mediaFromMxc } from "../../customisations/Media"; import InfoTooltip from "../views/elements/InfoTooltip"; import TextWithTooltip from "../views/elements/TextWithTooltip"; import { useStateToggle } from "../../hooks/useStateToggle"; -import { getChildOrder } from "../../stores/SpaceStore"; +import SpaceStore, { getChildOrder } from "../../stores/SpaceStore"; import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton"; import { linkifyElement } from "../../HtmlUtils"; import { useDispatcher } from "../../hooks/useDispatcher"; @@ -333,6 +334,29 @@ interface IHierarchyLevelProps { onToggleClick?(parentId: string, childId: string): void; } +const toLocalRoom = (cli: MatrixClient, room: IHierarchyRoom, upgradedRoomMap: Map): IHierarchyRoom => { + const cliRoom = cli.getRoom(SpaceStore.instance.findMostUpgradedVersion(room.room_id, upgradedRoomMap)); + if (cliRoom) { + return { + ...room, + room_id: cliRoom.roomId, + room_type: cliRoom.getType(), + name: cliRoom.name, + topic: cliRoom.currentState.getStateEvents(EventType.RoomTopic, "")?.getContent().topic, + avatar_url: cliRoom.getMxcAvatarUrl(), + canonical_alias: cliRoom.getCanonicalAlias(), + aliases: cliRoom.getAltAliases(), + world_readable: cliRoom.currentState.getStateEvents(EventType.RoomHistoryVisibility, "")?.getContent() + .history_visibility === HistoryVisibility.WorldReadable, + guest_can_join: cliRoom.currentState.getStateEvents(EventType.RoomGuestAccess, "")?.getContent() + .guest_access === GuestAccess.CanJoin, + num_joined_members: cliRoom.getJoinedMemberCount(), + }; + } + + return room; +}; + export const HierarchyLevel = ({ root, roomSet, @@ -350,10 +374,11 @@ export const HierarchyLevel = ({ return getChildOrder(ev.content.order, ev.origin_server_ts, ev.state_key); }); + const upgradedRoomMap = new Map(); const [subspaces, childRooms] = sortedChildren.reduce((result, ev: IHierarchyRelation) => { const room = hierarchy.roomMap.get(ev.state_key); if (room && roomSet.has(room)) { - result[room.room_type === RoomType.Space ? 0 : 1].push(room); + result[room.room_type === RoomType.Space ? 0 : 1].push(toLocalRoom(cli, room, upgradedRoomMap)); } return result; }, [[] as IHierarchyRoom[], [] as IHierarchyRoom[]]); @@ -361,7 +386,7 @@ export const HierarchyLevel = ({ const newParents = new Set(parents).add(root.room_id); return { - childRooms.map(room => ( + uniqBy(childRooms, "room_id").map(room => ( { const createTs = childRoom?.currentState.getStateEvents(EventType.RoomCreate, "")?.getTs(); return getChildOrder(ev.getContent().order, createTs, roomId); }).map(ev => { - return this.matrixClient.getRoom(ev.getStateKey()); + return this.matrixClient.getRoom(this.findMostUpgradedVersion(ev.getStateKey())); }).filter(room => { return room?.getMyMembership() === "join" || room?.getMyMembership() === "invite"; }) || []; @@ -452,6 +452,28 @@ export class SpaceStoreClass extends AsyncStoreWithClient { this.onRoomsUpdate(); }; + // Utility to walk tombstones and find the most updated variant of the given room, + // takes a Map to enable caching of the responses given the recursive nature of the function. + public findMostUpgradedVersion( + roomId: string, + upgradedRoomMap?: Map, + seen= new Set(), + ): string { + if (seen.has(roomId)) return roomId; + if (upgradedRoomMap?.has(roomId)) return upgradedRoomMap.get(roomId); + const room = this.matrixClient.getRoom(roomId); + const tombstone = room?.currentState.getStateEvents(EventType.RoomTombstone, ""); + const replacementRoom = tombstone?.getContent().replacement_room; + if (replacementRoom && this.matrixClient.getRoom(replacementRoom)?.getMyMembership() === "join") { + seen.add(roomId); + const result = this.findMostUpgradedVersion(replacementRoom, upgradedRoomMap); + upgradedRoomMap?.set(roomId, result); + return result; + } + upgradedRoomMap?.set(roomId, roomId); + return roomId; + } + private onRoomsUpdate = throttle(() => { // TODO resolve some updates as deltas const visibleRooms = this.matrixClient.getVisibleRooms(); @@ -479,6 +501,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient { }); }); + const upgradedRoomMap = new Map(); this.rootSpaces.forEach(s => { // traverse each space tree in DFS to build up the supersets as you go up, // reusing results from like subtrees. @@ -491,7 +514,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient { } const [childSpaces, childRooms] = partitionSpacesAndRooms(this.getChildren(spaceId)); - const roomIds = new Set(childRooms.map(r => r.roomId)); + const roomIds = new Set(childRooms.map(r => this.findMostUpgradedVersion(r.roomId, upgradedRoomMap))); const space = this.matrixClient?.getRoom(spaceId); // Add relevant DMs @@ -505,11 +528,11 @@ export class SpaceStoreClass extends AsyncStoreWithClient { const newPath = new Set(parentPath).add(spaceId); childSpaces.forEach(childSpace => { fn(childSpace.roomId, newPath)?.forEach(roomId => { - roomIds.add(roomId); + roomIds.add(this.findMostUpgradedVersion(roomId, upgradedRoomMap)); }); }); hiddenChildren.get(spaceId)?.forEach(roomId => { - roomIds.add(roomId); + roomIds.add(this.findMostUpgradedVersion(roomId, upgradedRoomMap)); }); this.spaceFilteredRooms.set(spaceId, roomIds); return roomIds; From cadc9d29905ebb84213f7230906e5291c6ab6363 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 6 Oct 2021 09:47:56 +0100 Subject: [PATCH 074/143] Improve emoji shortcodes generated from annotations --- src/emoji.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/emoji.ts b/src/emoji.ts index ee84583fc9..73898c12eb 100644 --- a/src/emoji.ts +++ b/src/emoji.ts @@ -74,7 +74,7 @@ export const EMOJI: IEmoji[] = EMOJIBASE.map((emojiData: Omit Date: Wed, 6 Oct 2021 10:27:16 +0100 Subject: [PATCH 075/143] Simplify and improve useRoomHierarchy hook --- src/components/structures/SpaceHierarchy.tsx | 25 ++++++-------------- 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/src/components/structures/SpaceHierarchy.tsx b/src/components/structures/SpaceHierarchy.tsx index ed87b04c8a..069454f842 100644 --- a/src/components/structures/SpaceHierarchy.tsx +++ b/src/components/structures/SpaceHierarchy.tsx @@ -410,50 +410,39 @@ export const HierarchyLevel = ({ const INITIAL_PAGE_SIZE = 20; -export const useSpaceSummary = (space: Room): { +export const useRoomHierarchy = (space: Room): { loading: boolean; rooms: IHierarchyRoom[]; hierarchy: RoomHierarchy; loadMore(pageSize?: number): Promise ; } => { const [rooms, setRooms] = useState([]); - const [loading, setLoading] = useState(true); const [hierarchy, setHierarchy] = useState(); const resetHierarchy = useCallback(() => { const hierarchy = new RoomHierarchy(space, INITIAL_PAGE_SIZE); - setHierarchy(hierarchy); - - let discard = false; hierarchy.load().then(() => { - if (discard) return; + if (space !== hierarchy.root) return; // discard stale results setRooms(hierarchy.rooms); - setLoading(false); }); - - return () => { - discard = true; - }; + setHierarchy(hierarchy); }, [space]); useEffect(resetHierarchy, [resetHierarchy]); useDispatcher(defaultDispatcher, (payload => { if (payload.action === Action.UpdateSpaceHierarchy) { - setLoading(true); setRooms([]); // TODO resetHierarchy(); } })); const loadMore = useCallback(async (pageSize?: number) => { - if (loading || !hierarchy.canLoadMore || hierarchy.noSupport) return; - - setLoading(true); + if (hierarchy.loading || !hierarchy.canLoadMore || hierarchy.noSupport) return; await hierarchy.load(pageSize); setRooms(hierarchy.rooms); - setLoading(false); - }, [loading, hierarchy]); + }, [hierarchy]); + const loading = hierarchy?.loading ?? true; return { loading, rooms, hierarchy, loadMore }; }; @@ -587,7 +576,7 @@ const SpaceHierarchy = ({ const [selected, setSelected] = useState(new Map>()); // Map> - const { loading, rooms, hierarchy, loadMore } = useSpaceSummary(space); + const { loading, rooms, hierarchy, loadMore } = useRoomHierarchy(space); const filteredRoomSet = useMemo>(() => { if (!rooms?.length) return new Set(); From d8bc868e79d3f2dff5eae89503ba0fae82f999d3 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 6 Oct 2021 10:56:11 +0100 Subject: [PATCH 076/143] Fix spaces keyboard shortcuts not working for last space --- src/stores/SpaceStore.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stores/SpaceStore.ts b/src/stores/SpaceStore.ts index bb22aa4dbb..87562d6a07 100644 --- a/src/stores/SpaceStore.ts +++ b/src/stores/SpaceStore.ts @@ -793,7 +793,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient { // 1 is Home, 2-9 are the spaces after Home if (payload.num === 1) { this.setActiveSpace(null); - } else if (this.spacePanelSpaces.length >= payload.num) { + } else if (payload.num > 0 && this.spacePanelSpaces.length > payload.num - 2) { this.setActiveSpace(this.spacePanelSpaces[payload.num - 2]); } break; From a0c0eea4fdecde03f1e54c869e481bc8a94351e5 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 6 Oct 2021 10:27:16 +0100 Subject: [PATCH 077/143] Simplify and improve useRoomHierarchy hook --- src/components/structures/SpaceHierarchy.tsx | 25 ++++++-------------- 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/src/components/structures/SpaceHierarchy.tsx b/src/components/structures/SpaceHierarchy.tsx index ed87b04c8a..069454f842 100644 --- a/src/components/structures/SpaceHierarchy.tsx +++ b/src/components/structures/SpaceHierarchy.tsx @@ -410,50 +410,39 @@ export const HierarchyLevel = ({ const INITIAL_PAGE_SIZE = 20; -export const useSpaceSummary = (space: Room): { +export const useRoomHierarchy = (space: Room): { loading: boolean; rooms: IHierarchyRoom[]; hierarchy: RoomHierarchy; loadMore(pageSize?: number): Promise ; } => { const [rooms, setRooms] = useState([]); - const [loading, setLoading] = useState(true); const [hierarchy, setHierarchy] = useState(); const resetHierarchy = useCallback(() => { const hierarchy = new RoomHierarchy(space, INITIAL_PAGE_SIZE); - setHierarchy(hierarchy); - - let discard = false; hierarchy.load().then(() => { - if (discard) return; + if (space !== hierarchy.root) return; // discard stale results setRooms(hierarchy.rooms); - setLoading(false); }); - - return () => { - discard = true; - }; + setHierarchy(hierarchy); }, [space]); useEffect(resetHierarchy, [resetHierarchy]); useDispatcher(defaultDispatcher, (payload => { if (payload.action === Action.UpdateSpaceHierarchy) { - setLoading(true); setRooms([]); // TODO resetHierarchy(); } })); const loadMore = useCallback(async (pageSize?: number) => { - if (loading || !hierarchy.canLoadMore || hierarchy.noSupport) return; - - setLoading(true); + if (hierarchy.loading || !hierarchy.canLoadMore || hierarchy.noSupport) return; await hierarchy.load(pageSize); setRooms(hierarchy.rooms); - setLoading(false); - }, [loading, hierarchy]); + }, [hierarchy]); + const loading = hierarchy?.loading ?? true; return { loading, rooms, hierarchy, loadMore }; }; @@ -587,7 +576,7 @@ const SpaceHierarchy = ({ const [selected, setSelected] = useState(new Map>()); // Map> - const { loading, rooms, hierarchy, loadMore } = useSpaceSummary(space); + const { loading, rooms, hierarchy, loadMore } = useRoomHierarchy(space); const filteredRoomSet = useMemo>(() => { if (!rooms?.length) return new Set(); From 52d0b0133ce0e68b23af91e585da2f5ccb2d8341 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 6 Oct 2021 14:46:39 +0100 Subject: [PATCH 078/143] Hide kick & ban options in UserInfo when looking at own profile --- src/components/views/right_panel/UserInfo.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/components/views/right_panel/UserInfo.tsx b/src/components/views/right_panel/UserInfo.tsx index 3ac4088182..829710185d 100644 --- a/src/components/views/right_panel/UserInfo.tsx +++ b/src/components/views/right_panel/UserInfo.tsx @@ -535,6 +535,8 @@ interface IBaseProps { const RoomKickButton: React.FC = ({ member, startUpdating, stopUpdating }) => { const cli = useContext(MatrixClientContext); + // don't render this button on our own profile, we don't want to kick ourselves + if (member.userId === cli.getUserId()) return null; // check if user can be kicked/disinvited if (member.membership !== "invite" && member.membership !== "join") return null; @@ -659,6 +661,9 @@ const RedactMessagesButton: React.FC = ({ member }) => { const BanToggleButton: React.FC = ({ member, startUpdating, stopUpdating }) => { const cli = useContext(MatrixClientContext); + // don't render this button on our own profile, we don't want to ban ourselves and can't unban ourselves anyhow + if (member.userId === cli.getUserId()) return null; + const onBanOrUnban = async () => { const { finished } = Modal.createTrackedDialog( 'Confirm User Action Dialog', From 3f6f2bcbb33df749d673a2023fcdbb165aaef595 Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Wed, 6 Oct 2021 16:48:17 +0100 Subject: [PATCH 079/143] no-op a setBotPower request from the integration manager when the PL is equal to or greater to the requested PL When configured --- src/ScalarMessaging.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/ScalarMessaging.ts b/src/ScalarMessaging.ts index 888b9ce9ed..3fc362c0eb 100644 --- a/src/ScalarMessaging.ts +++ b/src/ScalarMessaging.ts @@ -452,7 +452,7 @@ function setBotOptions(event: MessageEvent, roomId: string, userId: string) }); } -function setBotPower(event: MessageEvent, roomId: string, userId: string, level: number): void { +function setBotPower(event: MessageEvent, roomId: string, userId: string, level: number, ignoreIfGreater?: boolean): void { if (!(Number.isInteger(level) && level >= 0)) { sendError(event, _t('Power level must be positive integer.')); return; @@ -473,6 +473,18 @@ function setBotPower(event: MessageEvent, roomId: string, userId: string, l }, ); + // If the PL is equal to or greater than the requested PL, ignore. + if (ignoreIfGreater) { + // As per https://matrix.org/docs/spec/client_server/r0.6.0#m-room-power-levels + const currentPl = (powerLevels.content.users && powerLevels.content.users[userId]) || powerLevels.content.users_default || 0; + + if (currentPl >= level) { + sendResponse(event, { + success: true, + }); + } + } + client.setPowerLevel(roomId, userId, level, powerEvent).then(() => { sendResponse(event, { success: true, @@ -678,7 +690,7 @@ const onMessage = function(event: MessageEvent): void { setBotOptions(event, roomId, userId); break; case Action.SetBotPower: - setBotPower(event, roomId, userId, event.data.level); + setBotPower(event, roomId, userId, event.data.level, event.data.ignoreIfGreater); break; default: console.warn("Unhandled postMessage event with action '" + event.data.action +"'"); From b373b98d487a2ca3305113f62026ea6e52dd425b Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 6 Oct 2021 16:49:53 +0100 Subject: [PATCH 080/143] Simplify aria menu item roles/selectors --- src/components/structures/ContextMenu.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/components/structures/ContextMenu.tsx b/src/components/structures/ContextMenu.tsx index e2ec5d232c..dc6cbb59cd 100644 --- a/src/components/structures/ContextMenu.tsx +++ b/src/components/structures/ContextMenu.tsx @@ -44,9 +44,6 @@ function getOrCreateContainer(): HTMLDivElement { return container; } -const ARIA_MENU_ITEM_ROLES = new Set(["menuitem", "menuitemcheckbox", "menuitemradio"]); -const ARIA_MENU_ITEM_SELECTOR = '[role^="menuitem"], [role^="menuitemcheckbox"], [role^="menuitemradio"]'; - export interface IPosition { top?: number; bottom?: number; @@ -117,7 +114,7 @@ export class ContextMenu extends React.PureComponent { // We don't need to clean up when unmounting, so ignore if (!element) return; - const first = element.querySelector(ARIA_MENU_ITEM_SELECTOR) + const first = element.querySelector('[role^="menuitem"]') || element.querySelector('[tab-index]'); if (first) { @@ -196,7 +193,7 @@ export class ContextMenu extends React.PureComponent { descending = true; } } - } while (element && !ARIA_MENU_ITEM_ROLES.has(element.getAttribute("role"))); + } while (element && !element.getAttribute("role")?.startsWith("menuitem")); if (element) { (element as HTMLElement).focus(); From 88410a1b295ae1b2e89f449fbc7a9353073df90f Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Wed, 6 Oct 2021 16:51:07 +0100 Subject: [PATCH 081/143] Make function async --- src/ScalarMessaging.ts | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/src/ScalarMessaging.ts b/src/ScalarMessaging.ts index 3fc362c0eb..d068c1f924 100644 --- a/src/ScalarMessaging.ts +++ b/src/ScalarMessaging.ts @@ -452,7 +452,9 @@ function setBotOptions(event: MessageEvent, roomId: string, userId: string) }); } -function setBotPower(event: MessageEvent, roomId: string, userId: string, level: number, ignoreIfGreater?: boolean): void { +async function setBotPower( + event: MessageEvent, roomId: string, userId: string, level: number, ignoreIfGreater?: boolean, +): Promise { if (!(Number.isInteger(level) && level >= 0)) { sendError(event, _t('Power level must be positive integer.')); return; @@ -465,34 +467,34 @@ function setBotPower(event: MessageEvent, roomId: string, userId: string, l return; } - client.getStateEvent(roomId, "m.room.power_levels", "").then((powerLevels) => { - const powerEvent = new MatrixEvent( - { - type: "m.room.power_levels", - content: powerLevels, - }, - ); + try { + const powerLevels = await client.getStateEvent(roomId, "m.room.power_levels", ""); // If the PL is equal to or greater than the requested PL, ignore. - if (ignoreIfGreater) { + if (ignoreIfGreater === true) { // As per https://matrix.org/docs/spec/client_server/r0.6.0#m-room-power-levels - const currentPl = (powerLevels.content.users && powerLevels.content.users[userId]) || powerLevels.content.users_default || 0; + const currentPl = ( + powerLevels.content.users && powerLevels.content.users[userId] + ) || powerLevels.content.users_default || 0; if (currentPl >= level) { - sendResponse(event, { + return sendResponse(event, { success: true, }); } } - - client.setPowerLevel(roomId, userId, level, powerEvent).then(() => { - sendResponse(event, { - success: true, - }); - }, (err) => { - sendError(event, err.message ? err.message : _t('Failed to send request.'), err); + await client.setPowerLevel(roomId, userId, level, new MatrixEvent( + { + type: "m.room.power_levels", + content: powerLevels, + }, + )); + return sendResponse(event, { + success: true, }); - }); + } catch (err) { + sendError(event, err.message ? err.message : _t('Failed to send request.'), err); + } } function getMembershipState(event: MessageEvent, roomId: string, userId: string): void { From ab98549fff4cce1df885e20e031484a3f81f0369 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 6 Oct 2021 17:08:32 +0100 Subject: [PATCH 082/143] move the logic to the parent so that the section hiding works --- src/components/views/right_panel/UserInfo.tsx | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/components/views/right_panel/UserInfo.tsx b/src/components/views/right_panel/UserInfo.tsx index 829710185d..7de38b587f 100644 --- a/src/components/views/right_panel/UserInfo.tsx +++ b/src/components/views/right_panel/UserInfo.tsx @@ -535,8 +535,6 @@ interface IBaseProps { const RoomKickButton: React.FC = ({ member, startUpdating, stopUpdating }) => { const cli = useContext(MatrixClientContext); - // don't render this button on our own profile, we don't want to kick ourselves - if (member.userId === cli.getUserId()) return null; // check if user can be kicked/disinvited if (member.membership !== "invite" && member.membership !== "join") return null; @@ -661,9 +659,6 @@ const RedactMessagesButton: React.FC = ({ member }) => { const BanToggleButton: React.FC = ({ member, startUpdating, stopUpdating }) => { const cli = useContext(MatrixClientContext); - // don't render this button on our own profile, we don't want to ban ourselves and can't unban ourselves anyhow - if (member.userId === cli.getUserId()) return null; - const onBanOrUnban = async () => { const { finished } = Modal.createTrackedDialog( 'Confirm User Action Dialog', @@ -822,7 +817,7 @@ const RoomAdminToolsContainer: React.FC = ({ const isMe = me.userId === member.userId; const canAffectUser = member.powerLevel < me.powerLevel || isMe; - if (canAffectUser && me.powerLevel >= kickPowerLevel) { + if (!isMe && canAffectUser && me.powerLevel >= kickPowerLevel) { kickButton = ; } if (me.powerLevel >= redactPowerLevel && (!SpaceStore.spacesEnabled || !room.isSpaceRoom())) { @@ -830,10 +825,10 @@ const RoomAdminToolsContainer: React.FC = ({ ); } - if (canAffectUser && me.powerLevel >= banPowerLevel) { + if (!isMe && canAffectUser && me.powerLevel >= banPowerLevel) { banButton = ; } - if (canAffectUser && me.powerLevel >= editPowerLevel && !room.isSpaceRoom()) { + if (!isMe && canAffectUser && me.powerLevel >= editPowerLevel && !room.isSpaceRoom()) { muteButton = ( Date: Thu, 7 Oct 2021 10:57:23 +0100 Subject: [PATCH 083/143] Allow the header container to collapse on itself when room list not minimised --- res/css/views/rooms/_RoomSublist.scss | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/res/css/views/rooms/_RoomSublist.scss b/res/css/views/rooms/_RoomSublist.scss index 6db2185dd5..5f92108e72 100644 --- a/res/css/views/rooms/_RoomSublist.scss +++ b/res/css/views/rooms/_RoomSublist.scss @@ -22,6 +22,12 @@ limitations under the License. display: none; } + &:not(.mx_RoomSublist_minimized) { + .mx_RoomSublist_headerContainer { + height: auto; + } + } + .mx_RoomSublist_headerContainer { // Create a flexbox to make alignment easy display: flex; @@ -41,9 +47,7 @@ limitations under the License. // The combined height must be set in the LeftPanel component for sticky headers // to work correctly. padding-bottom: 8px; - // Allow the container to collapse on itself if its children - // are not in the normal document flow - max-height: 24px; + height: 24px; color: $roomlist-header-color; .mx_RoomSublist_stickable { @@ -176,9 +180,9 @@ limitations under the License. // scroll jumps when they become sticky. However, that leaves a gap when // scrolled to the top above the first sublist (whose header can only ever // stick to top), so we make sure to exclude the first visible sublist. - &:not(.mx_RoomSublist_hidden) ~ .mx_RoomSublist .mx_RoomSublist_headerContainer { - height: 24px; - } + // &:not(.mx_RoomSublist_hidden) ~ .mx_RoomSublist .mx_RoomSublist_headerContainer { + // height: 24px; + // } .mx_RoomSublist_resizeBox { position: relative; From 047f182cd8f42d82424e960ba3d4ea768f484f3e Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 7 Oct 2021 11:04:10 +0100 Subject: [PATCH 084/143] focusLock only specific context menus --- src/components/structures/ContextMenu.tsx | 31 ++++++++++++++++--- .../views/directory/NetworkDropdown.tsx | 2 +- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/components/structures/ContextMenu.tsx b/src/components/structures/ContextMenu.tsx index dc6cbb59cd..90d16a2eff 100644 --- a/src/components/structures/ContextMenu.tsx +++ b/src/components/structures/ContextMenu.tsx @@ -83,6 +83,10 @@ export interface IProps extends IPosition { // it will be mounted to a container at the root of the DOM. mountAsChild?: boolean; + // If specified, contents will be wrapped in a FocusLock, this is only needed if the context menu is being rendered + // within an existing FocusLock e.g inside a modal. + focusLock?: boolean; + // Function to be called on menu close onFinished(); // on resize callback @@ -98,6 +102,8 @@ interface IState { // this will allow the ContextMenu to manage its own focus using arrow keys as per the ARIA guidelines. @replaceableComponent("structures.ContextMenu") export class ContextMenu extends React.PureComponent { + private readonly initialFocus: HTMLElement; + static defaultProps = { hasBackground: true, managed: true, @@ -105,9 +111,18 @@ export class ContextMenu extends React.PureComponent { constructor(props, context) { super(props, context); + this.state = { contextMenuElem: null, }; + + // persist what had focus when we got initialized so we can return it after + this.initialFocus = document.activeElement as HTMLElement; + } + + componentWillUnmount() { + // return focus to the thing which had it before us after the unmount + this.initialFocus.focus(); } private collectContextMenuRect = (element: HTMLDivElement) => { @@ -371,6 +386,17 @@ export class ContextMenu extends React.PureComponent { ); } + let body = <> + { chevron } + { props.children } + ; + + if (props.focusLock) { + body = + { body } + ; + } + return (
{ ref={this.collectContextMenuRect} role={this.props.managed ? "menu" : undefined} > - - { chevron } - { props.children } - + { body }
{ background }
diff --git a/src/components/views/directory/NetworkDropdown.tsx b/src/components/views/directory/NetworkDropdown.tsx index dbad2ca024..9a999625d7 100644 --- a/src/components/views/directory/NetworkDropdown.tsx +++ b/src/components/views/directory/NetworkDropdown.tsx @@ -268,7 +268,7 @@ const NetworkDropdown = ({ onOptionChange, protocols = {}, selectedServerName, s }; const buttonRect = handle.current.getBoundingClientRect(); - content = + content =
{ options } From 1c8bcce0ede25ac8c7a07a17aadb88ed3adeb4f1 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 7 Oct 2021 11:13:13 +0100 Subject: [PATCH 085/143] comment --- src/components/structures/ContextMenu.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/ContextMenu.tsx b/src/components/structures/ContextMenu.tsx index 90d16a2eff..4250b5925b 100644 --- a/src/components/structures/ContextMenu.tsx +++ b/src/components/structures/ContextMenu.tsx @@ -121,7 +121,7 @@ export class ContextMenu extends React.PureComponent { } componentWillUnmount() { - // return focus to the thing which had it before us after the unmount + // return focus to the thing which had it before us this.initialFocus.focus(); } From e470d7d030562d032f568296e29f5aaec6755950 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 7 Oct 2021 13:19:51 +0100 Subject: [PATCH 086/143] Make use of MatrixClient::getRoomUpgradeHistory --- src/components/structures/SpaceHierarchy.tsx | 10 ++--- src/stores/SpaceStore.ts | 41 ++++++-------------- 2 files changed, 17 insertions(+), 34 deletions(-) diff --git a/src/components/structures/SpaceHierarchy.tsx b/src/components/structures/SpaceHierarchy.tsx index 8e1a472984..38d4129294 100644 --- a/src/components/structures/SpaceHierarchy.tsx +++ b/src/components/structures/SpaceHierarchy.tsx @@ -49,7 +49,7 @@ import { mediaFromMxc } from "../../customisations/Media"; import InfoTooltip from "../views/elements/InfoTooltip"; import TextWithTooltip from "../views/elements/TextWithTooltip"; import { useStateToggle } from "../../hooks/useStateToggle"; -import SpaceStore, { getChildOrder } from "../../stores/SpaceStore"; +import { getChildOrder } from "../../stores/SpaceStore"; import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton"; import { linkifyElement } from "../../HtmlUtils"; import { useDispatcher } from "../../hooks/useDispatcher"; @@ -334,8 +334,9 @@ interface IHierarchyLevelProps { onToggleClick?(parentId: string, childId: string): void; } -const toLocalRoom = (cli: MatrixClient, room: IHierarchyRoom, upgradedRoomMap: Map): IHierarchyRoom => { - const cliRoom = cli.getRoom(SpaceStore.instance.findMostUpgradedVersion(room.room_id, upgradedRoomMap)); +const toLocalRoom = (cli: MatrixClient, room: IHierarchyRoom): IHierarchyRoom => { + const history = cli.getRoomUpgradeHistory(room.room_id, true); + const cliRoom = history[history.length - 1]; if (cliRoom) { return { ...room, @@ -374,11 +375,10 @@ export const HierarchyLevel = ({ return getChildOrder(ev.content.order, ev.origin_server_ts, ev.state_key); }); - const upgradedRoomMap = new Map(); const [subspaces, childRooms] = sortedChildren.reduce((result, ev: IHierarchyRelation) => { const room = hierarchy.roomMap.get(ev.state_key); if (room && roomSet.has(room)) { - result[room.room_type === RoomType.Space ? 0 : 1].push(toLocalRoom(cli, room, upgradedRoomMap)); + result[room.room_type === RoomType.Space ? 0 : 1].push(toLocalRoom(cli, room)); } return result; }, [[] as IHierarchyRoom[], [] as IHierarchyRoom[]]); diff --git a/src/stores/SpaceStore.ts b/src/stores/SpaceStore.ts index e8bdce738b..3b28cda57f 100644 --- a/src/stores/SpaceStore.ts +++ b/src/stores/SpaceStore.ts @@ -283,7 +283,8 @@ export class SpaceStoreClass extends AsyncStoreWithClient { const createTs = childRoom?.currentState.getStateEvents(EventType.RoomCreate, "")?.getTs(); return getChildOrder(ev.getContent().order, createTs, roomId); }).map(ev => { - return this.matrixClient.getRoom(this.findMostUpgradedVersion(ev.getStateKey())); + const history = this.matrixClient.getRoomUpgradeHistory(ev.getStateKey(), true); + return history[history.length - 1]; }).filter(room => { return room?.getMyMembership() === "join" || room?.getMyMembership() === "invite"; }) || []; @@ -452,28 +453,6 @@ export class SpaceStoreClass extends AsyncStoreWithClient { this.onRoomsUpdate(); }; - // Utility to walk tombstones and find the most updated variant of the given room, - // takes a Map to enable caching of the responses given the recursive nature of the function. - public findMostUpgradedVersion( - roomId: string, - upgradedRoomMap?: Map, - seen= new Set(), - ): string { - if (seen.has(roomId)) return roomId; - if (upgradedRoomMap?.has(roomId)) return upgradedRoomMap.get(roomId); - const room = this.matrixClient.getRoom(roomId); - const tombstone = room?.currentState.getStateEvents(EventType.RoomTombstone, ""); - const replacementRoom = tombstone?.getContent().replacement_room; - if (replacementRoom && this.matrixClient.getRoom(replacementRoom)?.getMyMembership() === "join") { - seen.add(roomId); - const result = this.findMostUpgradedVersion(replacementRoom, upgradedRoomMap); - upgradedRoomMap?.set(roomId, result); - return result; - } - upgradedRoomMap?.set(roomId, roomId); - return roomId; - } - private onRoomsUpdate = throttle(() => { // TODO resolve some updates as deltas const visibleRooms = this.matrixClient.getVisibleRooms(); @@ -501,7 +480,6 @@ export class SpaceStoreClass extends AsyncStoreWithClient { }); }); - const upgradedRoomMap = new Map(); this.rootSpaces.forEach(s => { // traverse each space tree in DFS to build up the supersets as you go up, // reusing results from like subtrees. @@ -514,7 +492,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient { } const [childSpaces, childRooms] = partitionSpacesAndRooms(this.getChildren(spaceId)); - const roomIds = new Set(childRooms.map(r => this.findMostUpgradedVersion(r.roomId, upgradedRoomMap))); + const roomIds = new Set(childRooms.map(r => r.roomId)); const space = this.matrixClient?.getRoom(spaceId); // Add relevant DMs @@ -528,14 +506,19 @@ export class SpaceStoreClass extends AsyncStoreWithClient { const newPath = new Set(parentPath).add(spaceId); childSpaces.forEach(childSpace => { fn(childSpace.roomId, newPath)?.forEach(roomId => { - roomIds.add(this.findMostUpgradedVersion(roomId, upgradedRoomMap)); + roomIds.add(roomId); }); }); hiddenChildren.get(spaceId)?.forEach(roomId => { - roomIds.add(this.findMostUpgradedVersion(roomId, upgradedRoomMap)); + roomIds.add(roomId); }); - this.spaceFilteredRooms.set(spaceId, roomIds); - return roomIds; + + // Expand room IDs to all known versions of the given rooms + const expandedRoomIds = new Set(Array.from(roomIds).flatMap(roomId => { + return this.matrixClient.getRoomUpgradeHistory(roomId, true).map(r => r.roomId); + })); + this.spaceFilteredRooms.set(spaceId, expandedRoomIds); + return expandedRoomIds; }; fn(s.roomId, new Set()); From 1b334e47aae6959d2c6d5949701f0f5bd8431013 Mon Sep 17 00:00:00 2001 From: Paulo Pinto Date: Thu, 7 Oct 2021 15:42:23 +0100 Subject: [PATCH 087/143] Fix issue that caused the value of certain settings to be inverted (#6896) When using the SettingsStore.watchSetting() method for settings which have an invertedSettingName, the newValueAt argument passed to the callback function, would erroneously contain the inverted value. This was making it so that such settings appeared to be disabled when they should in fact be enabled, or vice-versa. This was however only the case for code which took in account the newValueAt argument. Code using the newValue argument was not affected. The settings which have an invertedSettingName, and were thus potentially impacted are: - MessageComposerInput.dontSuggestEmoji - hideRedactions - hideJoinLeaves - hideAvatarChanges - hideDisplaynameChanges - hideReadReceipts - Pill.shouldHidePillAvatar - TextualBody.disableBigEmoji - dontSendTypingNotifications - TagPanel.disableTagPanel - webRtcForceTURN Signed-off-by: Paulo Pinto --- src/settings/SettingsStore.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/settings/SettingsStore.ts b/src/settings/SettingsStore.ts index af858d2379..d2f5568988 100644 --- a/src/settings/SettingsStore.ts +++ b/src/settings/SettingsStore.ts @@ -162,9 +162,10 @@ export default class SettingsStore { const watcherId = `${new Date().getTime()}_${SettingsStore.watcherCount++}_${settingName}_${roomId}`; - const localizedCallback = (changedInRoomId, atLevel, newValAtLevel) => { + const localizedCallback = (changedInRoomId: string | null, atLevel: SettingLevel, newValAtLevel: any) => { const newValue = SettingsStore.getValue(originalSettingName); - callbackFn(originalSettingName, changedInRoomId, atLevel, newValAtLevel, newValue); + const newValueAtLevel = SettingsStore.getValueAt(atLevel, originalSettingName) ?? newValAtLevel; + callbackFn(originalSettingName, changedInRoomId, atLevel, newValueAtLevel, newValue); }; SettingsStore.watchers.set(watcherId, localizedCallback); From 57b919b10af21663aa56793281d13cad5544c701 Mon Sep 17 00:00:00 2001 From: Germain Date: Thu, 7 Oct 2021 16:51:39 +0100 Subject: [PATCH 088/143] Delete fixed headerContainer height Co-authored-by: Travis Ralston --- res/css/views/rooms/_RoomSublist.scss | 3 --- 1 file changed, 3 deletions(-) diff --git a/res/css/views/rooms/_RoomSublist.scss b/res/css/views/rooms/_RoomSublist.scss index 5f92108e72..494c8174d7 100644 --- a/res/css/views/rooms/_RoomSublist.scss +++ b/res/css/views/rooms/_RoomSublist.scss @@ -180,9 +180,6 @@ limitations under the License. // scroll jumps when they become sticky. However, that leaves a gap when // scrolled to the top above the first sublist (whose header can only ever // stick to top), so we make sure to exclude the first visible sublist. - // &:not(.mx_RoomSublist_hidden) ~ .mx_RoomSublist .mx_RoomSublist_headerContainer { - // height: 24px; - // } .mx_RoomSublist_resizeBox { position: relative; From ea55b0d45f713751066831c451a40ef57819ed9e Mon Sep 17 00:00:00 2001 From: Paulo Pinto Date: Thu, 7 Oct 2021 17:01:39 +0100 Subject: [PATCH 089/143] Add room name to component state Signed-off-by: Paulo Pinto --- .../views/dialogs/RoomSettingsDialog.tsx | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/components/views/dialogs/RoomSettingsDialog.tsx b/src/components/views/dialogs/RoomSettingsDialog.tsx index a73f0a595b..b1c21d5044 100644 --- a/src/components/views/dialogs/RoomSettingsDialog.tsx +++ b/src/components/views/dialogs/RoomSettingsDialog.tsx @@ -44,12 +44,22 @@ interface IProps { initialTabId?: string; } +interface IState { + roomName: string; +} + @replaceableComponent("views.dialogs.RoomSettingsDialog") -export default class RoomSettingsDialog extends React.Component { +export default class RoomSettingsDialog extends React.Component { private dispatcherRef: string; + constructor(props: IProps) { + super(props); + this.state = { roomName: '' }; + } + public componentDidMount() { this.dispatcherRef = dis.register(this.onAction); + this.setRoomName(); } public componentWillUnmount() { @@ -66,6 +76,12 @@ export default class RoomSettingsDialog extends React.Component { } }; + private setRoomName = (): void => { + this.setState({ + roomName: MatrixClientPeg.get().getRoom(this.props.roomId).name, + }); + }; + private getTabs(): Tab[] { const tabs: Tab[] = []; @@ -122,7 +138,7 @@ export default class RoomSettingsDialog extends React.Component { } render() { - const roomName = MatrixClientPeg.get().getRoom(this.props.roomId).name; + const roomName = this.state.roomName; return ( Date: Thu, 7 Oct 2021 17:04:30 +0100 Subject: [PATCH 090/143] Keep room name up-to-date in settings dialog Signed-off-by: Paulo Pinto --- src/components/views/dialogs/RoomSettingsDialog.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/views/dialogs/RoomSettingsDialog.tsx b/src/components/views/dialogs/RoomSettingsDialog.tsx index b1c21d5044..a0f1c10884 100644 --- a/src/components/views/dialogs/RoomSettingsDialog.tsx +++ b/src/components/views/dialogs/RoomSettingsDialog.tsx @@ -59,6 +59,7 @@ export default class RoomSettingsDialog extends React.Component public componentDidMount() { this.dispatcherRef = dis.register(this.onAction); + MatrixClientPeg.get().on("Room.name", this.setRoomName); this.setRoomName(); } @@ -66,6 +67,8 @@ export default class RoomSettingsDialog extends React.Component if (this.dispatcherRef) { dis.unregister(this.dispatcherRef); } + + MatrixClientPeg.get().removeListener("Room.name", this.setRoomName); } private onAction = (payload): void => { From 6aa325ed543a2af9efeea032774a8ff3df0d2d7b Mon Sep 17 00:00:00 2001 From: Paulo Pinto Date: Thu, 7 Oct 2021 17:13:57 +0100 Subject: [PATCH 091/143] Rename method to onRoomName Signed-off-by: Paulo Pinto --- src/components/views/dialogs/RoomSettingsDialog.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/views/dialogs/RoomSettingsDialog.tsx b/src/components/views/dialogs/RoomSettingsDialog.tsx index a0f1c10884..b0c6fc4050 100644 --- a/src/components/views/dialogs/RoomSettingsDialog.tsx +++ b/src/components/views/dialogs/RoomSettingsDialog.tsx @@ -59,8 +59,8 @@ export default class RoomSettingsDialog extends React.Component public componentDidMount() { this.dispatcherRef = dis.register(this.onAction); - MatrixClientPeg.get().on("Room.name", this.setRoomName); - this.setRoomName(); + MatrixClientPeg.get().on("Room.name", this.onRoomName); + this.onRoomName(); } public componentWillUnmount() { @@ -68,7 +68,7 @@ export default class RoomSettingsDialog extends React.Component dis.unregister(this.dispatcherRef); } - MatrixClientPeg.get().removeListener("Room.name", this.setRoomName); + MatrixClientPeg.get().removeListener("Room.name", this.onRoomName); } private onAction = (payload): void => { @@ -79,7 +79,7 @@ export default class RoomSettingsDialog extends React.Component } }; - private setRoomName = (): void => { + private onRoomName = (): void => { this.setState({ roomName: MatrixClientPeg.get().getRoom(this.props.roomId).name, }); From 822f73edf7b5a5c8203e297cce95dd279e7a650e Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Thu, 7 Oct 2021 17:28:37 +0100 Subject: [PATCH 092/143] Remove stale comments in _RoomSublist.scss --- res/css/views/rooms/_RoomSublist.scss | 5 ----- 1 file changed, 5 deletions(-) diff --git a/res/css/views/rooms/_RoomSublist.scss b/res/css/views/rooms/_RoomSublist.scss index 494c8174d7..95b9f1822d 100644 --- a/res/css/views/rooms/_RoomSublist.scss +++ b/res/css/views/rooms/_RoomSublist.scss @@ -176,11 +176,6 @@ limitations under the License. } } - // In the general case, we reserve space for each sublist header to prevent - // scroll jumps when they become sticky. However, that leaves a gap when - // scrolled to the top above the first sublist (whose header can only ever - // stick to top), so we make sure to exclude the first visible sublist. - .mx_RoomSublist_resizeBox { position: relative; From c56d6ba539d00c737544134cea3cb22f765530ac Mon Sep 17 00:00:00 2001 From: Logan Arnett Date: Thu, 7 Oct 2021 13:22:43 -0400 Subject: [PATCH 093/143] updating from boolean to object in order to track if more than one thing is edited --- .../room_settings/RoomProfileSettings.tsx | 62 ++++++++++++++----- 1 file changed, 47 insertions(+), 15 deletions(-) diff --git a/src/components/views/room_settings/RoomProfileSettings.tsx b/src/components/views/room_settings/RoomProfileSettings.tsx index 6533028e8c..71c0094026 100644 --- a/src/components/views/room_settings/RoomProfileSettings.tsx +++ b/src/components/views/room_settings/RoomProfileSettings.tsx @@ -35,7 +35,7 @@ interface IState { avatarFile: File; originalTopic: string; topic: string; - enableProfileSave: boolean; + profileFieldsTouched: Record; canSetName: boolean; canSetTopic: boolean; canSetAvatar: boolean; @@ -71,7 +71,7 @@ export default class RoomProfileSettings extends React.Component avatarFile: null, originalTopic: topic, topic: topic, - enableProfileSave: false, + profileFieldsTouched: {}, canSetName: room.currentState.maySendStateEvent('m.room.name', client.getUserId()), canSetTopic: room.currentState.maySendStateEvent('m.room.topic', client.getUserId()), canSetAvatar: room.currentState.maySendStateEvent('m.room.avatar', client.getUserId()), @@ -88,17 +88,24 @@ export default class RoomProfileSettings extends React.Component this.setState({ avatarUrl: null, avatarFile: null, - enableProfileSave: true, + profileFieldsTouched: { + ...this.state.profileFieldsTouched, + avatar: true + }, }); }; + private isSaveEnabled = () => { + return Boolean(Object.values(this.state.profileFieldsTouched).length) + } + private cancelProfileChanges = async (e: React.MouseEvent): Promise => { e.stopPropagation(); e.preventDefault(); - if (!this.state.enableProfileSave) return; + if (!this.isSaveEnabled()) return; this.setState({ - enableProfileSave: false, + profileFieldsTouched: {}, displayName: this.state.originalDisplayName, topic: this.state.originalTopic, avatarUrl: this.state.originalAvatarUrl, @@ -110,8 +117,8 @@ export default class RoomProfileSettings extends React.Component e.stopPropagation(); e.preventDefault(); - if (!this.state.enableProfileSave) return; - this.setState({ enableProfileSave: false }); + if (!this.isSaveEnabled()) return; + this.setState({ profileFieldsTouched: {} }); const client = MatrixClientPeg.get(); @@ -156,18 +163,37 @@ export default class RoomProfileSettings extends React.Component private onDisplayNameChanged = (e: React.ChangeEvent): void => { this.setState({ displayName: e.target.value }); if (this.state.originalDisplayName === e.target.value) { - this.setState({ enableProfileSave: false }); + this.setState({ + profileFieldsTouched: { + ...this.state.profileFieldsTouched, + name: false + }, }); } else { - this.setState({ enableProfileSave: true }); + this.setState({ + profileFieldsTouched: { + ...this.state.profileFieldsTouched, + name: true + }, + }); } }; private onTopicChanged = (e: React.ChangeEvent): void => { this.setState({ topic: e.target.value }); if (this.state.originalTopic === e.target.value) { - this.setState({ enableProfileSave: false }); + this.setState({ + profileFieldsTouched: { + ...this.state.profileFieldsTouched, + topic: false + }, + }); } else { - this.setState({ enableProfileSave: true }); + this.setState({ + profileFieldsTouched: { + ...this.state.profileFieldsTouched, + topic: true + }, + }); } }; @@ -176,7 +202,10 @@ export default class RoomProfileSettings extends React.Component this.setState({ avatarUrl: this.state.originalAvatarUrl, avatarFile: null, - enableProfileSave: false, + profileFieldsTouched: { + ...this.state.profileFieldsTouched, + avatar: false + }, }); return; } @@ -187,7 +216,10 @@ export default class RoomProfileSettings extends React.Component this.setState({ avatarUrl: String(ev.target.result), avatarFile: file, - enableProfileSave: true, + profileFieldsTouched: { + ...this.state.profileFieldsTouched, + avatar: true + }, }); }; reader.readAsDataURL(file); @@ -205,14 +237,14 @@ export default class RoomProfileSettings extends React.Component { _t("Cancel") } { _t("Save") } From 0b64dfa59ab60ae57767fbda7997fdc2eee108fd Mon Sep 17 00:00:00 2001 From: Vitor Eller Date: Thu, 7 Oct 2021 15:23:54 -0300 Subject: [PATCH 094/143] Alter phone verification button disable label --- src/components/views/settings/account/PhoneNumbers.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/settings/account/PhoneNumbers.tsx b/src/components/views/settings/account/PhoneNumbers.tsx index e5cca72867..9105dfc312 100644 --- a/src/components/views/settings/account/PhoneNumbers.tsx +++ b/src/components/views/settings/account/PhoneNumbers.tsx @@ -268,7 +268,7 @@ export default class PhoneNumbers extends React.Component { { _t("Continue") } From 4759b4fb5d7184fa5c34ccf09908b8e24d2c7687 Mon Sep 17 00:00:00 2001 From: Logan Arnett Date: Thu, 7 Oct 2021 14:58:35 -0400 Subject: [PATCH 095/143] updating for lint issues --- .../room_settings/RoomProfileSettings.tsx | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/components/views/room_settings/RoomProfileSettings.tsx b/src/components/views/room_settings/RoomProfileSettings.tsx index 71c0094026..8cc7a620f8 100644 --- a/src/components/views/room_settings/RoomProfileSettings.tsx +++ b/src/components/views/room_settings/RoomProfileSettings.tsx @@ -90,14 +90,14 @@ export default class RoomProfileSettings extends React.Component avatarFile: null, profileFieldsTouched: { ...this.state.profileFieldsTouched, - avatar: true + avatar: true, }, }); }; private isSaveEnabled = () => { - return Boolean(Object.values(this.state.profileFieldsTouched).length) - } + return Boolean(Object.values(this.state.profileFieldsTouched).length); + }; private cancelProfileChanges = async (e: React.MouseEvent): Promise => { e.stopPropagation(); @@ -166,13 +166,14 @@ export default class RoomProfileSettings extends React.Component this.setState({ profileFieldsTouched: { ...this.state.profileFieldsTouched, - name: false - }, }); + name: false, + }, + }); } else { this.setState({ profileFieldsTouched: { ...this.state.profileFieldsTouched, - name: true + name: true, }, }); } @@ -184,14 +185,14 @@ export default class RoomProfileSettings extends React.Component this.setState({ profileFieldsTouched: { ...this.state.profileFieldsTouched, - topic: false + topic: false, }, }); } else { this.setState({ profileFieldsTouched: { ...this.state.profileFieldsTouched, - topic: true + topic: true, }, }); } @@ -204,7 +205,7 @@ export default class RoomProfileSettings extends React.Component avatarFile: null, profileFieldsTouched: { ...this.state.profileFieldsTouched, - avatar: false + avatar: false, }, }); return; @@ -218,7 +219,7 @@ export default class RoomProfileSettings extends React.Component avatarFile: file, profileFieldsTouched: { ...this.state.profileFieldsTouched, - avatar: true + avatar: true, }, }); }; From 0af5f8a173c84054c1ce61b9fb4bf3e307d06733 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Fri, 8 Oct 2021 08:30:34 +0100 Subject: [PATCH 096/143] Upgrade matrix-js-sdk to 14.0.0-rc.2 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 40633b9723..5b750f176b 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,7 @@ "katex": "^0.12.0", "linkifyjs": "^2.1.9", "lodash": "^4.17.20", - "matrix-js-sdk": "14.0.0-rc.1", + "matrix-js-sdk": "14.0.0-rc.2", "matrix-widget-api": "^0.1.0-beta.16", "minimist": "^1.2.5", "opus-recorder": "^8.0.3", diff --git a/yarn.lock b/yarn.lock index 0b17dc1284..0bd21610ea 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5862,10 +5862,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@14.0.0-rc.1: - version "14.0.0-rc.1" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-14.0.0-rc.1.tgz#1cb3dfd2949d3a4414986f8ab0a92575f5fff0d1" - integrity sha512-idDBJRGOOdn9yOQWoZxwLSWv2xn7jF3IJ7W5UCmOZ0EKYmH7C1VlKAfvkGDpxdbrNCRs84SUvqJqImAuQoV4Gw== +matrix-js-sdk@14.0.0-rc.2: + version "14.0.0-rc.2" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-14.0.0-rc.2.tgz#36415152740c07a99eb7ed07fad032296fac59d8" + integrity sha512-6s9WP+GKzI4/SkunULHVfs+LnkcwvopQzVyN62+7HbfEOmlzrR77JbtIfPLZmcbcm9e+g4IkoiBMOFYt35bwvA== dependencies: "@babel/runtime" "^7.12.5" another-json "^0.2.0" From 4c1e2e3f3dbfcf804714ddebf7446b205ff445f8 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Fri, 8 Oct 2021 08:32:25 +0100 Subject: [PATCH 097/143] Prepare changelog for v3.32.0-rc.2 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 327890d4da..95a9c605ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +Changes in [3.32.0-rc.2](https://github.com/vector-im/element-desktop/releases/tag/v3.32.0-rc.2) (2021-10-08) +============================================================================================================= + +## 🐛 Bug Fixes + * [Release] Fix space hierarchy pagination ([\#6910](https://github.com/matrix-org/matrix-react-sdk/pull/6910)). + Changes in [3.32.0-rc.1](https://github.com/vector-im/element-desktop/releases/tag/v3.32.0-rc.1) (2021-10-04) ============================================================================================================= From 2a440e90cbef0c076e4bcc95fbe31e04aeb2fc88 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Fri, 8 Oct 2021 08:32:27 +0100 Subject: [PATCH 098/143] v3.32.0-rc.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5b750f176b..f4f6e3c4f0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "3.32.0-rc.1", + "version": "3.32.0-rc.2", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From 82ad85a9744b0da3f1f3128138ba6064989e15b6 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 8 Oct 2021 10:30:46 +0100 Subject: [PATCH 099/143] Mock usage of getRoomUpgradeHistory in SpaceStore tests --- test/stores/SpaceStore-test.ts | 1 + test/test-utils.js | 1 + 2 files changed, 2 insertions(+) diff --git a/test/stores/SpaceStore-test.ts b/test/stores/SpaceStore-test.ts index e7ca727e28..cdc3e58a4f 100644 --- a/test/stores/SpaceStore-test.ts +++ b/test/stores/SpaceStore-test.ts @@ -77,6 +77,7 @@ describe("SpaceStore", () => { const run = async () => { client.getRoom.mockImplementation(roomId => rooms.find(room => room.roomId === roomId)); + client.getRoomUpgradeHistory.mockImplementation(roomId => [rooms.find(room => room.roomId === roomId)]); await testUtils.setupAsyncStoreWithClient(store, client); jest.runAllTimers(); }; diff --git a/test/test-utils.js b/test/test-utils.js index 2091a6e0ed..d43a08ab3a 100644 --- a/test/test-utils.js +++ b/test/test-utils.js @@ -103,6 +103,7 @@ export function createTestClient() { isUserIgnored: jest.fn().mockReturnValue(false), getCapabilities: jest.fn().mockResolvedValue({}), supportsExperimentalThreads: () => false, + getRoomUpgradeHistory: jest.fn().mockReturnValue([]), }; } From 2483f1dc90af743b8a90f1613ca09865c6d50493 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 8 Oct 2021 12:20:43 +0100 Subject: [PATCH 100/143] Add progress bar to restricted room upgrade dialog --- .../dialogs/_RoomUpgradeWarningDialog.scss | 18 +++- .../dialogs/RoomUpgradeWarningDialog.tsx | 53 ++++++++-- .../views/settings/JoinRuleSettings.tsx | 96 ++++++++++++------- src/i18n/strings/en_EN.json | 10 +- src/utils/RoomUpgrade.ts | 81 ++++++++++++---- 5 files changed, 188 insertions(+), 70 deletions(-) diff --git a/res/css/views/dialogs/_RoomUpgradeWarningDialog.scss b/res/css/views/dialogs/_RoomUpgradeWarningDialog.scss index 5b9978eba0..941c8cb807 100644 --- a/res/css/views/dialogs/_RoomUpgradeWarningDialog.scss +++ b/res/css/views/dialogs/_RoomUpgradeWarningDialog.scss @@ -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,6 +17,22 @@ limitations under the License. .mx_RoomUpgradeWarningDialog { max-width: 38vw; width: 38vw; + + .mx_RoomUpgradeWarningDialog_progress { + .mx_ProgressBar { + height: 8px; + width: 100%; + + @mixin ProgressBarBorderRadius 8px; + } + + .mx_RoomUpgradeWarningDialog_progressText { + margin-top: 8px; + font-size: $font-15px; + line-height: $font-24px; + color: $primary-content; + } + } } .mx_RoomUpgradeWarningDialog .mx_SettingsFlag { diff --git a/src/components/views/dialogs/RoomUpgradeWarningDialog.tsx b/src/components/views/dialogs/RoomUpgradeWarningDialog.tsx index a90f417959..35d27afe25 100644 --- a/src/components/views/dialogs/RoomUpgradeWarningDialog.tsx +++ b/src/components/views/dialogs/RoomUpgradeWarningDialog.tsx @@ -28,15 +28,25 @@ import { IDialogProps } from "./IDialogProps"; import BugReportDialog from './BugReportDialog'; import BaseDialog from "./BaseDialog"; import DialogButtons from "../elements/DialogButtons"; +import ProgressBar from "../elements/ProgressBar"; + +export interface IFinishedOpts { + continue: boolean; + invite: boolean; +} interface IProps extends IDialogProps { roomId: string; targetVersion: string; description?: ReactNode; + doUpgrade?(opts: IFinishedOpts, fn: (progressText: string, progress: number, total: number) => void): Promise; } interface IState { inviteUsersToNewRoom: boolean; + progressText?: string; + progress?: number; + total?: number; } @replaceableComponent("views.dialogs.RoomUpgradeWarningDialog") @@ -50,15 +60,30 @@ export default class RoomUpgradeWarningDialog extends React.Component { + this.setState({ progressText, progress, total }); + }; + private onContinue = () => { - this.props.onFinished({ continue: true, invite: this.isPrivate && this.state.inviteUsersToNewRoom }); + const opts = { + continue: true, + invite: this.isPrivate && this.state.inviteUsersToNewRoom, + }; + + if (this.props.doUpgrade) { + this.props.doUpgrade(opts, this.onProgressCallback).then(() => { + this.props.onFinished(opts); + }); + } else { + this.props.onFinished(opts); + } }; private onCancel = () => { @@ -118,6 +143,23 @@ export default class RoomUpgradeWarningDialog extends React.Component + +
+ { this.state.progressText } +
+ ; + } else { + footer = ; + } + return ( { inviteToggle }
- + { footer } ); } diff --git a/src/components/views/settings/JoinRuleSettings.tsx b/src/components/views/settings/JoinRuleSettings.tsx index 76596103f5..2d622683e0 100644 --- a/src/components/views/settings/JoinRuleSettings.tsx +++ b/src/components/views/settings/JoinRuleSettings.tsx @@ -27,8 +27,7 @@ import SpaceStore from "../../../stores/SpaceStore"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; import Modal from "../../../Modal"; import ManageRestrictedJoinRuleDialog from "../dialogs/ManageRestrictedJoinRuleDialog"; -import RoomUpgradeWarningDialog from "../dialogs/RoomUpgradeWarningDialog"; -import QuestionDialog from "../dialogs/QuestionDialog"; +import RoomUpgradeWarningDialog, { IFinishedOpts } from "../dialogs/RoomUpgradeWarningDialog"; import { upgradeRoom } from "../../../utils/RoomUpgrade"; import { arrayHasDiff } from "../../../utils/arrays"; import { useLocalEcho } from "../../../hooks/useLocalEcho"; @@ -210,47 +209,70 @@ const JoinRuleSettings = ({ room, promptUpgrade, onError, beforeChange, closeSet // Block this action on a room upgrade otherwise it'd make their room unjoinable const targetVersion = preferredRestrictionVersion; - const modal = Modal.createTrackedDialog('Restricted join rule upgrade', '', RoomUpgradeWarningDialog, { - roomId: room.roomId, - targetVersion, - description: _t("This upgrade will allow members of selected spaces " + - "access to this room without an invite."), - }); - - const [resp] = await modal.finished; - if (!resp?.continue) return; - + let warning: JSX.Element; const userId = cli.getUserId(); const unableToUpdateSomeParents = Array.from(SpaceStore.instance.getKnownParents(room.roomId)) .some(roomId => !cli.getRoom(roomId)?.currentState.maySendStateEvent(EventType.SpaceChild, userId)); if (unableToUpdateSomeParents) { - const modal = Modal.createTrackedDialog<[boolean]>('Parent relink warning', '', QuestionDialog, { - title: _t("Before you upgrade"), - description: ( -
{ _t("This room is in some spaces you’re not an admin of. " + - "In those spaces, the old room will still be shown, " + - "but people will be prompted to join the new one.") }
- ), - hasCancelButton: true, - button: _t("Upgrade anyway"), - danger: true, - }); - - const [shouldUpgrade] = await modal.finished; - if (!shouldUpgrade) return; + warning = + { _t("This room is in some spaces you’re not an admin of. " + + "In those spaces, the old room will still be shown, " + + "but people will be prompted to join the new one.") } + ; } - const roomId = await upgradeRoom(room, targetVersion, resp.invite, true, true, true); - closeSettingsFn(); - // switch to the new room in the background - dis.dispatch({ - action: "view_room", - room_id: roomId, - }); - // open new settings on this tab - dis.dispatch({ - action: "open_room_settings", - initial_tab_id: ROOM_SECURITY_TAB, + Modal.createTrackedDialog('Restricted join rule upgrade', '', RoomUpgradeWarningDialog, { + roomId: room.roomId, + targetVersion, + description: <> + { _t("This upgrade will allow members of selected spaces " + + "access to this room without an invite.") } + { warning } + , + doUpgrade: async ( + opts: IFinishedOpts, + fn: (progressText: string, progress: number, total: number) => void, + ): Promise => { + const roomId = await upgradeRoom( + room, + targetVersion, + opts.invite, + true, + true, + true, + progress => { + const total = 2 + progress.updateSpacesTotal + progress.inviteUsersTotal; + if (!progress.roomUpgraded) { + fn(_t("Upgrading room"), 0, total); + } else if (!progress.roomSynced) { + fn(_t("Loading new room"), 1, total); + } else if (progress.inviteUsersProgress < progress.inviteUsersTotal) { + fn(_t("Sending invites... (%(progress)s out of %(count)s)", { + progress: progress.inviteUsersProgress, + count: progress.inviteUsersTotal, + }), 2 + progress.inviteUsersProgress, total); + } else if (progress.updateSpacesProgress < progress.updateSpacesTotal) { + fn(_t("Updating spaces... (%(progress)s out of %(count)s)", { + progress: progress.updateSpacesProgress, + count: progress.updateSpacesTotal, + }), 2 + progress.inviteUsersProgress + progress.updateSpacesProgress, total); + } + }, + ); + closeSettingsFn(); + + // switch to the new room in the background + dis.dispatch({ + action: "view_room", + room_id: roomId, + }); + + // open new settings on this tab + dis.dispatch({ + action: "open_room_settings", + initial_tab_id: ROOM_SECURITY_TAB, + }); + }, }); return; diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index bdc86a9e08..b5a67ebe6a 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1166,10 +1166,14 @@ "Anyone in can find and join. You can select other spaces too.": "Anyone in can find and join. You can select other spaces too.", "Anyone in a space can find and join. You can select multiple spaces.": "Anyone in a space can find and join. You can select multiple spaces.", "Space members": "Space members", - "This upgrade will allow members of selected spaces access to this room without an invite.": "This upgrade will allow members of selected spaces access to this room without an invite.", - "Before you upgrade": "Before you upgrade", "This room is in some spaces you’re not an admin of. In those spaces, the old room will still be shown, but people will be prompted to join the new one.": "This room is in some spaces you’re not an admin of. In those spaces, the old room will still be shown, but people will be prompted to join the new one.", - "Upgrade anyway": "Upgrade anyway", + "This upgrade will allow members of selected spaces access to this room without an invite.": "This upgrade will allow members of selected spaces access to this room without an invite.", + "Upgrading room": "Upgrading room", + "Loading new room": "Loading new room", + "Sending invites... (%(progress)s out of %(count)s)|other": "Sending invites... (%(progress)s out of %(count)s)", + "Sending invites... (%(progress)s out of %(count)s)|one": "Sending invite...", + "Updating spaces... (%(progress)s out of %(count)s)|other": "Updating spaces... (%(progress)s out of %(count)s)", + "Updating spaces... (%(progress)s out of %(count)s)|one": "Updating space...", "Message layout": "Message layout", "IRC": "IRC", "Modern": "Modern", diff --git a/src/utils/RoomUpgrade.ts b/src/utils/RoomUpgrade.ts index 366f49d892..7e5115f53e 100644 --- a/src/utils/RoomUpgrade.ts +++ b/src/utils/RoomUpgrade.ts @@ -18,12 +18,21 @@ import { Room } from "matrix-js-sdk/src/models/room"; import { EventType } from "matrix-js-sdk/src/@types/event"; import { inviteUsersToRoom } from "../RoomInvite"; -import Modal from "../Modal"; +import Modal, { IHandle } from "../Modal"; import { _t } from "../languageHandler"; import ErrorDialog from "../components/views/dialogs/ErrorDialog"; import SpaceStore from "../stores/SpaceStore"; import Spinner from "../components/views/elements/Spinner"; +interface IProgress { + roomUpgraded: boolean; + roomSynced?: boolean; + inviteUsersProgress?: number; + inviteUsersTotal: number; + updateSpacesProgress?: number; + updateSpacesTotal: number; +} + export async function upgradeRoom( room: Room, targetVersion: string, @@ -31,9 +40,38 @@ export async function upgradeRoom( handleError = true, updateSpaces = true, awaitRoom = false, + progressCallback?: (progress: IProgress) => void, ): Promise { const cli = room.client; - const spinnerModal = Modal.createDialog(Spinner, null, "mx_Dialog_spinner"); + let spinnerModal: IHandle; + if (!progressCallback) { + spinnerModal = Modal.createDialog(Spinner, null, "mx_Dialog_spinner"); + } + + let toInvite: string[]; + if (inviteUsers) { + toInvite = [ + ...room.getMembersWithMembership("join"), + ...room.getMembersWithMembership("invite"), + ].map(m => m.userId).filter(m => m !== cli.getUserId()); + } + + let parentsToRelink: Room[]; + if (updateSpaces) { + parentsToRelink = Array.from(SpaceStore.instance.getKnownParents(room.roomId)) + .map(roomId => cli.getRoom(roomId)) + .filter(parent => parent?.currentState.maySendStateEvent(EventType.SpaceChild, cli.getUserId())); + } + + const progress: IProgress = { + roomUpgraded: false, + roomSynced: (awaitRoom || inviteUsers) ? false : undefined, + inviteUsersProgress: inviteUsers ? 0 : undefined, + inviteUsersTotal: toInvite.length, + updateSpacesProgress: updateSpaces ? 0 : undefined, + updateSpacesTotal: parentsToRelink.length, + }; + progressCallback?.(progress); let newRoomId: string; try { @@ -49,6 +87,9 @@ export async function upgradeRoom( throw e; } + progress.roomUpgraded = true; + progressCallback?.(progress); + if (awaitRoom || inviteUsers) { await new Promise(resolve => { // already have the room @@ -67,33 +108,31 @@ export async function upgradeRoom( }; cli.on("Room", checkForRoomFn); }); + + progress.roomSynced = true; + progressCallback?.(progress); } - if (inviteUsers) { - const toInvite = [ - ...room.getMembersWithMembership("join"), - ...room.getMembersWithMembership("invite"), - ].map(m => m.userId).filter(m => m !== cli.getUserId()); - - if (toInvite.length > 0) { - // Errors are handled internally to this function - await inviteUsersToRoom(newRoomId, toInvite); - } + if (toInvite.length > 0) { + // Errors are handled internally to this function + await inviteUsersToRoom(newRoomId, toInvite, () => { + progress.inviteUsersProgress++; + progressCallback?.(progress); + }); } - if (updateSpaces) { - const parents = SpaceStore.instance.getKnownParents(room.roomId); + if (parentsToRelink.length > 0) { try { - for (const parentId of parents) { - const parent = cli.getRoom(parentId); - if (!parent?.currentState.maySendStateEvent(EventType.SpaceChild, cli.getUserId())) continue; - + for (const parent of parentsToRelink) { const currentEv = parent.currentState.getStateEvents(EventType.SpaceChild, room.roomId); - await cli.sendStateEvent(parentId, EventType.SpaceChild, { + await cli.sendStateEvent(parent.roomId, EventType.SpaceChild, { ...(currentEv?.getContent() || {}), // copy existing attributes like suggested via: [cli.getDomain()], }, newRoomId); - await cli.sendStateEvent(parentId, EventType.SpaceChild, {}, room.roomId); + await cli.sendStateEvent(parent.roomId, EventType.SpaceChild, {}, room.roomId); + + progress.updateSpacesProgress++; + progressCallback?.(progress); } } catch (e) { // These errors are not critical to the room upgrade itself @@ -101,6 +140,6 @@ export async function upgradeRoom( } } - spinnerModal.close(); + spinnerModal?.close(); return newRoomId; } From 8cb4454ea3a218c7734d2479b0f5d0bf07e00c6b Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 8 Oct 2021 13:43:06 +0100 Subject: [PATCH 101/143] Disable leave room button if user isn't in the room e.g peeking --- .../settings/tabs/room/GeneralRoomSettingsTab.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.tsx b/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.tsx index 790e2999f5..37ac358660 100644 --- a/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.tsx +++ b/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.tsx @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React from 'react'; +import React, { ContextType } from 'react'; import { _t } from "../../../../../languageHandler"; import RoomProfileSettings from "../../../room_settings/RoomProfileSettings"; import AccessibleButton from "../../../elements/AccessibleButton"; @@ -38,9 +38,10 @@ interface IState { @replaceableComponent("views.settings.tabs.room.GeneralRoomSettingsTab") export default class GeneralRoomSettingsTab extends React.Component { public static contextType = MatrixClientContext; + context: ContextType; - constructor(props: IProps) { - super(props); + constructor(props: IProps, context: ContextType) { + super(props, context); this.state = { isRoomPublished: false, // loaded async @@ -111,7 +112,11 @@ export default class GeneralRoomSettingsTab extends React.Component{ _t("Leave room") }
- + { _t('Leave room') }
From ccba7badff89494e6bede69d84494e5557cf268a Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 8 Oct 2021 14:33:58 +0100 Subject: [PATCH 102/143] Make public space alias field mandatory again --- src/components/views/elements/Field.tsx | 4 ++++ src/components/views/spaces/SpaceCreateMenu.tsx | 11 +++-------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/components/views/elements/Field.tsx b/src/components/views/elements/Field.tsx index 5713518eb8..476b0f73c7 100644 --- a/src/components/views/elements/Field.tsx +++ b/src/components/views/elements/Field.tsx @@ -143,6 +143,10 @@ export default class Field extends React.PureComponent { public focus() { this.input.focus(); + // programmatic does not fire onFocus handler + this.setState({ + focused: true, + }); } private onFocus = (ev) => { diff --git a/src/components/views/spaces/SpaceCreateMenu.tsx b/src/components/views/spaces/SpaceCreateMenu.tsx index 1d63f85f71..22cbb4db65 100644 --- a/src/components/views/spaces/SpaceCreateMenu.tsx +++ b/src/components/views/spaces/SpaceCreateMenu.tsx @@ -214,7 +214,6 @@ export const SpaceCreateForm: React.FC = ({ }; const SpaceCreateMenu = ({ onFinished }) => { - const cli = useContext(MatrixClientContext); const [visibility, setVisibility] = useState(null); const [busy, setBusy] = useState(false); @@ -238,13 +237,9 @@ const SpaceCreateMenu = ({ onFinished }) => { return; } - // validate the space alias field but do not require it - const aliasLocalpart = alias.substring(1, alias.length - cli.getDomain().length - 1); - if (visibility === Visibility.Public && aliasLocalpart && - (await spaceAliasField.current.validate({ allowEmpty: true })) === false - ) { + if (visibility === Visibility.Public && !(await spaceAliasField.current.validate({ allowEmpty: false }))) { spaceAliasField.current.focus(); - spaceAliasField.current.validate({ allowEmpty: true, focused: true }); + spaceAliasField.current.validate({ allowEmpty: false, focused: true }); setBusy(false); return; } @@ -253,7 +248,7 @@ const SpaceCreateMenu = ({ onFinished }) => { await createSpace( name, visibility === Visibility.Public, - aliasLocalpart ? alias : undefined, + alias, topic, avatar, ); From 436996dc303a0f4552f908b421db3841c87108be Mon Sep 17 00:00:00 2001 From: rom4nik <46846000+rom4nik@users.noreply.github.com> Date: Mon, 11 Oct 2021 02:21:09 +0200 Subject: [PATCH 103/143] Prevent backdrop image from being selected --- res/css/structures/_BackdropPanel.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/res/css/structures/_BackdropPanel.scss b/res/css/structures/_BackdropPanel.scss index 482507cb15..63a33276e1 100644 --- a/res/css/structures/_BackdropPanel.scss +++ b/res/css/structures/_BackdropPanel.scss @@ -34,4 +34,5 @@ limitations under the License. z-index: 0; pointer-events: none; overflow: hidden; + user-select: none; } From 414b20f17e8b7a2baf0d20ee499709cbf8959d1d Mon Sep 17 00:00:00 2001 From: Dariusz Niemczyk <3636685+Palid@users.noreply.github.com> Date: Mon, 11 Oct 2021 11:26:05 +0200 Subject: [PATCH 104/143] Make thread button always visible (#6903) Fix https://github.com/vector-im/element-web/issues/18956 --- src/components/structures/FilePanel.tsx | 66 +++++++++++-------- .../structures/NotificationPanel.tsx | 13 +++- .../views/messages/MessageActionBar.tsx | 15 ++++- src/contexts/RoomContext.ts | 2 + 4 files changed, 64 insertions(+), 32 deletions(-) diff --git a/src/components/structures/FilePanel.tsx b/src/components/structures/FilePanel.tsx index 52cf5ae55b..77629839d9 100644 --- a/src/components/structures/FilePanel.tsx +++ b/src/components/structures/FilePanel.tsx @@ -37,6 +37,7 @@ import TimelinePanel from "./TimelinePanel"; import Spinner from "../views/elements/Spinner"; import { TileShape } from '../views/rooms/EventTile'; import { Layout } from "../../settings/Layout"; +import RoomContext, { TimelineRenderingType } from '../../contexts/RoomContext'; interface IProps { roomId: string; @@ -57,6 +58,7 @@ class FilePanel extends React.Component { // added to the timeline. private decryptingEvents = new Set(); public noRoom: boolean; + static contextType = RoomContext; state = { timelineSet: null, @@ -249,38 +251,46 @@ class FilePanel extends React.Component { const isRoomEncrypted = this.noRoom ? false : MatrixClientPeg.get().isRoomEncrypted(this.props.roomId); if (this.state.timelineSet) { - // console.log("rendering TimelinePanel for timelineSet " + this.state.timelineSet.room.roomId + " " + - // "(" + this.state.timelineSet._timelines.join(", ") + ")" + " with key " + this.props.roomId); return ( - - - - + + + + + + ); } else { return ( - - - + + + + + ); } } diff --git a/src/components/structures/NotificationPanel.tsx b/src/components/structures/NotificationPanel.tsx index f71c017c06..68c9049067 100644 --- a/src/components/structures/NotificationPanel.tsx +++ b/src/components/structures/NotificationPanel.tsx @@ -24,6 +24,7 @@ import TimelinePanel from "./TimelinePanel"; import Spinner from "../views/elements/Spinner"; import { TileShape } from "../views/rooms/EventTile"; import { Layout } from "../../settings/Layout"; +import RoomContext, { TimelineRenderingType } from "../../contexts/RoomContext"; interface IProps { onClose(): void; @@ -34,6 +35,7 @@ interface IProps { */ @replaceableComponent("structures.NotificationPanel") export default class NotificationPanel extends React.PureComponent { + static contextType = RoomContext; render() { const emptyState = (

{ _t('You’re all caught up') }

@@ -61,8 +63,13 @@ export default class NotificationPanel extends React.PureComponent { content = ; } - return - { content } - ; + return + + { content } + ; + ; } } diff --git a/src/components/views/messages/MessageActionBar.tsx b/src/components/views/messages/MessageActionBar.tsx index 7ee951a812..2246d2bacc 100644 --- a/src/components/views/messages/MessageActionBar.tsx +++ b/src/components/views/messages/MessageActionBar.tsx @@ -289,7 +289,7 @@ export default class MessageActionBar extends React.PureComponent ); } } + // Show thread icon even for deleted messages, but only within main timeline + if (this.context.timelineRenderingType === TimelineRenderingType.Room && + SettingsStore.getValue("feature_thread") && + this.props.mxEvent.getThread() && + !isContentActionable(this.props.mxEvent) + ) { + toolbarOpts.unshift(); + } if (allowCancel) { toolbarOpts.push(cancelSendingButton); diff --git a/src/contexts/RoomContext.ts b/src/contexts/RoomContext.ts index a57c14d90f..d3a4fadd19 100644 --- a/src/contexts/RoomContext.ts +++ b/src/contexts/RoomContext.ts @@ -21,6 +21,8 @@ import { Layout } from "../settings/Layout"; export enum TimelineRenderingType { Room, + File, + Notification, Thread } From 0d524ae70b13548a861c5f4352a793789ec10644 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 11 Oct 2021 10:43:37 +0100 Subject: [PATCH 105/143] Iterate invite your teammates to Space view --- res/css/structures/_SpaceRoomView.scss | 11 ++++++++--- src/components/structures/SpaceRoomView.tsx | 1 - 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/res/css/structures/_SpaceRoomView.scss b/res/css/structures/_SpaceRoomView.scss index 812b6dcea9..e116885047 100644 --- a/res/css/structures/_SpaceRoomView.scss +++ b/res/css/structures/_SpaceRoomView.scss @@ -422,7 +422,7 @@ $SpaceRoomViewInnerWidth: 428px; .mx_SpaceRoomView_inviteTeammates { // XXX remove this when spaces leaves Beta .mx_SpaceRoomView_inviteTeammates_betaDisclaimer { - padding: 58px 16px 16px; + padding: 16px; position: relative; border-radius: 8px; background-color: $header-panel-bg-color; @@ -465,8 +465,13 @@ $SpaceRoomViewInnerWidth: 428px; } } - .mx_SpaceRoomView_inviteTeammates_inviteDialogButton::before { - mask-image: url('$(res)/img/element-icons/room/invite.svg'); + .mx_SpaceRoomView_inviteTeammates_inviteDialogButton { + color: $accent-color; + + &::before { + mask-image: url('$(res)/img/element-icons/room/invite.svg'); + background-color: $accent-color; + } } } } diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx index 270db21408..629c62cde0 100644 --- a/src/components/structures/SpaceRoomView.tsx +++ b/src/components/structures/SpaceRoomView.tsx @@ -729,7 +729,6 @@ 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 }, From e54d803343e905cef10e2fd6b34f99f998e89d2a Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 11 Oct 2021 10:50:33 +0100 Subject: [PATCH 106/143] Tweak skeleton UI height to be more reasonable --- res/css/views/rooms/_RoomSublist.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/css/views/rooms/_RoomSublist.scss b/res/css/views/rooms/_RoomSublist.scss index 95b9f1822d..315ce08da5 100644 --- a/res/css/views/rooms/_RoomSublist.scss +++ b/res/css/views/rooms/_RoomSublist.scss @@ -391,7 +391,7 @@ limitations under the License. .mx_RoomSublist_skeletonUI { position: relative; margin-left: 4px; - height: 288px; + height: 240px; &::before { background: $roomsublist-skeleton-ui-bg; From 11480e8641a4776defab4e629eb102d0b5bd6b4d Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 11 Oct 2021 10:50:49 +0100 Subject: [PATCH 107/143] Hide Skeleton UI if you have Suggested Rooms --- src/components/views/rooms/RoomList.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/RoomList.tsx b/src/components/views/rooms/RoomList.tsx index 5ae2939c74..326e5cd892 100644 --- a/src/components/views/rooms/RoomList.tsx +++ b/src/components/views/rooms/RoomList.tsx @@ -449,8 +449,8 @@ export default class RoomList extends React.PureComponent { } private renderSublists(): React.ReactElement[] { - // show a skeleton UI if the user is in no rooms and they are not filtering - const showSkeleton = !this.state.isNameFiltering && + // show a skeleton UI if the user is in no rooms and they are not filtering and have no suggested rooms + const showSkeleton = !this.state.isNameFiltering && !this.state.suggestedRooms?.length && Object.values(RoomListStore.instance.unfilteredLists).every(list => !list?.length); return TAG_ORDER.reduce((tags, tagId) => { From 93cdda869379d6995a0c658bda97eb742150f93d Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Mon, 11 Oct 2021 11:55:21 +0100 Subject: [PATCH 108/143] Upgrade matrix-js-sdk to 14.0.0 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index f4f6e3c4f0..d2254bfa26 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,7 @@ "katex": "^0.12.0", "linkifyjs": "^2.1.9", "lodash": "^4.17.20", - "matrix-js-sdk": "14.0.0-rc.2", + "matrix-js-sdk": "14.0.0", "matrix-widget-api": "^0.1.0-beta.16", "minimist": "^1.2.5", "opus-recorder": "^8.0.3", diff --git a/yarn.lock b/yarn.lock index 0bd21610ea..4a810366fc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5862,10 +5862,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@14.0.0-rc.2: - version "14.0.0-rc.2" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-14.0.0-rc.2.tgz#36415152740c07a99eb7ed07fad032296fac59d8" - integrity sha512-6s9WP+GKzI4/SkunULHVfs+LnkcwvopQzVyN62+7HbfEOmlzrR77JbtIfPLZmcbcm9e+g4IkoiBMOFYt35bwvA== +matrix-js-sdk@14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-14.0.0.tgz#e04bca71a3dc3e3256171e184ac7614973e00db2" + integrity sha512-7OOSYpGUW7iRyNQrl/gdRxFRmbpW/C7L0gEdMbZwbOPqpbcvp6DVgl0eO+ibHoX0C8t0+rGAl/hMdOST9agGWg== dependencies: "@babel/runtime" "^7.12.5" another-json "^0.2.0" From e91d591c9070bb5e9e389591e5da453209685eb6 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Mon, 11 Oct 2021 11:57:03 +0100 Subject: [PATCH 109/143] Prepare changelog for v3.32.0 --- CHANGELOG.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 95a9c605ad..a647e376f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,31 @@ +Changes in [3.32.0](https://github.com/vector-im/element-desktop/releases/tag/v3.32.0) (2021-10-11) +=================================================================================================== + +## ✨ Features + * Decrease profile button touch target ([\#6900](https://github.com/matrix-org/matrix-react-sdk/pull/6900)). Contributed by [ColonisationCaptain](https://github.com/ColonisationCaptain). + * Don't let click events propagate out of context menus ([\#6892](https://github.com/matrix-org/matrix-react-sdk/pull/6892)). + * Allow closing Dropdown via its chevron ([\#6885](https://github.com/matrix-org/matrix-react-sdk/pull/6885)). Fixes vector-im/element-web#19030 and vector-im/element-web#19030. + * Improve AUX panel behaviour ([\#6699](https://github.com/matrix-org/matrix-react-sdk/pull/6699)). Fixes vector-im/element-web#18787 and vector-im/element-web#18787. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + * A nicer opening animation for the Image View ([\#6454](https://github.com/matrix-org/matrix-react-sdk/pull/6454)). Fixes vector-im/element-web#18186 and vector-im/element-web#18186. Contributed by [SimonBrandner](https://github.com/SimonBrandner). + +## 🐛 Bug Fixes + * [Release] Fix space hierarchy pagination ([\#6910](https://github.com/matrix-org/matrix-react-sdk/pull/6910)). + * Fix leaving space via other client leaving you in undefined-land ([\#6891](https://github.com/matrix-org/matrix-react-sdk/pull/6891)). Fixes vector-im/element-web#18455 and vector-im/element-web#18455. + * Handle newer voice message encrypted event format for chat export ([\#6893](https://github.com/matrix-org/matrix-react-sdk/pull/6893)). Contributed by [jaiwanth-v](https://github.com/jaiwanth-v). + * Fix pagination when filtering space hierarchy ([\#6876](https://github.com/matrix-org/matrix-react-sdk/pull/6876)). Fixes vector-im/element-web#19235 and vector-im/element-web#19235. + * Fix spaces null-guard breaking the dispatcher settings watching ([\#6886](https://github.com/matrix-org/matrix-react-sdk/pull/6886)). Fixes vector-im/element-web#19223 and vector-im/element-web#19223. + * Fix space children without specific `order` being sorted after those with one ([\#6878](https://github.com/matrix-org/matrix-react-sdk/pull/6878)). Fixes vector-im/element-web#19192 and vector-im/element-web#19192. + * Ensure that sub-spaces aren't considered for notification badges ([\#6881](https://github.com/matrix-org/matrix-react-sdk/pull/6881)). Fixes vector-im/element-web#18975 and vector-im/element-web#18975. + * Fix timeline autoscroll with non-standard DPI settings. ([\#6880](https://github.com/matrix-org/matrix-react-sdk/pull/6880)). Fixes vector-im/element-web#18984 and vector-im/element-web#18984. + * Pluck out JoinRuleSettings styles so they apply in space settings too ([\#6879](https://github.com/matrix-org/matrix-react-sdk/pull/6879)). Fixes vector-im/element-web#19164 and vector-im/element-web#19164. + * Null guard around the matrixClient in SpaceStore ([\#6874](https://github.com/matrix-org/matrix-react-sdk/pull/6874)). + * Fix issue (https ([\#6871](https://github.com/matrix-org/matrix-react-sdk/pull/6871)). Fixes vector-im/element-web#19138 and vector-im/element-web#19138. Contributed by [psrpinto](https://github.com/psrpinto). + * Fix pills being cut off in message bubble layout ([\#6865](https://github.com/matrix-org/matrix-react-sdk/pull/6865)). Fixes vector-im/element-web#18627 and vector-im/element-web#18627. Contributed by [robintown](https://github.com/robintown). + * Fix space admin check false positive on multiple admins ([\#6824](https://github.com/matrix-org/matrix-react-sdk/pull/6824)). + * Fix the User View ([\#6860](https://github.com/matrix-org/matrix-react-sdk/pull/6860)). Fixes vector-im/element-web#19158 and vector-im/element-web#19158. + * Fix spacing for message composer buttons ([\#6852](https://github.com/matrix-org/matrix-react-sdk/pull/6852)). Fixes vector-im/element-web#18999 and vector-im/element-web#18999. + * Always show root event of a thread in room's timeline ([\#6842](https://github.com/matrix-org/matrix-react-sdk/pull/6842)). Fixes vector-im/element-web#19016 and vector-im/element-web#19016. + Changes in [3.32.0-rc.2](https://github.com/vector-im/element-desktop/releases/tag/v3.32.0-rc.2) (2021-10-08) ============================================================================================================= From 4ceb2a74cf44daf21322e25adcdf5ad6a72b5f8f Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Mon, 11 Oct 2021 11:57:04 +0100 Subject: [PATCH 110/143] v3.32.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d2254bfa26..b364f0b33c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "3.32.0-rc.2", + "version": "3.32.0", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From 79a46782d6cc72fbd9018de6ea8c54c97afba55c Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Mon, 11 Oct 2021 12:03:50 +0100 Subject: [PATCH 111/143] Resetting package fields for development --- package.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index b364f0b33c..56e413acc4 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "bin": { "reskindex": "scripts/reskindex.js" }, - "main": "./lib/index.ts", + "main": "./src/index.ts", "matrix_src_main": "./src/index.ts", "matrix_lib_main": "./lib/index.ts", "matrix_lib_typings": "./lib/index.d.ts", @@ -215,6 +215,5 @@ "coverageReporters": [ "text" ] - }, - "typings": "./lib/index.d.ts" + } } From c4d4229340475e343d52806f3becef421b7f37c7 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 11 Oct 2021 13:50:34 +0100 Subject: [PATCH 112/143] hide leave section if you aren't in the room instead of disabling --- .../tabs/room/GeneralRoomSettingsTab.tsx | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.tsx b/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.tsx index 37ac358660..1cfe023ba9 100644 --- a/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.tsx +++ b/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.tsx @@ -90,6 +90,18 @@ export default class GeneralRoomSettingsTab extends React.Component; } + let leaveSection; + if (room.getMyMembership() === "join") { + leaveSection = <> + { _t("Leave room") } +
+ + { _t('Leave room') } + +
+ ; + } + return (
{ _t("General") }
@@ -109,17 +121,7 @@ export default class GeneralRoomSettingsTab extends React.Component{ _t("Other") }
{ flairSection } { urlPreviewSettings } - - { _t("Leave room") } -
- - { _t('Leave room') } - -
+ { leaveSection }
); } From c28c62d9f1d9adc0243eb94d7f3db732264d4e9b Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 11 Oct 2021 14:43:55 +0100 Subject: [PATCH 113/143] Inhibit `Unable to get validated threepid` error during UIA --- src/components/structures/InteractiveAuth.tsx | 49 ++++++------------- .../auth/InteractiveAuthEntryComponents.tsx | 27 +++++++--- 2 files changed, 36 insertions(+), 40 deletions(-) diff --git a/src/components/structures/InteractiveAuth.tsx b/src/components/structures/InteractiveAuth.tsx index 869cd29cba..970ea26309 100644 --- a/src/components/structures/InteractiveAuth.tsx +++ b/src/components/structures/InteractiveAuth.tsx @@ -84,7 +84,7 @@ interface IState { stageState?: IStageStatus; busy: boolean; errorText?: string; - stageErrorText?: string; + errorCode?: string; submitButtonEnabled: boolean; } @@ -103,7 +103,7 @@ export default class InteractiveAuthComponent extends React.Component { if (oldStage !== stageType) { this.setFocus(); @@ -208,7 +210,7 @@ export default class InteractiveAuthComponent extends React.Component { + this.props.onAuthFinished(false, e); + }; + + private setEmailSid = (sid: string): void => { + this.authLogic.setEmailSid(sid); + }; + + render() { const stage = this.state.authStage; if (!stage) { if (this.state.busy) { @@ -255,7 +265,8 @@ export default class InteractiveAuthComponent extends React.Component ); } - - private onAuthStageFailed = (e: Error): void => { - this.props.onAuthFinished(false, e); - }; - - private setEmailSid = (sid: string): void => { - this.authLogic.setEmailSid(sid); - }; - - render() { - let error = null; - if (this.state.errorText) { - error = ( -
- { this.state.errorText } -
- ); - } - - return ( -
-
- { this.renderCurrentStage() } - { error } -
-
- ); - } } diff --git a/src/components/views/auth/InteractiveAuthEntryComponents.tsx b/src/components/views/auth/InteractiveAuthEntryComponents.tsx index 5544810a03..53eef7031c 100644 --- a/src/components/views/auth/InteractiveAuthEntryComponents.tsx +++ b/src/components/views/auth/InteractiveAuthEntryComponents.tsx @@ -41,7 +41,7 @@ import { logger } from "matrix-js-sdk/src/logger"; * * matrixClient: A matrix client. May be a different one to the one * currently being used generally (eg. to register with - * one HS whilst beign a guest on another). + * one HS whilst being a guest on another). * loginType: the login type of the auth stage being attempted * authSessionId: session id from the server * clientSecret: The client secret in use for identity server auth sessions @@ -84,6 +84,7 @@ interface IAuthEntryProps { loginType: string; authSessionId: string; errorText?: string; + errorCode?: string; // Is the auth logic currently waiting for something to happen? busy?: boolean; onPhaseChange: (phase: number) => void; @@ -427,18 +428,29 @@ export class EmailIdentityAuthEntry extends React.Component + { this.props.errorText } +
+ ); + } + // This component is now only displayed once the token has been requested, // so we know the email has been sent. It can also get loaded after the user // has clicked the validation link if the server takes a while to propagate // the validation internally. If we're in the session spawned from clicking // the validation link, we won't know the email address, so if we don't have it, // assume that the link has been clicked and the server will realise when we poll. - if (this.props.inputs.emailAddress === undefined) { - return ; - } else if (this.props.stageState?.emailSid) { - // we only have a session ID if the user has clicked the link in their email, - // so show a loading state instead of "an email has been sent to..." because - // that's confusing when you've already read that email. + // We only have a session ID if the user has clicked the link in their email, + // so show a loading state instead of "an email has been sent to..." because + // that's confusing when you've already read that email. + if (this.props.inputs.emailAddress === undefined || this.props.stageState?.emailSid) { + if (errorSection) { + return errorSection; + } return ; } else { return ( @@ -448,6 +460,7 @@ export class EmailIdentityAuthEntry extends React.Component

{ _t("Open the link in the email to continue registration.") }

+ { errorSection } ); } From c078e89f5953557184f7649a8f9da63c5b304bb5 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Mon, 11 Oct 2021 14:33:40 -0400 Subject: [PATCH 114/143] Remove semicolon from notifications panel Signed-off-by: Robin Townsend --- src/components/structures/NotificationPanel.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/structures/NotificationPanel.tsx b/src/components/structures/NotificationPanel.tsx index 68c9049067..c37eeca091 100644 --- a/src/components/structures/NotificationPanel.tsx +++ b/src/components/structures/NotificationPanel.tsx @@ -69,7 +69,7 @@ export default class NotificationPanel extends React.PureComponent { }}> { content } - ; + ; } } From 6b4bcbd289860f320966360722e0d51e34904bce Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 12 Oct 2021 08:40:57 +0100 Subject: [PATCH 115/143] Upgrade matrix-js-sdk to 14.0.1 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 40633b9723..b2b09e334f 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,7 @@ "katex": "^0.12.0", "linkifyjs": "^2.1.9", "lodash": "^4.17.20", - "matrix-js-sdk": "14.0.0-rc.1", + "matrix-js-sdk": "14.0.1", "matrix-widget-api": "^0.1.0-beta.16", "minimist": "^1.2.5", "opus-recorder": "^8.0.3", diff --git a/yarn.lock b/yarn.lock index 0b17dc1284..15cc106ebd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5862,10 +5862,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@14.0.0-rc.1: - version "14.0.0-rc.1" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-14.0.0-rc.1.tgz#1cb3dfd2949d3a4414986f8ab0a92575f5fff0d1" - integrity sha512-idDBJRGOOdn9yOQWoZxwLSWv2xn7jF3IJ7W5UCmOZ0EKYmH7C1VlKAfvkGDpxdbrNCRs84SUvqJqImAuQoV4Gw== +matrix-js-sdk@14.0.1: + version "14.0.1" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-14.0.1.tgz#5984d9fafb2eda435fbe7d04a0daf37b48d595fd" + integrity sha512-+x+TaftVUXY8otBBSEHuVQp1B9UACEcHuKxmocFN/cmsjJGlk3z8hmthMbwnyq3HyOX9apme1TdbqqsoC2IlWg== dependencies: "@babel/runtime" "^7.12.5" another-json "^0.2.0" From acce5ea43af30b97c7727af797da6445a84f3bee Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 12 Oct 2021 08:42:34 +0100 Subject: [PATCH 116/143] Prepare changelog for v3.32.1 --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 327890d4da..28875dcfc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +Changes in [3.32.1](https://github.com/vector-im/element-desktop/releases/tag/v3.32.1) (2021-10-12) +=================================================================================================== + +## 🐛 Bug Fixes + + * Upgrade to matrix-js-sdk#14.0.1 + Changes in [3.32.0-rc.1](https://github.com/vector-im/element-desktop/releases/tag/v3.32.0-rc.1) (2021-10-04) ============================================================================================================= From b1baa3575a54f1d06450d75338073eb61d56fa40 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 12 Oct 2021 08:42:35 +0100 Subject: [PATCH 117/143] v3.32.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b2b09e334f..9fb603eaae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matrix-react-sdk", - "version": "3.32.0-rc.1", + "version": "3.32.1", "description": "SDK for matrix.org using React", "author": "matrix.org", "repository": { From 89365d943b4eb9d45ee6bb13ae5c4e47b6c653e5 Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 12 Oct 2021 08:48:24 +0100 Subject: [PATCH 118/143] Resetting package fields for development --- package.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 9fb603eaae..1433e45a44 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "bin": { "reskindex": "scripts/reskindex.js" }, - "main": "./lib/index.ts", + "main": "./src/index.ts", "matrix_src_main": "./src/index.ts", "matrix_lib_main": "./lib/index.ts", "matrix_lib_typings": "./lib/index.d.ts", @@ -215,6 +215,5 @@ "coverageReporters": [ "text" ] - }, - "typings": "./lib/index.d.ts" + } } From 193a060ec9c5278615a2698880320c24357a800d Mon Sep 17 00:00:00 2001 From: RiotRobot Date: Tue, 12 Oct 2021 09:13:06 +0100 Subject: [PATCH 119/143] 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 1433e45a44..599f61dc38 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,7 @@ "katex": "^0.12.0", "linkifyjs": "^2.1.9", "lodash": "^4.17.20", - "matrix-js-sdk": "14.0.1", + "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop", "matrix-widget-api": "^0.1.0-beta.16", "minimist": "^1.2.5", "opus-recorder": "^8.0.3", diff --git a/yarn.lock b/yarn.lock index dea4566b59..3d39a5344c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5840,10 +5840,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@14.0.1: +"matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop": version "14.0.1" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-14.0.1.tgz#5984d9fafb2eda435fbe7d04a0daf37b48d595fd" - integrity sha512-+x+TaftVUXY8otBBSEHuVQp1B9UACEcHuKxmocFN/cmsjJGlk3z8hmthMbwnyq3HyOX9apme1TdbqqsoC2IlWg== + resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/e7b41fadd0d6eda7423a369c99ec7b94afd48d5d" dependencies: "@babel/runtime" "^7.12.5" another-json "^0.2.0" From d050c0070347f313d0fbb3950210cefe110fc34e Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 12 Oct 2021 10:30:36 +0100 Subject: [PATCH 120/143] Fix room list skeleton ui for narrow room list --- res/css/views/rooms/_RoomSublist.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/res/css/views/rooms/_RoomSublist.scss b/res/css/views/rooms/_RoomSublist.scss index 315ce08da5..0cf5f5a9e0 100644 --- a/res/css/views/rooms/_RoomSublist.scss +++ b/res/css/views/rooms/_RoomSublist.scss @@ -406,3 +406,8 @@ limitations under the License. mask-image: url('$(res)/img/element-icons/roomlist/skeleton-ui.svg'); } } + +.mx_RoomSublist_minimized .mx_RoomSublist_skeletonUI { + width: 32px; // cut off the horizontal lines in the svg + margin-left: 10px; // align with sublist + buttons +} From fe70e64a40b341b3e21b8c25baacbf5693ef1a75 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 12 Oct 2021 11:01:40 +0100 Subject: [PATCH 121/143] Improve typing --- src/editor/deserialize.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/editor/deserialize.ts b/src/editor/deserialize.ts index 14be9f8a92..b9043e565a 100644 --- a/src/editor/deserialize.ts +++ b/src/editor/deserialize.ts @@ -20,7 +20,7 @@ import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import { walkDOMDepthFirst } from "./dom"; import { checkBlockNode } from "../HtmlUtils"; import { getPrimaryPermalinkEntity } from "../utils/permalinks/Permalinks"; -import { PartCreator, Type } from "./parts"; +import { Part, PartCreator, Type } from "./parts"; import SdkConfig from "../SdkConfig"; function parseAtRoomMentions(text: string, partCreator: PartCreator) { @@ -213,12 +213,12 @@ function prefixQuoteLines(isFirstNode, parts, partCreator) { } } -function parseHtmlMessage(html: string, partCreator: PartCreator, isQuotedMessage: boolean) { +function parseHtmlMessage(html: string, partCreator: PartCreator, isQuotedMessage: boolean): Part[] { // no nodes from parsing here should be inserted in the document, // as scripts in event handlers, etc would be executed then. // we're only taking text, so that is fine const rootNode = new DOMParser().parseFromString(html, "text/html").body; - const parts = []; + const parts: Part[] = []; let lastNode; let inQuote = isQuotedMessage; const state: IState = { @@ -233,7 +233,7 @@ function parseHtmlMessage(html: string, partCreator: PartCreator, isQuotedMessag inQuote = true; } - const newParts = []; + const newParts: Part[] = []; if (lastNode && (checkBlockNode(lastNode) || checkBlockNode(n))) { newParts.push(partCreator.newline()); } @@ -288,7 +288,7 @@ function parseHtmlMessage(html: string, partCreator: PartCreator, isQuotedMessag return parts; } -export function parsePlainTextMessage(body: string, partCreator: PartCreator, isQuotedMessage?: boolean) { +export function parsePlainTextMessage(body: string, partCreator: PartCreator, isQuotedMessage?: boolean): Part[] { const lines = body.split(/\r\n|\r|\n/g); // split on any new-line combination not just \n, collapses \r\n return lines.reduce((parts, line, i) => { if (isQuotedMessage) { @@ -300,7 +300,7 @@ export function parsePlainTextMessage(body: string, partCreator: PartCreator, is parts.push(partCreator.newline()); } return parts; - }, []); + }, [] as Part[]); } export function parseEvent(event: MatrixEvent, partCreator: PartCreator, { isQuotedMessage = false } = {}) { From ddc408690cf0931ca5d640a49a2de5091dc5edd6 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 12 Oct 2021 11:02:06 +0100 Subject: [PATCH 122/143] Fix EditorModel clone to actually be useful --- src/editor/model.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/editor/model.ts b/src/editor/model.ts index 212a7d17c0..b9850a7ba7 100644 --- a/src/editor/model.ts +++ b/src/editor/model.ts @@ -91,7 +91,8 @@ export default class EditorModel { } public clone(): EditorModel { - return new EditorModel(this._parts, this._partCreator, this.updateCallback); + const clonedParts = this.parts.map(p => this.partCreator.deserializePart(p.serialize())); + return new EditorModel(clonedParts, this._partCreator, this.updateCallback); } private insertPart(index: number, part: Part): void { From fd6d853bb13d3561622c674722cca6373d2dc462 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 12 Oct 2021 14:02:05 +0100 Subject: [PATCH 123/143] Allow editing of /rainbow and /rainbowme --- src/editor/deserialize.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/editor/deserialize.ts b/src/editor/deserialize.ts index b9043e565a..1f84c08239 100644 --- a/src/editor/deserialize.ts +++ b/src/editor/deserialize.ts @@ -22,6 +22,7 @@ import { checkBlockNode } from "../HtmlUtils"; import { getPrimaryPermalinkEntity } from "../utils/permalinks/Permalinks"; import { Part, PartCreator, Type } from "./parts"; import SdkConfig from "../SdkConfig"; +import { textToHtmlRainbow } from "../utils/colour"; function parseAtRoomMentions(text: string, partCreator: PartCreator) { const ATROOM = "@room"; @@ -305,14 +306,26 @@ export function parsePlainTextMessage(body: string, partCreator: PartCreator, is export function parseEvent(event: MatrixEvent, partCreator: PartCreator, { isQuotedMessage = false } = {}) { const content = event.getContent(); - let parts; + let parts: Part[]; + const isEmote = content.msgtype === "m.emote"; + let isRainbow = false; + if (content.format === "org.matrix.custom.html") { parts = parseHtmlMessage(content.formatted_body || "", partCreator, isQuotedMessage); + if (content.body && content.formatted_body && textToHtmlRainbow(content.body) === content.formatted_body) { + isRainbow = true; + } } else { parts = parsePlainTextMessage(content.body || "", partCreator, isQuotedMessage); } - if (content.msgtype === "m.emote") { + + if (isEmote && isRainbow) { + parts.unshift(partCreator.plain("/rainbowme ")); + } else if (isRainbow) { + parts.unshift(partCreator.plain("/rainbow ")); + } else if (isEmote) { parts.unshift(partCreator.plain("/me ")); } + return parts; } From 8873c75567f20c735ca8e92db23f2703e169d352 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 12 Oct 2021 13:44:49 -0600 Subject: [PATCH 124/143] Fix bad imports to js-sdk --- src/AddThreepid.ts | 2 +- src/stores/ActiveWidgetStore.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AddThreepid.ts b/src/AddThreepid.ts index 54250c5eb3..b1c7abc68b 100644 --- a/src/AddThreepid.ts +++ b/src/AddThreepid.ts @@ -21,7 +21,7 @@ import Modal from './Modal'; import { _t } from './languageHandler'; import IdentityAuthClient from './IdentityAuthClient'; import { SSOAuthEntry } from "./components/views/auth/InteractiveAuthEntryComponents"; -import { IRequestMsisdnTokenResponse, IRequestTokenResponse } from "matrix-js-sdk"; +import { IRequestMsisdnTokenResponse, IRequestTokenResponse } from "matrix-js-sdk/src"; import InteractiveAuthDialog from "./components/views/dialogs/InteractiveAuthDialog"; function getIdServerDomain(): string { diff --git a/src/stores/ActiveWidgetStore.ts b/src/stores/ActiveWidgetStore.ts index ca50689188..81fc6de911 100644 --- a/src/stores/ActiveWidgetStore.ts +++ b/src/stores/ActiveWidgetStore.ts @@ -15,7 +15,7 @@ limitations under the License. */ import EventEmitter from 'events'; -import { MatrixEvent } from "matrix-js-sdk"; +import { MatrixEvent } from "matrix-js-sdk/src"; import { MatrixClientPeg } from '../MatrixClientPeg'; import { WidgetMessagingStore } from "./widgets/WidgetMessagingStore"; From d99660d420be70298a5f53dd84c1ab07c4fc5850 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 8 Oct 2021 16:04:26 -0600 Subject: [PATCH 125/143] Add customisation point for visibility of invites and room creation Fixes https://github.com/vector-im/element-web/issues/19331 --- src/SlashCommands.tsx | 4 +- src/components/structures/SpaceRoomView.tsx | 4 +- src/components/views/right_panel/UserInfo.tsx | 4 +- src/components/views/rooms/MemberList.tsx | 4 +- src/components/views/rooms/NewRoomIntro.tsx | 6 +- src/components/views/rooms/RoomList.tsx | 60 +++++++++++-------- src/components/views/rooms/RoomSublist.tsx | 5 +- .../views/spaces/SpacePublicShare.tsx | 24 ++++---- src/customisations/ComponentVisibility.ts | 51 ++++++++++++++++ src/customisations/helpers/UIComponents.ts | 22 +++++++ src/settings/UIFeature.ts | 5 ++ 11 files changed, 146 insertions(+), 43 deletions(-) create mode 100644 src/customisations/ComponentVisibility.ts create mode 100644 src/customisations/helpers/UIComponents.ts diff --git a/src/SlashCommands.tsx b/src/SlashCommands.tsx index f3214c4757..4ffab08780 100644 --- a/src/SlashCommands.tsx +++ b/src/SlashCommands.tsx @@ -44,7 +44,7 @@ import { Action } from "./dispatcher/actions"; import { EffectiveMembership, getEffectiveMembership, leaveRoomBehaviour } from "./utils/membership"; import SdkConfig from "./SdkConfig"; import SettingsStore from "./settings/SettingsStore"; -import { UIFeature } from "./settings/UIFeature"; +import { UIComponent, UIFeature } from "./settings/UIFeature"; import { CHAT_EFFECTS } from "./effects"; import CallHandler from "./CallHandler"; import { guessAndSetDMRoom } from "./Rooms"; @@ -56,6 +56,7 @@ import InfoDialog from "./components/views/dialogs/InfoDialog"; import SlashCommandHelpDialog from "./components/views/dialogs/SlashCommandHelpDialog"; import { logger } from "matrix-js-sdk/src/logger"; +import { shouldShowComponent } from "./customisations/helpers/UIComponents"; // XXX: workaround for https://github.com/microsoft/TypeScript/issues/31816 interface HTMLInputEvent extends Event { @@ -403,6 +404,7 @@ export const Commands = [ command: 'invite', args: ' []', description: _td('Invites user with given id to current room'), + isEnabled: () => shouldShowComponent(UIComponent.InviteUsers), runFn: function(roomId, args) { if (args) { const [address, reason] = args.split(/\s+(.+)/); diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx index 629c62cde0..54dde2e891 100644 --- a/src/components/structures/SpaceRoomView.tsx +++ b/src/components/structures/SpaceRoomView.tsx @@ -81,6 +81,8 @@ import GroupAvatar from "../views/avatars/GroupAvatar"; import { useDispatcher } from "../../hooks/useDispatcher"; import { logger } from "matrix-js-sdk/src/logger"; +import { shouldShowComponent } from "../../customisations/helpers/UIComponents"; +import { UIComponent } from "../../settings/UIFeature"; interface IProps { space: Room; @@ -411,7 +413,7 @@ const SpaceLanding = ({ space }) => { const userId = cli.getUserId(); let inviteButton; - if (myMembership === "join" && space.canInvite(userId)) { + if (myMembership === "join" && space.canInvite(userId) && shouldShowComponent(UIComponent.InviteUsers)) { inviteButton = ( { try { diff --git a/src/components/views/rooms/MemberList.tsx b/src/components/views/rooms/MemberList.tsx index df4f2d21fa..b31b09ab24 100644 --- a/src/components/views/rooms/MemberList.tsx +++ b/src/components/views/rooms/MemberList.tsx @@ -44,6 +44,8 @@ import MemberTile from "./MemberTile"; import BaseAvatar from '../avatars/BaseAvatar'; import { throttle } from 'lodash'; import SpaceStore from "../../../stores/SpaceStore"; +import { shouldShowComponent } from "../../../customisations/helpers/UIComponents"; +import { UIComponent } from "../../../settings/UIFeature"; const getSearchQueryLSKey = (roomId: string) => `mx_MemberList_searchQuarry_${roomId}`; @@ -530,7 +532,7 @@ export default class MemberList extends React.Component { const room = cli.getRoom(this.props.roomId); let inviteButton; - if (room && room.getMyMembership() === 'join') { + if (room?.getMyMembership() === 'join' && shouldShowComponent(UIComponent.InviteUsers)) { let inviteButtonText = _t("Invite to this room"); const chat = CommunityPrototypeStore.instance.getSelectedCommunityGeneralChat(); if (chat && chat.roomId === this.props.roomId) { diff --git a/src/components/views/rooms/NewRoomIntro.tsx b/src/components/views/rooms/NewRoomIntro.tsx index 8a96b8a9ba..fbaccfd6b5 100644 --- a/src/components/views/rooms/NewRoomIntro.tsx +++ b/src/components/views/rooms/NewRoomIntro.tsx @@ -28,15 +28,17 @@ import AccessibleButton from "../elements/AccessibleButton"; import MiniAvatarUploader, { AVATAR_SIZE } from "../elements/MiniAvatarUploader"; import RoomAvatar from "../avatars/RoomAvatar"; import defaultDispatcher from "../../../dispatcher/dispatcher"; +import dis from "../../../dispatcher/dispatcher"; import { ViewUserPayload } from "../../../dispatcher/payloads/ViewUserPayload"; import { Action } from "../../../dispatcher/actions"; -import dis from "../../../dispatcher/dispatcher"; import SpaceStore from "../../../stores/SpaceStore"; import { showSpaceInvite } from "../../../utils/space"; import { privateShouldBeEncrypted } from "../../../createRoom"; import EventTileBubble from "../messages/EventTileBubble"; import { ROOM_SECURITY_TAB } from "../dialogs/RoomSettingsDialog"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; +import { shouldShowComponent } from "../../../customisations/helpers/UIComponents"; +import { UIComponent } from "../../../settings/UIFeature"; function hasExpectedEncryptionSettings(matrixClient: MatrixClient, room: Room): boolean { const isEncrypted: boolean = matrixClient.isRoomEncrypted(room.roomId); @@ -150,7 +152,7 @@ const NewRoomIntro = () => { { _t("Invite to just this room") } } ; - } else if (room.canInvite(cli.getUserId())) { + } else if (room.canInvite(cli.getUserId()) && shouldShowComponent(UIComponent.InviteUsers)) { buttons =
void; @@ -133,32 +135,38 @@ const TAG_AESTHETICS: ITagAestheticsMap = { MatrixClientPeg.get().getUserId()); return - { - e.preventDefault(); - e.stopPropagation(); - onFinished(); - showCreateNewRoom(SpaceStore.instance.activeSpace); - }} - disabled={!canAddRooms} - tooltip={canAddRooms ? undefined - : _t("You do not have permissions to create new rooms in this space")} - /> - { - e.preventDefault(); - e.stopPropagation(); - onFinished(); - showAddExistingRooms(SpaceStore.instance.activeSpace); - }} - disabled={!canAddRooms} - tooltip={canAddRooms ? undefined - : _t("You do not have permissions to add rooms to this space")} - /> + { + shouldShowComponent(UIComponent.CreateRooms) + ? (<> + { + e.preventDefault(); + e.stopPropagation(); + onFinished(); + showCreateNewRoom(SpaceStore.instance.activeSpace); + }} + disabled={!canAddRooms} + tooltip={canAddRooms ? undefined + : _t("You do not have permissions to create new rooms in this space")} + /> + { + e.preventDefault(); + e.stopPropagation(); + onFinished(); + showAddExistingRooms(SpaceStore.instance.activeSpace); + }} + disabled={!canAddRooms} + tooltip={canAddRooms ? undefined + : _t("You do not have permissions to add rooms to this space")} + /> + ) + : null + } { ); let addRoomButton = null; - if (!!this.props.onAddRoom) { + if (!!this.props.onAddRoom && shouldShowComponent(UIComponent.CreateRooms)) { addRoomButton = ( { /> ); } else if (this.props.addRoomContextMenu) { + // We assume that shouldShowComponent() is checked by the context menu itself. addRoomButton = ( {

{ _t("Share invite link") }

{ copiedText }
- { space.canInvite(MatrixClientPeg.get()?.getUserId()) ? { - if (onFinished) onFinished(); - showRoomInviteDialog(space.roomId); - }} - > -

{ _t("Invite people") }

- { _t("Invite with email or username") } -
: null } + { space.canInvite(MatrixClientPeg.get()?.getUserId()) && shouldShowComponent(UIComponent.InviteUsers) + ? { + if (onFinished) onFinished(); + showRoomInviteDialog(space.roomId); + }} + > +

{ _t("Invite people") }

+ { _t("Invite with email or username") } +
+ : null }
; }; diff --git a/src/customisations/ComponentVisibility.ts b/src/customisations/ComponentVisibility.ts new file mode 100644 index 0000000000..3e12805f42 --- /dev/null +++ b/src/customisations/ComponentVisibility.ts @@ -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. +*/ + +// Dev note: this customisation point is heavily inspired by UIFeature flags, though +// with an intention of being used for more complex switching on whether or not a feature +// should be shown. + +// Populate this class with the details of your customisations when copying it. + +import { UIComponent } from "../settings/UIFeature"; + +/** + * Determines whether or not the active MatrixClient user should be able to use + * the given UI component. If shown, the user might still not be able to use the + * component depending on their contextual permissions. For example, invite options + * might be shown to the user but they won't have permission to invite users to + * the current room: the button will appear disabled. + * @param {UIComponent} component The component to check visibility for. + * @returns {boolean} True (default) if the user is able to see the component, false + * otherwise. + */ +function shouldShowComponent(component: UIComponent): boolean { + return true; // default to visible +} + +// This interface summarises all available customisation points and also marks +// them all as optional. This allows customisers to only define and export the +// customisations they need while still maintaining type safety. +export interface IComponentVisibilityCustomisations { + shouldShowComponent?: typeof shouldShowComponent; +} + +// A real customisation module will define and export one or more of the +// customisation points that make up the interface above. +export const ComponentVisibilityCustomisations: IComponentVisibilityCustomisations = { + // while we don't specify the functions here, their defaults are described + // in their pseudo-implementations above. +}; diff --git a/src/customisations/helpers/UIComponents.ts b/src/customisations/helpers/UIComponents.ts new file mode 100644 index 0000000000..11b8a40969 --- /dev/null +++ b/src/customisations/helpers/UIComponents.ts @@ -0,0 +1,22 @@ +/* +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 { UIComponent } from "../../settings/UIFeature"; +import { ComponentVisibilityCustomisations } from "../ComponentVisibility"; + +export function shouldShowComponent(component: UIComponent): boolean { + return ComponentVisibilityCustomisations.shouldShowComponent?.(component) ?? true; +} diff --git a/src/settings/UIFeature.ts b/src/settings/UIFeature.ts index 82dfdf0bb5..847da2537e 100644 --- a/src/settings/UIFeature.ts +++ b/src/settings/UIFeature.ts @@ -33,3 +33,8 @@ export enum UIFeature { AdvancedSettings = "UIFeature.advancedSettings", RoomHistorySettings = "UIFeature.roomHistorySettings", } + +export enum UIComponent { + InviteUsers = "UIComponent.sendInvites", + CreateRooms = "UIComponent.roomCreation", +} From 71c5b023904dd2ac05bd9976c367027a193517f3 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 12 Oct 2021 15:13:56 -0600 Subject: [PATCH 126/143] Add feature flag for polls and placeholder dialog We're anticipating development of polls soon, so for efficiency reasons we're getting the labs flag in early. If something goes wrong with the plan, this whole change will be reverted. --- res/css/views/rooms/_MessageComposer.scss | 4 +++ res/img/element-icons/room/composer/poll.svg | 5 +++ .../views/rooms/MessageComposer.tsx | 32 +++++++++++++++++++ src/i18n/strings/en_EN.json | 2 ++ src/settings/Settings.tsx | 6 ++++ 5 files changed, 49 insertions(+) create mode 100644 res/img/element-icons/room/composer/poll.svg diff --git a/res/css/views/rooms/_MessageComposer.scss b/res/css/views/rooms/_MessageComposer.scss index c20dd43daf..62cbdb910a 100644 --- a/res/css/views/rooms/_MessageComposer.scss +++ b/res/css/views/rooms/_MessageComposer.scss @@ -252,6 +252,10 @@ limitations under the License. mask-image: url('$(res)/img/element-icons/room/composer/attach.svg'); } +.mx_MessageComposer_poll::before { + mask-image: url('$(res)/img/element-icons/room/composer/poll.svg'); +} + .mx_MessageComposer_voiceMessage::before { mask-image: url('$(res)/img/voip/mic-on-mask.svg'); } diff --git a/res/img/element-icons/room/composer/poll.svg b/res/img/element-icons/room/composer/poll.svg new file mode 100644 index 0000000000..063edab7ab --- /dev/null +++ b/res/img/element-icons/room/composer/poll.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/components/views/rooms/MessageComposer.tsx b/src/components/views/rooms/MessageComposer.tsx index f14af69a6d..e092081e6a 100644 --- a/src/components/views/rooms/MessageComposer.tsx +++ b/src/components/views/rooms/MessageComposer.tsx @@ -52,6 +52,8 @@ import EditorModel from "../../../editor/model"; import EmojiPicker from '../emojipicker/EmojiPicker'; import MemberStatusMessageAvatar from "../avatars/MemberStatusMessageAvatar"; import UIStore, { UI_EVENTS } from '../../../stores/UIStore'; +import Modal from "../../../Modal"; +import InfoDialog from "../dialogs/InfoDialog"; let instanceCount = 0; const NARROW_MODE_BREAKPOINT = 500; @@ -193,6 +195,31 @@ class UploadButton extends React.Component { } } +// TODO: [polls] Make this component actually do something +class PollButton extends React.PureComponent { + private onCreateClick = () => { + Modal.createTrackedDialog('Polls', 'Not Yet Implemented', InfoDialog, { + // XXX: Deliberately not translated given this dialog is meant to be replaced and we don't + // want to clutter the language files with short-lived strings. + title: "Polls are currently in development", + description: "" + + "Thanks for testing polls! We haven't quite gotten a chance to write the feature yet " + + "though. Check back later for updates.", + hasCloseButton: true, + }); + }; + + render() { + return ( + + ); + } +} + interface IProps { room: Room; resizeNotifier: ResizeNotifier; @@ -432,6 +459,11 @@ export default class MessageComposer extends React.Component { private renderButtons(menuPosition): JSX.Element | JSX.Element[] { const buttons: JSX.Element[] = []; if (!this.state.haveRecording) { + if (SettingsStore.getValue("feature_polls")) { + buttons.push( + + ); + } buttons.push( , ); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index bdc86a9e08..c9573a69db 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -823,6 +823,7 @@ "Show message previews for reactions in all rooms": "Show message previews for reactions in all rooms", "Offline encrypted messaging using dehydrated devices": "Offline encrypted messaging using dehydrated devices", "Send pseudonymous analytics data": "Send pseudonymous analytics data", + "Polls (under active development)": "Polls (under active development)", "Show info about bridges in room settings": "Show info about bridges in room settings", "New layout switcher (with message bubbles)": "New layout switcher (with message bubbles)", "Don't send read receipts": "Don't send read receipts", @@ -1575,6 +1576,7 @@ "Emoji picker": "Emoji picker", "Add emoji": "Add emoji", "Upload file": "Upload file", + "Create poll": "Create poll", "Reply to encrypted thread…": "Reply to encrypted thread…", "Reply to thread…": "Reply to thread…", "Send an encrypted reply…": "Send an encrypted reply…", diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx index 9fba69a63b..d36ea2ac94 100644 --- a/src/settings/Settings.tsx +++ b/src/settings/Settings.tsx @@ -246,6 +246,12 @@ export const SETTINGS: {[setting: string]: ISetting} = { default: false, controller: new PseudonymousAnalyticsController(), }, + "feature_polls": { + isFeature: true, + supportedLevels: LEVELS_FEATURE, + displayName: _td("Polls (under active development)"), + default: false, + }, "doNotDisturb": { supportedLevels: [SettingLevel.DEVICE], default: false, From ad53662704bce987ef419a58a80803831c933a72 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 12 Oct 2021 15:26:22 -0600 Subject: [PATCH 127/143] add comma --- src/components/views/rooms/MessageComposer.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/MessageComposer.tsx b/src/components/views/rooms/MessageComposer.tsx index e092081e6a..6633aacbb5 100644 --- a/src/components/views/rooms/MessageComposer.tsx +++ b/src/components/views/rooms/MessageComposer.tsx @@ -461,7 +461,7 @@ export default class MessageComposer extends React.Component { if (!this.state.haveRecording) { if (SettingsStore.getValue("feature_polls")) { buttons.push( - + , ); } buttons.push( From bc336abf475dca54ab000ea23f3911482d7b8f6d Mon Sep 17 00:00:00 2001 From: Dariusz Niemczyk <3636685+Palid@users.noreply.github.com> Date: Wed, 13 Oct 2021 12:09:43 +0200 Subject: [PATCH 128/143] Fix missing snapshot serializer&enzyme init (#6932) --- package.json | 3 ++ test/accessibility/RovingTabIndex-test.js | 5 +-- .../structures/MessagePanel-test.js | 5 +-- .../views/dialogs/ForwardDialog-test.js | 5 +-- .../views/messages/TextualBody-test.js | 5 +-- .../views/rooms/SendMessageComposer-test.tsx | 5 +-- test/setupTests.js | 5 +++ yarn.lock | 34 ++++++++++++++++--- 8 files changed, 42 insertions(+), 25 deletions(-) diff --git a/package.json b/package.json index 599f61dc38..c601072126 100644 --- a/package.json +++ b/package.json @@ -134,6 +134,7 @@ "@types/counterpart": "^0.18.1", "@types/css-font-loading-module": "^0.0.6", "@types/diff-match-patch": "^1.0.32", + "@types/enzyme": "^3.10.9", "@types/file-saver": "^2.0.3", "@types/flux": "^3.1.9", "@types/jest": "^26.0.20", @@ -158,6 +159,7 @@ "chokidar": "^3.5.1", "concurrently": "^5.3.0", "enzyme": "^3.11.0", + "enzyme-to-json": "^3.6.2", "eslint": "7.18.0", "eslint-config-google": "^0.14.0", "eslint-plugin-matrix-org": "github:matrix-org/eslint-plugin-matrix-org#2306b3d4da4eba908b256014b979f1d3d43d2945", @@ -186,6 +188,7 @@ "@types/react": "17.0.14" }, "jest": { + "snapshotSerializers": ["enzyme-to-json/serializer"], "testEnvironment": "./__test-utils__/environment.js", "testMatch": [ "/test/**/*-test.[jt]s?(x)" diff --git a/test/accessibility/RovingTabIndex-test.js b/test/accessibility/RovingTabIndex-test.js index 72d4253710..861aeaf9d7 100644 --- a/test/accessibility/RovingTabIndex-test.js +++ b/test/accessibility/RovingTabIndex-test.js @@ -16,8 +16,7 @@ limitations under the License. import '../skinned-sdk'; // Must be first for skinning to work import React from "react"; -import Adapter from "@wojtekmaj/enzyme-adapter-react-17"; -import { configure, mount } from "enzyme"; +import { mount } from "enzyme"; import { RovingTabIndexProvider, @@ -25,8 +24,6 @@ import { useRovingTabIndex, } from "../../src/accessibility/RovingTabIndex"; -configure({ adapter: new Adapter() }); - const Button = (props) => { const [onFocus, isActive, ref] = useRovingTabIndex(); return { SettingsStore.getValue("feature_thread") && ( - ) } diff --git a/src/components/views/rooms/EventTile.tsx b/src/components/views/rooms/EventTile.tsx index b74ee3a8cf..9d608c2833 100644 --- a/src/components/views/rooms/EventTile.tsx +++ b/src/components/views/rooms/EventTile.tsx @@ -56,9 +56,9 @@ import ReadReceiptMarker from "./ReadReceiptMarker"; import MessageActionBar from "../messages/MessageActionBar"; import ReactionsRow from '../messages/ReactionsRow'; import { getEventDisplayInfo } from '../../../utils/EventUtils'; -import { RightPanelPhases } from "../../../stores/RightPanelStorePhases"; import SettingsStore from "../../../settings/SettingsStore"; import MKeyVerificationConclusion from "../messages/MKeyVerificationConclusion"; +import { dispatchShowThreadEvent } from '../../../dispatcher/dispatch-actions/threads'; const eventTileTypes = { [EventType.RoomMessage]: 'messages.MessageEvent', @@ -193,6 +193,7 @@ export enum TileShape { FileGrid = "file_grid", Pinned = "pinned", Thread = "thread", + ThreadPanel = "thread_list" } interface IProps { @@ -511,6 +512,10 @@ export default class EventTile extends React.Component { if (this.props.showReactions) { this.props.mxEvent.removeListener("Event.relationsCreated", this.onReactionsCreated); } + if (SettingsStore.getValue("feature_thread")) { + this.props.mxEvent.off(ThreadEvent.Ready, this.updateThread); + this.props.mxEvent.off(ThreadEvent.Update, this.updateThread); + } } componentDidUpdate(prevProps, prevState, snapshot) { @@ -541,13 +546,7 @@ export default class EventTile extends React.Component {
{ - dis.dispatch({ - action: Action.SetRightPanelPhase, - phase: RightPanelPhases.ThreadView, - refireParams: { - event: this.props.mxEvent, - }, - }); + dispatchShowThreadEvent(this.props.mxEvent); }} > diff --git a/src/components/views/rooms/RoomHeader.tsx b/src/components/views/rooms/RoomHeader.tsx index d0e438bcda..e3b4804ae6 100644 --- a/src/components/views/rooms/RoomHeader.tsx +++ b/src/components/views/rooms/RoomHeader.tsx @@ -155,58 +155,55 @@ export default class RoomHeader extends React.Component { />; } - let forgetButton; - if (this.props.onForgetClick) { - forgetButton = - ; - } + const buttons: JSX.Element[] = []; - let appsButton; - if (this.props.onAppsClick) { - appsButton = - ; - } - - let searchButton; - if (this.props.onSearchClick && this.props.inRoom) { - searchButton = - ; - } - - let voiceCallButton; - let videoCallButton; if (this.props.inRoom && SettingsStore.getValue("showCallButtonsInComposer")) { - voiceCallButton = - this.props.onCallPlaced(PlaceCallType.Voice)} - title={_t("Voice call")} />; - videoCallButton = - ) => ev.shiftKey ? - this.displayInfoDialogAboutScreensharing() : this.props.onCallPlaced(PlaceCallType.Video)} - title={_t("Video call")} />; + const voiceCallButton = this.props.onCallPlaced(PlaceCallType.Voice)} + title={_t("Voice call")} + />; + const videoCallButton = ) => ev.shiftKey ? + this.displayInfoDialogAboutScreensharing() : this.props.onCallPlaced(PlaceCallType.Video)} + title={_t("Video call")} + />; + buttons.push(voiceCallButton, videoCallButton); + } + + if (this.props.onForgetClick) { + const forgetButton = ; + buttons.push(forgetButton); + } + + if (this.props.onAppsClick) { + const appsButton = ; + buttons.push(appsButton); + } + + if (this.props.onSearchClick && this.props.inRoom) { + const searchButton = ; + buttons.push(searchButton); } const rightRow =
- { videoCallButton } - { voiceCallButton } - { forgetButton } - { appsButton } - { searchButton } + { buttons }
; const e2eIcon = this.props.e2eStatus ? : undefined; diff --git a/src/contexts/RoomContext.ts b/src/contexts/RoomContext.ts index d3a4fadd19..c5426e0dcd 100644 --- a/src/contexts/RoomContext.ts +++ b/src/contexts/RoomContext.ts @@ -21,9 +21,10 @@ import { Layout } from "../settings/Layout"; export enum TimelineRenderingType { Room, + Thread, + ThreadsList, File, Notification, - Thread } const RoomContext = createContext({ diff --git a/src/dispatcher/dispatch-actions/threads.ts b/src/dispatcher/dispatch-actions/threads.ts new file mode 100644 index 0000000000..cda2f55707 --- /dev/null +++ b/src/dispatcher/dispatch-actions/threads.ts @@ -0,0 +1,38 @@ +/* +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 { RightPanelPhases } from "../../stores/RightPanelStorePhases"; +import { Action } from "../actions"; +import dis from '../dispatcher'; +import { SetRightPanelPhasePayload } from "../payloads/SetRightPanelPhasePayload"; + +export const dispatchShowThreadEvent = (event: MatrixEvent) => { + dis.dispatch({ + action: Action.SetRightPanelPhase, + phase: RightPanelPhases.ThreadView, + refireParams: { + event, + }, + }); +}; + +export const dispatchShowThreadsPanelEvent = () => { + dis.dispatch({ + action: Action.SetRightPanelPhase, + phase: RightPanelPhases.ThreadPanel, + }); +}; + diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index fc68c60943..3e61146acb 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1831,6 +1831,7 @@ "Nothing pinned, yet": "Nothing pinned, yet", "If you have permissions, open the menu on any message and select Pin to stick them here.": "If you have permissions, open the menu on any message and select Pin to stick them here.", "Pinned messages": "Pinned messages", + "Threads": "Threads", "Room Info": "Room Info", "You can only pin up to %(count)s widgets|other": "You can only pin up to %(count)s widgets", "Unpin a widget to view it in this panel": "Unpin a widget to view it in this panel", @@ -2974,6 +2975,11 @@ "You can add more later too, including already existing ones.": "You can add more later too, including already existing ones.", "What projects are you working on?": "What projects are you working on?", "We'll create rooms for each of them. You can add more later too, including already existing ones.": "We'll create rooms for each of them. You can add more later too, including already existing ones.", + "My threads": "My threads", + "Shows all threads you’ve participated in": "Shows all threads you’ve participated in", + "All threads": "All threads", + "Shows all threads from current room": "Shows all threads from current room", + "Show:": "Show:", "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.": "Tried to load a specific point in this room's timeline, but you do not have permission to view the message in question.", "Tried to load a specific point in this room's timeline, but was unable to find it.": "Tried to load a specific point in this room's timeline, but was unable to find it.", "Failed to load timeline position": "Failed to load timeline position", diff --git a/test/components/structures/ThreadPanel-test.tsx b/test/components/structures/ThreadPanel-test.tsx new file mode 100644 index 0000000000..d6de2ebde6 --- /dev/null +++ b/test/components/structures/ThreadPanel-test.tsx @@ -0,0 +1,81 @@ +/* +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 { shallow, mount, configure } from "enzyme"; +import '../../skinned-sdk'; +import Adapter from "@wojtekmaj/enzyme-adapter-react-17"; + +import { + ThreadFilterType, + ThreadPanelHeader, + ThreadPanelHeaderFilterOptionItem, +} from '../../../src/components/structures/ThreadPanel'; +import { ContextMenuButton } from '../../../src/accessibility/context_menu/ContextMenuButton'; +import ContextMenu from '../../../src/components/structures/ContextMenu'; +import { _t } from '../../../src/languageHandler'; + +configure({ adapter: new Adapter() }); + +describe('ThreadPanel', () => { + describe('Header', () => { + it('expect that All filter for ThreadPanelHeader properly renders Show: All threads', () => { + const wrapper = shallow( + undefined} />, + ); + expect(wrapper).toMatchSnapshot(); + }); + + it('expect that My filter for ThreadPanelHeader properly renders Show: My threads', () => { + const wrapper = shallow( + undefined} />, + ); + expect(wrapper).toMatchSnapshot(); + }); + + it('expect that ThreadPanelHeader properly opens a context menu when clicked on the button', () => { + const wrapper = mount( + undefined} />, + ); + const found = wrapper.find(ContextMenuButton); + expect(found).not.toBe(undefined); + expect(found).not.toBe(null); + expect(wrapper.exists(ContextMenu)).toEqual(false); + found.simulate('click'); + expect(wrapper.exists(ContextMenu)).toEqual(true); + }); + + it('expect that ThreadPanelHeader has the correct option selected in the context menu', () => { + const wrapper = mount( + undefined} />, + ); + wrapper.find(ContextMenuButton).simulate('click'); + const found = wrapper.find(ThreadPanelHeaderFilterOptionItem); + expect(found.length).toEqual(2); + const foundButton = found.find('[aria-selected=true]').first(); + expect(foundButton.text()).toEqual(`${_t("All threads")}${_t('Shows all threads from current room')}`); + expect(foundButton).toMatchSnapshot(); + }); + }); +}); diff --git a/test/components/structures/__snapshots__/ThreadPanel-test.tsx.snap b/test/components/structures/__snapshots__/ThreadPanel-test.tsx.snap new file mode 100644 index 0000000000..016da53ddd --- /dev/null +++ b/test/components/structures/__snapshots__/ThreadPanel-test.tsx.snap @@ -0,0 +1,71 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ThreadPanel Header expect that All filter for ThreadPanelHeader properly renders Show: All threads 1`] = ` +
+ + Threads + + + Show: All threads + +
+`; + +exports[`ThreadPanel Header expect that My filter for ThreadPanelHeader properly renders Show: My threads 1`] = ` +
+ + Threads + + + Show: My threads + +
+`; + +exports[`ThreadPanel Header expect that ThreadPanelHeader has the correct option selected in the context menu 1`] = ` + +
+ + All threads + + + Shows all threads from current room + +
+
+`; From c31bd8c647493ab2fc349b7abc3d80c5d1a30258 Mon Sep 17 00:00:00 2001 From: Dariusz Niemczyk <3636685+Palid@users.noreply.github.com> Date: Thu, 14 Oct 2021 16:42:54 +0200 Subject: [PATCH 136/143] Remove unnecessary adapter in ThreadPanel-test.tsx (#6946) --- test/components/structures/ThreadPanel-test.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test/components/structures/ThreadPanel-test.tsx b/test/components/structures/ThreadPanel-test.tsx index d6de2ebde6..a59e9aa6cd 100644 --- a/test/components/structures/ThreadPanel-test.tsx +++ b/test/components/structures/ThreadPanel-test.tsx @@ -15,9 +15,8 @@ limitations under the License. */ import React from 'react'; -import { shallow, mount, configure } from "enzyme"; +import { shallow, mount } from "enzyme"; import '../../skinned-sdk'; -import Adapter from "@wojtekmaj/enzyme-adapter-react-17"; import { ThreadFilterType, @@ -28,8 +27,6 @@ import { ContextMenuButton } from '../../../src/accessibility/context_menu/Conte import ContextMenu from '../../../src/components/structures/ContextMenu'; import { _t } from '../../../src/languageHandler'; -configure({ adapter: new Adapter() }); - describe('ThreadPanel', () => { describe('Header', () => { it('expect that All filter for ThreadPanelHeader properly renders Show: All threads', () => { From 2dd6dddc676d6d1dd32ef6909443b1da1e212ae2 Mon Sep 17 00:00:00 2001 From: Dariusz Niemczyk <3636685+Palid@users.noreply.github.com> Date: Thu, 14 Oct 2021 17:37:56 +0200 Subject: [PATCH 137/143] Fix incorrect liveTimeline reference (#6948) Fixes https://github.com/vector-im/element-web/issues/19400 --- src/components/views/rooms/SendMessageComposer.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/views/rooms/SendMessageComposer.tsx b/src/components/views/rooms/SendMessageComposer.tsx index 35a028aadc..1a8315be7b 100644 --- a/src/components/views/rooms/SendMessageComposer.tsx +++ b/src/components/views/rooms/SendMessageComposer.tsx @@ -143,6 +143,8 @@ interface ISendMessageComposerProps extends MatrixClientProps { @replaceableComponent("views.rooms.SendMessageComposer") export class SendMessageComposer extends React.Component { static contextType = RoomContext; + public context!: React.ContextType; + private readonly prepareToEncrypt?: DebouncedFunc<() => void>; private readonly editorRef = createRef(); private model: EditorModel = null; @@ -279,7 +281,7 @@ export class SendMessageComposer extends React.Component= 0; i--) { From d3156410564afc8b4469ee2c1af388dc234b2619 Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Thu, 14 Oct 2021 16:57:02 +0100 Subject: [PATCH 138/143] Make threads use 'm.thread' relation --- src/components/structures/MessagePanel.tsx | 6 +-- src/components/structures/ThreadPanel.tsx | 6 +-- src/components/structures/ThreadView.tsx | 7 ++- src/components/views/elements/ReplyThread.tsx | 18 +------- .../views/rooms/EditMessageComposer.tsx | 15 ++----- .../views/rooms/MessageComposer.tsx | 13 +++--- .../views/rooms/SendMessageComposer.tsx | 45 ++++++++++++------- 7 files changed, 52 insertions(+), 58 deletions(-) diff --git a/src/components/structures/MessagePanel.tsx b/src/components/structures/MessagePanel.tsx index 79c010cb8f..c1d22ecedf 100644 --- a/src/components/structures/MessagePanel.tsx +++ b/src/components/structures/MessagePanel.tsx @@ -271,9 +271,6 @@ export default class MessagePanel extends React.Component { componentDidMount() { this.calculateRoomMembersCount(); this.props.room?.on("RoomState.members", this.calculateRoomMembersCount); - if (SettingsStore.getValue("feature_thread")) { - this.props.room?.getThreads().forEach(thread => thread.fetchReplyChain()); - } this.isMounted = true; } @@ -463,8 +460,7 @@ export default class MessagePanel extends React.Component { // Checking if the message has a "parentEventId" as we do not // want to hide the root event of the thread - if (mxEv.replyInThread && mxEv.parentEventId - && this.props.hideThreadedMessages + if (mxEv.isThreadRoot && this.props.hideThreadedMessages && SettingsStore.getValue("feature_thread")) { return false; } diff --git a/src/components/structures/ThreadPanel.tsx b/src/components/structures/ThreadPanel.tsx index fbb5547641..40e9479251 100644 --- a/src/components/structures/ThreadPanel.tsx +++ b/src/components/structures/ThreadPanel.tsx @@ -71,7 +71,7 @@ const useFilteredThreadsTimelinePanel = ({ userId, updateTimeline, }: { - threads: Set; + threads: Map; room: Room; userId: string; filterOption: ThreadFilterType; @@ -85,13 +85,13 @@ const useFilteredThreadsTimelinePanel = ({ useEffect(() => { let filteredThreads = Array.from(threads); if (filterOption === ThreadFilterType.My) { - filteredThreads = filteredThreads.filter(thread => { + filteredThreads = filteredThreads.filter(([id, thread]) => { return thread.rootEvent.getSender() === userId; }); } // NOTE: Temporarily reverse the list until https://github.com/vector-im/element-web/issues/19393 gets properly resolved // The proper list order should be top-to-bottom, like in social-media newsfeeds. - filteredThreads.reverse().forEach(thread => { + filteredThreads.reverse().forEach(([id, thread]) => { const event = thread.rootEvent; if (timelineSet.findEventById(event.getId()) || event.status !== null) return; timelineSet.addEventToTimeline( diff --git a/src/components/structures/ThreadView.tsx b/src/components/structures/ThreadView.tsx index d444ed5d50..3462212834 100644 --- a/src/components/structures/ThreadView.tsx +++ b/src/components/structures/ThreadView.tsx @@ -17,6 +17,7 @@ limitations under the License. import React from 'react'; import { MatrixEvent, Room } from 'matrix-js-sdk/src'; import { Thread, ThreadEvent } from 'matrix-js-sdk/src/models/thread'; +import { RelationType } from 'matrix-js-sdk/src/@types/event'; import BaseCard from "../views/right_panel/BaseCard"; import { RightPanelPhases } from "../../stores/RightPanelStorePhases"; @@ -185,8 +186,10 @@ export default class ThreadView extends React.Component { { this.state?.thread?.timelineSet && ( { return { body, html }; } - public static makeReplyMixIn(ev: MatrixEvent, replyInThread: boolean) { + public static makeReplyMixIn(ev: MatrixEvent) { if (!ev) return {}; - - const replyMixin = { + return { 'm.relates_to': { 'm.in_reply_to': { 'event_id': ev.getId(), }, }, }; - - /** - * @experimental - * Rendering hint for threads, only attached if true to make - * sure that Element does not start sending that property for all events - */ - if (replyInThread) { - const inReplyTo = replyMixin['m.relates_to']['m.in_reply_to']; - inReplyTo[UNSTABLE_ELEMENT_REPLY_IN_THREAD.name] = replyInThread; - } - - return replyMixin; } public static hasThreadReply(event: MatrixEvent) { diff --git a/src/components/views/rooms/EditMessageComposer.tsx b/src/components/views/rooms/EditMessageComposer.tsx index ce42131b6d..538de9afbf 100644 --- a/src/components/views/rooms/EditMessageComposer.tsx +++ b/src/components/views/rooms/EditMessageComposer.tsx @@ -35,7 +35,7 @@ import { getKeyBindingsManager, MessageComposerAction } from '../../../KeyBindin import { replaceableComponent } from "../../../utils/replaceableComponent"; import SendHistoryManager from '../../../SendHistoryManager'; import Modal from '../../../Modal'; -import { MsgType, UNSTABLE_ELEMENT_REPLY_IN_THREAD } from 'matrix-js-sdk/src/@types/event'; +import { MsgType } from 'matrix-js-sdk/src/@types/event'; import { Room } from 'matrix-js-sdk/src/models/room'; import ErrorDialog from "../dialogs/ErrorDialog"; import QuestionDialog from "../dialogs/QuestionDialog"; @@ -46,7 +46,7 @@ import SettingsStore from "../../../settings/SettingsStore"; import { logger } from "matrix-js-sdk/src/logger"; import { withMatrixClientHOC, MatrixClientProps } from '../../../contexts/MatrixClientContext'; -import RoomContext, { TimelineRenderingType } from '../../../contexts/RoomContext'; +import RoomContext from '../../../contexts/RoomContext'; function getHtmlReplyFallback(mxEvent: MatrixEvent): string { const html = mxEvent.getContent().formatted_body; @@ -70,7 +70,6 @@ function getTextReplyFallback(mxEvent: MatrixEvent): string { function createEditContent( model: EditorModel, editedEvent: MatrixEvent, - renderingContext?: TimelineRenderingType, ): IContent { const isEmote = containsEmote(model); if (isEmote) { @@ -112,10 +111,6 @@ function createEditContent( }, }; - if (renderingContext === TimelineRenderingType.Thread) { - relation['m.relates_to'][UNSTABLE_ELEMENT_REPLY_IN_THREAD.name] = true; - } - return Object.assign(relation, contentBody); } @@ -143,8 +138,7 @@ class EditMessageComposer extends React.Component { private instanceId: number; static defaultProps = { - replyInThread: false, showReplyPreview: true, compact: false, }; @@ -378,9 +378,10 @@ export default class MessageComposer extends React.Component { private renderPlaceholderText = () => { if (this.props.replyToEvent) { - if (this.props.replyInThread && this.props.e2eStatus) { + const replyingToThread = this.props.relation?.rel_type === RelationType.Thread; + if (replyingToThread && this.props.e2eStatus) { return _t('Reply to encrypted thread…'); - } else if (this.props.replyInThread) { + } else if (replyingToThread) { return _t('Reply to thread…'); } else if (this.props.e2eStatus) { return _t('Send an encrypted reply…'); @@ -558,7 +559,7 @@ export default class MessageComposer extends React.Component { room={this.props.room} placeholder={this.renderPlaceholderText()} permalinkCreator={this.props.permalinkCreator} - replyInThread={this.props.replyInThread} + relation={this.props.relation} replyToEvent={this.props.replyToEvent} onChange={this.onChange} disabled={this.state.haveRecording} diff --git a/src/components/views/rooms/SendMessageComposer.tsx b/src/components/views/rooms/SendMessageComposer.tsx index 35a028aadc..79411e6ebc 100644 --- a/src/components/views/rooms/SendMessageComposer.tsx +++ b/src/components/views/rooms/SendMessageComposer.tsx @@ -16,7 +16,7 @@ limitations under the License. import React, { ClipboardEvent, createRef, KeyboardEvent } from 'react'; import EMOJI_REGEX from 'emojibase-regex'; -import { IContent, MatrixEvent } from 'matrix-js-sdk/src/models/event'; +import { IContent, MatrixEvent, IEventRelation } from 'matrix-js-sdk/src/models/event'; import { DebouncedFunc, throttle } from 'lodash'; import { EventType, RelationType } from "matrix-js-sdk/src/@types/event"; import { logger } from "matrix-js-sdk/src/logger"; @@ -61,10 +61,10 @@ import RoomContext from '../../../contexts/RoomContext'; function addReplyToMessageContent( content: IContent, replyToEvent: MatrixEvent, - replyInThread: boolean, permalinkCreator: RoomPermalinkCreator, + relation?: IEventRelation, ): void { - const replyContent = ReplyThread.makeReplyMixIn(replyToEvent, replyInThread); + const replyContent = ReplyThread.makeReplyMixIn(replyToEvent); Object.assign(content, replyContent); // Part of Replies fallback support - prepend the text we're sending @@ -76,13 +76,20 @@ function addReplyToMessageContent( } content.body = nestedReply.body + content.body; } + + if (relation) { + content['m.relates_to'] = { + ...relation, // the composer can have a default + ...content['m.relates_to'], + }; + } } // exported for tests export function createMessageContent( model: EditorModel, replyToEvent: MatrixEvent, - replyInThread: boolean, + relation: IEventRelation, permalinkCreator: RoomPermalinkCreator, ): IContent { const isEmote = containsEmote(model); @@ -106,7 +113,14 @@ export function createMessageContent( } if (replyToEvent) { - addReplyToMessageContent(content, replyToEvent, replyInThread, permalinkCreator); + addReplyToMessageContent(content, replyToEvent, permalinkCreator); + } + + if (relation) { + content['m.relates_to'] = { + ...relation, + ...content['m.relates_to'], + }; } return content; @@ -134,7 +148,7 @@ interface ISendMessageComposerProps extends MatrixClientProps { room: Room; placeholder?: string; permalinkCreator: RoomPermalinkCreator; - replyInThread?: boolean; + relation?: IEventRelation; replyToEvent?: MatrixEvent; disabled?: boolean; onChange?(model: EditorModel): void; @@ -162,12 +176,11 @@ export class SendMessageComposer extends React.Component Date: Thu, 14 Oct 2021 17:22:06 +0100 Subject: [PATCH 139/143] Add 'm.thread' relation for replies to a threaded event --- src/components/views/elements/ReplyThread.tsx | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/components/views/elements/ReplyThread.tsx b/src/components/views/elements/ReplyThread.tsx index 7dd81f469a..3243d5ee03 100644 --- a/src/components/views/elements/ReplyThread.tsx +++ b/src/components/views/elements/ReplyThread.tsx @@ -35,6 +35,8 @@ import Spinner from './Spinner'; import ReplyTile from "../rooms/ReplyTile"; import Pill from './Pill'; import { Room } from 'matrix-js-sdk/src/models/room'; +import { threadId } from 'worker_threads'; +import { RelationType } from 'matrix-js-sdk/src/@types/event'; /** * This number is based on the previous behavior - if we have message of height @@ -226,13 +228,30 @@ export default class ReplyThread extends React.Component { public static makeReplyMixIn(ev: MatrixEvent) { if (!ev) return {}; - return { + + const mixin: any = { 'm.relates_to': { 'm.in_reply_to': { 'event_id': ev.getId(), }, }, }; + + /** + * If the event replied is part of a thread + * Add the `m.thread` relation so that clients + * that know how to handle that relation will + * be able to render them more accurately + */ + if (ev.isThreadRelation) { + mixin['m.relates_to'] = { + ...mixin['m.relates_to'], + rel_type: RelationType.Thread, + event_id: ev.threadRootId, + }; + } + + return mixin; } public static hasThreadReply(event: MatrixEvent) { From 5fccbd4ef72b84c9db0c6a90d6f0e69641103baf Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Thu, 14 Oct 2021 17:40:00 +0100 Subject: [PATCH 140/143] Remove auto-import --- src/components/views/elements/ReplyThread.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/views/elements/ReplyThread.tsx b/src/components/views/elements/ReplyThread.tsx index 3243d5ee03..e0cca0c81e 100644 --- a/src/components/views/elements/ReplyThread.tsx +++ b/src/components/views/elements/ReplyThread.tsx @@ -35,7 +35,6 @@ import Spinner from './Spinner'; import ReplyTile from "../rooms/ReplyTile"; import Pill from './Pill'; import { Room } from 'matrix-js-sdk/src/models/room'; -import { threadId } from 'worker_threads'; import { RelationType } from 'matrix-js-sdk/src/@types/event'; /** From 8cdb1c667df0d42901ecb5bb9079af8403cb089e Mon Sep 17 00:00:00 2001 From: Aaron Raimist Date: Fri, 15 Oct 2021 05:23:59 -0500 Subject: [PATCH 141/143] Fix tooltip when downloading unencrypted file --- src/components/views/messages/DownloadActionButton.tsx | 10 ++++++++-- src/i18n/strings/en_EN.json | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/components/views/messages/DownloadActionButton.tsx b/src/components/views/messages/DownloadActionButton.tsx index 6dc48b0936..35fd5c49be 100644 --- a/src/components/views/messages/DownloadActionButton.tsx +++ b/src/components/views/messages/DownloadActionButton.tsx @@ -20,7 +20,7 @@ import React from "react"; import { RovingAccessibleTooltipButton } from "../../../accessibility/RovingTabIndex"; import Spinner from "../elements/Spinner"; import classNames from "classnames"; -import { _t } from "../../../languageHandler"; +import { _t, _td } from "../../../languageHandler"; import { replaceableComponent } from "../../../utils/replaceableComponent"; import { FileDownloader } from "../../../utils/FileDownloader"; @@ -36,6 +36,7 @@ interface IProps { interface IState { loading: boolean; blob?: Blob; + tooltip: string; } @replaceableComponent("views.messages.DownloadActionButton") @@ -47,12 +48,17 @@ export default class DownloadActionButton extends React.PureComponent { if (this.state.loading) return; + if (this.props.mediaEventHelperGet().media.isEncrypted) { + this.setState({ tooltip: _td("Decrypting") }); + } + this.setState({ loading: true }); if (this.state.blob) { @@ -87,7 +93,7 @@ export default class DownloadActionButton extends React.PureComponent diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 3e61146acb..a46d48b655 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1959,6 +1959,7 @@ "Saturday": "Saturday", "Today": "Today", "Yesterday": "Yesterday", + "Downloading": "Downloading", "Decrypting": "Decrypting", "Download": "Download", "View Source": "View Source", From 7edec291acacd687f7a335ee26e5a42b67ba4c43 Mon Sep 17 00:00:00 2001 From: Andy Balaam Date: Fri, 15 Oct 2021 11:49:27 +0100 Subject: [PATCH 142/143] Switch DevicesPanel to use table (for screen readers) --- res/css/views/settings/_DevicesPanel.scss | 18 +++++-------- .../views/settings/DevicesPanel.tsx | 26 +++++++++++-------- .../views/settings/DevicesPanelEntry.tsx | 20 +++++++------- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/res/css/views/settings/_DevicesPanel.scss b/res/css/views/settings/_DevicesPanel.scss index 7e836e0d87..1354f6d051 100644 --- a/res/css/views/settings/_DevicesPanel.scss +++ b/res/css/views/settings/_DevicesPanel.scss @@ -15,7 +15,6 @@ limitations under the License. */ .mx_DevicesPanel { - display: table; table-layout: fixed; // Normally the panel is 880px, however this can easily overflow the container. // TODO: Fix the table to not be squishy @@ -25,16 +24,16 @@ limitations under the License. } .mx_DevicesPanel_header { - display: table-header-group; font-weight: bold; } -.mx_DevicesPanel_header > .mx_DevicesPanel_deviceButtons { +.mx_DevicesPanel_header .mx_DevicesPanel_deviceButtons { height: 48px; // make this tall so the table doesn't move down when the delete button appears } -.mx_DevicesPanel_header > div { - display: table-cell; +.mx_DevicesPanel_header th { + padding: 0px; + text-align: left; vertical-align: middle; } @@ -50,12 +49,9 @@ limitations under the License. width: 20%; } -.mx_DevicesPanel_device { - display: table-row; -} - -.mx_DevicesPanel_device > div { - display: table-cell; +.mx_DevicesPanel_device td { + vertical-align: baseline; + padding: 0px; } .mx_DevicesPanel_myDevice { diff --git a/src/components/views/settings/DevicesPanel.tsx b/src/components/views/settings/DevicesPanel.tsx index 9a1321619e..d66d0f42eb 100644 --- a/src/components/views/settings/DevicesPanel.tsx +++ b/src/components/views/settings/DevicesPanel.tsx @@ -218,17 +218,21 @@ export default class DevicesPanel extends React.Component { const classes = classNames(this.props.className, "mx_DevicesPanel"); return ( -
-
-
{ _t("ID") }
-
{ _t("Public Name") }
-
{ _t("Last seen") }
-
- { this.state.selectedDevices.length > 0 ? deleteButton : null } -
-
- { devices.map(this.renderDevice) } -
+ + + + + + + + + + + { devices.map(this.renderDevice) } + +
{ _t("ID") }{ _t("Public Name") }{ _t("Last seen") } + { this.state.selectedDevices.length > 0 ? deleteButton : null } +
); } } diff --git a/src/components/views/settings/DevicesPanelEntry.tsx b/src/components/views/settings/DevicesPanelEntry.tsx index d033bc41a9..1131114556 100644 --- a/src/components/views/settings/DevicesPanelEntry.tsx +++ b/src/components/views/settings/DevicesPanelEntry.tsx @@ -66,23 +66,23 @@ export default class DevicesPanelEntry extends React.Component { } return ( -
-
+ + { device.device_id } -
-
+ + -
-
+ + { lastSeen } -
-
+ + -
-
+ + ); } } From 690893ea6b5c2d0d7f51a2b7d578f1a7371cac90 Mon Sep 17 00:00:00 2001 From: Andy Balaam Date: Fri, 15 Oct 2021 13:32:39 +0100 Subject: [PATCH 143/143] Merge duplicate CSS selectors --- res/css/views/settings/_DevicesPanel.scss | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/res/css/views/settings/_DevicesPanel.scss b/res/css/views/settings/_DevicesPanel.scss index 1354f6d051..7d6db7bc96 100644 --- a/res/css/views/settings/_DevicesPanel.scss +++ b/res/css/views/settings/_DevicesPanel.scss @@ -29,6 +29,7 @@ limitations under the License. .mx_DevicesPanel_header .mx_DevicesPanel_deviceButtons { height: 48px; // make this tall so the table doesn't move down when the delete button appears + width: 20%; } .mx_DevicesPanel_header th { @@ -45,10 +46,6 @@ limitations under the License. width: 30%; } -.mx_DevicesPanel_header .mx_DevicesPanel_deviceButtons { - width: 20%; -} - .mx_DevicesPanel_device td { vertical-align: baseline; padding: 0px;