New Room List: Prevent old tombstoned rooms from appearing in the list (#29881)
* Write failing playwright test Basically when someone changes their name, any old tombstoned rooms that were previously hidden would suddenly show up in the list. * Split addRoom into two methods - `reInsertRoom` that re-inserts a room that is already known by the skiplist. - `addNewRoom` to add new rooms The idea is that sometimes you only want to re-insert to noop, eg: when you get an event in an old room that was upgraded. * Use new methods in the RLS Only use `addNewRoom` when absolutely necessary. Most events should instead use `reInsertRoom` which will noop when the room isn't already known by the skiplist. * Fix broken tests * Add new test * Fix playwright test
This commit is contained in:
@@ -211,23 +211,28 @@ export class RoomListStoreV3Class extends AsyncStoreWithClient<EmptyObject> {
|
||||
const oldMembership = getEffectiveMembership(payload.oldMembership);
|
||||
const newMembership = getEffectiveMembershipTag(payload.room, payload.membership);
|
||||
|
||||
// If the user is kicked, re-insert the room and do nothing more.
|
||||
const ownUserId = this.matrixClient.getSafeUserId();
|
||||
const isKicked = (payload.room as Room).getMember(ownUserId)?.isKicked();
|
||||
const shouldRemove =
|
||||
!isKicked &&
|
||||
if (isKicked) {
|
||||
this.addRoomAndEmit(payload.room);
|
||||
return;
|
||||
}
|
||||
|
||||
// If the user has left this room, remove it from the skiplist.
|
||||
if (
|
||||
(payload.oldMembership === KnownMembership.Invite ||
|
||||
payload.oldMembership === KnownMembership.Join) &&
|
||||
payload.membership === KnownMembership.Leave;
|
||||
|
||||
if (shouldRemove) {
|
||||
payload.membership === KnownMembership.Leave
|
||||
) {
|
||||
this.roomSkipList.removeRoom(payload.room);
|
||||
this.emit(LISTS_UPDATE_EVENT);
|
||||
return;
|
||||
}
|
||||
|
||||
// If we're joining an upgraded room, we'll want to make sure we don't proliferate
|
||||
// the dead room in the list.
|
||||
if (oldMembership !== EffectiveMembership.Join && newMembership === EffectiveMembership.Join) {
|
||||
// If we're joining an upgraded room, we'll want to make sure we don't proliferate
|
||||
// the dead room in the list.
|
||||
const roomState: RoomState = payload.room.currentState;
|
||||
const predecessor = roomState.findPredecessor(this.msc3946ProcessDynamicPredecessor);
|
||||
if (predecessor) {
|
||||
@@ -236,7 +241,8 @@ export class RoomListStoreV3Class extends AsyncStoreWithClient<EmptyObject> {
|
||||
else logger.warn(`Unable to find predecessor room with id ${predecessor.roomId}`);
|
||||
}
|
||||
}
|
||||
this.addRoomAndEmit(payload.room);
|
||||
|
||||
this.addRoomAndEmit(payload.room, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -260,7 +266,7 @@ export class RoomListStoreV3Class extends AsyncStoreWithClient<EmptyObject> {
|
||||
logger.warn(`${roomId} was found in DMs but the room is not in the store`);
|
||||
continue;
|
||||
}
|
||||
this.roomSkipList!.addRoom(room);
|
||||
this.roomSkipList!.reInsertRoom(room);
|
||||
needsEmit = true;
|
||||
}
|
||||
}
|
||||
@@ -274,7 +280,7 @@ export class RoomListStoreV3Class extends AsyncStoreWithClient<EmptyObject> {
|
||||
.map((id) => this.matrixClient?.getRoom(id))
|
||||
.filter((room) => !!room);
|
||||
for (const room of rooms) {
|
||||
this.roomSkipList!.addRoom(room);
|
||||
this.roomSkipList!.reInsertRoom(room);
|
||||
needsEmit = true;
|
||||
}
|
||||
break;
|
||||
@@ -303,10 +309,12 @@ export class RoomListStoreV3Class extends AsyncStoreWithClient<EmptyObject> {
|
||||
/**
|
||||
* Add a room to the skiplist and emit an update.
|
||||
* @param room The room to add to the skiplist
|
||||
* @param isNewRoom Set this to true if this a new room that the isn't already in the skiplist
|
||||
*/
|
||||
private addRoomAndEmit(room: Room): void {
|
||||
private addRoomAndEmit(room: Room, isNewRoom = false): void {
|
||||
if (!this.roomSkipList) throw new Error("roomSkipList hasn't been created yet!");
|
||||
this.roomSkipList.addRoom(room);
|
||||
if (isNewRoom) this.roomSkipList.addNewRoom(room);
|
||||
else this.roomSkipList.reInsertRoom(room);
|
||||
this.emit(LISTS_UPDATE_EVENT);
|
||||
}
|
||||
|
||||
|
||||
@@ -90,15 +90,34 @@ export class RoomSkipList implements Iterable<Room> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a given room to the correct sorted position in the list.
|
||||
* If the room is already present in the list, it is first removed.
|
||||
* Re-inserts a room that is already in the skiplist.
|
||||
* This method does nothing if the room isn't already in the skiplist.
|
||||
* @param room the room to add
|
||||
*/
|
||||
public addRoom(room: Room): void {
|
||||
/**
|
||||
* Remove this room from the skip list if necessary.
|
||||
*/
|
||||
public reInsertRoom(room: Room): void {
|
||||
if (!this.roomNodeMap.has(room.roomId)) {
|
||||
return;
|
||||
}
|
||||
this.removeRoom(room);
|
||||
this.addNewRoom(room);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new room to the skiplist.
|
||||
* This method will throw an error if the room is already in the skiplist.
|
||||
* @param room the room to add
|
||||
*/
|
||||
public addNewRoom(room: Room): void {
|
||||
if (this.roomNodeMap.has(room.roomId)) {
|
||||
throw new Error(`Can't add room to skiplist: ${room.roomId} is already in the skiplist!`);
|
||||
}
|
||||
this.insertRoom(room);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a given room to the correct sorted position in the list.
|
||||
*/
|
||||
private insertRoom(room: Room): void {
|
||||
const newNode = new RoomNode(room);
|
||||
newNode.checkIfRoomBelongsToActiveSpace();
|
||||
newNode.applyFilters(this.filters);
|
||||
|
||||
Reference in New Issue
Block a user