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