[Archive] enhance lazyload archive
This commit is contained in:
		
							parent
							
								
									c38f041a5a
								
							
						
					
					
						commit
						888155fbc7
					
				|  | @ -98,9 +98,6 @@ class Client { | ||||||
|   /// A list of all rooms the user is participating or invited. |   /// A list of all rooms the user is participating or invited. | ||||||
|   RoomList roomList; |   RoomList roomList; | ||||||
| 
 | 
 | ||||||
|   /// A list of all rooms the user is not participating anymore. |  | ||||||
|   RoomList archive; |  | ||||||
| 
 |  | ||||||
|   /// Key/Value store of account data. |   /// Key/Value store of account data. | ||||||
|   Map<String, AccountData> accountData = {}; |   Map<String, AccountData> accountData = {}; | ||||||
| 
 | 
 | ||||||
|  | @ -262,27 +259,33 @@ class Client { | ||||||
| 
 | 
 | ||||||
|   /// Creates a new [RoomList] object. |   /// Creates a new [RoomList] object. | ||||||
|   RoomList getRoomList( |   RoomList getRoomList( | ||||||
|       {bool onlyLeft = false, |       {onRoomListUpdateCallback onUpdate, | ||||||
|       onRoomListUpdateCallback onUpdate, |  | ||||||
|       onRoomListInsertCallback onInsert, |       onRoomListInsertCallback onInsert, | ||||||
|       onRoomListRemoveCallback onRemove}) { |       onRoomListRemoveCallback onRemove}) { | ||||||
|     List<Room> rooms = onlyLeft ? archive.rooms : roomList.rooms; |     List<Room> rooms = roomList.rooms; | ||||||
|     return RoomList( |     return RoomList( | ||||||
|         client: this, |         client: this, | ||||||
|         onlyLeft: onlyLeft, |         onlyLeft: false, | ||||||
|         onUpdate: onUpdate, |         onUpdate: onUpdate, | ||||||
|         onInsert: onInsert, |         onInsert: onInsert, | ||||||
|         onRemove: onRemove, |         onRemove: onRemove, | ||||||
|         rooms: rooms); |         rooms: rooms); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /// Searches in the roomList and in the archive for a room with the given [id]. |   Future<RoomList> get archive async { | ||||||
|   Room getRoomById(String id) { |     RoomList archiveList = RoomList(client: this, rooms: [], onlyLeft: true); | ||||||
|     Room room = roomList.getRoomById(id); |     String syncFilters = | ||||||
|     if (room == null) room = archive.getRoomById(id); |         '{"room":{"include_leave":true,"timeline":{"limit":1}}}'; | ||||||
|     return room; |     String action = "/client/r0/sync?filter=$syncFilters&timeout=0"; | ||||||
|  |     final syncResp = | ||||||
|  |         await connection.jsonRequest(type: HTTPType.GET, action: action); | ||||||
|  |     if (!(syncResp is ErrorResponse)) await connection.handleSync(syncResp); | ||||||
|  |     return archiveList; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   /// Searches in the roomList and in the archive for a room with the given [id]. | ||||||
|  |   Room getRoomById(String id) => roomList.getRoomById(id); | ||||||
|  | 
 | ||||||
|   Future<dynamic> joinRoomById(String id) async { |   Future<dynamic> joinRoomById(String id) async { | ||||||
|     return await connection.jsonRequest( |     return await connection.jsonRequest( | ||||||
|         type: HTTPType.POST, action: "/client/r0/join/$id"); |         type: HTTPType.POST, action: "/client/r0/join/$id"); | ||||||
|  |  | ||||||
|  | @ -49,9 +49,6 @@ class Connection { | ||||||
| 
 | 
 | ||||||
|   static String syncFilters = '{"room":{"state":{"lazy_load_members":true}}}'; |   static String syncFilters = '{"room":{"state":{"lazy_load_members":true}}}'; | ||||||
| 
 | 
 | ||||||
|   static String firstSyncFilters = |  | ||||||
|       '{"room":{"include_leave":true,"state":{"lazy_load_members":true}}}'; |  | ||||||
| 
 |  | ||||||
|   /// Handles the connection to the Matrix Homeserver. You can change this to a |   /// Handles the connection to the Matrix Homeserver. You can change this to a | ||||||
|   /// MockClient for testing. |   /// MockClient for testing. | ||||||
|   http.Client httpClient = http.Client(); |   http.Client httpClient = http.Client(); | ||||||
|  | @ -145,11 +142,9 @@ class Connection { | ||||||
|     client.prevBatch = newPrevBatch; |     client.prevBatch = newPrevBatch; | ||||||
| 
 | 
 | ||||||
|     List<Room> rooms = []; |     List<Room> rooms = []; | ||||||
|     List<Room> archivedRooms = []; |  | ||||||
|     if (client.store != null) { |     if (client.store != null) { | ||||||
|       client.store.storeClient(); |       client.store.storeClient(); | ||||||
|       rooms = await client.store.getRoomList(onlyLeft: false); |       rooms = await client.store.getRoomList(onlyLeft: false); | ||||||
|       archivedRooms = await client.store.getRoomList(onlyLeft: true); |  | ||||||
|       client.accountData = await client.store.getAccountData(); |       client.accountData = await client.store.getAccountData(); | ||||||
|       client.presences = await client.store.getPresences(); |       client.presences = await client.store.getPresences(); | ||||||
|     } |     } | ||||||
|  | @ -162,14 +157,6 @@ class Connection { | ||||||
|         onRemove: null, |         onRemove: null, | ||||||
|         rooms: rooms); |         rooms: rooms); | ||||||
| 
 | 
 | ||||||
|     client.archive = RoomList( |  | ||||||
|         client: client, |  | ||||||
|         onlyLeft: true, |  | ||||||
|         onUpdate: null, |  | ||||||
|         onInsert: null, |  | ||||||
|         onRemove: null, |  | ||||||
|         rooms: archivedRooms); |  | ||||||
| 
 |  | ||||||
|     _userEventSub ??= onUserEvent.stream.listen(client.handleUserUpdate); |     _userEventSub ??= onUserEvent.stream.listen(client.handleUserUpdate); | ||||||
| 
 | 
 | ||||||
|     onLoginStateChanged.add(LoginState.logged); |     onLoginStateChanged.add(LoginState.logged); | ||||||
|  | @ -309,10 +296,9 @@ class Connection { | ||||||
|   Future<void> _sync() async { |   Future<void> _sync() async { | ||||||
|     if (client.isLogged() == false) return; |     if (client.isLogged() == false) return; | ||||||
| 
 | 
 | ||||||
|     String action = "/client/r0/sync?filter=$firstSyncFilters"; |     String action = "/client/r0/sync?filter=$syncFilters"; | ||||||
| 
 | 
 | ||||||
|     if (client.prevBatch != null) { |     if (client.prevBatch != null) { | ||||||
|       action = "/client/r0/sync?filter=$syncFilters"; |  | ||||||
|       action += "&timeout=30000"; |       action += "&timeout=30000"; | ||||||
|       action += "&since=${client.prevBatch}"; |       action += "&since=${client.prevBatch}"; | ||||||
|     } |     } | ||||||
|  | @ -327,12 +313,12 @@ class Connection { | ||||||
|       try { |       try { | ||||||
|         if (client.store != null) |         if (client.store != null) | ||||||
|           await client.store.transaction(() { |           await client.store.transaction(() { | ||||||
|             _handleSync(syncResp); |             handleSync(syncResp); | ||||||
|             client.store.storePrevBatch(syncResp); |             client.store.storePrevBatch(syncResp); | ||||||
|             return; |             return; | ||||||
|           }); |           }); | ||||||
|         else |         else | ||||||
|           await _handleSync(syncResp); |           await handleSync(syncResp); | ||||||
|         if (client.prevBatch == null) client.connection.onFirstSync.add(true); |         if (client.prevBatch == null) client.connection.onFirstSync.add(true); | ||||||
|         client.prevBatch = syncResp["next_batch"]; |         client.prevBatch = syncResp["next_batch"]; | ||||||
|       } catch (e) { |       } catch (e) { | ||||||
|  | @ -344,7 +330,7 @@ class Connection { | ||||||
|     if (hash == _syncRequest.hashCode) _sync(); |     if (hash == _syncRequest.hashCode) _sync(); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   void _handleSync(dynamic sync) { |   void handleSync(dynamic sync) { | ||||||
|     if (sync["rooms"] is Map<String, dynamic>) { |     if (sync["rooms"] is Map<String, dynamic>) { | ||||||
|       if (sync["rooms"]["join"] is Map<String, dynamic>) |       if (sync["rooms"]["join"] is Map<String, dynamic>) | ||||||
|         _handleRooms(sync["rooms"]["join"], Membership.join); |         _handleRooms(sync["rooms"]["join"], Membership.join); | ||||||
|  |  | ||||||
|  | @ -203,11 +203,25 @@ class Room { | ||||||
|         !canonicalAlias.isEmpty && |         !canonicalAlias.isEmpty && | ||||||
|         canonicalAlias.length > 3) |         canonicalAlias.length > 3) | ||||||
|       return canonicalAlias.substring(1, canonicalAlias.length).split(":")[0]; |       return canonicalAlias.substring(1, canonicalAlias.length).split(":")[0]; | ||||||
|     if (mHeroes != null && mHeroes.length > 0 && mHeroes.any((h) => h.isNotEmpty)) { |     List<String> heroes = []; | ||||||
|  |     if (mHeroes != null && | ||||||
|  |         mHeroes.length > 0 && | ||||||
|  |         mHeroes.any((h) => h.isNotEmpty)) { | ||||||
|  |       heroes = mHeroes; | ||||||
|  |     } else { | ||||||
|  |       if (states["m.room.member"] is Map<String, dynamic>) { | ||||||
|  |         for (var entry in states["m.room.member"].entries) { | ||||||
|  |           RoomState state = entry.value; | ||||||
|  |           if (state.type == EventTypes.RoomMember && | ||||||
|  |               state.stateKey != client?.userID) heroes.add(state.stateKey); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     if (heroes.length > 0) { | ||||||
|       String displayname = ""; |       String displayname = ""; | ||||||
|       for (int i = 0; i < mHeroes.length; i++) { |       for (int i = 0; i < heroes.length; i++) { | ||||||
|         if (mHeroes[i].isEmpty) continue; |         if (heroes[i].isEmpty) continue; | ||||||
|         displayname += User(mHeroes[i]).calcDisplayname() + ", "; |         displayname += User(heroes[i]).calcDisplayname() + ", "; | ||||||
|       } |       } | ||||||
|       return displayname.substring(0, displayname.length - 2); |       return displayname.substring(0, displayname.length - 2); | ||||||
|     } |     } | ||||||
|  | @ -679,7 +693,6 @@ class Room { | ||||||
|   List<User> getParticipants() { |   List<User> getParticipants() { | ||||||
|     List<User> userList = []; |     List<User> userList = []; | ||||||
|     if (states["m.room.member"] is Map<String, dynamic>) { |     if (states["m.room.member"] is Map<String, dynamic>) { | ||||||
|       print('Check members: ${states["m.room.member"].length}'); |  | ||||||
|       for (var entry in states["m.room.member"].entries) { |       for (var entry in states["m.room.member"].entries) { | ||||||
|         RoomState state = entry.value; |         RoomState state = entry.value; | ||||||
|         if (state.type == EventTypes.RoomMember) userList.add(state.asUser); |         if (state.type == EventTypes.RoomMember) userList.add(state.asUser); | ||||||
|  |  | ||||||
|  | @ -27,6 +27,7 @@ import 'package:famedlysdk/src/AccountData.dart'; | ||||||
| import 'package:famedlysdk/src/Client.dart'; | import 'package:famedlysdk/src/Client.dart'; | ||||||
| import 'package:famedlysdk/src/Connection.dart'; | import 'package:famedlysdk/src/Connection.dart'; | ||||||
| import 'package:famedlysdk/src/Presence.dart'; | import 'package:famedlysdk/src/Presence.dart'; | ||||||
|  | import 'package:famedlysdk/src/RoomList.dart'; | ||||||
| import 'package:famedlysdk/src/User.dart'; | import 'package:famedlysdk/src/User.dart'; | ||||||
| import 'package:famedlysdk/src/requests/SetPushersRequest.dart'; | import 'package:famedlysdk/src/requests/SetPushersRequest.dart'; | ||||||
| import 'package:famedlysdk/src/responses/ErrorResponse.dart'; | import 'package:famedlysdk/src/responses/ErrorResponse.dart'; | ||||||
|  | @ -207,7 +208,7 @@ void main() { | ||||||
| 
 | 
 | ||||||
|       List<RoomUpdate> roomUpdateList = await roomUpdateListFuture; |       List<RoomUpdate> roomUpdateList = await roomUpdateListFuture; | ||||||
| 
 | 
 | ||||||
|       expect(roomUpdateList.length, 3); |       expect(roomUpdateList.length, 2); | ||||||
| 
 | 
 | ||||||
|       expect(roomUpdateList[0].id == "!726s6s6q:example.com", true); |       expect(roomUpdateList[0].id == "!726s6s6q:example.com", true); | ||||||
|       expect(roomUpdateList[0].membership == Membership.join, true); |       expect(roomUpdateList[0].membership == Membership.join, true); | ||||||
|  | @ -222,13 +223,6 @@ void main() { | ||||||
|       expect(roomUpdateList[1].limitedTimeline == false, true); |       expect(roomUpdateList[1].limitedTimeline == false, true); | ||||||
|       expect(roomUpdateList[1].notification_count == 0, true); |       expect(roomUpdateList[1].notification_count == 0, true); | ||||||
|       expect(roomUpdateList[1].highlight_count == 0, true); |       expect(roomUpdateList[1].highlight_count == 0, true); | ||||||
| 
 |  | ||||||
|       expect(roomUpdateList[2].id == "!5345234234:example.com", true); |  | ||||||
|       expect(roomUpdateList[2].membership == Membership.leave, true); |  | ||||||
|       expect(roomUpdateList[2].prev_batch == "", true); |  | ||||||
|       expect(roomUpdateList[2].limitedTimeline == false, true); |  | ||||||
|       expect(roomUpdateList[2].notification_count == 0, true); |  | ||||||
|       expect(roomUpdateList[2].highlight_count == 0, true); |  | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     test('Event Update Test', () async { |     test('Event Update Test', () async { | ||||||
|  | @ -364,6 +358,15 @@ void main() { | ||||||
|       expect(resp["room_id"], roomID); |       expect(resp["room_id"], roomID); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|  |     test('get archive', () async { | ||||||
|  |       RoomList archive = await matrix.archive; | ||||||
|  | 
 | ||||||
|  |       await new Future.delayed(new Duration(milliseconds: 50)); | ||||||
|  |       expect(archive.rooms.length, 1); | ||||||
|  |       expect(archive.rooms[0].id, "!5345234234:example.com"); | ||||||
|  |       expect(archive.rooms[0].membership, Membership.leave); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|     test('Logout when token is unknown', () async { |     test('Logout when token is unknown', () async { | ||||||
|       Future<LoginState> loginStateFuture = |       Future<LoginState> loginStateFuture = | ||||||
|           matrix.connection.onLoginStateChanged.stream.first; |           matrix.connection.onLoginStateChanged.stream.first; | ||||||
|  |  | ||||||
|  | @ -62,6 +62,176 @@ class FakeMatrixApi extends MockClient { | ||||||
|           return Response(json.encode(res), 100); |           return Response(json.encode(res), 100); | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|  |   static Map<String, dynamic> syncResponse = { | ||||||
|  |     "next_batch": Random().nextDouble().toString(), | ||||||
|  |     "presence": { | ||||||
|  |       "events": [ | ||||||
|  |         { | ||||||
|  |           "sender": "@alice:example.com", | ||||||
|  |           "type": "m.presence", | ||||||
|  |           "content": {"presence": "online"} | ||||||
|  |         } | ||||||
|  |       ] | ||||||
|  |     }, | ||||||
|  |     "account_data": { | ||||||
|  |       "events": [ | ||||||
|  |         { | ||||||
|  |           "type": "org.example.custom.config", | ||||||
|  |           "content": {"custom_config_key": "custom_config_value"} | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           "content": { | ||||||
|  |             "@bob:example.com": [ | ||||||
|  |               "!726s6s6q:example.com", | ||||||
|  |               "!hgfedcba:example.com" | ||||||
|  |             ] | ||||||
|  |           }, | ||||||
|  |           "type": "m.direct" | ||||||
|  |         }, | ||||||
|  |       ] | ||||||
|  |     }, | ||||||
|  |     "to_device": { | ||||||
|  |       "events": [ | ||||||
|  |         { | ||||||
|  |           "sender": "@alice:example.com", | ||||||
|  |           "type": "m.new_device", | ||||||
|  |           "content": { | ||||||
|  |             "device_id": "XYZABCDE", | ||||||
|  |             "rooms": ["!726s6s6q:example.com"] | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       ] | ||||||
|  |     }, | ||||||
|  |     "rooms": { | ||||||
|  |       "join": { | ||||||
|  |         "!726s6s6q:example.com": { | ||||||
|  |           "unread_notifications": { | ||||||
|  |             "highlight_count": 2, | ||||||
|  |             "notification_count": 2, | ||||||
|  |           }, | ||||||
|  |           "state": { | ||||||
|  |             "events": [ | ||||||
|  |               { | ||||||
|  |                 "sender": "@alice:example.com", | ||||||
|  |                 "type": "m.room.member", | ||||||
|  |                 "state_key": "@alice:example.com", | ||||||
|  |                 "content": {"membership": "join"}, | ||||||
|  |                 "origin_server_ts": 1417731086795, | ||||||
|  |                 "event_id": "66697273743031:example.com" | ||||||
|  |               }, | ||||||
|  |               { | ||||||
|  |                 "sender": "@alice:example.com", | ||||||
|  |                 "type": "m.room.canonical_alias", | ||||||
|  |                 "content": { | ||||||
|  |                   "alias": "#famedlyContactDiscovery:fakeServer.notExisting" | ||||||
|  |                 }, | ||||||
|  |                 "state_key": "", | ||||||
|  |                 "origin_server_ts": 1417731086796, | ||||||
|  |                 "event_id": "66697273743032:example.com" | ||||||
|  |               } | ||||||
|  |             ] | ||||||
|  |           }, | ||||||
|  |           "timeline": { | ||||||
|  |             "events": [ | ||||||
|  |               { | ||||||
|  |                 "sender": "@bob:example.com", | ||||||
|  |                 "type": "m.room.member", | ||||||
|  |                 "state_key": "@bob:example.com", | ||||||
|  |                 "content": {"membership": "join"}, | ||||||
|  |                 "prev_content": {"membership": "invite"}, | ||||||
|  |                 "origin_server_ts": 1417731086795, | ||||||
|  |                 "event_id": "7365636s6r6432:example.com" | ||||||
|  |               }, | ||||||
|  |               { | ||||||
|  |                 "sender": "@alice:example.com", | ||||||
|  |                 "type": "m.room.message", | ||||||
|  |                 "txn_id": "1234", | ||||||
|  |                 "content": {"body": "I am a fish", "msgtype": "m.text"}, | ||||||
|  |                 "origin_server_ts": 1417731086797, | ||||||
|  |                 "event_id": "74686972643033:example.com" | ||||||
|  |               } | ||||||
|  |             ], | ||||||
|  |             "limited": true, | ||||||
|  |             "prev_batch": "t34-23535_0_0" | ||||||
|  |           }, | ||||||
|  |           "ephemeral": { | ||||||
|  |             "events": [ | ||||||
|  |               { | ||||||
|  |                 "type": "m.typing", | ||||||
|  |                 "content": { | ||||||
|  |                   "user_ids": ["@alice:example.com"] | ||||||
|  |                 } | ||||||
|  |               }, | ||||||
|  |               { | ||||||
|  |                 "content": { | ||||||
|  |                   "7365636s6r6432:example.com": { | ||||||
|  |                     "m.read": { | ||||||
|  |                       "@alice:example.com": {"ts": 1436451550453} | ||||||
|  |                     } | ||||||
|  |                   } | ||||||
|  |                 }, | ||||||
|  |                 "room_id": "!726s6s6q:example.com", | ||||||
|  |                 "type": "m.receipt" | ||||||
|  |               } | ||||||
|  |             ] | ||||||
|  |           }, | ||||||
|  |           "account_data": { | ||||||
|  |             "events": [ | ||||||
|  |               { | ||||||
|  |                 "type": "m.tag", | ||||||
|  |                 "content": { | ||||||
|  |                   "tags": { | ||||||
|  |                     "work": {"order": 1} | ||||||
|  |                   } | ||||||
|  |                 } | ||||||
|  |               }, | ||||||
|  |               { | ||||||
|  |                 "type": "org.example.custom.room.config", | ||||||
|  |                 "content": {"custom_config_key": "custom_config_value"} | ||||||
|  |               } | ||||||
|  |             ] | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "invite": { | ||||||
|  |         "!696r7674:example.com": { | ||||||
|  |           "invite_state": { | ||||||
|  |             "events": [ | ||||||
|  |               { | ||||||
|  |                 "sender": "@alice:example.com", | ||||||
|  |                 "type": "m.room.name", | ||||||
|  |                 "state_key": "", | ||||||
|  |                 "content": {"name": "My Room Name"} | ||||||
|  |               }, | ||||||
|  |               { | ||||||
|  |                 "sender": "@alice:example.com", | ||||||
|  |                 "type": "m.room.member", | ||||||
|  |                 "state_key": "@bob:example.com", | ||||||
|  |                 "content": {"membership": "invite"} | ||||||
|  |               } | ||||||
|  |             ] | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   static Map<String, dynamic> archiveSyncResponse = { | ||||||
|  |     "next_batch": Random().nextDouble().toString(), | ||||||
|  |     "presence": {"events": []}, | ||||||
|  |     "account_data": {"events": []}, | ||||||
|  |     "to_device": {"events": []}, | ||||||
|  |     "rooms": { | ||||||
|  |       "join": {}, | ||||||
|  |       "invite": {}, | ||||||
|  |       "leave": { | ||||||
|  |         "!5345234234:example.com": { | ||||||
|  |           "timeline": {"events": []} | ||||||
|  |         }, | ||||||
|  |       }, | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|   static final Map<String, Map<String, dynamic>> api = { |   static final Map<String, Map<String, dynamic>> api = { | ||||||
|     "GET": { |     "GET": { | ||||||
|       "/client/r0/rooms/!localpart:server.abc/state/m.room.member/@getme:example.com": |       "/client/r0/rooms/!localpart:server.abc/state/m.room.member/@getme:example.com": | ||||||
|  | @ -339,171 +509,10 @@ class FakeMatrixApi extends MockClient { | ||||||
|               ] |               ] | ||||||
|             } |             } | ||||||
|           }, |           }, | ||||||
|       "/client/r0/sync?filter=%7B%22room%22:%7B%22include_leave%22:true,%22state%22:%7B%22lazy_load_members%22:true%7D%7D%7D": |       "/client/r0/sync?filter=%7B%22room%22:%7B%22include_leave%22:true,%22timeline%22:%7B%22limit%22:1%7D%7D%7D&timeout=0": | ||||||
|           (var req) => { |           (var req) => archiveSyncResponse, | ||||||
|                 "next_batch": Random().nextDouble().toString(), |       "/client/r0/sync?filter=%7B%22room%22:%7B%22state%22:%7B%22lazy_load_members%22:true%7D%7D%7D": | ||||||
|                 "presence": { |           (var req) => syncResponse, | ||||||
|                   "events": [ |  | ||||||
|                     { |  | ||||||
|                       "sender": "@alice:example.com", |  | ||||||
|                       "type": "m.presence", |  | ||||||
|                       "content": {"presence": "online"} |  | ||||||
|                     } |  | ||||||
|                   ] |  | ||||||
|                 }, |  | ||||||
|                 "account_data": { |  | ||||||
|                   "events": [ |  | ||||||
|                     { |  | ||||||
|                       "type": "org.example.custom.config", |  | ||||||
|                       "content": {"custom_config_key": "custom_config_value"} |  | ||||||
|                     }, |  | ||||||
|                     { |  | ||||||
|                       "content": { |  | ||||||
|                         "@bob:example.com": [ |  | ||||||
|                           "!726s6s6q:example.com", |  | ||||||
|                           "!hgfedcba:example.com" |  | ||||||
|                         ] |  | ||||||
|                       }, |  | ||||||
|                       "type": "m.direct" |  | ||||||
|                     }, |  | ||||||
|                   ] |  | ||||||
|                 }, |  | ||||||
|                 "to_device": { |  | ||||||
|                   "events": [ |  | ||||||
|                     { |  | ||||||
|                       "sender": "@alice:example.com", |  | ||||||
|                       "type": "m.new_device", |  | ||||||
|                       "content": { |  | ||||||
|                         "device_id": "XYZABCDE", |  | ||||||
|                         "rooms": ["!726s6s6q:example.com"] |  | ||||||
|                       } |  | ||||||
|                     } |  | ||||||
|                   ] |  | ||||||
|                 }, |  | ||||||
|                 "rooms": { |  | ||||||
|                   "join": { |  | ||||||
|                     "!726s6s6q:example.com": { |  | ||||||
|                       "unread_notifications": { |  | ||||||
|                         "highlight_count": 2, |  | ||||||
|                         "notification_count": 2, |  | ||||||
|                       }, |  | ||||||
|                       "state": { |  | ||||||
|                         "events": [ |  | ||||||
|                           { |  | ||||||
|                             "sender": "@alice:example.com", |  | ||||||
|                             "type": "m.room.member", |  | ||||||
|                             "state_key": "@alice:example.com", |  | ||||||
|                             "content": {"membership": "join"}, |  | ||||||
|                             "origin_server_ts": 1417731086795, |  | ||||||
|                             "event_id": "66697273743031:example.com" |  | ||||||
|                           }, |  | ||||||
|                           { |  | ||||||
|                             "sender": "@alice:example.com", |  | ||||||
|                             "type": "m.room.canonical_alias", |  | ||||||
|                             "content": { |  | ||||||
|                               "alias": |  | ||||||
|                                   "#famedlyContactDiscovery:fakeServer.notExisting" |  | ||||||
|                             }, |  | ||||||
|                             "state_key": "", |  | ||||||
|                             "origin_server_ts": 1417731086796, |  | ||||||
|                             "event_id": "66697273743032:example.com" |  | ||||||
|                           } |  | ||||||
|                         ] |  | ||||||
|                       }, |  | ||||||
|                       "timeline": { |  | ||||||
|                         "events": [ |  | ||||||
|                           { |  | ||||||
|                             "sender": "@bob:example.com", |  | ||||||
|                             "type": "m.room.member", |  | ||||||
|                             "state_key": "@bob:example.com", |  | ||||||
|                             "content": {"membership": "join"}, |  | ||||||
|                             "prev_content": {"membership": "invite"}, |  | ||||||
|                             "origin_server_ts": 1417731086795, |  | ||||||
|                             "event_id": "7365636s6r6432:example.com" |  | ||||||
|                           }, |  | ||||||
|                           { |  | ||||||
|                             "sender": "@alice:example.com", |  | ||||||
|                             "type": "m.room.message", |  | ||||||
|                             "txn_id": "1234", |  | ||||||
|                             "content": { |  | ||||||
|                               "body": "I am a fish", |  | ||||||
|                               "msgtype": "m.text" |  | ||||||
|                             }, |  | ||||||
|                             "origin_server_ts": 1417731086797, |  | ||||||
|                             "event_id": "74686972643033:example.com" |  | ||||||
|                           } |  | ||||||
|                         ], |  | ||||||
|                         "limited": true, |  | ||||||
|                         "prev_batch": "t34-23535_0_0" |  | ||||||
|                       }, |  | ||||||
|                       "ephemeral": { |  | ||||||
|                         "events": [ |  | ||||||
|                           { |  | ||||||
|                             "type": "m.typing", |  | ||||||
|                             "content": { |  | ||||||
|                               "user_ids": ["@alice:example.com"] |  | ||||||
|                             } |  | ||||||
|                           }, |  | ||||||
|                           { |  | ||||||
|                             "content": { |  | ||||||
|                               "7365636s6r6432:example.com": { |  | ||||||
|                                 "m.read": { |  | ||||||
|                                   "@alice:example.com": {"ts": 1436451550453} |  | ||||||
|                                 } |  | ||||||
|                               } |  | ||||||
|                             }, |  | ||||||
|                             "room_id": "!726s6s6q:example.com", |  | ||||||
|                             "type": "m.receipt" |  | ||||||
|                           } |  | ||||||
|                         ] |  | ||||||
|                       }, |  | ||||||
|                       "account_data": { |  | ||||||
|                         "events": [ |  | ||||||
|                           { |  | ||||||
|                             "type": "m.tag", |  | ||||||
|                             "content": { |  | ||||||
|                               "tags": { |  | ||||||
|                                 "work": {"order": 1} |  | ||||||
|                               } |  | ||||||
|                             } |  | ||||||
|                           }, |  | ||||||
|                           { |  | ||||||
|                             "type": "org.example.custom.room.config", |  | ||||||
|                             "content": { |  | ||||||
|                               "custom_config_key": "custom_config_value" |  | ||||||
|                             } |  | ||||||
|                           } |  | ||||||
|                         ] |  | ||||||
|                       } |  | ||||||
|                     } |  | ||||||
|                   }, |  | ||||||
|                   "invite": { |  | ||||||
|                     "!696r7674:example.com": { |  | ||||||
|                       "invite_state": { |  | ||||||
|                         "events": [ |  | ||||||
|                           { |  | ||||||
|                             "sender": "@alice:example.com", |  | ||||||
|                             "type": "m.room.name", |  | ||||||
|                             "state_key": "", |  | ||||||
|                             "content": {"name": "My Room Name"} |  | ||||||
|                           }, |  | ||||||
|                           { |  | ||||||
|                             "sender": "@alice:example.com", |  | ||||||
|                             "type": "m.room.member", |  | ||||||
|                             "state_key": "@bob:example.com", |  | ||||||
|                             "content": {"membership": "invite"} |  | ||||||
|                           } |  | ||||||
|                         ] |  | ||||||
|                       } |  | ||||||
|                     } |  | ||||||
|                   }, |  | ||||||
|                   "leave": { |  | ||||||
|                     "!5345234234:example.com": { |  | ||||||
|                       "timeline": {"events": []} |  | ||||||
|                     }, |  | ||||||
|                   }, |  | ||||||
|                 } |  | ||||||
|               }, |  | ||||||
|     }, |     }, | ||||||
|     "POST": { |     "POST": { | ||||||
|       "/client/r0/login": (var req) => { |       "/client/r0/login": (var req) => { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue