diff --git a/res/css/views/rooms/_EventTile.scss b/res/css/views/rooms/_EventTile.scss index 53339bb965..6e950dea84 100644 --- a/res/css/views/rooms/_EventTile.scss +++ b/res/css/views/rooms/_EventTile.scss @@ -24,6 +24,11 @@ $left-gutter: 64px; font-size: $font-14px; position: relative; + .mx_ThreadInfo { + margin-right: 110px; + margin-left: 64px; + } + &.mx_EventTile_info { padding-top: 1px; } @@ -693,7 +698,7 @@ $left-gutter: 64px; justify-content: flex-start; clear: both; - &:hover, &-active { + &:hover { cursor: pointer; border: 1px solid $quinary-content; padding-top: 7px; @@ -785,6 +790,12 @@ $left-gutter: 64px; left: auto; right: 0; } + + .mx_ReactionsRow { + order: 999; + padding-left: 0; + padding-right: 0; + } } .mx_MessageComposer_sendMessage { diff --git a/src/components/structures/MessagePanel.tsx b/src/components/structures/MessagePanel.tsx index 79aeea8321..4660423678 100644 --- a/src/components/structures/MessagePanel.tsx +++ b/src/components/structures/MessagePanel.tsx @@ -560,6 +560,9 @@ export default class MessagePanel extends React.Component { } private get pendingEditItem(): string | undefined { + if (!this.props.room) { + return undefined; + } try { return localStorage.getItem(`mx_edit_room_${this.props.room.roomId}_${this.context.timelineRenderingType}`); } catch (err) { diff --git a/src/components/structures/ThreadPanel.tsx b/src/components/structures/ThreadPanel.tsx index 2c3cba683b..4e278f5cce 100644 --- a/src/components/structures/ThreadPanel.tsx +++ b/src/components/structures/ThreadPanel.tsx @@ -64,10 +64,10 @@ const useFilteredThreadsTimelinePanel = ({ filterOption: ThreadFilterType; updateTimeline: () => void; }) => { - const timelineSet = useMemo(() => new EventTimelineSet(room, { - unstableClientRelationAggregation: true, + const timelineSet = useMemo(() => new EventTimelineSet(null, { timelineSupport: true, - }), [room]); + unstableClientRelationAggregation: true, + }), []); useEffect(() => { let filteredThreads = Array.from(threads); @@ -217,7 +217,7 @@ const ThreadPanel: React.FC = ({ roomId, onClose }) => { showReactions={true} className="mx_RoomView_messagePanel mx_GroupLayout" membersLoaded={true} - tileShape={TileShape.Thread} + tileShape={TileShape.ThreadPanel} /> diff --git a/src/components/views/rooms/EventTile.tsx b/src/components/views/rooms/EventTile.tsx index cd24ca8781..db76091025 100644 --- a/src/components/views/rooms/EventTile.tsx +++ b/src/components/views/rooms/EventTile.tsx @@ -561,13 +561,14 @@ export default class EventTile extends React.Component { thread.addEvent(this.props.mxEvent, true); } - if (!thread || this.props.showThreadInfo === false || thread.length <= 1) { + if (!thread || this.props.showThreadInfo === false || thread.length === 0) { return null; } - const threadMessagePreview = MessagePreviewStore.instance.generateThreadPreview(this.state.thread); - - if (!threadMessagePreview) return null; + const [lastEvent] = thread.events + .filter(event => event.isThreadRelation) + .slice(-1); + const threadMessagePreview = MessagePreviewStore.instance.generatePreviewForEvent(lastEvent); return (
{ { _t("%(count)s reply", { - count: thread.length - 1, + count: thread.length, }) } - -
- - { threadMessagePreview } - -
+ { (threadMessagePreview && lastEvent.sender) && <> + +
+ + { threadMessagePreview } + +
+ }
); } @@ -1214,7 +1217,7 @@ export default class EventTile extends React.Component { ]); } case TileShape.Thread: { - const thread = haveTileForEvent(this.props.mxEvent) && + const replyChain = haveTileForEvent(this.props.mxEvent) && ReplyChain.hasReply(this.props.mxEvent) ? ( { "aria-live": ariaLive, "aria-atomic": true, "data-scroll-tokens": scrollToken, - "data-has-reply": !!thread, + "data-has-reply": !!replyChain, }, [
@@ -1249,7 +1252,7 @@ export default class EventTile extends React.Component {
,
- { thread } + { replyChain } { /> { actionBar }
, + reactionsRow, ]); } case TileShape.FileGrid: { @@ -1297,7 +1301,7 @@ export default class EventTile extends React.Component { } default: { - const thread = haveTileForEvent(this.props.mxEvent) && + const replyChain = haveTileForEvent(this.props.mxEvent) && ReplyChain.hasReply(this.props.mxEvent) ? ( { "data-scroll-tokens": scrollToken, "data-layout": this.props.layout, "data-self": isOwnEvent, - "data-has-reply": !!thread, + "data-has-reply": !!replyChain, "onMouseEnter": () => this.setState({ hover: true }), "onMouseLeave": () => this.setState({ hover: false }), }, <> @@ -1334,7 +1338,7 @@ export default class EventTile extends React.Component {
{ groupTimestamp } { groupPadlock } - { thread } + { replyChain } { return previews.get(inTagId); } - public generateThreadPreview(thread: Thread): string { - const lastEvent = thread.replyToEvent; - const previewDef = PREVIEWS[lastEvent.getType()]; + public generatePreviewForEvent(event: MatrixEvent): string { + const previewDef = PREVIEWS[event.getType()]; // TODO: Handle case where we don't have if (!previewDef) return ''; - const previewText = previewDef.previewer.getTextFor(lastEvent, null, true); + const previewText = previewDef.previewer.getTextFor(event, null, true); return previewText ?? ''; }