Hide pre-join UTDs (#3881)
This commit is contained in:
parent
02ba548a62
commit
793ff2cccc
1 changed files with 88 additions and 6 deletions
|
@ -2,7 +2,7 @@
|
||||||
Copyright 2016 OpenMarket Ltd
|
Copyright 2016 OpenMarket Ltd
|
||||||
Copyright 2017 Vector Creations Ltd
|
Copyright 2017 Vector Creations Ltd
|
||||||
Copyright 2019 New Vector Ltd
|
Copyright 2019 New Vector Ltd
|
||||||
Copyright 2019 The Matrix.org Foundation C.I.C.
|
Copyright 2019-2020 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -146,6 +146,9 @@ const TimelinePanel = createReactClass({
|
||||||
liveEvents: [],
|
liveEvents: [],
|
||||||
timelineLoading: true, // track whether our room timeline is loading
|
timelineLoading: true, // track whether our room timeline is loading
|
||||||
|
|
||||||
|
// the index of the first event that is to be shown
|
||||||
|
firstVisibleEventIndex: 0,
|
||||||
|
|
||||||
// canBackPaginate == false may mean:
|
// canBackPaginate == false may mean:
|
||||||
//
|
//
|
||||||
// * we haven't (successfully) loaded the timeline yet, or:
|
// * we haven't (successfully) loaded the timeline yet, or:
|
||||||
|
@ -333,11 +336,12 @@ const TimelinePanel = createReactClass({
|
||||||
|
|
||||||
// We can now paginate in the unpaginated direction
|
// We can now paginate in the unpaginated direction
|
||||||
const canPaginateKey = (backwards) ? 'canBackPaginate' : 'canForwardPaginate';
|
const canPaginateKey = (backwards) ? 'canBackPaginate' : 'canForwardPaginate';
|
||||||
const { events, liveEvents } = this._getEvents();
|
const { events, liveEvents, firstVisibleEventIndex } = this._getEvents();
|
||||||
this.setState({
|
this.setState({
|
||||||
[canPaginateKey]: true,
|
[canPaginateKey]: true,
|
||||||
events,
|
events,
|
||||||
liveEvents,
|
liveEvents,
|
||||||
|
firstVisibleEventIndex,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -369,6 +373,11 @@ const TimelinePanel = createReactClass({
|
||||||
return Promise.resolve(false);
|
return Promise.resolve(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (backwards && this.state.firstVisibleEventIndex !== 0) {
|
||||||
|
debuglog("TimelinePanel: won't", dir, "paginate past first visible event");
|
||||||
|
return Promise.resolve(false);
|
||||||
|
}
|
||||||
|
|
||||||
debuglog("TimelinePanel: Initiating paginate; backwards:"+backwards);
|
debuglog("TimelinePanel: Initiating paginate; backwards:"+backwards);
|
||||||
this.setState({[paginatingKey]: true});
|
this.setState({[paginatingKey]: true});
|
||||||
|
|
||||||
|
@ -377,12 +386,13 @@ const TimelinePanel = createReactClass({
|
||||||
|
|
||||||
debuglog("TimelinePanel: paginate complete backwards:"+backwards+"; success:"+r);
|
debuglog("TimelinePanel: paginate complete backwards:"+backwards+"; success:"+r);
|
||||||
|
|
||||||
const { events, liveEvents } = this._getEvents();
|
const { events, liveEvents, firstVisibleEventIndex } = this._getEvents();
|
||||||
const newState = {
|
const newState = {
|
||||||
[paginatingKey]: false,
|
[paginatingKey]: false,
|
||||||
[canPaginateKey]: r,
|
[canPaginateKey]: r,
|
||||||
events,
|
events,
|
||||||
liveEvents,
|
liveEvents,
|
||||||
|
firstVisibleEventIndex,
|
||||||
};
|
};
|
||||||
|
|
||||||
// moving the window in this direction may mean that we can now
|
// moving the window in this direction may mean that we can now
|
||||||
|
@ -402,7 +412,11 @@ const TimelinePanel = createReactClass({
|
||||||
// itself into the right place
|
// itself into the right place
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
this.setState(newState, () => {
|
this.setState(newState, () => {
|
||||||
resolve(r);
|
// we can continue paginating in the given direction if:
|
||||||
|
// - _timelineWindow.paginate says we can
|
||||||
|
// - we're paginating forwards, or we won't be trying to
|
||||||
|
// paginate backwards past the first visible event
|
||||||
|
resolve(r && (!backwards || firstVisibleEventIndex === 0));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -476,12 +490,13 @@ const TimelinePanel = createReactClass({
|
||||||
this._timelineWindow.paginate(EventTimeline.FORWARDS, 1, false).then(() => {
|
this._timelineWindow.paginate(EventTimeline.FORWARDS, 1, false).then(() => {
|
||||||
if (this.unmounted) { return; }
|
if (this.unmounted) { return; }
|
||||||
|
|
||||||
const { events, liveEvents } = this._getEvents();
|
const { events, liveEvents, firstVisibleEventIndex } = this._getEvents();
|
||||||
const lastLiveEvent = liveEvents[liveEvents.length - 1];
|
const lastLiveEvent = liveEvents[liveEvents.length - 1];
|
||||||
|
|
||||||
const updatedState = {
|
const updatedState = {
|
||||||
events,
|
events,
|
||||||
liveEvents,
|
liveEvents,
|
||||||
|
firstVisibleEventIndex,
|
||||||
};
|
};
|
||||||
|
|
||||||
let callRMUpdated;
|
let callRMUpdated;
|
||||||
|
@ -1115,6 +1130,7 @@ const TimelinePanel = createReactClass({
|
||||||
// get the list of events from the timeline window and the pending event list
|
// get the list of events from the timeline window and the pending event list
|
||||||
_getEvents: function() {
|
_getEvents: function() {
|
||||||
const events = this._timelineWindow.getEvents();
|
const events = this._timelineWindow.getEvents();
|
||||||
|
const firstVisibleEventIndex = this._checkForPreJoinUISI(events);
|
||||||
|
|
||||||
// Hold onto the live events separately. The read receipt and read marker
|
// Hold onto the live events separately. The read receipt and read marker
|
||||||
// should use this list, so that they don't advance into pending events.
|
// should use this list, so that they don't advance into pending events.
|
||||||
|
@ -1128,9 +1144,72 @@ const TimelinePanel = createReactClass({
|
||||||
return {
|
return {
|
||||||
events,
|
events,
|
||||||
liveEvents,
|
liveEvents,
|
||||||
|
firstVisibleEventIndex,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check for undecryptable messages that were sent while the user was not in
|
||||||
|
* the room.
|
||||||
|
*
|
||||||
|
* @param {Array<MatrixEvent>} events The timeline events to check
|
||||||
|
*
|
||||||
|
* @return {Number} The index within `events` of the event after the most recent
|
||||||
|
* undecryptable event that was sent while the user was not in the room. If no
|
||||||
|
* such events were found, then it returns 0.
|
||||||
|
*/
|
||||||
|
_checkForPreJoinUISI: function(events) {
|
||||||
|
const room = this.props.timelineSet.room;
|
||||||
|
|
||||||
|
if (events.length === 0 || !room ||
|
||||||
|
!MatrixClientPeg.get().isRoomEncrypted(room.roomId)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const userId = MatrixClientPeg.get().credentials.userId;
|
||||||
|
|
||||||
|
// get the user's membership at the last event by getting the timeline
|
||||||
|
// that the event belongs to, and traversing the timeline looking for
|
||||||
|
// that event, while keeping track of the user's membership
|
||||||
|
const lastEvent = events[events.length - 1];
|
||||||
|
const timeline = room.getTimelineForEvent(lastEvent.getId());
|
||||||
|
const userMembershipEvent =
|
||||||
|
timeline.getState(EventTimeline.FORWARDS).getMember(userId);
|
||||||
|
let userMembership = userMembershipEvent
|
||||||
|
? userMembershipEvent.membership : "leave";
|
||||||
|
const timelineEvents = timeline.getEvents();
|
||||||
|
for (let i = timelineEvents.length - 1; i >= 0; i--) {
|
||||||
|
const event = timelineEvents[i];
|
||||||
|
if (event.getId() === lastEvent.getId()) {
|
||||||
|
// found the last event, so we can stop looking through the timeline
|
||||||
|
break;
|
||||||
|
} else if (event.getStateKey() === userId
|
||||||
|
&& event.getType() === "m.room.member") {
|
||||||
|
const prevContent = event.getPrevContent();
|
||||||
|
userMembership = prevContent.membership || "leave";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// now go through the events that we have and find the first undecryptable
|
||||||
|
// one that was sent when the user wasn't in the room
|
||||||
|
for (let i = events.length - 1; i >= 0; i--) {
|
||||||
|
const event = events[i];
|
||||||
|
if (event.getStateKey() === userId
|
||||||
|
&& event.getType() === "m.room.member") {
|
||||||
|
const prevContent = event.getPrevContent();
|
||||||
|
userMembership = prevContent.membership || "leave";
|
||||||
|
} else if (userMembership === "leave" &&
|
||||||
|
(event.isDecryptionFailure() || event.isBeingDecrypted())) {
|
||||||
|
// reached an undecryptable message when the user wasn't in
|
||||||
|
// the room -- don't try to load any more
|
||||||
|
// Note: for now, we assume that events that are being decrypted are
|
||||||
|
// not decryptable
|
||||||
|
return i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
},
|
||||||
|
|
||||||
_indexForEventId: function(evId) {
|
_indexForEventId: function(evId) {
|
||||||
for (let i = 0; i < this.state.events.length; ++i) {
|
for (let i = 0; i < this.state.events.length; ++i) {
|
||||||
if (evId == this.state.events[i].getId()) {
|
if (evId == this.state.events[i].getId()) {
|
||||||
|
@ -1323,6 +1402,9 @@ const TimelinePanel = createReactClass({
|
||||||
this.state.forwardPaginating ||
|
this.state.forwardPaginating ||
|
||||||
['PREPARED', 'CATCHUP'].includes(this.state.clientSyncState)
|
['PREPARED', 'CATCHUP'].includes(this.state.clientSyncState)
|
||||||
);
|
);
|
||||||
|
const events = this.state.firstVisibleEventIndex
|
||||||
|
? this.state.events.slice(this.state.firstVisibleEventIndex)
|
||||||
|
: this.state.events;
|
||||||
return (
|
return (
|
||||||
<MessagePanel
|
<MessagePanel
|
||||||
ref={this._messagePanel}
|
ref={this._messagePanel}
|
||||||
|
@ -1331,7 +1413,7 @@ const TimelinePanel = createReactClass({
|
||||||
hidden={this.props.hidden}
|
hidden={this.props.hidden}
|
||||||
backPaginating={this.state.backPaginating}
|
backPaginating={this.state.backPaginating}
|
||||||
forwardPaginating={forwardPaginating}
|
forwardPaginating={forwardPaginating}
|
||||||
events={this.state.events}
|
events={events}
|
||||||
highlightedEventId={this.props.highlightedEventId}
|
highlightedEventId={this.props.highlightedEventId}
|
||||||
readMarkerEventId={this.state.readMarkerEventId}
|
readMarkerEventId={this.state.readMarkerEventId}
|
||||||
readMarkerVisible={this.state.readMarkerVisible}
|
readMarkerVisible={this.state.readMarkerVisible}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue