From 4e9462f5950b6720c617ac3dd85d9fc0c6f62b53 Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Tue, 30 Nov 2021 12:09:10 +0000 Subject: [PATCH 1/2] Send read receipts for events in thread's timeline --- src/components/structures/ThreadView.tsx | 9 +++++---- src/components/structures/TimelinePanel.tsx | 6 +----- src/components/views/rooms/EventTile.tsx | 1 + 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/components/structures/ThreadView.tsx b/src/components/structures/ThreadView.tsx index 2e618d6bece..5cf8f4a9b6e 100644 --- a/src/components/structures/ThreadView.tsx +++ b/src/components/structures/ThreadView.tsx @@ -242,10 +242,11 @@ export default class ThreadView extends React.Component { { this.state.thread && ( { let shouldSendRR = true; const currentRREventId = this.getCurrentReadReceipt(true); - const currentRREventIndex = this.indexForEventId(currentRREventId); // We want to avoid sending out read receipts when we are looking at // events in the past which are before the latest RR. // @@ -745,7 +744,7 @@ class TimelinePanel extends React.Component { // RRs) - but that is a bit of a niche case. It will sort itself out when // the user eventually hits the live timeline. // - if (currentRREventId && currentRREventIndex === null && + if (currentRREventId && this.timelineWindow.canPaginate(EventTimeline.FORWARDS)) { shouldSendRR = false; } @@ -758,9 +757,6 @@ class TimelinePanel extends React.Component { } let lastReadEvent = this.state.events[lastReadEventIndex]; shouldSendRR = shouldSendRR && - // Only send a RR if the last read event is ahead in the timeline relative to - // the current RR event. - lastReadEventIndex > currentRREventIndex && // Only send a RR if the last RR set != the one we would send this.lastRRSentEventId != lastReadEvent.getId(); diff --git a/src/components/views/rooms/EventTile.tsx b/src/components/views/rooms/EventTile.tsx index 12ab121b9d3..8cf59a2d5d0 100644 --- a/src/components/views/rooms/EventTile.tsx +++ b/src/components/views/rooms/EventTile.tsx @@ -1294,6 +1294,7 @@ export default class EventTile extends React.Component { case TileShape.Thread: { const room = this.context.getRoom(this.props.mxEvent.getRoomId()); return React.createElement(this.props.as || "li", { + "ref": this.ref, "className": classes, "aria-live": ariaLive, "aria-atomic": true, From bf1e0ac039ca18ce48513e952a29d37ac588836b Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Wed, 1 Dec 2021 10:21:56 +0000 Subject: [PATCH 2/2] Make indexForEventId always return 0 for thread messages --- src/components/structures/TimelinePanel.tsx | 23 ++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/components/structures/TimelinePanel.tsx b/src/components/structures/TimelinePanel.tsx index fa9da2c2fcf..b4ff8827020 100644 --- a/src/components/structures/TimelinePanel.tsx +++ b/src/components/structures/TimelinePanel.tsx @@ -28,7 +28,7 @@ import SettingsStore from "../../settings/SettingsStore"; import { Layout } from "../../settings/enums/Layout"; import { _t } from '../../languageHandler'; import { MatrixClientPeg } from "../../MatrixClientPeg"; -import RoomContext from "../../contexts/RoomContext"; +import RoomContext, { TimelineRenderingType } from "../../contexts/RoomContext"; import UserActivity from "../../UserActivity"; import Modal from "../../Modal"; import dis from "../../dispatcher/dispatcher"; @@ -731,6 +731,7 @@ class TimelinePanel extends React.Component { let shouldSendRR = true; const currentRREventId = this.getCurrentReadReceipt(true); + const currentRREventIndex = this.indexForEventId(currentRREventId); // We want to avoid sending out read receipts when we are looking at // events in the past which are before the latest RR. // @@ -744,7 +745,7 @@ class TimelinePanel extends React.Component { // RRs) - but that is a bit of a niche case. It will sort itself out when // the user eventually hits the live timeline. // - if (currentRREventId && + if (currentRREventId && currentRREventIndex === null && this.timelineWindow.canPaginate(EventTimeline.FORWARDS)) { shouldSendRR = false; } @@ -757,6 +758,9 @@ class TimelinePanel extends React.Component { } let lastReadEvent = this.state.events[lastReadEventIndex]; shouldSendRR = shouldSendRR && + // Only send a RR if the last read event is ahead in the timeline relative to + // the current RR event. + lastReadEventIndex > currentRREventIndex && // Only send a RR if the last RR set != the one we would send this.lastRRSentEventId != lastReadEvent.getId(); @@ -1306,12 +1310,17 @@ class TimelinePanel extends React.Component { } private indexForEventId(evId: string): number | null { - for (let i = 0; i < this.state.events.length; ++i) { - if (evId == this.state.events[i].getId()) { - return i; - } + /* Threads do not have server side support for read receipts and the concept + is very tied to the main room timeline, we are forcing the timeline to + send read receipts for threaded events */ + const isThreadTimeline = this.context.timelineRenderingType === TimelineRenderingType.Thread; + if (SettingsStore.getValue("feature_thread") && isThreadTimeline) { + return 0; } - return null; + const index = this.state.events.findIndex(ev => ev.getId() === evId); + return index > -1 + ? index + : null; } private getLastDisplayedEventIndex(opts: IEventIndexOpts = {}): number | null {