From 3911666c52fb1e731d0bc298f9c26b80df3ff8b3 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Wed, 21 Jul 2021 02:13:30 -0400 Subject: [PATCH 01/32] Zoom images to where the cursor points Signed-off-by: Robin Townsend --- src/components/views/elements/ImageView.tsx | 83 +++++++++++++++------ 1 file changed, 60 insertions(+), 23 deletions(-) diff --git a/src/components/views/elements/ImageView.tsx b/src/components/views/elements/ImageView.tsx index 954c1ab783..215c92671b 100644 --- a/src/components/views/elements/ImageView.tsx +++ b/src/components/views/elements/ImageView.tsx @@ -160,41 +160,82 @@ export default class ImageView extends React.Component { }); }; - private zoom(delta: number) { - const newZoom = this.state.zoom + delta; + private zoomDelta(delta: number, zoomX?: number, zoomY?: number) { + this.zoom(this.state.zoom + delta, zoomX, zoomY); + } + + private zoom(zoomLevel: number, zoomX?: number, zoomY?: number) { + const oldZoom = this.state.zoom; + const newZoom = Math.min(zoomLevel, this.state.maxZoom); if (newZoom <= this.state.minZoom) { + // Zoom out fully this.setState({ zoom: this.state.minZoom, translationX: 0, translationY: 0, }); - return; - } - if (newZoom >= this.state.maxZoom) { - this.setState({ zoom: this.state.maxZoom }); - return; - } + } else if (zoomX === undefined && zoomY === undefined) { + // Zoom relative to the center of the view + this.setState({ + zoom: newZoom, + translationX: this.state.translationX * newZoom / oldZoom, + translationY: this.state.translationY * newZoom / oldZoom, + }); + } else { + // Zoom relative to the given point on the image. + // First we need to figure out the offset of the anchor point + // relative to the center of the image, accounting for rotation. + let offsetX; + let offsetY; + switch (((this.state.rotation % 360) + 360) % 360) { + case 0: + offsetX = this.image.current.clientWidth / 2 - zoomX; + offsetY = this.image.current.clientHeight / 2 - zoomY; + break; + case 90: + offsetX = zoomY - this.image.current.clientHeight / 2; + offsetY = this.image.current.clientWidth / 2 - zoomX; + break; + case 180: + offsetX = zoomX - this.image.current.clientWidth / 2; + offsetY = zoomY - this.image.current.clientHeight / 2; + break; + case 270: + offsetX = this.image.current.clientHeight / 2 - zoomY; + offsetY = zoomX - this.image.current.clientWidth / 2; + } - this.setState({ - zoom: newZoom, - }); + // Apply the zoom and offset + this.setState({ + zoom: newZoom, + translationX: this.state.translationX + (newZoom - oldZoom) * offsetX, + translationY: this.state.translationY + (newZoom - oldZoom) * offsetY, + }); + } } private onWheel = (ev: WheelEvent) => { ev.stopPropagation(); ev.preventDefault(); - const { deltaY } = normalizeWheelEvent(ev); - this.zoom(-(deltaY * ZOOM_COEFFICIENT)); + + if (ev.target === this.image.current) { + // Zoom in on the point on the image targeted by the cursor + this.zoomDelta(-deltaY * ZOOM_COEFFICIENT, ev.offsetX, ev.offsetY); + } else { + // The user is scrolling outside of the image, so we can't really + // get a targeted point. Instead, we'll just zoom in on the center. + this.zoomDelta(-deltaY * ZOOM_COEFFICIENT); + } }; - private onZoomInClick = () => { - this.zoom(ZOOM_STEP); + private onZoomInClick = (ev: MouseEvent) => { + this.zoomDelta(ZOOM_STEP); }; - private onZoomOutClick = () => { - this.zoom(-ZOOM_STEP); + private onZoomOutClick = (ev: MouseEvent) => { + this.zoomDelta(-ZOOM_STEP); }; private onKeyDown = (ev: KeyboardEvent) => { @@ -259,7 +300,7 @@ export default class ImageView extends React.Component { // Zoom in if we are completely zoomed out if (this.state.zoom === this.state.minZoom) { - this.setState({ zoom: this.state.maxZoom }); + this.zoom(this.state.maxZoom, ev.nativeEvent.offsetX, ev.nativeEvent.offsetY); return; } @@ -289,11 +330,7 @@ export default class ImageView extends React.Component { Math.abs(this.state.translationX - this.previousX) < ZOOM_DISTANCE && Math.abs(this.state.translationY - this.previousY) < ZOOM_DISTANCE ) { - this.setState({ - zoom: this.state.minZoom, - translationX: 0, - translationY: 0, - }); + this.zoom(this.state.minZoom); this.initX = 0; this.initY = 0; } From 0497e0864f74beddb5f432bea2e6a4691a44af18 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Wed, 21 Jul 2021 02:42:30 -0400 Subject: [PATCH 02/32] Fix types Signed-off-by: Robin Townsend --- src/components/views/elements/ImageView.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/elements/ImageView.tsx b/src/components/views/elements/ImageView.tsx index 215c92671b..40003f734c 100644 --- a/src/components/views/elements/ImageView.tsx +++ b/src/components/views/elements/ImageView.tsx @@ -230,11 +230,11 @@ export default class ImageView extends React.Component { } }; - private onZoomInClick = (ev: MouseEvent) => { + private onZoomInClick = () => { this.zoomDelta(ZOOM_STEP); }; - private onZoomOutClick = (ev: MouseEvent) => { + private onZoomOutClick = () => { this.zoomDelta(-ZOOM_STEP); }; From 8da2d0fe72103b0b3301c9f5e09c9f2c819e237d Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Thu, 22 Jul 2021 11:31:46 +0200 Subject: [PATCH 03/32] Fix avatar obstructing membership and state changes --- res/css/views/rooms/_EventTile.scss | 3 ++- res/css/views/rooms/_GroupLayout.scss | 1 + src/components/views/rooms/EventTile.tsx | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/res/css/views/rooms/_EventTile.scss b/res/css/views/rooms/_EventTile.scss index ab4fb28791..af3f480999 100644 --- a/res/css/views/rooms/_EventTile.scss +++ b/res/css/views/rooms/_EventTile.scss @@ -132,7 +132,8 @@ $hover-select-border: 4px; } } - &.mx_EventTile_info .mx_EventTile_line { + &.mx_EventTile_info .mx_EventTile_line, + & ~ .mx_EventListSummary .mx_EventTile_avatar ~ .mx_EventTile_line { padding-left: calc($left-gutter + 18px); } diff --git a/res/css/views/rooms/_GroupLayout.scss b/res/css/views/rooms/_GroupLayout.scss index ddee81a914..ebb7f99e45 100644 --- a/res/css/views/rooms/_GroupLayout.scss +++ b/res/css/views/rooms/_GroupLayout.scss @@ -26,6 +26,7 @@ $left-gutter: 64px; > .mx_EventTile_avatar { position: absolute; + z-index: 9; } .mx_MessageTimestamp { diff --git a/src/components/views/rooms/EventTile.tsx b/src/components/views/rooms/EventTile.tsx index 6861ea7af5..c6c605a8c2 100644 --- a/src/components/views/rooms/EventTile.tsx +++ b/src/components/views/rooms/EventTile.tsx @@ -1142,6 +1142,7 @@ export default class EventTile extends React.Component { { ircTimestamp } { sender } { ircPadlock } + { avatar }
{ groupTimestamp } { groupPadlock } @@ -1162,7 +1163,6 @@ export default class EventTile extends React.Component {
{ reactionsRow } { msgOption } - { avatar } ) ); } From 552770c15a131a900df342d136270f811185191e Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Thu, 22 Jul 2021 14:24:49 +0200 Subject: [PATCH 04/32] Remove excessive padding after url previews --- src/components/views/messages/TextualBody.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/views/messages/TextualBody.tsx b/src/components/views/messages/TextualBody.tsx index 666fc1cbe0..969caccaee 100644 --- a/src/components/views/messages/TextualBody.tsx +++ b/src/components/views/messages/TextualBody.tsx @@ -514,7 +514,7 @@ export default class TextualBody extends React.Component { switch (content.msgtype) { case MsgType.Emote: return ( - +
{   { body } { widgets } - +
); case MsgType.Notice: return ( - +
{ body } { widgets } - +
); default: // including "m.text" return ( - +
{ body } { widgets } - +
); } } From 2e173d78105e3f6966fd295c0d26bfe0882572ae Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Thu, 22 Jul 2021 14:38:57 +0200 Subject: [PATCH 05/32] Add right padding for event replies --- res/css/views/elements/_ReplyThread.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/css/views/elements/_ReplyThread.scss b/res/css/views/elements/_ReplyThread.scss index bc77407041..032cb49359 100644 --- a/res/css/views/elements/_ReplyThread.scss +++ b/res/css/views/elements/_ReplyThread.scss @@ -19,7 +19,7 @@ limitations under the License. margin-left: 0; margin-right: 0; margin-bottom: 8px; - padding-left: 10px; + padding: 0 10px; border-left: 2px solid $button-bg-color; border-radius: 2px; From 8a9d89ae85a63f247783430e2830cfcfd0719b2e Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Thu, 22 Jul 2021 15:05:44 +0200 Subject: [PATCH 06/32] Fix event tile cut off in share preview --- res/css/views/dialogs/_ForwardDialog.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/res/css/views/dialogs/_ForwardDialog.scss b/res/css/views/dialogs/_ForwardDialog.scss index 95d7ce74c4..e018f60172 100644 --- a/res/css/views/dialogs/_ForwardDialog.scss +++ b/res/css/views/dialogs/_ForwardDialog.scss @@ -36,6 +36,10 @@ limitations under the License. flex-shrink: 0; overflow-y: auto; + .mx_EventTile[data-layout=bubble] { + margin-top: 20px; + } + div { pointer-events: none; } From 229d139568dafb069127cf883ced954ef9a176c9 Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Thu, 22 Jul 2021 15:22:18 +0200 Subject: [PATCH 07/32] Always display the Sender in the reply tile --- res/css/views/rooms/_EventBubbleTile.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/res/css/views/rooms/_EventBubbleTile.scss b/res/css/views/rooms/_EventBubbleTile.scss index 6bc75e650e..cac463d4db 100644 --- a/res/css/views/rooms/_EventBubbleTile.scss +++ b/res/css/views/rooms/_EventBubbleTile.scss @@ -97,6 +97,11 @@ limitations under the License. .mx_SenderProfile { display: none; } + + .mx_ReplyTile .mx_SenderProfile { + display: block; + } + .mx_ReactionsRow { float: right; clear: right; From b99a6a8d5405532bb6bac11157f678db49f41ca5 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Thu, 22 Jul 2021 09:41:39 -0400 Subject: [PATCH 08/32] Use typeof to check for presence of parameters Signed-off-by: Robin Townsend --- src/components/views/elements/ImageView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/elements/ImageView.tsx b/src/components/views/elements/ImageView.tsx index 40003f734c..eff0ad4d61 100644 --- a/src/components/views/elements/ImageView.tsx +++ b/src/components/views/elements/ImageView.tsx @@ -175,7 +175,7 @@ export default class ImageView extends React.Component { translationX: 0, translationY: 0, }); - } else if (zoomX === undefined && zoomY === undefined) { + } else if (typeof zoomX !== "number" && typeof zoomY !== "number") { // Zoom relative to the center of the view this.setState({ zoom: newZoom, From 875b46bacb0719e58d5ee6537f0cdf326d973986 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Thu, 22 Jul 2021 09:46:29 -0400 Subject: [PATCH 09/32] Don't zoom images when the cursor isn't over the image Signed-off-by: Robin Townsend --- src/components/views/elements/ImageView.tsx | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/components/views/elements/ImageView.tsx b/src/components/views/elements/ImageView.tsx index eff0ad4d61..4059277ea3 100644 --- a/src/components/views/elements/ImageView.tsx +++ b/src/components/views/elements/ImageView.tsx @@ -216,17 +216,13 @@ export default class ImageView extends React.Component { } private onWheel = (ev: WheelEvent) => { - ev.stopPropagation(); - ev.preventDefault(); - const { deltaY } = normalizeWheelEvent(ev); - if (ev.target === this.image.current) { + ev.stopPropagation(); + ev.preventDefault(); + + const { deltaY } = normalizeWheelEvent(ev); // Zoom in on the point on the image targeted by the cursor this.zoomDelta(-deltaY * ZOOM_COEFFICIENT, ev.offsetX, ev.offsetY); - } else { - // The user is scrolling outside of the image, so we can't really - // get a targeted point. Instead, we'll just zoom in on the center. - this.zoomDelta(-deltaY * ZOOM_COEFFICIENT); } }; From 9e0720a6c42da82bc0a24d17b097361a4bf9fd6d Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Thu, 22 Jul 2021 09:48:56 -0400 Subject: [PATCH 10/32] Rename zoom anchor variables for clarity Signed-off-by: Robin Townsend --- src/components/views/elements/ImageView.tsx | 24 ++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/components/views/elements/ImageView.tsx b/src/components/views/elements/ImageView.tsx index 4059277ea3..1979da5295 100644 --- a/src/components/views/elements/ImageView.tsx +++ b/src/components/views/elements/ImageView.tsx @@ -160,11 +160,11 @@ export default class ImageView extends React.Component { }); }; - private zoomDelta(delta: number, zoomX?: number, zoomY?: number) { - this.zoom(this.state.zoom + delta, zoomX, zoomY); + private zoomDelta(delta: number, anchorX?: number, anchorY?: number) { + this.zoom(this.state.zoom + delta, anchorX, anchorY); } - private zoom(zoomLevel: number, zoomX?: number, zoomY?: number) { + private zoom(zoomLevel: number, anchorX?: number, anchorY?: number) { const oldZoom = this.state.zoom; const newZoom = Math.min(zoomLevel, this.state.maxZoom); @@ -175,7 +175,7 @@ export default class ImageView extends React.Component { translationX: 0, translationY: 0, }); - } else if (typeof zoomX !== "number" && typeof zoomY !== "number") { + } else if (typeof anchorX !== "number" && typeof anchorY !== "number") { // Zoom relative to the center of the view this.setState({ zoom: newZoom, @@ -190,20 +190,20 @@ export default class ImageView extends React.Component { let offsetY; switch (((this.state.rotation % 360) + 360) % 360) { case 0: - offsetX = this.image.current.clientWidth / 2 - zoomX; - offsetY = this.image.current.clientHeight / 2 - zoomY; + offsetX = this.image.current.clientWidth / 2 - anchorX; + offsetY = this.image.current.clientHeight / 2 - anchorY; break; case 90: - offsetX = zoomY - this.image.current.clientHeight / 2; - offsetY = this.image.current.clientWidth / 2 - zoomX; + offsetX = anchorY - this.image.current.clientHeight / 2; + offsetY = this.image.current.clientWidth / 2 - anchorX; break; case 180: - offsetX = zoomX - this.image.current.clientWidth / 2; - offsetY = zoomY - this.image.current.clientHeight / 2; + offsetX = anchorX - this.image.current.clientWidth / 2; + offsetY = anchorY - this.image.current.clientHeight / 2; break; case 270: - offsetX = this.image.current.clientHeight / 2 - zoomY; - offsetY = zoomX - this.image.current.clientWidth / 2; + offsetX = this.image.current.clientHeight / 2 - anchorY; + offsetY = anchorX - this.image.current.clientWidth / 2; } // Apply the zoom and offset From 5d4b293e0a189efd19dc755c5aad8e3d20452dba Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Thu, 22 Jul 2021 09:56:26 -0400 Subject: [PATCH 11/32] Add comment about modulo operator Signed-off-by: Robin Townsend --- src/components/views/elements/ImageView.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/views/elements/ImageView.tsx b/src/components/views/elements/ImageView.tsx index 1979da5295..db63dbbfc2 100644 --- a/src/components/views/elements/ImageView.tsx +++ b/src/components/views/elements/ImageView.tsx @@ -188,6 +188,8 @@ export default class ImageView extends React.Component { // relative to the center of the image, accounting for rotation. let offsetX; let offsetY; + // The modulo operator can return negative values for some + // rotations, so we have to do some extra work to normalize it switch (((this.state.rotation % 360) + 360) % 360) { case 0: offsetX = this.image.current.clientWidth / 2 - anchorX; From 02b08888b52766dbd321cf3c2d2c715bea9f6ec5 Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Thu, 22 Jul 2021 16:00:41 +0200 Subject: [PATCH 12/32] Use modern layout in file and notification panel --- res/css/structures/_FilePanel.scss | 9 +++++++-- res/css/structures/_NotificationPanel.scss | 4 ++-- src/components/structures/FilePanel.tsx | 2 ++ src/components/structures/NotificationPanel.tsx | 2 ++ 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/res/css/structures/_FilePanel.scss b/res/css/structures/_FilePanel.scss index 1a02c0d5ac..c180a8a02d 100644 --- a/res/css/structures/_FilePanel.scss +++ b/res/css/structures/_FilePanel.scss @@ -45,9 +45,14 @@ limitations under the License. /* Overrides for the attachment body tiles */ -.mx_FilePanel .mx_EventTile { +.mx_FilePanel .mx_EventTile:not([data-layout=bubble]) { word-break: break-word; - margin-top: 32px; + margin-top: 10px; + padding-top: 0; + + .mx_EventTile_line { + padding-left: 0; + } } .mx_FilePanel .mx_EventTile .mx_MImageBody { diff --git a/res/css/structures/_NotificationPanel.scss b/res/css/structures/_NotificationPanel.scss index e54feca175..d271cd2bcc 100644 --- a/res/css/structures/_NotificationPanel.scss +++ b/res/css/structures/_NotificationPanel.scss @@ -84,7 +84,7 @@ limitations under the License. display: inline; } -.mx_NotificationPanel .mx_EventTile_senderDetails { +.mx_NotificationPanel .mx_EventTile:not([data-layout=bubble]) .mx_EventTile_senderDetails { padding-left: 36px; // align with the room name position: relative; @@ -105,7 +105,7 @@ limitations under the License. padding-left: 5px; } -.mx_NotificationPanel .mx_EventTile_line { +.mx_NotificationPanel .mx_EventTile:not([data-layout=bubble]) .mx_EventTile_line { margin-right: 0px; padding-left: 36px; // align with the room name padding-top: 0px; diff --git a/src/components/structures/FilePanel.tsx b/src/components/structures/FilePanel.tsx index c6d72d04bb..52cf5ae55b 100644 --- a/src/components/structures/FilePanel.tsx +++ b/src/components/structures/FilePanel.tsx @@ -36,6 +36,7 @@ import ResizeNotifier from '../../utils/ResizeNotifier'; import TimelinePanel from "./TimelinePanel"; import Spinner from "../views/elements/Spinner"; import { TileShape } from '../views/rooms/EventTile'; +import { Layout } from "../../settings/Layout"; interface IProps { roomId: string; @@ -267,6 +268,7 @@ class FilePanel extends React.Component { tileShape={TileShape.FileGrid} resizeNotifier={this.props.resizeNotifier} empty={emptyState} + layout={Layout.Group} /> ); diff --git a/src/components/structures/NotificationPanel.tsx b/src/components/structures/NotificationPanel.tsx index 8abc161bab..f71c017c06 100644 --- a/src/components/structures/NotificationPanel.tsx +++ b/src/components/structures/NotificationPanel.tsx @@ -23,6 +23,7 @@ import { replaceableComponent } from "../../utils/replaceableComponent"; import TimelinePanel from "./TimelinePanel"; import Spinner from "../views/elements/Spinner"; import { TileShape } from "../views/rooms/EventTile"; +import { Layout } from "../../settings/Layout"; interface IProps { onClose(): void; @@ -52,6 +53,7 @@ export default class NotificationPanel extends React.PureComponent { tileShape={TileShape.Notif} empty={emptyState} alwaysShowTimestamps={true} + layout={Layout.Group} /> ); } else { From 472ead41fbf31cc4248a8643f8bff6214a3534a5 Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Thu, 22 Jul 2021 16:05:09 +0200 Subject: [PATCH 13/32] Make images fit inside message bubble --- src/components/views/messages/MImageBody.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/views/messages/MImageBody.tsx b/src/components/views/messages/MImageBody.tsx index 44c15d50e7..c24f014d84 100644 --- a/src/components/views/messages/MImageBody.tsx +++ b/src/components/views/messages/MImageBody.tsx @@ -341,7 +341,7 @@ export default class MImageBody extends React.Component { // mx_MImageBody_thumbnail resizes img to exactly container size img = ( {content.body} { { showPlaceholder &&
{ placeholder }
@@ -452,7 +452,7 @@ export class HiddenImagePlaceholder extends React.PureComponent +
{ _t("Show image") } From 224a9db3ec39e2445cc0a4273638f44b5176a12f Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Thu, 22 Jul 2021 16:48:55 +0200 Subject: [PATCH 14/32] Add event selected state for message bubbles --- res/css/views/rooms/_EventBubbleTile.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/res/css/views/rooms/_EventBubbleTile.scss b/res/css/views/rooms/_EventBubbleTile.scss index cac463d4db..a65afdf0d5 100644 --- a/res/css/views/rooms/_EventBubbleTile.scss +++ b/res/css/views/rooms/_EventBubbleTile.scss @@ -38,7 +38,8 @@ limitations under the License. padding-top: 0; } - &:hover { + &:hover, + &.mx_EventTile_selected { &::before { content: ''; position: absolute; From eec63574e6223058f470668207b399735f236a27 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 22 Jul 2021 09:26:26 -0600 Subject: [PATCH 15/32] Move src/voice to src/audio for better naming Many of these files are used by Audio and Voice messages. Fixes https://github.com/vector-im/element-web/issues/18131 --- src/{voice => audio}/ManagedPlayback.ts | 0 src/{voice => audio}/Playback.ts | 0 src/{voice => audio}/PlaybackClock.ts | 0 src/{voice => audio}/PlaybackManager.ts | 0 src/{voice => audio}/RecorderWorklet.ts | 0 src/{voice => audio}/VoiceRecording.ts | 0 src/{voice => audio}/compat.ts | 0 src/{voice => audio}/consts.ts | 0 src/components/views/audio_messages/AudioPlayer.tsx | 2 +- src/components/views/audio_messages/DurationClock.tsx | 2 +- src/components/views/audio_messages/LiveRecordingClock.tsx | 2 +- src/components/views/audio_messages/LiveRecordingWaveform.tsx | 2 +- src/components/views/audio_messages/PlayPauseButton.tsx | 2 +- src/components/views/audio_messages/PlaybackClock.tsx | 2 +- src/components/views/audio_messages/PlaybackWaveform.tsx | 2 +- src/components/views/audio_messages/RecordingPlayback.tsx | 2 +- src/components/views/audio_messages/SeekBar.tsx | 2 +- src/components/views/messages/MAudioBody.tsx | 4 ++-- src/components/views/rooms/MessageComposer.tsx | 2 +- src/components/views/rooms/VoiceRecordComposerTile.tsx | 2 +- src/stores/VoiceRecordingStore.ts | 2 +- 21 files changed, 14 insertions(+), 14 deletions(-) rename src/{voice => audio}/ManagedPlayback.ts (100%) rename src/{voice => audio}/Playback.ts (100%) rename src/{voice => audio}/PlaybackClock.ts (100%) rename src/{voice => audio}/PlaybackManager.ts (100%) rename src/{voice => audio}/RecorderWorklet.ts (100%) rename src/{voice => audio}/VoiceRecording.ts (100%) rename src/{voice => audio}/compat.ts (100%) rename src/{voice => audio}/consts.ts (100%) diff --git a/src/voice/ManagedPlayback.ts b/src/audio/ManagedPlayback.ts similarity index 100% rename from src/voice/ManagedPlayback.ts rename to src/audio/ManagedPlayback.ts diff --git a/src/voice/Playback.ts b/src/audio/Playback.ts similarity index 100% rename from src/voice/Playback.ts rename to src/audio/Playback.ts diff --git a/src/voice/PlaybackClock.ts b/src/audio/PlaybackClock.ts similarity index 100% rename from src/voice/PlaybackClock.ts rename to src/audio/PlaybackClock.ts diff --git a/src/voice/PlaybackManager.ts b/src/audio/PlaybackManager.ts similarity index 100% rename from src/voice/PlaybackManager.ts rename to src/audio/PlaybackManager.ts diff --git a/src/voice/RecorderWorklet.ts b/src/audio/RecorderWorklet.ts similarity index 100% rename from src/voice/RecorderWorklet.ts rename to src/audio/RecorderWorklet.ts diff --git a/src/voice/VoiceRecording.ts b/src/audio/VoiceRecording.ts similarity index 100% rename from src/voice/VoiceRecording.ts rename to src/audio/VoiceRecording.ts diff --git a/src/voice/compat.ts b/src/audio/compat.ts similarity index 100% rename from src/voice/compat.ts rename to src/audio/compat.ts diff --git a/src/voice/consts.ts b/src/audio/consts.ts similarity index 100% rename from src/voice/consts.ts rename to src/audio/consts.ts diff --git a/src/components/views/audio_messages/AudioPlayer.tsx b/src/components/views/audio_messages/AudioPlayer.tsx index fb9270765e..3c0e5c1143 100644 --- a/src/components/views/audio_messages/AudioPlayer.tsx +++ b/src/components/views/audio_messages/AudioPlayer.tsx @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { Playback, PlaybackState } from "../../../voice/Playback"; +import { Playback, PlaybackState } from "../../../audio/Playback"; import React, { createRef, ReactNode, RefObject } from "react"; import { UPDATE_EVENT } from "../../../stores/AsyncStore"; import PlayPauseButton from "./PlayPauseButton"; diff --git a/src/components/views/audio_messages/DurationClock.tsx b/src/components/views/audio_messages/DurationClock.tsx index 81852b5944..15bc6c98a4 100644 --- a/src/components/views/audio_messages/DurationClock.tsx +++ b/src/components/views/audio_messages/DurationClock.tsx @@ -17,7 +17,7 @@ limitations under the License. import React from "react"; import { replaceableComponent } from "../../../utils/replaceableComponent"; import Clock from "./Clock"; -import { Playback } from "../../../voice/Playback"; +import { Playback } from "../../../audio/Playback"; interface IProps { playback: Playback; diff --git a/src/components/views/audio_messages/LiveRecordingClock.tsx b/src/components/views/audio_messages/LiveRecordingClock.tsx index a9dbd3c52f..e7330efc1d 100644 --- a/src/components/views/audio_messages/LiveRecordingClock.tsx +++ b/src/components/views/audio_messages/LiveRecordingClock.tsx @@ -15,7 +15,7 @@ limitations under the License. */ import React from "react"; -import { IRecordingUpdate, VoiceRecording } from "../../../voice/VoiceRecording"; +import { IRecordingUpdate, VoiceRecording } from "../../../audio/VoiceRecording"; import { replaceableComponent } from "../../../utils/replaceableComponent"; import Clock from "./Clock"; import { MarkedExecution } from "../../../utils/MarkedExecution"; diff --git a/src/components/views/audio_messages/LiveRecordingWaveform.tsx b/src/components/views/audio_messages/LiveRecordingWaveform.tsx index b9c5f80f05..9c33889884 100644 --- a/src/components/views/audio_messages/LiveRecordingWaveform.tsx +++ b/src/components/views/audio_messages/LiveRecordingWaveform.tsx @@ -15,7 +15,7 @@ limitations under the License. */ import React from "react"; -import { IRecordingUpdate, RECORDING_PLAYBACK_SAMPLES, VoiceRecording } from "../../../voice/VoiceRecording"; +import { IRecordingUpdate, RECORDING_PLAYBACK_SAMPLES, VoiceRecording } from "../../../audio/VoiceRecording"; import { replaceableComponent } from "../../../utils/replaceableComponent"; import { arrayFastResample } from "../../../utils/arrays"; import { percentageOf } from "../../../utils/numbers"; diff --git a/src/components/views/audio_messages/PlayPauseButton.tsx b/src/components/views/audio_messages/PlayPauseButton.tsx index a4f1e770f2..de2822cc39 100644 --- a/src/components/views/audio_messages/PlayPauseButton.tsx +++ b/src/components/views/audio_messages/PlayPauseButton.tsx @@ -18,7 +18,7 @@ import React, { ReactNode } from "react"; import { replaceableComponent } from "../../../utils/replaceableComponent"; import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; import { _t } from "../../../languageHandler"; -import { Playback, PlaybackState } from "../../../voice/Playback"; +import { Playback, PlaybackState } from "../../../audio/Playback"; import classNames from "classnames"; // omitted props are handled by render function diff --git a/src/components/views/audio_messages/PlaybackClock.tsx b/src/components/views/audio_messages/PlaybackClock.tsx index 374d47c31d..affb025d86 100644 --- a/src/components/views/audio_messages/PlaybackClock.tsx +++ b/src/components/views/audio_messages/PlaybackClock.tsx @@ -17,7 +17,7 @@ limitations under the License. import React from "react"; import { replaceableComponent } from "../../../utils/replaceableComponent"; import Clock from "./Clock"; -import { Playback, PlaybackState } from "../../../voice/Playback"; +import { Playback, PlaybackState } from "../../../audio/Playback"; import { UPDATE_EVENT } from "../../../stores/AsyncStore"; interface IProps { diff --git a/src/components/views/audio_messages/PlaybackWaveform.tsx b/src/components/views/audio_messages/PlaybackWaveform.tsx index ea1b846c01..96fd3f5ae2 100644 --- a/src/components/views/audio_messages/PlaybackWaveform.tsx +++ b/src/components/views/audio_messages/PlaybackWaveform.tsx @@ -18,7 +18,7 @@ import React from "react"; import { replaceableComponent } from "../../../utils/replaceableComponent"; import { arraySeed, arrayTrimFill } from "../../../utils/arrays"; import Waveform from "./Waveform"; -import { Playback, PLAYBACK_WAVEFORM_SAMPLES } from "../../../voice/Playback"; +import { Playback, PLAYBACK_WAVEFORM_SAMPLES } from "../../../audio/Playback"; import { percentageOf } from "../../../utils/numbers"; interface IProps { diff --git a/src/components/views/audio_messages/RecordingPlayback.tsx b/src/components/views/audio_messages/RecordingPlayback.tsx index ca0ed83d84..9a45101efc 100644 --- a/src/components/views/audio_messages/RecordingPlayback.tsx +++ b/src/components/views/audio_messages/RecordingPlayback.tsx @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { Playback, PlaybackState } from "../../../voice/Playback"; +import { Playback, PlaybackState } from "../../../audio/Playback"; import React, { ReactNode } from "react"; import { UPDATE_EVENT } from "../../../stores/AsyncStore"; import PlayPauseButton from "./PlayPauseButton"; diff --git a/src/components/views/audio_messages/SeekBar.tsx b/src/components/views/audio_messages/SeekBar.tsx index 5231a2fb79..f0c03bb032 100644 --- a/src/components/views/audio_messages/SeekBar.tsx +++ b/src/components/views/audio_messages/SeekBar.tsx @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { Playback, PlaybackState } from "../../../voice/Playback"; +import { Playback, PlaybackState } from "../../../audio/Playback"; import React, { ChangeEvent, CSSProperties, ReactNode } from "react"; import { replaceableComponent } from "../../../utils/replaceableComponent"; import { MarkedExecution } from "../../../utils/MarkedExecution"; diff --git a/src/components/views/messages/MAudioBody.tsx b/src/components/views/messages/MAudioBody.tsx index 1f0b0f25f4..823198f44d 100644 --- a/src/components/views/messages/MAudioBody.tsx +++ b/src/components/views/messages/MAudioBody.tsx @@ -16,14 +16,14 @@ limitations under the License. import React from "react"; import { replaceableComponent } from "../../../utils/replaceableComponent"; -import { Playback } from "../../../voice/Playback"; +import { Playback } from "../../../audio/Playback"; import InlineSpinner from '../elements/InlineSpinner'; import { _t } from "../../../languageHandler"; import AudioPlayer from "../audio_messages/AudioPlayer"; import { IMediaEventContent } from "../../../customisations/models/IMediaEventContent"; import MFileBody from "./MFileBody"; import { IBodyProps } from "./IBodyProps"; -import { PlaybackManager } from "../../../voice/PlaybackManager"; +import { PlaybackManager } from "../../../audio/PlaybackManager"; interface IState { error?: Error; diff --git a/src/components/views/rooms/MessageComposer.tsx b/src/components/views/rooms/MessageComposer.tsx index b16d22b416..ee1ff7d17d 100644 --- a/src/components/views/rooms/MessageComposer.tsx +++ b/src/components/views/rooms/MessageComposer.tsx @@ -35,7 +35,7 @@ import { UPDATE_EVENT } from "../../../stores/AsyncStore"; import { replaceableComponent } from "../../../utils/replaceableComponent"; import VoiceRecordComposerTile from "./VoiceRecordComposerTile"; import { VoiceRecordingStore } from "../../../stores/VoiceRecordingStore"; -import { RecordingState } from "../../../voice/VoiceRecording"; +import { RecordingState } from "../../../audio/VoiceRecording"; import Tooltip, { Alignment } from "../elements/Tooltip"; import ResizeNotifier from "../../../utils/ResizeNotifier"; import { E2EStatus } from '../../../utils/ShieldUtils'; diff --git a/src/components/views/rooms/VoiceRecordComposerTile.tsx b/src/components/views/rooms/VoiceRecordComposerTile.tsx index f0df64fcb4..4c40d218b0 100644 --- a/src/components/views/rooms/VoiceRecordComposerTile.tsx +++ b/src/components/views/rooms/VoiceRecordComposerTile.tsx @@ -20,7 +20,7 @@ import React, { ReactNode } from "react"; import { RecordingState, VoiceRecording, -} from "../../../voice/VoiceRecording"; +} from "../../../audio/VoiceRecording"; import { Room } from "matrix-js-sdk/src/models/room"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; import classNames from "classnames"; diff --git a/src/stores/VoiceRecordingStore.ts b/src/stores/VoiceRecordingStore.ts index 81c19e7e82..df837fec88 100644 --- a/src/stores/VoiceRecordingStore.ts +++ b/src/stores/VoiceRecordingStore.ts @@ -17,7 +17,7 @@ limitations under the License. import { AsyncStoreWithClient } from "./AsyncStoreWithClient"; import defaultDispatcher from "../dispatcher/dispatcher"; import { ActionPayload } from "../dispatcher/payloads"; -import { VoiceRecording } from "../voice/VoiceRecording"; +import { VoiceRecording } from "../audio/VoiceRecording"; interface IState { recording?: VoiceRecording; From e1bb04f45a071318872bed0623bba3c5b59ce8db Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 22 Jul 2021 09:27:38 -0600 Subject: [PATCH 16/32] Remove answered TODOs --- src/components/views/messages/MAudioBody.tsx | 2 -- src/components/views/messages/MVoiceMessageBody.tsx | 2 -- src/components/views/rooms/VoiceRecordComposerTile.tsx | 1 - 3 files changed, 5 deletions(-) diff --git a/src/components/views/messages/MAudioBody.tsx b/src/components/views/messages/MAudioBody.tsx index 823198f44d..288ad16d88 100644 --- a/src/components/views/messages/MAudioBody.tsx +++ b/src/components/views/messages/MAudioBody.tsx @@ -76,7 +76,6 @@ export default class MAudioBody extends React.PureComponent public render() { if (this.state.error) { - // TODO: @@TR: Verify error state return ( @@ -86,7 +85,6 @@ export default class MAudioBody extends React.PureComponent } if (!this.state.playback) { - // TODO: @@TR: Verify loading/decrypting state return ( diff --git a/src/components/views/messages/MVoiceMessageBody.tsx b/src/components/views/messages/MVoiceMessageBody.tsx index f184caf448..55b608cf2d 100644 --- a/src/components/views/messages/MVoiceMessageBody.tsx +++ b/src/components/views/messages/MVoiceMessageBody.tsx @@ -27,7 +27,6 @@ export default class MVoiceMessageBody extends MAudioBody { // A voice message is an audio file but rendered in a special way. public render() { if (this.state.error) { - // TODO: @@TR: Verify error state return ( @@ -37,7 +36,6 @@ export default class MVoiceMessageBody extends MAudioBody { } if (!this.state.playback) { - // TODO: @@TR: Verify loading/decrypting state return ( diff --git a/src/components/views/rooms/VoiceRecordComposerTile.tsx b/src/components/views/rooms/VoiceRecordComposerTile.tsx index 4c40d218b0..8323320520 100644 --- a/src/components/views/rooms/VoiceRecordComposerTile.tsx +++ b/src/components/views/rooms/VoiceRecordComposerTile.tsx @@ -189,7 +189,6 @@ export default class VoiceRecordComposerTile extends React.PureComponent; } From bd46275ec6a77806fdfd92868d74f25b099cc430 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 22 Jul 2021 17:48:17 +0200 Subject: [PATCH 17/32] Don't show scrollbar for url previews MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/rooms/_LinkPreviewWidget.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/css/views/rooms/_LinkPreviewWidget.scss b/res/css/views/rooms/_LinkPreviewWidget.scss index 0832337ecd..8505905108 100644 --- a/res/css/views/rooms/_LinkPreviewWidget.scss +++ b/res/css/views/rooms/_LinkPreviewWidget.scss @@ -33,7 +33,7 @@ limitations under the License. .mx_LinkPreviewWidget_caption { margin-left: 15px; flex: 1 1 auto; - overflow-x: hidden; // cause it to wrap rather than clip + overflow: hidden; // cause it to wrap rather than clip } .mx_LinkPreviewWidget_title { From c427612c241a5f5e34439c0b672c0dac047a9fe3 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 22 Jul 2021 12:14:38 -0600 Subject: [PATCH 18/32] de-dupe audio player Fixes https://github.com/vector-im/element-web/issues/18161 --- .../views/audio_messages/AudioPlayer.tsx | 47 ++----------- .../views/audio_messages/AudioPlayerBase.tsx | 70 +++++++++++++++++++ .../audio_messages/RecordingPlayback.tsx | 48 ++----------- 3 files changed, 80 insertions(+), 85 deletions(-) create mode 100644 src/components/views/audio_messages/AudioPlayerBase.tsx diff --git a/src/components/views/audio_messages/AudioPlayer.tsx b/src/components/views/audio_messages/AudioPlayer.tsx index 3c0e5c1143..b83f89fe5b 100644 --- a/src/components/views/audio_messages/AudioPlayer.tsx +++ b/src/components/views/audio_messages/AudioPlayer.tsx @@ -14,9 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { Playback, PlaybackState } from "../../../audio/Playback"; import React, { createRef, ReactNode, RefObject } from "react"; -import { UPDATE_EVENT } from "../../../stores/AsyncStore"; import PlayPauseButton from "./PlayPauseButton"; import { replaceableComponent } from "../../../utils/replaceableComponent"; import { formatBytes } from "../../../utils/FormattingUtils"; @@ -25,47 +23,13 @@ import { Key } from "../../../Keyboard"; import { _t } from "../../../languageHandler"; import SeekBar from "./SeekBar"; import PlaybackClock from "./PlaybackClock"; - -interface IProps { - // Playback instance to render. Cannot change during component lifecycle: create - // an all-new component instead. - playback: Playback; - - mediaName: string; -} - -interface IState { - playbackPhase: PlaybackState; - error?: boolean; -} +import AudioPlayerBase from "./AudioPlayerBase"; @replaceableComponent("views.audio_messages.AudioPlayer") -export default class AudioPlayer extends React.PureComponent { +export default class AudioPlayer extends AudioPlayerBase { private playPauseRef: RefObject = createRef(); private seekRef: RefObject = createRef(); - constructor(props: IProps) { - super(props); - - this.state = { - playbackPhase: PlaybackState.Decoding, // default assumption - }; - - // We don't need to de-register: the class handles this for us internally - this.props.playback.on(UPDATE_EVENT, this.onPlaybackUpdate); - - // Don't wait for the promise to complete - it will emit a progress update when it - // is done, and it's not meant to take long anyhow. - this.props.playback.prepare().catch(e => { - console.error("Error processing audio file:", e); - this.setState({ error: true }); - }); - } - - private onPlaybackUpdate = (ev: PlaybackState) => { - this.setState({ playbackPhase: ev }); - }; - private onKeyDown = (ev: React.KeyboardEvent) => { // stopPropagation() prevents the FocusComposer catch-all from triggering, // but we need to do it on key down instead of press (even though the user @@ -91,10 +55,10 @@ export default class AudioPlayer extends React.PureComponent { return `(${formatBytes(bytes)})`; } - public render(): ReactNode { + protected renderComponent(): ReactNode { // tabIndex=0 to ensure that the whole component becomes a tab stop, where we handle keyboard // events for accessibility - return <> + return (
{
- { this.state.error &&
{ _t("Error downloading audio") }
} - ; + ); } } diff --git a/src/components/views/audio_messages/AudioPlayerBase.tsx b/src/components/views/audio_messages/AudioPlayerBase.tsx new file mode 100644 index 0000000000..d8fc9d507f --- /dev/null +++ b/src/components/views/audio_messages/AudioPlayerBase.tsx @@ -0,0 +1,70 @@ +/* +Copyright 2021 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { Playback, PlaybackState } from "../../../audio/Playback"; +import { TileShape } from "../rooms/EventTile"; +import React, { ReactNode } from "react"; +import { UPDATE_EVENT } from "../../../stores/AsyncStore"; +import { replaceableComponent } from "../../../utils/replaceableComponent"; +import { _t } from "../../../languageHandler"; + +interface IProps { + // Playback instance to render. Cannot change during component lifecycle: create + // an all-new component instead. + playback: Playback; + + mediaName?: string; + tileShape?: TileShape; +} + +interface IState { + playbackPhase: PlaybackState; + error?: boolean; +} + +@replaceableComponent("views.audio_messages.AudioPlayerBase") +export default abstract class AudioPlayerBase extends React.PureComponent { + constructor(props: IProps) { + super(props); + + this.state = { + playbackPhase: PlaybackState.Decoding, // default assumption + }; + + // We don't need to de-register: the class handles this for us internally + this.props.playback.on(UPDATE_EVENT, this.onPlaybackUpdate); + + // Don't wait for the promise to complete - it will emit a progress update when it + // is done, and it's not meant to take long anyhow. + this.props.playback.prepare().catch(e => { + console.error("Error processing audio file:", e); + this.setState({ error: true }); + }); + } + + private onPlaybackUpdate = (ev: PlaybackState) => { + this.setState({ playbackPhase: ev }); + }; + + protected abstract renderComponent(): ReactNode; + + public render(): ReactNode { + return <> + { this.renderComponent() } + { this.state.error &&
{ _t("Error downloading audio") }
} + ; + } +} diff --git a/src/components/views/audio_messages/RecordingPlayback.tsx b/src/components/views/audio_messages/RecordingPlayback.tsx index 9a45101efc..e3f612c9b6 100644 --- a/src/components/views/audio_messages/RecordingPlayback.tsx +++ b/src/components/views/audio_messages/RecordingPlayback.tsx @@ -14,68 +14,30 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { Playback, PlaybackState } from "../../../audio/Playback"; import React, { ReactNode } from "react"; -import { UPDATE_EVENT } from "../../../stores/AsyncStore"; import PlayPauseButton from "./PlayPauseButton"; import PlaybackClock from "./PlaybackClock"; import { replaceableComponent } from "../../../utils/replaceableComponent"; import { TileShape } from "../rooms/EventTile"; import PlaybackWaveform from "./PlaybackWaveform"; -import { _t } from "../../../languageHandler"; - -interface IProps { - // Playback instance to render. Cannot change during component lifecycle: create - // an all-new component instead. - playback: Playback; - - tileShape?: TileShape; -} - -interface IState { - playbackPhase: PlaybackState; - error?: boolean; -} +import AudioPlayerBase from "./AudioPlayerBase"; @replaceableComponent("views.audio_messages.RecordingPlayback") -export default class RecordingPlayback extends React.PureComponent { - constructor(props: IProps) { - super(props); - - this.state = { - playbackPhase: PlaybackState.Decoding, // default assumption - }; - - // We don't need to de-register: the class handles this for us internally - this.props.playback.on(UPDATE_EVENT, this.onPlaybackUpdate); - - // Don't wait for the promise to complete - it will emit a progress update when it - // is done, and it's not meant to take long anyhow. - this.props.playback.prepare().catch(e => { - console.error("Error processing audio file:", e); - this.setState({ error: true }); - }); - } - +export default class RecordingPlayback extends AudioPlayerBase { private get isWaveformable(): boolean { return this.props.tileShape !== TileShape.Notif && this.props.tileShape !== TileShape.FileGrid && this.props.tileShape !== TileShape.Pinned; } - private onPlaybackUpdate = (ev: PlaybackState) => { - this.setState({ playbackPhase: ev }); - }; - - public render(): ReactNode { + protected renderComponent(): ReactNode { const shapeClass = !this.isWaveformable ? 'mx_VoiceMessagePrimaryContainer_noWaveform' : ''; - return <> + return (
{ this.isWaveformable && }
- { this.state.error &&
{ _t("Error downloading audio") }
} - ; + ); } } From d38f2cf5b59467adf0597efddf51f80cdce9ed21 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 22 Jul 2021 22:49:30 +0100 Subject: [PATCH 19/32] Fix display of image messages that lack thumbnails Fixes https://github.com/vector-im/element-web/issues/18175 --- src/utils/MediaEventHelper.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/utils/MediaEventHelper.ts b/src/utils/MediaEventHelper.ts index cf34d5dea4..8b8edcc62a 100644 --- a/src/utils/MediaEventHelper.ts +++ b/src/utils/MediaEventHelper.ts @@ -67,6 +67,7 @@ export class MediaEventHelper implements IDestroyable { private prepareThumbnailUrl = async () => { if (this.media.isEncrypted) { const blob = await this.thumbnailBlob.value; + if (blob === null) return null; return URL.createObjectURL(blob); } else { return this.media.thumbnailHttp; From cd77b9f1af11e59f51e0a23c6258c7cb95db7034 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 23 Jul 2021 08:55:16 +0100 Subject: [PATCH 20/32] merge two opposing if statements --- src/components/views/dialogs/CreateRoomDialog.tsx | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/components/views/dialogs/CreateRoomDialog.tsx b/src/components/views/dialogs/CreateRoomDialog.tsx index b5d8421ae0..a06f508908 100644 --- a/src/components/views/dialogs/CreateRoomDialog.tsx +++ b/src/components/views/dialogs/CreateRoomDialog.tsx @@ -93,13 +93,18 @@ export default class CreateRoomDialog extends React.Component { const opts: IOpts = {}; const createOpts: IOpts["createOpts"] = opts.createOpts = {}; createOpts.name = this.state.name; + if (this.state.joinRule === JoinRule.Public) { createOpts.visibility = Visibility.Public; createOpts.preset = Preset.PublicChat; opts.guestAccess = false; const { alias } = this.state; createOpts.room_alias_name = alias.substr(1, alias.indexOf(":") - 1); + } else { + // If we cannot change encryption we pass `true` for safety, the server should automatically do this for us. + opts.encryption = this.state.canChangeEncryption ? this.state.isEncrypted : true; } + if (this.state.topic) { createOpts.topic = this.state.topic; } @@ -107,16 +112,6 @@ export default class CreateRoomDialog extends React.Component { createOpts.creation_content = { 'm.federate': false }; } - if (this.state.joinRule !== JoinRule.Public) { - if (this.state.canChangeEncryption) { - opts.encryption = this.state.isEncrypted; - } else { - // the server should automatically do this for us, but for safety - // we'll demand it too. - opts.encryption = true; - } - } - if (CommunityPrototypeStore.instance.getSelectedCommunityId()) { opts.associatedWithCommunity = CommunityPrototypeStore.instance.getSelectedCommunityId(); } From f5630acea77b24af819172b61d250201d9a8009d Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 23 Jul 2021 10:23:45 +0100 Subject: [PATCH 21/32] Adhere to better eslint rules --- src/Registration.js | 13 ++- .../dialogs/security/CreateKeyBackupDialog.js | 2 +- .../security/CreateSecretStorageDialog.js | 7 +- .../dialogs/security/ExportE2eKeysDialog.js | 14 ++- .../dialogs/security/ImportE2eKeysDialog.js | 5 +- src/components/structures/EmbeddedPage.js | 3 +- src/components/structures/GroupView.js | 41 +++++--- src/components/structures/MyGroups.js | 3 +- src/components/structures/RoomStatusBar.js | 8 +- src/components/structures/RoomView.tsx | 3 +- src/components/structures/SearchBox.js | 4 +- src/components/structures/SpaceRoomView.tsx | 16 ++-- .../structures/auth/ForgotPassword.tsx | 10 +- src/components/structures/auth/Login.tsx | 4 +- .../structures/auth/Registration.tsx | 16 ++-- .../views/audio_messages/Waveform.tsx | 10 +- .../auth/InteractiveAuthEntryComponents.tsx | 10 +- src/components/views/avatars/BaseAvatar.tsx | 6 +- src/components/views/avatars/MemberAvatar.tsx | 8 +- .../context_menus/DialpadContextMenu.tsx | 6 +- .../context_menus/StatusMessageContextMenu.js | 23 +++-- .../views/context_menus/WidgetContextMenu.tsx | 3 +- .../dialogs/AddExistingToSpaceDialog.tsx | 14 ++- .../views/dialogs/AddressPickerDialog.tsx | 12 ++- src/components/views/dialogs/BaseDialog.js | 4 +- .../views/dialogs/BetaFeedbackDialog.tsx | 13 ++- .../views/dialogs/BugReportDialog.tsx | 4 +- .../CommunityPrototypeInviteDialog.tsx | 14 ++- .../views/dialogs/ConfirmRedactDialog.tsx | 4 +- .../views/dialogs/ConfirmUserActionDialog.tsx | 4 +- .../CreateCommunityPrototypeDialog.tsx | 6 +- .../views/dialogs/CreateGroupDialog.tsx | 11 ++- .../views/dialogs/CreateRoomDialog.tsx | 4 +- .../views/dialogs/CryptoStoreTooNewDialog.tsx | 2 +- .../views/dialogs/DevtoolsDialog.tsx | 94 ++++++++++++++----- .../dialogs/EditCommunityPrototypeDialog.tsx | 6 +- .../views/dialogs/ForwardDialog.tsx | 18 ++-- .../views/dialogs/IncomingSasDialog.js | 13 ++- src/components/views/dialogs/InfoDialog.js | 3 +- src/components/views/dialogs/InviteDialog.tsx | 39 +++++--- .../dialogs/SessionRestoreErrorDialog.js | 4 +- .../views/dialogs/StorageEvictedDialog.js | 4 +- .../security/AccessSecretStorageDialog.tsx | 3 +- .../security/RestoreKeyBackupDialog.js | 2 +- src/components/views/elements/AddressTile.tsx | 2 +- .../elements/DesktopCapturerSourcePicker.tsx | 3 +- src/components/views/elements/ImageView.tsx | 29 +++--- .../views/elements/MiniAvatarUploader.tsx | 2 +- src/components/views/elements/Pill.js | 5 +- .../views/elements/PowerSelector.js | 15 ++- src/components/views/elements/Tooltip.tsx | 3 +- src/components/views/emojipicker/Category.tsx | 10 +- .../views/groups/GroupMemberList.js | 18 +++- .../views/groups/GroupMemberTile.js | 11 ++- src/components/views/groups/GroupRoomList.js | 24 +++-- src/components/views/groups/GroupRoomTile.js | 6 +- src/components/views/messages/CallEvent.tsx | 2 +- src/components/views/messages/MImageBody.tsx | 23 +++-- src/components/views/messages/MVideoBody.tsx | 3 +- .../views/messages/RoomAvatarEvent.js | 7 +- src/components/views/right_panel/UserInfo.tsx | 30 +++--- src/components/views/rooms/EventTile.tsx | 13 ++- .../views/rooms/JumpToBottomButton.js | 7 +- src/components/views/rooms/MemberList.tsx | 22 +++-- .../views/rooms/MessageComposer.tsx | 7 +- src/components/views/rooms/NewRoomIntro.tsx | 13 ++- .../views/rooms/ReadReceiptMarker.js | 4 +- .../views/rooms/RoomBreadcrumbs.tsx | 4 +- src/components/views/rooms/RoomDetailRow.js | 8 +- src/components/views/rooms/RoomList.tsx | 4 +- src/components/views/rooms/RoomPreviewBar.js | 6 +- .../views/rooms/SimpleRoomHeader.js | 8 +- src/components/views/rooms/Stickerpicker.js | 6 +- .../views/rooms/TopUnreadMessagesBar.js | 14 +-- src/components/views/settings/BridgeTile.tsx | 2 +- src/components/views/settings/ChangeAvatar.js | 15 ++- .../views/settings/EventIndexPanel.tsx | 19 ++-- .../views/settings/ProfileSettings.js | 6 +- src/components/views/settings/SetIdServer.tsx | 4 +- .../tabs/room/GeneralRoomSettingsTab.js | 9 +- .../tabs/room/RolesRoomSettingsTab.tsx | 7 +- .../tabs/room/SecurityRoomSettingsTab.tsx | 13 ++- .../tabs/user/AppearanceUserSettingsTab.tsx | 7 +- .../tabs/user/GeneralUserSettingsTab.js | 8 +- .../tabs/user/HelpUserSettingsTab.tsx | 50 ++++++---- .../settings/tabs/user/LabsUserSettingsTab.js | 7 +- .../views/spaces/SpaceBasicSettings.tsx | 39 +++++--- src/components/views/voip/CallView.tsx | 14 ++- src/components/views/voip/DialPad.tsx | 12 ++- src/components/views/voip/DialPadModal.tsx | 8 +- src/components/views/voip/VideoFeed.tsx | 2 +- .../structures/MessagePanel-test.js | 34 +++++-- 92 files changed, 710 insertions(+), 348 deletions(-) diff --git a/src/Registration.js b/src/Registration.js index 70dcd38454..c59d244149 100644 --- a/src/Registration.js +++ b/src/Registration.js @@ -51,10 +51,15 @@ export async function startAnyRegistrationFlow(options) { description: _t("Use your account or create a new one to continue."), button: _t("Create Account"), extraButtons: [ - , + , ], onFinished: (proceed) => { if (proceed) { diff --git a/src/async-components/views/dialogs/security/CreateKeyBackupDialog.js b/src/async-components/views/dialogs/security/CreateKeyBackupDialog.js index 412194ab43..2cef1c0e41 100644 --- a/src/async-components/views/dialogs/security/CreateKeyBackupDialog.js +++ b/src/async-components/views/dialogs/security/CreateKeyBackupDialog.js @@ -269,7 +269,7 @@ export default class CreateKeyBackupDialog extends React.PureComponent {
{ _t("Advanced") } - + { _t("Set up with a Security Key") }
diff --git a/src/async-components/views/dialogs/security/CreateSecretStorageDialog.js b/src/async-components/views/dialogs/security/CreateSecretStorageDialog.js index aa78d68830..641df4f897 100644 --- a/src/async-components/views/dialogs/security/CreateSecretStorageDialog.js +++ b/src/async-components/views/dialogs/security/CreateSecretStorageDialog.js @@ -474,7 +474,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent { outlined >
- + { _t("Generate a Security Key") }
{ _t("We’ll generate a Security Key for you to store somewhere safe, like a password manager or a safe.") }
@@ -493,7 +493,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent { outlined >
- + { _t("Enter a Security Phrase") }
{ _t("Use a secret phrase only you know, and optionally save a Security Key to use for backup.") }
@@ -701,7 +701,8 @@ export default class CreateSecretStorageDialog extends React.PureComponent { { this._recoveryKey.encodedPrivateKey }
- diff --git a/src/async-components/views/dialogs/security/ExportE2eKeysDialog.js b/src/async-components/views/dialogs/security/ExportE2eKeysDialog.js index 0435d81968..dbed9f3968 100644 --- a/src/async-components/views/dialogs/security/ExportE2eKeysDialog.js +++ b/src/async-components/views/dialogs/security/ExportE2eKeysDialog.js @@ -148,8 +148,12 @@ export default class ExportE2eKeysDialog extends React.Component {
-
@@ -161,8 +165,10 @@ export default class ExportE2eKeysDialog extends React.Component {
-
diff --git a/src/async-components/views/dialogs/security/ImportE2eKeysDialog.js b/src/async-components/views/dialogs/security/ImportE2eKeysDialog.js index 6017d07047..0936ad696d 100644 --- a/src/async-components/views/dialogs/security/ImportE2eKeysDialog.js +++ b/src/async-components/views/dialogs/security/ImportE2eKeysDialog.js @@ -174,7 +174,10 @@ export default class ImportE2eKeysDialog extends React.Component {
- ; + submitButton = ; } return ( @@ -616,7 +618,9 @@ export class MsisdnAuthEntry extends React.Component
- diff --git a/src/components/views/avatars/BaseAvatar.tsx b/src/components/views/avatars/BaseAvatar.tsx index 87cdbe7512..6aaef29854 100644 --- a/src/components/views/avatars/BaseAvatar.tsx +++ b/src/components/views/avatars/BaseAvatar.tsx @@ -187,7 +187,8 @@ const BaseAvatar = (props: IProps) => { width: toPx(width), height: toPx(height), }} - title={title} alt={_t("Avatar")} + title={title} + alt={_t("Avatar")} inputRef={inputRef} {...otherProps} /> ); @@ -201,7 +202,8 @@ const BaseAvatar = (props: IProps) => { width: toPx(width), height: toPx(height), }} - title={title} alt="" + title={title} + alt="" ref={inputRef} {...otherProps} /> ); diff --git a/src/components/views/avatars/MemberAvatar.tsx b/src/components/views/avatars/MemberAvatar.tsx index 61155e3880..11c24a5981 100644 --- a/src/components/views/avatars/MemberAvatar.tsx +++ b/src/components/views/avatars/MemberAvatar.tsx @@ -102,8 +102,12 @@ export default class MemberAvatar extends React.Component { } return ( - + ); } } diff --git a/src/components/views/context_menus/DialpadContextMenu.tsx b/src/components/views/context_menus/DialpadContextMenu.tsx index 39dfd50795..aead3a266e 100644 --- a/src/components/views/context_menus/DialpadContextMenu.tsx +++ b/src/components/views/context_menus/DialpadContextMenu.tsx @@ -60,8 +60,10 @@ export default class DialpadContextMenu extends React.Component
-
diff --git a/src/components/views/context_menus/StatusMessageContextMenu.js b/src/components/views/context_menus/StatusMessageContextMenu.js index f90d9cc005..e05b05116c 100644 --- a/src/components/views/context_menus/StatusMessageContextMenu.js +++ b/src/components/views/context_menus/StatusMessageContextMenu.js @@ -109,8 +109,10 @@ export default class StatusMessageContextMenu extends React.Component { ; } } else { - actionButton = { _t("Set status") } ; @@ -121,12 +123,19 @@ export default class StatusMessageContextMenu extends React.Component { spinner = ; } - const form =
-
diff --git a/src/components/views/context_menus/WidgetContextMenu.tsx b/src/components/views/context_menus/WidgetContextMenu.tsx index b21efdceb9..26d7b640a4 100644 --- a/src/components/views/context_menus/WidgetContextMenu.tsx +++ b/src/components/views/context_menus/WidgetContextMenu.tsx @@ -76,7 +76,8 @@ const WidgetContextMenu: React.FC = ({ onFinished(); }; streamAudioStreamButton = ; } diff --git a/src/components/views/dialogs/AddExistingToSpaceDialog.tsx b/src/components/views/dialogs/AddExistingToSpaceDialog.tsx index 0f78b971eb..89f7c8596f 100644 --- a/src/components/views/dialogs/AddExistingToSpaceDialog.tsx +++ b/src/components/views/dialogs/AddExistingToSpaceDialog.tsx @@ -211,10 +211,16 @@ export const AddExistingToSpace: React.FC = ({ function overflowTile(overflowCount, totalCount) { const text = _t("and %(count)s others...", { count: overflowCount }); return ( - - } name={text} presenceState="online" suppressOnHover={true} - onClick={() => setTruncateAt(totalCount)} /> + + } + name={text} + presenceState="online" + suppressOnHover={true} + onClick={() => setTruncateAt(totalCount)} + /> ); } diff --git a/src/components/views/dialogs/AddressPickerDialog.tsx b/src/components/views/dialogs/AddressPickerDialog.tsx index 1a976918bd..6b239ee570 100644 --- a/src/components/views/dialogs/AddressPickerDialog.tsx +++ b/src/components/views/dialogs/AddressPickerDialog.tsx @@ -665,8 +665,8 @@ export default class AddressPickerDialog extends React.Component onChange={this.onQueryChanged} placeholder={this.getPlaceholder()} defaultValue={this.props.value} - autoFocus={this.props.focus}> - , + autoFocus={this.props.focus} + />, ); const filteredSuggestedList = this.getFilteredSuggestions(); @@ -727,8 +727,12 @@ export default class AddressPickerDialog extends React.Component } return ( - + { inputLabel }
{ query }
diff --git a/src/components/views/dialogs/BaseDialog.js b/src/components/views/dialogs/BaseDialog.js index 8ccc485d7c..42b21ec743 100644 --- a/src/components/views/dialogs/BaseDialog.js +++ b/src/components/views/dialogs/BaseDialog.js @@ -118,9 +118,7 @@ export default class BaseDialog extends React.Component { let headerImage; if (this.props.headerImage) { - headerImage = ; + headerImage = ; } return ( diff --git a/src/components/views/dialogs/BetaFeedbackDialog.tsx b/src/components/views/dialogs/BetaFeedbackDialog.tsx index 917004dbc7..34218a3399 100644 --- a/src/components/views/dialogs/BetaFeedbackDialog.tsx +++ b/src/components/views/dialogs/BetaFeedbackDialog.tsx @@ -71,13 +71,16 @@ const BetaFeedbackDialog: React.FC = ({ featureId, onFinished }) => {   { _t("Your platform and username will be noted to help us use your feedback as much as we can.") } - { - onFinished(false); - defaultDispatcher.dispatch({ + { + onFinished(false); + defaultDispatcher.dispatch({ action: Action.ViewUserSettings, initialTabId: UserTab.Labs, - }); - }}> + }); + }} + > { _t("To leave the beta, visit your settings.") }
diff --git a/src/components/views/dialogs/BugReportDialog.tsx b/src/components/views/dialogs/BugReportDialog.tsx index 64e984fe20..3df05dac6e 100644 --- a/src/components/views/dialogs/BugReportDialog.tsx +++ b/src/components/views/dialogs/BugReportDialog.tsx @@ -188,7 +188,9 @@ export default class BugReportDialog extends React.Component { } return ( - diff --git a/src/components/views/dialogs/CommunityPrototypeInviteDialog.tsx b/src/components/views/dialogs/CommunityPrototypeInviteDialog.tsx index 73fd4def25..6a8773ce45 100644 --- a/src/components/views/dialogs/CommunityPrototypeInviteDialog.tsx +++ b/src/components/views/dialogs/CommunityPrototypeInviteDialog.tsx @@ -205,9 +205,12 @@ export default class CommunityPrototypeInviteDialog extends React.PureComponent< people.push(( { _t("Show more") } + > + { _t("Show more") } + )); } } @@ -240,10 +243,13 @@ export default class CommunityPrototypeInviteDialog extends React.PureComponent< { peopleIntro } { people } { buttonText } + > + { buttonText } +
diff --git a/src/components/views/dialogs/ConfirmRedactDialog.tsx b/src/components/views/dialogs/ConfirmRedactDialog.tsx index a2f2b10144..b346d2d44c 100644 --- a/src/components/views/dialogs/ConfirmRedactDialog.tsx +++ b/src/components/views/dialogs/ConfirmRedactDialog.tsx @@ -37,8 +37,8 @@ export default class ConfirmRedactDialog extends React.Component { "Note that if you delete a room name or topic change, it could undo the change.")} placeholder={_t("Reason (optional)")} focus - button={_t("Remove")}> - + button={_t("Remove")} + /> ); } } diff --git a/src/components/views/dialogs/ConfirmUserActionDialog.tsx b/src/components/views/dialogs/ConfirmUserActionDialog.tsx index cbef474c69..7099556ac6 100644 --- a/src/components/views/dialogs/ConfirmUserActionDialog.tsx +++ b/src/components/views/dialogs/ConfirmUserActionDialog.tsx @@ -104,7 +104,9 @@ export default class ConfirmUserActionDialog extends React.Component { } return ( - diff --git a/src/components/views/dialogs/CreateCommunityPrototypeDialog.tsx b/src/components/views/dialogs/CreateCommunityPrototypeDialog.tsx index 392ab9edad..ccac45fbcc 100644 --- a/src/components/views/dialogs/CreateCommunityPrototypeDialog.tsx +++ b/src/components/views/dialogs/CreateCommunityPrototypeDialog.tsx @@ -204,8 +204,10 @@ export default class CreateCommunityPrototypeDialog extends React.PureComponent<
{ } return ( -
@@ -133,8 +135,11 @@ export default class CreateGroupDialog extends React.Component {
- { title = _t("Create a room in %(communityName)s", { communityName: name }); } return ( - diff --git a/src/components/views/dialogs/CryptoStoreTooNewDialog.tsx b/src/components/views/dialogs/CryptoStoreTooNewDialog.tsx index 134c4ab79e..d03b668cd9 100644 --- a/src/components/views/dialogs/CryptoStoreTooNewDialog.tsx +++ b/src/components/views/dialogs/CryptoStoreTooNewDialog.tsx @@ -72,7 +72,7 @@ const CryptoStoreTooNewDialog: React.FC = (props: IProps) => { hasCancel={false} onPrimaryButtonClick={props.onFinished} > - diff --git a/src/components/views/dialogs/DevtoolsDialog.tsx b/src/components/views/dialogs/DevtoolsDialog.tsx index 61cda796ee..8ae9d0654f 100644 --- a/src/components/views/dialogs/DevtoolsDialog.tsx +++ b/src/components/views/dialogs/DevtoolsDialog.tsx @@ -182,14 +182,23 @@ export class SendCustomEvent extends GenericEditor - +
{ !this.state.message && } { showTglFlip &&
- - +
{ !this.state.message && } { !this.state.message &&
- - + key={this.props.children[0] ? this.props.children[0].key : ''} + /> ; + }} + />; } return
@@ -594,7 +625,9 @@ class AccountDataExplorer extends React.PureComponent; + }} + forceMode={true} + />; } return
@@ -631,7 +664,9 @@ class AccountDataExplorer extends React.PureComponent
-
@@ -1040,7 +1080,9 @@ class SettingsExplorer extends React.PureComponent this.onViewClick(e, i)}> { i } - this.onEditClick(e, i)} + this.onEditClick(e, i)} className='mx_DevTools_SettingsExplorer_edit' > ✏ @@ -1104,18 +1146,26 @@ class SettingsExplorer extends React.PureComponent
diff --git a/src/components/views/dialogs/EditCommunityPrototypeDialog.tsx b/src/components/views/dialogs/EditCommunityPrototypeDialog.tsx index 1eabb68081..a0e6046d71 100644 --- a/src/components/views/dialogs/EditCommunityPrototypeDialog.tsx +++ b/src/components/views/dialogs/EditCommunityPrototypeDialog.tsx @@ -144,8 +144,10 @@ export default class EditCommunityPrototypeDialog extends React.PureComponent
= ({ room, event, matrixClient: cli, onFinish className = "mx_ForwardList_sending"; disabled = true; title = _t("Sending"); - icon =
; + icon =
; } else if (sendState === SendState.Sent) { className = "mx_ForwardList_sent"; disabled = true; title = _t("Sent"); - icon =
; + icon =
; } else { className = "mx_ForwardList_sendFailed"; disabled = true; @@ -204,10 +204,16 @@ const ForwardDialog: React.FC = ({ matrixClient: cli, event, permalinkCr function overflowTile(overflowCount, totalCount) { const text = _t("and %(count)s others...", { count: overflowCount }); return ( - - } name={text} presenceState="online" suppressOnHover={true} - onClick={() => setTruncateAt(totalCount)} /> + + } + name={text} + presenceState="online" + suppressOnHover={true} + onClick={() => setTruncateAt(totalCount)} + /> ); } diff --git a/src/components/views/dialogs/IncomingSasDialog.js b/src/components/views/dialogs/IncomingSasDialog.js index 963d98ef3f..a5c9f2107f 100644 --- a/src/components/views/dialogs/IncomingSasDialog.js +++ b/src/components/views/dialogs/IncomingSasDialog.js @@ -133,18 +133,23 @@ export default class IncomingSasDialog extends React.Component { ? mediaFromMxc(oppProfile.avatar_url).getSquareThumbnailHttp(48) : null; profile =
-

{ oppProfile.displayname }

; } else if (this.state.opponentProfileError) { profile =
-

{ this.props.verifier.userId }

; diff --git a/src/components/views/dialogs/InfoDialog.js b/src/components/views/dialogs/InfoDialog.js index 8207d334d3..ff8c3645ca 100644 --- a/src/components/views/dialogs/InfoDialog.js +++ b/src/components/views/dialogs/InfoDialog.js @@ -63,8 +63,7 @@ export default class InfoDialog extends React.Component { { this.props.button !== false && - } + /> } ); } diff --git a/src/components/views/dialogs/InviteDialog.tsx b/src/components/views/dialogs/InviteDialog.tsx index 46f140fd39..609829b833 100644 --- a/src/components/views/dialogs/InviteDialog.tsx +++ b/src/components/views/dialogs/InviteDialog.tsx @@ -196,7 +196,9 @@ class DMUserTile extends React.PureComponent { ? + width={avatarSize} + height={avatarSize} + /> : { className='mx_InviteDialog_userTile_remove' onClick={this.onRemove} > - {_t('Remove')} ); @@ -297,7 +302,9 @@ class DMRoomTile extends React.PureComponent { const avatar = (this.props.member as ThreepidMember).isEmail ? + width={avatarSize} + height={avatarSize} + /> : + width={14} + height={14} /> { " " + _t("Invited people will be able to read old messages.") }

; } @@ -1534,14 +1542,18 @@ export default class InviteDialog extends React.PureComponent; } else { - dialPadField = { dialPadField } -
; tabs.push(new Tab(TabId.DialPad, _td("Dial pad"), 'mx_InviteDialog_dialPadIcon', dialPadSection)); dialogContent = - { consultConnectSection } ; diff --git a/src/components/views/dialogs/SessionRestoreErrorDialog.js b/src/components/views/dialogs/SessionRestoreErrorDialog.js index b7037d1f4f..eeeadbbfe5 100644 --- a/src/components/views/dialogs/SessionRestoreErrorDialog.js +++ b/src/components/views/dialogs/SessionRestoreErrorDialog.js @@ -85,7 +85,9 @@ export default class SessionRestoreErrorDialog extends React.Component { } return ( - { _t("Forgotten or lost all recovery methods?
Reset all", null, { a: (sub) => { sub }, }) }
diff --git a/src/components/views/dialogs/security/RestoreKeyBackupDialog.js b/src/components/views/dialogs/security/RestoreKeyBackupDialog.js index e8bd8af01c..2b272a3b88 100644 --- a/src/components/views/dialogs/security/RestoreKeyBackupDialog.js +++ b/src/components/views/dialogs/security/RestoreKeyBackupDialog.js @@ -399,7 +399,7 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { let keyStatus; if (this.state.recoveryKey.length === 0) { - keyStatus =
; + keyStatus =
; } else if (this.state.recoveryKeyValid) { keyStatus =
{ "\uD83D\uDC4D " }{ _t("This looks like a valid Security Key!") } diff --git a/src/components/views/elements/AddressTile.tsx b/src/components/views/elements/AddressTile.tsx index cdeb7cacd6..52c0d84ac2 100644 --- a/src/components/views/elements/AddressTile.tsx +++ b/src/components/views/elements/AddressTile.tsx @@ -122,7 +122,7 @@ export default class AddressTile extends React.Component { let dismiss; if (this.props.canDismiss) { dismiss = ( -
+
); diff --git a/src/components/views/elements/DesktopCapturerSourcePicker.tsx b/src/components/views/elements/DesktopCapturerSourcePicker.tsx index 82d0aa4976..20ecf08a5f 100644 --- a/src/components/views/elements/DesktopCapturerSourcePicker.tsx +++ b/src/components/views/elements/DesktopCapturerSourcePicker.tsx @@ -51,7 +51,8 @@ export class ExistingSource extends React.Component + onClick={this.onClick} + > { const avatar = ( ); @@ -403,7 +404,7 @@ export default class ImageView extends React.Component { // an empty div here, since the panel uses space-between // and we want the same placement of elements info = ( -
+
); } @@ -427,15 +428,15 @@ export default class ImageView extends React.Component { - + onClick={this.onZoomOutClick} + /> ); zoomInButton = ( - + onClick={this.onZoomInClick} + /> ); } @@ -457,24 +458,24 @@ export default class ImageView extends React.Component { - + onClick={this.onRotateCounterClockwiseClick} + /> - + onClick={this.onRotateClockwiseClick} + /> - + onClick={this.onDownloadClick} + /> { contextMenuButton } - + onClick={this.props.onFinished} + /> { this.renderContextMenu() }
diff --git a/src/components/views/elements/MiniAvatarUploader.tsx b/src/components/views/elements/MiniAvatarUploader.tsx index 47bcd845ba..22ff4bf4b3 100644 --- a/src/components/views/elements/MiniAvatarUploader.tsx +++ b/src/components/views/elements/MiniAvatarUploader.tsx @@ -92,7 +92,7 @@ const MiniAvatarUploader: React.FC = ({ hasAvatar, hasAvatarLabel, noAva
{ busy ? : -
} +
}
- diff --git a/src/components/views/rooms/RoomList.tsx b/src/components/views/rooms/RoomList.tsx index 9e7d9ca205..080816df14 100644 --- a/src/components/views/rooms/RoomList.tsx +++ b/src/components/views/rooms/RoomList.tsx @@ -428,7 +428,9 @@ export default class RoomList extends React.PureComponent { groupId={g.groupId} groupName={g.name} groupAvatarUrl={g.avatarUrl} - width={32} height={32} resizeMethod='crop' + width={32} + height={32} + resizeMethod='crop' /> ); const openGroup = () => { diff --git a/src/components/views/rooms/RoomPreviewBar.js b/src/components/views/rooms/RoomPreviewBar.js index 3cd34b1966..b8a4315e2d 100644 --- a/src/components/views/rooms/RoomPreviewBar.js +++ b/src/components/views/rooms/RoomPreviewBar.js @@ -536,8 +536,10 @@ export default class RoomPreviewBar extends React.Component { "If you think you're seeing this message in error, please " + "submit a bug report.", { errcode: this.props.error.errcode }, - { issueLink: label => { label } }, + { issueLink: label => { label } }, ), ]; break; diff --git a/src/components/views/rooms/SimpleRoomHeader.js b/src/components/views/rooms/SimpleRoomHeader.js index 768a456b35..a2b5566e39 100644 --- a/src/components/views/rooms/SimpleRoomHeader.js +++ b/src/components/views/rooms/SimpleRoomHeader.js @@ -35,13 +35,15 @@ export default class SimpleRoomHeader extends React.Component { let icon; if (this.props.icon) { icon = ; } return ( -
+
{ icon } { this.props.title } diff --git a/src/components/views/rooms/Stickerpicker.js b/src/components/views/rooms/Stickerpicker.js index c0e6826ba5..6649948331 100644 --- a/src/components/views/rooms/Stickerpicker.js +++ b/src/components/views/rooms/Stickerpicker.js @@ -403,8 +403,7 @@ export default class Stickerpicker extends React.PureComponent { onClick={this._onHideStickersClick} active={this.state.showStickers.toString()} title={_t("Hide Stickers")} - > - ; + />; const GenericElementContextMenu = sdk.getComponent('context_menus.GenericElementContextMenu'); stickerPicker = - ; + />; } return { stickersButton } diff --git a/src/components/views/rooms/TopUnreadMessagesBar.js b/src/components/views/rooms/TopUnreadMessagesBar.js index 0f632e7128..d2a3e3a303 100644 --- a/src/components/views/rooms/TopUnreadMessagesBar.js +++ b/src/components/views/rooms/TopUnreadMessagesBar.js @@ -32,14 +32,16 @@ export default class TopUnreadMessagesBar extends React.Component { render() { return (
- - - + - + onClick={this.props.onCloseClick} + />
); } diff --git a/src/components/views/settings/BridgeTile.tsx b/src/components/views/settings/BridgeTile.tsx index 7228e4b939..5dd5ed9ba1 100644 --- a/src/components/views/settings/BridgeTile.tsx +++ b/src/components/views/settings/BridgeTile.tsx @@ -124,7 +124,7 @@ export default class BridgeTile extends React.PureComponent { url={avatarUrl} />; } else { - networkIcon =
; + networkIcon =
; } let networkItem = null; if (network) { diff --git a/src/components/views/settings/ChangeAvatar.js b/src/components/views/settings/ChangeAvatar.js index 36d5d4aa0c..c3a1544cdc 100644 --- a/src/components/views/settings/ChangeAvatar.js +++ b/src/components/views/settings/ChangeAvatar.js @@ -148,13 +148,22 @@ export default class ChangeAvatar extends React.Component { if (this.props.room && !this.avatarSet) { const RoomAvatar = sdk.getComponent('avatars.RoomAvatar'); avatarImg = ; } else { const BaseAvatar = sdk.getComponent("avatars.BaseAvatar"); // XXX: FIXME: once we track in the JS what our own displayname is(!) then use it here rather than ? - avatarImg = ; + avatarImg = ; } let uploadSection; diff --git a/src/components/views/settings/EventIndexPanel.tsx b/src/components/views/settings/EventIndexPanel.tsx index de49c2a980..9966e38de8 100644 --- a/src/components/views/settings/EventIndexPanel.tsx +++ b/src/components/views/settings/EventIndexPanel.tsx @@ -178,8 +178,11 @@ export default class EventIndexPanel extends React.Component<{}, IState> { "appear in search results.", ) }
- + { _t("Enable") } { this.state.enabling ? :
} @@ -203,8 +206,10 @@ export default class EventIndexPanel extends React.Component<{}, IState> { brand, }, { - nativeLink: sub => { sub }, }, ) }
@@ -219,8 +224,10 @@ export default class EventIndexPanel extends React.Component<{}, IState> { brand, }, { - desktopLink: sub => { sub }, }, ) }
diff --git a/src/components/views/settings/ProfileSettings.js b/src/components/views/settings/ProfileSettings.js index 02eaaaeea8..d05fca983c 100644 --- a/src/components/views/settings/ProfileSettings.js +++ b/src/components/views/settings/ProfileSettings.js @@ -172,7 +172,8 @@ export default class ProfileSettings extends React.Component { > @@ -181,7 +182,8 @@ export default class ProfileSettings extends React.Component { { _t("Profile") } diff --git a/src/components/views/settings/SetIdServer.tsx b/src/components/views/settings/SetIdServer.tsx index fd8abc0dbe..1f488f1e67 100644 --- a/src/components/views/settings/SetIdServer.tsx +++ b/src/components/views/settings/SetIdServer.tsx @@ -426,7 +426,9 @@ export default class SetIdServer extends React.Component { disabled={this.state.busy} forceValidity={this.state.error ? false : null} /> - { _t("Change") } diff --git a/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.js b/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.js index e2f30192b9..b90fb310e0 100644 --- a/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.js +++ b/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.js @@ -97,9 +97,12 @@ export default class GeneralRoomSettingsTab extends React.Component {
{ _t("Room Addresses") }
- +
{ _t("Other") }
{ flairSection } diff --git a/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx b/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx index edc0220921..9225bc6b94 100644 --- a/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx +++ b/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx @@ -346,8 +346,11 @@ export default class RolesRoomSettingsTab extends React.Component { let bannedBy = member.events.member.getSender(); // start by falling back to mxid if (sender) bannedBy = sender.name; return ( - ); diff --git a/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx b/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx index 88bc2046ce..99ae2e52ab 100644 --- a/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx +++ b/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx @@ -133,8 +133,10 @@ export default class SecurityRoomSettingsTab extends React.ComponentLearn more about encryption.", {}, { - a: sub => { sub }, }, ), @@ -424,8 +426,11 @@ export default class SecurityRoomSettingsTab extends React.Component { _t("Once enabled, encryption cannot be disabled.") }
-
{ encryptionSettings } diff --git a/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx b/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx index d1c497b351..44873816dc 100644 --- a/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx @@ -303,9 +303,12 @@ export default class AppearanceUserSettingsTab extends React.Component { _t("Add theme") } + > + { _t("Add theme") } + { messageElement }
diff --git a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js index 2a6e8937a3..238d6cca21 100644 --- a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.js @@ -426,9 +426,13 @@ export default class GeneralUserSettingsTab extends React.Component { const supportsMultiLanguageSpellCheck = plaf.supportsMultiLanguageSpellCheck(); const discoWarning = this.state.requiredPolicyInfo.hasTerms - ? {_t("Warning")} + width="18" + height="18" + alt={_t("Warning")} + /> : null; let accountManagementSection; diff --git a/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx b/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx index 33de634611..eaf52e6062 100644 --- a/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/HelpUserSettingsTab.tsx @@ -134,28 +134,39 @@ export default class HelpUserSettingsTab extends React.Component { _t("Credits") } @@ -254,7 +265,8 @@ export default class HelpUserSettingsTab extends React.Component "Security Disclosure Policy.", {}, { a: sub => { sub }, }, ) } diff --git a/src/components/views/settings/tabs/user/LabsUserSettingsTab.js b/src/components/views/settings/tabs/user/LabsUserSettingsTab.js index aace4ca557..fa854fc4d8 100644 --- a/src/components/views/settings/tabs/user/LabsUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/LabsUserSettingsTab.js @@ -86,8 +86,11 @@ export default class LabsUserSettingsTab extends React.Component { 'test out new features and help shape them before they actually launch. ' + 'Learn more.', {}, { 'a': (sub) => { - return { sub }; + return { sub }; }, }) } diff --git a/src/components/views/spaces/SpaceBasicSettings.tsx b/src/components/views/spaces/SpaceBasicSettings.tsx index 6d2cc1f5db..9d3696c5a9 100644 --- a/src/components/views/spaces/SpaceBasicSettings.tsx +++ b/src/components/views/spaces/SpaceBasicSettings.tsx @@ -57,11 +57,15 @@ export const SpaceAvatar = ({ src={avatar} alt="" /> - { - avatarUploadRef.current.value = ""; - setAvatarDataUrl(undefined); - setAvatar(undefined); - }} kind="link" className="mx_SpaceBasicSettings_avatar_remove"> + { + avatarUploadRef.current.value = ""; + setAvatarDataUrl(undefined); + setAvatar(undefined); + }} + kind="link" + className="mx_SpaceBasicSettings_avatar_remove" + > { _t("Delete") } ; @@ -77,16 +81,21 @@ export const SpaceAvatar = ({ return
{ avatarSection } - { - if (!e.target.files?.length) return; - const file = e.target.files[0]; - setAvatar(file); - const reader = new FileReader(); - reader.onload = (ev) => { - setAvatarDataUrl(ev.target.result as string); - }; - reader.readAsDataURL(file); - }} accept="image/*" /> + { + if (!e.target.files?.length) return; + const file = e.target.files[0]; + setAvatar(file); + const reader = new FileReader(); + reader.onload = (ev) => { + setAvatarDataUrl(ev.target.result as string); + }; + reader.readAsDataURL(file); + }} + accept="image/*" + />
; }; diff --git a/src/components/views/voip/CallView.tsx b/src/components/views/voip/CallView.tsx index 8bdd6e0f55..e53c2f4823 100644 --- a/src/components/views/voip/CallView.tsx +++ b/src/components/views/voip/CallView.tsx @@ -665,15 +665,19 @@ export default class CallView extends React.Component { let fullScreenButton; if (this.props.call.type === CallType.Video && !this.props.pipMode) { - fullScreenButton =
; } let expandButton; if (this.props.pipMode) { - expandButton =
; } @@ -685,7 +689,7 @@ export default class CallView extends React.Component { let header: React.ReactNode; if (!this.props.pipMode) { header =
-
+
{ callTypeText } { headerControls }
; diff --git a/src/components/views/voip/DialPad.tsx b/src/components/views/voip/DialPad.tsx index 2af8bd6989..3b4a29b3f9 100644 --- a/src/components/views/voip/DialPad.tsx +++ b/src/components/views/voip/DialPad.tsx @@ -68,13 +68,19 @@ export default class Dialpad extends React.PureComponent { for (let i = 0; i < BUTTONS.length; i++) { const button = BUTTONS[i]; const digitSubtext = BUTTON_LETTERS[i]; - buttonNodes.push(); } if (this.props.hasDial) { - buttonNodes.push(); } diff --git a/src/components/views/voip/DialPadModal.tsx b/src/components/views/voip/DialPadModal.tsx index 0bba65e44f..a36fc37dff 100644 --- a/src/components/views/voip/DialPadModal.tsx +++ b/src/components/views/voip/DialPadModal.tsx @@ -81,14 +81,18 @@ export default class DialpadModal extends React.PureComponent { // Only show the backspace button if the field has content let dialPadField; if (this.state.value.length !== 0) { - dialPadField = ; } else { - dialPadField = { const avatarSize = this.props.pipMode ? 76 : 160; return ( -
+
, + , ); const tiles = TestUtils.scryRenderedComponentsWithType( @@ -330,8 +334,12 @@ describe('MessagePanel', function() { it('should show the read-marker that fall in summarised events after the summary', function() { const melsEvents = mkMelsEvents(); const res = TestUtils.renderIntoDocument( - , + , ); const summary = TestUtils.findRenderedDOMComponentWithClass(res, 'mx_EventListSummary'); @@ -348,8 +356,12 @@ describe('MessagePanel', function() { it('should hide the read-marker at the end of summarised events', function() { const melsEvents = mkMelsEventsOnly(); const res = TestUtils.renderIntoDocument( - , + , ); const summary = TestUtils.findRenderedDOMComponentWithClass(res, 'mx_EventListSummary'); @@ -371,7 +383,10 @@ describe('MessagePanel', function() { // first render with the RM in one place let mp = ReactDOM.render( - , parentDiv); @@ -387,7 +402,10 @@ describe('MessagePanel', function() { // now move the RM mp = ReactDOM.render( - , parentDiv); From f99c0fad3ec428e34523e7b3f2daf151d43093f3 Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Fri, 23 Jul 2021 11:40:34 +0200 Subject: [PATCH 22/32] Make inline events feel less claustrophobic in bubble layout --- res/css/views/rooms/_EventBubbleTile.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/res/css/views/rooms/_EventBubbleTile.scss b/res/css/views/rooms/_EventBubbleTile.scss index a65afdf0d5..487bb38c49 100644 --- a/res/css/views/rooms/_EventBubbleTile.scss +++ b/res/css/views/rooms/_EventBubbleTile.scss @@ -221,6 +221,7 @@ limitations under the License. display: flex; align-items: center; justify-content: center; + padding: 5px 0; .mx_EventTile_avatar { position: static; @@ -287,7 +288,7 @@ limitations under the License. & + .mx_EventListSummary { .mx_EventTile { margin-top: 0; - padding: 0; + padding: 2px 0; } } From 1ba5f19f2eee5914f0c2cb28749cfc8045a64aa4 Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Fri, 23 Jul 2021 12:09:39 +0200 Subject: [PATCH 23/32] Put avatar is right place when sender isnt displayed in message bubbles --- res/css/views/rooms/_EventBubbleTile.scss | 6 ++++++ src/components/views/rooms/EventTile.tsx | 1 + 2 files changed, 7 insertions(+) diff --git a/res/css/views/rooms/_EventBubbleTile.scss b/res/css/views/rooms/_EventBubbleTile.scss index a65afdf0d5..44afd23ac6 100644 --- a/res/css/views/rooms/_EventBubbleTile.scss +++ b/res/css/views/rooms/_EventBubbleTile.scss @@ -162,6 +162,12 @@ limitations under the License. } } + &.mx_EventTile_noSender { + .mx_EventTile_avatar { + top: -19px; + } + } + &[data-has-reply=true] { > .mx_EventTile_line { flex-direction: column; diff --git a/src/components/views/rooms/EventTile.tsx b/src/components/views/rooms/EventTile.tsx index c6c605a8c2..96520143b9 100644 --- a/src/components/views/rooms/EventTile.tsx +++ b/src/components/views/rooms/EventTile.tsx @@ -893,6 +893,7 @@ export default class EventTile extends React.Component { mx_EventTile_unknown: !isBubbleMessage && this.state.verified === E2E_STATE.UNKNOWN, mx_EventTile_bad: isEncryptionFailure, mx_EventTile_emote: msgtype === 'm.emote', + mx_EventTile_noSender: this.props.hideSender, }); // If the tile is in the Sending state, don't speak the message. From dcfd5d47933b9f6cbc99cfef95006d0edea27df3 Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Fri, 23 Jul 2021 12:12:52 +0200 Subject: [PATCH 24/32] Overlay avatar on top of bubbles --- res/css/views/rooms/_EventBubbleTile.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/res/css/views/rooms/_EventBubbleTile.scss b/res/css/views/rooms/_EventBubbleTile.scss index 44afd23ac6..f325d68551 100644 --- a/res/css/views/rooms/_EventBubbleTile.scss +++ b/res/css/views/rooms/_EventBubbleTile.scss @@ -156,6 +156,7 @@ limitations under the License. position: absolute; top: 0; line-height: 1; + z-index: 9; img { box-shadow: 0 0 0 3px $eventbubble-avatar-outline; border-radius: 50%; From 4a4ec596bd90b117df5da5e495a06dc628fd1f0c Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 23 Jul 2021 11:27:00 +0100 Subject: [PATCH 25/32] Fix position of the space hierarchy spinner --- res/css/structures/_SpaceRoomView.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/res/css/structures/_SpaceRoomView.scss b/res/css/structures/_SpaceRoomView.scss index 48b565be7f..3119d2fe6e 100644 --- a/res/css/structures/_SpaceRoomView.scss +++ b/res/css/structures/_SpaceRoomView.scss @@ -234,6 +234,9 @@ $SpaceRoomViewInnerWidth: 428px; } .mx_SpaceRoomView_landing { + display: flex; + flex-direction: column; + > .mx_BaseAvatar_image, > .mx_BaseAvatar > .mx_BaseAvatar_image { border-radius: 12px; @@ -340,6 +343,7 @@ $SpaceRoomViewInnerWidth: 428px; .mx_SearchBox { margin: 0 0 20px; + flex: 0; } .mx_SpaceFeedbackPrompt { From 2b133deb63db689a373bddabe48125e16233e09a Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 23 Jul 2021 12:19:54 +0100 Subject: [PATCH 26/32] fix scroll behaviour to match that of prior to the spinner fix --- res/css/structures/_SpaceRoomView.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/res/css/structures/_SpaceRoomView.scss b/res/css/structures/_SpaceRoomView.scss index 3119d2fe6e..e4832d9430 100644 --- a/res/css/structures/_SpaceRoomView.scss +++ b/res/css/structures/_SpaceRoomView.scss @@ -354,6 +354,11 @@ $SpaceRoomViewInnerWidth: 428px; display: none; } } + + .mx_SpaceRoomDirectory_list { + // we don't want this container to get forced into the flexbox layout + display: contents; + } } .mx_SpaceRoomView_privateScope { From 42b213ba8c873041680dd7a1792a59f3fe37b934 Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Fri, 23 Jul 2021 14:17:26 +0200 Subject: [PATCH 27/32] Fix clipped avatar in room list --- res/css/views/avatars/_BaseAvatar.scss | 1 - res/css/views/rooms/_EventBubbleTile.scss | 6 +++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/res/css/views/avatars/_BaseAvatar.scss b/res/css/views/avatars/_BaseAvatar.scss index 65e4493f19..cbddd97e18 100644 --- a/res/css/views/avatars/_BaseAvatar.scss +++ b/res/css/views/avatars/_BaseAvatar.scss @@ -27,7 +27,6 @@ limitations under the License. // https://bugzilla.mozilla.org/show_bug.cgi?id=255139 display: inline-block; user-select: none; - line-height: 1; } .mx_BaseAvatar_initial { diff --git a/res/css/views/rooms/_EventBubbleTile.scss b/res/css/views/rooms/_EventBubbleTile.scss index 487bb38c49..8629682693 100644 --- a/res/css/views/rooms/_EventBubbleTile.scss +++ b/res/css/views/rooms/_EventBubbleTile.scss @@ -155,13 +155,17 @@ limitations under the License. .mx_EventTile_avatar { position: absolute; top: 0; - line-height: 1; img { box-shadow: 0 0 0 3px $eventbubble-avatar-outline; border-radius: 50%; } } + .mx_BaseAvatar, + .mx_EventTile_avatar { + line-height: 1; + } + &[data-has-reply=true] { > .mx_EventTile_line { flex-direction: column; From 3ce6fcc64b7259d5cd1e1f694e4420c36f178a4f Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Fri, 23 Jul 2021 14:52:51 +0200 Subject: [PATCH 28/32] Fix reactions row pushing content on IRC layout --- res/css/views/rooms/_IRCLayout.scss | 5 +++++ src/components/views/rooms/EventTile.tsx | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/res/css/views/rooms/_IRCLayout.scss b/res/css/views/rooms/_IRCLayout.scss index 97190807ca..578c0325d2 100644 --- a/res/css/views/rooms/_IRCLayout.scss +++ b/res/css/views/rooms/_IRCLayout.scss @@ -116,6 +116,11 @@ $irc-line-height: $font-18px; .mx_EditMessageComposer_buttons { position: relative; } + + .mx_ReactionsRow { + padding-left: 0; + padding-right: 0; + } } .mx_EventTile_emote { diff --git a/src/components/views/rooms/EventTile.tsx b/src/components/views/rooms/EventTile.tsx index c6c605a8c2..556ce1e577 100644 --- a/src/components/views/rooms/EventTile.tsx +++ b/src/components/views/rooms/EventTile.tsx @@ -1160,8 +1160,9 @@ export default class EventTile extends React.Component { /> { keyRequestInfo } { actionBar } + { this.props.layout === Layout.IRC && (reactionsRow) }
- { reactionsRow } + { this.props.layout !== Layout.IRC && (reactionsRow) } { msgOption } ) ); From 3c1902c26a69c463bcaff95f48a23b6b3d608f34 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 23 Jul 2021 16:09:41 +0100 Subject: [PATCH 29/32] Update matrix-org-eslint-plugin --- yarn.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn.lock b/yarn.lock index 5283f5778a..c576148e19 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3234,8 +3234,8 @@ eslint-config-google@^0.14.0: integrity sha512-WsbX4WbjuMvTdeVL6+J3rK1RGhCTqjsFjX7UMSMgZiyxxaNLkoJENbrGExzERFeoTpGw3F3FypTiWAP9ZXzkEw== "eslint-plugin-matrix-org@github:matrix-org/eslint-plugin-matrix-org#main": - version "0.3.2" - resolved "https://codeload.github.com/matrix-org/eslint-plugin-matrix-org/tar.gz/8529f1d77863db6327cf1a1a4fa65d06cc26f91b" + version "0.3.3" + resolved "https://codeload.github.com/matrix-org/eslint-plugin-matrix-org/tar.gz/50d6bdf6704dd95016d5f1f824f00cac6eaa64e1" eslint-plugin-react-hooks@^4.2.0: version "4.2.0" From 5f2582395ffcf07d8edf6a384ba2d9db084a666b Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 23 Jul 2021 16:21:59 +0100 Subject: [PATCH 30/32] Fix blurhash rounded corners missing regression --- res/css/views/messages/_MImageBody.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/css/views/messages/_MImageBody.scss b/res/css/views/messages/_MImageBody.scss index f5d8131e6e..42565a76d0 100644 --- a/res/css/views/messages/_MImageBody.scss +++ b/res/css/views/messages/_MImageBody.scss @@ -28,7 +28,7 @@ $timelineImageBorderRadius: 4px; justify-content: center; align-items: center; - > canvas { + > div > canvas { border-radius: $timelineImageBorderRadius; } } From 4fe0e216d6417ad15559d57ed9ef1720b8c705be Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 23 Jul 2021 16:22:35 +0100 Subject: [PATCH 31/32] Use div instead of span for mx_MImageBody to not violate spec --- res/css/views/messages/_MImageBody.scss | 4 ---- src/components/views/messages/MImageBody.tsx | 8 ++++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/res/css/views/messages/_MImageBody.scss b/res/css/views/messages/_MImageBody.scss index 42565a76d0..a748435cd8 100644 --- a/res/css/views/messages/_MImageBody.scss +++ b/res/css/views/messages/_MImageBody.scss @@ -16,10 +16,6 @@ limitations under the License. $timelineImageBorderRadius: 4px; -.mx_MImageBody { - display: block; -} - .mx_MImageBody_thumbnail { object-fit: contain; border-radius: $timelineImageBorderRadius; diff --git a/src/components/views/messages/MImageBody.tsx b/src/components/views/messages/MImageBody.tsx index c24f014d84..945994d964 100644 --- a/src/components/views/messages/MImageBody.tsx +++ b/src/components/views/messages/MImageBody.tsx @@ -416,10 +416,10 @@ export default class MImageBody extends React.Component { if (this.state.error !== null) { return ( - +
{ _t("Error decrypting image") } - +
); } @@ -434,10 +434,10 @@ export default class MImageBody extends React.Component { const thumbnail = this.messageContent(contentUrl, thumbUrl, content); const fileBody = this.getFileBody(); - return + return
{ thumbnail } { fileBody } - ; +
; } } From fa550a65af11f5b0e9422b2ca8b0f51cab6b0736 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 23 Jul 2021 19:01:12 +0100 Subject: [PATCH 32/32] Fix editing of & & --- src/editor/deserialize.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/editor/deserialize.ts b/src/editor/deserialize.ts index eb8adfda9d..9033f99b6c 100644 --- a/src/editor/deserialize.ts +++ b/src/editor/deserialize.ts @@ -121,6 +121,12 @@ function parseElement(n: HTMLElement, partCreator: PartCreator, lastNode: HTMLEl return partCreator.plain(`\`${n.textContent}\``); case "DEL": return partCreator.plain(`${n.textContent}`); + case "SUB": + return partCreator.plain(`${n.textContent}`); + case "SUP": + return partCreator.plain(`${n.textContent}`); + case "U": + return partCreator.plain(`${n.textContent}`); case "LI": { const indent = " ".repeat(state.listDepth - 1); if (n.parentElement.nodeName === "OL") {