diff --git a/src/components/structures/TimelinePanel.tsx b/src/components/structures/TimelinePanel.tsx index c92836e1a7b..9a115e99a82 100644 --- a/src/components/structures/TimelinePanel.tsx +++ b/src/components/structures/TimelinePanel.tsx @@ -24,7 +24,7 @@ import { TimelineWindow } from "matrix-js-sdk/src/timeline-window"; import { EventType, RelationType } from 'matrix-js-sdk/src/@types/event'; import { SyncState } from 'matrix-js-sdk/src/sync'; import { RoomMember, RoomMemberEvent } from 'matrix-js-sdk/src/models/room-member'; -import { debounce } from 'lodash'; +import { debounce, throttle } 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'; @@ -806,16 +806,20 @@ class TimelinePanel extends React.Component { // Can be null for the notification timeline, etc. if (!this.props.timelineSet.room) return; + if (ev.getRoomId() !== this.props.timelineSet.room.roomId) return; + + if (!this.state.events.includes(ev)) return; + + this.recheckFirstVisibleEventIndex(); + // Need to update as we don't display event tiles for events that // haven't yet been decrypted. The event will have just been updated // in place so we just need to re-render. // TODO: We should restrict this to only events in our timeline, // but possibly the event tile itself should just update when this // happens to save us re-rendering the whole timeline. - if (ev.getRoomId() === this.props.timelineSet.room.roomId) { - this.buildCallEventGroupers(this.state.events); - this.forceUpdate(); - } + this.buildCallEventGroupers(this.state.events); + this.forceUpdate(); }; private onSync = (clientSyncState: SyncState, prevState: SyncState, data: object): void => { @@ -823,6 +827,13 @@ class TimelinePanel extends React.Component { this.setState({ clientSyncState }); }; + private recheckFirstVisibleEventIndex = throttle((): void => { + const firstVisibleEventIndex = this.checkForPreJoinUISI(this.state.events); + if (firstVisibleEventIndex !== this.state.firstVisibleEventIndex) { + this.setState({ firstVisibleEventIndex }); + } + }, 500, { leading: true, trailing: true }); + private readMarkerTimeout(readMarkerPosition: number): number { return readMarkerPosition === 0 ? this.context?.readMarkerInViewThresholdMs ?? this.state.readMarkerInViewThresholdMs :