Merge branch 'room-fix-states-with-statekeys' into 'master'
[Room] fix states with statekeys See merge request famedly/famedlysdk!118
This commit is contained in:
		
						commit
						a408764c86
					
				|  | @ -32,6 +32,7 @@ export 'package:famedlysdk/src/sync/UserUpdate.dart'; | ||||||
| export 'package:famedlysdk/src/utils/ChatTime.dart'; | export 'package:famedlysdk/src/utils/ChatTime.dart'; | ||||||
| export 'package:famedlysdk/src/utils/MatrixFile.dart'; | export 'package:famedlysdk/src/utils/MatrixFile.dart'; | ||||||
| export 'package:famedlysdk/src/utils/MxContent.dart'; | export 'package:famedlysdk/src/utils/MxContent.dart'; | ||||||
|  | export 'package:famedlysdk/src/utils/StatesMap.dart'; | ||||||
| export 'package:famedlysdk/src/AccountData.dart'; | export 'package:famedlysdk/src/AccountData.dart'; | ||||||
| export 'package:famedlysdk/src/Client.dart'; | export 'package:famedlysdk/src/Client.dart'; | ||||||
| export 'package:famedlysdk/src/Connection.dart'; | export 'package:famedlysdk/src/Connection.dart'; | ||||||
|  |  | ||||||
|  | @ -37,6 +37,7 @@ import 'package:mime_type/mime_type.dart'; | ||||||
| import './User.dart'; | import './User.dart'; | ||||||
| import 'Connection.dart'; | import 'Connection.dart'; | ||||||
| import 'Timeline.dart'; | import 'Timeline.dart'; | ||||||
|  | import 'utils/StatesMap.dart'; | ||||||
| 
 | 
 | ||||||
| typedef onRoomUpdate = void Function(); | typedef onRoomUpdate = void Function(); | ||||||
| 
 | 
 | ||||||
|  | @ -67,8 +68,7 @@ class Room { | ||||||
|   /// The number of users with membership of invite. |   /// The number of users with membership of invite. | ||||||
|   int mInvitedMemberCount; |   int mInvitedMemberCount; | ||||||
| 
 | 
 | ||||||
|   /// Key-Value store for room states. |   StatesMap states = StatesMap(); | ||||||
|   Map<String, RoomState> states = {}; |  | ||||||
| 
 | 
 | ||||||
|   /// Key-Value store for ephemerals. |   /// Key-Value store for ephemerals. | ||||||
|   Map<String, RoomAccountData> ephemerals = {}; |   Map<String, RoomAccountData> ephemerals = {}; | ||||||
|  | @ -155,18 +155,16 @@ class Room { | ||||||
| 
 | 
 | ||||||
|   Event get lastEvent { |   Event get lastEvent { | ||||||
|     ChatTime lastTime = ChatTime(0); |     ChatTime lastTime = ChatTime(0); | ||||||
|     Event lastEvent = null; |     Event lastEvent = states["m.room.message"]?.timelineEvent; | ||||||
|     for (final entry in states.entries) { |     if (lastEvent == null) | ||||||
|       final RoomState state = entry.value; |       states.forEach((final String key, final entry) { | ||||||
|       if ((state.time != null && state.time > lastTime) || |         if (!entry.containsKey("")) return; | ||||||
|           state.typeKey == "m.room.message") { |         final RoomState state = entry[""]; | ||||||
|         lastTime = state.time; |         if (state.time != null && state.time > lastTime) { | ||||||
|         lastEvent = state.timelineEvent; |           lastTime = state.time; | ||||||
|         if (state.typeKey == "m.room.message") { |           lastEvent = state.timelineEvent; | ||||||
|           break; |  | ||||||
|         } |         } | ||||||
|       } |       }); | ||||||
|     } |  | ||||||
|     return lastEvent; |     return lastEvent; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | @ -194,7 +192,6 @@ class Room { | ||||||
|     this.mHeroes = const [], |     this.mHeroes = const [], | ||||||
|     this.mInvitedMemberCount = 0, |     this.mInvitedMemberCount = 0, | ||||||
|     this.mJoinedMemberCount = 0, |     this.mJoinedMemberCount = 0, | ||||||
|     this.states = const {}, |  | ||||||
|     this.roomAccountData = const {}, |     this.roomAccountData = const {}, | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|  | @ -624,7 +621,6 @@ class Room { | ||||||
|       mJoinedMemberCount: row["joined_member_count"], |       mJoinedMemberCount: row["joined_member_count"], | ||||||
|       mHeroes: row["heroes"]?.split(",") ?? [], |       mHeroes: row["heroes"]?.split(",") ?? [], | ||||||
|       client: matrix, |       client: matrix, | ||||||
|       states: {}, |  | ||||||
|       roomAccountData: {}, |       roomAccountData: {}, | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
|  | @ -635,7 +631,8 @@ class Room { | ||||||
|         RoomState newState = RoomState.fromJson(rawStates[i], newRoom); |         RoomState newState = RoomState.fromJson(rawStates[i], newRoom); | ||||||
|         newStates[newState.key] = newState; |         newStates[newState.key] = newState; | ||||||
|       } |       } | ||||||
|       newRoom.states = newStates; |       for (var entry in newStates.entries) | ||||||
|  |         newRoom.states[entry.key] = entry.value; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     Map<String, RoomAccountData> newRoomAccountData = {}; |     Map<String, RoomAccountData> newRoomAccountData = {}; | ||||||
|  | @ -682,9 +679,13 @@ class Room { | ||||||
|   /// case. |   /// case. | ||||||
|   List<User> getParticipants() { |   List<User> getParticipants() { | ||||||
|     List<User> userList = []; |     List<User> userList = []; | ||||||
|     for (var entry in states.entries) |     if (states["m.room.member"] is Map<String, dynamic>) { | ||||||
|       if (entry.value.type == EventTypes.RoomMember) |       print('Check members: ${states["m.room.member"].length}'); | ||||||
|         userList.add(entry.value.asUser); |       for (var entry in states["m.room.member"].entries) { | ||||||
|  |         RoomState state = entry.value; | ||||||
|  |         if (state.type == EventTypes.RoomMember) userList.add(state.asUser); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|     return userList; |     return userList; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -130,7 +130,6 @@ class RoomList { | ||||||
|         mHeroes: chatUpdate.summary?.mHeroes, |         mHeroes: chatUpdate.summary?.mHeroes, | ||||||
|         mJoinedMemberCount: chatUpdate.summary?.mJoinedMemberCount, |         mJoinedMemberCount: chatUpdate.summary?.mJoinedMemberCount, | ||||||
|         mInvitedMemberCount: chatUpdate.summary?.mInvitedMemberCount, |         mInvitedMemberCount: chatUpdate.summary?.mInvitedMemberCount, | ||||||
|         states: {}, |  | ||||||
|         roomAccountData: {}, |         roomAccountData: {}, | ||||||
|         client: client, |         client: client, | ||||||
|       ); |       ); | ||||||
|  |  | ||||||
|  | @ -0,0 +1,36 @@ | ||||||
|  | import 'package:famedlysdk/famedlysdk.dart'; | ||||||
|  | 
 | ||||||
|  | /// Matrix room states are addressed by a tuple of the [type] and an | ||||||
|  | /// optional [stateKey]. | ||||||
|  | class StatesMap { | ||||||
|  |   Map<String, Map<String, RoomState>> states = {}; | ||||||
|  | 
 | ||||||
|  |   /// Returns either the [RoomState] or a map of state_keys to [RoomState] objects. | ||||||
|  |   /// If you just enter a MatrixID, it will try to return the corresponding m.room.member event. | ||||||
|  |   dynamic operator [](String key) { | ||||||
|  |     if (key.startsWith("@") && key.contains(":")) { | ||||||
|  |       if (!states.containsKey("m.room.member")) states["m.room.member"] = {}; | ||||||
|  |       return states["m.room.member"][key]; | ||||||
|  |     } | ||||||
|  |     if (!states.containsKey(key)) states[key] = {}; | ||||||
|  |     if (states[key][""] is RoomState) | ||||||
|  |       return states[key][""]; | ||||||
|  |     else if (states[key].length == 0) | ||||||
|  |       return null; | ||||||
|  |     else | ||||||
|  |       return states[key]; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   void operator []=(String key, RoomState val) { | ||||||
|  |     if (key.startsWith("@") && key.contains(":")) { | ||||||
|  |       if (!states.containsKey("m.room.member")) states["m.room.member"] = {}; | ||||||
|  |       states["m.room.member"][key] = val; | ||||||
|  |     } | ||||||
|  |     if (!states.containsKey(key)) states[key] = {}; | ||||||
|  |     states[key][val.stateKey ?? ""] = val; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   bool containsKey(String key) => states.containsKey(key); | ||||||
|  | 
 | ||||||
|  |   void forEach(f) => states.forEach(f); | ||||||
|  | } | ||||||
|  | @ -0,0 +1,74 @@ | ||||||
|  | /* | ||||||
|  |  * Copyright (c) 2019 Zender & Kurtz GbR. | ||||||
|  |  * | ||||||
|  |  * Authors: | ||||||
|  |  *   Christian Pauly <krille@famedly.com> | ||||||
|  |  *   Marcel Radzio <mtrnord@famedly.com> | ||||||
|  |  * | ||||||
|  |  * This file is part of famedlysdk. | ||||||
|  |  * | ||||||
|  |  * famedlysdk is free software: you can redistribute it and/or modify | ||||||
|  |  * it under the terms of the GNU General Public License as published by | ||||||
|  |  * the Free Software Foundation, either version 3 of the License, or | ||||||
|  |  * (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  * famedlysdk is distributed in the hope that it will be useful, | ||||||
|  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |  * GNU General Public License for more details. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU General Public License | ||||||
|  |  * along with famedlysdk.  If not, see <http://www.gnu.org/licenses/>. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | import 'package:famedlysdk/famedlysdk.dart'; | ||||||
|  | import 'package:test/test.dart'; | ||||||
|  | import 'package:famedlysdk/src/utils/StatesMap.dart'; | ||||||
|  | 
 | ||||||
|  | void main() { | ||||||
|  |   /// All Tests related to the ChatTime | ||||||
|  |   group("StateKeys", () { | ||||||
|  |     test("Operator overload", () async { | ||||||
|  |       StatesMap states = StatesMap(); | ||||||
|  |       states["m.room.name"] = RoomState( | ||||||
|  |           eventId: "1", | ||||||
|  |           content: {"name": "test"}, | ||||||
|  |           typeKey: "m.room.name", | ||||||
|  |           stateKey: "", | ||||||
|  |           roomId: "!test:test.test", | ||||||
|  |           senderId: "@alice:test.test"); | ||||||
|  | 
 | ||||||
|  |       states["@alice:test.test"] = RoomState( | ||||||
|  |           eventId: "2", | ||||||
|  |           content: {"membership": "join"}, | ||||||
|  |           typeKey: "m.room.name", | ||||||
|  |           stateKey: "@alice:test.test", | ||||||
|  |           roomId: "!test:test.test", | ||||||
|  |           senderId: "@alice:test.test"); | ||||||
|  | 
 | ||||||
|  |       states["m.room.member"]["@bob:test.test"] = RoomState( | ||||||
|  |           eventId: "3", | ||||||
|  |           content: {"membership": "join"}, | ||||||
|  |           typeKey: "m.room.name", | ||||||
|  |           stateKey: "@bob:test.test", | ||||||
|  |           roomId: "!test:test.test", | ||||||
|  |           senderId: "@bob:test.test"); | ||||||
|  | 
 | ||||||
|  |       states["com.test.custom"] = RoomState( | ||||||
|  |           eventId: "4", | ||||||
|  |           content: {"custom": "stuff"}, | ||||||
|  |           typeKey: "com.test.custom", | ||||||
|  |           stateKey: "customStateKey", | ||||||
|  |           roomId: "!test:test.test", | ||||||
|  |           senderId: "@bob:test.test"); | ||||||
|  | 
 | ||||||
|  |       expect(states["m.room.name"].eventId, "1"); | ||||||
|  |       expect(states["@alice:test.test"].eventId, "2"); | ||||||
|  |       expect(states["m.room.member"]["@alice:test.test"].eventId, "2"); | ||||||
|  |       expect(states["@bob:test.test"].eventId, "3"); | ||||||
|  |       expect(states["m.room.member"]["@bob:test.test"].eventId, "3"); | ||||||
|  |       expect(states["m.room.member"].length, 2); | ||||||
|  |       expect(states["com.test.custom"]["customStateKey"].eventId, "4"); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  | @ -43,11 +43,7 @@ void main() { | ||||||
|     client.homeserver = "https://fakeServer.notExisting"; |     client.homeserver = "https://fakeServer.notExisting"; | ||||||
| 
 | 
 | ||||||
|     Room room = Room( |     Room room = Room( | ||||||
|         id: roomID, |         id: roomID, client: client, prev_batch: "1234", roomAccountData: {}); | ||||||
|         client: client, |  | ||||||
|         prev_batch: "1234", |  | ||||||
|         states: {}, |  | ||||||
|         roomAccountData: {}); |  | ||||||
|     Timeline timeline = Timeline( |     Timeline timeline = Timeline( | ||||||
|         room: room, |         room: room, | ||||||
|         events: [], |         events: [], | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue