From 83e6753c4ebf60c12c917ccf53ccbb3d90e8809d Mon Sep 17 00:00:00 2001 From: R Midhun Suresh Date: Sat, 26 Apr 2025 18:13:23 +0530 Subject: [PATCH] RoomListStore: Remove invite rooms on decline (#29804) * Remove room when new membership is leave It doesn't really matter what the previous membership was. * Fix test * Remove on join/invite only * Exclude kicked rooms from being removed --- src/stores/room-list-v3/RoomListStoreV3.ts | 14 ++++++-- .../room-list-v3/RoomListStoreV3-test.ts | 35 ++++++++++++++++--- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/stores/room-list-v3/RoomListStoreV3.ts b/src/stores/room-list-v3/RoomListStoreV3.ts index e8eac5dff9..9a6a7702b9 100644 --- a/src/stores/room-list-v3/RoomListStoreV3.ts +++ b/src/stores/room-list-v3/RoomListStoreV3.ts @@ -6,7 +6,7 @@ Please see LICENSE files in the repository root for full details. */ import { logger } from "matrix-js-sdk/src/logger"; -import { EventType } from "matrix-js-sdk/src/matrix"; +import { EventType, KnownMembership } from "matrix-js-sdk/src/matrix"; import type { EmptyObject, Room, RoomState } from "matrix-js-sdk/src/matrix"; import type { MatrixDispatcher } from "../../dispatcher/dispatcher"; @@ -194,11 +194,21 @@ export class RoomListStoreV3Class extends AsyncStoreWithClient { case "MatrixActions.Room.myMembership": { const oldMembership = getEffectiveMembership(payload.oldMembership); const newMembership = getEffectiveMembershipTag(payload.room, payload.membership); - if (oldMembership === EffectiveMembership.Join && newMembership === EffectiveMembership.Leave) { + + const ownUserId = this.matrixClient.getSafeUserId(); + const isKicked = (payload.room as Room).getMember(ownUserId)?.isKicked(); + const shouldRemove = + !isKicked && + (payload.oldMembership === KnownMembership.Invite || + payload.oldMembership === KnownMembership.Join) && + payload.membership === KnownMembership.Leave; + + if (shouldRemove) { this.roomSkipList.removeRoom(payload.room); this.emit(LISTS_UPDATE_EVENT); return; } + 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. diff --git a/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts b/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts index 915f6db0b9..9b9e1ee665 100644 --- a/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts +++ b/test/unit-tests/stores/room-list-v3/RoomListStoreV3-test.ts @@ -122,11 +122,38 @@ describe("RoomListStoreV3", () => { expect(store.getSortedRooms()[0].roomId).toEqual(room.roomId); }); - it("Room is removed when membership changes from join to leave", async () => { - const { store, rooms, dispatcher } = await getRoomListStore(); + it.each([KnownMembership.Join, KnownMembership.Invite])( + "Room is removed when membership changes to leave", + async (membership) => { + const { store, rooms, dispatcher } = await getRoomListStore(); - // Let's say the user leaves room at index 37 + // Let's say the user leaves room at index 37 + const room = rooms[37]; + + const payload = { + action: "MatrixActions.Room.myMembership", + oldMembership: membership, + membership: KnownMembership.Leave, + room, + }; + + const fn = jest.fn(); + store.on(LISTS_UPDATE_EVENT, fn); + dispatcher.dispatch(payload, true); + + expect(fn).toHaveBeenCalled(); + expect(store.getSortedRooms()).not.toContain(room); + }, + ); + + it("Room is not removed when user is kicked", async () => { + const { store, rooms, dispatcher, client } = await getRoomListStore(); + + // Let's say the user gets kicked out of room at index 37 const room = rooms[37]; + const mockMember = room.getMember(client.getSafeUserId())!; + mockMember.isKicked = () => true; + room.getMember = () => mockMember; const payload = { action: "MatrixActions.Room.myMembership", @@ -140,7 +167,7 @@ describe("RoomListStoreV3", () => { dispatcher.dispatch(payload, true); expect(fn).toHaveBeenCalled(); - expect(store.getSortedRooms()).not.toContain(room); + expect(store.getSortedRooms()).toContain(room); }); it("Predecessor room is removed on room upgrade", async () => {