Fix CallEventGrouper map building to not occur during a Render phase (#7638)
This commit is contained in:
parent
ae490841c6
commit
f2249b3e37
4 changed files with 45 additions and 23 deletions
|
@ -170,6 +170,7 @@ export default class CallEventGrouper extends EventEmitter {
|
|||
};
|
||||
|
||||
public add(event: MatrixEvent) {
|
||||
if (this.events.has(event)) return; // nothing to do
|
||||
this.events.add(event);
|
||||
this.setCall();
|
||||
}
|
||||
|
|
|
@ -183,6 +183,8 @@ interface IProps {
|
|||
|
||||
hideThreadedMessages?: boolean;
|
||||
disableGrouping?: boolean;
|
||||
|
||||
callEventGroupers: Map<string, CallEventGrouper>;
|
||||
}
|
||||
|
||||
interface IState {
|
||||
|
@ -254,9 +256,6 @@ export default class MessagePanel extends React.Component<IProps, IState> {
|
|||
private readonly showTypingNotificationsWatcherRef: string;
|
||||
private eventTiles: Record<string, EventTile> = {};
|
||||
|
||||
// A map of <callId, CallEventGrouper>
|
||||
private callEventGroupers = new Map<string, CallEventGrouper>();
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
|
@ -650,20 +649,6 @@ export default class MessagePanel extends React.Component<IProps, IState> {
|
|||
const last = (mxEv === lastShownEvent);
|
||||
const { nextEvent, nextTile } = this.getNextEventInfo(this.props.events, i);
|
||||
|
||||
if (
|
||||
mxEv.getType().indexOf("m.call.") === 0 ||
|
||||
mxEv.getType().indexOf("org.matrix.call.") === 0
|
||||
) {
|
||||
const callId = mxEv.getContent().call_id;
|
||||
if (this.callEventGroupers.has(callId)) {
|
||||
this.callEventGroupers.get(callId).add(mxEv);
|
||||
} else {
|
||||
const callEventGrouper = new CallEventGrouper();
|
||||
callEventGrouper.add(mxEv);
|
||||
this.callEventGroupers.set(callId, callEventGrouper);
|
||||
}
|
||||
}
|
||||
|
||||
if (grouper) {
|
||||
if (grouper.shouldGroup(mxEv)) {
|
||||
grouper.add(mxEv, this.showHiddenEvents);
|
||||
|
@ -784,7 +769,7 @@ export default class MessagePanel extends React.Component<IProps, IState> {
|
|||
// it's successful: we received it.
|
||||
isLastSuccessful = isLastSuccessful && mxEv.getSender() === MatrixClientPeg.get().getUserId();
|
||||
|
||||
const callEventGrouper = this.callEventGroupers.get(mxEv.getContent().call_id);
|
||||
const callEventGrouper = this.props.callEventGroupers.get(mxEv.getContent().call_id);
|
||||
// use txnId as key if available so that we don't remount during sending
|
||||
ret.push(
|
||||
<TileErrorBoundary key={mxEv.getTxnId() || eventId} mxEvent={mxEv}>
|
||||
|
|
|
@ -51,6 +51,7 @@ import { RoomPermalinkCreator } from "../../utils/permalinks/Permalinks";
|
|||
import Spinner from "../views/elements/Spinner";
|
||||
import EditorStateTransfer from '../../utils/EditorStateTransfer';
|
||||
import ErrorDialog from '../views/dialogs/ErrorDialog';
|
||||
import CallEventGrouper from "./CallEventGrouper";
|
||||
|
||||
const PAGINATE_SIZE = 20;
|
||||
const INITIAL_SIZE = 20;
|
||||
|
@ -237,6 +238,9 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
|||
private readReceiptActivityTimer: Timer;
|
||||
private readMarkerActivityTimer: Timer;
|
||||
|
||||
// A map of <callId, CallEventGrouper>
|
||||
private callEventGroupers = new Map<string, CallEventGrouper>();
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
|
||||
|
@ -388,6 +392,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
|||
this.timelineWindow.unpaginate(count, backwards);
|
||||
|
||||
const { events, liveEvents, firstVisibleEventIndex } = this.getEvents();
|
||||
this.buildCallEventGroupers(events);
|
||||
const newState: Partial<IState> = {
|
||||
events,
|
||||
liveEvents,
|
||||
|
@ -449,6 +454,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
|||
debuglog("paginate complete backwards:"+backwards+"; success:"+r);
|
||||
|
||||
const { events, liveEvents, firstVisibleEventIndex } = this.getEvents();
|
||||
this.buildCallEventGroupers(events);
|
||||
const newState: Partial<IState> = {
|
||||
[paginatingKey]: false,
|
||||
[canPaginateKey]: r,
|
||||
|
@ -561,6 +567,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
|||
if (this.unmounted) { return; }
|
||||
|
||||
const { events, liveEvents, firstVisibleEventIndex } = this.getEvents();
|
||||
this.buildCallEventGroupers(events);
|
||||
const lastLiveEvent = liveEvents[liveEvents.length - 1];
|
||||
|
||||
const updatedState: Partial<IState> = {
|
||||
|
@ -1231,6 +1238,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
|||
canForwardPaginate: false,
|
||||
timelineLoading: true,
|
||||
});
|
||||
this.buildCallEventGroupers();
|
||||
prom.then(onLoaded, onError);
|
||||
}
|
||||
}
|
||||
|
@ -1243,7 +1251,9 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
|||
// the results if so.
|
||||
if (this.unmounted) return;
|
||||
|
||||
this.setState(this.getEvents());
|
||||
const state = this.getEvents();
|
||||
this.buildCallEventGroupers(state.events);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
// Force refresh the timeline before threads support pending events
|
||||
|
@ -1512,6 +1522,27 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
|||
eventType: EventType | string,
|
||||
) => this.props.timelineSet.getRelationsForEvent(eventId, relationType, eventType);
|
||||
|
||||
private buildCallEventGroupers(events?: MatrixEvent[]): void {
|
||||
const oldCallEventGroupers = this.callEventGroupers;
|
||||
this.callEventGroupers = new Map();
|
||||
events?.forEach(ev => {
|
||||
if (!ev.getType().startsWith("m.call.") && !ev.getType().startsWith("org.matrix.call.")) {
|
||||
return;
|
||||
}
|
||||
|
||||
const callId = ev.getContent().call_id;
|
||||
if (!this.callEventGroupers.has(callId)) {
|
||||
if (oldCallEventGroupers.has(callId)) {
|
||||
// reuse the CallEventGrouper object where possible
|
||||
this.callEventGroupers.set(callId, oldCallEventGroupers.get(callId));
|
||||
} else {
|
||||
this.callEventGroupers.set(callId, new CallEventGrouper());
|
||||
}
|
||||
}
|
||||
this.callEventGroupers.get(callId).add(ev);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
// just show a spinner while the timeline loads.
|
||||
//
|
||||
|
@ -1596,6 +1627,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
|
|||
enableFlair={SettingsStore.getValue(UIFeature.Flair)}
|
||||
hideThreadedMessages={this.props.hideThreadedMessages}
|
||||
disableGrouping={this.props.disableGrouping}
|
||||
callEventGroupers={this.callEventGroupers}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -41,9 +41,8 @@ const room = new Matrix.Room("!roomId:server_name");
|
|||
|
||||
// wrap MessagePanel with a component which provides the MatrixClient in the context.
|
||||
class WrappedMessagePanel extends React.Component {
|
||||
state = {
|
||||
resizeNotifier: new EventEmitter(),
|
||||
};
|
||||
resizeNotifier = new EventEmitter();
|
||||
callEventGroupers = new Map();
|
||||
|
||||
render() {
|
||||
const roomContext = {
|
||||
|
@ -60,7 +59,12 @@ class WrappedMessagePanel extends React.Component {
|
|||
|
||||
return <MatrixClientContext.Provider value={client}>
|
||||
<RoomContext.Provider value={roomContext}>
|
||||
<MessagePanel room={room} {...this.props} resizeNotifier={this.state.resizeNotifier} />
|
||||
<MessagePanel
|
||||
room={room}
|
||||
{...this.props}
|
||||
resizeNotifier={this.resizeNotifier}
|
||||
callEventGroupers={this.callEventGroupers}
|
||||
/>
|
||||
</RoomContext.Provider>
|
||||
</MatrixClientContext.Provider>;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue