diff --git a/cypress/integration/12-spotlight/spotlight.spec.ts b/cypress/integration/12-spotlight/spotlight.spec.ts index 5a76d17b4c..e5507af7e6 100644 --- a/cypress/integration/12-spotlight/spotlight.spec.ts +++ b/cypress/integration/12-spotlight/spotlight.spec.ts @@ -156,6 +156,7 @@ describe("Spotlight", () => { }); afterEach(() => { + cy.visit("/#/home"); cy.stopSynapse(synapse); }); @@ -264,6 +265,47 @@ describe("Spotlight", () => { }); }); + it("should find group DMs by usernames or user ids", () => { + // First we want to share a room with both bots to ensure we’ve got their usernames cached + cy.inviteUser(room1Id, bot2.getUserId()); + + // Starting a DM with ByteBot (will be turned into a group dm later) + cy.openSpotlightDialog().within(() => { + cy.spotlightFilter(Filter.People); + cy.spotlightSearch().clear().type(bot2Name); + cy.spotlightResults().should("have.length", 1); + cy.spotlightResults().eq(0).should("contain", bot2Name); + cy.spotlightResults().eq(0).click(); + }).then(() => { + cy.roomHeaderName().should("contain", bot2Name); + cy.get(".mx_RoomSublist[aria-label=People]").should("contain", bot2Name); + }); + + // Invite BotBob into existing DM with ByteBot + cy.getDmRooms(bot2.getUserId()).then(dmRooms => dmRooms[0]) + .then(groupDmId => cy.inviteUser(groupDmId, bot1.getUserId())) + .then(() => { + cy.roomHeaderName().should("contain", `${bot1Name} and ${bot2Name}`); + cy.get(".mx_RoomSublist[aria-label=People]").should("contain", `${bot1Name} and ${bot2Name}`); + }); + + // Search for BotBob by id, should return group DM and user + cy.openSpotlightDialog().within(() => { + cy.spotlightFilter(Filter.People); + cy.spotlightSearch().clear().type(bot1.getUserId()); + cy.spotlightResults().should("have.length", 2); + cy.spotlightResults().eq(0).should("contain", `${bot1Name} and ${bot2Name}`); + }); + + // Search for ByteBot by id, should return group DM and user + cy.openSpotlightDialog().within(() => { + cy.spotlightFilter(Filter.People); + cy.spotlightSearch().clear().type(bot2.getUserId()); + cy.spotlightResults().should("have.length", 2); + cy.spotlightResults().eq(0).should("contain", `${bot1Name} and ${bot2Name}`); + }); + }); + it("should allow opening group chat dialog", () => { cy.openSpotlightDialog().within(() => { cy.spotlightFilter(Filter.People); diff --git a/cypress/support/client.ts b/cypress/support/client.ts index bd3f6d1514..c4577760a8 100644 --- a/cypress/support/client.ts +++ b/cypress/support/client.ts @@ -53,6 +53,12 @@ declare global { * @param data The data to store. */ setAccountData(type: string, data: object): Chainable<{}>; + /** + * Gets the list of DMs with a given user + * @param userId The ID of the user + * @return the list of DMs with that user + */ + getDmRooms(userId: string): Chainable; /** * Boostraps cross-signing. */ @@ -65,6 +71,12 @@ Cypress.Commands.add("getClient", (): Chainable => { return cy.window({ log: false }).then(win => win.mxMatrixClientPeg.matrixClient); }); +Cypress.Commands.add("getDmRooms", (userId: string): Chainable => { + return cy.getClient() + .then(cli => cli.getAccountData("m.direct")?.getContent>()) + .then(dmRoomMap => dmRoomMap[userId] ?? []); +}); + Cypress.Commands.add("createRoom", (options: ICreateRoomOpts): Chainable => { return cy.window({ log: false }).then(async win => { const cli = win.mxMatrixClientPeg.matrixClient; diff --git a/src/components/views/dialogs/spotlight/SpotlightDialog.tsx b/src/components/views/dialogs/spotlight/SpotlightDialog.tsx index 7658a54399..cb2950c686 100644 --- a/src/components/views/dialogs/spotlight/SpotlightDialog.tsx +++ b/src/components/views/dialogs/spotlight/SpotlightDialog.tsx @@ -177,16 +177,20 @@ const toPublicRoomResult = (publicRoom: IPublicRoomsChunkRoom): IPublicRoomResul }); const toRoomResult = (room: Room): IRoomResult => { + const myUserId = MatrixClientPeg.get().getUserId(); const otherUserId = DMRoomMap.shared().getUserIdForRoomId(room.roomId); + if (otherUserId) { + const otherMembers = room.getMembers().filter(it => it.userId !== myUserId); + const query = [ + ...otherMembers.map(it => it.name.toLowerCase()), + ...otherMembers.map(it => it.userId.toLowerCase()), + ].filter(Boolean); return { room, section: Section.People, filter: [Filter.People], - query: [ - otherUserId.toLowerCase(), - room.getMember(otherUserId)?.name.toLowerCase(), - ].filter(Boolean), + query, }; } else if (room.isSpaceRoom()) { return { diff --git a/src/utils/i18n-helpers.ts b/src/utils/i18n-helpers.ts index ce1d04f9f4..26cbf60cd2 100644 --- a/src/utils/i18n-helpers.ts +++ b/src/utils/i18n-helpers.ts @@ -44,7 +44,9 @@ export function roomContextDetailsText(room: Room): string { if (room.isSpaceRoom()) return undefined; const dmPartner = DMRoomMap.shared().getUserIdForRoomId(room.roomId); - if (dmPartner) { + // if we’ve got more than 2 users, don’t treat it like a regular DM + const isGroupDm = room.getMembers().length > 2; + if (dmPartner && !isGroupDm) { return dmPartner; }