diff --git a/res/css/views/audio_messages/_PlaybackContainer.scss b/res/css/views/audio_messages/_PlaybackContainer.scss index fd01864bba..5548f6198e 100644 --- a/res/css/views/audio_messages/_PlaybackContainer.scss +++ b/res/css/views/audio_messages/_PlaybackContainer.scss @@ -49,4 +49,8 @@ limitations under the License. padding-right: 6px; // with the fixed width this ends up as a visual 8px most of the time, as intended. padding-left: 8px; // isolate from recording circle / play control } + + &.mx_VoiceMessagePrimaryContainer_noWaveform { + max-width: 162px; // with all the padding this results in 185px wide + } } diff --git a/src/components/views/audio_messages/RecordingPlayback.tsx b/src/components/views/audio_messages/RecordingPlayback.tsx index a0dea1c6db..7d9312f369 100644 --- a/src/components/views/audio_messages/RecordingPlayback.tsx +++ b/src/components/views/audio_messages/RecordingPlayback.tsx @@ -17,15 +17,18 @@ limitations under the License. import { Playback, PlaybackState } from "../../../voice/Playback"; import React, { ReactNode } from "react"; import { UPDATE_EVENT } from "../../../stores/AsyncStore"; -import PlaybackWaveform from "./PlaybackWaveform"; import PlayPauseButton from "./PlayPauseButton"; import PlaybackClock from "./PlaybackClock"; import { replaceableComponent } from "../../../utils/replaceableComponent"; +import { TileShape } from "../rooms/EventTile"; +import PlaybackWaveform from "./PlaybackWaveform"; interface IProps { // Playback instance to render. Cannot change during component lifecycle: create // an all-new component instead. playback: Playback; + + tileShape?: TileShape; } interface IState { @@ -50,15 +53,22 @@ export default class RecordingPlayback extends React.PureComponent { this.setState({ playbackPhase: ev }); }; public render(): ReactNode { - return
+ const shapeClass = !this.isWaveformable ? 'mx_VoiceMessagePrimaryContainer_noWaveform' : ''; + return
- + { this.isWaveformable && }
; } } diff --git a/src/components/views/elements/ReplyThread.js b/src/components/views/elements/ReplyThread.js index 2047de6c58..4dcdf70845 100644 --- a/src/components/views/elements/ReplyThread.js +++ b/src/components/views/elements/ReplyThread.js @@ -1,7 +1,6 @@ /* -Copyright 2017 New Vector Ltd +Copyright 2017 - 2021 The Matrix.org Foundation C.I.C. Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> -Copyright 2019 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -32,6 +31,7 @@ import sanitizeHtml from "sanitize-html"; import { UIFeature } from "../../../settings/UIFeature"; import { PERMITTED_URL_SCHEMES } from "../../../HtmlUtils"; import { replaceableComponent } from "../../../utils/replaceableComponent"; +import { TileShape } from "../rooms/EventTile"; // This component does no cycle detection, simply because the only way to make such a cycle would be to // craft event_id's, using a homeserver that generates predictable event IDs; even then the impact would @@ -384,7 +384,7 @@ export default class ReplyThread extends React.Component { { dateSep } {placeholder} diff --git a/src/components/views/messages/MVoiceMessageBody.tsx b/src/components/views/messages/MVoiceMessageBody.tsx index 2edd42f2e4..bec224dd2d 100644 --- a/src/components/views/messages/MVoiceMessageBody.tsx +++ b/src/components/views/messages/MVoiceMessageBody.tsx @@ -25,9 +25,11 @@ import { mediaFromContent } from "../../../customisations/Media"; import { decryptFile } from "../../../utils/DecryptFile"; import RecordingPlayback from "../audio_messages/RecordingPlayback"; import { IMediaEventContent } from "../../../customisations/models/IMediaEventContent"; +import { TileShape } from "../rooms/EventTile"; interface IProps { mxEvent: MatrixEvent; + tileShape?: TileShape; } interface IState { @@ -103,7 +105,7 @@ export default class MVoiceMessageBody extends React.PureComponent - + ); diff --git a/src/components/views/messages/MessageEvent.js b/src/components/views/messages/MessageEvent.js index 52a0b9ad08..4168744d42 100644 --- a/src/components/views/messages/MessageEvent.js +++ b/src/components/views/messages/MessageEvent.js @@ -42,7 +42,7 @@ export default class MessageEvent extends React.Component { onHeightChanged: PropTypes.func, /* the shape of the tile, used */ - tileShape: PropTypes.string, + tileShape: PropTypes.string, // TODO: Use TileShape enum /* the maximum image height to use, if the event is an image */ maxImageHeight: PropTypes.number, diff --git a/src/components/views/rooms/EventTile.tsx b/src/components/views/rooms/EventTile.tsx index a470d3f40c..05f0b5876e 100644 --- a/src/components/views/rooms/EventTile.tsx +++ b/src/components/views/rooms/EventTile.tsx @@ -192,6 +192,7 @@ export enum TileShape { FileGrid = "file_grid", Reply = "reply", ReplyPreview = "reply_preview", + Pinned = "pinned", } interface IProps { @@ -907,7 +908,7 @@ export default class EventTile extends React.Component { mx_EventTile_12hr: this.props.isTwelveHour, // Note: we keep the `sending` state class for tests, not for our styles mx_EventTile_sending: !isEditing && isSending, - mx_EventTile_highlight: this.props.tileShape === 'notif' ? false : this.shouldHighlight(), + mx_EventTile_highlight: this.props.tileShape === TileShape.Notif ? false : this.shouldHighlight(), mx_EventTile_selected: this.props.isSelectedEvent, mx_EventTile_continuation: this.props.tileShape ? '' : this.props.continuation, mx_EventTile_last: this.props.last, @@ -940,7 +941,7 @@ export default class EventTile extends React.Component { let avatarSize; let needsSenderProfile; - if (this.props.tileShape === "notif") { + if (this.props.tileShape === TileShape.Notif) { avatarSize = 24; needsSenderProfile = true; } else if (tileHandler === 'messages.RoomCreate' || isBubbleMessage) { @@ -954,7 +955,7 @@ export default class EventTile extends React.Component { } else if (this.props.layout == Layout.IRC) { avatarSize = 14; needsSenderProfile = true; - } else if (this.props.continuation && this.props.tileShape !== "file_grid") { + } else if (this.props.continuation && this.props.tileShape !== TileShape.FileGrid) { // no avatar or sender profile for continuation messages avatarSize = 0; needsSenderProfile = false; @@ -984,7 +985,11 @@ export default class EventTile extends React.Component { } if (needsSenderProfile && this.props.hideSender !== true) { - if (!this.props.tileShape || this.props.tileShape === 'reply' || this.props.tileShape === 'reply_preview') { + if ( + !this.props.tileShape + || this.props.tileShape === TileShape.Reply + || this.props.tileShape === TileShape.ReplyPreview + ) { sender = { } switch (this.props.tileShape) { - case 'notif': { + case TileShape.Notif: { const room = this.context.getRoom(this.props.mxEvent.getRoomId()); return React.createElement(this.props.as || "li", { "className": classes, @@ -1102,11 +1107,12 @@ export default class EventTile extends React.Component { highlightLink={this.props.highlightLink} showUrlPreview={this.props.showUrlPreview} onHeightChanged={this.props.onHeightChanged} + tileShape={this.props.tileShape} />
, ]); } - case 'file_grid': { + case TileShape.FileGrid: { return React.createElement(this.props.as || "li", { "className": classes, "aria-live": ariaLive, @@ -1137,10 +1143,10 @@ export default class EventTile extends React.Component { ]); } - case 'reply': - case 'reply_preview': { + case TileShape.Reply: + case TileShape.ReplyPreview: { let thread; - if (this.props.tileShape === 'reply_preview') { + if (this.props.tileShape === TileShape.ReplyPreview) { thread = ReplyThread.makeThread( this.props.mxEvent, this.props.onHeightChanged, diff --git a/src/components/views/rooms/PinnedEventTile.tsx b/src/components/views/rooms/PinnedEventTile.tsx index 774dea70c8..0e3396e9b0 100644 --- a/src/components/views/rooms/PinnedEventTile.tsx +++ b/src/components/views/rooms/PinnedEventTile.tsx @@ -29,6 +29,7 @@ import { replaceableComponent } from "../../../utils/replaceableComponent"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; import { getUserNameColorClass } from "../../../utils/FormattingUtils"; import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; +import { TileShape } from "./EventTile"; interface IProps { room: Room; @@ -87,6 +88,7 @@ export default class PinnedEventTile extends React.Component { className="mx_PinnedEventTile_body" maxImageHeight={150} onHeightChanged={() => {}} // we need to give this, apparently + tileShape={TileShape.Pinned} /> diff --git a/src/components/views/rooms/ReplyPreview.js b/src/components/views/rooms/ReplyPreview.js index f9c8e622a7..e1e5a0a846 100644 --- a/src/components/views/rooms/ReplyPreview.js +++ b/src/components/views/rooms/ReplyPreview.js @@ -1,5 +1,5 @@ /* -Copyright 2017 New Vector Ltd +Copyright 2017 - 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. @@ -24,6 +24,7 @@ import PropTypes from "prop-types"; import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks"; import { UIFeature } from "../../../settings/UIFeature"; import { replaceableComponent } from "../../../utils/replaceableComponent"; +import { TileShape } from "./EventTile"; function cancelQuoting() { dis.dispatch({ @@ -90,7 +91,7 @@ export default class ReplyPreview extends React.Component {