From d282675bc643058c4835db499e68d7b34af0e13f Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Sun, 13 Oct 2019 15:08:50 +0300 Subject: [PATCH 01/90] Improve reply rendering Signed-off-by: Tulir Asokan --- res/css/_components.scss | 1 + res/css/views/elements/_ReplyThread.scss | 11 +- res/css/views/rooms/_ReplyPreview.scss | 7 +- res/css/views/rooms/_ReplyTile.scss | 96 +++++++ src/components/views/elements/ReplyThread.js | 15 +- .../views/messages/MImageReplyBody.js | 33 +++ src/components/views/messages/MessageEvent.js | 9 +- src/components/views/rooms/ReplyPreview.js | 12 +- src/components/views/rooms/ReplyTile.js | 234 ++++++++++++++++++ 9 files changed, 388 insertions(+), 30 deletions(-) create mode 100644 res/css/views/rooms/_ReplyTile.scss create mode 100644 src/components/views/messages/MImageReplyBody.js create mode 100644 src/components/views/rooms/ReplyTile.js diff --git a/res/css/_components.scss b/res/css/_components.scss index 4891fd90c02..2c54c5f37f9 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -153,6 +153,7 @@ @import "./views/rooms/_PinnedEventsPanel.scss"; @import "./views/rooms/_PresenceLabel.scss"; @import "./views/rooms/_ReplyPreview.scss"; +@import "./views/rooms/_ReplyTile.scss"; @import "./views/rooms/_RoomBreadcrumbs.scss"; @import "./views/rooms/_RoomDropTarget.scss"; @import "./views/rooms/_RoomHeader.scss"; diff --git a/res/css/views/elements/_ReplyThread.scss b/res/css/views/elements/_ReplyThread.scss index bf44a117289..0d53a6b6f43 100644 --- a/res/css/views/elements/_ReplyThread.scss +++ b/res/css/views/elements/_ReplyThread.scss @@ -18,20 +18,13 @@ limitations under the License. margin-top: 0; } -.mx_ReplyThread .mx_DateSeparator { - font-size: 1em !important; - margin-top: 0; - margin-bottom: 0; - padding-bottom: 1px; - bottom: -5px; -} - .mx_ReplyThread_show { cursor: pointer; } blockquote.mx_ReplyThread { margin-left: 0; + margin-bottom: 8px; padding-left: 10px; - border-left: 4px solid $blockquote-bar-color; + border-left: 4px solid $button-bg-color; } diff --git a/res/css/views/rooms/_ReplyPreview.scss b/res/css/views/rooms/_ReplyPreview.scss index 4dc4cb2c406..08fbd278083 100644 --- a/res/css/views/rooms/_ReplyPreview.scss +++ b/res/css/views/rooms/_ReplyPreview.scss @@ -32,12 +32,16 @@ limitations under the License. } .mx_ReplyPreview_header { - margin: 12px; + margin: 8px; color: $primary-fg-color; font-weight: 400; opacity: 0.4; } +.mx_ReplyPreview_tile { + margin: 0 8px; +} + .mx_ReplyPreview_title { float: left; } @@ -45,6 +49,7 @@ limitations under the License. .mx_ReplyPreview_cancel { float: right; cursor: pointer; + display: flex; } .mx_ReplyPreview_clear { diff --git a/res/css/views/rooms/_ReplyTile.scss b/res/css/views/rooms/_ReplyTile.scss new file mode 100644 index 00000000000..0a055297c6a --- /dev/null +++ b/res/css/views/rooms/_ReplyTile.scss @@ -0,0 +1,96 @@ +/* +Copyright 2019 Tulir Asokan + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_ReplyTile { + max-width: 100%; + clear: both; + padding-top: 2px; + padding-bottom: 2px; + font-size: 14px; + position: relative; + line-height: 16px; +} + +.mx_ReplyTile > a { + display: block; + text-decoration: none; + color: $primary-fg-color; +} + +// We do reply size limiting with CSS to avoid duplicating the TextualBody component. +.mx_ReplyTile .mx_EventTile_content { + $reply-lines: 2; + $line-height: 22px; + + text-overflow: ellipsis; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: $reply-lines; + line-height: $line-height; + + .mx_EventTile_body.mx_EventTile_bigEmoji { + line-height: $line-height !important; + // Override the big emoji override + font-size: 14px !important; + } +} + +.mx_ReplyTile.mx_ReplyTile_info { + padding-top: 0px; +} + +.mx_ReplyTile .mx_SenderProfile { + color: $primary-fg-color; + font-size: 14px; + display: inline-block; /* anti-zalgo, with overflow hidden */ + overflow: hidden; + cursor: pointer; + padding-left: 0px; /* left gutter */ + padding-bottom: 0px; + padding-top: 0px; + margin: 0px; + line-height: 17px; + /* the next three lines, along with overflow hidden, truncate long display names */ + white-space: nowrap; + text-overflow: ellipsis; + max-width: calc(100% - 65px); +} + +.mx_ReplyTile_redacted .mx_UnknownBody { + --lozenge-color: $event-redacted-fg-color; + --lozenge-border-color: $event-redacted-border-color; + display: block; + height: 22px; + width: 250px; + border-radius: 11px; + background: + repeating-linear-gradient( + -45deg, + var(--lozenge-color), + var(--lozenge-color) 3px, + transparent 3px, + transparent 6px + ); + box-shadow: 0px 0px 3px var(--lozenge-border-color) inset; +} + +.mx_ReplyTile_sending.mx_ReplyTile_redacted .mx_UnknownBody { + opacity: 0.4; +} + +.mx_ReplyTile_contextual { + opacity: 0.4; +} diff --git a/src/components/views/elements/ReplyThread.js b/src/components/views/elements/ReplyThread.js index fac0a716175..1764c008faf 100644 --- a/src/components/views/elements/ReplyThread.js +++ b/src/components/views/elements/ReplyThread.js @@ -304,20 +304,11 @@ export default class ReplyThread extends React.Component { header = ; } - const EventTile = sdk.getComponent('views.rooms.EventTile'); - const DateSeparator = sdk.getComponent('messages.DateSeparator'); + const ReplyTile = sdk.getComponent('views.rooms.ReplyTile'); const evTiles = this.state.events.map((ev) => { - let dateSep = null; - - if (wantsDateSeparator(this.props.parentEv.getDate(), ev.getDate())) { - dateSep = ; - } - return
- { dateSep } - ; }); - return
+ return
{ header }
{ evTiles }
; diff --git a/src/components/views/messages/MImageReplyBody.js b/src/components/views/messages/MImageReplyBody.js new file mode 100644 index 00000000000..bb869919fc7 --- /dev/null +++ b/src/components/views/messages/MImageReplyBody.js @@ -0,0 +1,33 @@ +/* +Copyright 2019 Tulir Asokan + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React from 'react'; +import MImageBody from './MImageBody'; + +export default class MImageReplyBody extends MImageBody { + onClick(ev) { + ev.preventDefault(); + } + + wrapImage(contentUrl, children) { + return children; + } + + // Don't show "Download this_file.png ..." + getFileBody() { + return null; + } +} diff --git a/src/components/views/messages/MessageEvent.js b/src/components/views/messages/MessageEvent.js index a616dd96ed6..28f2a471bbe 100644 --- a/src/components/views/messages/MessageEvent.js +++ b/src/components/views/messages/MessageEvent.js @@ -43,6 +43,9 @@ module.exports = createReactClass({ /* the maximum image height to use, if the event is an image */ maxImageHeight: PropTypes.number, + + overrideBodyTypes: PropTypes.object, + overrideEventTypes: PropTypes.object, }, getEventTileOps: function() { @@ -60,9 +63,11 @@ module.exports = createReactClass({ 'm.file': sdk.getComponent('messages.MFileBody'), 'm.audio': sdk.getComponent('messages.MAudioBody'), 'm.video': sdk.getComponent('messages.MVideoBody'), + ...(this.props.overrideBodyTypes || {}), }; const evTypes = { 'm.sticker': sdk.getComponent('messages.MStickerBody'), + ...(this.props.overrideEventTypes || {}), }; const content = this.props.mxEvent.getContent(); @@ -81,7 +86,7 @@ module.exports = createReactClass({ } } - return ; + onHeightChanged={this.props.onHeightChanged} /> : null; }, }); diff --git a/src/components/views/rooms/ReplyPreview.js b/src/components/views/rooms/ReplyPreview.js index caf8feeea27..a69a286a152 100644 --- a/src/components/views/rooms/ReplyPreview.js +++ b/src/components/views/rooms/ReplyPreview.js @@ -68,7 +68,7 @@ export default class ReplyPreview extends React.Component { render() { if (!this.state.event) return null; - const EventTile = sdk.getComponent('rooms.EventTile'); + const ReplyTile = sdk.getComponent('rooms.ReplyTile'); return
@@ -80,11 +80,11 @@ export default class ReplyPreview extends React.Component { onClick={cancelQuoting} />
- +
+ +
; } diff --git a/src/components/views/rooms/ReplyTile.js b/src/components/views/rooms/ReplyTile.js new file mode 100644 index 00000000000..5a56ba9dc17 --- /dev/null +++ b/src/components/views/rooms/ReplyTile.js @@ -0,0 +1,234 @@ +/* +Copyright 2019 Tulir Asokan + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React from 'react'; +import PropTypes from 'prop-types'; +const classNames = require("classnames"); +import { _t, _td } from '../../../languageHandler'; + +const sdk = require('../../../index'); + +import dis from '../../../dispatcher'; +import SettingsStore from "../../../settings/SettingsStore"; +import {MatrixClient} from 'matrix-js-sdk'; + +const ObjectUtils = require('../../../ObjectUtils'); + +const eventTileTypes = { + 'm.room.message': 'messages.MessageEvent', + 'm.sticker': 'messages.MessageEvent', + 'm.call.invite': 'messages.TextualEvent', + 'm.call.answer': 'messages.TextualEvent', + 'm.call.hangup': 'messages.TextualEvent', +}; + +const stateEventTileTypes = { + 'm.room.aliases': 'messages.TextualEvent', + // 'm.room.aliases': 'messages.RoomAliasesEvent', // too complex + 'm.room.canonical_alias': 'messages.TextualEvent', + 'm.room.create': 'messages.RoomCreate', + 'm.room.member': 'messages.TextualEvent', + 'm.room.name': 'messages.TextualEvent', + 'm.room.avatar': 'messages.RoomAvatarEvent', + 'm.room.third_party_invite': 'messages.TextualEvent', + 'm.room.history_visibility': 'messages.TextualEvent', + 'm.room.encryption': 'messages.TextualEvent', + 'm.room.topic': 'messages.TextualEvent', + 'm.room.power_levels': 'messages.TextualEvent', + 'm.room.pinned_events': 'messages.TextualEvent', + 'm.room.server_acl': 'messages.TextualEvent', + 'im.vector.modular.widgets': 'messages.TextualEvent', + 'm.room.tombstone': 'messages.TextualEvent', + 'm.room.join_rules': 'messages.TextualEvent', + 'm.room.guest_access': 'messages.TextualEvent', + 'm.room.related_groups': 'messages.TextualEvent', +}; + +function getHandlerTile(ev) { + const type = ev.getType(); + return ev.isState() ? stateEventTileTypes[type] : eventTileTypes[type]; +} + +class ReplyTile extends React.Component { + static contextTypes = { + matrixClient: PropTypes.instanceOf(MatrixClient).isRequired, + } + + static propTypes = { + mxEvent: PropTypes.object.isRequired, + isRedacted: PropTypes.bool, + permalinkCreator: PropTypes.object, + onHeightChanged: PropTypes.func, + } + + static defaultProps = { + onHeightChanged: function() {}, + } + + constructor(props, context) { + super(props, context); + this.state = {}; + this.onClick = this.onClick.bind(this); + } + + componentDidMount() { + this.props.mxEvent.on("Event.decrypted", this._onDecrypted); + } + + shouldComponentUpdate(nextProps, nextState) { + if (!ObjectUtils.shallowEqual(this.state, nextState)) { + return true; + } + + return !this._propsEqual(this.props, nextProps); + } + + componentWillUnmount() { + const client = this.context.matrixClient; + this.props.mxEvent.removeListener("Event.decrypted", this._onDecrypted); + } + + _onDecrypted() { + this.forceUpdate(); + } + + _propsEqual(objA, objB) { + const keysA = Object.keys(objA); + const keysB = Object.keys(objB); + + if (keysA.length !== keysB.length) { + return false; + } + + for (let i = 0; i < keysA.length; i++) { + const key = keysA[i]; + + if (!objB.hasOwnProperty(key)) { + return false; + } + + if (objA[key] !== objB[key]) { + return false; + } + } + return true; + } + + onClick(e) { + // This allows the permalink to be opened in a new tab/window or copied as + // matrix.to, but also for it to enable routing within Riot when clicked. + e.preventDefault(); + dis.dispatch({ + action: 'view_room', + event_id: this.props.mxEvent.getId(), + highlighted: true, + room_id: this.props.mxEvent.getRoomId(), + }); + } + + render() { + const SenderProfile = sdk.getComponent('messages.SenderProfile'); + + const content = this.props.mxEvent.getContent(); + const msgtype = content.msgtype; + const eventType = this.props.mxEvent.getType(); + + // Info messages are basically information about commands processed on a room + let isInfoMessage = ( + eventType !== 'm.room.message' && eventType !== 'm.sticker' && eventType !== 'm.room.create' + ); + + let tileHandler = getHandlerTile(this.props.mxEvent); + // If we're showing hidden events in the timeline, we should use the + // source tile when there's no regular tile for an event and also for + // replace relations (which otherwise would display as a confusing + // duplicate of the thing they are replacing). + const useSource = !tileHandler || this.props.mxEvent.isRelation("m.replace"); + if (useSource && SettingsStore.getValue("showHiddenEventsInTimeline")) { + tileHandler = "messages.ViewSourceEvent"; + // Reuse info message avatar and sender profile styling + isInfoMessage = true; + } + // This shouldn't happen: the caller should check we support this type + // before trying to instantiate us + if (!tileHandler) { + const {mxEvent} = this.props; + console.warn(`Event type not supported: type:${mxEvent.getType()} isState:${mxEvent.isState()}`); + return
+ { _t('This event could not be displayed') } +
; + } + const EventTileType = sdk.getComponent(tileHandler); + + const classes = classNames({ + mx_ReplyTile: true, + mx_ReplyTile_info: isInfoMessage, + mx_ReplyTile_redacted: this.props.isRedacted, + }); + + let permalink = "#"; + if (this.props.permalinkCreator) { + permalink = this.props.permalinkCreator.forEvent(this.props.mxEvent.getId()); + } + + let sender; + let needsSenderProfile = tileHandler !== 'messages.RoomCreate' && !isInfoMessage; + + if (needsSenderProfile) { + let text = null; + if (msgtype === 'm.image') text = _td('%(senderName)s sent an image'); + else if (msgtype === 'm.video') text = _td('%(senderName)s sent a video'); + else if (msgtype === 'm.file') text = _td('%(senderName)s uploaded a file'); + sender = ; + } + + const MImageReplyBody = sdk.getComponent('messages.MImageReplyBody'); + const TextualBody = sdk.getComponent('messages.TextualBody'); + const msgtypeOverrides = { + "m.image": MImageReplyBody, + // We don't want a download link for files, just the file name is enough. + "m.file": TextualBody, + "m.sticker": TextualBody, + "m.audio": TextualBody, + "m.video": TextualBody, + }; + const evOverrides = { + "m.sticker": TextualBody, + }; + + return ( + + ) + } +} + +module.exports = ReplyTile; From 03d36f30ec1093dab132c8c2bbe9414da00cb9b2 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Thu, 5 Mar 2020 13:44:54 +0200 Subject: [PATCH 02/90] Fix lint errors --- src/components/views/elements/ReplyThread.js | 1 - src/components/views/messages/MImageReplyBody.js | 1 - src/components/views/messages/MessageEvent.js | 2 +- src/components/views/rooms/ReplyPreview.js | 1 - src/components/views/rooms/ReplyTile.js | 7 +++---- 5 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/components/views/elements/ReplyThread.js b/src/components/views/elements/ReplyThread.js index 25b39a2ad43..954c6b49c4d 100644 --- a/src/components/views/elements/ReplyThread.js +++ b/src/components/views/elements/ReplyThread.js @@ -20,7 +20,6 @@ import * as sdk from '../../../index'; import {_t} from '../../../languageHandler'; import PropTypes from 'prop-types'; import dis from '../../../dispatcher'; -import {wantsDateSeparator} from '../../../DateUtils'; import {MatrixEvent} from 'matrix-js-sdk'; import {makeUserPermalink, RoomPermalinkCreator} from "../../../utils/permalinks/Permalinks"; import SettingsStore from "../../../settings/SettingsStore"; diff --git a/src/components/views/messages/MImageReplyBody.js b/src/components/views/messages/MImageReplyBody.js index bb869919fc7..31b4d1fa82c 100644 --- a/src/components/views/messages/MImageReplyBody.js +++ b/src/components/views/messages/MImageReplyBody.js @@ -14,7 +14,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React from 'react'; import MImageBody from './MImageBody'; export default class MImageReplyBody extends MImageBody { diff --git a/src/components/views/messages/MessageEvent.js b/src/components/views/messages/MessageEvent.js index 14ab3c8757e..3703d3a629c 100644 --- a/src/components/views/messages/MessageEvent.js +++ b/src/components/views/messages/MessageEvent.js @@ -123,6 +123,6 @@ export default createReactClass({ editState={this.props.editState} onHeightChanged={this.props.onHeightChanged} onMessageAllowed={this.onTileUpdate} - /> : null + /> : null; }, }); diff --git a/src/components/views/rooms/ReplyPreview.js b/src/components/views/rooms/ReplyPreview.js index 92e3f123a0f..a22a85a2f13 100644 --- a/src/components/views/rooms/ReplyPreview.js +++ b/src/components/views/rooms/ReplyPreview.js @@ -19,7 +19,6 @@ import dis from '../../../dispatcher'; import * as sdk from '../../../index'; import { _t } from '../../../languageHandler'; import RoomViewStore from '../../../stores/RoomViewStore'; -import SettingsStore from "../../../settings/SettingsStore"; import PropTypes from "prop-types"; import {RoomPermalinkCreator} from "../../../utils/permalinks/Permalinks"; diff --git a/src/components/views/rooms/ReplyTile.js b/src/components/views/rooms/ReplyTile.js index 5a56ba9dc17..36cb07f092d 100644 --- a/src/components/views/rooms/ReplyTile.js +++ b/src/components/views/rooms/ReplyTile.js @@ -97,7 +97,6 @@ class ReplyTile extends React.Component { } componentWillUnmount() { - const client = this.context.matrixClient; this.props.mxEvent.removeListener("Event.decrypted", this._onDecrypted); } @@ -185,7 +184,7 @@ class ReplyTile extends React.Component { } let sender; - let needsSenderProfile = tileHandler !== 'messages.RoomCreate' && !isInfoMessage; + const needsSenderProfile = tileHandler !== 'messages.RoomCreate' && !isInfoMessage; if (needsSenderProfile) { let text = null; @@ -224,10 +223,10 @@ class ReplyTile extends React.Component { showUrlPreview={false} overrideBodyTypes={msgtypeOverrides} overrideEventTypes={evOverrides} - maxImageHeight={96}/> + maxImageHeight={96} />
- ) + ); } } From 03299a28a4f27e96a5b9b0351945b3b9c3c5218d Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Fri, 10 Apr 2020 14:23:34 +0300 Subject: [PATCH 03/90] Fix import/export things --- src/components/views/rooms/ReplyTile.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/views/rooms/ReplyTile.js b/src/components/views/rooms/ReplyTile.js index 36cb07f092d..3ad6962f1a5 100644 --- a/src/components/views/rooms/ReplyTile.js +++ b/src/components/views/rooms/ReplyTile.js @@ -1,5 +1,5 @@ /* -Copyright 2019 Tulir Asokan +Copyright 2020 Tulir Asokan Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -16,16 +16,16 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; -const classNames = require("classnames"); +import classNames from 'classnames'; import { _t, _td } from '../../../languageHandler'; -const sdk = require('../../../index'); +import * as sdk from '../../../index'; import dis from '../../../dispatcher'; import SettingsStore from "../../../settings/SettingsStore"; import {MatrixClient} from 'matrix-js-sdk'; -const ObjectUtils = require('../../../ObjectUtils'); +import * as ObjectUtils from '../../../ObjectUtils'; const eventTileTypes = { 'm.room.message': 'messages.MessageEvent', @@ -230,4 +230,4 @@ class ReplyTile extends React.Component { } } -module.exports = ReplyTile; +export default ReplyTile; From e64ff0f099ac6660e596fc640a839c9f76f9f79b Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Fri, 10 Apr 2020 14:39:16 +0300 Subject: [PATCH 04/90] Change score color to match sender name --- res/css/views/elements/_ReplyThread.scss | 32 ++++++++++++++++++++ src/components/views/elements/ReplyThread.js | 9 ++++-- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/res/css/views/elements/_ReplyThread.scss b/res/css/views/elements/_ReplyThread.scss index 0d53a6b6f43..d5388e46310 100644 --- a/res/css/views/elements/_ReplyThread.scss +++ b/res/css/views/elements/_ReplyThread.scss @@ -27,4 +27,36 @@ blockquote.mx_ReplyThread { margin-bottom: 8px; padding-left: 10px; border-left: 4px solid $button-bg-color; + + &.mx_ReplyThread_color1 { + border-left-color: $username-variant1-color; + } + + &.mx_ReplyThread_color2 { + border-left-color: $username-variant2-color; + } + + &.mx_ReplyThread_color3 { + border-left-color: $username-variant3-color; + } + + &.mx_ReplyThread_color4 { + border-left-color: $username-variant4-color; + } + + &.mx_ReplyThread_color5 { + border-left-color: $username-variant5-color; + } + + &.mx_ReplyThread_color6 { + border-left-color: $username-variant6-color; + } + + &.mx_ReplyThread_color7 { + border-left-color: $username-variant7-color; + } + + &.mx_ReplyThread_color8 { + border-left-color: $username-variant8-color; + } } diff --git a/src/components/views/elements/ReplyThread.js b/src/components/views/elements/ReplyThread.js index 976b3a88150..92e87ad945e 100644 --- a/src/components/views/elements/ReplyThread.js +++ b/src/components/views/elements/ReplyThread.js @@ -25,6 +25,7 @@ import {makeUserPermalink, RoomPermalinkCreator} from "../../../utils/permalinks import SettingsStore from "../../../settings/SettingsStore"; import escapeHtml from "escape-html"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; +import { getUserNameColorClass } from "../../../utils/FormattingUtils" // 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 @@ -285,6 +286,10 @@ export default class ReplyThread extends React.Component { dis.dispatch({action: 'focus_composer'}); } + getReplyThreadColorClass(ev) { + return getUserNameColorClass(ev.getSender()).replace("Username", "ReplyThread"); + } + render() { let header = null; @@ -299,7 +304,7 @@ export default class ReplyThread extends React.Component { const ev = this.state.loadedEv; const Pill = sdk.getComponent('elements.Pill'); const room = this.context.getRoom(ev.getRoomId()); - header =
+ header =
{ _t('In reply to ', {}, { 'a': (sub) => { sub }, @@ -315,7 +320,7 @@ export default class ReplyThread extends React.Component { const ReplyTile = sdk.getComponent('views.rooms.ReplyTile'); const evTiles = this.state.events.map((ev) => { - return
+ return
Date: Fri, 10 Apr 2020 14:52:24 +0300 Subject: [PATCH 05/90] Add missing semicolon --- src/components/views/elements/ReplyThread.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/elements/ReplyThread.js b/src/components/views/elements/ReplyThread.js index 92e87ad945e..770f95f9dc1 100644 --- a/src/components/views/elements/ReplyThread.js +++ b/src/components/views/elements/ReplyThread.js @@ -25,7 +25,7 @@ import {makeUserPermalink, RoomPermalinkCreator} from "../../../utils/permalinks import SettingsStore from "../../../settings/SettingsStore"; import escapeHtml from "escape-html"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; -import { getUserNameColorClass } from "../../../utils/FormattingUtils" +import { getUserNameColorClass } from "../../../utils/FormattingUtils"; // 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 From 25af26323c3ca9048ab7a45d63ed74116e553aa8 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Fri, 10 Apr 2020 15:45:59 +0300 Subject: [PATCH 06/90] Make image reply rendering even more compact --- res/css/_components.scss | 1 + res/css/views/messages/_MImageReplyBody.scss | 35 +++++++++++++++++++ .../views/messages/MImageReplyBody.js | 31 ++++++++++++++-- src/components/views/rooms/ReplyTile.js | 2 +- 4 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 res/css/views/messages/_MImageReplyBody.scss diff --git a/res/css/_components.scss b/res/css/_components.scss index 607257400b8..2d701bb1e13 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -130,6 +130,7 @@ @import "./views/messages/_MEmoteBody.scss"; @import "./views/messages/_MFileBody.scss"; @import "./views/messages/_MImageBody.scss"; +@import "./views/messages/_MImageReplyBody.scss"; @import "./views/messages/_MNoticeBody.scss"; @import "./views/messages/_MStickerBody.scss"; @import "./views/messages/_MTextBody.scss"; diff --git a/res/css/views/messages/_MImageReplyBody.scss b/res/css/views/messages/_MImageReplyBody.scss new file mode 100644 index 00000000000..8169e027d12 --- /dev/null +++ b/res/css/views/messages/_MImageReplyBody.scss @@ -0,0 +1,35 @@ +/* +Copyright 2020 Tulir Asokan + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +.mx_MImageReplyBody { + display: grid; + grid-template: "image sender" 20px + "image filename" 20px + / 44px auto; + grid-gap: 4px; +} + +.mx_MImageReplyBody_thumbnail { + grid-area: image; +} + +.mx_MImageReplyBody_sender { + grid-area: sender; +} + +.mx_MImageReplyBody_filename { + grid-area: filename; +} diff --git a/src/components/views/messages/MImageReplyBody.js b/src/components/views/messages/MImageReplyBody.js index 31b4d1fa82c..cdc78e46e86 100644 --- a/src/components/views/messages/MImageReplyBody.js +++ b/src/components/views/messages/MImageReplyBody.js @@ -1,5 +1,5 @@ /* -Copyright 2019 Tulir Asokan +Copyright 2020 Tulir Asokan Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,7 +14,11 @@ See the License for the specific language governing permissions and limitations under the License. */ +import React from "react"; +import { _td } from "../../../languageHandler"; +import * as sdk from "../../../index"; import MImageBody from './MImageBody'; +import MFileBody from "./MFileBody"; export default class MImageReplyBody extends MImageBody { onClick(ev) { @@ -27,6 +31,29 @@ export default class MImageReplyBody extends MImageBody { // Don't show "Download this_file.png ..." getFileBody() { - return null; + return MFileBody.prototype.presentableTextForFile.call(this, this.props.mxEvent.getContent()); + } + + render() { + if (this.state.error !== null) { + return super.render(); + } + + const content = this.props.mxEvent.getContent(); + + const contentUrl = this._getContentUrl(); + const thumbnail = this._messageContent(contentUrl, this._getThumbUrl(), content); + const fileBody = this.getFileBody(); + const SenderProfile = sdk.getComponent('messages.SenderProfile'); + const sender = ; + + return
+
{ thumbnail }
+
{ sender }
+
{ fileBody }
+
; } } diff --git a/src/components/views/rooms/ReplyTile.js b/src/components/views/rooms/ReplyTile.js index 3ad6962f1a5..ca349baac2d 100644 --- a/src/components/views/rooms/ReplyTile.js +++ b/src/components/views/rooms/ReplyTile.js @@ -184,7 +184,7 @@ class ReplyTile extends React.Component { } let sender; - const needsSenderProfile = tileHandler !== 'messages.RoomCreate' && !isInfoMessage; + const needsSenderProfile = msgtype !== 'm.image' && tileHandler !== 'messages.RoomCreate' && !isInfoMessage; if (needsSenderProfile) { let text = null; From ec7acd1c0fbaf5d96415f380a3b85b54d079aa9f Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Fri, 10 Apr 2020 15:56:09 +0300 Subject: [PATCH 07/90] Fix rendering reply after event is decrypted --- src/components/views/rooms/ReplyTile.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/views/rooms/ReplyTile.js b/src/components/views/rooms/ReplyTile.js index ca349baac2d..34b2c6ad38a 100644 --- a/src/components/views/rooms/ReplyTile.js +++ b/src/components/views/rooms/ReplyTile.js @@ -82,6 +82,7 @@ class ReplyTile extends React.Component { super(props, context); this.state = {}; this.onClick = this.onClick.bind(this); + this._onDecrypted = this._onDecrypted.bind(this); } componentDidMount() { @@ -102,6 +103,9 @@ class ReplyTile extends React.Component { _onDecrypted() { this.forceUpdate(); + if (this.props.onHeightChanged) { + this.props.onHeightChanged(); + } } _propsEqual(objA, objB) { From da3bd5ebee68dc15f04e15c3b55183f769413ce9 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Fri, 10 Apr 2020 16:03:27 +0300 Subject: [PATCH 08/90] Disable pointer events inside replies --- res/css/views/rooms/_ReplyTile.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/res/css/views/rooms/_ReplyTile.scss b/res/css/views/rooms/_ReplyTile.scss index 0a055297c6a..a6cff00ff24 100644 --- a/res/css/views/rooms/_ReplyTile.scss +++ b/res/css/views/rooms/_ReplyTile.scss @@ -35,6 +35,8 @@ limitations under the License. $reply-lines: 2; $line-height: 22px; + pointer-events: none; + text-overflow: ellipsis; display: -webkit-box; -webkit-box-orient: vertical; From 6b96a161087f4cda8ab6dcafd155e2d689a5adff Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Fri, 10 Apr 2020 16:18:06 +0300 Subject: [PATCH 09/90] Add absolute max height and some improvements for
 replies

---
 res/css/views/rooms/_ReplyTile.scss | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/res/css/views/rooms/_ReplyTile.scss b/res/css/views/rooms/_ReplyTile.scss
index a6cff00ff24..70a383a1cf6 100644
--- a/res/css/views/rooms/_ReplyTile.scss
+++ b/res/css/views/rooms/_ReplyTile.scss
@@ -34,6 +34,7 @@ limitations under the License.
 .mx_ReplyTile .mx_EventTile_content {
     $reply-lines: 2;
     $line-height: 22px;
+    $max-height: 66px;
 
     pointer-events: none;
 
@@ -42,12 +43,26 @@ limitations under the License.
     -webkit-box-orient: vertical;
     -webkit-line-clamp: $reply-lines;
     line-height: $line-height;
+    max-height: $max-height;
 
     .mx_EventTile_body.mx_EventTile_bigEmoji {
         line-height: $line-height !important;
         // Override the big emoji override
         font-size: 14px !important;
     }
+
+    // Hack to cut content in 
 tags too
+    .mx_EventTile_pre_container > pre {
+        overflow: hidden;
+        text-overflow: ellipsis;
+        display: -webkit-box;
+        -webkit-box-orient: vertical;
+        -webkit-line-clamp: $reply-lines;
+        padding: 4px;
+    }
+    .markdown-body blockquote, .markdown-body dl, .markdown-body ol, .markdown-body p, .markdown-body pre, .markdown-body table, .markdown-body ul {
+        margin-bottom: 4px;
+    }
 }
 
 .mx_ReplyTile.mx_ReplyTile_info {

From e7ad9b82e0f42e6c7ac5511ade135e71a273e414 Mon Sep 17 00:00:00 2001
From: Tulir Asokan 
Date: Fri, 10 Apr 2020 16:27:39 +0300
Subject: [PATCH 10/90] Fix stylelint issue and update header

---
 res/css/views/messages/_MImageReplyBody.scss | 7 ++++---
 res/css/views/rooms/_ReplyTile.scss          | 2 +-
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/res/css/views/messages/_MImageReplyBody.scss b/res/css/views/messages/_MImageReplyBody.scss
index 8169e027d12..9b25b4392a6 100644
--- a/res/css/views/messages/_MImageReplyBody.scss
+++ b/res/css/views/messages/_MImageReplyBody.scss
@@ -16,9 +16,10 @@ limitations under the License.
 
 .mx_MImageReplyBody {
     display: grid;
-    grid-template: "image sender"   20px
-                   "image filename" 20px
-                  / 44px  auto;
+    grid-template:
+        "image sender"   20px
+        "image filename" 20px
+        / 44px  auto;
     grid-gap: 4px;
 }
 
diff --git a/res/css/views/rooms/_ReplyTile.scss b/res/css/views/rooms/_ReplyTile.scss
index 70a383a1cf6..fd684301579 100644
--- a/res/css/views/rooms/_ReplyTile.scss
+++ b/res/css/views/rooms/_ReplyTile.scss
@@ -1,5 +1,5 @@
 /*
-Copyright 2019 Tulir Asokan 
+Copyright 2020 Tulir Asokan 
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.

From b554d59ed165d68b56a9b08faadeec86d2f7c2b7 Mon Sep 17 00:00:00 2001
From: Tulir Asokan 
Date: Fri, 10 Apr 2020 17:05:29 +0300
Subject: [PATCH 11/90] Prevent reply thumbnail image from overflowing

---
 res/css/views/messages/_MImageReplyBody.scss | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/res/css/views/messages/_MImageReplyBody.scss b/res/css/views/messages/_MImageReplyBody.scss
index 9b25b4392a6..8c5cb97478d 100644
--- a/res/css/views/messages/_MImageReplyBody.scss
+++ b/res/css/views/messages/_MImageReplyBody.scss
@@ -25,6 +25,10 @@ limitations under the License.
 
 .mx_MImageReplyBody_thumbnail {
     grid-area: image;
+
+    .mx_MImageBody_thumbnail_container {
+        max-height: 44px !important;
+    }
 }
 
 .mx_MImageReplyBody_sender {

From dfe277b78d1e7fe39fe91245646b41d72bb367fc Mon Sep 17 00:00:00 2001
From: Tulir Asokan 
Date: Mon, 25 May 2020 19:24:03 +0300
Subject: [PATCH 12/90] Remove unnecessary right margin in reply blockquote

---
 res/css/views/elements/_ReplyThread.scss | 1 +
 1 file changed, 1 insertion(+)

diff --git a/res/css/views/elements/_ReplyThread.scss b/res/css/views/elements/_ReplyThread.scss
index d5388e46310..af8ca956ba7 100644
--- a/res/css/views/elements/_ReplyThread.scss
+++ b/res/css/views/elements/_ReplyThread.scss
@@ -24,6 +24,7 @@ limitations under the License.
 
 blockquote.mx_ReplyThread {
     margin-left: 0;
+    margin-right: 0;
     margin-bottom: 8px;
     padding-left: 10px;
     border-left: 4px solid $button-bg-color;

From c60483728fc8526538e43c1a27834c85d8c1984c Mon Sep 17 00:00:00 2001
From: Tulir Asokan 
Date: Mon, 25 May 2020 19:33:30 +0300
Subject: [PATCH 13/90] Fix dispatcher import in ReplyTile.js

---
 src/components/views/rooms/ReplyTile.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/views/rooms/ReplyTile.js b/src/components/views/rooms/ReplyTile.js
index 34b2c6ad38a..f6c4a69deff 100644
--- a/src/components/views/rooms/ReplyTile.js
+++ b/src/components/views/rooms/ReplyTile.js
@@ -21,7 +21,7 @@ import { _t, _td } from '../../../languageHandler';
 
 import * as sdk from '../../../index';
 
-import dis from '../../../dispatcher';
+import dis from '../../../dispatcher/dispatcher';
 import SettingsStore from "../../../settings/SettingsStore";
 import {MatrixClient} from 'matrix-js-sdk';
 

From cdf8f09ec256f8bd69e478ffc11ad26ff883c398 Mon Sep 17 00:00:00 2001
From: Tulir Asokan 
Date: Sat, 20 Mar 2021 13:38:42 +0200
Subject: [PATCH 14/90] Remove unused import and run yarn i18n

---
 src/components/views/elements/ReplyThread.js | 1 -
 src/i18n/strings/en_EN.json                  | 3 +++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/components/views/elements/ReplyThread.js b/src/components/views/elements/ReplyThread.js
index eb29e524965..4129f1d14f7 100644
--- a/src/components/views/elements/ReplyThread.js
+++ b/src/components/views/elements/ReplyThread.js
@@ -20,7 +20,6 @@ import * as sdk from '../../../index';
 import {_t} from '../../../languageHandler';
 import PropTypes from 'prop-types';
 import dis from '../../../dispatcher/dispatcher';
-import {wantsDateSeparator} from '../../../DateUtils';
 import {MatrixEvent} from 'matrix-js-sdk/src/models/event';
 import {makeUserPermalink, RoomPermalinkCreator} from "../../../utils/permalinks/Permalinks";
 import SettingsStore from "../../../settings/SettingsStore";
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json
index 63b19831bbb..66b1843e645 100644
--- a/src/i18n/strings/en_EN.json
+++ b/src/i18n/strings/en_EN.json
@@ -1500,6 +1500,9 @@
     "Seen by %(userName)s at %(dateTime)s": "Seen by %(userName)s at %(dateTime)s",
     "Seen by %(displayName)s (%(userName)s) at %(dateTime)s": "Seen by %(displayName)s (%(userName)s) at %(dateTime)s",
     "Replying": "Replying",
+    "%(senderName)s sent an image": "%(senderName)s sent an image",
+    "%(senderName)s sent a video": "%(senderName)s sent a video",
+    "%(senderName)s uploaded a file": "%(senderName)s uploaded a file",
     "Room %(name)s": "Room %(name)s",
     "Recently visited rooms": "Recently visited rooms",
     "No recently visited rooms": "No recently visited rooms",

From 330f222dd1a9df7aafe4488110be747d03fc5515 Mon Sep 17 00:00:00 2001
From: Tulir Asokan 
Date: Sat, 1 May 2021 16:11:30 +0300
Subject: [PATCH 15/90] Remove redundant code and move presentableTextForFile
 out of MFileBody

Signed-off-by: Tulir Asokan 
---
 src/components/views/messages/MFileBody.js    | 62 +++++++++---------
 .../views/messages/MImageReplyBody.js         | 24 +++----
 src/components/views/rooms/EventTile.tsx      | 37 +----------
 src/components/views/rooms/ReplyPreview.js    |  8 ++-
 src/components/views/rooms/ReplyTile.js       | 64 ++-----------------
 5 files changed, 55 insertions(+), 140 deletions(-)

diff --git a/src/components/views/messages/MFileBody.js b/src/components/views/messages/MFileBody.js
index 8f464e08bde..5be4468a286 100644
--- a/src/components/views/messages/MFileBody.js
+++ b/src/components/views/messages/MFileBody.js
@@ -89,6 +89,35 @@ function computedStyle(element) {
     return cssText;
 }
 
+/**
+ * Extracts a human readable label for the file attachment to use as
+ * link text.
+ *
+ * @param {Object} content The "content" key of the matrix event.
+ * @param {boolean} withSize Whether to include size information. Default true.
+ * @return {string} the human readable link text for the attachment.
+ */
+export function presentableTextForFile(content, withSize = true) {
+    let linkText = _t("Attachment");
+    if (content.body && content.body.length > 0) {
+        // The content body should be the name of the file including a
+        // file extension.
+        linkText = content.body;
+    }
+
+    if (content.info && content.info.size && withSize) {
+        // If we know the size of the file then add it as human readable
+        // string to the end of the link text so that the user knows how
+        // big a file they are downloading.
+        // The content.info also contains a MIME-type but we don't display
+        // it since it is "ugly", users generally aren't aware what it
+        // means and the type of the attachment can usually be inferrered
+        // from the file extension.
+        linkText += ' (' + filesize(content.info.size) + ')';
+    }
+    return linkText;
+}
+
 @replaceableComponent("views.messages.MFileBody")
 export default class MFileBody extends React.Component {
     static propTypes = {
@@ -119,35 +148,6 @@ export default class MFileBody extends React.Component {
         this._dummyLink = createRef();
     }
 
-    /**
-     * Extracts a human readable label for the file attachment to use as
-     * link text.
-     *
-     * @param {Object} content The "content" key of the matrix event.
-     * @param {boolean} withSize Whether to include size information. Default true.
-     * @return {string} the human readable link text for the attachment.
-     */
-    presentableTextForFile(content, withSize = true) {
-        let linkText = _t("Attachment");
-        if (content.body && content.body.length > 0) {
-            // The content body should be the name of the file including a
-            // file extension.
-            linkText = content.body;
-        }
-
-        if (content.info && content.info.size && withSize) {
-            // If we know the size of the file then add it as human readable
-            // string to the end of the link text so that the user knows how
-            // big a file they are downloading.
-            // The content.info also contains a MIME-type but we don't display
-            // it since it is "ugly", users generally aren't aware what it
-            // means and the type of the attachment can usually be inferrered
-            // from the file extension.
-            linkText += ' (' + filesize(content.info.size) + ')';
-        }
-        return linkText;
-    }
-
     _getContentUrl() {
         const media = mediaFromContent(this.props.mxEvent.getContent());
         return media.srcHttp;
@@ -161,7 +161,7 @@ export default class MFileBody extends React.Component {
 
     render() {
         const content = this.props.mxEvent.getContent();
-        const text = this.presentableTextForFile(content);
+        const text = presentableTextForFile(content);
         const isEncrypted = content.file !== undefined;
         const fileName = content.body && content.body.length > 0 ? content.body : _t("Attachment");
         const contentUrl = this._getContentUrl();
@@ -173,7 +173,7 @@ export default class MFileBody extends React.Component {
             placeholder = (
                 
- {this.presentableTextForFile(content, false)} + {presentableTextForFile(content, false)}
); } diff --git a/src/components/views/messages/MImageReplyBody.js b/src/components/views/messages/MImageReplyBody.js index cdc78e46e86..5ace22a560a 100644 --- a/src/components/views/messages/MImageReplyBody.js +++ b/src/components/views/messages/MImageReplyBody.js @@ -1,5 +1,5 @@ /* -Copyright 2020 Tulir Asokan +Copyright 2020-2021 Tulir Asokan Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -15,10 +15,10 @@ limitations under the License. */ import React from "react"; -import { _td } from "../../../languageHandler"; +import {_td} from "../../../languageHandler"; import * as sdk from "../../../index"; import MImageBody from './MImageBody'; -import MFileBody from "./MFileBody"; +import {presentableTextForFile} from "./MFileBody"; export default class MImageReplyBody extends MImageBody { onClick(ev) { @@ -31,7 +31,7 @@ export default class MImageReplyBody extends MImageBody { // Don't show "Download this_file.png ..." getFileBody() { - return MFileBody.prototype.presentableTextForFile.call(this, this.props.mxEvent.getContent()); + return presentableTextForFile(this.props.mxEvent.getContent()); } render() { @@ -45,15 +45,17 @@ export default class MImageReplyBody extends MImageBody { const thumbnail = this._messageContent(contentUrl, this._getThumbUrl(), content); const fileBody = this.getFileBody(); const SenderProfile = sdk.getComponent('messages.SenderProfile'); - const sender = ; + const sender = ; return
-
{ thumbnail }
-
{ sender }
-
{ fileBody }
+
{thumbnail}
+
{sender}
+
{fileBody}
; } } diff --git a/src/components/views/rooms/EventTile.tsx b/src/components/views/rooms/EventTile.tsx index 19c5a7acaa9..4411f94f025 100644 --- a/src/components/views/rooms/EventTile.tsx +++ b/src/components/views/rooms/EventTile.tsx @@ -247,7 +247,7 @@ interface IProps { // It could also be done by subclassing EventTile, but that'd be quite // boiilerplatey. So just make the necessary render decisions conditional // for now. - tileShape?: 'notif' | 'file_grid' | 'reply' | 'reply_preview'; + tileShape?: 'notif' | 'file_grid'; // show twelve hour timestamps isTwelveHour?: boolean; @@ -940,7 +940,7 @@ export default class EventTile extends React.Component { } if (needsSenderProfile) { - if (!this.props.tileShape || this.props.tileShape === 'reply' || this.props.tileShape === 'reply_preview') { + if (!this.props.tileShape) { sender = { ); } - case 'reply': - case 'reply_preview': { - let thread; - if (this.props.tileShape === 'reply_preview') { - thread = ReplyThread.makeThread( - this.props.mxEvent, - this.props.onHeightChanged, - this.props.permalinkCreator, - this.replyThread, - ); - } - return ( -
- { ircTimestamp } - { avatar } - { sender } - { ircPadlock } -
- { groupTimestamp } - { groupPadlock } - { thread } - -
-
- ); - } default: { const thread = ReplyThread.makeThread( this.props.mxEvent, diff --git a/src/components/views/rooms/ReplyPreview.js b/src/components/views/rooms/ReplyPreview.js index 56a6609cc72..222fcea5524 100644 --- a/src/components/views/rooms/ReplyPreview.js +++ b/src/components/views/rooms/ReplyPreview.js @@ -87,9 +87,11 @@ export default class ReplyPreview extends React.Component {
- +
; diff --git a/src/components/views/rooms/ReplyTile.js b/src/components/views/rooms/ReplyTile.js index 95503493f74..336c5a721ba 100644 --- a/src/components/views/rooms/ReplyTile.js +++ b/src/components/views/rooms/ReplyTile.js @@ -1,5 +1,5 @@ /* -Copyright 2020 Tulir Asokan +Copyright 2020-2021 Tulir Asokan Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -25,42 +25,8 @@ import dis from '../../../dispatcher/dispatcher'; import SettingsStore from "../../../settings/SettingsStore"; import {MatrixClient} from 'matrix-js-sdk'; -import { objectHasDiff } from '../../../utils/objects'; - -const eventTileTypes = { - 'm.room.message': 'messages.MessageEvent', - 'm.sticker': 'messages.MessageEvent', - 'm.call.invite': 'messages.TextualEvent', - 'm.call.answer': 'messages.TextualEvent', - 'm.call.hangup': 'messages.TextualEvent', -}; - -const stateEventTileTypes = { - 'm.room.aliases': 'messages.TextualEvent', - // 'm.room.aliases': 'messages.RoomAliasesEvent', // too complex - 'm.room.canonical_alias': 'messages.TextualEvent', - 'm.room.create': 'messages.RoomCreate', - 'm.room.member': 'messages.TextualEvent', - 'm.room.name': 'messages.TextualEvent', - 'm.room.avatar': 'messages.RoomAvatarEvent', - 'm.room.third_party_invite': 'messages.TextualEvent', - 'm.room.history_visibility': 'messages.TextualEvent', - 'm.room.encryption': 'messages.TextualEvent', - 'm.room.topic': 'messages.TextualEvent', - 'm.room.power_levels': 'messages.TextualEvent', - 'm.room.pinned_events': 'messages.TextualEvent', - 'm.room.server_acl': 'messages.TextualEvent', - 'im.vector.modular.widgets': 'messages.TextualEvent', - 'm.room.tombstone': 'messages.TextualEvent', - 'm.room.join_rules': 'messages.TextualEvent', - 'm.room.guest_access': 'messages.TextualEvent', - 'm.room.related_groups': 'messages.TextualEvent', -}; - -function getHandlerTile(ev) { - const type = ev.getType(); - return ev.isState() ? stateEventTileTypes[type] : eventTileTypes[type]; -} +import {objectHasDiff} from '../../../utils/objects'; +import {getHandlerTile} from "./EventTile"; class ReplyTile extends React.Component { static contextTypes = { @@ -94,7 +60,7 @@ class ReplyTile extends React.Component { return true; } - return !this._propsEqual(this.props, nextProps); + return objectHasDiff(this.props, nextProps); } componentWillUnmount() { @@ -108,28 +74,6 @@ class ReplyTile extends React.Component { } } - _propsEqual(objA, objB) { - const keysA = Object.keys(objA); - const keysB = Object.keys(objB); - - if (keysA.length !== keysB.length) { - return false; - } - - for (let i = 0; i < keysA.length; i++) { - const key = keysA[i]; - - if (!objB.hasOwnProperty(key)) { - return false; - } - - if (objA[key] !== objB[key]) { - return false; - } - } - return true; - } - onClick(e) { // This allows the permalink to be opened in a new tab/window or copied as // matrix.to, but also for it to enable routing within Riot when clicked. From 9f66bd0f652f0aeee604471a1509c9f9b6af37fc Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Tue, 15 Jun 2021 17:48:16 +0300 Subject: [PATCH 16/90] Remove extra space --- src/components/views/rooms/ReplyPreview.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/ReplyPreview.js b/src/components/views/rooms/ReplyPreview.js index 3cd88902ce1..222fcea5524 100644 --- a/src/components/views/rooms/ReplyPreview.js +++ b/src/components/views/rooms/ReplyPreview.js @@ -89,7 +89,7 @@ export default class ReplyPreview extends React.Component {
From 598689b059196c47e1d1455c823383fd062807c4 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Fri, 2 Jul 2021 12:56:08 +0300 Subject: [PATCH 17/90] Run eslint --- src/components/views/messages/MImageReplyBody.js | 4 ++-- src/components/views/rooms/ReplyTile.js | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/views/messages/MImageReplyBody.js b/src/components/views/messages/MImageReplyBody.js index 5ace22a560a..2ed7a637bd2 100644 --- a/src/components/views/messages/MImageReplyBody.js +++ b/src/components/views/messages/MImageReplyBody.js @@ -15,10 +15,10 @@ limitations under the License. */ import React from "react"; -import {_td} from "../../../languageHandler"; +import { _td } from "../../../languageHandler"; import * as sdk from "../../../index"; import MImageBody from './MImageBody'; -import {presentableTextForFile} from "./MFileBody"; +import { presentableTextForFile } from "./MFileBody"; export default class MImageReplyBody extends MImageBody { onClick(ev) { diff --git a/src/components/views/rooms/ReplyTile.js b/src/components/views/rooms/ReplyTile.js index 336c5a721ba..23dcdc21a36 100644 --- a/src/components/views/rooms/ReplyTile.js +++ b/src/components/views/rooms/ReplyTile.js @@ -23,10 +23,10 @@ import * as sdk from '../../../index'; import dis from '../../../dispatcher/dispatcher'; import SettingsStore from "../../../settings/SettingsStore"; -import {MatrixClient} from 'matrix-js-sdk'; +import { MatrixClient } from 'matrix-js-sdk'; -import {objectHasDiff} from '../../../utils/objects'; -import {getHandlerTile} from "./EventTile"; +import { objectHasDiff } from '../../../utils/objects'; +import { getHandlerTile } from "./EventTile"; class ReplyTile extends React.Component { static contextTypes = { @@ -112,7 +112,7 @@ class ReplyTile extends React.Component { // This shouldn't happen: the caller should check we support this type // before trying to instantiate us if (!tileHandler) { - const {mxEvent} = this.props; + const { mxEvent } = this.props; console.warn(`Event type not supported: type:${mxEvent.getType()} isState:${mxEvent.isState()}`); return
{ _t('This event could not be displayed') } From 38710eab88e4fb8a55948d431319982ba9a733df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 2 Jul 2021 13:31:56 +0200 Subject: [PATCH 18/90] Export IProps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/elements/ImageView.tsx | 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 2628170f9c1..985160019ea 100644 --- a/src/components/views/elements/ImageView.tsx +++ b/src/components/views/elements/ImageView.tsx @@ -43,14 +43,14 @@ const ZOOM_COEFFICIENT = 0.0025; // If we have moved only this much we can zoom const ZOOM_DISTANCE = 10; -interface IProps { +export interface IProps { src: string; // the source of the image being displayed name?: string; // the main title ('name') for the image link?: string; // the link (if any) applied to the name of the image width?: number; // width of the image src in pixels height?: number; // height of the image src in pixels fileSize?: number; // size of the image src in bytes - onFinished(): void; // callback when the lightbox is dismissed + onFinished?(): void; // callback when the lightbox is dismissed // the event (if any) that the Image is displaying. Used for event-specific stuff like // redactions, senders, timestamps etc. Other descriptors are taken from the explicit From 869f31deef3a917b653ce36b4a24efd3d1bc7ed6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 2 Jul 2021 13:46:42 +0200 Subject: [PATCH 19/90] Convert MImageBody to TS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- .../{MImageBody.js => MImageBody.tsx} | 178 +++++++++--------- 1 file changed, 92 insertions(+), 86 deletions(-) rename src/components/views/messages/{MImageBody.js => MImageBody.tsx} (80%) diff --git a/src/components/views/messages/MImageBody.js b/src/components/views/messages/MImageBody.tsx similarity index 80% rename from src/components/views/messages/MImageBody.js rename to src/components/views/messages/MImageBody.tsx index 5566f5aec0a..c2553b51a38 100644 --- a/src/components/views/messages/MImageBody.js +++ b/src/components/views/messages/MImageBody.tsx @@ -17,8 +17,6 @@ limitations under the License. */ import React, { createRef } from 'react'; -import PropTypes from 'prop-types'; - import MFileBody from './MFileBody'; import Modal from '../../../Modal'; import * as sdk from '../../../index'; @@ -31,36 +29,48 @@ import { replaceableComponent } from "../../../utils/replaceableComponent"; import { mediaFromContent } from "../../../customisations/Media"; import BlurhashPlaceholder from "../elements/BlurhashPlaceholder"; import { BLURHASH_FIELD } from "../../../ContentMessages"; +import { MatrixEvent } from 'matrix-js-sdk/src/models/event'; +import { RoomPermalinkCreator } from '../../../utils/permalinks/Permalinks'; +import { IMediaEventContent } from '../../../customisations/models/IMediaEventContent'; +import { IProps as ImageViewIProps } from "../elements/ImageView"; + +export interface IProps { + /* the MatrixEvent to show */ + mxEvent: MatrixEvent, + /* called when the image has loaded */ + onHeightChanged(): void, + + /* the maximum image height to use */ + maxImageHeight?: number, + + /* the permalinkCreator */ + permalinkCreator?: RoomPermalinkCreator, +} -@replaceableComponent("views.messages.MImageBody") -export default class MImageBody extends React.Component { - static propTypes = { - /* the MatrixEvent to show */ - mxEvent: PropTypes.object.isRequired, - - /* called when the image has loaded */ - onHeightChanged: PropTypes.func.isRequired, - - /* the maximum image height to use */ - maxImageHeight: PropTypes.number, - - /* the permalinkCreator */ - permalinkCreator: PropTypes.object, - }; +interface IState { + decryptedUrl?: string, + decryptedThumbnailUrl?: string, + decryptedBlob?: Blob, + error, + imgError: boolean, + imgLoaded: boolean, + loadedImageDimensions?: { + naturalWidth: number; + naturalHeight: number; + }, + hover: boolean, + showImage: boolean, +} +@replaceableComponent("views.messages.MImageBody") +export default class MImageBody extends React.Component { static contextType = MatrixClientContext; + private unmounted = true; + private image = createRef(); - constructor(props) { + constructor(props: IProps) { super(props); - this.onImageError = this.onImageError.bind(this); - this.onImageLoad = this.onImageLoad.bind(this); - this.onImageEnter = this.onImageEnter.bind(this); - this.onImageLeave = this.onImageLeave.bind(this); - this.onClientSync = this.onClientSync.bind(this); - this.onClick = this.onClick.bind(this); - this._isGif = this._isGif.bind(this); - this.state = { decryptedUrl: null, decryptedThumbnailUrl: null, @@ -72,12 +82,10 @@ export default class MImageBody extends React.Component { hover: false, showImage: SettingsStore.getValue("showImages"), }; - - this._image = createRef(); } // FIXME: factor this out and apply it to MVideoBody and MAudioBody too! - onClientSync(syncState, prevState) { + private onClientSync = (syncState, prevState): void => { if (this.unmounted) return; // Consider the client reconnected if there is no error with syncing. // This means the state could be RECONNECTING, SYNCING, PREPARED or CATCHUP. @@ -88,15 +96,15 @@ export default class MImageBody extends React.Component { imgError: false, }); } - } + }; - showImage() { + protected showImage(): void { localStorage.setItem("mx_ShowImage_" + this.props.mxEvent.getId(), "true"); this.setState({ showImage: true }); - this._downloadImage(); + this.downloadImage(); } - onClick(ev) { + protected onClick = (ev: React.MouseEvent): void => { if (ev.button === 0 && !ev.metaKey) { ev.preventDefault(); if (!this.state.showImage) { @@ -104,12 +112,12 @@ export default class MImageBody extends React.Component { return; } - const content = this.props.mxEvent.getContent(); - const httpUrl = this._getContentUrl(); + const content = this.props.mxEvent.getContent() as IMediaEventContent; + const httpUrl = this.getContentUrl(); const ImageView = sdk.getComponent("elements.ImageView"); - const params = { + const params: ImageViewIProps = { src: httpUrl, - name: content.body && content.body.length > 0 ? content.body : _t('Attachment'), + name: content.body?.length > 0 ? content.body : _t('Attachment'), mxEvent: this.props.mxEvent, permalinkCreator: this.props.permalinkCreator, }; @@ -122,58 +130,54 @@ export default class MImageBody extends React.Component { Modal.createDialog(ImageView, params, "mx_Dialog_lightbox", null, true); } - } + }; - _isGif() { + private isGif = (): boolean => { const content = this.props.mxEvent.getContent(); - return ( - content && - content.info && - content.info.mimetype === "image/gif" - ); - } + return content?.info?.mimetype === "image/gif"; + }; - onImageEnter(e) { + private onImageEnter = (e: React.MouseEvent): void => { this.setState({ hover: true }); - if (!this.state.showImage || !this._isGif() || SettingsStore.getValue("autoplayGifsAndVideos")) { + if (!this.state.showImage || !this.isGif() || SettingsStore.getValue("autoplayGifsAndVideos")) { return; } - const imgElement = e.target; - imgElement.src = this._getContentUrl(); - } + const imgElement = e.target as HTMLImageElement; + imgElement.src = this.getContentUrl(); + }; - onImageLeave(e) { + private onImageLeave = (e: React.MouseEvent): void => { this.setState({ hover: false }); - if (!this.state.showImage || !this._isGif() || SettingsStore.getValue("autoplayGifsAndVideos")) { + if (!this.state.showImage || !this.isGif() || SettingsStore.getValue("autoplayGifsAndVideos")) { return; } - const imgElement = e.target; - imgElement.src = this._getThumbUrl(); - } + const imgElement = e.target as HTMLImageElement; + imgElement.src = this.getThumbUrl(); + }; - onImageError() { + private onImageError = (): void => { this.setState({ imgError: true, }); - } + }; - onImageLoad() { + private onImageLoad = (): void => { this.props.onHeightChanged(); let loadedImageDimensions; - if (this._image.current) { - const { naturalWidth, naturalHeight } = this._image.current; + if (this.image.current) { + const { naturalWidth, naturalHeight } = this.image.current; // this is only used as a fallback in case content.info.w/h is missing loadedImageDimensions = { naturalWidth, naturalHeight }; } this.setState({ imgLoaded: true, loadedImageDimensions }); - } + }; - _getContentUrl() { + protected getContentUrl(): string { const media = mediaFromContent(this.props.mxEvent.getContent()); if (media.isEncrypted) { return this.state.decryptedUrl; @@ -182,7 +186,7 @@ export default class MImageBody extends React.Component { } } - _getThumbUrl() { + protected getThumbUrl(): string { // FIXME: we let images grow as wide as you like, rather than capped to 800x600. // So either we need to support custom timeline widths here, or reimpose the cap, otherwise the // thumbnail resolution will be unnecessarily reduced. @@ -190,7 +194,7 @@ export default class MImageBody extends React.Component { const thumbWidth = 800; const thumbHeight = 600; - const content = this.props.mxEvent.getContent(); + const content = this.props.mxEvent.getContent() as IMediaEventContent; const media = mediaFromContent(content); if (media.isEncrypted) { @@ -218,7 +222,7 @@ export default class MImageBody extends React.Component { // - If there's no sizing info in the event, default to thumbnail const info = content.info; if ( - this._isGif() || + this.isGif() || window.devicePixelRatio === 1.0 || (!info || !info.w || !info.h || !info.size) ) { @@ -253,7 +257,7 @@ export default class MImageBody extends React.Component { } } - _downloadImage() { + private downloadImage(): void { const content = this.props.mxEvent.getContent(); if (content.file !== undefined && this.state.decryptedUrl === null) { let thumbnailPromise = Promise.resolve(null); @@ -297,7 +301,7 @@ export default class MImageBody extends React.Component { if (showImage) { // Don't download anything becaue we don't want to display anything. - this._downloadImage(); + this.downloadImage(); this.setState({ showImage: true }); } @@ -327,7 +331,7 @@ export default class MImageBody extends React.Component { _afterComponentWillUnmount() { } - _messageContent(contentUrl, thumbUrl, content) { + protected messageContent(contentUrl: string, thumbUrl: string, content: IMediaEventContent): JSX.Element { let infoWidth; let infoHeight; @@ -348,7 +352,7 @@ export default class MImageBody extends React.Component { imageElement = ; } else { imageElement = ( - {content.body}; + img = ; showPlaceholder = false; // because we're hiding the image, so don't show the placeholder. } - if (this._isGif() && !SettingsStore.getValue("autoplayGifsAndVideos") && !this.state.hover) { + if (this.isGif() && !SettingsStore.getValue("autoplayGifsAndVideos") && !this.state.hover) { gifLabel =

GIF

; } @@ -427,14 +431,14 @@ export default class MImageBody extends React.Component { } // Overidden by MStickerBody - wrapImage(contentUrl, children) { + protected wrapImage(contentUrl: string, children: JSX.Element): JSX.Element { return {children} ; } // Overidden by MStickerBody - getPlaceholder(width, height) { + protected getPlaceholder() { const blurhash = this.props.mxEvent.getContent().info[BLURHASH_FIELD]; if (blurhash) return ; return
@@ -443,17 +447,17 @@ export default class MImageBody extends React.Component { } // Overidden by MStickerBody - getTooltip() { + protected getTooltip() { return null; } // Overidden by MStickerBody - getFileBody() { + protected getFileBody(): JSX.Element { return ; } render() { - const content = this.props.mxEvent.getContent(); + const content = this.props.mxEvent.getContent() as IMediaEventContent; if (this.state.error !== null) { return ( @@ -464,15 +468,15 @@ export default class MImageBody extends React.Component { ); } - const contentUrl = this._getContentUrl(); + const contentUrl = this.getContentUrl(); let thumbUrl; - if (this._isGif() && SettingsStore.getValue("autoplayGifsAndVideos")) { + if (this.isGif() && SettingsStore.getValue("autoplayGifsAndVideos")) { thumbUrl = contentUrl; } else { - thumbUrl = this._getThumbUrl(); + thumbUrl = this.getThumbUrl(); } - const thumbnail = this._messageContent(contentUrl, thumbUrl, content); + const thumbnail = this.messageContent(contentUrl, thumbUrl, content); const fileBody = this.getFileBody(); return @@ -482,16 +486,18 @@ export default class MImageBody extends React.Component { } } -export class HiddenImagePlaceholder extends React.PureComponent { - static propTypes = { - hover: PropTypes.bool, - }; +interface PlaceholderIProps { + hover?: boolean; + maxWidth?: number; +} +export class HiddenImagePlaceholder extends React.PureComponent { render() { + const maxWidth = this.props.maxWidth ? this.props.maxWidth + "px" : null; let className = 'mx_HiddenImagePlaceholder'; if (this.props.hover) className += ' mx_HiddenImagePlaceholder_hover'; return ( -
+
{_t("Show image")} From 969be0921023930c91f35827d18df03d68336498 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 2 Jul 2021 13:50:34 +0200 Subject: [PATCH 20/90] Add a few things to IMediaEventContent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/customisations/models/IMediaEventContent.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/customisations/models/IMediaEventContent.ts b/src/customisations/models/IMediaEventContent.ts index fb05d76a4d5..62dfe4ee19a 100644 --- a/src/customisations/models/IMediaEventContent.ts +++ b/src/customisations/models/IMediaEventContent.ts @@ -32,11 +32,16 @@ export interface IEncryptedFile { } export interface IMediaEventContent { + body?: string; url?: string; // required on unencrypted media file?: IEncryptedFile; // required for *encrypted* media info?: { thumbnail_url?: string; // eslint-disable-line camelcase thumbnail_file?: IEncryptedFile; // eslint-disable-line camelcase + mimetype: string; + w?: number; + h?: number; + size?: number; }; } From 5f49b2d374e9da04ab976dbade1e854bc633bac5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 2 Jul 2021 13:53:38 +0200 Subject: [PATCH 21/90] Missing args MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/messages/MImageBody.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/messages/MImageBody.tsx b/src/components/views/messages/MImageBody.tsx index c2553b51a38..c6a4131d1d1 100644 --- a/src/components/views/messages/MImageBody.tsx +++ b/src/components/views/messages/MImageBody.tsx @@ -438,7 +438,7 @@ export default class MImageBody extends React.Component { } // Overidden by MStickerBody - protected getPlaceholder() { + protected getPlaceholder(width: number, height: number) { const blurhash = this.props.mxEvent.getContent().info[BLURHASH_FIELD]; if (blurhash) return ; return
From 5d78eb4a755ec664062f9c81b54a2db3e387bc43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 2 Jul 2021 14:01:30 +0200 Subject: [PATCH 22/90] Member delimiter rules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/messages/MImageBody.tsx | 26 ++++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/components/views/messages/MImageBody.tsx b/src/components/views/messages/MImageBody.tsx index c6a4131d1d1..e29c87599f8 100644 --- a/src/components/views/messages/MImageBody.tsx +++ b/src/components/views/messages/MImageBody.tsx @@ -36,30 +36,30 @@ import { IProps as ImageViewIProps } from "../elements/ImageView"; export interface IProps { /* the MatrixEvent to show */ - mxEvent: MatrixEvent, + mxEvent: MatrixEvent; /* called when the image has loaded */ - onHeightChanged(): void, + onHeightChanged(): void; /* the maximum image height to use */ - maxImageHeight?: number, + maxImageHeight?: number; /* the permalinkCreator */ - permalinkCreator?: RoomPermalinkCreator, + permalinkCreator?: RoomPermalinkCreator; } interface IState { - decryptedUrl?: string, - decryptedThumbnailUrl?: string, - decryptedBlob?: Blob, - error, - imgError: boolean, - imgLoaded: boolean, + decryptedUrl?: string; + decryptedThumbnailUrl?: string; + decryptedBlob?: Blob; + error; + imgError: boolean; + imgLoaded: boolean; loadedImageDimensions?: { naturalWidth: number; naturalHeight: number; - }, - hover: boolean, - showImage: boolean, + }; + hover: boolean; + showImage: boolean; } @replaceableComponent("views.messages.MImageBody") From 664503678079c500d970f8dc389981fbead88646 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 2 Jul 2021 14:17:40 +0200 Subject: [PATCH 23/90] Convert MImageReplyBody to TS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- ...MImageReplyBody.js => MImageReplyBody.tsx} | 27 ++++++++++--------- .../views/messages/SenderProfile.tsx | 2 +- 2 files changed, 15 insertions(+), 14 deletions(-) rename src/components/views/messages/{MImageReplyBody.js => MImageReplyBody.tsx} (69%) diff --git a/src/components/views/messages/MImageReplyBody.js b/src/components/views/messages/MImageReplyBody.tsx similarity index 69% rename from src/components/views/messages/MImageReplyBody.js rename to src/components/views/messages/MImageReplyBody.tsx index 2ed7a637bd2..da720fc00fa 100644 --- a/src/components/views/messages/MImageReplyBody.js +++ b/src/components/views/messages/MImageReplyBody.tsx @@ -15,22 +15,26 @@ limitations under the License. */ import React from "react"; -import { _td } from "../../../languageHandler"; -import * as sdk from "../../../index"; -import MImageBody from './MImageBody'; +import MImageBody, { IProps as MImageBodyIProps } from "./MImageBody"; import { presentableTextForFile } from "./MFileBody"; +import { IMediaEventContent } from "../../../customisations/models/IMediaEventContent"; +import SenderProfile from "./SenderProfile"; export default class MImageReplyBody extends MImageBody { - onClick(ev) { - ev.preventDefault(); + constructor(props: MImageBodyIProps) { + super(props); } - wrapImage(contentUrl, children) { + public onClick = (ev: React.MouseEvent): void => { + ev.preventDefault(); + }; + + public wrapImage(contentUrl: string, children: JSX.Element): JSX.Element { return children; } // Don't show "Download this_file.png ..." - getFileBody() { + public getFileBody(): JSX.Element { return presentableTextForFile(this.props.mxEvent.getContent()); } @@ -39,17 +43,14 @@ export default class MImageReplyBody extends MImageBody { return super.render(); } - const content = this.props.mxEvent.getContent(); + const content = this.props.mxEvent.getContent() as IMediaEventContent; - const contentUrl = this._getContentUrl(); - const thumbnail = this._messageContent(contentUrl, this._getThumbUrl(), content); + const contentUrl = this.getContentUrl(); + const thumbnail = this.messageContent(contentUrl, this.getThumbUrl(), content); const fileBody = this.getFileBody(); - const SenderProfile = sdk.getComponent('messages.SenderProfile'); const sender = ; return
diff --git a/src/components/views/messages/SenderProfile.tsx b/src/components/views/messages/SenderProfile.tsx index 11c3ca4e3cd..bdae9cec4a3 100644 --- a/src/components/views/messages/SenderProfile.tsx +++ b/src/components/views/messages/SenderProfile.tsx @@ -24,7 +24,7 @@ import { MatrixEvent } from "matrix-js-sdk/src/models/event"; interface IProps { mxEvent: MatrixEvent; - onClick(): void; + onClick?(): void; enableFlair: boolean; } From 0fe10e4502dfa234ef9e8388e91ac8ca481b99ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 2 Jul 2021 14:22:46 +0200 Subject: [PATCH 24/90] Fix replies to deleted messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/messages/_RedactedBody.scss | 4 +++- res/css/views/rooms/_ReplyTile.scss | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/res/css/views/messages/_RedactedBody.scss b/res/css/views/messages/_RedactedBody.scss index 600ac0c6b70..767dfef7368 100644 --- a/res/css/views/messages/_RedactedBody.scss +++ b/res/css/views/messages/_RedactedBody.scss @@ -20,6 +20,8 @@ limitations under the License. padding-left: 20px; position: relative; + line-height: 2.2rem; + &::before { height: 14px; width: 14px; @@ -30,7 +32,7 @@ limitations under the License. mask-size: contain; content: ''; position: absolute; - top: 1px; + top: 4px; left: 0; } } diff --git a/res/css/views/rooms/_ReplyTile.scss b/res/css/views/rooms/_ReplyTile.scss index fd684301579..487b6162408 100644 --- a/res/css/views/rooms/_ReplyTile.scss +++ b/res/css/views/rooms/_ReplyTile.scss @@ -25,7 +25,8 @@ limitations under the License. } .mx_ReplyTile > a { - display: block; + display: flex; + flex-direction: column; text-decoration: none; color: $primary-fg-color; } From 9a1b73f86735d12455ec1ac44ffa6de640437dd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 2 Jul 2021 14:51:51 +0200 Subject: [PATCH 25/90] Convert ReplyTile to TS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- .../rooms/{ReplyTile.js => ReplyTile.tsx} | 84 +++++++------------ 1 file changed, 31 insertions(+), 53 deletions(-) rename src/components/views/rooms/{ReplyTile.js => ReplyTile.tsx} (72%) diff --git a/src/components/views/rooms/ReplyTile.js b/src/components/views/rooms/ReplyTile.tsx similarity index 72% rename from src/components/views/rooms/ReplyTile.js rename to src/components/views/rooms/ReplyTile.tsx index 23dcdc21a36..6a01e8dc974 100644 --- a/src/components/views/rooms/ReplyTile.js +++ b/src/components/views/rooms/ReplyTile.tsx @@ -15,66 +15,52 @@ limitations under the License. */ import React from 'react'; -import PropTypes from 'prop-types'; import classNames from 'classnames'; -import { _t, _td } from '../../../languageHandler'; - -import * as sdk from '../../../index'; - +import { _t } from '../../../languageHandler'; import dis from '../../../dispatcher/dispatcher'; import SettingsStore from "../../../settings/SettingsStore"; -import { MatrixClient } from 'matrix-js-sdk'; - -import { objectHasDiff } from '../../../utils/objects'; import { getHandlerTile } from "./EventTile"; +import { MatrixEvent } from "matrix-js-sdk/src/models/event"; +import { RoomPermalinkCreator } from '../../../utils/permalinks/Permalinks'; +import SenderProfile from "../messages/SenderProfile"; +import TextualBody from "../messages/TextualBody"; +import MImageReplyBody from "../messages/MImageReplyBody"; +import * as sdk from '../../../index'; -class ReplyTile extends React.Component { - static contextTypes = { - matrixClient: PropTypes.instanceOf(MatrixClient).isRequired, - } - - static propTypes = { - mxEvent: PropTypes.object.isRequired, - isRedacted: PropTypes.bool, - permalinkCreator: PropTypes.object, - onHeightChanged: PropTypes.func, - } +interface IProps { + mxEvent: MatrixEvent; + isRedacted?: boolean; + permalinkCreator?: RoomPermalinkCreator; + highlights?: Array; + highlightLink?: string; + onHeightChanged?(): void; +} +export default class ReplyTile extends React.PureComponent { static defaultProps = { - onHeightChanged: function() {}, - } + onHeightChanged: () => {}, + }; - constructor(props, context) { - super(props, context); - this.state = {}; - this.onClick = this.onClick.bind(this); - this._onDecrypted = this._onDecrypted.bind(this); + constructor(props: IProps) { + super(props); } componentDidMount() { - this.props.mxEvent.on("Event.decrypted", this._onDecrypted); - } - - shouldComponentUpdate(nextProps, nextState) { - if (objectHasDiff(this.state, nextState)) { - return true; - } - - return objectHasDiff(this.props, nextProps); + this.props.mxEvent.on("Event.decrypted", this.onDecrypted); } componentWillUnmount() { - this.props.mxEvent.removeListener("Event.decrypted", this._onDecrypted); + this.props.mxEvent.removeListener("Event.decrypted", this.onDecrypted); } - _onDecrypted() { + private onDecrypted = (): void => { this.forceUpdate(); if (this.props.onHeightChanged) { this.props.onHeightChanged(); } - } + }; - onClick(e) { + private onClick = (e: React.MouseEvent): void => { // This allows the permalink to be opened in a new tab/window or copied as // matrix.to, but also for it to enable routing within Riot when clicked. e.preventDefault(); @@ -84,11 +70,9 @@ class ReplyTile extends React.Component { highlighted: true, room_id: this.props.mxEvent.getRoomId(), }); - } + }; render() { - const SenderProfile = sdk.getComponent('messages.SenderProfile'); - const content = this.props.mxEvent.getContent(); const msgtype = content.msgtype; const eventType = this.props.mxEvent.getType(); @@ -118,6 +102,7 @@ class ReplyTile extends React.Component { { _t('This event could not be displayed') }
; } + const EventTileType = sdk.getComponent(tileHandler); const classes = classNames({ @@ -135,18 +120,12 @@ class ReplyTile extends React.Component { const needsSenderProfile = msgtype !== 'm.image' && tileHandler !== 'messages.RoomCreate' && !isInfoMessage; if (needsSenderProfile) { - let text = null; - if (msgtype === 'm.image') text = _td('%(senderName)s sent an image'); - else if (msgtype === 'm.video') text = _td('%(senderName)s sent a video'); - else if (msgtype === 'm.file') text = _td('%(senderName)s uploaded a file'); - sender = ; + />; } - const MImageReplyBody = sdk.getComponent('messages.MImageReplyBody'); - const TextualBody = sdk.getComponent('messages.TextualBody'); const msgtypeOverrides = { "m.image": MImageReplyBody, // We don't want a download link for files, just the file name is enough. @@ -163,7 +142,8 @@ class ReplyTile extends React.Component {
{ sender } - Date: Fri, 2 Jul 2021 14:57:08 +0200 Subject: [PATCH 26/90] i18n MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/i18n/strings/en_EN.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 908c023b48a..618d5763fa1 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1563,9 +1563,6 @@ "Seen by %(userName)s at %(dateTime)s": "Seen by %(userName)s at %(dateTime)s", "Seen by %(displayName)s (%(userName)s) at %(dateTime)s": "Seen by %(displayName)s (%(userName)s) at %(dateTime)s", "Replying": "Replying", - "%(senderName)s sent an image": "%(senderName)s sent an image", - "%(senderName)s sent a video": "%(senderName)s sent a video", - "%(senderName)s uploaded a file": "%(senderName)s uploaded a file", "Room %(name)s": "Room %(name)s", "Recently visited rooms": "Recently visited rooms", "No recently visited rooms": "No recently visited rooms", From e582b1559b1d6a30f64d0c223a26a043f32e5769 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 2 Jul 2021 15:09:02 +0200 Subject: [PATCH 27/90] Fix redacted messages (again) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/messages/_RedactedBody.scss | 4 +--- res/css/views/rooms/_ReplyTile.scss | 9 +++++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/res/css/views/messages/_RedactedBody.scss b/res/css/views/messages/_RedactedBody.scss index 767dfef7368..600ac0c6b70 100644 --- a/res/css/views/messages/_RedactedBody.scss +++ b/res/css/views/messages/_RedactedBody.scss @@ -20,8 +20,6 @@ limitations under the License. padding-left: 20px; position: relative; - line-height: 2.2rem; - &::before { height: 14px; width: 14px; @@ -32,7 +30,7 @@ limitations under the License. mask-size: contain; content: ''; position: absolute; - top: 4px; + top: 1px; left: 0; } } diff --git a/res/css/views/rooms/_ReplyTile.scss b/res/css/views/rooms/_ReplyTile.scss index 487b6162408..027b9626a6b 100644 --- a/res/css/views/rooms/_ReplyTile.scss +++ b/res/css/views/rooms/_ReplyTile.scss @@ -31,6 +31,15 @@ limitations under the License. color: $primary-fg-color; } +.mx_ReplyTile > .mx_RedactedBody { + padding: 18px; + + &::before { + height: 13px; + width: 13px; + } +} + // We do reply size limiting with CSS to avoid duplicating the TextualBody component. .mx_ReplyTile .mx_EventTile_content { $reply-lines: 2; From 0d8f84c769b9bee61acc299c461f9788547d9ec5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 2 Jul 2021 15:35:52 +0200 Subject: [PATCH 28/90] Delete lozenge effect MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/rooms/_ReplyTile.scss | 22 -------------------- src/components/views/elements/ReplyThread.js | 1 - src/components/views/rooms/ReplyPreview.js | 1 - src/components/views/rooms/ReplyTile.tsx | 2 -- 4 files changed, 26 deletions(-) diff --git a/res/css/views/rooms/_ReplyTile.scss b/res/css/views/rooms/_ReplyTile.scss index 027b9626a6b..d8184d01be2 100644 --- a/res/css/views/rooms/_ReplyTile.scss +++ b/res/css/views/rooms/_ReplyTile.scss @@ -96,28 +96,6 @@ limitations under the License. max-width: calc(100% - 65px); } -.mx_ReplyTile_redacted .mx_UnknownBody { - --lozenge-color: $event-redacted-fg-color; - --lozenge-border-color: $event-redacted-border-color; - display: block; - height: 22px; - width: 250px; - border-radius: 11px; - background: - repeating-linear-gradient( - -45deg, - var(--lozenge-color), - var(--lozenge-color) 3px, - transparent 3px, - transparent 6px - ); - box-shadow: 0px 0px 3px var(--lozenge-border-color) inset; -} - -.mx_ReplyTile_sending.mx_ReplyTile_redacted .mx_UnknownBody { - opacity: 0.4; -} - .mx_ReplyTile_contextual { opacity: 0.4; } diff --git a/src/components/views/elements/ReplyThread.js b/src/components/views/elements/ReplyThread.js index f199cd53b58..d309c718ddb 100644 --- a/src/components/views/elements/ReplyThread.js +++ b/src/components/views/elements/ReplyThread.js @@ -382,7 +382,6 @@ export default class ReplyThread extends React.Component { mxEvent={ev} onHeightChanged={this.props.onHeightChanged} permalinkCreator={this.props.permalinkCreator} - isRedacted={ev.isRedacted()} isTwelveHour={SettingsStore.getValue("showTwelveHourTimestamps")} layout={this.props.layout} alwaysShowTimestamps={this.props.alwaysShowTimestamps} diff --git a/src/components/views/rooms/ReplyPreview.js b/src/components/views/rooms/ReplyPreview.js index 1dbec2451ac..ca95dbb62f0 100644 --- a/src/components/views/rooms/ReplyPreview.js +++ b/src/components/views/rooms/ReplyPreview.js @@ -88,7 +88,6 @@ export default class ReplyPreview extends React.Component {
diff --git a/src/components/views/rooms/ReplyTile.tsx b/src/components/views/rooms/ReplyTile.tsx index 6a01e8dc974..757c273b50d 100644 --- a/src/components/views/rooms/ReplyTile.tsx +++ b/src/components/views/rooms/ReplyTile.tsx @@ -29,7 +29,6 @@ import * as sdk from '../../../index'; interface IProps { mxEvent: MatrixEvent; - isRedacted?: boolean; permalinkCreator?: RoomPermalinkCreator; highlights?: Array; highlightLink?: string; @@ -108,7 +107,6 @@ export default class ReplyTile extends React.PureComponent { const classes = classNames({ mx_ReplyTile: true, mx_ReplyTile_info: isInfoMessage, - mx_ReplyTile_redacted: this.props.isRedacted, }); let permalink = "#"; From 259b36c13d5d27b542e4d6bc9a43a682d231b90e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 2 Jul 2021 15:38:44 +0200 Subject: [PATCH 29/90] Remove unused code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/elements/ReplyThread.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/components/views/elements/ReplyThread.js b/src/components/views/elements/ReplyThread.js index d309c718ddb..585c4bbdc0d 100644 --- a/src/components/views/elements/ReplyThread.js +++ b/src/components/views/elements/ReplyThread.js @@ -382,12 +382,6 @@ export default class ReplyThread extends React.Component { mxEvent={ev} onHeightChanged={this.props.onHeightChanged} permalinkCreator={this.props.permalinkCreator} - isTwelveHour={SettingsStore.getValue("showTwelveHourTimestamps")} - layout={this.props.layout} - alwaysShowTimestamps={this.props.alwaysShowTimestamps} - enableFlair={SettingsStore.getValue(UIFeature.Flair)} - replacingEventId={ev.replacingEventId()} - as="div" />
; }); From 090acc4811f2dc3f03089cb5346a7bee44db9033 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Fri, 2 Jul 2021 15:41:36 +0200 Subject: [PATCH 30/90] Unused import MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/elements/ReplyThread.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/views/elements/ReplyThread.js b/src/components/views/elements/ReplyThread.js index 585c4bbdc0d..b6368eb5b31 100644 --- a/src/components/views/elements/ReplyThread.js +++ b/src/components/views/elements/ReplyThread.js @@ -29,7 +29,6 @@ import MatrixClientContext from "../../../contexts/MatrixClientContext"; import { getUserNameColorClass } from "../../../utils/FormattingUtils"; import { Action } from "../../../dispatcher/actions"; import sanitizeHtml from "sanitize-html"; -import { UIFeature } from "../../../settings/UIFeature"; import { PERMITTED_URL_SCHEMES } from "../../../HtmlUtils"; import { replaceableComponent } from "../../../utils/replaceableComponent"; From 2e295a94ed61abc21ea1e404eaa5d2fda166cbd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 08:17:51 +0200 Subject: [PATCH 31/90] Don't export IProps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/elements/ImageView.tsx | 2 +- src/components/views/messages/MImageBody.tsx | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/components/views/elements/ImageView.tsx b/src/components/views/elements/ImageView.tsx index 9d9559cdd15..91206e67e86 100644 --- a/src/components/views/elements/ImageView.tsx +++ b/src/components/views/elements/ImageView.tsx @@ -43,7 +43,7 @@ const ZOOM_COEFFICIENT = 0.0025; // If we have moved only this much we can zoom const ZOOM_DISTANCE = 10; -export interface IProps { +interface IProps { src: string; // the source of the image being displayed name?: string; // the main title ('name') for the image link?: string; // the link (if any) applied to the name of the image diff --git a/src/components/views/messages/MImageBody.tsx b/src/components/views/messages/MImageBody.tsx index cd0e259befb..48e57432121 100644 --- a/src/components/views/messages/MImageBody.tsx +++ b/src/components/views/messages/MImageBody.tsx @@ -16,12 +16,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, { createRef } from 'react'; +import React, { ComponentProps, createRef } from 'react'; import { Blurhash } from "react-blurhash"; import MFileBody from './MFileBody'; import Modal from '../../../Modal'; -import * as sdk from '../../../index'; import { decryptFile } from '../../../utils/DecryptFile'; import { _t } from '../../../languageHandler'; import SettingsStore from "../../../settings/SettingsStore"; @@ -33,7 +32,7 @@ import { BLURHASH_FIELD } from "../../../ContentMessages"; import { MatrixEvent } from 'matrix-js-sdk/src/models/event'; import { RoomPermalinkCreator } from '../../../utils/permalinks/Permalinks'; import { IMediaEventContent } from '../../../customisations/models/IMediaEventContent'; -import { IProps as ImageViewIProps } from "../elements/ImageView"; +import ImageView from '../elements/ImageView'; export interface IProps { /* the MatrixEvent to show */ @@ -115,8 +114,7 @@ export default class MImageBody extends React.Component { const content = this.props.mxEvent.getContent() as IMediaEventContent; const httpUrl = this.getContentUrl(); - const ImageView = sdk.getComponent("elements.ImageView"); - const params: ImageViewIProps = { + const params: ComponentProps = { src: httpUrl, name: content.body?.length > 0 ? content.body : _t('Attachment'), mxEvent: this.props.mxEvent, From 7bd7f704f91cd37dd2dd6b2c54ce073f8b774d9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 08:20:17 +0200 Subject: [PATCH 32/90] Extend IDialogProps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/elements/ImageView.tsx | 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 91206e67e86..94f60d29eb2 100644 --- a/src/components/views/elements/ImageView.tsx +++ b/src/components/views/elements/ImageView.tsx @@ -33,6 +33,7 @@ import { replaceableComponent } from "../../../utils/replaceableComponent"; import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks"; import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import { normalizeWheelEvent } from "../../../utils/Mouse"; +import { IDialogProps } from '../dialogs/IDialogProps'; // Max scale to keep gaps around the image const MAX_SCALE = 0.95; @@ -43,14 +44,13 @@ const ZOOM_COEFFICIENT = 0.0025; // If we have moved only this much we can zoom const ZOOM_DISTANCE = 10; -interface IProps { +interface IProps extends IDialogProps { src: string; // the source of the image being displayed name?: string; // the main title ('name') for the image link?: string; // the link (if any) applied to the name of the image width?: number; // width of the image src in pixels height?: number; // height of the image src in pixels fileSize?: number; // size of the image src in bytes - onFinished?(): void; // callback when the lightbox is dismissed // the event (if any) that the Image is displaying. Used for event-specific stuff like // redactions, senders, timestamps etc. Other descriptors are taken from the explicit From cbe94c3c5fbd84b1f24ddf79a94d6e90c0ae37ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 08:23:01 +0200 Subject: [PATCH 33/90] Kill-off sdk.getComponent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/elements/ReplyThread.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/components/views/elements/ReplyThread.js b/src/components/views/elements/ReplyThread.js index b6368eb5b31..c22225f766a 100644 --- a/src/components/views/elements/ReplyThread.js +++ b/src/components/views/elements/ReplyThread.js @@ -16,7 +16,6 @@ See the License for the specific language governing permissions and limitations under the License. */ import React from 'react'; -import * as sdk from '../../../index'; import { _t } from '../../../languageHandler'; import PropTypes from 'prop-types'; import dis from '../../../dispatcher/dispatcher'; @@ -31,6 +30,9 @@ import { Action } from "../../../dispatcher/actions"; import sanitizeHtml from "sanitize-html"; import { PERMITTED_URL_SCHEMES } from "../../../HtmlUtils"; import { replaceableComponent } from "../../../utils/replaceableComponent"; +import Spinner from './Spinner'; +import ReplyTile from "../rooms/ReplyTile"; +import Pill from './Pill'; // 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 @@ -352,7 +354,6 @@ export default class ReplyThread extends React.Component {
; } else if (this.state.loadedEv) { const ev = this.state.loadedEv; - const Pill = sdk.getComponent('elements.Pill'); const room = this.context.getRoom(ev.getRoomId()); header =
{ @@ -370,11 +371,9 @@ export default class ReplyThread extends React.Component { }
; } else if (this.state.loading) { - const Spinner = sdk.getComponent("elements.Spinner"); header = ; } - const ReplyTile = sdk.getComponent('views.rooms.ReplyTile'); const evTiles = this.state.events.map((ev) => { return
Date: Tue, 13 Jul 2021 08:24:18 +0200 Subject: [PATCH 34/90] Nicer formatting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/rooms/_ReplyTile.scss | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/res/css/views/rooms/_ReplyTile.scss b/res/css/views/rooms/_ReplyTile.scss index d8184d01be2..8bf1d168f3f 100644 --- a/res/css/views/rooms/_ReplyTile.scss +++ b/res/css/views/rooms/_ReplyTile.scss @@ -70,7 +70,14 @@ limitations under the License. -webkit-line-clamp: $reply-lines; padding: 4px; } - .markdown-body blockquote, .markdown-body dl, .markdown-body ol, .markdown-body p, .markdown-body pre, .markdown-body table, .markdown-body ul { + + .markdown-body blockquote, + .markdown-body dl, + .markdown-body ol, + .markdown-body p, + .markdown-body pre, + .markdown-body table, + .markdown-body ul { margin-bottom: 4px; } } From ae5e10ff0cefa79c22b584d018cea6738eeb833f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 08:45:36 +0200 Subject: [PATCH 35/90] Burn sdk.getComponent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/ReplyPreview.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/views/rooms/ReplyPreview.js b/src/components/views/rooms/ReplyPreview.js index ca95dbb62f0..2e06cb57bdc 100644 --- a/src/components/views/rooms/ReplyPreview.js +++ b/src/components/views/rooms/ReplyPreview.js @@ -16,12 +16,12 @@ limitations under the License. import React from 'react'; import dis from '../../../dispatcher/dispatcher'; -import * as sdk from '../../../index'; import { _t } from '../../../languageHandler'; import RoomViewStore from '../../../stores/RoomViewStore'; import PropTypes from "prop-types"; import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks"; import { replaceableComponent } from "../../../utils/replaceableComponent"; +import ReplyTile from './ReplyTile'; function cancelQuoting() { dis.dispatch({ @@ -69,8 +69,6 @@ export default class ReplyPreview extends React.Component { render() { if (!this.state.event) return null; - const ReplyTile = sdk.getComponent('rooms.ReplyTile'); - return
From 04098dc74cd106eadf58338de6b64d49971aea68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 08:46:45 +0200 Subject: [PATCH 36/90] Remove unnecessary constructor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/messages/MImageReplyBody.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/components/views/messages/MImageReplyBody.tsx b/src/components/views/messages/MImageReplyBody.tsx index da720fc00fa..cf60ef2ed03 100644 --- a/src/components/views/messages/MImageReplyBody.tsx +++ b/src/components/views/messages/MImageReplyBody.tsx @@ -15,16 +15,12 @@ limitations under the License. */ import React from "react"; -import MImageBody, { IProps as MImageBodyIProps } from "./MImageBody"; +import MImageBody from "./MImageBody"; import { presentableTextForFile } from "./MFileBody"; import { IMediaEventContent } from "../../../customisations/models/IMediaEventContent"; import SenderProfile from "./SenderProfile"; export default class MImageReplyBody extends MImageBody { - constructor(props: MImageBodyIProps) { - super(props); - } - public onClick = (ev: React.MouseEvent): void => { ev.preventDefault(); }; From b5baf404be3124faf64d2a7d5e00f55abb2f798c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 08:47:37 +0200 Subject: [PATCH 37/90] Don't use as MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/messages/MImageReplyBody.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/messages/MImageReplyBody.tsx b/src/components/views/messages/MImageReplyBody.tsx index cf60ef2ed03..9a12cd454cb 100644 --- a/src/components/views/messages/MImageReplyBody.tsx +++ b/src/components/views/messages/MImageReplyBody.tsx @@ -39,7 +39,7 @@ export default class MImageReplyBody extends MImageBody { return super.render(); } - const content = this.props.mxEvent.getContent() as IMediaEventContent; + const content = this.props.mxEvent.getContent(); const contentUrl = this.getContentUrl(); const thumbnail = this.messageContent(contentUrl, this.getThumbUrl(), content); From 70e94f9af5d7b18d8855bd13bb0cabfb170a4fca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 08:48:43 +0200 Subject: [PATCH 38/90] Formatting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/messages/MImageReplyBody.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/views/messages/MImageReplyBody.tsx b/src/components/views/messages/MImageReplyBody.tsx index 9a12cd454cb..74cb8ac7a91 100644 --- a/src/components/views/messages/MImageReplyBody.tsx +++ b/src/components/views/messages/MImageReplyBody.tsx @@ -50,9 +50,9 @@ export default class MImageReplyBody extends MImageBody { />; return
-
{thumbnail}
-
{sender}
-
{fileBody}
+
{ thumbnail }
+
{ sender }
+
{ fileBody }
; } } From 8f8377a71ccd5d6345457ad698632d1a2a365ef1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 09:16:01 +0200 Subject: [PATCH 39/90] Types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/messages/MImageBody.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/views/messages/MImageBody.tsx b/src/components/views/messages/MImageBody.tsx index 48e57432121..c56ec2f6c82 100644 --- a/src/components/views/messages/MImageBody.tsx +++ b/src/components/views/messages/MImageBody.tsx @@ -33,6 +33,7 @@ import { MatrixEvent } from 'matrix-js-sdk/src/models/event'; import { RoomPermalinkCreator } from '../../../utils/permalinks/Permalinks'; import { IMediaEventContent } from '../../../customisations/models/IMediaEventContent'; import ImageView from '../elements/ImageView'; +import { SyncState } from 'matrix-js-sdk/src/sync.api'; export interface IProps { /* the MatrixEvent to show */ @@ -85,7 +86,7 @@ export default class MImageBody extends React.Component { } // FIXME: factor this out and apply it to MVideoBody and MAudioBody too! - private onClientSync = (syncState, prevState): void => { + private onClientSync = (syncState: SyncState, prevState: SyncState): void => { if (this.unmounted) return; // Consider the client reconnected if there is no error with syncing. // This means the state could be RECONNECTING, SYNCING, PREPARED or CATCHUP. From 5fc35565df19698fab4528175a3326ef8a472036 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 09:16:53 +0200 Subject: [PATCH 40/90] More TS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/messages/MImageBody.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/views/messages/MImageBody.tsx b/src/components/views/messages/MImageBody.tsx index c56ec2f6c82..b4cb67e0550 100644 --- a/src/components/views/messages/MImageBody.tsx +++ b/src/components/views/messages/MImageBody.tsx @@ -113,13 +113,14 @@ export default class MImageBody extends React.Component { return; } - const content = this.props.mxEvent.getContent() as IMediaEventContent; + const content = this.props.mxEvent.getContent(); const httpUrl = this.getContentUrl(); const params: ComponentProps = { src: httpUrl, name: content.body?.length > 0 ? content.body : _t('Attachment'), mxEvent: this.props.mxEvent, permalinkCreator: this.props.permalinkCreator, + onFinished: () => {}, }; if (content.info) { From 2a403f6cfef977372af42eac6610822c33fa9b3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 09:17:18 +0200 Subject: [PATCH 41/90] Remove additional ? MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/messages/MImageBody.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/messages/MImageBody.tsx b/src/components/views/messages/MImageBody.tsx index b4cb67e0550..a72cfa01d45 100644 --- a/src/components/views/messages/MImageBody.tsx +++ b/src/components/views/messages/MImageBody.tsx @@ -135,7 +135,7 @@ export default class MImageBody extends React.Component { private isGif = (): boolean => { const content = this.props.mxEvent.getContent(); - return content?.info?.mimetype === "image/gif"; + return content.info?.mimetype === "image/gif"; }; private onImageEnter = (e: React.MouseEvent): void => { From bdbd03c4ff0eb7080faa4171c1de4f56d82056da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 09:18:05 +0200 Subject: [PATCH 42/90] Types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/messages/MImageBody.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/messages/MImageBody.tsx b/src/components/views/messages/MImageBody.tsx index a72cfa01d45..f3ef1bf3046 100644 --- a/src/components/views/messages/MImageBody.tsx +++ b/src/components/views/messages/MImageBody.tsx @@ -138,7 +138,7 @@ export default class MImageBody extends React.Component { return content.info?.mimetype === "image/gif"; }; - private onImageEnter = (e: React.MouseEvent): void => { + private onImageEnter = (e: React.MouseEvent): void => { this.setState({ hover: true }); if (!this.state.showImage || !this.isGif() || SettingsStore.getValue("autoplayGifsAndVideos")) { From fa4977c4da0b9e9875bafb567358c75e46a4a71e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 09:18:34 +0200 Subject: [PATCH 43/90] Use current target MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/messages/MImageBody.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/messages/MImageBody.tsx b/src/components/views/messages/MImageBody.tsx index f3ef1bf3046..91f1315f7a5 100644 --- a/src/components/views/messages/MImageBody.tsx +++ b/src/components/views/messages/MImageBody.tsx @@ -144,7 +144,7 @@ export default class MImageBody extends React.Component { if (!this.state.showImage || !this.isGif() || SettingsStore.getValue("autoplayGifsAndVideos")) { return; } - const imgElement = e.target as HTMLImageElement; + const imgElement = e.currentTarget; imgElement.src = this.getContentUrl(); }; From 6193bc2a828aab69251e4fb09ef0c0b4731bbf82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 09:19:19 +0200 Subject: [PATCH 44/90] Types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/messages/MImageBody.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/messages/MImageBody.tsx b/src/components/views/messages/MImageBody.tsx index 91f1315f7a5..35975109e71 100644 --- a/src/components/views/messages/MImageBody.tsx +++ b/src/components/views/messages/MImageBody.tsx @@ -148,7 +148,7 @@ export default class MImageBody extends React.Component { imgElement.src = this.getContentUrl(); }; - private onImageLeave = (e: React.MouseEvent): void => { + private onImageLeave = (e: React.MouseEvent): void => { this.setState({ hover: false }); if (!this.state.showImage || !this.isGif() || SettingsStore.getValue("autoplayGifsAndVideos")) { From 86580f3f20f7bef1937a8416c07a541514ea0c91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 09:19:45 +0200 Subject: [PATCH 45/90] current target MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/messages/MImageBody.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/messages/MImageBody.tsx b/src/components/views/messages/MImageBody.tsx index 35975109e71..a669505181f 100644 --- a/src/components/views/messages/MImageBody.tsx +++ b/src/components/views/messages/MImageBody.tsx @@ -154,7 +154,7 @@ export default class MImageBody extends React.Component { if (!this.state.showImage || !this.isGif() || SettingsStore.getValue("autoplayGifsAndVideos")) { return; } - const imgElement = e.target as HTMLImageElement; + const imgElement = e.currentTarget; imgElement.src = this.getThumbUrl(); }; From af7769ce935a39c525adede743056963f765d8c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 09:20:13 +0200 Subject: [PATCH 46/90] Types! MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/messages/MImageBody.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/messages/MImageBody.tsx b/src/components/views/messages/MImageBody.tsx index a669505181f..1e9678dbefc 100644 --- a/src/components/views/messages/MImageBody.tsx +++ b/src/components/views/messages/MImageBody.tsx @@ -195,7 +195,7 @@ export default class MImageBody extends React.Component { const thumbWidth = 800; const thumbHeight = 600; - const content = this.props.mxEvent.getContent() as IMediaEventContent; + const content = this.props.mxEvent.getContent(); const media = mediaFromContent(content); if (media.isEncrypted) { From 4cf4ab2266959370f78eea4919cb0237813085ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 09:20:40 +0200 Subject: [PATCH 47/90] Return type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/messages/MImageBody.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/messages/MImageBody.tsx b/src/components/views/messages/MImageBody.tsx index 1e9678dbefc..a4a615fa65e 100644 --- a/src/components/views/messages/MImageBody.tsx +++ b/src/components/views/messages/MImageBody.tsx @@ -439,7 +439,7 @@ export default class MImageBody extends React.Component { } // Overidden by MStickerBody - protected getPlaceholder(width: number, height: number) { + protected getPlaceholder(width: number, height: number): JSX.Element { const blurhash = this.props.mxEvent.getContent().info[BLURHASH_FIELD]; if (blurhash) return ; return
From e4d1859fb70d9ffa9b8e8c7516e793ed56224df2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 09:21:05 +0200 Subject: [PATCH 48/90] Ret type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/messages/MImageBody.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/messages/MImageBody.tsx b/src/components/views/messages/MImageBody.tsx index a4a615fa65e..2062191303d 100644 --- a/src/components/views/messages/MImageBody.tsx +++ b/src/components/views/messages/MImageBody.tsx @@ -448,7 +448,7 @@ export default class MImageBody extends React.Component { } // Overidden by MStickerBody - protected getTooltip() { + protected getTooltip(): JSX.Element { return null; } From ef1a1ebe12c5033cfe01a47f3cf0bb88125c715c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 09:21:33 +0200 Subject: [PATCH 49/90] TS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/messages/MImageBody.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/messages/MImageBody.tsx b/src/components/views/messages/MImageBody.tsx index 2062191303d..3f5f27eca8e 100644 --- a/src/components/views/messages/MImageBody.tsx +++ b/src/components/views/messages/MImageBody.tsx @@ -458,7 +458,7 @@ export default class MImageBody extends React.Component { } render() { - const content = this.props.mxEvent.getContent() as IMediaEventContent; + const content = this.props.mxEvent.getContent(); if (this.state.error !== null) { return ( From 931bba747abbf9e2fe7f4974eed55441ff71125d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 09:22:13 +0200 Subject: [PATCH 50/90] Replaceable component MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/ReplyTile.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/views/rooms/ReplyTile.tsx b/src/components/views/rooms/ReplyTile.tsx index 757c273b50d..227c5b6585d 100644 --- a/src/components/views/rooms/ReplyTile.tsx +++ b/src/components/views/rooms/ReplyTile.tsx @@ -35,6 +35,7 @@ interface IProps { onHeightChanged?(): void; } +@replaceableComponent("views.rooms.ReplyTile") export default class ReplyTile extends React.PureComponent { static defaultProps = { onHeightChanged: () => {}, From 63ad95246a0a62bf5e24a207c5a054dd2764c89d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 09:23:57 +0200 Subject: [PATCH 51/90] EventType enum! MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/ReplyTile.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/components/views/rooms/ReplyTile.tsx b/src/components/views/rooms/ReplyTile.tsx index 227c5b6585d..775091a59f4 100644 --- a/src/components/views/rooms/ReplyTile.tsx +++ b/src/components/views/rooms/ReplyTile.tsx @@ -26,6 +26,7 @@ import SenderProfile from "../messages/SenderProfile"; import TextualBody from "../messages/TextualBody"; import MImageReplyBody from "../messages/MImageReplyBody"; import * as sdk from '../../../index'; +import { EventType } from 'matrix-js-sdk/src/@types/event'; interface IProps { mxEvent: MatrixEvent; @@ -78,9 +79,11 @@ export default class ReplyTile extends React.PureComponent { const eventType = this.props.mxEvent.getType(); // Info messages are basically information about commands processed on a room - let isInfoMessage = ( - eventType !== 'm.room.message' && eventType !== 'm.sticker' && eventType !== 'm.room.create' - ); + let isInfoMessage = [ + EventType.RoomMessage, + EventType.Sticker, + EventType.RoomCreate, + ].includes(eventType as EventType); let tileHandler = getHandlerTile(this.props.mxEvent); // If we're showing hidden events in the timeline, we should use the From 22b029d11672186296558f4e570e76f0b851e925 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 09:24:40 +0200 Subject: [PATCH 52/90] Relation type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/ReplyTile.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/ReplyTile.tsx b/src/components/views/rooms/ReplyTile.tsx index 775091a59f4..8807be680c8 100644 --- a/src/components/views/rooms/ReplyTile.tsx +++ b/src/components/views/rooms/ReplyTile.tsx @@ -26,7 +26,7 @@ import SenderProfile from "../messages/SenderProfile"; import TextualBody from "../messages/TextualBody"; import MImageReplyBody from "../messages/MImageReplyBody"; import * as sdk from '../../../index'; -import { EventType } from 'matrix-js-sdk/src/@types/event'; +import { EventType, RelationType } from 'matrix-js-sdk/src/@types/event'; interface IProps { mxEvent: MatrixEvent; @@ -90,7 +90,7 @@ export default class ReplyTile extends React.PureComponent { // source tile when there's no regular tile for an event and also for // replace relations (which otherwise would display as a confusing // duplicate of the thing they are replacing). - const useSource = !tileHandler || this.props.mxEvent.isRelation("m.replace"); + const useSource = !tileHandler || this.props.mxEvent.isRelation(RelationType.Replace); if (useSource && SettingsStore.getValue("showHiddenEventsInTimeline")) { tileHandler = "messages.ViewSourceEvent"; // Reuse info message avatar and sender profile styling From 0bf595d8d494f6bcd2e9d38c2147be1eb39099f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 09:26:27 +0200 Subject: [PATCH 53/90] Enums MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/ReplyTile.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/views/rooms/ReplyTile.tsx b/src/components/views/rooms/ReplyTile.tsx index 8807be680c8..f6a4bd7a18a 100644 --- a/src/components/views/rooms/ReplyTile.tsx +++ b/src/components/views/rooms/ReplyTile.tsx @@ -26,7 +26,7 @@ import SenderProfile from "../messages/SenderProfile"; import TextualBody from "../messages/TextualBody"; import MImageReplyBody from "../messages/MImageReplyBody"; import * as sdk from '../../../index'; -import { EventType, RelationType } from 'matrix-js-sdk/src/@types/event'; +import { EventType, MsgType, RelationType } from 'matrix-js-sdk/src/@types/event'; interface IProps { mxEvent: MatrixEvent; @@ -119,7 +119,7 @@ export default class ReplyTile extends React.PureComponent { } let sender; - const needsSenderProfile = msgtype !== 'm.image' && tileHandler !== 'messages.RoomCreate' && !isInfoMessage; + const needsSenderProfile = msgtype !== MsgType.Image && tileHandler !== EventType.RoomCreate && !isInfoMessage; if (needsSenderProfile) { sender = Date: Tue, 13 Jul 2021 09:27:22 +0200 Subject: [PATCH 54/90] More compact classNames MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/ReplyTile.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/views/rooms/ReplyTile.tsx b/src/components/views/rooms/ReplyTile.tsx index f6a4bd7a18a..1b9f3e2facf 100644 --- a/src/components/views/rooms/ReplyTile.tsx +++ b/src/components/views/rooms/ReplyTile.tsx @@ -108,8 +108,7 @@ export default class ReplyTile extends React.PureComponent { const EventTileType = sdk.getComponent(tileHandler); - const classes = classNames({ - mx_ReplyTile: true, + const classes = classNames("mx_ReplyTile", { mx_ReplyTile_info: isInfoMessage, }); From c44de3bea817bab53c3bcc74ecad7ef993d97a63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 09:30:52 +0200 Subject: [PATCH 55/90] Enums MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/ReplyTile.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/views/rooms/ReplyTile.tsx b/src/components/views/rooms/ReplyTile.tsx index 1b9f3e2facf..593ebffedd7 100644 --- a/src/components/views/rooms/ReplyTile.tsx +++ b/src/components/views/rooms/ReplyTile.tsx @@ -128,15 +128,15 @@ export default class ReplyTile extends React.PureComponent { } const msgtypeOverrides = { - "m.image": MImageReplyBody, + [MsgType.Image]: MImageReplyBody, // We don't want a download link for files, just the file name is enough. - "m.file": TextualBody, + [MsgType.File]: TextualBody, "m.sticker": TextualBody, - "m.audio": TextualBody, - "m.video": TextualBody, + [MsgType.Audio]: TextualBody, + [MsgType.Video]: TextualBody, }; const evOverrides = { - "m.sticker": TextualBody, + [EventType.Sticker]: TextualBody, }; return ( From 069180b16dda2cf02c97569017cbd27064f534ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 09:31:28 +0200 Subject: [PATCH 56/90] Remove contructor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/ReplyTile.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/components/views/rooms/ReplyTile.tsx b/src/components/views/rooms/ReplyTile.tsx index 593ebffedd7..9cc42faca32 100644 --- a/src/components/views/rooms/ReplyTile.tsx +++ b/src/components/views/rooms/ReplyTile.tsx @@ -42,10 +42,6 @@ export default class ReplyTile extends React.PureComponent { onHeightChanged: () => {}, }; - constructor(props: IProps) { - super(props); - } - componentDidMount() { this.props.mxEvent.on("Event.decrypted", this.onDecrypted); } From 43cf7bc6110cdbe6750f5a239224a0813e758ebb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 09:33:45 +0200 Subject: [PATCH 57/90] Remove 0px MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/rooms/_ReplyTile.scss | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/res/css/views/rooms/_ReplyTile.scss b/res/css/views/rooms/_ReplyTile.scss index 8bf1d168f3f..04dc34092a9 100644 --- a/res/css/views/rooms/_ReplyTile.scss +++ b/res/css/views/rooms/_ReplyTile.scss @@ -83,7 +83,7 @@ limitations under the License. } .mx_ReplyTile.mx_ReplyTile_info { - padding-top: 0px; + padding-top: 0; } .mx_ReplyTile .mx_SenderProfile { @@ -92,10 +92,10 @@ limitations under the License. display: inline-block; /* anti-zalgo, with overflow hidden */ overflow: hidden; cursor: pointer; - padding-left: 0px; /* left gutter */ - padding-bottom: 0px; - padding-top: 0px; - margin: 0px; + padding-left: 0; /* left gutter */ + padding-bottom: 0; + padding-top: 0; + margin: 0; line-height: 17px; /* the next three lines, along with overflow hidden, truncate long display names */ white-space: nowrap; From e01d1572ac1521d2b4f845c794bd0a81762fb53d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 09:34:43 +0200 Subject: [PATCH 58/90] Formatting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/messages/MFileBody.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/views/messages/MFileBody.js b/src/components/views/messages/MFileBody.js index f6346e56d91..e95f397e40c 100644 --- a/src/components/views/messages/MFileBody.js +++ b/src/components/views/messages/MFileBody.js @@ -173,7 +173,9 @@ export default class MFileBody extends React.Component { placeholder = (
- {presentableTextForFile(content, false)} + + { presentableTextForFile(content, false) } +
); } From 562d43e81c48fae61a51a0561b28f248ff086238 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 09:36:31 +0200 Subject: [PATCH 59/90] Font MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/rooms/_ReplyTile.scss | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/res/css/views/rooms/_ReplyTile.scss b/res/css/views/rooms/_ReplyTile.scss index 04dc34092a9..ff3a0d07d14 100644 --- a/res/css/views/rooms/_ReplyTile.scss +++ b/res/css/views/rooms/_ReplyTile.scss @@ -19,7 +19,7 @@ limitations under the License. clear: both; padding-top: 2px; padding-bottom: 2px; - font-size: 14px; + font-size: $font-14px; position: relative; line-height: 16px; } @@ -43,7 +43,7 @@ limitations under the License. // We do reply size limiting with CSS to avoid duplicating the TextualBody component. .mx_ReplyTile .mx_EventTile_content { $reply-lines: 2; - $line-height: 22px; + $line-height: $font-22px; $max-height: 66px; pointer-events: none; @@ -58,7 +58,7 @@ limitations under the License. .mx_EventTile_body.mx_EventTile_bigEmoji { line-height: $line-height !important; // Override the big emoji override - font-size: 14px !important; + font-size: $font-14px !important; } // Hack to cut content in
 tags too
@@ -88,7 +88,7 @@ limitations under the License.
 
 .mx_ReplyTile .mx_SenderProfile {
     color: $primary-fg-color;
-    font-size: 14px;
+    font-size: $font-14px;
     display: inline-block; /* anti-zalgo, with overflow hidden */
     overflow: hidden;
     cursor: pointer;
@@ -96,7 +96,7 @@ limitations under the License.
     padding-bottom: 0;
     padding-top: 0;
     margin: 0;
-    line-height: 17px;
+    line-height: $font-17px;
     /* the next three lines, along with overflow hidden, truncate long display names */
     white-space: nowrap;
     text-overflow: ellipsis;

From 9455a6d77270595d1b8c07d17c4d00a0a1332293 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?= 
Date: Tue, 13 Jul 2021 09:40:29 +0200
Subject: [PATCH 60/90] Import replaceableComponent
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Šimon Brandner 
---
 src/components/views/rooms/ReplyTile.tsx | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/components/views/rooms/ReplyTile.tsx b/src/components/views/rooms/ReplyTile.tsx
index 9cc42faca32..fdd43e32001 100644
--- a/src/components/views/rooms/ReplyTile.tsx
+++ b/src/components/views/rooms/ReplyTile.tsx
@@ -27,6 +27,7 @@ import TextualBody from "../messages/TextualBody";
 import MImageReplyBody from "../messages/MImageReplyBody";
 import * as sdk from '../../../index';
 import { EventType, MsgType, RelationType } from 'matrix-js-sdk/src/@types/event';
+import { replaceableComponent } from '../../../utils/replaceableComponent';
 
 interface IProps {
     mxEvent: MatrixEvent;

From bc7a8f8406e960772e16932dd4df96daf38ba6b8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?= 
Date: Tue, 13 Jul 2021 10:12:24 +0200
Subject: [PATCH 61/90] Handle redaction
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Šimon Brandner 
---
 src/components/views/rooms/ReplyTile.tsx | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/components/views/rooms/ReplyTile.tsx b/src/components/views/rooms/ReplyTile.tsx
index fdd43e32001..fd90d2d5368 100644
--- a/src/components/views/rooms/ReplyTile.tsx
+++ b/src/components/views/rooms/ReplyTile.tsx
@@ -45,6 +45,7 @@ export default class ReplyTile extends React.PureComponent {
 
     componentDidMount() {
         this.props.mxEvent.on("Event.decrypted", this.onDecrypted);
+        this.props.mxEvent.on("Event.beforeRedaction", this.onBeforeRedaction);
     }
 
     componentWillUnmount() {
@@ -58,6 +59,11 @@ export default class ReplyTile extends React.PureComponent {
         }
     };
 
+    private onBeforeRedaction = (): void => {
+        // When the event gets redacted, update it, so that a different tile handler is used
+        this.forceUpdate();
+    };
+
     private onClick = (e: React.MouseEvent): void => {
         // This allows the permalink to be opened in a new tab/window or copied as
         // matrix.to, but also for it to enable routing within Riot when clicked.

From fca5125c5b1fc47c21d1cee9b856db7fd25f46a7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?= 
Date: Tue, 13 Jul 2021 10:36:44 +0200
Subject: [PATCH 62/90] Improve redacted body look
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Šimon Brandner 
---
 res/css/views/rooms/_ReplyTile.scss      | 2 +-
 src/components/views/rooms/ReplyTile.tsx | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/res/css/views/rooms/_ReplyTile.scss b/res/css/views/rooms/_ReplyTile.scss
index ff3a0d07d14..dee68871c2d 100644
--- a/res/css/views/rooms/_ReplyTile.scss
+++ b/res/css/views/rooms/_ReplyTile.scss
@@ -21,7 +21,7 @@ limitations under the License.
     padding-bottom: 2px;
     font-size: $font-14px;
     position: relative;
-    line-height: 16px;
+    line-height: $font-16px;
 }
 
 .mx_ReplyTile > a {
diff --git a/src/components/views/rooms/ReplyTile.tsx b/src/components/views/rooms/ReplyTile.tsx
index fd90d2d5368..78e630a0a2a 100644
--- a/src/components/views/rooms/ReplyTile.tsx
+++ b/src/components/views/rooms/ReplyTile.tsx
@@ -112,7 +112,7 @@ export default class ReplyTile extends React.PureComponent {
         const EventTileType = sdk.getComponent(tileHandler);
 
         const classes = classNames("mx_ReplyTile", {
-            mx_ReplyTile_info: isInfoMessage,
+            mx_ReplyTile_info: isInfoMessage && !this.props.mxEvent.isRedacted(),
         });
 
         let permalink = "#";

From 866a11d7e39b6746689453639018d221f40f94f3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=A0imon=20Brandner?= 
Date: Tue, 13 Jul 2021 11:49:49 +0200
Subject: [PATCH 63/90] Fix image alignment issues
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Šimon Brandner 
---
 res/css/views/messages/_MImageReplyBody.scss      | 14 +++-----------
 src/components/views/messages/MImageBody.tsx      | 13 +++++++++----
 src/components/views/messages/MImageReplyBody.tsx | 10 ++++++----
 3 files changed, 18 insertions(+), 19 deletions(-)

diff --git a/res/css/views/messages/_MImageReplyBody.scss b/res/css/views/messages/_MImageReplyBody.scss
index 8c5cb97478d..f0401d21dbf 100644
--- a/res/css/views/messages/_MImageReplyBody.scss
+++ b/res/css/views/messages/_MImageReplyBody.scss
@@ -15,19 +15,11 @@ limitations under the License.
 */
 
 .mx_MImageReplyBody {
-    display: grid;
-    grid-template:
-        "image sender"   20px
-        "image filename" 20px
-        / 44px  auto;
-    grid-gap: 4px;
-}
-
-.mx_MImageReplyBody_thumbnail {
-    grid-area: image;
+    display: flex;
 
     .mx_MImageBody_thumbnail_container {
-        max-height: 44px !important;
+        flex: 1;
+        padding-right: 4px;
     }
 }
 
diff --git a/src/components/views/messages/MImageBody.tsx b/src/components/views/messages/MImageBody.tsx
index 3f5f27eca8e..0acdbaf253f 100644
--- a/src/components/views/messages/MImageBody.tsx
+++ b/src/components/views/messages/MImageBody.tsx
@@ -332,7 +332,12 @@ export default class MImageBody extends React.Component {
     _afterComponentWillUnmount() {
     }
 
-    protected messageContent(contentUrl: string, thumbUrl: string, content: IMediaEventContent): JSX.Element {
+    protected messageContent(
+        contentUrl: string,
+        thumbUrl: string,
+        content: IMediaEventContent,
+        forcedHeight?: number,
+    ): JSX.Element {
         let infoWidth;
         let infoHeight;
 
@@ -367,7 +372,7 @@ export default class MImageBody extends React.Component {
         }
 
         // The maximum height of the thumbnail as it is rendered as an 
-        const maxHeight = Math.min(this.props.maxImageHeight || 600, infoHeight);
+        const maxHeight = forcedHeight || Math.min((this.props.maxImageHeight || 600), infoHeight);
         // The maximum width of the thumbnail, as dictated by its natural
         // maximum height.
         const maxWidth = infoWidth * maxHeight / infoHeight;
@@ -407,9 +412,9 @@ export default class MImageBody extends React.Component {
         }
 
         const thumbnail = (
-            
+
{ /* Calculate aspect ratio, using %padding will size _container correctly */ } -
+
{ showPlaceholder &&
(); const contentUrl = this.getContentUrl(); - const thumbnail = this.messageContent(contentUrl, this.getThumbUrl(), content); + const thumbnail = this.messageContent(contentUrl, this.getThumbUrl(), content, 44); const fileBody = this.getFileBody(); const sender = ; return
-
{ thumbnail }
-
{ sender }
-
{ fileBody }
+ { thumbnail } +
+
{ sender }
+
{ fileBody }
+
; } } From 75e7948ca8eed1ea98925af32cfbe62024f634b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 11:57:40 +0200 Subject: [PATCH 64/90] Handle event edits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/ReplyTile.tsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/components/views/rooms/ReplyTile.tsx b/src/components/views/rooms/ReplyTile.tsx index 78e630a0a2a..e751a8ddc35 100644 --- a/src/components/views/rooms/ReplyTile.tsx +++ b/src/components/views/rooms/ReplyTile.tsx @@ -45,11 +45,14 @@ export default class ReplyTile extends React.PureComponent { componentDidMount() { this.props.mxEvent.on("Event.decrypted", this.onDecrypted); - this.props.mxEvent.on("Event.beforeRedaction", this.onBeforeRedaction); + this.props.mxEvent.on("Event.beforeRedaction", this.onEventRequiresUpdate); + this.props.mxEvent.on("Event.replaced", this.onEventRequiresUpdate); } componentWillUnmount() { this.props.mxEvent.removeListener("Event.decrypted", this.onDecrypted); + this.props.mxEvent.removeListener("Event.beforeRedaction", this.onEventRequiresUpdate); + this.props.mxEvent.removeListener("Event.replaced", this.onEventRequiresUpdate); } private onDecrypted = (): void => { @@ -59,8 +62,8 @@ export default class ReplyTile extends React.PureComponent { } }; - private onBeforeRedaction = (): void => { - // When the event gets redacted, update it, so that a different tile handler is used + private onEventRequiresUpdate = (): void => { + // Force update when necessary - redactions and edits this.forceUpdate(); }; @@ -155,6 +158,7 @@ export default class ReplyTile extends React.PureComponent { showUrlPreview={false} overrideBodyTypes={msgtypeOverrides} overrideEventTypes={evOverrides} + replacingEventId={this.props.mxEvent.replacingEventId()} maxImageHeight={96} />
From b4ae54dcce460a6147fed525705c35f7224f62e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 12:15:22 +0200 Subject: [PATCH 65/90] Remove unused CSS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/rooms/_ReplyTile.scss | 6 ------ 1 file changed, 6 deletions(-) diff --git a/res/css/views/rooms/_ReplyTile.scss b/res/css/views/rooms/_ReplyTile.scss index dee68871c2d..d059d553a95 100644 --- a/res/css/views/rooms/_ReplyTile.scss +++ b/res/css/views/rooms/_ReplyTile.scss @@ -15,8 +15,6 @@ limitations under the License. */ .mx_ReplyTile { - max-width: 100%; - clear: both; padding-top: 2px; padding-bottom: 2px; font-size: $font-14px; @@ -102,7 +100,3 @@ limitations under the License. text-overflow: ellipsis; max-width: calc(100% - 65px); } - -.mx_ReplyTile_contextual { - opacity: 0.4; -} From 8fc90e1d5341f1977cf93779897d508f57488389 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 12:26:14 +0200 Subject: [PATCH 66/90] Fix isInfoMessage regression MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/ReplyTile.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/ReplyTile.tsx b/src/components/views/rooms/ReplyTile.tsx index e751a8ddc35..19da3455792 100644 --- a/src/components/views/rooms/ReplyTile.tsx +++ b/src/components/views/rooms/ReplyTile.tsx @@ -85,7 +85,7 @@ export default class ReplyTile extends React.PureComponent { const eventType = this.props.mxEvent.getType(); // Info messages are basically information about commands processed on a room - let isInfoMessage = [ + let isInfoMessage = ![ EventType.RoomMessage, EventType.Sticker, EventType.RoomCreate, From d149cead5fb0348ba0c6cc8013a2e78beb4675ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 12:27:03 +0200 Subject: [PATCH 67/90] Remove unused CSS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/rooms/_ReplyTile.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/res/css/views/rooms/_ReplyTile.scss b/res/css/views/rooms/_ReplyTile.scss index d059d553a95..21e5fedea93 100644 --- a/res/css/views/rooms/_ReplyTile.scss +++ b/res/css/views/rooms/_ReplyTile.scss @@ -98,5 +98,4 @@ limitations under the License. /* the next three lines, along with overflow hidden, truncate long display names */ white-space: nowrap; text-overflow: ellipsis; - max-width: calc(100% - 65px); } From 8e456b062ad5909dee2f3f3f009a2d051dedad55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 12:32:17 +0200 Subject: [PATCH 68/90] More unused CSS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/rooms/_ReplyTile.scss | 2 -- 1 file changed, 2 deletions(-) diff --git a/res/css/views/rooms/_ReplyTile.scss b/res/css/views/rooms/_ReplyTile.scss index 21e5fedea93..007ed35ecfa 100644 --- a/res/css/views/rooms/_ReplyTile.scss +++ b/res/css/views/rooms/_ReplyTile.scss @@ -42,7 +42,6 @@ limitations under the License. .mx_ReplyTile .mx_EventTile_content { $reply-lines: 2; $line-height: $font-22px; - $max-height: 66px; pointer-events: none; @@ -51,7 +50,6 @@ limitations under the License. -webkit-box-orient: vertical; -webkit-line-clamp: $reply-lines; line-height: $line-height; - max-height: $max-height; .mx_EventTile_body.mx_EventTile_bigEmoji { line-height: $line-height !important; From 2660e25d6e932627a0814cd7d3b34a4d26a9865a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 13:04:37 +0200 Subject: [PATCH 69/90] Deduplicate some code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/EventTile.tsx | 31 ++----------------- src/components/views/rooms/ReplyTile.tsx | 26 +++------------- src/utils/EventUtils.ts | 38 ++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 50 deletions(-) diff --git a/src/components/views/rooms/EventTile.tsx b/src/components/views/rooms/EventTile.tsx index bf2438d2678..b1e75443a06 100644 --- a/src/components/views/rooms/EventTile.tsx +++ b/src/components/views/rooms/EventTile.tsx @@ -54,6 +54,7 @@ import TooltipButton from '../elements/TooltipButton'; import ReadReceiptMarker from "./ReadReceiptMarker"; import MessageActionBar from "../messages/MessageActionBar"; import ReactionsRow from '../messages/ReactionsRow'; +import { getEventDisplayInfo } from '../../../utils/EventUtils'; const eventTileTypes = { [EventType.RoomMessage]: 'messages.MessageEvent', @@ -845,35 +846,9 @@ export default class EventTile extends React.Component { }; render() { - //console.info("EventTile showUrlPreview for %s is %s", this.props.mxEvent.getId(), this.props.showUrlPreview); - - const content = this.props.mxEvent.getContent(); - const msgtype = content.msgtype; - const eventType = this.props.mxEvent.getType(); - - let tileHandler = getHandlerTile(this.props.mxEvent); - - // Info messages are basically information about commands processed on a room - let isBubbleMessage = eventType.startsWith("m.key.verification") || - (eventType === EventType.RoomMessage && msgtype && msgtype.startsWith("m.key.verification")) || - (eventType === EventType.RoomCreate) || - (eventType === EventType.RoomEncryption) || - (tileHandler === "messages.MJitsiWidgetEvent"); - let isInfoMessage = ( - !isBubbleMessage && eventType !== EventType.RoomMessage && - eventType !== EventType.Sticker && eventType !== EventType.RoomCreate - ); + const msgtype = this.props.mxEvent.getContent().msgtype; + const { tileHandler, isBubbleMessage, isInfoMessage } = getEventDisplayInfo(this.props.mxEvent); - // If we're showing hidden events in the timeline, we should use the - // source tile when there's no regular tile for an event and also for - // replace relations (which otherwise would display as a confusing - // duplicate of the thing they are replacing). - if (SettingsStore.getValue("showHiddenEventsInTimeline") && !haveTileForEvent(this.props.mxEvent)) { - tileHandler = "messages.ViewSourceEvent"; - isBubbleMessage = false; - // Reuse info message avatar and sender profile styling - isInfoMessage = true; - } // This shouldn't happen: the caller should check we support this type // before trying to instantiate us if (!tileHandler) { diff --git a/src/components/views/rooms/ReplyTile.tsx b/src/components/views/rooms/ReplyTile.tsx index 19da3455792..054a920d649 100644 --- a/src/components/views/rooms/ReplyTile.tsx +++ b/src/components/views/rooms/ReplyTile.tsx @@ -28,6 +28,7 @@ import MImageReplyBody from "../messages/MImageReplyBody"; import * as sdk from '../../../index'; import { EventType, MsgType, RelationType } from 'matrix-js-sdk/src/@types/event'; import { replaceableComponent } from '../../../utils/replaceableComponent'; +import { getEventDisplayInfo } from '../../../utils/EventUtils'; interface IProps { mxEvent: MatrixEvent; @@ -80,28 +81,9 @@ export default class ReplyTile extends React.PureComponent { }; render() { - const content = this.props.mxEvent.getContent(); - const msgtype = content.msgtype; - const eventType = this.props.mxEvent.getType(); - - // Info messages are basically information about commands processed on a room - let isInfoMessage = ![ - EventType.RoomMessage, - EventType.Sticker, - EventType.RoomCreate, - ].includes(eventType as EventType); - - let tileHandler = getHandlerTile(this.props.mxEvent); - // If we're showing hidden events in the timeline, we should use the - // source tile when there's no regular tile for an event and also for - // replace relations (which otherwise would display as a confusing - // duplicate of the thing they are replacing). - const useSource = !tileHandler || this.props.mxEvent.isRelation(RelationType.Replace); - if (useSource && SettingsStore.getValue("showHiddenEventsInTimeline")) { - tileHandler = "messages.ViewSourceEvent"; - // Reuse info message avatar and sender profile styling - isInfoMessage = true; - } + const msgtype = this.props.mxEvent.getContent().msgtype; + + const { tileHandler, isInfoMessage } = getEventDisplayInfo(this.props.mxEvent); // This shouldn't happen: the caller should check we support this type // before trying to instantiate us if (!tileHandler) { diff --git a/src/utils/EventUtils.ts b/src/utils/EventUtils.ts index 1a467b157f6..d69c285e18f 100644 --- a/src/utils/EventUtils.ts +++ b/src/utils/EventUtils.ts @@ -19,6 +19,9 @@ import { MatrixEvent, EventStatus } from 'matrix-js-sdk/src/models/event'; import { MatrixClientPeg } from '../MatrixClientPeg'; import shouldHideEvent from "../shouldHideEvent"; +import { getHandlerTile, haveTileForEvent } from "../components/views/rooms/EventTile"; +import SettingsStore from "../settings/SettingsStore"; +import { EventType } from "matrix-js-sdk/src/@types/event"; /** * Returns whether an event should allow actions like reply, reactions, edit, etc. @@ -96,3 +99,38 @@ export function findEditableEvent(room: Room, isForward: boolean, fromEventId: s } } +export function getEventDisplayInfo(mxEvent: MatrixEvent): { + isInfoMessage: boolean; + tileHandler; + isBubbleMessage: boolean; +} { + const content = mxEvent.getContent(); + const msgtype = content.msgtype; + const eventType = mxEvent.getType(); + + let tileHandler = getHandlerTile(mxEvent); + + // Info messages are basically information about commands processed on a room + let isBubbleMessage = eventType.startsWith("m.key.verification") || + (eventType === EventType.RoomMessage && msgtype && msgtype.startsWith("m.key.verification")) || + (eventType === EventType.RoomCreate) || + (eventType === EventType.RoomEncryption) || + (tileHandler === "messages.MJitsiWidgetEvent"); + let isInfoMessage = ( + !isBubbleMessage && eventType !== EventType.RoomMessage && + eventType !== EventType.Sticker && eventType !== EventType.RoomCreate + ); + + // If we're showing hidden events in the timeline, we should use the + // source tile when there's no regular tile for an event and also for + // replace relations (which otherwise would display as a confusing + // duplicate of the thing they are replacing). + if (SettingsStore.getValue("showHiddenEventsInTimeline") && !haveTileForEvent(mxEvent)) { + tileHandler = "messages.ViewSourceEvent"; + isBubbleMessage = false; + // Reuse info message avatar and sender profile styling + isInfoMessage = true; + } + + return { tileHandler, isInfoMessage, isBubbleMessage }; +} From 1ec4ead62d38e63851e55ff3bcb7f51c4e9cbe09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 13:04:59 +0200 Subject: [PATCH 70/90] Unused imports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/EventTile.tsx | 1 - src/components/views/rooms/ReplyTile.tsx | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/components/views/rooms/EventTile.tsx b/src/components/views/rooms/EventTile.tsx index b1e75443a06..553b7801ccf 100644 --- a/src/components/views/rooms/EventTile.tsx +++ b/src/components/views/rooms/EventTile.tsx @@ -27,7 +27,6 @@ import { _t } from '../../../languageHandler'; import { hasText } from "../../../TextForEvent"; import * as sdk from "../../../index"; import dis from '../../../dispatcher/dispatcher'; -import SettingsStore from "../../../settings/SettingsStore"; import { Layout } from "../../../settings/Layout"; import { formatTime } from "../../../DateUtils"; import { MatrixClientPeg } from '../../../MatrixClientPeg'; diff --git a/src/components/views/rooms/ReplyTile.tsx b/src/components/views/rooms/ReplyTile.tsx index 054a920d649..c875553a961 100644 --- a/src/components/views/rooms/ReplyTile.tsx +++ b/src/components/views/rooms/ReplyTile.tsx @@ -18,15 +18,13 @@ import React from 'react'; import classNames from 'classnames'; import { _t } from '../../../languageHandler'; import dis from '../../../dispatcher/dispatcher'; -import SettingsStore from "../../../settings/SettingsStore"; -import { getHandlerTile } from "./EventTile"; import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import { RoomPermalinkCreator } from '../../../utils/permalinks/Permalinks'; import SenderProfile from "../messages/SenderProfile"; import TextualBody from "../messages/TextualBody"; import MImageReplyBody from "../messages/MImageReplyBody"; import * as sdk from '../../../index'; -import { EventType, MsgType, RelationType } from 'matrix-js-sdk/src/@types/event'; +import { EventType, MsgType } from 'matrix-js-sdk/src/@types/event'; import { replaceableComponent } from '../../../utils/replaceableComponent'; import { getEventDisplayInfo } from '../../../utils/EventUtils'; From 8f831a89f62769e360546dbe5c56cd21a8e7d6c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 13:07:47 +0200 Subject: [PATCH 71/90] Remove unused code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/elements/ReplyThread.js | 31 -------------------- 1 file changed, 31 deletions(-) diff --git a/src/components/views/elements/ReplyThread.js b/src/components/views/elements/ReplyThread.js index c22225f766a..434900c8dec 100644 --- a/src/components/views/elements/ReplyThread.js +++ b/src/components/views/elements/ReplyThread.js @@ -70,10 +70,7 @@ export default class ReplyThread extends React.Component { }; this.unmounted = false; - this.context.on("Event.replaced", this.onEventReplaced); this.room = this.context.getRoom(this.props.parentEv.getRoomId()); - this.room.on("Room.redaction", this.onRoomRedaction); - this.room.on("Room.redactionCancelled", this.onRoomRedaction); this.onQuoteClick = this.onQuoteClick.bind(this); this.canCollapse = this.canCollapse.bind(this); @@ -239,36 +236,8 @@ export default class ReplyThread extends React.Component { componentWillUnmount() { this.unmounted = true; - this.context.removeListener("Event.replaced", this.onEventReplaced); - if (this.room) { - this.room.removeListener("Room.redaction", this.onRoomRedaction); - this.room.removeListener("Room.redactionCancelled", this.onRoomRedaction); - } } - updateForEventId = (eventId) => { - if (this.state.events.some(event => event.getId() === eventId)) { - this.forceUpdate(); - } - }; - - onEventReplaced = (ev) => { - if (this.unmounted) return; - - // If one of the events we are rendering gets replaced, force a re-render - this.updateForEventId(ev.getId()); - }; - - onRoomRedaction = (ev) => { - if (this.unmounted) return; - - const eventId = ev.getAssociatedId(); - if (!eventId) return; - - // If one of the events we are rendering gets redacted, force a re-render - this.updateForEventId(eventId); - }; - async initialize() { const { parentEv } = this.props; // at time of making this component we checked that props.parentEv has a parentEventId From 1bca5371d1f6f92cff106e78861676390fa79801 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 13 Jul 2021 13:18:01 +0200 Subject: [PATCH 72/90] Fix redacted messages for the 100th #*&@*%^ time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/rooms/_ReplyTile.scss | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/res/css/views/rooms/_ReplyTile.scss b/res/css/views/rooms/_ReplyTile.scss index 007ed35ecfa..517ef79ef06 100644 --- a/res/css/views/rooms/_ReplyTile.scss +++ b/res/css/views/rooms/_ReplyTile.scss @@ -29,12 +29,13 @@ limitations under the License. color: $primary-fg-color; } -.mx_ReplyTile > .mx_RedactedBody { - padding: 18px; +.mx_ReplyTile .mx_RedactedBody { + padding: 4px 0 2px 20px; &::before { height: 13px; width: 13px; + top: 5px; } } From 9aae33e076443a9f9b38eff7426cb4cdfc59433b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 14 Jul 2021 09:28:37 +0200 Subject: [PATCH 73/90] Use string[] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/ReplyTile.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/rooms/ReplyTile.tsx b/src/components/views/rooms/ReplyTile.tsx index c875553a961..cb2815ee6a1 100644 --- a/src/components/views/rooms/ReplyTile.tsx +++ b/src/components/views/rooms/ReplyTile.tsx @@ -31,7 +31,7 @@ import { getEventDisplayInfo } from '../../../utils/EventUtils'; interface IProps { mxEvent: MatrixEvent; permalinkCreator?: RoomPermalinkCreator; - highlights?: Array; + highlights?: string[]; highlightLink?: string; onHeightChanged?(): void; } From 74ff85ae305c03e96647620fbc01b8b91bf5a132 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 14 Jul 2021 09:52:45 +0200 Subject: [PATCH 74/90] Remove m.sticker since it's not a message type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/ReplyTile.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/views/rooms/ReplyTile.tsx b/src/components/views/rooms/ReplyTile.tsx index cb2815ee6a1..41fc61aa7fb 100644 --- a/src/components/views/rooms/ReplyTile.tsx +++ b/src/components/views/rooms/ReplyTile.tsx @@ -117,7 +117,6 @@ export default class ReplyTile extends React.PureComponent { [MsgType.Image]: MImageReplyBody, // We don't want a download link for files, just the file name is enough. [MsgType.File]: TextualBody, - "m.sticker": TextualBody, [MsgType.Audio]: TextualBody, [MsgType.Video]: TextualBody, }; From 58dedbeeffdaa090d0ee0deebbac929b7ab2f753 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 14 Jul 2021 09:52:56 +0200 Subject: [PATCH 75/90] Add missing type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/utils/EventUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/EventUtils.ts b/src/utils/EventUtils.ts index d69c285e18f..849e5464858 100644 --- a/src/utils/EventUtils.ts +++ b/src/utils/EventUtils.ts @@ -101,7 +101,7 @@ export function findEditableEvent(room: Room, isForward: boolean, fromEventId: s export function getEventDisplayInfo(mxEvent: MatrixEvent): { isInfoMessage: boolean; - tileHandler; + tileHandler: string; isBubbleMessage: boolean; } { const content = mxEvent.getContent(); From 7b35d2c27046c432dcdb9b768c1de40a1ca03c4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 14 Jul 2021 09:53:40 +0200 Subject: [PATCH 76/90] FORCED_IMAGE_HEIGHT into a const MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/messages/MImageReplyBody.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/views/messages/MImageReplyBody.tsx b/src/components/views/messages/MImageReplyBody.tsx index b0f7415347f..44acf180044 100644 --- a/src/components/views/messages/MImageReplyBody.tsx +++ b/src/components/views/messages/MImageReplyBody.tsx @@ -20,6 +20,8 @@ import { presentableTextForFile } from "./MFileBody"; import { IMediaEventContent } from "../../../customisations/models/IMediaEventContent"; import SenderProfile from "./SenderProfile"; +const FORCED_IMAGE_HEIGHT = 44; + export default class MImageReplyBody extends MImageBody { public onClick = (ev: React.MouseEvent): void => { ev.preventDefault(); @@ -42,7 +44,7 @@ export default class MImageReplyBody extends MImageBody { const content = this.props.mxEvent.getContent(); const contentUrl = this.getContentUrl(); - const thumbnail = this.messageContent(contentUrl, this.getThumbUrl(), content, 44); + const thumbnail = this.messageContent(contentUrl, this.getThumbUrl(), content, FORCED_IMAGE_HEIGHT); const fileBody = this.getFileBody(); const sender = Date: Wed, 14 Jul 2021 09:54:33 +0200 Subject: [PATCH 77/90] Omit onFinished MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/messages/MImageBody.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/views/messages/MImageBody.tsx b/src/components/views/messages/MImageBody.tsx index 0acdbaf253f..74d15dd9b5d 100644 --- a/src/components/views/messages/MImageBody.tsx +++ b/src/components/views/messages/MImageBody.tsx @@ -115,12 +115,11 @@ export default class MImageBody extends React.Component { const content = this.props.mxEvent.getContent(); const httpUrl = this.getContentUrl(); - const params: ComponentProps = { + const params: Omit, "onFinished"> = { src: httpUrl, name: content.body?.length > 0 ? content.body : _t('Attachment'), mxEvent: this.props.mxEvent, permalinkCreator: this.props.permalinkCreator, - onFinished: () => {}, }; if (content.info) { From 4afd985e7e63e03586b8e7d003690f9ef6653621 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 14 Jul 2021 09:55:14 +0200 Subject: [PATCH 78/90] Kill off _afterComponentWillUnmount MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/messages/MImageBody.tsx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/components/views/messages/MImageBody.tsx b/src/components/views/messages/MImageBody.tsx index 74d15dd9b5d..96c8652aeec 100644 --- a/src/components/views/messages/MImageBody.tsx +++ b/src/components/views/messages/MImageBody.tsx @@ -316,7 +316,6 @@ export default class MImageBody extends React.Component { componentWillUnmount() { this.unmounted = true; this.context.removeListener('sync', this.onClientSync); - this._afterComponentWillUnmount(); if (this.state.decryptedUrl) { URL.revokeObjectURL(this.state.decryptedUrl); @@ -326,11 +325,6 @@ export default class MImageBody extends React.Component { } } - // To be overridden by subclasses (e.g. MStickerBody) for further - // cleanup after componentWillUnmount - _afterComponentWillUnmount() { - } - protected messageContent( contentUrl: string, thumbUrl: string, From 18355599e88107f342dcef78dc6e5aa58704b4c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 14 Jul 2021 10:07:41 +0200 Subject: [PATCH 79/90] Fix senderProfile getting cutoff MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/messages/_MImageReplyBody.scss | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/res/css/views/messages/_MImageReplyBody.scss b/res/css/views/messages/_MImageReplyBody.scss index f0401d21dbf..0b18308847c 100644 --- a/res/css/views/messages/_MImageReplyBody.scss +++ b/res/css/views/messages/_MImageReplyBody.scss @@ -21,12 +21,17 @@ limitations under the License. flex: 1; padding-right: 4px; } -} -.mx_MImageReplyBody_sender { - grid-area: sender; -} + .mx_MImageReplyBody_info { + flex: 1; -.mx_MImageReplyBody_filename { - grid-area: filename; + .mx_MImageReplyBody_sender { + grid-area: sender; + } + + .mx_MImageReplyBody_filename { + grid-area: filename; + } + } } + From 586e85cbff97da634fb7bf19491cffb2618487ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 14 Jul 2021 10:14:44 +0200 Subject: [PATCH 80/90] Use MFileBody in replies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/rooms/_ReplyTile.scss | 4 ++++ src/components/views/rooms/ReplyTile.tsx | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/res/css/views/rooms/_ReplyTile.scss b/res/css/views/rooms/_ReplyTile.scss index 517ef79ef06..552d54367e8 100644 --- a/res/css/views/rooms/_ReplyTile.scss +++ b/res/css/views/rooms/_ReplyTile.scss @@ -20,6 +20,10 @@ limitations under the License. font-size: $font-14px; position: relative; line-height: $font-16px; + + .mx_MFileBody_info { + margin: 5px 0; + } } .mx_ReplyTile > a { diff --git a/src/components/views/rooms/ReplyTile.tsx b/src/components/views/rooms/ReplyTile.tsx index 41fc61aa7fb..2911e538fc1 100644 --- a/src/components/views/rooms/ReplyTile.tsx +++ b/src/components/views/rooms/ReplyTile.tsx @@ -27,6 +27,7 @@ import * as sdk from '../../../index'; import { EventType, MsgType } from 'matrix-js-sdk/src/@types/event'; import { replaceableComponent } from '../../../utils/replaceableComponent'; import { getEventDisplayInfo } from '../../../utils/EventUtils'; +import MFileBody from "../messages/MFileBody"; interface IProps { mxEvent: MatrixEvent; @@ -116,7 +117,7 @@ export default class ReplyTile extends React.PureComponent { const msgtypeOverrides = { [MsgType.Image]: MImageReplyBody, // We don't want a download link for files, just the file name is enough. - [MsgType.File]: TextualBody, + [MsgType.File]: MFileBody, [MsgType.Audio]: TextualBody, [MsgType.Video]: TextualBody, }; From f26c75bdcc35f98c36ee4816ff72848f8c7ac9f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 14 Jul 2021 10:23:10 +0200 Subject: [PATCH 81/90] Use margin instead of padding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/messages/_MImageReplyBody.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/css/views/messages/_MImageReplyBody.scss b/res/css/views/messages/_MImageReplyBody.scss index 0b18308847c..70c53f8c9c4 100644 --- a/res/css/views/messages/_MImageReplyBody.scss +++ b/res/css/views/messages/_MImageReplyBody.scss @@ -19,7 +19,7 @@ limitations under the License. .mx_MImageBody_thumbnail_container { flex: 1; - padding-right: 4px; + margin-right: 4px; } .mx_MImageReplyBody_info { From ae4d8c291daf667a422dc6596d16ace2c3e5f927 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 14 Jul 2021 10:23:24 +0200 Subject: [PATCH 82/90] It's not an override MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/ReplyTile.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/views/rooms/ReplyTile.tsx b/src/components/views/rooms/ReplyTile.tsx index 2911e538fc1..a22fbc44948 100644 --- a/src/components/views/rooms/ReplyTile.tsx +++ b/src/components/views/rooms/ReplyTile.tsx @@ -27,7 +27,6 @@ import * as sdk from '../../../index'; import { EventType, MsgType } from 'matrix-js-sdk/src/@types/event'; import { replaceableComponent } from '../../../utils/replaceableComponent'; import { getEventDisplayInfo } from '../../../utils/EventUtils'; -import MFileBody from "../messages/MFileBody"; interface IProps { mxEvent: MatrixEvent; @@ -117,7 +116,6 @@ export default class ReplyTile extends React.PureComponent { const msgtypeOverrides = { [MsgType.Image]: MImageReplyBody, // We don't want a download link for files, just the file name is enough. - [MsgType.File]: MFileBody, [MsgType.Audio]: TextualBody, [MsgType.Video]: TextualBody, }; From 04db6beb108fea542db2bb3f25afc93dfe8caed4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 14 Jul 2021 10:30:24 +0200 Subject: [PATCH 83/90] Remove stale comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/ReplyTile.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/views/rooms/ReplyTile.tsx b/src/components/views/rooms/ReplyTile.tsx index a22fbc44948..8ac34afa286 100644 --- a/src/components/views/rooms/ReplyTile.tsx +++ b/src/components/views/rooms/ReplyTile.tsx @@ -115,7 +115,6 @@ export default class ReplyTile extends React.PureComponent { const msgtypeOverrides = { [MsgType.Image]: MImageReplyBody, - // We don't want a download link for files, just the file name is enough. [MsgType.Audio]: TextualBody, [MsgType.Video]: TextualBody, }; From 782563af5356281ef2a8264b32235554cec9a061 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 14 Jul 2021 10:47:29 +0200 Subject: [PATCH 84/90] Override audio and video body with file body MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/rooms/_ReplyTile.scss | 10 ++++++++-- src/components/views/rooms/ReplyTile.tsx | 6 ++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/res/css/views/rooms/_ReplyTile.scss b/res/css/views/rooms/_ReplyTile.scss index 552d54367e8..8fe3a3e94c1 100644 --- a/res/css/views/rooms/_ReplyTile.scss +++ b/res/css/views/rooms/_ReplyTile.scss @@ -21,8 +21,14 @@ limitations under the License. position: relative; line-height: $font-16px; - .mx_MFileBody_info { - margin: 5px 0; + .mx_MFileBody { + .mx_MFileBody_info { + margin: 5px 0; + } + + .mx_MFileBody_download { + display: none; + } } } diff --git a/src/components/views/rooms/ReplyTile.tsx b/src/components/views/rooms/ReplyTile.tsx index 8ac34afa286..f2f75c4918c 100644 --- a/src/components/views/rooms/ReplyTile.tsx +++ b/src/components/views/rooms/ReplyTile.tsx @@ -27,6 +27,7 @@ import * as sdk from '../../../index'; import { EventType, MsgType } from 'matrix-js-sdk/src/@types/event'; import { replaceableComponent } from '../../../utils/replaceableComponent'; import { getEventDisplayInfo } from '../../../utils/EventUtils'; +import MFileBody from "../messages/MFileBody"; interface IProps { mxEvent: MatrixEvent; @@ -115,8 +116,9 @@ export default class ReplyTile extends React.PureComponent { const msgtypeOverrides = { [MsgType.Image]: MImageReplyBody, - [MsgType.Audio]: TextualBody, - [MsgType.Video]: TextualBody, + // Override audio and video body with file body. We also hide the download/decrypt button using CSS + [MsgType.Audio]: MFileBody, + [MsgType.Video]: MFileBody, }; const evOverrides = { [EventType.Sticker]: TextualBody, From 6c801fea53530f37b8d309e871869d81d46d3e2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 14 Jul 2021 12:15:13 +0200 Subject: [PATCH 85/90] Use MImageReplyBody for stickers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/ReplyTile.tsx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/components/views/rooms/ReplyTile.tsx b/src/components/views/rooms/ReplyTile.tsx index f2f75c4918c..49c904a9409 100644 --- a/src/components/views/rooms/ReplyTile.tsx +++ b/src/components/views/rooms/ReplyTile.tsx @@ -80,7 +80,9 @@ export default class ReplyTile extends React.PureComponent { }; render() { - const msgtype = this.props.mxEvent.getContent().msgtype; + const mxEvent = this.props.mxEvent; + const msgtype = mxEvent.getContent().msgtype; + const evType = mxEvent.getType() as EventType; const { tileHandler, isInfoMessage } = getEventDisplayInfo(this.props.mxEvent); // This shouldn't happen: the caller should check we support this type @@ -105,7 +107,12 @@ export default class ReplyTile extends React.PureComponent { } let sender; - const needsSenderProfile = msgtype !== MsgType.Image && tileHandler !== EventType.RoomCreate && !isInfoMessage; + const needsSenderProfile = ( + !isInfoMessage && + msgtype !== MsgType.Image && + tileHandler !== EventType.RoomCreate && + evType !== EventType.Sticker + ); if (needsSenderProfile) { sender = { [MsgType.Video]: MFileBody, }; const evOverrides = { - [EventType.Sticker]: TextualBody, + // Use MImageReplyBody so that the sticker isn't taking up a lot of space + [EventType.Sticker]: MImageReplyBody, }; return ( From 54d2784818e7c6908052997266a3613de97b575f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Wed, 14 Jul 2021 12:19:16 +0200 Subject: [PATCH 86/90] Remove unused import MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/components/views/rooms/ReplyTile.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/views/rooms/ReplyTile.tsx b/src/components/views/rooms/ReplyTile.tsx index 49c904a9409..f44a75a2647 100644 --- a/src/components/views/rooms/ReplyTile.tsx +++ b/src/components/views/rooms/ReplyTile.tsx @@ -21,7 +21,6 @@ import dis from '../../../dispatcher/dispatcher'; import { MatrixEvent } from "matrix-js-sdk/src/models/event"; import { RoomPermalinkCreator } from '../../../utils/permalinks/Permalinks'; import SenderProfile from "../messages/SenderProfile"; -import TextualBody from "../messages/TextualBody"; import MImageReplyBody from "../messages/MImageReplyBody"; import * as sdk from '../../../index'; import { EventType, MsgType } from 'matrix-js-sdk/src/@types/event'; From 375e2798258f21578a66ac312f3c0eb4f04b3603 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 15 Jul 2021 15:15:48 +0200 Subject: [PATCH 87/90] Add speaker icon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/img/element-icons/speaker.svg | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 res/img/element-icons/speaker.svg diff --git a/res/img/element-icons/speaker.svg b/res/img/element-icons/speaker.svg new file mode 100644 index 00000000000..fd811d2cda8 --- /dev/null +++ b/res/img/element-icons/speaker.svg @@ -0,0 +1,5 @@ + + + + + From 68640a4dbd8f140013fd857334f42413acd4ede2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 15 Jul 2021 15:16:05 +0200 Subject: [PATCH 88/90] Fix icon postion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/messages/_MFileBody.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/res/css/views/messages/_MFileBody.scss b/res/css/views/messages/_MFileBody.scss index c215d69ec27..b91c461ce53 100644 --- a/res/css/views/messages/_MFileBody.scss +++ b/res/css/views/messages/_MFileBody.scss @@ -83,12 +83,12 @@ limitations under the License. mask-size: cover; mask-image: url('$(res)/img/element-icons/room/composer/attach.svg'); background-color: $message-body-panel-icon-fg-color; - width: 13px; + width: 15px; height: 15px; position: absolute; top: 8px; - left: 9px; + left: 8px; } } From 88da0f4dcf500c44c5bae2673b538f0f47ac76b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 15 Jul 2021 15:17:41 +0200 Subject: [PATCH 89/90] Give audio and video replies an icon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/rooms/_ReplyTile.scss | 8 ++++++++ src/components/views/rooms/ReplyTile.tsx | 6 ++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/res/css/views/rooms/_ReplyTile.scss b/res/css/views/rooms/_ReplyTile.scss index 8fe3a3e94c1..ccb00691900 100644 --- a/res/css/views/rooms/_ReplyTile.scss +++ b/res/css/views/rooms/_ReplyTile.scss @@ -21,6 +21,14 @@ limitations under the License. position: relative; line-height: $font-16px; + &.mx_ReplyTile_audio .mx_MFileBody_info_icon::before { + mask-image: url("$(res)/img/element-icons/speaker.svg"); + } + + &.mx_ReplyTile_video .mx_MFileBody_info_icon::before { + mask-image: url("$(res)/img/element-icons/call/video-call.svg"); + } + .mx_MFileBody { .mx_MFileBody_info { margin: 5px 0; diff --git a/src/components/views/rooms/ReplyTile.tsx b/src/components/views/rooms/ReplyTile.tsx index f44a75a2647..18b30d33d5a 100644 --- a/src/components/views/rooms/ReplyTile.tsx +++ b/src/components/views/rooms/ReplyTile.tsx @@ -80,7 +80,7 @@ export default class ReplyTile extends React.PureComponent { render() { const mxEvent = this.props.mxEvent; - const msgtype = mxEvent.getContent().msgtype; + const msgType = mxEvent.getContent().msgtype; const evType = mxEvent.getType() as EventType; const { tileHandler, isInfoMessage } = getEventDisplayInfo(this.props.mxEvent); @@ -98,6 +98,8 @@ export default class ReplyTile extends React.PureComponent { const classes = classNames("mx_ReplyTile", { mx_ReplyTile_info: isInfoMessage && !this.props.mxEvent.isRedacted(), + mx_ReplyTile_audio: msgType === MsgType.Audio, + mx_ReplyTile_video: msgType === MsgType.Video, }); let permalink = "#"; @@ -108,7 +110,7 @@ export default class ReplyTile extends React.PureComponent { let sender; const needsSenderProfile = ( !isInfoMessage && - msgtype !== MsgType.Image && + msgType !== MsgType.Image && tileHandler !== EventType.RoomCreate && evType !== EventType.Sticker ); From 5d0afdb70673fb1401c9986ba1f72c843a8b8593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 15 Jul 2021 15:38:07 +0200 Subject: [PATCH 90/90] Don't show line number in replies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/rooms/_ReplyTile.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/res/css/views/rooms/_ReplyTile.scss b/res/css/views/rooms/_ReplyTile.scss index ccb00691900..c8f76ee9951 100644 --- a/res/css/views/rooms/_ReplyTile.scss +++ b/res/css/views/rooms/_ReplyTile.scss @@ -76,6 +76,11 @@ limitations under the License. font-size: $font-14px !important; } + // Hide line numbers + .mx_EventTile_lineNumbers { + display: none; + } + // Hack to cut content in
 tags too
     .mx_EventTile_pre_container > pre {
         overflow: hidden;