Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit 50f8c61

Browse files
authored
Fix search results view for layouts other than Group/Modern (#7648)
1 parent 31e6b94 commit 50f8c61

File tree

6 files changed

+69
-26
lines changed

6 files changed

+69
-26
lines changed

res/css/structures/_RoomView.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,10 @@ limitations under the License.
209209
.mx_RoomView_searchResultsPanel {
210210
.mx_RoomView_messageListWrapper {
211211
justify-content: flex-start;
212+
213+
> .mx_RoomView_MessageList > li > ol {
214+
list-style-type: none;
215+
}
212216
}
213217

214218
a {

src/components/structures/MessagePanel.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ import { RoomPermalinkCreator } from "../../utils/permalinks/Permalinks";
5252
import EditorStateTransfer from "../../utils/EditorStateTransfer";
5353
import { Action } from '../../dispatcher/actions';
5454
import { getEventDisplayInfo } from "../../utils/EventUtils";
55+
import { IReadReceiptInfo } from "../views/rooms/ReadReceiptMarker";
5556

5657
const CONTINUATION_MAX_INTERVAL = 5 * 60 * 1000; // 5 minutes
5758
const continuedTypes = [EventType.Sticker, EventType.RoomMessage];
@@ -72,7 +73,7 @@ export function shouldFormContinuation(
7273
): boolean {
7374
if (timelineRenderingType === TimelineRenderingType.ThreadsList) return false;
7475
// sanity check inputs
75-
if (!prevEvent || !prevEvent.sender || !mxEvent.sender) return false;
76+
if (!prevEvent?.sender || !mxEvent.sender) return false;
7677
// check if within the max continuation period
7778
if (mxEvent.getTs() - prevEvent.getTs() > CONTINUATION_MAX_INTERVAL) return false;
7879

@@ -208,7 +209,7 @@ export default class MessagePanel extends React.Component<IProps, IState> {
208209

209210
// opaque readreceipt info for each userId; used by ReadReceiptMarker
210211
// to manage its animations
211-
private readonly readReceiptMap: Record<string, object> = {};
212+
private readonly readReceiptMap: { [userId: string]: IReadReceiptInfo } = {};
212213

213214
// Track read receipts by event ID. For each _shown_ event ID, we store
214215
// the list of read receipts to display:

src/components/structures/RoomView.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1783,6 +1783,13 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
17831783
});
17841784
};
17851785

1786+
private get messagePanelClassNames(): string {
1787+
return classNames("mx_RoomView_messagePanel", {
1788+
mx_IRCLayout: this.state.layout === Layout.IRC,
1789+
mx_GroupLayout: this.state.layout === Layout.Group,
1790+
});
1791+
}
1792+
17861793
render() {
17871794
if (!this.state.room) {
17881795
const loading = !this.state.matrixClientIsReady || this.state.roomLoading || this.state.peekLoading;
@@ -2068,7 +2075,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
20682075
searchResultsPanel = (
20692076
<ScrollPanel
20702077
ref={this.searchResultsPanel}
2071-
className="mx_RoomView_messagePanel mx_RoomView_searchResultsPanel mx_GroupLayout"
2078+
className={"mx_RoomView_searchResultsPanel " + this.messagePanelClassNames}
20722079
onFillRequest={this.onSearchResultsFillRequest}
20732080
resizeNotifier={this.props.resizeNotifier}
20742081
>
@@ -2085,13 +2092,6 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
20852092
highlightedEventId = this.state.initialEventId;
20862093
}
20872094

2088-
const messagePanelClassNames = classNames(
2089-
"mx_RoomView_messagePanel",
2090-
{
2091-
"mx_IRCLayout": this.state.layout == Layout.IRC,
2092-
"mx_GroupLayout": this.state.layout == Layout.Group,
2093-
});
2094-
20952095
// console.info("ShowUrlPreview for %s is %s", this.state.room.roomId, this.state.showUrlPreview);
20962096
const messagePanel = (
20972097
<TimelinePanel
@@ -2109,7 +2109,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
21092109
onUserScroll={this.onUserScroll}
21102110
onReadMarkerUpdated={this.updateTopUnreadMessagesBar}
21112111
showUrlPreview={this.state.showUrlPreview}
2112-
className={messagePanelClassNames}
2112+
className={this.messagePanelClassNames}
21132113
membersLoaded={this.state.membersLoaded}
21142114
permalinkCreator={this.getPermalinkCreatorForRoom(this.state.room)}
21152115
resizeNotifier={this.props.resizeNotifier}

src/components/views/rooms/EventTile.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ import MemberAvatar from '../avatars/MemberAvatar';
5555
import SenderProfile from '../messages/SenderProfile';
5656
import MessageTimestamp from '../messages/MessageTimestamp';
5757
import TooltipButton from '../elements/TooltipButton';
58-
import ReadReceiptMarker from "./ReadReceiptMarker";
58+
import ReadReceiptMarker, { IReadReceiptInfo } from "./ReadReceiptMarker";
5959
import MessageActionBar from "../messages/MessageActionBar";
6060
import ReactionsRow from '../messages/ReactionsRow';
6161
import { getEventDisplayInfo } from '../../../utils/EventUtils';
@@ -262,8 +262,7 @@ interface IProps {
262262
// opaque readreceipt info for each userId; used by ReadReceiptMarker
263263
// to manage its animations. Should be an empty object when the room
264264
// first loads
265-
// TODO: Proper typing for RR info
266-
readReceiptMap?: any;
265+
readReceiptMap?: { [userId: string]: IReadReceiptInfo };
267266

268267
// A function which is used to check if the parent panel is being
269268
// unmounted, to avoid unnecessary work. Should return true if we
@@ -929,7 +928,7 @@ export default class EventTile extends React.Component<IProps, IState> {
929928
left = (hidden ? MAX_READ_AVATARS - 1 : i) * -receiptOffset;
930929

931930
const userId = receipt.userId;
932-
let readReceiptInfo;
931+
let readReceiptInfo: IReadReceiptInfo;
933932

934933
if (this.props.readReceiptMap) {
935934
readReceiptInfo = this.props.readReceiptMap[userId];

src/components/views/rooms/ReadReceiptMarker.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ import { toPx } from "../../../utils/units";
2626
import { replaceableComponent } from "../../../utils/replaceableComponent";
2727
import MemberAvatar from '../avatars/MemberAvatar';
2828

29+
export interface IReadReceiptInfo {
30+
top?: number;
31+
left?: number;
32+
parent?: Element;
33+
}
34+
2935
interface IProps {
3036
// the RoomMember to show the RR for
3137
member?: RoomMember;
@@ -43,10 +49,8 @@ interface IProps {
4349
// don't animate this RR into position
4450
suppressAnimation?: boolean;
4551

46-
// an opaque object for storing information about this user's RR in
47-
// this room
48-
// TODO: proper typing for RR info
49-
readReceiptInfo: any;
52+
// an opaque object for storing information about this user's RR in this room
53+
readReceiptInfo: IReadReceiptInfo;
5054

5155
// A function which is used to check if the parent panel is being
5256
// unmounted, to avoid unnecessary work. Should return true if we

src/components/views/rooms/SearchResultTile.tsx

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import { RoomPermalinkCreator } from '../../../utils/permalinks/Permalinks';
2525
import { replaceableComponent } from "../../../utils/replaceableComponent";
2626
import DateSeparator from "../messages/DateSeparator";
2727
import EventTile, { haveTileForEvent } from "./EventTile";
28+
import { shouldFormContinuation } from "../../structures/MessagePanel";
29+
import { wantsDateSeparator } from "../../../DateUtils";
2830

2931
interface IProps {
3032
// a matrix-js-sdk SearchResult containing the details of this result
@@ -43,10 +45,10 @@ export default class SearchResultTile extends React.Component<IProps> {
4345

4446
public render() {
4547
const result = this.props.searchResult;
46-
const mxEv = result.context.getEvent();
47-
const eventId = mxEv.getId();
48+
const resultEvent = result.context.getEvent();
49+
const eventId = resultEvent.getId();
4850

49-
const ts1 = mxEv.getTs();
51+
const ts1 = resultEvent.getTs();
5052
const ret = [<DateSeparator key={ts1 + "-search"} ts={ts1} />];
5153
const layout = SettingsStore.getValue("layout");
5254
const isTwelveHour = SettingsStore.getValue("showTwelveHourTimestamps");
@@ -55,17 +57,46 @@ export default class SearchResultTile extends React.Component<IProps> {
5557

5658
const timeline = result.context.getTimeline();
5759
for (let j = 0; j < timeline.length; j++) {
58-
const ev = timeline[j];
60+
const mxEv = timeline[j];
5961
let highlights;
6062
const contextual = (j != result.context.getOurEventIndex());
6163
if (!contextual) {
6264
highlights = this.props.searchHighlights;
6365
}
64-
if (haveTileForEvent(ev, this.context?.showHiddenEventsInTimeline)) {
66+
67+
if (haveTileForEvent(mxEv, this.context?.showHiddenEventsInTimeline)) {
68+
// do we need a date separator since the last event?
69+
const prevEv = timeline[j - 1];
70+
// is this a continuation of the previous message?
71+
const continuation = prevEv &&
72+
!wantsDateSeparator(prevEv.getDate(), mxEv.getDate()) &&
73+
shouldFormContinuation(
74+
prevEv,
75+
mxEv,
76+
this.context?.showHiddenEventsInTimeline,
77+
TimelineRenderingType.Search,
78+
);
79+
80+
let lastInSection = true;
81+
const nextEv = timeline[j + 1];
82+
if (nextEv) {
83+
const willWantDateSeparator = wantsDateSeparator(mxEv.getDate(), nextEv.getDate());
84+
lastInSection = (
85+
willWantDateSeparator ||
86+
mxEv.getSender() !== nextEv.getSender() ||
87+
!shouldFormContinuation(
88+
mxEv,
89+
nextEv,
90+
this.context?.showHiddenEventsInTimeline,
91+
TimelineRenderingType.Search,
92+
)
93+
);
94+
}
95+
6596
ret.push(
6697
<EventTile
6798
key={`${eventId}+${j}`}
68-
mxEvent={ev}
99+
mxEvent={mxEv}
69100
layout={layout}
70101
contextual={contextual}
71102
highlights={highlights}
@@ -76,11 +107,15 @@ export default class SearchResultTile extends React.Component<IProps> {
76107
alwaysShowTimestamps={alwaysShowTimestamps}
77108
enableFlair={enableFlair}
78109
timelineRenderingType={TimelineRenderingType.Search}
110+
lastInSection={lastInSection}
111+
continuation={continuation}
79112
/>,
80113
);
81114
}
82115
}
83116

84-
return <li data-scroll-tokens={eventId}>{ ret }</li>;
117+
return <li data-scroll-tokens={eventId}>
118+
<ol>{ ret }</ol>
119+
</li>;
85120
}
86121
}

0 commit comments

Comments
 (0)