From 4a754ded5f13fd482b46a8ca90c4b7e2e632726b Mon Sep 17 00:00:00 2001 From: Krille Date: Fri, 4 Oct 2024 13:41:35 +0200 Subject: [PATCH] fix: (BREAKING) Change power level without changing memory The problem here is that we have not created a deep copy of the power level map. By using .copy() we create a deep copy now. --- lib/src/room.dart | 27 ++++++++++++++++++--------- test/room_test.dart | 14 ++++++++++++++ 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/lib/src/room.dart b/lib/src/room.dart index 9a1fe35e..bdef55e4 100644 --- a/lib/src/room.dart +++ b/lib/src/room.dart @@ -1189,22 +1189,31 @@ class Room { /// Set the power level of the user with the [userID] to the value [power]. /// Returns the event ID of the new state event. If there is no known /// power level event, there might something broken and this returns null. - Future setPower(String userID, int power) async { - final powerMap = Map.from( - getState(EventTypes.RoomPowerLevels)?.content ?? {}, - ); + /// Please note, that you need to await the power level state from sync before + /// the changes are actually applied. Especially if you want to set multiple + /// power levels at once, you need to await each change in the sync, to not + /// override those. + Future setPower(String userId, int power) async { + final powerLevelMapCopy = + getState(EventTypes.RoomPowerLevels)?.content.copy() ?? {}; - final usersPowerMap = powerMap['users'] is Map - ? powerMap['users'] as Map - : (powerMap['users'] = {}); + var users = powerLevelMapCopy['users']; - usersPowerMap[userID] = power; + if (users is! Map) { + if (users != null) { + Logs().v( + 'Repairing Power Level "users" has the wrong type "${powerLevelMapCopy['users'].runtimeType}"'); + } + users = powerLevelMapCopy['users'] = {}; + } + + users[userId] = power; return await client.setRoomStateWithKey( id, EventTypes.RoomPowerLevels, '', - powerMap, + powerLevelMapCopy, ); } diff --git a/test/room_test.dart b/test/room_test.dart index 99c8f197..6edbdda5 100644 --- a/test/room_test.dart +++ b/test/room_test.dart @@ -787,6 +787,20 @@ void main() { await room.invite('Testname'); }); + test('setPower', () async { + final powerLevelMap = + room.getState(EventTypes.RoomPowerLevels, '')!.content.copy(); + + // Request to fake api does not update anything: + await room.setPower('@bob:fakeServer.notExisting', 100); + + // Original power level map has not changed: + expect( + powerLevelMap, + room.getState(EventTypes.RoomPowerLevels, '')!.content.copy(), + ); + }); + test('getParticipants', () async { var userList = room.getParticipants(); expect(userList.length, 4);