Fix converttoroom & converttodm not working (#29705)

* Fix converttoroom & converttodm not working

setAccountData uses `deepCompare` within to avoid writing no-op updates

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update tests

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Use filterValidMDirect utility in setDMRoom

Ensure we do not mutate the account data as this would then upset `setAccountData`'s deepCompare later

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Iterate

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

---------

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
Michael Telatynski
2025-04-10 16:54:41 +01:00
committed by GitHub
parent 60117b92d8
commit d70d4486f0
2 changed files with 11 additions and 46 deletions

View File

@@ -9,6 +9,7 @@ Please see LICENSE files in the repository root for full details.
import { type Room, EventType, type RoomMember, type MatrixClient } from "matrix-js-sdk/src/matrix"; import { type Room, EventType, type RoomMember, type MatrixClient } from "matrix-js-sdk/src/matrix";
import AliasCustomisations from "./customisations/Alias"; import AliasCustomisations from "./customisations/Alias";
import { filterValidMDirect } from "./utils/dm/filterValidMDirect.ts";
/** /**
* Given a room object, return the alias we should use for it, * Given a room object, return the alias we should use for it,
@@ -56,39 +57,23 @@ export async function setDMRoom(client: MatrixClient, roomId: string, userId: st
if (client.isGuest()) return; if (client.isGuest()) return;
const mDirectEvent = client.getAccountData(EventType.Direct); const mDirectEvent = client.getAccountData(EventType.Direct);
const currentContent = mDirectEvent?.getContent() || {}; const { filteredContent } = filterValidMDirect(mDirectEvent?.getContent() ?? {});
const dmRoomMap = new Map(Object.entries(currentContent)); // remove it from the lists of all users (it can only be a DM room for one person)
let modified = false; for (const thisUserId in filteredContent) {
if (!filteredContent[thisUserId]) continue;
// remove it from the lists of any others users filteredContent[thisUserId] = filteredContent[thisUserId].filter((room) => room !== roomId);
// (it can only be a DM room for one person)
for (const thisUserId of dmRoomMap.keys()) {
const roomList = dmRoomMap.get(thisUserId) || [];
if (thisUserId != userId) {
const indexOfRoom = roomList.indexOf(roomId);
if (indexOfRoom > -1) {
roomList.splice(indexOfRoom, 1);
modified = true;
}
}
} }
// now add it, if it's not already there // now add it if the caller asked for it to be a DM room
if (userId) { if (userId) {
const roomList = dmRoomMap.get(userId) || []; if (!filteredContent[userId]) {
if (roomList.indexOf(roomId) == -1) { filteredContent[userId] = [];
roomList.push(roomId);
modified = true;
} }
dmRoomMap.set(userId, roomList); filteredContent[userId].push(roomId);
} }
// prevent unnecessary calls to setAccountData await client.setAccountData(EventType.Direct, filteredContent);
if (!modified) return;
await client.setAccountData(EventType.Direct, Object.fromEntries(dmRoomMap));
} }
/** /**

View File

@@ -79,16 +79,6 @@ describe("setDMRoom", () => {
}); });
}); });
describe("when trying to add a DM, that already exists", () => {
beforeEach(() => {
setDMRoom(client, roomId1, userId1);
});
it("should not update the account data", () => {
expect(client.setAccountData).not.toHaveBeenCalled();
});
});
describe("when removing an existing DM", () => { describe("when removing an existing DM", () => {
beforeEach(() => { beforeEach(() => {
setDMRoom(client, roomId1, null); setDMRoom(client, roomId1, null);
@@ -102,16 +92,6 @@ describe("setDMRoom", () => {
}); });
}); });
describe("when removing an unknown room", () => {
beforeEach(() => {
setDMRoom(client, roomId4, null);
});
it("should not update the account data", () => {
expect(client.setAccountData).not.toHaveBeenCalled();
});
});
describe("when the direct event is undefined", () => { describe("when the direct event is undefined", () => {
beforeEach(() => { beforeEach(() => {
mocked(client.getAccountData).mockReturnValue(undefined); mocked(client.getAccountData).mockReturnValue(undefined);