Refactor TimelinePanel to avoid race conditions in React 18 between state updates (#28416)
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
parent
3132fe3233
commit
f77d9b4bcb
1 changed files with 14 additions and 9 deletions
|
@ -1217,7 +1217,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const lastDisplayedEvent = this.state.events[lastDisplayedIndex];
|
const lastDisplayedEvent = this.state.events[lastDisplayedIndex];
|
||||||
this.setReadMarker(lastDisplayedEvent.getId()!, lastDisplayedEvent.getTs());
|
await this.setReadMarker(lastDisplayedEvent.getId()!, lastDisplayedEvent.getTs());
|
||||||
|
|
||||||
// the read-marker should become invisible, so that if the user scrolls
|
// the read-marker should become invisible, so that if the user scrolls
|
||||||
// down, they don't see it.
|
// down, they don't see it.
|
||||||
|
@ -1335,7 +1335,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the read marker to the values we found
|
// Update the read marker to the values we found
|
||||||
this.setReadMarker(rmId, rmTs);
|
await this.setReadMarker(rmId, rmTs);
|
||||||
|
|
||||||
// Send the receipts to the server immediately (don't wait for activity)
|
// Send the receipts to the server immediately (don't wait for activity)
|
||||||
await this.sendReadReceipts();
|
await this.sendReadReceipts();
|
||||||
|
@ -1866,7 +1866,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
||||||
return receiptStore?.getEventReadUpTo(myUserId, ignoreSynthesized) ?? null;
|
return receiptStore?.getEventReadUpTo(myUserId, ignoreSynthesized) ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private setReadMarker(eventId: string | null, eventTs?: number, inhibitSetState = false): void {
|
private async setReadMarker(eventId: string | null, eventTs?: number, inhibitSetState = false): Promise<void> {
|
||||||
const roomId = this.props.timelineSet.room?.roomId;
|
const roomId = this.props.timelineSet.room?.roomId;
|
||||||
|
|
||||||
// don't update the state (and cause a re-render) if there is
|
// don't update the state (and cause a re-render) if there is
|
||||||
|
@ -1890,12 +1890,17 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
||||||
// Do the local echo of the RM
|
// Do the local echo of the RM
|
||||||
// run the render cycle before calling the callback, so that
|
// run the render cycle before calling the callback, so that
|
||||||
// getReadMarkerPosition() returns the right thing.
|
// getReadMarkerPosition() returns the right thing.
|
||||||
|
await new Promise<void>((resolve) => {
|
||||||
this.setState(
|
this.setState(
|
||||||
{
|
{
|
||||||
readMarkerEventId: eventId,
|
readMarkerEventId: eventId,
|
||||||
},
|
},
|
||||||
this.props.onReadMarkerUpdated,
|
() => {
|
||||||
|
this.props.onReadMarkerUpdated?.();
|
||||||
|
resolve();
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private shouldPaginate(): boolean {
|
private shouldPaginate(): boolean {
|
||||||
|
|
Loading…
Reference in a new issue