From acd12c38a9a1de19b10708be6be10d87cbdbe32d Mon Sep 17 00:00:00 2001 From: Germain Date: Thu, 3 Mar 2022 15:22:16 +0000 Subject: [PATCH] Fix threads timeline message ordering (#7968) --- src/components/structures/ThreadView.tsx | 30 ++++++++++++------- src/components/structures/TimelinePanel.tsx | 16 ++++++++++ .../notifications/ThreadNotificationState.ts | 2 +- 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/components/structures/ThreadView.tsx b/src/components/structures/ThreadView.tsx index c5d404a901..7509c64dd6 100644 --- a/src/components/structures/ThreadView.tsx +++ b/src/components/structures/ThreadView.tsx @@ -186,8 +186,10 @@ export default class ThreadView extends React.Component { }, async () => { thread.emit(ThreadEvent.ViewThread); if (!thread.initialEventsFetched) { - await thread.fetchInitialEvents(); + const { nextBatch } = await thread.fetchInitialEvents(); + this.nextBatch = nextBatch; } + this.timelinePanel.current?.refreshTimeline(); }); } @@ -241,29 +243,35 @@ export default class ThreadView extends React.Component { } }; + private nextBatch: string; + private onPaginationRequest = async ( timelineWindow: TimelineWindow | null, direction = Direction.Backward, limit = 20, ): Promise => { if (!Thread.hasServerSideSupport) { - return false; + timelineWindow.extend(direction, limit); + return true; } - const timelineIndex = timelineWindow.getTimelineIndex(direction); - - const paginationKey = direction === Direction.Backward ? "from" : "to"; - const paginationToken = timelineIndex.timeline.getPaginationToken(direction); - const opts: IRelationsRequestOpts = { limit, - [paginationKey]: paginationToken, - direction, }; - await this.state.thread.fetchEvents(opts); + if (this.nextBatch) { + opts.from = this.nextBatch; + } - return timelineWindow.paginate(direction, limit); + const { nextBatch } = await this.state.thread.fetchEvents(opts); + + this.nextBatch = nextBatch; + + // Advances the marker on the TimelineWindow to define the correct + // window of events to display on screen + timelineWindow.extend(direction, limit); + + return !!nextBatch; }; private onFileDrop = (dataTransfer: DataTransfer) => { diff --git a/src/components/structures/TimelinePanel.tsx b/src/components/structures/TimelinePanel.tsx index 35818629bf..f968cb6a19 100644 --- a/src/components/structures/TimelinePanel.tsx +++ b/src/components/structures/TimelinePanel.tsx @@ -27,6 +27,7 @@ import { RoomMember, RoomMemberEvent } from 'matrix-js-sdk/src/models/room-membe import { debounce } from 'lodash'; import { logger } from "matrix-js-sdk/src/logger"; import { ClientEvent } from "matrix-js-sdk/src/client"; +import { Thread } from 'matrix-js-sdk/src/models/thread'; import SettingsStore from "../../settings/SettingsStore"; import { Layout } from "../../settings/enums/Layout"; @@ -540,6 +541,21 @@ class TimelinePanel extends React.Component { // ignore events for other timeline sets if (data.timeline.getTimelineSet() !== this.props.timelineSet) return; + if (!Thread.hasServerSideSupport && this.context.timelineRenderingType === TimelineRenderingType.Thread) { + // const direction = toStartOfTimeline ? Direction.Backward : Direction.Forward; + // this.timelineWindow.extend(direction, 1); + if (toStartOfTimeline && !this.state.canBackPaginate) { + this.setState({ + canBackPaginate: true, + }); + } + if (!toStartOfTimeline && !this.state.canForwardPaginate) { + this.setState({ + canForwardPaginate: true, + }); + } + } + // ignore anything but real-time updates at the end of the room: // updates from pagination will happen when the paginate completes. if (toStartOfTimeline || !data || !data.liveEvent) return; diff --git a/src/stores/notifications/ThreadNotificationState.ts b/src/stores/notifications/ThreadNotificationState.ts index b2f8e26406..70209d398d 100644 --- a/src/stores/notifications/ThreadNotificationState.ts +++ b/src/stores/notifications/ThreadNotificationState.ts @@ -47,7 +47,7 @@ export class ThreadNotificationState extends NotificationState implements IDestr const isOwn = myUserId === event.getSender(); const readReceipt = this.thread.room.getReadReceiptForUserId(myUserId); - if (!isOwn && !readReceipt || event.getTs() >= readReceipt.data.ts) { + if (!isOwn && !readReceipt || (readReceipt && event.getTs() >= readReceipt.data.ts)) { const actions = client.getPushActionsForEvent(event, true); if (actions?.tweaks) {