From a3c5add79e55caddc7d28451689cf1617c808a48 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Mon, 30 Mar 2020 09:08:38 +0000 Subject: [PATCH] [SDK] Refactoring with new linter rules --- lib/src/account_data.dart | 3 +- lib/src/client.dart | 1066 ++++++++------- lib/src/event.dart | 249 ++-- lib/src/presence.dart | 2 +- lib/src/room.dart | 899 +++++++------ lib/src/room_account_data.dart | 3 +- lib/src/store_api.dart | 3 +- lib/src/sync/event_update.dart | 6 +- lib/src/timeline.dart | 56 +- lib/src/user.dart | 34 +- lib/src/utils/device_keys_list.dart | 43 +- lib/src/utils/matrix_exception.dart | 33 +- lib/src/utils/matrix_file.dart | 7 +- lib/src/utils/matrix_id_string_extension.dart | 18 +- lib/src/utils/mx_content.dart | 10 +- lib/src/utils/open_id_credentials.dart | 11 +- lib/src/utils/profile.dart | 4 +- lib/src/utils/public_rooms_response.dart | 2 +- lib/src/utils/push_rules.dart | 48 +- lib/src/utils/room_key_request.dart | 26 +- lib/src/utils/session_key.dart | 25 +- lib/src/utils/states_map.dart | 18 +- lib/src/utils/to_device_event.dart | 11 +- lib/src/utils/user_device.dart | 8 +- pubspec.lock | 4 +- pubspec.yaml | 2 +- test/canonical_json_test.dart | 26 +- test/client_test.dart | 483 ++++--- test/device_keys_list_test.dart | 52 +- test/event_test.dart | 205 ++- test/fake_matrix_api.dart | 1156 ++++++++--------- test/fake_store.dart | 52 +- test/matrix_id_string_extension_test.dart | 36 +- test/mx_content_test.dart | 28 +- test/presence_test.dart | 30 +- test/push_rules_test.dart | 198 +-- test/room_key_request_test.dart | 48 +- test/room_test.dart | 399 +++--- test/states_map_test.dart | 76 +- test/timeline_test.dart | 156 +-- test/user_test.dart | 52 +- test_driver/famedlysdk_test.dart | 86 +- 42 files changed, 2827 insertions(+), 2847 deletions(-) diff --git a/lib/src/account_data.dart b/lib/src/account_data.dart index 7d41ebc..1a0208b 100644 --- a/lib/src/account_data.dart +++ b/lib/src/account_data.dart @@ -35,8 +35,7 @@ class AccountData { /// Get a State event from a table row or from the event stream. factory AccountData.fromJson(Map jsonPayload) { - final Map content = - Event.getMapFromPayload(jsonPayload['content']); + final content = Event.getMapFromPayload(jsonPayload['content']); return AccountData(content: content, typeKey: jsonPayload['type']); } } diff --git a/lib/src/client.dart b/lib/src/client.dart index d43095c..5b37bf5 100644 --- a/lib/src/client.dart +++ b/lib/src/client.dart @@ -74,8 +74,8 @@ class Client { StoreAPI storeAPI; Client(this.clientName, {this.debug = false, this.storeAPI}) { - this.onLoginStateChanged.stream.listen((loginState) { - print("LoginState: ${loginState.toString()}"); + onLoginStateChanged.stream.listen((loginState) { + print('LoginState: ${loginState.toString()}'); }); } @@ -139,7 +139,7 @@ class Client { /// Warning! This endpoint is for testing only! set rooms(List newList) { - print("Warning! This endpoint is for testing only!"); + print('Warning! This endpoint is for testing only!'); _rooms = newList; } @@ -152,57 +152,57 @@ class Client { int _timeoutFactor = 1; Room getRoomByAlias(String alias) { - for (int i = 0; i < rooms.length; i++) { + for (var i = 0; i < rooms.length; i++) { if (rooms[i].canonicalAlias == alias) return rooms[i]; } return null; } Room getRoomById(String id) { - for (int j = 0; j < rooms.length; j++) { + for (var j = 0; j < rooms.length; j++) { if (rooms[j].id == id) return rooms[j]; } return null; } void handleUserUpdate(UserUpdate userUpdate) { - if (userUpdate.type == "account_data") { - AccountData newAccountData = AccountData.fromJson(userUpdate.content); + if (userUpdate.type == 'account_data') { + var newAccountData = AccountData.fromJson(userUpdate.content); accountData[newAccountData.typeKey] = newAccountData; if (onAccountData != null) onAccountData.add(newAccountData); } - if (userUpdate.type == "presence") { - Presence newPresence = Presence.fromJson(userUpdate.content); + if (userUpdate.type == 'presence') { + var newPresence = Presence.fromJson(userUpdate.content); presences[newPresence.sender] = newPresence; if (onPresence != null) onPresence.add(newPresence); } } Map get directChats => - accountData["m.direct"] != null ? accountData["m.direct"].content : {}; + accountData['m.direct'] != null ? accountData['m.direct'].content : {}; /// Returns the (first) room ID from the store which is a private chat with the user [userId]. /// Returns null if there is none. String getDirectChatFromUserId(String userId) { - if (accountData["m.direct"] != null && - accountData["m.direct"].content[userId] is List && - accountData["m.direct"].content[userId].length > 0) { - if (getRoomById(accountData["m.direct"].content[userId][0]) != null) { - return accountData["m.direct"].content[userId][0]; + if (accountData['m.direct'] != null && + accountData['m.direct'].content[userId] is List && + accountData['m.direct'].content[userId].length > 0) { + if (getRoomById(accountData['m.direct'].content[userId][0]) != null) { + return accountData['m.direct'].content[userId][0]; } - (accountData["m.direct"].content[userId] as List) - .remove(accountData["m.direct"].content[userId][0]); - this.jsonRequest( + (accountData['m.direct'].content[userId] as List) + .remove(accountData['m.direct'].content[userId][0]); + jsonRequest( type: HTTPType.PUT, - action: "/client/r0/user/${userID}/account_data/m.direct", + action: '/client/r0/user/${userID}/account_data/m.direct', data: directChats); return getDirectChatFromUserId(userId); } - for (int i = 0; i < this.rooms.length; i++) { - if (this.rooms[i].membership == Membership.invite && - this.rooms[i].states[userID]?.senderId == userId && - this.rooms[i].states[userID].content["is_direct"] == true) { - return this.rooms[i].id; + for (var i = 0; i < rooms.length; i++) { + if (rooms[i].membership == Membership.invite && + rooms[i].states[userID]?.senderId == userId && + rooms[i].states[userID].content['is_direct'] == true) { + return rooms[i].id; } } return null; @@ -215,13 +215,13 @@ class Client { Future checkServer(serverUrl) async { try { _homeserver = serverUrl; - final versionResp = await this - .jsonRequest(type: HTTPType.GET, action: "/client/versions"); + final versionResp = + await jsonRequest(type: HTTPType.GET, action: '/client/versions'); - final List versions = List.from(versionResp["versions"]); + final versions = List.from(versionResp['versions']); - for (int i = 0; i < versions.length; i++) { - if (versions[i] == "r0.5.0") { + for (var i = 0; i < versions.length; i++) { + if (versions[i] == 'r0.5.0') { break; } else if (i == versions.length - 1) { return false; @@ -230,22 +230,22 @@ class Client { _matrixVersions = versions; - if (versionResp.containsKey("unstable_features") && - versionResp["unstable_features"].containsKey("m.lazy_load_members")) { - _lazyLoadMembers = versionResp["unstable_features"] - ["m.lazy_load_members"] + if (versionResp.containsKey('unstable_features') && + versionResp['unstable_features'].containsKey('m.lazy_load_members')) { + _lazyLoadMembers = versionResp['unstable_features'] + ['m.lazy_load_members'] ? true : false; } - final loginResp = await this - .jsonRequest(type: HTTPType.GET, action: "/client/r0/login"); + final loginResp = + await jsonRequest(type: HTTPType.GET, action: '/client/r0/login'); - final List flows = loginResp["flows"]; + final List flows = loginResp['flows']; - for (int i = 0; i < flows.length; i++) { - if (flows[i].containsKey("type") && - flows[i]["type"] == "m.login.password") { + for (var i = 0; i < flows.length; i++) { + if (flows[i].containsKey('type') && + flows[i]['type'] == 'm.login.password') { break; } else if (i == flows.length - 1) { return false; @@ -253,7 +253,7 @@ class Client { } return true; } catch (_) { - this._homeserver = this._matrixVersions = null; + _homeserver = _matrixVersions = null; rethrow; } } @@ -261,11 +261,11 @@ class Client { /// Checks to see if a username is available, and valid, for the server. /// You have to call [checkServer] first to set a homeserver. Future usernameAvailable(String username) async { - final Map response = await this.jsonRequest( + final response = await jsonRequest( type: HTTPType.GET, - action: "/client/r0/register/available?username=$username", + action: '/client/r0/register/available?username=$username', ); - return response["available"]; + return response['available']; } /// Checks to see if a username is available, and valid, for the server. @@ -280,30 +280,29 @@ class Client { String initialDeviceDisplayName, bool inhibitLogin, }) async { - final String action = - "/client/r0/register" + (kind != null ? "?kind=$kind" : ""); - Map data = {}; - if (username != null) data["username"] = username; - if (password != null) data["password"] = password; - if (auth != null) data["auth"] = auth; - if (deviceId != null) data["device_id"] = deviceId; + final action = '/client/r0/register' + (kind != null ? '?kind=$kind' : ''); + var data = {}; + if (username != null) data['username'] = username; + if (password != null) data['password'] = password; + if (auth != null) data['auth'] = auth; + if (deviceId != null) data['device_id'] = deviceId; if (initialDeviceDisplayName != null) { - data["initial_device_display_name"] = initialDeviceDisplayName; + data['initial_device_display_name'] = initialDeviceDisplayName; } - if (inhibitLogin != null) data["inhibit_login"] = inhibitLogin; - final Map response = - await this.jsonRequest(type: HTTPType.POST, action: action, data: data); + if (inhibitLogin != null) data['inhibit_login'] = inhibitLogin; + final response = + await jsonRequest(type: HTTPType.POST, action: action, data: data); // Connect if there is an access token in the response. - if (response.containsKey("access_token") && - response.containsKey("device_id") && - response.containsKey("user_id")) { - await this.connect( - newToken: response["access_token"], - newUserID: response["user_id"], + if (response.containsKey('access_token') && + response.containsKey('device_id') && + response.containsKey('user_id')) { + await connect( + newToken: response['access_token'], + newUserID: response['user_id'], newHomeserver: homeserver, - newDeviceName: initialDeviceDisplayName ?? "", - newDeviceID: response["device_id"], + newDeviceName: initialDeviceDisplayName ?? '', + newDeviceID: response['device_id'], newMatrixVersions: matrixVersions, newLazyLoadMembers: lazyLoadMembers); } @@ -320,32 +319,32 @@ class Client { String initialDeviceDisplayName, String deviceId, }) async { - Map data = { - "type": "m.login.password", - "user": username, - "identifier": { - "type": "m.id.user", - "user": username, + var data = { + 'type': 'm.login.password', + 'user': username, + 'identifier': { + 'type': 'm.id.user', + 'user': username, }, - "password": password, + 'password': password, }; - if (deviceId != null) data["device_id"] = deviceId; + if (deviceId != null) data['device_id'] = deviceId; if (initialDeviceDisplayName != null) { - data["initial_device_display_name"] = initialDeviceDisplayName; + data['initial_device_display_name'] = initialDeviceDisplayName; } final loginResp = await jsonRequest( - type: HTTPType.POST, action: "/client/r0/login", data: data); + type: HTTPType.POST, action: '/client/r0/login', data: data); - if (loginResp.containsKey("user_id") && - loginResp.containsKey("access_token") && - loginResp.containsKey("device_id")) { - await this.connect( - newToken: loginResp["access_token"], - newUserID: loginResp["user_id"], + if (loginResp.containsKey('user_id') && + loginResp.containsKey('access_token') && + loginResp.containsKey('device_id')) { + await connect( + newToken: loginResp['access_token'], + newUserID: loginResp['user_id'], newHomeserver: homeserver, - newDeviceName: initialDeviceDisplayName ?? "", - newDeviceID: loginResp["device_id"], + newDeviceName: initialDeviceDisplayName ?? '', + newDeviceID: loginResp['device_id'], newMatrixVersions: matrixVersions, newLazyLoadMembers: lazyLoadMembers, ); @@ -358,11 +357,11 @@ class Client { /// including all persistent data from the store. Future logout() async { try { - await this.jsonRequest(type: HTTPType.POST, action: "/client/r0/logout"); + await jsonRequest(type: HTTPType.POST, action: '/client/r0/logout'); } catch (exception) { rethrow; } finally { - await this.clear(); + await clear(); } } @@ -372,8 +371,8 @@ class Client { /// profile will be requested from the homserver. Future get ownProfile async { if (rooms.isNotEmpty) { - Set profileSet = {}; - for (Room room in rooms) { + var profileSet = {}; + for (var room in rooms) { final user = room.getUserByMXIDSync(userID); profileSet.add(Profile.fromJson(user.content)); } @@ -386,43 +385,42 @@ class Client { /// fetch the user's own profile information or other users; either locally /// or on remote homeservers. Future getProfileFromUserId(String userId) async { - final dynamic resp = await this.jsonRequest( - type: HTTPType.GET, action: "/client/r0/profile/${userId}"); + final dynamic resp = await jsonRequest( + type: HTTPType.GET, action: '/client/r0/profile/${userId}'); return Profile.fromJson(resp); } Future> get archive async { - List archiveList = []; - String syncFilters = - '{"room":{"include_leave":true,"timeline":{"limit":10}}}'; - String action = "/client/r0/sync?filter=$syncFilters&timeout=0"; - final sync = await this.jsonRequest(type: HTTPType.GET, action: action); - if (sync["rooms"]["leave"] is Map) { - for (var entry in sync["rooms"]["leave"].entries) { + var archiveList = []; + var syncFilters = '{"room":{"include_leave":true,"timeline":{"limit":10}}}'; + var action = '/client/r0/sync?filter=$syncFilters&timeout=0'; + final sync = await jsonRequest(type: HTTPType.GET, action: action); + if (sync['rooms']['leave'] is Map) { + for (var entry in sync['rooms']['leave'].entries) { final String id = entry.key; final dynamic room = entry.value; - Room leftRoom = Room( + var leftRoom = Room( id: id, membership: Membership.leave, client: this, roomAccountData: {}, mHeroes: []); - if (room["account_data"] is Map && - room["account_data"]["events"] is List) { - for (dynamic event in room["account_data"]["events"]) { - leftRoom.roomAccountData[event["type"]] = + if (room['account_data'] is Map && + room['account_data']['events'] is List) { + for (dynamic event in room['account_data']['events']) { + leftRoom.roomAccountData[event['type']] = RoomAccountData.fromJson(event, leftRoom); } } - if (room["timeline"] is Map && - room["timeline"]["events"] is List) { - for (dynamic event in room["timeline"]["events"]) { + if (room['timeline'] is Map && + room['timeline']['events'] is List) { + for (dynamic event in room['timeline']['events']) { leftRoom.setState(Event.fromJson(event, leftRoom)); } } - if (room["state"] is Map && - room["state"]["events"] is List) { - for (dynamic event in room["state"]["events"]) { + if (room['state'] is Map && + room['state']['events'] is List) { + for (dynamic event in room['state']['events']) { leftRoom.setState(Event.fromJson(event, leftRoom)); } } @@ -436,8 +434,8 @@ class Client { /// After this call, the client is allowed to see all current state events in the room, and all subsequent events /// associated with the room until the user leaves the room. Future joinRoomById(String roomIdOrAlias) async { - return await this.jsonRequest( - type: HTTPType.POST, action: "/client/r0/join/$roomIdOrAlias"); + return await jsonRequest( + type: HTTPType.POST, action: '/client/r0/join/$roomIdOrAlias'); } /// Loads the contact list for this user excluding the user itself. @@ -445,16 +443,16 @@ class Client { /// the famedlyContactDiscovery room, which is /// defined by the autojoin room feature in Synapse. Future> loadFamedlyContacts() async { - List contacts = []; - Room contactDiscoveryRoom = - this.getRoomByAlias("#famedlyContactDiscovery:${userID.domain}"); + var contacts = []; + var contactDiscoveryRoom = + getRoomByAlias('#famedlyContactDiscovery:${userID.domain}'); if (contactDiscoveryRoom != null) { contacts = await contactDiscoveryRoom.requestParticipants(); } else { - Map userMap = {}; - for (int i = 0; i < this.rooms.length; i++) { - List roomUsers = this.rooms[i].getParticipants(); - for (int j = 0; j < roomUsers.length; j++) { + var userMap = {}; + for (var i = 0; i < rooms.length; i++) { + var roomUsers = rooms[i].getParticipants(); + for (var j = 0; j < roomUsers.length; j++) { if (userMap[roomUsers[j].id] != true) contacts.add(roomUsers[j]); userMap[roomUsers[j].id] = true; } @@ -472,23 +470,22 @@ class Client { /// to configure [params]. Future createRoom( {List invite, Map params}) async { - List inviteIDs = []; + var inviteIDs = []; if (params == null && invite != null) { - for (int i = 0; i < invite.length; i++) { + for (var i = 0; i < invite.length; i++) { inviteIDs.add(invite[i].id); } } try { - final dynamic resp = await this.jsonRequest( + final dynamic resp = await jsonRequest( type: HTTPType.POST, - action: "/client/r0/createRoom", - data: params == null - ? { - "invite": inviteIDs, - } - : params); - return resp["room_id"]; + action: '/client/r0/createRoom', + data: params ?? + { + 'invite': inviteIDs, + }); + return resp['room_id']; } catch (e) { rethrow; } @@ -496,71 +493,71 @@ class Client { /// Changes the user's displayname. Future setDisplayname(String displayname) async { - await this.jsonRequest( + await jsonRequest( type: HTTPType.PUT, - action: "/client/r0/profile/$userID/displayname", - data: {"displayname": displayname}); + action: '/client/r0/profile/$userID/displayname', + data: {'displayname': displayname}); return; } /// Uploads a new user avatar for this user. Future setAvatar(MatrixFile file) async { - final uploadResp = await this.upload(file); - await this.jsonRequest( + final uploadResp = await upload(file); + await jsonRequest( type: HTTPType.PUT, - action: "/client/r0/profile/$userID/avatar_url", - data: {"avatar_url": uploadResp}); + action: '/client/r0/profile/$userID/avatar_url', + data: {'avatar_url': uploadResp}); return; } /// Get credentials for the client to use when initiating calls. Future getTurnServerCredentials() async { - final Map response = await this.jsonRequest( + final response = await jsonRequest( type: HTTPType.GET, - action: "/client/r0/voip/turnServer", + action: '/client/r0/voip/turnServer', ); return TurnServerCredentials.fromJson(response); } /// Fetches the pushrules for the logged in user. /// These are needed for notifications on Android - @Deprecated("Use [pushRules] instead.") + @Deprecated('Use [pushRules] instead.') Future getPushrules() async { - final dynamic resp = await this.jsonRequest( + final dynamic resp = await jsonRequest( type: HTTPType.GET, - action: "/client/r0/pushrules/", + action: '/client/r0/pushrules/', ); return PushRules.fromJson(resp); } /// Returns the push rules for the logged in user. - PushRules get pushRules => accountData.containsKey("m.push_rules") - ? PushRules.fromJson(accountData["m.push_rules"].content) + PushRules get pushRules => accountData.containsKey('m.push_rules') + ? PushRules.fromJson(accountData['m.push_rules'].content) : null; /// This endpoint allows the creation, modification and deletion of pushers for this user ID. Future setPushers(String pushKey, String kind, String appId, String appDisplayName, String deviceDisplayName, String lang, String url, {bool append, String profileTag, String format}) async { - Map data = { - "lang": lang, - "kind": kind, - "app_display_name": appDisplayName, - "device_display_name": deviceDisplayName, - "profile_tag": profileTag, - "app_id": appId, - "pushkey": pushKey, - "data": {"url": url} + var data = { + 'lang': lang, + 'kind': kind, + 'app_display_name': appDisplayName, + 'device_display_name': deviceDisplayName, + 'profile_tag': profileTag, + 'app_id': appId, + 'pushkey': pushKey, + 'data': {'url': url} }; - if (format != null) data["data"]["format"] = format; - if (profileTag != null) data["profile_tag"] = profileTag; - if (append != null) data["append"] = append; + if (format != null) data['data']['format'] = format; + if (profileTag != null) data['profile_tag'] = profileTag; + if (append != null) data['append'] = append; - await this.jsonRequest( + await jsonRequest( type: HTTPType.POST, - action: "/client/r0/pushers/set", + action: '/client/r0/pushers/set', data: data, ); return; @@ -568,10 +565,10 @@ class Client { static String syncFilters = '{"room":{"state":{"lazy_load_members":true}}}'; static const List supportedDirectEncryptionAlgorithms = [ - "m.olm.v1.curve25519-aes-sha2" + 'm.olm.v1.curve25519-aes-sha2' ]; static const List supportedGroupEncryptionAlgorithms = [ - "m.megolm.v1.aes-sha2" + 'm.megolm.v1.aes-sha2' ]; http.Client httpClient = http.Client(); @@ -683,42 +680,42 @@ class Client { String newPrevBatch, String newOlmAccount, }) async { - this._accessToken = newToken; - this._homeserver = newHomeserver; - this._userID = newUserID; - this._deviceID = newDeviceID; - this._deviceName = newDeviceName; - this._matrixVersions = newMatrixVersions; - this._lazyLoadMembers = newLazyLoadMembers; - this.prevBatch = newPrevBatch; + _accessToken = newToken; + _homeserver = newHomeserver; + _userID = newUserID; + _deviceID = newDeviceID; + _deviceName = newDeviceName; + _matrixVersions = newMatrixVersions; + _lazyLoadMembers = newLazyLoadMembers; + prevBatch = newPrevBatch; // Try to create a new olm account or restore a previous one. if (newOlmAccount == null) { try { await olm.init(); - this._olmAccount = olm.Account(); - this._olmAccount.create(); - if (await this._uploadKeys(uploadDeviceKeys: true) == false) { - throw ("Upload key failed"); + _olmAccount = olm.Account(); + _olmAccount.create(); + if (await _uploadKeys(uploadDeviceKeys: true) == false) { + throw ('Upload key failed'); } } catch (_) { - this._olmAccount = null; + _olmAccount = null; } } else { try { await olm.init(); - this._olmAccount = olm.Account(); - this._olmAccount.unpickle(userID, newOlmAccount); + _olmAccount = olm.Account(); + _olmAccount.unpickle(userID, newOlmAccount); } catch (_) { - this._olmAccount = null; + _olmAccount = null; } } - if (this.storeAPI != null) { - await this.storeAPI.storeClient(); - _userDeviceKeys = await this.storeAPI.getUserDeviceKeys(); + if (storeAPI != null) { + await storeAPI.storeClient(); + _userDeviceKeys = await storeAPI.getUserDeviceKeys(); final String olmSessionPickleString = - await storeAPI.getItem("/clients/$userID/olm-sessions"); + await storeAPI.getItem('/clients/$userID/olm-sessions'); if (olmSessionPickleString != null) { final Map pickleMap = json.decode(olmSessionPickleString); @@ -726,24 +723,24 @@ class Client { for (String pickle in entry.value) { _olmSessions[entry.key] = []; try { - olm.Session session = olm.Session(); + var session = olm.Session(); session.unpickle(userID, pickle); _olmSessions[entry.key].add(session); } catch (e) { - print("[LibOlm] Could not unpickle olm session: " + e.toString()); + print('[LibOlm] Could not unpickle olm session: ' + e.toString()); } } } } - if (this.store != null) { - this._rooms = await this.store.getRoomList(onlyLeft: false); - this._sortRooms(); - this.accountData = await this.store.getAccountData(); - this.presences = await this.store.getPresences(); + if (store != null) { + _rooms = await store.getRoomList(onlyLeft: false); + _sortRooms(); + accountData = await store.getAccountData(); + presences = await store.getPresences(); } } - _userEventSub ??= onUserEvent.stream.listen(this.handleUserUpdate); + _userEventSub ??= onUserEvent.stream.listen(handleUserUpdate); onLoginStateChanged.add(LoginState.logged); @@ -763,11 +760,10 @@ class Client { sessionKey.inboundGroupSession?.free(); }); }); - this._olmAccount?.free(); - this.storeAPI?.clear(); - this._accessToken = this._homeserver = this._userID = this._deviceID = this - ._deviceName = - this._matrixVersions = this._lazyLoadMembers = this.prevBatch = null; + _olmAccount?.free(); + storeAPI?.clear(); + _accessToken = _homeserver = _userID = _deviceID = + _deviceName = _matrixVersions = _lazyLoadMembers = prevBatch = null; onLoginStateChanged.add(LoginState.loggedOut); } @@ -793,58 +789,58 @@ class Client { Future> jsonRequest( {HTTPType type, String action, - dynamic data = "", + dynamic data = '', int timeout, - String contentType = "application/json"}) async { - if (this.isLogged() == false && this.homeserver == null) { - throw ("No homeserver specified."); + String contentType = 'application/json'}) async { + if (isLogged() == false && homeserver == null) { + throw ('No homeserver specified.'); } - if (timeout == null) timeout = (_timeoutFactor * syncTimeoutSec) + 5; + timeout ??= (_timeoutFactor * syncTimeoutSec) + 5; dynamic json; if (data is Map) data.removeWhere((k, v) => v == null); (!(data is String)) ? json = jsonEncode(data) : json = data; - if (data is List || action.startsWith("/media/r0/upload")) json = data; + if (data is List || action.startsWith('/media/r0/upload')) json = data; - final url = "${this.homeserver}/_matrix${action}"; + final url = '${homeserver}/_matrix${action}'; - Map headers = {}; + var headers = {}; if (type == HTTPType.PUT || type == HTTPType.POST) { - headers["Content-Type"] = contentType; + headers['Content-Type'] = contentType; } - if (this.isLogged()) { - headers["Authorization"] = "Bearer ${this.accessToken}"; + if (isLogged()) { + headers['Authorization'] = 'Bearer ${accessToken}'; } - if (this.debug) { + if (debug) { print( "[REQUEST ${type.toString().split('.').last}] Action: $action, Data: ${jsonEncode(data)}"); } http.Response resp; - Map jsonResp = {}; + var jsonResp = {}; try { switch (type.toString().split('.').last) { - case "GET": + case 'GET': resp = await httpClient.get(url, headers: headers).timeout( Duration(seconds: timeout), onTimeout: () => null, ); break; - case "POST": + case 'POST': resp = await httpClient.post(url, body: json, headers: headers).timeout( Duration(seconds: timeout), onTimeout: () => null, ); break; - case "PUT": + case 'PUT': resp = await httpClient.put(url, body: json, headers: headers).timeout( Duration(seconds: timeout), onTimeout: () => null, ); break; - case "DELETE": + case 'DELETE': resp = await httpClient.delete(url, headers: headers).timeout( Duration(seconds: timeout), onTimeout: () => null, @@ -859,7 +855,7 @@ class Client { if (resp.statusCode >= 400 && resp.statusCode < 500) { // The server has responsed with an matrix related error. - MatrixException exception = MatrixException(resp); + var exception = MatrixException(resp); if (exception.error == MatrixError.M_UNKNOWN_TOKEN) { // The token is no longer valid. Need to sign off.... onError.add(exception); @@ -869,7 +865,7 @@ class Client { throw exception; } - if (this.debug) print("[RESPONSE] ${jsonResp.toString()}"); + if (debug) print('[RESPONSE] ${jsonResp.toString()}'); } on ArgumentError catch (exception) { print(exception); // Ignore this error @@ -888,62 +884,62 @@ class Client { /// and returns the mxc url as a string. Future upload(MatrixFile file, {String contentType}) async { // For testing - if (this.homeserver.toLowerCase() == "https://fakeserver.notexisting") { - return "mxc://example.com/AQwafuaFswefuhsfAFAgsw"; + if (homeserver.toLowerCase() == 'https://fakeserver.notexisting') { + return 'mxc://example.com/AQwafuaFswefuhsfAFAgsw'; } - Map headers = {}; - headers["Authorization"] = "Bearer $accessToken"; - headers["Content-Type"] = contentType ?? mime(file.path); - String fileName = Uri.encodeFull(file.path.split("/").last.toLowerCase()); - final url = "$homeserver/_matrix/media/r0/upload?filename=$fileName"; + var headers = {}; + headers['Authorization'] = 'Bearer $accessToken'; + headers['Content-Type'] = contentType ?? mime(file.path); + var fileName = Uri.encodeFull(file.path.split('/').last.toLowerCase()); + final url = '$homeserver/_matrix/media/r0/upload?filename=$fileName'; final streamedRequest = http.StreamedRequest('POST', Uri.parse(url)) ..headers.addAll(headers); streamedRequest.contentLength = await file.bytes.length; streamedRequest.sink.add(file.bytes); streamedRequest.sink.close(); - print("[UPLOADING] $fileName"); + print('[UPLOADING] $fileName'); var streamedResponse = await streamedRequest.send(); Map jsonResponse = json.decode( String.fromCharCodes(await streamedResponse.stream.first), ); - if (!(jsonResponse["content_uri"] is String && - jsonResponse["content_uri"].isNotEmpty)) { + if (!(jsonResponse['content_uri'] is String && + jsonResponse['content_uri'].isNotEmpty)) { throw ("Missing json key: 'content_uri' ${jsonResponse.toString()}"); } - return jsonResponse["content_uri"]; + return jsonResponse['content_uri']; } Future _syncRequest; Future _sync() async { - if (this.isLogged() == false) return; + if (isLogged() == false) return; - String action = "/client/r0/sync?filter=$syncFilters"; + var action = '/client/r0/sync?filter=$syncFilters'; - if (this.prevBatch != null) { - action += "&timeout=30000"; - action += "&since=${this.prevBatch}"; + if (prevBatch != null) { + action += '&timeout=30000'; + action += '&since=${prevBatch}'; } try { _syncRequest = jsonRequest(type: HTTPType.GET, action: action); - final int hash = _syncRequest.hashCode; + final hash = _syncRequest.hashCode; final syncResp = await _syncRequest; if (hash != _syncRequest.hashCode) return; _timeoutFactor = 1; - if (this.store != null) { - await this.store.transaction(() { + if (store != null) { + await store.transaction(() { handleSync(syncResp); - this.store.storePrevBatch(syncResp["next_batch"]); + store.storePrevBatch(syncResp['next_batch']); }); } else { await handleSync(syncResp); } - if (this.prevBatch == null) { - this.onFirstSync.add(true); - this.prevBatch = syncResp["next_batch"]; + if (prevBatch == null) { + onFirstSync.add(true); + prevBatch = syncResp['next_batch']; _sortRooms(); } - this.prevBatch = syncResp["next_batch"]; + prevBatch = syncResp['next_batch']; await _updateUserDeviceKeys(); if (hash == _syncRequest.hashCode) unawaited(_sync()); } on MatrixException catch (exception) { @@ -956,34 +952,34 @@ class Client { /// Use this method only for testing utilities! void handleSync(dynamic sync) { - if (sync["rooms"] is Map) { - if (sync["rooms"]["join"] is Map) { - _handleRooms(sync["rooms"]["join"], Membership.join); + if (sync['rooms'] is Map) { + if (sync['rooms']['join'] is Map) { + _handleRooms(sync['rooms']['join'], Membership.join); } - if (sync["rooms"]["invite"] is Map) { - _handleRooms(sync["rooms"]["invite"], Membership.invite); + if (sync['rooms']['invite'] is Map) { + _handleRooms(sync['rooms']['invite'], Membership.invite); } - if (sync["rooms"]["leave"] is Map) { - _handleRooms(sync["rooms"]["leave"], Membership.leave); + if (sync['rooms']['leave'] is Map) { + _handleRooms(sync['rooms']['leave'], Membership.leave); } } - if (sync["presence"] is Map && - sync["presence"]["events"] is List) { - _handleGlobalEvents(sync["presence"]["events"], "presence"); + if (sync['presence'] is Map && + sync['presence']['events'] is List) { + _handleGlobalEvents(sync['presence']['events'], 'presence'); } - if (sync["account_data"] is Map && - sync["account_data"]["events"] is List) { - _handleGlobalEvents(sync["account_data"]["events"], "account_data"); + if (sync['account_data'] is Map && + sync['account_data']['events'] is List) { + _handleGlobalEvents(sync['account_data']['events'], 'account_data'); } - if (sync["to_device"] is Map && - sync["to_device"]["events"] is List) { - _handleToDeviceEvents(sync["to_device"]["events"]); + if (sync['to_device'] is Map && + sync['to_device']['events'] is List) { + _handleToDeviceEvents(sync['to_device']['events']); } - if (sync["device_lists"] is Map) { - _handleDeviceListsEvents(sync["device_lists"]); + if (sync['device_lists'] is Map) { + _handleDeviceListsEvents(sync['device_lists']); } - if (sync["device_one_time_keys_count"] is Map) { - _handleDeviceOneTimeKeysCount(sync["device_one_time_keys_count"]); + if (sync['device_one_time_keys_count'] is Map) { + _handleDeviceOneTimeKeysCount(sync['device_one_time_keys_count']); } onSync.add(sync); } @@ -993,8 +989,8 @@ class Client { if (!encryptionEnabled) return; // Check if there are at least half of max_number_of_one_time_keys left on the server // and generate and upload more if not. - if (deviceOneTimeKeysCount["signed_curve25519"] is int) { - final int oneTimeKeysCount = deviceOneTimeKeysCount["signed_curve25519"]; + if (deviceOneTimeKeysCount['signed_curve25519'] is int) { + final int oneTimeKeysCount = deviceOneTimeKeysCount['signed_curve25519']; if (oneTimeKeysCount < (_olmAccount.max_number_of_one_time_keys() / 2)) { // Generate and upload more one time keys: _uploadKeys(); @@ -1003,13 +999,13 @@ class Client { } void _handleDeviceListsEvents(Map deviceLists) { - if (deviceLists["changed"] is List) { - for (final userId in deviceLists["changed"]) { + if (deviceLists['changed'] is List) { + for (final userId in deviceLists['changed']) { if (_userDeviceKeys.containsKey(userId)) { _userDeviceKeys[userId].outdated = true; } } - for (final userId in deviceLists["left"]) { + for (final userId in deviceLists['left']) { if (_userDeviceKeys.containsKey(userId)) { _userDeviceKeys.remove(userId); } @@ -1018,22 +1014,22 @@ class Client { } void _handleToDeviceEvents(List events) { - for (int i = 0; i < events.length; i++) { - bool isValid = events[i] is Map && - events[i]["type"] is String && - events[i]["sender"] is String && - events[i]["content"] is Map; + for (var i = 0; i < events.length; i++) { + var isValid = events[i] is Map && + events[i]['type'] is String && + events[i]['sender'] is String && + events[i]['content'] is Map; if (!isValid) { - print("[Sync] Invalid To Device Event! ${events[i]}"); + print('[Sync] Invalid To Device Event! ${events[i]}'); continue; } - ToDeviceEvent toDeviceEvent = ToDeviceEvent.fromJson(events[i]); - if (toDeviceEvent.type == "m.room.encrypted") { + var toDeviceEvent = ToDeviceEvent.fromJson(events[i]); + if (toDeviceEvent.type == 'm.room.encrypted') { try { toDeviceEvent = decryptToDeviceEvent(toDeviceEvent); } catch (e) { print( - "[LibOlm] Could not decrypt to device event from ${toDeviceEvent.sender}: " + + '[LibOlm] Could not decrypt to device event from ${toDeviceEvent.sender}: ' + e.toString()); print(toDeviceEvent.sender); toDeviceEvent = ToDeviceEvent.fromJson(events[i]); @@ -1049,35 +1045,35 @@ class Client { // calculate the notification counts, the limitedTimeline and prevbatch num highlight_count = 0; num notification_count = 0; - String prev_batch = ""; - bool limitedTimeline = false; + var prev_batch = ''; + var limitedTimeline = false; - if (room["unread_notifications"] is Map) { - if (room["unread_notifications"]["highlight_count"] is num) { - highlight_count = room["unread_notifications"]["highlight_count"]; + if (room['unread_notifications'] is Map) { + if (room['unread_notifications']['highlight_count'] is num) { + highlight_count = room['unread_notifications']['highlight_count']; } - if (room["unread_notifications"]["notification_count"] is num) { + if (room['unread_notifications']['notification_count'] is num) { notification_count = - room["unread_notifications"]["notification_count"]; + room['unread_notifications']['notification_count']; } } - if (room["timeline"] is Map) { - if (room["timeline"]["limited"] is bool) { - limitedTimeline = room["timeline"]["limited"]; + if (room['timeline'] is Map) { + if (room['timeline']['limited'] is bool) { + limitedTimeline = room['timeline']['limited']; } - if (room["timeline"]["prev_batch"] is String) { - prev_batch = room["timeline"]["prev_batch"]; + if (room['timeline']['prev_batch'] is String) { + prev_batch = room['timeline']['prev_batch']; } } RoomSummary summary; - if (room["summary"] is Map) { - summary = RoomSummary.fromJson(room["summary"]); + if (room['summary'] is Map) { + summary = RoomSummary.fromJson(room['summary']); } - RoomUpdate update = RoomUpdate( + var update = RoomUpdate( id: id, membership: membership, notification_count: notification_count, @@ -1087,78 +1083,78 @@ class Client { summary: summary, ); _updateRoomsByRoomUpdate(update); - unawaited(this.store?.storeRoomUpdate(update)); + unawaited(store?.storeRoomUpdate(update)); onRoomUpdate.add(update); /// Handle now all room events and save them in the database - if (room["state"] is Map && - room["state"]["events"] is List) { - _handleRoomEvents(id, room["state"]["events"], "state"); + if (room['state'] is Map && + room['state']['events'] is List) { + _handleRoomEvents(id, room['state']['events'], 'state'); } - if (room["invite_state"] is Map && - room["invite_state"]["events"] is List) { - _handleRoomEvents(id, room["invite_state"]["events"], "invite_state"); + if (room['invite_state'] is Map && + room['invite_state']['events'] is List) { + _handleRoomEvents(id, room['invite_state']['events'], 'invite_state'); } - if (room["timeline"] is Map && - room["timeline"]["events"] is List) { - _handleRoomEvents(id, room["timeline"]["events"], "timeline"); + if (room['timeline'] is Map && + room['timeline']['events'] is List) { + _handleRoomEvents(id, room['timeline']['events'], 'timeline'); } - if (room["ephemeral"] is Map && - room["ephemeral"]["events"] is List) { - _handleEphemerals(id, room["ephemeral"]["events"]); + if (room['ephemeral'] is Map && + room['ephemeral']['events'] is List) { + _handleEphemerals(id, room['ephemeral']['events']); } - if (room["account_data"] is Map && - room["account_data"]["events"] is List) { - _handleRoomEvents(id, room["account_data"]["events"], "account_data"); + if (room['account_data'] is Map && + room['account_data']['events'] is List) { + _handleRoomEvents(id, room['account_data']['events'], 'account_data'); } }); } void _handleEphemerals(String id, List events) { for (num i = 0; i < events.length; i++) { - _handleEvent(events[i], id, "ephemeral"); + _handleEvent(events[i], id, 'ephemeral'); // Receipt events are deltas between two states. We will create a // fake room account data event for this and store the difference // there. - if (events[i]["type"] == "m.receipt") { - Room room = this.getRoomById(id); - if (room == null) room = Room(id: id); + if (events[i]['type'] == 'm.receipt') { + var room = getRoomById(id); + room ??= Room(id: id); - Map receiptStateContent = - room.roomAccountData["m.receipt"]?.content ?? {}; - for (var eventEntry in events[i]["content"].entries) { + var receiptStateContent = + room.roomAccountData['m.receipt']?.content ?? {}; + for (var eventEntry in events[i]['content'].entries) { final String eventID = eventEntry.key; - if (events[i]["content"][eventID]["m.read"] != null) { + if (events[i]['content'][eventID]['m.read'] != null) { final Map userTimestampMap = - events[i]["content"][eventID]["m.read"]; + events[i]['content'][eventID]['m.read']; for (var userTimestampMapEntry in userTimestampMap.entries) { - final String mxid = userTimestampMapEntry.key; + final mxid = userTimestampMapEntry.key; // Remove previous receipt event from this user for (var entry in receiptStateContent.entries) { - if (entry.value["m.read"] is Map && - entry.value["m.read"].containsKey(mxid)) { - entry.value["m.read"].remove(mxid); + if (entry.value['m.read'] is Map && + entry.value['m.read'].containsKey(mxid)) { + entry.value['m.read'].remove(mxid); break; } } if (userTimestampMap[mxid] is Map && - userTimestampMap[mxid].containsKey("ts")) { + userTimestampMap[mxid].containsKey('ts')) { receiptStateContent[mxid] = { - "event_id": eventID, - "ts": userTimestampMap[mxid]["ts"], + 'event_id': eventID, + 'ts': userTimestampMap[mxid]['ts'], }; } } } } - events[i]["content"] = receiptStateContent; - _handleEvent(events[i], id, "account_data"); + events[i]['content'] = receiptStateContent; + _handleEvent(events[i], id, 'account_data'); } } } @@ -1170,49 +1166,49 @@ class Client { } void _handleGlobalEvents(List events, String type) { - for (int i = 0; i < events.length; i++) { - if (events[i]["type"] is String && - events[i]["content"] is Map) { - UserUpdate update = UserUpdate( - eventType: events[i]["type"], + for (var i = 0; i < events.length; i++) { + if (events[i]['type'] is String && + events[i]['content'] is Map) { + var update = UserUpdate( + eventType: events[i]['type'], type: type, content: events[i], ); - this.store?.storeUserEventUpdate(update); + store?.storeUserEventUpdate(update); onUserEvent.add(update); } } } void _handleEvent(Map event, String roomID, String type) { - if (event["type"] is String && event["content"] is Map) { + if (event['type'] is String && event['content'] is Map) { // The client must ignore any new m.room.encryption event to prevent // man-in-the-middle attacks! - if (event["type"] == "m.room.encryption" && + if (event['type'] == 'm.room.encryption' && getRoomById(roomID).encrypted) { return; } - EventUpdate update = EventUpdate( - eventType: event["type"], + var update = EventUpdate( + eventType: event['type'], roomID: roomID, type: type, content: event, ); - if (event["type"] == "m.room.encrypted") { - update = update.decrypt(this.getRoomById(update.roomID)); + if (event['type'] == 'm.room.encrypted') { + update = update.decrypt(getRoomById(update.roomID)); } - this.store?.storeEventUpdate(update); + store?.storeEventUpdate(update); _updateRoomsByEventUpdate(update); onEvent.add(update); - if (event["type"] == "m.call.invite") { + if (event['type'] == 'm.call.invite') { onCallInvite.add(Event.fromJson(event, getRoomById(roomID))); - } else if (event["type"] == "m.call.hangup") { + } else if (event['type'] == 'm.call.hangup') { onCallHangup.add(Event.fromJson(event, getRoomById(roomID))); - } else if (event["type"] == "m.call.answer") { + } else if (event['type'] == 'm.call.answer') { onCallAnswer.add(Event.fromJson(event, getRoomById(roomID))); - } else if (event["type"] == "m.call.candidates") { + } else if (event['type'] == 'm.call.candidates') { onCallCandidates.add(Event.fromJson(event, getRoomById(roomID))); } } @@ -1225,14 +1221,14 @@ class Client { for (j = 0; j < rooms.length; j++) { if (rooms[j].id == chatUpdate.id) break; } - final bool found = (j < rooms.length && rooms[j].id == chatUpdate.id); - final bool isLeftRoom = chatUpdate.membership == Membership.leave; + final found = (j < rooms.length && rooms[j].id == chatUpdate.id); + final isLeftRoom = chatUpdate.membership == Membership.leave; // Does the chat already exist in the list rooms? if (!found && !isLeftRoom) { - num position = chatUpdate.membership == Membership.invite ? 0 : j; + var position = chatUpdate.membership == Membership.invite ? 0 : j; // Add the new chat to the list - Room newRoom = Room( + var newRoom = Room( id: chatUpdate.id, membership: chatUpdate.membership, prev_batch: chatUpdate.prev_batch, @@ -1281,20 +1277,20 @@ class Client { } void _updateRoomsByEventUpdate(EventUpdate eventUpdate) { - if (eventUpdate.type == "history") return; + if (eventUpdate.type == 'history') return; // Search the room in the rooms num j = 0; for (j = 0; j < rooms.length; j++) { if (rooms[j].id == eventUpdate.roomID) break; } - final bool found = (j < rooms.length && rooms[j].id == eventUpdate.roomID); + final found = (j < rooms.length && rooms[j].id == eventUpdate.roomID); if (!found) return; - if (eventUpdate.type == "timeline" || - eventUpdate.type == "state" || - eventUpdate.type == "invite_state") { - Event stateEvent = Event.fromJson(eventUpdate.content, rooms[j]); + if (eventUpdate.type == 'timeline' || + eventUpdate.type == 'state' || + eventUpdate.type == 'invite_state') { + var stateEvent = Event.fromJson(eventUpdate.content, rooms[j]); if (stateEvent.type == EventTypes.Redaction) { - final String redacts = eventUpdate.content["redacts"]; + final String redacts = eventUpdate.content['redacts']; rooms[j].states.states.forEach( (String key, Map states) => states.forEach( (String key, Event state) { @@ -1305,57 +1301,57 @@ class Client { ), ); } else { - Event prevState = + var prevState = rooms[j].getState(stateEvent.typeKey, stateEvent.stateKey); if (prevState != null && prevState.time.millisecondsSinceEpoch > stateEvent.time.millisecondsSinceEpoch) return; rooms[j].setState(stateEvent); } - } else if (eventUpdate.type == "account_data") { + } else if (eventUpdate.type == 'account_data') { rooms[j].roomAccountData[eventUpdate.eventType] = RoomAccountData.fromJson(eventUpdate.content, rooms[j]); - } else if (eventUpdate.type == "ephemeral") { + } else if (eventUpdate.type == 'ephemeral') { rooms[j].ephemerals[eventUpdate.eventType] = RoomAccountData.fromJson(eventUpdate.content, rooms[j]); } if (rooms[j].onUpdate != null) rooms[j].onUpdate.add(rooms[j].id); - if (eventUpdate.type == "timeline") _sortRooms(); + if (eventUpdate.type == 'timeline') _sortRooms(); } void _updateRoomsByToDeviceEvent(ToDeviceEvent toDeviceEvent) { try { switch (toDeviceEvent.type) { - case "m.room_key": - case "m.forwarded_room_key": - Room room = getRoomById(toDeviceEvent.content["room_id"]); + case 'm.room_key': + case 'm.forwarded_room_key': + var room = getRoomById(toDeviceEvent.content['room_id']); if (room != null) { - final String sessionId = toDeviceEvent.content["session_id"]; + final String sessionId = toDeviceEvent.content['session_id']; if (room != null) { - if (toDeviceEvent.type == "m.room_key" && + if (toDeviceEvent.type == 'm.room_key' && userDeviceKeys.containsKey(toDeviceEvent.sender) && userDeviceKeys[toDeviceEvent.sender].deviceKeys.containsKey( - toDeviceEvent.content["requesting_device_id"])) { - toDeviceEvent.content["sender_claimed_ed25519_key"] = + toDeviceEvent.content['requesting_device_id'])) { + toDeviceEvent.content['sender_claimed_ed25519_key'] = userDeviceKeys[toDeviceEvent.sender] .deviceKeys[ - toDeviceEvent.content["requesting_device_id"]] + toDeviceEvent.content['requesting_device_id']] .ed25519Key; } room.setSessionKey( sessionId, toDeviceEvent.content, - forwarded: toDeviceEvent.type == "m.forwarded_room_key", + forwarded: toDeviceEvent.type == 'm.forwarded_room_key', ); - if (toDeviceEvent.type == "m.forwarded_room_key") { + if (toDeviceEvent.type == 'm.forwarded_room_key') { sendToDevice( [], - "m.room_key_request", + 'm.room_key_request', { - "action": "request_cancellation", - "request_id": base64 - .encode(utf8.encode(toDeviceEvent.content["room_id"])), - "requesting_device_id": room.client.deviceID, + 'action': 'request_cancellation', + 'request_id': base64 + .encode(utf8.encode(toDeviceEvent.content['room_id'])), + 'requesting_device_id': room.client.deviceID, }, encrypted: false, ); @@ -1363,19 +1359,19 @@ class Client { } } break; - case "m.room_key_request": - if (!toDeviceEvent.content.containsKey("body")) break; - Room room = getRoomById(toDeviceEvent.content["body"]["room_id"]); + case 'm.room_key_request': + if (!toDeviceEvent.content.containsKey('body')) break; + var room = getRoomById(toDeviceEvent.content['body']['room_id']); DeviceKeys deviceKeys; - final String sessionId = toDeviceEvent.content["body"]["session_id"]; + final String sessionId = toDeviceEvent.content['body']['session_id']; if (userDeviceKeys.containsKey(toDeviceEvent.sender) && userDeviceKeys[toDeviceEvent.sender] .deviceKeys - .containsKey(toDeviceEvent.content["requesting_device_id"])) { + .containsKey(toDeviceEvent.content['requesting_device_id'])) { deviceKeys = userDeviceKeys[toDeviceEvent.sender] - .deviceKeys[toDeviceEvent.content["requesting_device_id"]]; + .deviceKeys[toDeviceEvent.content['requesting_device_id']]; if (room.sessionKeys.containsKey(sessionId)) { - final RoomKeyRequest roomKeyRequest = + final roomKeyRequest = RoomKeyRequest.fromToDeviceEvent(toDeviceEvent, this); if (deviceKeys.userId == userID && deviceKeys.verified && @@ -1389,7 +1385,7 @@ class Client { break; } } catch (e) { - print("[Matrix] Error while processing to-device-event: " + e.toString()); + print('[Matrix] Error while processing to-device-event: ' + e.toString()); } } @@ -1401,7 +1397,7 @@ class Client { RoomSorter sortRoomsBy = (a, b) => b.timeCreated.millisecondsSinceEpoch .compareTo(a.timeCreated.millisecondsSinceEpoch); - _sortRooms() { + void _sortRooms() { if (prevBatch == null || _sortLock || rooms.length < 2) return; _sortLock = true; rooms?.sort(sortRoomsBy); @@ -1411,9 +1407,9 @@ class Client { /// Gets an OpenID token object that the requester may supply to another service to verify their identity in Matrix. /// The generated token is only valid for exchanging for user information from the federation API for OpenID. Future requestOpenIdCredentials() async { - final Map response = await jsonRequest( + final response = await jsonRequest( type: HTTPType.POST, - action: "/client/r0/user/$userID/openid/request_token", + action: '/client/r0/user/$userID/openid/request_token', data: {}, ); return OpenIdCredentials.fromJson(response); @@ -1424,11 +1420,11 @@ class Client { Map _userDeviceKeys = {}; Future> _getUserIdsInEncryptedRooms() async { - Set userIds = {}; - for (int i = 0; i < rooms.length; i++) { + var userIds = {}; + for (var i = 0; i < rooms.length; i++) { if (rooms[i].encrypted) { - List userList = await rooms[i].requestParticipants(); - for (User user in userList) { + var userList = await rooms[i].requestParticipants(); + for (var user in userList) { if ([Membership.join, Membership.invite].contains(user.membership)) { userIds.add(user.id); } @@ -1440,21 +1436,21 @@ class Client { Future _updateUserDeviceKeys() async { try { - if (!this.isLogged()) return; - Set trackedUserIds = await _getUserIdsInEncryptedRooms(); - trackedUserIds.add(this.userID); + if (!isLogged()) return; + var trackedUserIds = await _getUserIdsInEncryptedRooms(); + trackedUserIds.add(userID); // Remove all userIds we no longer need to track the devices of. _userDeviceKeys .removeWhere((String userId, v) => !trackedUserIds.contains(userId)); // Check if there are outdated device key lists. Add it to the set. - Map outdatedLists = {}; - for (String userId in trackedUserIds) { + var outdatedLists = {}; + for (var userId in trackedUserIds) { if (!userDeviceKeys.containsKey(userId)) { _userDeviceKeys[userId] = DeviceKeysList(userId); } - DeviceKeysList deviceKeysList = userDeviceKeys[userId]; + var deviceKeysList = userDeviceKeys[userId]; if (deviceKeysList.outdated) { outdatedLists[userId] = []; } @@ -1462,14 +1458,14 @@ class Client { if (outdatedLists.isNotEmpty) { // Request the missing device key lists from the server. - final Map response = await this.jsonRequest( + final response = await jsonRequest( type: HTTPType.POST, - action: "/client/r0/keys/query", - data: {"timeout": 10000, "device_keys": outdatedLists}); + action: '/client/r0/keys/query', + data: {'timeout': 10000, 'device_keys': outdatedLists}); - for (final rawDeviceKeyListEntry in response["device_keys"].entries) { + for (final rawDeviceKeyListEntry in response['device_keys'].entries) { final String userId = rawDeviceKeyListEntry.key; - final Map oldKeys = + final oldKeys = Map.from(_userDeviceKeys[userId].deviceKeys); _userDeviceKeys[userId].deviceKeys = {}; for (final rawDeviceKeyEntry in rawDeviceKeyListEntry.value.entries) { @@ -1479,9 +1475,9 @@ class Client { if (!oldKeys.containsKey(deviceId)) { _userDeviceKeys[userId].deviceKeys[deviceId] = DeviceKeys.fromJson(rawDeviceKeyEntry.value); - if (deviceId == this.deviceID && + if (deviceId == deviceID && _userDeviceKeys[userId].deviceKeys[deviceId].ed25519Key == - this.fingerprintKey) { + fingerprintKey) { // Always trust the own device _userDeviceKeys[userId].deviceKeys[deviceId].verified = true; } @@ -1492,42 +1488,42 @@ class Client { _userDeviceKeys[userId].outdated = false; } } - await this.storeAPI?.storeUserDeviceKeys(userDeviceKeys); + await storeAPI?.storeUserDeviceKeys(userDeviceKeys); rooms.forEach((Room room) { if (room.encrypted) { room.clearOutboundGroupSession(); } }); } catch (e) { - print("[LibOlm] Unable to update user device keys: " + e.toString()); + print('[LibOlm] Unable to update user device keys: ' + e.toString()); } } String get fingerprintKey => encryptionEnabled - ? json.decode(_olmAccount.identity_keys())["ed25519"] + ? json.decode(_olmAccount.identity_keys())['ed25519'] : null; String get identityKey => encryptionEnabled - ? json.decode(_olmAccount.identity_keys())["curve25519"] + ? json.decode(_olmAccount.identity_keys())['curve25519'] : null; /// Adds a signature to this json from this olm account. Map signJson(Map payload) { - if (!encryptionEnabled) throw ("Encryption is disabled"); - final Map unsigned = payload["unsigned"]; - final Map signatures = payload["signatures"]; - payload.remove("unsigned"); - payload.remove("signatures"); - final List canonical = canonicalJson.encode(payload); - final String signature = _olmAccount.sign(String.fromCharCodes(canonical)); + if (!encryptionEnabled) throw ('Encryption is disabled'); + final Map unsigned = payload['unsigned']; + final Map signatures = payload['signatures']; + payload.remove('unsigned'); + payload.remove('signatures'); + final canonical = canonicalJson.encode(payload); + final signature = _olmAccount.sign(String.fromCharCodes(canonical)); if (signatures != null) { - payload["signatures"] = signatures; + payload['signatures'] = signatures; } else { - payload["signatures"] = Map(); + payload['signatures'] = {}; } - payload["signatures"][userID] = Map(); - payload["signatures"][userID]["ed25519:$deviceID"] = signature; + payload['signatures'][userID] = {}; + payload['signatures'][userID]['ed25519:$deviceID'] = signature; if (unsigned != null) { - payload["unsigned"] = unsigned; + payload['unsigned'] = unsigned; } return payload; } @@ -1535,23 +1531,23 @@ class Client { /// Checks the signature of a signed json object. bool checkJsonSignature(String key, Map signedJson, String userId, String deviceId) { - if (!encryptionEnabled) throw ("Encryption is disabled"); - final Map signatures = signedJson["signatures"]; + if (!encryptionEnabled) throw ('Encryption is disabled'); + final Map signatures = signedJson['signatures']; if (signatures == null || !signatures.containsKey(userId)) return false; - signedJson.remove("unsigned"); - signedJson.remove("signatures"); - if (!signatures[userId].containsKey("ed25519:$deviceId")) return false; - final String signature = signatures[userId]["ed25519:$deviceId"]; - final List canonical = canonicalJson.encode(signedJson); - final String message = String.fromCharCodes(canonical); - bool isValid = true; + signedJson.remove('unsigned'); + signedJson.remove('signatures'); + if (!signatures[userId].containsKey('ed25519:$deviceId')) return false; + final String signature = signatures[userId]['ed25519:$deviceId']; + final canonical = canonicalJson.encode(signedJson); + final message = String.fromCharCodes(canonical); + var isValid = true; try { olm.Utility() ..ed25519_verify(key, message, signature) ..free(); } catch (e) { isValid = false; - print("[LibOlm] Signature check failed: " + e.toString()); + print('[LibOlm] Signature check failed: ' + e.toString()); } return isValid; } @@ -1562,52 +1558,52 @@ class Client { Future _uploadKeys({bool uploadDeviceKeys = false}) async { if (!encryptionEnabled) return true; - final int oneTimeKeysCount = _olmAccount.max_number_of_one_time_keys(); + final oneTimeKeysCount = _olmAccount.max_number_of_one_time_keys(); _olmAccount.generate_one_time_keys(oneTimeKeysCount); final Map oneTimeKeys = json.decode(_olmAccount.one_time_keys()); - Map signedOneTimeKeys = Map(); + var signedOneTimeKeys = {}; - for (String key in oneTimeKeys["curve25519"].keys) { - signedOneTimeKeys["signed_curve25519:$key"] = Map(); - signedOneTimeKeys["signed_curve25519:$key"]["key"] = - oneTimeKeys["curve25519"][key]; - signedOneTimeKeys["signed_curve25519:$key"] = - signJson(signedOneTimeKeys["signed_curve25519:$key"]); + for (String key in oneTimeKeys['curve25519'].keys) { + signedOneTimeKeys['signed_curve25519:$key'] = {}; + signedOneTimeKeys['signed_curve25519:$key']['key'] = + oneTimeKeys['curve25519'][key]; + signedOneTimeKeys['signed_curve25519:$key'] = + signJson(signedOneTimeKeys['signed_curve25519:$key']); } - Map keysContent = { + var keysContent = { if (uploadDeviceKeys) - "device_keys": { - "user_id": userID, - "device_id": deviceID, - "algorithms": [ - "m.olm.v1.curve25519-aes-sha2", - "m.megolm.v1.aes-sha2" + 'device_keys': { + 'user_id': userID, + 'device_id': deviceID, + 'algorithms': [ + 'm.olm.v1.curve25519-aes-sha2', + 'm.megolm.v1.aes-sha2' ], - "keys": Map(), + 'keys': {}, }, - "one_time_keys": signedOneTimeKeys, + 'one_time_keys': signedOneTimeKeys, }; if (uploadDeviceKeys) { final Map keys = json.decode(_olmAccount.identity_keys()); - for (String algorithm in keys.keys) { - keysContent["device_keys"]["keys"]["$algorithm:$deviceID"] = + for (var algorithm in keys.keys) { + keysContent['device_keys']['keys']['$algorithm:$deviceID'] = keys[algorithm]; } - keysContent["device_keys"] = - signJson(keysContent["device_keys"] as Map); + keysContent['device_keys'] = + signJson(keysContent['device_keys'] as Map); } _olmAccount.mark_keys_as_published(); - final Map response = await jsonRequest( + final response = await jsonRequest( type: HTTPType.POST, - action: "/client/r0/keys/upload", + action: '/client/r0/keys/upload', data: keysContent, ); - if (response["one_time_key_counts"]["signed_curve25519"] != + if (response['one_time_key_counts']['signed_curve25519'] != oneTimeKeysCount) { return false; } @@ -1618,28 +1614,28 @@ class Client { /// Try to decrypt a ToDeviceEvent encrypted with olm. ToDeviceEvent decryptToDeviceEvent(ToDeviceEvent toDeviceEvent) { - if (toDeviceEvent.type != "m.room.encrypted") { + if (toDeviceEvent.type != 'm.room.encrypted') { print( - "[LibOlm] Warning! Tried to decrypt a not-encrypted to-device-event"); + '[LibOlm] Warning! Tried to decrypt a not-encrypted to-device-event'); return toDeviceEvent; } - if (toDeviceEvent.content["algorithm"] != "m.olm.v1.curve25519-aes-sha2") { - throw ("Unknown algorithm: ${toDeviceEvent.content}"); + if (toDeviceEvent.content['algorithm'] != 'm.olm.v1.curve25519-aes-sha2') { + throw ('Unknown algorithm: ${toDeviceEvent.content}'); } - if (!toDeviceEvent.content["ciphertext"].containsKey(identityKey)) { + if (!toDeviceEvent.content['ciphertext'].containsKey(identityKey)) { throw ("The message isn't sent for this device"); } String plaintext; - final String senderKey = toDeviceEvent.content["sender_key"]; + final String senderKey = toDeviceEvent.content['sender_key']; final String body = - toDeviceEvent.content["ciphertext"][identityKey]["body"]; - final int type = toDeviceEvent.content["ciphertext"][identityKey]["type"]; + toDeviceEvent.content['ciphertext'][identityKey]['body']; + final int type = toDeviceEvent.content['ciphertext'][identityKey]['type']; if (type != 0 && type != 1) { - throw ("Unknown message type"); + throw ('Unknown message type'); } - List existingSessions = olmSessions[senderKey]; + var existingSessions = olmSessions[senderKey]; if (existingSessions != null) { - for (olm.Session session in existingSessions) { + for (var session in existingSessions) { if (type == 0 && session.matches_inbound(body) == true) { plaintext = session.decrypt(type, body); storeOlmSession(senderKey, session); @@ -1656,11 +1652,11 @@ class Client { } } if (plaintext == null && type != 0) { - throw ("No existing sessions found"); + throw ('No existing sessions found'); } if (plaintext == null) { - olm.Session newSession = olm.Session(); + var newSession = olm.Session(); newSession.create_inbound_from(_olmAccount, senderKey, body); _olmAccount.remove_one_time_keys(newSession); storeAPI?.storeClient(); @@ -1668,29 +1664,29 @@ class Client { storeOlmSession(senderKey, newSession); } final Map plainContent = json.decode(plaintext); - if (plainContent.containsKey("sender") && - plainContent["sender"] != toDeviceEvent.sender) { + if (plainContent.containsKey('sender') && + plainContent['sender'] != toDeviceEvent.sender) { throw ("Message was decrypted but sender doesn't match"); } - if (plainContent.containsKey("recipient") && - plainContent["recipient"] != userID) { + if (plainContent.containsKey('recipient') && + plainContent['recipient'] != userID) { throw ("Message was decrypted but recipient doesn't match"); } - if (plainContent["recipient_keys"] is Map && - plainContent["recipient_keys"]["ed25519"] is String && - plainContent["recipient_keys"]["ed25519"] != fingerprintKey) { + if (plainContent['recipient_keys'] is Map && + plainContent['recipient_keys']['ed25519'] is String && + plainContent['recipient_keys']['ed25519'] != fingerprintKey) { throw ("Message was decrypted but own fingerprint Key doesn't match"); } return ToDeviceEvent( - content: plainContent["content"], - type: plainContent["type"], + content: plainContent['content'], + type: plainContent['type'], sender: toDeviceEvent.sender, ); } /// A map from Curve25519 identity keys to existing olm sessions. Map> get olmSessions => _olmSessions; - Map> _olmSessions = {}; + final Map> _olmSessions = {}; void storeOlmSession(String curve25519IdentityKey, olm.Session session) { if (!_olmSessions.containsKey(curve25519IdentityKey)) { @@ -1701,18 +1697,18 @@ class Client { -1) { _olmSessions[curve25519IdentityKey].add(session); } - Map> pickleMap = {}; + var pickleMap = >{}; for (var entry in olmSessions.entries) { pickleMap[entry.key] = []; - for (olm.Session session in entry.value) { + for (var session in entry.value) { try { pickleMap[entry.key].add(session.pickle(userID)); } catch (e) { - print("[LibOlm] Could not pickle olm session: " + e.toString()); + print('[LibOlm] Could not pickle olm session: ' + e.toString()); } } } - storeAPI?.setItem("/clients/$userID/olm-sessions", json.encode(pickleMap)); + storeAPI?.setItem('/clients/$userID/olm-sessions', json.encode(pickleMap)); } /// Sends an encrypted [message] of this [type] to these [deviceKeys]. To send @@ -1732,103 +1728,101 @@ class Client { if (deviceKeys.isEmpty) return; } - Map sendToDeviceMessage = message; + var sendToDeviceMessage = message; // Send with send-to-device messaging - Map data = { - "messages": Map(), + var data = { + 'messages': {}, }; if (deviceKeys.isEmpty) { if (toUsers == null) { - data["messages"][this.userID] = Map(); - data["messages"][this.userID]["*"] = sendToDeviceMessage; + data['messages'][userID] = {}; + data['messages'][userID]['*'] = sendToDeviceMessage; } else { - for (User user in toUsers) { - data["messages"][user.id] = Map(); - data["messages"][user.id]["*"] = sendToDeviceMessage; + for (var user in toUsers) { + data['messages'][user.id] = {}; + data['messages'][user.id]['*'] = sendToDeviceMessage; } } } else { if (encrypted) { // Create new sessions with devices if there is no existing session yet. - List deviceKeysWithoutSession = - List.from(deviceKeys); + var deviceKeysWithoutSession = List.from(deviceKeys); deviceKeysWithoutSession.removeWhere((DeviceKeys deviceKeys) => olmSessions.containsKey(deviceKeys.curve25519Key)); if (deviceKeysWithoutSession.isNotEmpty) { await startOutgoingOlmSessions(deviceKeysWithoutSession); } } - for (int i = 0; i < deviceKeys.length; i++) { - DeviceKeys device = deviceKeys[i]; - if (!data["messages"].containsKey(device.userId)) { - data["messages"][device.userId] = Map(); + for (var i = 0; i < deviceKeys.length; i++) { + var device = deviceKeys[i]; + if (!data['messages'].containsKey(device.userId)) { + data['messages'][device.userId] = {}; } if (encrypted) { - List existingSessions = - olmSessions[device.curve25519Key]; + var existingSessions = olmSessions[device.curve25519Key]; if (existingSessions == null || existingSessions.isEmpty) continue; existingSessions .sort((a, b) => a.session_id().compareTo(b.session_id())); - final Map payload = { - "type": type, - "content": message, - "sender": this.userID, - "keys": {"ed25519": fingerprintKey}, - "recipient": device.userId, - "recipient_keys": {"ed25519": device.ed25519Key}, + final payload = { + 'type': type, + 'content': message, + 'sender': userID, + 'keys': {'ed25519': fingerprintKey}, + 'recipient': device.userId, + 'recipient_keys': {'ed25519': device.ed25519Key}, }; - final olm.EncryptResult encryptResult = + final encryptResult = existingSessions.first.encrypt(json.encode(payload)); storeOlmSession(device.curve25519Key, existingSessions.first); sendToDeviceMessage = { - "algorithm": "m.olm.v1.curve25519-aes-sha2", - "sender_key": identityKey, - "ciphertext": Map(), + 'algorithm': 'm.olm.v1.curve25519-aes-sha2', + 'sender_key': identityKey, + 'ciphertext': {}, }; - sendToDeviceMessage["ciphertext"][device.curve25519Key] = { - "type": encryptResult.type, - "body": encryptResult.body, + sendToDeviceMessage['ciphertext'][device.curve25519Key] = { + 'type': encryptResult.type, + 'body': encryptResult.body, }; } - data["messages"][device.userId][device.deviceId] = sendToDeviceMessage; + data['messages'][device.userId][device.deviceId] = sendToDeviceMessage; } } - if (encrypted) type = "m.room.encrypted"; - final String messageID = "msg${DateTime.now().millisecondsSinceEpoch}"; + if (encrypted) type = 'm.room.encrypted'; + final messageID = 'msg${DateTime.now().millisecondsSinceEpoch}'; await jsonRequest( type: HTTPType.PUT, - action: "/client/r0/sendToDevice/$type/$messageID", + action: '/client/r0/sendToDevice/$type/$messageID', data: data, ); } Future startOutgoingOlmSessions(List deviceKeys, {bool checkSignature = true}) async { - Map> requestingKeysFrom = {}; - for (DeviceKeys device in deviceKeys) { + var requestingKeysFrom = >{}; + for (var device in deviceKeys) { if (requestingKeysFrom[device.userId] == null) { requestingKeysFrom[device.userId] = {}; } - requestingKeysFrom[device.userId][device.deviceId] = "signed_curve25519"; + requestingKeysFrom[device.userId][device.deviceId] = 'signed_curve25519'; } - final Map response = await jsonRequest( + final response = await jsonRequest( type: HTTPType.POST, - action: "/client/r0/keys/claim", - data: {"timeout": 10000, "one_time_keys": requestingKeysFrom}, + action: '/client/r0/keys/claim', + data: {'timeout': 10000, 'one_time_keys': requestingKeysFrom}, ); - for (var userKeysEntry in response["one_time_keys"].entries) { + for (var userKeysEntry in response['one_time_keys'].entries) { final String userId = userKeysEntry.key; for (var deviceKeysEntry in userKeysEntry.value.entries) { final String deviceId = deviceKeysEntry.key; - final String fingerprintKey = + final fingerprintKey = userDeviceKeys[userId].deviceKeys[deviceId].ed25519Key; - final String identityKey = + final identityKey = userDeviceKeys[userId].deviceKeys[deviceId].curve25519Key; for (Map deviceKey in deviceKeysEntry.value.values) { if (checkSignature && @@ -1837,11 +1831,11 @@ class Client { continue; } try { - olm.Session session = olm.Session(); - session.create_outbound(_olmAccount, identityKey, deviceKey["key"]); + var session = olm.Session(); + session.create_outbound(_olmAccount, identityKey, deviceKey['key']); await storeOlmSession(identityKey, session); } catch (e) { - print("[LibOlm] Could not create new outbound olm session: " + + print('[LibOlm] Could not create new outbound olm session: ' + e.toString()); } } @@ -1851,10 +1845,10 @@ class Client { /// Gets information about all devices for the current user. Future> requestUserDevices() async { - final Map response = - await jsonRequest(type: HTTPType.GET, action: "/client/r0/devices"); - List userDevices = []; - for (final rawDevice in response["devices"]) { + final response = + await jsonRequest(type: HTTPType.GET, action: '/client/r0/devices'); + var userDevices = []; + for (final rawDevice in response['devices']) { userDevices.add( UserDevice.fromJson(rawDevice, this), ); @@ -1864,8 +1858,8 @@ class Client { /// Gets information about all devices for the current user. Future requestUserDevice(String deviceId) async { - final Map response = await jsonRequest( - type: HTTPType.GET, action: "/client/r0/devices/$deviceId"); + final response = await jsonRequest( + type: HTTPType.GET, action: '/client/r0/devices/$deviceId'); return UserDevice.fromJson(response, this); } @@ -1874,10 +1868,10 @@ class Client { {Map auth}) async { await jsonRequest( type: HTTPType.POST, - action: "/client/r0/delete_devices", + action: '/client/r0/delete_devices', data: { - "devices": deviceIds, - if (auth != null) "auth": auth, + 'devices': deviceIds, + if (auth != null) 'auth': auth, }, ); return; @@ -1892,22 +1886,22 @@ class Client { bool includeAllNetworks, String thirdPartyInstanceId, }) async { - String action = "/client/r0/publicRooms"; + var action = '/client/r0/publicRooms'; if (server != null) { - action += "?server=$server"; + action += '?server=$server'; } - final Map response = await jsonRequest( + final response = await jsonRequest( type: HTTPType.POST, action: action, data: { - if (limit != null) "limit": 10, - if (since != null) "since": since, + if (limit != null) 'limit': 10, + if (since != null) 'since': since, if (genericSearchTerm != null) - "filter": {"generic_search_term": genericSearchTerm}, + 'filter': {'generic_search_term': genericSearchTerm}, if (includeAllNetworks != null) - "include_all_networks": includeAllNetworks, + 'include_all_networks': includeAllNetworks, if (thirdPartyInstanceId != null) - "third_party_instance_id": thirdPartyInstanceId, + 'third_party_instance_id': thirdPartyInstanceId, }, ); return PublicRoomsResponse.fromJson(response, this); @@ -1916,18 +1910,18 @@ class Client { /// Whether all push notifications are muted using the [.m.rule.master] /// rule of the push rules: https://matrix.org/docs/spec/client_server/r0.6.0#m-rule-master bool get allPushNotificationsMuted { - if (!this.accountData.containsKey("m.push_rules") || - !(this.accountData["m.push_rules"].content["global"] is Map)) { + if (!accountData.containsKey('m.push_rules') || + !(accountData['m.push_rules'].content['global'] is Map)) { return false; } final Map globalPushRules = - this.accountData["m.push_rules"].content["global"]; + accountData['m.push_rules'].content['global']; if (globalPushRules == null) return false; - if (globalPushRules["override"] is List) { - for (var i = 0; i < globalPushRules["override"].length; i++) { - if (globalPushRules["override"][i]["rule_id"] == ".m.rule.master") { - return globalPushRules["override"][i]["enabled"]; + if (globalPushRules['override'] is List) { + for (var i = 0; i < globalPushRules['override'].length; i++) { + if (globalPushRules['override'][i]['rule_id'] == '.m.rule.master') { + return globalPushRules['override'][i]['enabled']; } } } @@ -1937,8 +1931,8 @@ class Client { Future setMuteAllPushNotifications(bool muted) async { await jsonRequest( type: HTTPType.PUT, - action: "/client/r0/pushrules/global/override/.m.rule.master/enabled", - data: {"enabled": muted}, + action: '/client/r0/pushrules/global/override/.m.rule.master/enabled', + data: {'enabled': muted}, ); return; } diff --git a/lib/src/event.dart b/lib/src/event.dart index da07e45..c406039 100644 --- a/lib/src/event.dart +++ b/lib/src/event.dart @@ -47,7 +47,7 @@ class Event { /// The user who has sent this event if it is not a global account data event. final String senderId; - User get sender => room.getUserByMXIDSync(senderId ?? "@unknown"); + User get sender => room.getUserByMXIDSync(senderId ?? '@unknown'); /// The time this event has received at the server. May be null for events like /// account data. @@ -78,17 +78,17 @@ class Event { static const int defaultStatus = 2; static const Map STATUS_TYPE = { - "ERROR": -1, - "SENDING": 0, - "SENT": 1, - "TIMELINE": 2, - "ROOM_STATE": 3, + 'ERROR': -1, + 'SENDING': 0, + 'SENT': 1, + 'TIMELINE': 2, + 'ROOM_STATE': 3, }; /// Optional. The event that redacted this event, if any. Otherwise null. Event get redactedBecause => - unsigned != null && unsigned.containsKey("redacted_because") - ? Event.fromJson(unsigned["redacted_because"], room) + unsigned != null && unsigned.containsKey('redacted_because') + ? Event.fromJson(unsigned['redacted_because'], room) : null; bool get redacted => redactedBecause != null; @@ -122,12 +122,9 @@ class Event { /// Get a State event from a table row or from the event stream. factory Event.fromJson(Map jsonPayload, Room room) { - final Map content = - Event.getMapFromPayload(jsonPayload['content']); - final Map unsigned = - Event.getMapFromPayload(jsonPayload['unsigned']); - final Map prevContent = - Event.getMapFromPayload(jsonPayload['prev_content']); + final content = Event.getMapFromPayload(jsonPayload['content']); + final unsigned = Event.getMapFromPayload(jsonPayload['unsigned']); + final prevContent = Event.getMapFromPayload(jsonPayload['prev_content']); return Event( status: jsonPayload['status'] ?? defaultStatus, stateKey: jsonPayload['state_key'], @@ -146,19 +143,19 @@ class Event { } Map toJson() { - final Map data = Map(); - if (this.stateKey != null) data['state_key'] = this.stateKey; - if (this.prevContent != null && this.prevContent.isNotEmpty) { - data['prev_content'] = this.prevContent; + final data = {}; + if (stateKey != null) data['state_key'] = stateKey; + if (prevContent != null && prevContent.isNotEmpty) { + data['prev_content'] = prevContent; } - data['content'] = this.content; - data['type'] = this.typeKey; - data['event_id'] = this.eventId; - data['room_id'] = this.roomId; - data['sender'] = this.senderId; - data['origin_server_ts'] = this.time.millisecondsSinceEpoch; - if (this.unsigned != null && this.unsigned.isNotEmpty) { - data['unsigned'] = this.unsigned; + data['content'] = content; + data['type'] = typeKey; + data['event_id'] = eventId; + data['room_id'] = roomId; + data['sender'] = senderId; + data['origin_server_ts'] = time.millisecondsSinceEpoch; + if (unsigned != null && unsigned.isNotEmpty) { + data['unsigned'] = unsigned; } return data; } @@ -183,45 +180,45 @@ class Event { /// Get the real type. EventTypes get type { switch (typeKey) { - case "m.room.avatar": + case 'm.room.avatar': return EventTypes.RoomAvatar; - case "m.room.name": + case 'm.room.name': return EventTypes.RoomName; - case "m.room.topic": + case 'm.room.topic': return EventTypes.RoomTopic; - case "m.room.aliases": + case 'm.room.aliases': return EventTypes.RoomAliases; - case "m.room.canonical_alias": + case 'm.room.canonical_alias': return EventTypes.RoomCanonicalAlias; - case "m.room.create": + case 'm.room.create': return EventTypes.RoomCreate; - case "m.room.redaction": + case 'm.room.redaction': return EventTypes.Redaction; - case "m.room.join_rules": + case 'm.room.join_rules': return EventTypes.RoomJoinRules; - case "m.room.member": + case 'm.room.member': return EventTypes.RoomMember; - case "m.room.power_levels": + case 'm.room.power_levels': return EventTypes.RoomPowerLevels; - case "m.room.guest_access": + case 'm.room.guest_access': return EventTypes.GuestAccess; - case "m.room.history_visibility": + case 'm.room.history_visibility': return EventTypes.HistoryVisibility; - case "m.sticker": + case 'm.sticker': return EventTypes.Sticker; - case "m.room.message": + case 'm.room.message': return EventTypes.Message; - case "m.room.encrypted": + case 'm.room.encrypted': return EventTypes.Encrypted; - case "m.room.encryption": + case 'm.room.encryption': return EventTypes.Encryption; - case "m.call.invite": + case 'm.call.invite': return EventTypes.CallInvite; - case "m.call.answer": + case 'm.call.answer': return EventTypes.CallAnswer; - case "m.call.candidates": + case 'm.call.candidates': return EventTypes.CallCandidates; - case "m.call.hangup": + case 'm.call.hangup': return EventTypes.CallHangup; } return EventTypes.Unknown; @@ -229,29 +226,29 @@ class Event { /// MessageTypes get messageType { - switch (content["msgtype"] ?? "m.text") { - case "m.text": - if (content.containsKey("m.relates_to")) { + switch (content['msgtype'] ?? 'm.text') { + case 'm.text': + if (content.containsKey('m.relates_to')) { return MessageTypes.Reply; } return MessageTypes.Text; - case "m.notice": + case 'm.notice': return MessageTypes.Notice; - case "m.emote": + case 'm.emote': return MessageTypes.Emote; - case "m.image": + case 'm.image': return MessageTypes.Image; - case "m.video": + case 'm.video': return MessageTypes.Video; - case "m.audio": + case 'm.audio': return MessageTypes.Audio; - case "m.file": + case 'm.file': return MessageTypes.File; - case "m.sticker": + case 'm.sticker': return MessageTypes.Sticker; - case "m.location": + case 'm.location': return MessageTypes.Location; - case "m.bad.encrypted": + case 'm.bad.encrypted': return MessageTypes.BadEncrypted; default: if (type == EventTypes.Message) { @@ -263,40 +260,40 @@ class Event { void setRedactionEvent(Event redactedBecause) { unsigned = { - "redacted_because": redactedBecause.toJson(), + 'redacted_because': redactedBecause.toJson(), }; prevContent = null; - List contentKeyWhiteList = []; + var contentKeyWhiteList = []; switch (type) { case EventTypes.RoomMember: - contentKeyWhiteList.add("membership"); + contentKeyWhiteList.add('membership'); break; case EventTypes.RoomCreate: - contentKeyWhiteList.add("creator"); + contentKeyWhiteList.add('creator'); break; case EventTypes.RoomJoinRules: - contentKeyWhiteList.add("join_rule"); + contentKeyWhiteList.add('join_rule'); break; case EventTypes.RoomPowerLevels: - contentKeyWhiteList.add("ban"); - contentKeyWhiteList.add("events"); - contentKeyWhiteList.add("events_default"); - contentKeyWhiteList.add("kick"); - contentKeyWhiteList.add("redact"); - contentKeyWhiteList.add("state_default"); - contentKeyWhiteList.add("users"); - contentKeyWhiteList.add("users_default"); + contentKeyWhiteList.add('ban'); + contentKeyWhiteList.add('events'); + contentKeyWhiteList.add('events_default'); + contentKeyWhiteList.add('kick'); + contentKeyWhiteList.add('redact'); + contentKeyWhiteList.add('state_default'); + contentKeyWhiteList.add('users'); + contentKeyWhiteList.add('users_default'); break; case EventTypes.RoomAliases: - contentKeyWhiteList.add("aliases"); + contentKeyWhiteList.add('aliases'); break; case EventTypes.HistoryVisibility: - contentKeyWhiteList.add("history_visibility"); + contentKeyWhiteList.add('history_visibility'); break; default: break; } - List toRemoveList = []; + var toRemoveList = []; for (var entry in content.entries) { if (!contentKeyWhiteList.contains(entry.key)) { toRemoveList.add(entry.key); @@ -306,30 +303,30 @@ class Event { } /// Returns the body of this event if it has a body. - String get text => content["body"] ?? ""; + String get text => content['body'] ?? ''; /// Returns the formatted boy of this event if it has a formatted body. - String get formattedText => content["formatted_body"] ?? ""; + String get formattedText => content['formatted_body'] ?? ''; - @Deprecated("Use [body] instead.") + @Deprecated('Use [body] instead.') String getBody() => body; /// Use this to get the body. String get body { - if (redacted) return "Redacted"; - if (text != "") return text; - if (formattedText != "") return formattedText; - return "$type"; + if (redacted) return 'Redacted'; + if (text != '') return text; + if (formattedText != '') return formattedText; + return '$type'; } /// Returns a list of [Receipt] instances for this event. List get receipts { - if (!(room.roomAccountData.containsKey("m.receipt"))) return []; - List receiptsList = []; - for (var entry in room.roomAccountData["m.receipt"].content.entries) { - if (entry.value["event_id"] == eventId) { + if (!(room.roomAccountData.containsKey('m.receipt'))) return []; + var receiptsList = []; + for (var entry in room.roomAccountData['m.receipt'].content.entries) { + if (entry.value['event_id'] == eventId) { receiptsList.add(Receipt(room.getUserByMXIDSync(entry.key), - DateTime.fromMillisecondsSinceEpoch(entry.value["ts"]))); + DateTime.fromMillisecondsSinceEpoch(entry.value['ts']))); } } return receiptsList; @@ -345,12 +342,12 @@ class Event { room.client.onEvent.add(EventUpdate( roomID: room.id, - type: "timeline", + type: 'timeline', eventType: typeKey, content: { - "event_id": eventId, - "status": -2, - "content": {"body": "Removed..."} + 'event_id': eventId, + 'status': -2, + 'content': {'body': 'Removed...'} })); return true; } @@ -361,7 +358,7 @@ class Event { Future sendAgain({String txid}) async { if (status != -1) return null; await remove(); - final String eventID = await room.sendTextEvent(text, txid: txid); + final eventID = await room.sendTextEvent(text, txid: txid); return eventID; } @@ -397,34 +394,34 @@ class Event { /// in the room. If the event is not encrypted or the decryption failed because /// of a different error, this throws an exception. Future requestKey() async { - if (this.type != EventTypes.Encrypted || - this.messageType != MessageTypes.BadEncrypted || - this.content["body"] != DecryptError.UNKNOWN_SESSION) { - throw ("Session key not unknown"); + if (type != EventTypes.Encrypted || + messageType != MessageTypes.BadEncrypted || + content['body'] != DecryptError.UNKNOWN_SESSION) { + throw ('Session key not unknown'); } - final List users = await room.requestParticipants(); + final users = await room.requestParticipants(); await room.client.sendToDevice( [], - "m.room_key_request", + 'm.room_key_request', { - "action": "request_cancellation", - "request_id": base64.encode(utf8.encode(content["session_id"])), - "requesting_device_id": room.client.deviceID, + 'action': 'request_cancellation', + 'request_id': base64.encode(utf8.encode(content['session_id'])), + 'requesting_device_id': room.client.deviceID, }, toUsers: users); await room.client.sendToDevice( [], - "m.room_key_request", + 'm.room_key_request', { - "action": "request", - "body": { - "algorithm": "m.megolm.v1.aes-sha2", - "room_id": roomId, - "sender_key": content["sender_key"], - "session_id": content["session_id"], + 'action': 'request', + 'body': { + 'algorithm': 'm.megolm.v1.aes-sha2', + 'room_id': roomId, + 'sender_key': content['sender_key'], + 'session_id': content['session_id'], }, - "request_id": base64.encode(utf8.encode(content["session_id"])), - "requesting_device_id": room.client.deviceID, + 'request_id': base64.encode(utf8.encode(content['session_id'])), + 'requesting_device_id': room.client.deviceID, }, encrypted: false, toUsers: users); @@ -435,27 +432,27 @@ class Event { /// event and returns it as a [MatrixFile]. If this event doesn't /// contain an attachment, this throws an error. Future downloadAndDecryptAttachment() async { - if (![EventTypes.Message, EventTypes.Sticker].contains(this.type)) { + if (![EventTypes.Message, EventTypes.Sticker].contains(type)) { throw ("This event has the type '$typeKey' and so it can't contain an attachment."); } - if (!content.containsKey("url") && !content.containsKey("file")) { + if (!content.containsKey('url') && !content.containsKey('file')) { throw ("This event hasn't any attachment."); } - final bool isEncrypted = !content.containsKey("url"); + final isEncrypted = !content.containsKey('url'); if (isEncrypted && !room.client.encryptionEnabled) { - throw ("Encryption is not enabled in your Client."); + throw ('Encryption is not enabled in your Client.'); } - MxContent mxContent = - MxContent(isEncrypted ? content["file"]["url"] : content["url"]); + var mxContent = + MxContent(isEncrypted ? content['file']['url'] : content['url']); Uint8List uint8list; // Is this file storeable? - final bool storeable = room.client.storeAPI.extended && - content["info"] is Map && - content["info"]["size"] is int && - content["info"]["size"] <= ExtendedStoreAPI.MAX_FILE_SIZE; + final storeable = room.client.storeAPI.extended && + content['info'] is Map && + content['info']['size'] is int && + content['info']['size'] <= ExtendedStoreAPI.MAX_FILE_SIZE; if (storeable) { uint8list = await room.client.store.getFile(mxContent.mxc); @@ -470,18 +467,18 @@ class Event { // Decrypt the file if (isEncrypted) { - if (!content.containsKey("file") || - !content["file"]["key"]["key_ops"].contains("decrypt")) { + if (!content.containsKey('file') || + !content['file']['key']['key_ops'].contains('decrypt')) { throw ("Missing 'decrypt' in 'key_ops'."); } - final EncryptedFile encryptedFile = EncryptedFile(); + final encryptedFile = EncryptedFile(); encryptedFile.data = uint8list; - encryptedFile.iv = content["file"]["iv"]; - encryptedFile.k = content["file"]["key"]["k"]; - encryptedFile.sha256 = content["file"]["hashes"]["sha256"]; + encryptedFile.iv = content['file']['iv']; + encryptedFile.k = content['file']['key']['k']; + encryptedFile.sha256 = content['file']['hashes']['sha256']; uint8list = await decryptFile(encryptedFile); } - return MatrixFile(bytes: uint8list, path: "/$body"); + return MatrixFile(bytes: uint8list, path: '/$body'); } } diff --git a/lib/src/presence.dart b/lib/src/presence.dart index 062b1c6..bf5a95d 100644 --- a/lib/src/presence.dart +++ b/lib/src/presence.dart @@ -44,7 +44,7 @@ class Presence { Presence.fromJson(Map json) : sender = json['sender'], displayname = json['content']['displayname'], - avatarUrl = MxContent(json['content']['avatar_url'] ?? ""), + avatarUrl = MxContent(json['content']['avatar_url'] ?? ''), currentlyActive = json['content']['currently_active'], lastActiveAgo = json['content']['last_active_ago'], time = DateTime.fromMillisecondsSinceEpoch( diff --git a/lib/src/room.dart b/lib/src/room.dart index 46513d2..ee665d4 100644 --- a/lib/src/room.dart +++ b/lib/src/room.dart @@ -94,10 +94,10 @@ class Room { /// to-device-messaging. Future createOutboundGroupSession() async { await clearOutboundGroupSession(wipe: true); - List deviceKeys = await getUserDeviceKeys(); + var deviceKeys = await getUserDeviceKeys(); olm.OutboundGroupSession outboundGroupSession; - List outboundGroupSessionDevices = []; - for (DeviceKeys keys in deviceKeys) { + var outboundGroupSessionDevices = []; + for (var keys in deviceKeys) { if (!keys.blocked) outboundGroupSessionDevices.add(keys.deviceId); } outboundGroupSessionDevices.sort(); @@ -106,29 +106,29 @@ class Room { outboundGroupSession.create(); } catch (e) { outboundGroupSession = null; - print("[LibOlm] Unable to create new outboundGroupSession: " + + print('[LibOlm] Unable to create new outboundGroupSession: ' + e.toString()); } if (outboundGroupSession == null) return; // Add as an inboundSession to the [sessionKeys]. - Map rawSession = { - "algorithm": "m.megolm.v1.aes-sha2", - "room_id": this.id, - "session_id": outboundGroupSession.session_id(), - "session_key": outboundGroupSession.session_key(), + var rawSession = { + 'algorithm': 'm.megolm.v1.aes-sha2', + 'room_id': id, + 'session_id': outboundGroupSession.session_id(), + 'session_key': outboundGroupSession.session_key(), }; - setSessionKey(rawSession["session_id"], rawSession); + setSessionKey(rawSession['session_id'], rawSession); try { - await client.sendToDevice(deviceKeys, "m.room_key", rawSession); + await client.sendToDevice(deviceKeys, 'm.room_key', rawSession); _outboundGroupSession = outboundGroupSession; _outboundGroupSessionDevices = outboundGroupSessionDevices; await _storeOutboundGroupSession(); } catch (e) { print( - "[LibOlm] Unable to send the session key to the participating devices: " + + '[LibOlm] Unable to send the session key to the participating devices: ' + e.toString()); - await this.clearOutboundGroupSession(); + await clearOutboundGroupSession(); } return; } @@ -136,10 +136,10 @@ class Room { Future _storeOutboundGroupSession() async { if (_outboundGroupSession == null) return; await client.storeAPI?.setItem( - "/clients/${client.deviceID}/rooms/${this.id}/outbound_group_session", + '/clients/${client.deviceID}/rooms/${id}/outbound_group_session', _outboundGroupSession.pickle(client.userID)); await client.storeAPI?.setItem( - "/clients/${client.deviceID}/rooms/${this.id}/outbound_group_session_devices", + '/clients/${client.deviceID}/rooms/${id}/outbound_group_session_devices', json.encode(_outboundGroupSessionDevices)); return; } @@ -148,27 +148,26 @@ class Room { /// devices have been changed. Returns false if the session has not been cleared because /// it wasn't necessary. Future clearOutboundGroupSession({bool wipe = false}) async { - if (!wipe && this._outboundGroupSessionDevices != null) { - List deviceKeys = await getUserDeviceKeys(); - List outboundGroupSessionDevices = []; - for (DeviceKeys keys in deviceKeys) { + if (!wipe && _outboundGroupSessionDevices != null) { + var deviceKeys = await getUserDeviceKeys(); + var outboundGroupSessionDevices = []; + for (var keys in deviceKeys) { if (!keys.blocked) outboundGroupSessionDevices.add(keys.deviceId); } outboundGroupSessionDevices.sort(); if (outboundGroupSessionDevices.toString() == - this._outboundGroupSessionDevices.toString()) { + _outboundGroupSessionDevices.toString()) { return false; } } - this._outboundGroupSessionDevices == null; + _outboundGroupSessionDevices == null; await client.storeAPI?.setItem( - "/clients/${client.deviceID}/rooms/${this.id}/outbound_group_session", - null); + '/clients/${client.deviceID}/rooms/${id}/outbound_group_session', null); await client.storeAPI?.setItem( - "/clients/${client.deviceID}/rooms/${this.id}/outbound_group_session_devices", + '/clients/${client.deviceID}/rooms/${id}/outbound_group_session_devices', null); - this._outboundGroupSession?.free(); - this._outboundGroupSession = null; + _outboundGroupSession?.free(); + _outboundGroupSession = null; return true; } @@ -188,17 +187,17 @@ class Room { {bool forwarded = false}) { if (sessionKeys.containsKey(sessionId)) return; olm.InboundGroupSession inboundGroupSession; - if (content["algorithm"] == "m.megolm.v1.aes-sha2") { + if (content['algorithm'] == 'm.megolm.v1.aes-sha2') { try { inboundGroupSession = olm.InboundGroupSession(); if (forwarded) { - inboundGroupSession.import_session(content["session_key"]); + inboundGroupSession.import_session(content['session_key']); } else { - inboundGroupSession.create(content["session_key"]); + inboundGroupSession.create(content['session_key']); } } catch (e) { inboundGroupSession = null; - print("[LibOlm] Could not create new InboundGroupSession: " + + print('[LibOlm] Could not create new InboundGroupSession: ' + e.toString()); } } @@ -210,7 +209,7 @@ class Room { ); if (_fullyRestored) { client.storeAPI?.setItem( - "/clients/${client.deviceID}/rooms/${this.id}/session_keys", + '/clients/${client.deviceID}/rooms/${id}/session_keys', json.encode(sessionKeys)); } _tryAgainDecryptLastMessage(); @@ -218,8 +217,8 @@ class Room { } void _tryAgainDecryptLastMessage() { - if (getState("m.room.encrypted") != null) { - final Event decrypted = getState("m.room.encrypted").decrypted; + if (getState('m.room.encrypted') != null) { + final decrypted = getState('m.room.encrypted').decrypted; if (decrypted.type != EventTypes.Encrypted) { setState(decrypted); } @@ -228,7 +227,7 @@ class Room { /// Returns the [Event] for the given [typeKey] and optional [stateKey]. /// If no [stateKey] is provided, it defaults to an empty string. - Event getState(String typeKey, [String stateKey = ""]) => + Event getState(String typeKey, [String stateKey = '']) => states.states[typeKey] != null ? states.states[typeKey][stateKey] : null; /// Adds the [state] to this room and overwrites a state with the same @@ -239,15 +238,15 @@ class Room { try { state = decryptGroupMessage(state); } catch (e) { - print("[LibOlm] Could not decrypt room state: " + e.toString()); + print('[LibOlm] Could not decrypt room state: ' + e.toString()); } } // Check if this is a member change and we need to clear the outboundGroupSession. if (encrypted && outboundGroupSession != null && state.type == EventTypes.RoomMember) { - User newUser = state.asUser; - User oldUser = getState("m.room.member", newUser.id)?.asUser; + var newUser = state.asUser; + var oldUser = getState('m.room.member', newUser.id)?.asUser; if (oldUser == null || oldUser.membership != newUser.membership) { clearOutboundGroupSession(); } @@ -259,13 +258,13 @@ class Room { if (!states.states.containsKey(state.typeKey)) { states.states[state.typeKey] = {}; } - states.states[state.typeKey][state.stateKey ?? ""] = state; + states.states[state.typeKey][state.stateKey ?? ''] = state; } /// ID of the fully read marker event. - String get fullyRead => roomAccountData["m.fully_read"] != null - ? roomAccountData["m.fully_read"].content["event_id"] - : ""; + String get fullyRead => roomAccountData['m.fully_read'] != null + ? roomAccountData['m.fully_read'].content['event_id'] + : ''; /// If something changes, this callback will be triggered. Will return the /// room id. @@ -277,34 +276,34 @@ class Room { StreamController.broadcast(); /// The name of the room if set by a participant. - String get name => states["m.room.name"] != null - ? states["m.room.name"].content["name"] - : ""; + String get name => states['m.room.name'] != null + ? states['m.room.name'].content['name'] + : ''; /// The topic of the room if set by a participant. - String get topic => states["m.room.topic"] != null - ? states["m.room.topic"].content["topic"] - : ""; + String get topic => states['m.room.topic'] != null + ? states['m.room.topic'].content['topic'] + : ''; /// The avatar of the room if set by a participant. MxContent get avatar { - if (states["m.room.avatar"] != null) { - return MxContent(states["m.room.avatar"].content["url"]); + if (states['m.room.avatar'] != null) { + return MxContent(states['m.room.avatar'].content['url']); } if (mHeroes != null && mHeroes.length == 1 && states[mHeroes[0]] != null) { return states[mHeroes[0]].asUser.avatarUrl; } if (membership == Membership.invite && - getState("m.room.member", client.userID) != null) { - return getState("m.room.member", client.userID).sender.avatarUrl; + getState('m.room.member', client.userID) != null) { + return getState('m.room.member', client.userID).sender.avatarUrl; } - return MxContent(""); + return MxContent(''); } /// The address in the format: #roomname:homeserver.org. - String get canonicalAlias => states["m.room.canonical_alias"] != null - ? states["m.room.canonical_alias"].content["alias"] - : ""; + String get canonicalAlias => states['m.room.canonical_alias'] != null + ? states['m.room.canonical_alias'].content['alias'] + : ''; /// If this room is a direct chat, this is the matrix ID of the user. /// Returns null otherwise. @@ -313,8 +312,8 @@ class Room { if (client.directChats is Map) { client.directChats.forEach((String userId, dynamic roomIds) { if (roomIds is List) { - for (int i = 0; i < roomIds.length; i++) { - if (roomIds[i] == this.id) { + for (var i = 0; i < roomIds.length; i++) { + if (roomIds[i] == id) { returnUserId = userId; break; } @@ -332,12 +331,12 @@ class Room { String notificationSettings; Event get lastEvent { - DateTime lastTime = DateTime.fromMillisecondsSinceEpoch(0); - Event lastEvent = getState("m.room.message"); + var lastTime = DateTime.fromMillisecondsSinceEpoch(0); + var lastEvent = getState('m.room.message'); if (lastEvent == null) { states.forEach((final String key, final entry) { - if (!entry.containsKey("")) return; - final Event state = entry[""]; + if (!entry.containsKey('')) return; + final Event state = entry['']; if (state.time != null && state.time.millisecondsSinceEpoch > lastTime.millisecondsSinceEpoch) { @@ -351,10 +350,10 @@ class Room { /// Returns a list of all current typing users. List get typingUsers { - if (!ephemerals.containsKey("m.typing")) return []; - List typingMxid = ephemerals["m.typing"].content["user_ids"]; - List typingUsers = []; - for (int i = 0; i < typingMxid.length; i++) { + if (!ephemerals.containsKey('m.typing')) return []; + List typingMxid = ephemerals['m.typing'].content['user_ids']; + var typingUsers = []; + for (var i = 0; i < typingMxid.length; i++) { typingUsers.add(getUserByMXIDSync(typingMxid[i])); } return typingUsers; @@ -368,7 +367,7 @@ class Room { this.membership = Membership.join, this.notificationCount = 0, this.highlightCount = 0, - this.prev_batch = "", + this.prev_batch = '', this.client, this.notificationSettings, this.mHeroes = const [], @@ -390,14 +389,14 @@ class Room { canonicalAlias.length > 3) { return canonicalAlias.localpart; } - List heroes = []; + var heroes = []; if (mHeroes != null && mHeroes.isNotEmpty && mHeroes.any((h) => h.isNotEmpty)) { heroes = mHeroes; } else { - if (states["m.room.member"] is Map) { - for (var entry in states["m.room.member"].entries) { + if (states['m.room.member'] is Map) { + for (var entry in states['m.room.member'].entries) { Event state = entry.value; if (state.type == EventTypes.RoomMember && state.stateKey != client?.userID) heroes.add(state.stateKey); @@ -405,18 +404,18 @@ class Room { } } if (heroes.isNotEmpty) { - String displayname = ""; - for (int i = 0; i < heroes.length; i++) { + var displayname = ''; + for (var i = 0; i < heroes.length; i++) { if (heroes[i].isEmpty) continue; - displayname += getUserByMXIDSync(heroes[i]).calcDisplayname() + ", "; + displayname += getUserByMXIDSync(heroes[i]).calcDisplayname() + ', '; } return displayname.substring(0, displayname.length - 2); } if (membership == Membership.invite && - getState("m.room.member", client.userID) != null) { - return getState("m.room.member", client.userID).sender.calcDisplayname(); + getState('m.room.member', client.userID) != null) { + return getState('m.room.member', client.userID).sender.calcDisplayname(); } - return "Empty chat"; + return 'Empty chat'; } /// The last message sent to this room. @@ -424,7 +423,7 @@ class Room { if (lastEvent != null) { return lastEvent.body; } else { - return ""; + return ''; } } @@ -439,31 +438,31 @@ class Room { /// Call the Matrix API to change the name of this room. Returns the event ID of the /// new m.room.name event. Future setName(String newName) async { - final Map resp = await client.jsonRequest( + final resp = await client.jsonRequest( type: HTTPType.PUT, - action: "/client/r0/rooms/${id}/state/m.room.name", - data: {"name": newName}); - return resp["event_id"]; + action: '/client/r0/rooms/${id}/state/m.room.name', + data: {'name': newName}); + return resp['event_id']; } /// Call the Matrix API to change the topic of this room. Future setDescription(String newName) async { - final Map resp = await client.jsonRequest( + final resp = await client.jsonRequest( type: HTTPType.PUT, - action: "/client/r0/rooms/${id}/state/m.room.topic", - data: {"topic": newName}); - return resp["event_id"]; + action: '/client/r0/rooms/${id}/state/m.room.topic', + data: {'topic': newName}); + return resp['event_id']; } /// Sends a normal text message to this room. Returns the event ID generated /// by the server for this message. Future sendTextEvent(String message, {String txid, Event inReplyTo}) { - String type = "m.text"; - if (message.startsWith("/me ")) { - type = "m.emote"; + var type = 'm.text'; + if (message.startsWith('/me ')) { + type = 'm.emote'; message = message.substring(4); } - return sendEvent({"msgtype": type, "body": message}, + return sendEvent({'msgtype': type, 'body': message}, txid: txid, inReplyTo: inReplyTo); } @@ -471,48 +470,47 @@ class Room { /// and will be detected by the mimetype of the file. Returns the mxc uri of /// the uploaded file. Future sendFileEvent(MatrixFile file, - {String msgType = "m.file", + {String msgType = 'm.file', String txid, Event inReplyTo, Map info}) async { - String fileName = file.path.split("/").last; - final bool sendEncrypted = this.encrypted && client.fileEncryptionEnabled; + var fileName = file.path.split('/').last; + final sendEncrypted = encrypted && client.fileEncryptionEnabled; EncryptedFile encryptedFile; if (sendEncrypted) { encryptedFile = await file.encrypt(); } - final String uploadResp = await client.upload( + final uploadResp = await client.upload( file, - contentType: sendEncrypted ? "application/octet-stream" : null, + contentType: sendEncrypted ? 'application/octet-stream' : null, ); // Send event - Map content = { - "msgtype": msgType, - "body": fileName, - "filename": fileName, - if (!sendEncrypted) "url": uploadResp, + var content = { + 'msgtype': msgType, + 'body': fileName, + 'filename': fileName, + if (!sendEncrypted) 'url': uploadResp, if (sendEncrypted) - "file": { - "url": uploadResp, - "mimetype": mime(file.path), - "v": "v2", - "key": { - "alg": "A256CTR", - "ext": true, - "k": encryptedFile.k, - "key_ops": ["encrypt", "decrypt"], - "kty": "oct" + 'file': { + 'url': uploadResp, + 'mimetype': mime(file.path), + 'v': 'v2', + 'key': { + 'alg': 'A256CTR', + 'ext': true, + 'k': encryptedFile.k, + 'key_ops': ['encrypt', 'decrypt'], + 'kty': 'oct' }, - "iv": encryptedFile.iv, - "hashes": {"sha256": encryptedFile.sha256} + 'iv': encryptedFile.iv, + 'hashes': {'sha256': encryptedFile.sha256} }, - "info": info != null - ? info - : { - "mimetype": mime(file.path), - "size": file.size, - } + 'info': info ?? + { + 'mimetype': mime(file.path), + 'size': file.size, + } }; unawaited(sendEvent(content, txid: txid, inReplyTo: inReplyTo)); return uploadResp; @@ -522,21 +520,21 @@ class Room { Future sendAudioEvent(MatrixFile file, {String txid, Event inReplyTo}) async { return await sendFileEvent(file, - msgType: "m.audio", txid: txid, inReplyTo: inReplyTo); + msgType: 'm.audio', txid: txid, inReplyTo: inReplyTo); } /// Sends an image to this room and returns the mxc uri. Future sendImageEvent(MatrixFile file, {String txid, int width, int height, Event inReplyTo}) async { return await sendFileEvent(file, - msgType: "m.image", + msgType: 'm.image', txid: txid, inReplyTo: inReplyTo, info: { - "size": file.size, - "mimetype": mime(file.path.split("/").last), - "w": width, - "h": height, + 'size': file.size, + 'mimetype': mime(file.path.split('/').last), + 'w': width, + 'h': height, }); } @@ -550,39 +548,39 @@ class Room { int thumbnailWidth, int thumbnailHeight, Event inReplyTo}) async { - String fileName = file.path.split("/").last; - Map info = { - "size": file.size, - "mimetype": mime(fileName), + var fileName = file.path.split('/').last; + var info = { + 'size': file.size, + 'mimetype': mime(fileName), }; if (videoWidth != null) { - info["w"] = videoWidth; + info['w'] = videoWidth; } if (thumbnailHeight != null) { - info["h"] = thumbnailHeight; + info['h'] = thumbnailHeight; } if (duration != null) { - info["duration"] = duration; + info['duration'] = duration; } - if (thumbnail != null && !(this.encrypted && client.encryptionEnabled)) { - String thumbnailName = file.path.split("/").last; - final String thumbnailUploadResp = await client.upload(thumbnail); - info["thumbnail_url"] = thumbnailUploadResp; - info["thumbnail_info"] = { - "size": thumbnail.size, - "mimetype": mime(thumbnailName), + if (thumbnail != null && !(encrypted && client.encryptionEnabled)) { + var thumbnailName = file.path.split('/').last; + final thumbnailUploadResp = await client.upload(thumbnail); + info['thumbnail_url'] = thumbnailUploadResp; + info['thumbnail_info'] = { + 'size': thumbnail.size, + 'mimetype': mime(thumbnailName), }; if (thumbnailWidth != null) { - info["thumbnail_info"]["w"] = thumbnailWidth; + info['thumbnail_info']['w'] = thumbnailWidth; } if (thumbnailHeight != null) { - info["thumbnail_info"]["h"] = thumbnailHeight; + info['thumbnail_info']['h'] = thumbnailHeight; } } return await sendFileEvent( file, - msgType: "m.video", + msgType: 'm.video', txid: txid, inReplyTo: inReplyTo, info: info, @@ -593,47 +591,46 @@ class Room { /// event ID generated from the server. Future sendEvent(Map content, {String txid, Event inReplyTo}) async { - final String type = "m.room.message"; - final String sendType = (this.encrypted && client.encryptionEnabled) - ? "m.room.encrypted" - : type; + final type = 'm.room.message'; + final sendType = + (encrypted && client.encryptionEnabled) ? 'm.room.encrypted' : type; // Create new transaction id String messageID; - final int now = DateTime.now().millisecondsSinceEpoch; + final now = DateTime.now().millisecondsSinceEpoch; if (txid == null) { - messageID = "msg$now"; + messageID = 'msg$now'; } else { messageID = txid; } if (inReplyTo != null) { - String replyText = "<${inReplyTo.senderId}> " + inReplyTo.body; - List replyTextLines = replyText.split("\n"); - for (int i = 0; i < replyTextLines.length; i++) { - replyTextLines[i] = "> " + replyTextLines[i]; + var replyText = '<${inReplyTo.senderId}> ' + inReplyTo.body; + var replyTextLines = replyText.split('\n'); + for (var i = 0; i < replyTextLines.length; i++) { + replyTextLines[i] = '> ' + replyTextLines[i]; } - replyText = replyTextLines.join("\n"); - content["format"] = "org.matrix.custom.html"; - content["formatted_body"] = + replyText = replyTextLines.join('\n'); + content['format'] = 'org.matrix.custom.html'; + content['formatted_body'] = '
In reply to ${inReplyTo.senderId}
${inReplyTo.body}
${content["formatted_body"] ?? content["body"]}'; - content["body"] = replyText + "\n\n${content["body"] ?? ""}"; - content["m.relates_to"] = { - "m.in_reply_to": { - "event_id": inReplyTo.eventId, + content['body'] = replyText + "\n\n${content["body"] ?? ""}"; + content['m.relates_to'] = { + 'm.in_reply_to': { + 'event_id': inReplyTo.eventId, }, }; } // Display a *sending* event and store it. - EventUpdate eventUpdate = - EventUpdate(type: "timeline", roomID: id, eventType: type, content: { - "type": type, - "event_id": messageID, - "sender": client.userID, - "status": 0, - "origin_server_ts": now, - "content": content + var eventUpdate = + EventUpdate(type: 'timeline', roomID: id, eventType: type, content: { + 'type': type, + 'event_id': messageID, + 'sender': client.userID, + 'status': 0, + 'origin_server_ts': now, + 'content': content }); client.onEvent.add(eventUpdate); await client.store?.transaction(() { @@ -643,16 +640,16 @@ class Room { // Send the text and on success, store and display a *sent* event. try { - final Map response = await client.jsonRequest( + final response = await client.jsonRequest( type: HTTPType.PUT, - action: "/client/r0/rooms/${id}/send/$sendType/$messageID", + action: '/client/r0/rooms/${id}/send/$sendType/$messageID', data: client.encryptionEnabled ? await encryptGroupMessagePayload(content) : content); - final String res = response["event_id"]; - eventUpdate.content["status"] = 1; - eventUpdate.content["unsigned"] = {"transaction_id": messageID}; - eventUpdate.content["event_id"] = res; + final String res = response['event_id']; + eventUpdate.content['status'] = 1; + eventUpdate.content['unsigned'] = {'transaction_id': messageID}; + eventUpdate.content['event_id'] = res; client.onEvent.add(eventUpdate); await client.store?.transaction(() { client.store.storeEventUpdate(eventUpdate); @@ -660,10 +657,10 @@ class Room { }); return res; } catch (exception) { - print("[Client] Error while sending: " + exception.toString()); + print('[Client] Error while sending: ' + exception.toString()); // On error, set status to -1 - eventUpdate.content["status"] = -1; - eventUpdate.content["unsigned"] = {"transaction_id": messageID}; + eventUpdate.content['status'] = -1; + eventUpdate.content['unsigned'] = {'transaction_id': messageID}; client.onEvent.add(eventUpdate); await client.store?.transaction(() { client.store.storeEventUpdate(eventUpdate); @@ -679,15 +676,15 @@ class Room { Future join() async { try { await client.jsonRequest( - type: HTTPType.POST, action: "/client/r0/rooms/${id}/join"); - final Event invitation = getState("m.room.member", client.userID); + type: HTTPType.POST, action: '/client/r0/rooms/${id}/join'); + final invitation = getState('m.room.member', client.userID); if (invitation != null && - invitation.content["is_direct"] is bool && - invitation.content["is_direct"]) { + invitation.content['is_direct'] is bool && + invitation.content['is_direct']) { await addToDirectChat(invitation.sender.id); } } on MatrixException catch (exception) { - if (exception.errorMessage == "No known servers") { + if (exception.errorMessage == 'No known servers') { await client.store?.forgetRoom(id); client.onRoomUpdate.add( RoomUpdate( @@ -704,9 +701,9 @@ class Room { /// Call the Matrix API to leave this room. If this room is set as a direct /// chat, this will be removed too. Future leave() async { - if (directChatMatrixID != "") await removeFromDirectChat(); + if (directChatMatrixID != '') await removeFromDirectChat(); await client.jsonRequest( - type: HTTPType.POST, action: "/client/r0/rooms/${id}/leave"); + type: HTTPType.POST, action: '/client/r0/rooms/${id}/leave'); return; } @@ -714,7 +711,7 @@ class Room { Future forget() async { await client.store?.forgetRoom(id); await client.jsonRequest( - type: HTTPType.POST, action: "/client/r0/rooms/${id}/forget"); + type: HTTPType.POST, action: '/client/r0/rooms/${id}/forget'); return; } @@ -722,8 +719,8 @@ class Room { Future kick(String userID) async { await client.jsonRequest( type: HTTPType.POST, - action: "/client/r0/rooms/${id}/kick", - data: {"user_id": userID}); + action: '/client/r0/rooms/${id}/kick', + data: {'user_id': userID}); return; } @@ -731,8 +728,8 @@ class Room { Future ban(String userID) async { await client.jsonRequest( type: HTTPType.POST, - action: "/client/r0/rooms/${id}/ban", - data: {"user_id": userID}); + action: '/client/r0/rooms/${id}/ban', + data: {'user_id': userID}); return; } @@ -740,8 +737,8 @@ class Room { Future unban(String userID) async { await client.jsonRequest( type: HTTPType.POST, - action: "/client/r0/rooms/${id}/unban", - data: {"user_id": userID}); + action: '/client/r0/rooms/${id}/unban', + data: {'user_id': userID}); return; } @@ -749,25 +746,24 @@ class Room { /// 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 { - if (states["m.room.power_levels"] == null) return null; - Map powerMap = {} - ..addAll(states["m.room.power_levels"].content); - if (powerMap["users"] == null) powerMap["users"] = {}; - powerMap["users"][userID] = power; + if (states['m.room.power_levels'] == null) return null; + var powerMap = {}..addAll(states['m.room.power_levels'].content); + if (powerMap['users'] == null) powerMap['users'] = {}; + powerMap['users'][userID] = power; - final Map resp = await client.jsonRequest( + final resp = await client.jsonRequest( type: HTTPType.PUT, - action: "/client/r0/rooms/$id/state/m.room.power_levels", + action: '/client/r0/rooms/$id/state/m.room.power_levels', data: powerMap); - return resp["event_id"]; + return resp['event_id']; } /// Call the Matrix API to invite a user to this room. Future invite(String userID) async { await client.jsonRequest( type: HTTPType.POST, - action: "/client/r0/rooms/${id}/invite", - data: {"user_id": userID}); + action: '/client/r0/rooms/${id}/invite', + data: {'user_id': userID}); return; } @@ -779,24 +775,24 @@ class Room { final dynamic resp = await client.jsonRequest( type: HTTPType.GET, action: - "/client/r0/rooms/$id/messages?from=${prev_batch}&dir=b&limit=$historyCount&filter=${Client.syncFilters}"); + '/client/r0/rooms/$id/messages?from=${prev_batch}&dir=b&limit=$historyCount&filter=${Client.syncFilters}'); if (onHistoryReceived != null) onHistoryReceived(); - prev_batch = resp["end"]; + prev_batch = resp['end']; await client.store?.storeRoomPrevBatch(this); - if (!(resp["chunk"] is List && - resp["chunk"].length > 0 && - resp["end"] is String)) return; + if (!(resp['chunk'] is List && + resp['chunk'].length > 0 && + resp['end'] is String)) return; - if (resp["state"] is List) { + if (resp['state'] is List) { await client.store?.transaction(() { - for (int i = 0; i < resp["state"].length; i++) { - EventUpdate eventUpdate = EventUpdate( - type: "state", + for (var i = 0; i < resp['state'].length; i++) { + var eventUpdate = EventUpdate( + type: 'state', roomID: id, - eventType: resp["state"][i]["type"], - content: resp["state"][i], + eventType: resp['state'][i]['type'], + content: resp['state'][i], ).decrypt(this); client.onEvent.add(eventUpdate); client.store.storeEventUpdate(eventUpdate); @@ -804,39 +800,39 @@ class Room { return; }); if (client.store == null) { - for (int i = 0; i < resp["state"].length; i++) { - EventUpdate eventUpdate = EventUpdate( - type: "state", + for (var i = 0; i < resp['state'].length; i++) { + var eventUpdate = EventUpdate( + type: 'state', roomID: id, - eventType: resp["state"][i]["type"], - content: resp["state"][i], + eventType: resp['state'][i]['type'], + content: resp['state'][i], ).decrypt(this); client.onEvent.add(eventUpdate); } } } - List history = resp["chunk"]; + List history = resp['chunk']; await client.store?.transaction(() { - for (int i = 0; i < history.length; i++) { - EventUpdate eventUpdate = EventUpdate( - type: "history", + for (var i = 0; i < history.length; i++) { + var eventUpdate = EventUpdate( + type: 'history', roomID: id, - eventType: history[i]["type"], + eventType: history[i]['type'], content: history[i], ).decrypt(this); client.onEvent.add(eventUpdate); client.store.storeEventUpdate(eventUpdate); - client.store.setRoomPrevBatch(id, resp["end"]); + client.store.setRoomPrevBatch(id, resp['end']); } return; }); if (client.store == null) { - for (int i = 0; i < history.length; i++) { - EventUpdate eventUpdate = EventUpdate( - type: "history", + for (var i = 0; i < history.length; i++) { + var eventUpdate = EventUpdate( + type: 'history', roomID: id, - eventType: history[i]["type"], + eventType: history[i]['type'], content: history[i], ).decrypt(this); client.onEvent.add(eventUpdate); @@ -846,7 +842,7 @@ class Room { RoomUpdate( id: id, membership: membership, - prev_batch: resp["end"], + prev_batch: resp['end'], notification_count: notificationCount, highlight_count: highlightCount, ), @@ -855,7 +851,7 @@ class Room { /// Sets this room as a direct chat for this user if not already. Future addToDirectChat(String userID) async { - Map directChats = client.directChats; + var directChats = client.directChats; if (directChats.containsKey(userID)) { if (!directChats[userID].contains(id)) { directChats[userID].add(id); @@ -868,14 +864,14 @@ class Room { await client.jsonRequest( type: HTTPType.PUT, - action: "/client/r0/user/${client.userID}/account_data/m.direct", + action: '/client/r0/user/${client.userID}/account_data/m.direct', data: directChats); return; } /// Removes this room from all direct chat tags. Future removeFromDirectChat() async { - Map directChats = client.directChats; + var directChats = client.directChats; if (directChats.containsKey(directChatMatrixID) && directChats[directChatMatrixID].contains(id)) { directChats[directChatMatrixID].remove(id); @@ -885,21 +881,21 @@ class Room { await client.jsonRequest( type: HTTPType.PUT, - action: "/client/r0/user/${client.userID}/account_data/m.direct", + action: '/client/r0/user/${client.userID}/account_data/m.direct', data: directChats); return; } /// Sends *m.fully_read* and *m.read* for the given event ID. Future sendReadReceipt(String eventID) async { - this.notificationCount = 0; - await client?.store?.resetNotificationCount(this.id); + notificationCount = 0; + await client?.store?.resetNotificationCount(id); await client.jsonRequest( type: HTTPType.POST, - action: "/client/r0/rooms/$id/read_markers", + action: '/client/r0/rooms/$id/read_markers', data: { - "m.fully_read": eventID, - "m.read": eventID, + 'm.fully_read': eventID, + 'm.read': eventID, }); return; } @@ -908,44 +904,43 @@ class Room { // Restore the inbound and outbound session keys if (client.encryptionEnabled && client.storeAPI != null) { final String outboundGroupSessionPickle = await client.storeAPI.getItem( - "/clients/${client.deviceID}/rooms/${this.id}/outbound_group_session"); + '/clients/${client.deviceID}/rooms/${id}/outbound_group_session'); if (outboundGroupSessionPickle != null) { try { - this._outboundGroupSession = olm.OutboundGroupSession(); - this - ._outboundGroupSession - .unpickle(client.userID, outboundGroupSessionPickle); + _outboundGroupSession = olm.OutboundGroupSession(); + _outboundGroupSession.unpickle( + client.userID, outboundGroupSessionPickle); } catch (e) { - this._outboundGroupSession = null; - print("[LibOlm] Unable to unpickle outboundGroupSession: " + + _outboundGroupSession = null; + print('[LibOlm] Unable to unpickle outboundGroupSession: ' + e.toString()); } } final String outboundGroupSessionDevicesString = await client.storeAPI .getItem( - "/clients/${client.deviceID}/rooms/${this.id}/outbound_group_session_devices"); + '/clients/${client.deviceID}/rooms/${id}/outbound_group_session_devices'); if (outboundGroupSessionDevicesString != null) { - this._outboundGroupSessionDevices = + _outboundGroupSessionDevices = List.from(json.decode(outboundGroupSessionDevicesString)); } final String sessionKeysPickle = await client.storeAPI - .getItem("/clients/${client.deviceID}/rooms/${this.id}/session_keys"); + .getItem('/clients/${client.deviceID}/rooms/${id}/session_keys'); if (sessionKeysPickle?.isNotEmpty ?? false) { final Map map = json.decode(sessionKeysPickle); - if (this._sessionKeys == null) this._sessionKeys = {}; + _sessionKeys ??= {}; for (var entry in map.entries) { try { - this._sessionKeys[entry.key] = + _sessionKeys[entry.key] = SessionKey.fromJson(entry.value, client.userID); } catch (e) { - print("[LibOlm] Could not unpickle inboundGroupSession: " + + print('[LibOlm] Could not unpickle inboundGroupSession: ' + e.toString()); } } } } await client.storeAPI?.setItem( - "/clients/${client.deviceID}/rooms/${this.id}/session_keys", + '/clients/${client.deviceID}/rooms/${id}/session_keys', json.encode(sessionKeys)); _tryAgainDecryptLastMessage(); _fullyRestored = true; @@ -959,17 +954,17 @@ class Room { Map row, Client matrix, {Future>> states, Future>> roomAccountData}) async { - Room newRoom = Room( - id: row["room_id"], + var newRoom = Room( + id: row['room_id'], membership: Membership.values - .firstWhere((e) => e.toString() == 'Membership.' + row["membership"]), - notificationCount: row["notification_count"], - highlightCount: row["highlight_count"], - notificationSettings: row["notification_settings"], - prev_batch: row["prev_batch"], - mInvitedMemberCount: row["invited_member_count"], - mJoinedMemberCount: row["joined_member_count"], - mHeroes: row["heroes"]?.split(",") ?? [], + .firstWhere((e) => e.toString() == 'Membership.' + row['membership']), + notificationCount: row['notification_count'], + highlightCount: row['highlight_count'], + notificationSettings: row['notification_settings'], + prev_batch: row['prev_batch'], + mInvitedMemberCount: row['invited_member_count'], + mJoinedMemberCount: row['joined_member_count'], + mHeroes: row['heroes']?.split(',') ?? [], client: matrix, roomAccountData: {}, ); @@ -978,19 +973,18 @@ class Room { await newRoom.restoreGroupSessionKeys(); if (states != null) { - List> rawStates = await states; - for (int i = 0; i < rawStates.length; i++) { - Event newState = Event.fromJson(rawStates[i], newRoom); + var rawStates = await states; + for (var i = 0; i < rawStates.length; i++) { + var newState = Event.fromJson(rawStates[i], newRoom); newRoom.setState(newState); } } - Map newRoomAccountData = {}; + var newRoomAccountData = {}; if (roomAccountData != null) { - List> rawRoomAccountData = await roomAccountData; - for (int i = 0; i < rawRoomAccountData.length; i++) { - RoomAccountData newData = - RoomAccountData.fromJson(rawRoomAccountData[i], newRoom); + var rawRoomAccountData = await roomAccountData; + for (var i = 0; i < rawRoomAccountData.length; i++) { + var newData = RoomAccountData.fromJson(rawRoomAccountData[i], newRoom); newRoomAccountData[newData.typeKey] = newData; } newRoom.roomAccountData = newRoomAccountData; @@ -1003,15 +997,16 @@ class Room { Future getTimeline( {onTimelineUpdateCallback onUpdate, onTimelineInsertCallback onInsert}) async { - List events = - client.store != null ? await client.store.getEventList(this) : []; + var events = client.store != null + ? await client.store.getEventList(this) + : []; // Try again to decrypt encrypted events and update the database. - if (this.encrypted && client.store != null) { + if (encrypted && client.store != null) { await client.store.transaction(() { - for (int i = 0; i < events.length; i++) { + for (var i = 0; i < events.length; i++) { if (events[i].type == EventTypes.Encrypted && - events[i].content["body"] == DecryptError.UNKNOWN_SESSION) { + events[i].content['body'] == DecryptError.UNKNOWN_SESSION) { events[i] = events[i].decrypted; if (events[i].type != EventTypes.Encrypted) { client.store.storeEventUpdate( @@ -1019,7 +1014,7 @@ class Room { eventType: events[i].typeKey, content: events[i].toJson(), roomID: events[i].roomId, - type: "timeline", + type: 'timeline', ), ); } @@ -1028,14 +1023,14 @@ class Room { }); } - Timeline timeline = Timeline( + var timeline = Timeline( room: this, events: events, onUpdate: onUpdate, onInsert: onInsert, ); if (client.store == null) { - prev_batch = ""; + prev_batch = ''; await requestHistory(historyCount: 10); } return timeline; @@ -1045,9 +1040,9 @@ class Room { /// list may not be complete. User [requestParticipants] in this /// case. List getParticipants() { - List userList = []; - if (states["m.room.member"] is Map) { - for (var entry in states["m.room.member"].entries) { + var userList = []; + if (states['m.room.member'] is Map) { + for (var entry in states['m.room.member'].entries) { Event state = entry.value; if (state.type == EventTypes.RoomMember) userList.add(state.asUser); } @@ -1059,13 +1054,13 @@ class Room { /// from the store is not complete if the client uses lazy loading. Future> requestParticipants() async { if (participantListComplete) return getParticipants(); - List participants = []; + var participants = []; dynamic res = await client.jsonRequest( - type: HTTPType.GET, action: "/client/r0/rooms/${id}/members"); + type: HTTPType.GET, action: '/client/r0/rooms/${id}/members'); - for (num i = 0; i < res["chunk"].length; i++) { - User newUser = Event.fromJson(res["chunk"][i], this).asUser; + for (num i = 0; i < res['chunk'].length; i++) { + var newUser = Event.fromJson(res['chunk'][i], this).asUser; if (![Membership.leave, Membership.ban].contains(newUser.membership)) { participants.add(newUser); setState(newUser); @@ -1077,11 +1072,11 @@ class Room { /// Checks if the local participant list of joined and invited users is complete. bool get participantListComplete { - List knownParticipants = getParticipants(); + var knownParticipants = getParticipants(); knownParticipants.removeWhere( (u) => ![Membership.join, Membership.invite].contains(u.membership)); return knownParticipants.length == - (this.mJoinedMemberCount ?? 0) + (this.mInvitedMemberCount ?? 0); + (mJoinedMemberCount ?? 0) + (mInvitedMemberCount ?? 0); } /// Returns the [User] object for the given [mxID] or requests it from @@ -1102,7 +1097,7 @@ class Room { } } - Set _requestingMatrixIds = Set(); + final Set _requestingMatrixIds = {}; /// Requests a missing [User] for this room. Important for clients using /// lazy loading. @@ -1112,14 +1107,14 @@ class Room { try { resp = await client.jsonRequest( type: HTTPType.GET, - action: "/client/r0/rooms/$id/state/m.room.member/$mxID"); + action: '/client/r0/rooms/$id/state/m.room.member/$mxID'); } catch (exception) { _requestingMatrixIds.remove(mxID); if (!ignoreErrors) rethrow; } - final User user = User(mxID, - displayName: resp["displayname"], - avatarUrl: resp["avatar_url"], + final user = User(mxID, + displayName: resp['displayname'], + avatarUrl: resp['avatar_url'], room: this); states[mxID] = user; if (client.store != null) { @@ -1128,8 +1123,8 @@ class Room { EventUpdate( content: resp, roomID: id, - type: "state", - eventType: "m.room.member"), + type: 'state', + eventType: 'm.room.member'), ); return; }); @@ -1142,21 +1137,21 @@ class Room { /// Searches for the event on the server. Returns null if not found. Future getEventById(String eventID) async { final dynamic resp = await client.jsonRequest( - type: HTTPType.GET, action: "/client/r0/rooms/$id/event/$eventID"); + type: HTTPType.GET, action: '/client/r0/rooms/$id/event/$eventID'); return Event.fromJson(resp, this); } /// Returns the power level of the given user ID. int getPowerLevelByUserId(String userId) { - int powerLevel = 0; - Event powerLevelState = states["m.room.power_levels"]; + var powerLevel = 0; + Event powerLevelState = states['m.room.power_levels']; if (powerLevelState == null) return powerLevel; - if (powerLevelState.content["users_default"] is int) { - powerLevel = powerLevelState.content["users_default"]; + if (powerLevelState.content['users_default'] is int) { + powerLevel = powerLevelState.content['users_default']; } - if (powerLevelState.content["users"] is Map && - powerLevelState.content["users"][userId] != null) { - powerLevel = powerLevelState.content["users"][userId]; + if (powerLevelState.content['users'] is Map && + powerLevelState.content['users'][userId] != null) { + powerLevel = powerLevelState.content['users'][userId]; } return powerLevel; } @@ -1166,9 +1161,9 @@ class Room { /// Returns the power levels from all users for this room or null if not given. Map get powerLevels { - Event powerLevelState = states["m.room.power_levels"]; - if (powerLevelState.content["users"] is Map) { - return powerLevelState.content["users"]; + Event powerLevelState = states['m.room.power_levels']; + if (powerLevelState.content['users'] is Map) { + return powerLevelState.content['users']; } return null; } @@ -1176,68 +1171,68 @@ class Room { /// Uploads a new user avatar for this room. Returns the event ID of the new /// m.room.avatar event. Future setAvatar(MatrixFile file) async { - final String uploadResp = await client.upload(file); - final Map setAvatarResp = await client.jsonRequest( + final uploadResp = await client.upload(file); + final setAvatarResp = await client.jsonRequest( type: HTTPType.PUT, - action: "/client/r0/rooms/$id/state/m.room.avatar/", - data: {"url": uploadResp}); - return setAvatarResp["event_id"]; + action: '/client/r0/rooms/$id/state/m.room.avatar/', + data: {'url': uploadResp}); + return setAvatarResp['event_id']; } bool _hasPermissionFor(String action) { - if (getState("m.room.power_levels") == null || - getState("m.room.power_levels").content[action] == null) return true; - return ownPowerLevel >= getState("m.room.power_levels").content[action]; + if (getState('m.room.power_levels') == null || + getState('m.room.power_levels').content[action] == null) return true; + return ownPowerLevel >= getState('m.room.power_levels').content[action]; } /// The level required to ban a user. - bool get canBan => _hasPermissionFor("ban"); + bool get canBan => _hasPermissionFor('ban'); /// The default level required to send message events. Can be overridden by the events key. - bool get canSendDefaultMessages => _hasPermissionFor("events_default"); + bool get canSendDefaultMessages => _hasPermissionFor('events_default'); /// The level required to invite a user. - bool get canInvite => _hasPermissionFor("invite"); + bool get canInvite => _hasPermissionFor('invite'); /// The level required to kick a user. - bool get canKick => _hasPermissionFor("kick"); + bool get canKick => _hasPermissionFor('kick'); /// The level required to redact an event. - bool get canRedact => _hasPermissionFor("redact"); + bool get canRedact => _hasPermissionFor('redact'); /// The default level required to send state events. Can be overridden by the events key. - bool get canSendDefaultStates => _hasPermissionFor("state_default"); + bool get canSendDefaultStates => _hasPermissionFor('state_default'); - bool get canChangePowerLevel => canSendEvent("m.room.power_levels"); + bool get canChangePowerLevel => canSendEvent('m.room.power_levels'); bool canSendEvent(String eventType) { - if (getState("m.room.power_levels") == null) return true; - if (getState("m.room.power_levels").content["events"] == null || - getState("m.room.power_levels").content["events"][eventType] == null) { - return eventType == "m.room.message" + if (getState('m.room.power_levels') == null) return true; + if (getState('m.room.power_levels').content['events'] == null || + getState('m.room.power_levels').content['events'][eventType] == null) { + return eventType == 'm.room.message' ? canSendDefaultMessages : canSendDefaultStates; } return ownPowerLevel >= - getState("m.room.power_levels").content["events"][eventType]; + getState('m.room.power_levels').content['events'][eventType]; } /// Returns the [PushRuleState] for this room, based on the m.push_rules stored in /// the account_data. PushRuleState get pushRuleState { - if (!client.accountData.containsKey("m.push_rules") || - !(client.accountData["m.push_rules"].content["global"] is Map)) { + if (!client.accountData.containsKey('m.push_rules') || + !(client.accountData['m.push_rules'].content['global'] is Map)) { return PushRuleState.notify; } final Map globalPushRules = - client.accountData["m.push_rules"].content["global"]; + client.accountData['m.push_rules'].content['global']; if (globalPushRules == null) return PushRuleState.notify; - if (globalPushRules["override"] is List) { - for (var i = 0; i < globalPushRules["override"].length; i++) { - if (globalPushRules["override"][i]["rule_id"] == id) { - if (globalPushRules["override"][i]["actions"] - .indexOf("dont_notify") != + if (globalPushRules['override'] is List) { + for (var i = 0; i < globalPushRules['override'].length; i++) { + if (globalPushRules['override'][i]['rule_id'] == id) { + if (globalPushRules['override'][i]['actions'] + .indexOf('dont_notify') != -1) { return PushRuleState.dont_notify; } @@ -1246,10 +1241,10 @@ class Room { } } - if (globalPushRules["room"] is List) { - for (var i = 0; i < globalPushRules["room"].length; i++) { - if (globalPushRules["room"][i]["rule_id"] == id) { - if (globalPushRules["room"][i]["actions"].indexOf("dont_notify") != + if (globalPushRules['room'] is List) { + for (var i = 0; i < globalPushRules['room'].length; i++) { + if (globalPushRules['room'][i]['rule_id'] == id) { + if (globalPushRules['room'][i]['actions'].indexOf('dont_notify') != -1) { return PushRuleState.mentions_only; } @@ -1272,12 +1267,12 @@ class Room { if (pushRuleState == PushRuleState.dont_notify) { resp = await client.jsonRequest( type: HTTPType.DELETE, - action: "/client/r0/pushrules/global/override/$id", + action: '/client/r0/pushrules/global/override/$id', data: {}); } else if (pushRuleState == PushRuleState.mentions_only) { resp = await client.jsonRequest( type: HTTPType.DELETE, - action: "/client/r0/pushrules/global/room/$id", + action: '/client/r0/pushrules/global/room/$id', data: {}); } break; @@ -1286,20 +1281,20 @@ class Room { if (pushRuleState == PushRuleState.dont_notify) { resp = await client.jsonRequest( type: HTTPType.DELETE, - action: "/client/r0/pushrules/global/override/$id", + action: '/client/r0/pushrules/global/override/$id', data: {}); resp = await client.jsonRequest( type: HTTPType.PUT, - action: "/client/r0/pushrules/global/room/$id", + action: '/client/r0/pushrules/global/room/$id', data: { - "actions": ["dont_notify"] + 'actions': ['dont_notify'] }); } else if (pushRuleState == PushRuleState.notify) { resp = await client.jsonRequest( type: HTTPType.PUT, - action: "/client/r0/pushrules/global/room/$id", + action: '/client/r0/pushrules/global/room/$id', data: { - "actions": ["dont_notify"] + 'actions': ['dont_notify'] }); } break; @@ -1308,16 +1303,16 @@ class Room { if (pushRuleState == PushRuleState.mentions_only) { resp = await client.jsonRequest( type: HTTPType.DELETE, - action: "/client/r0/pushrules/global/room/$id", + action: '/client/r0/pushrules/global/room/$id', data: {}); } resp = await client.jsonRequest( type: HTTPType.PUT, - action: "/client/r0/pushrules/global/override/$id", + action: '/client/r0/pushrules/global/override/$id', data: { - "actions": ["dont_notify"], - "conditions": [ - {"key": "room_id", "kind": "event_match", "pattern": id} + 'actions': ['dont_notify'], + 'conditions': [ + {'key': 'room_id', 'kind': 'event_match', 'pattern': id} ] }); } @@ -1329,29 +1324,29 @@ class Room { {String reason, String txid}) async { // Create new transaction id String messageID; - final int now = DateTime.now().millisecondsSinceEpoch; + final now = DateTime.now().millisecondsSinceEpoch; if (txid == null) { - messageID = "msg$now"; + messageID = 'msg$now'; } else { messageID = txid; } - Map data = {}; - if (reason != null) data["reason"] = reason; + var data = {}; + if (reason != null) data['reason'] = reason; final dynamic resp = await client.jsonRequest( type: HTTPType.PUT, - action: "/client/r0/rooms/$id/redact/$eventId/$messageID", + action: '/client/r0/rooms/$id/redact/$eventId/$messageID', data: data); return resp; } Future sendTypingInfo(bool isTyping, {int timeout}) { - Map data = { - "typing": isTyping, + var data = { + 'typing': isTyping, }; - if (timeout != null) data["timeout"] = timeout; + if (timeout != null) data['timeout'] = timeout; return client.jsonRequest( type: HTTPType.PUT, - action: "/client/r0/rooms/${this.id}/typing/${client.userID}", + action: '/client/r0/rooms/${id}/typing/${client.userID}', data: data, ); } @@ -1364,19 +1359,19 @@ class Room { /// [type] The type of session description. Must be 'offer'. /// [sdp] The SDP text of the session description. Future inviteToCall(String callId, int lifetime, String sdp, - {String type = "offer", int version = 0, String txid}) async { - if (txid == null) txid = "txid${DateTime.now().millisecondsSinceEpoch}"; - final Map response = await client.jsonRequest( + {String type = 'offer', int version = 0, String txid}) async { + txid ??= 'txid${DateTime.now().millisecondsSinceEpoch}'; + final response = await client.jsonRequest( type: HTTPType.PUT, - action: "/client/r0/rooms/$id/send/m.call.invite/$txid", + action: '/client/r0/rooms/$id/send/m.call.invite/$txid', data: { - "call_id": callId, - "lifetime": lifetime, - "offer": {"sdp": sdp, "type": type}, - "version": version, + 'call_id': callId, + 'lifetime': lifetime, + 'offer': {'sdp': sdp, 'type': type}, + 'version': version, }, ); - return response["event_id"]; + return response['event_id']; } /// This is sent by callers after sending an invite and by the callee after answering. @@ -1403,17 +1398,17 @@ class Room { int version = 0, String txid, }) async { - if (txid == null) txid = "txid${DateTime.now().millisecondsSinceEpoch}"; - final Map response = await client.jsonRequest( + txid ??= 'txid${DateTime.now().millisecondsSinceEpoch}'; + final response = await client.jsonRequest( type: HTTPType.PUT, - action: "/client/r0/rooms/$id/send/m.call.candidates/$txid", + action: '/client/r0/rooms/$id/send/m.call.candidates/$txid', data: { - "call_id": callId, - "candidates": candidates, - "version": version, + 'call_id': callId, + 'candidates': candidates, + 'version': version, }, ); - return response["event_id"]; + return response['event_id']; } /// This event is sent by the callee when they wish to answer the call. @@ -1422,18 +1417,18 @@ class Room { /// [type] The type of session description. Must be 'answer'. /// [sdp] The SDP text of the session description. Future answerCall(String callId, String sdp, - {String type = "answer", int version = 0, String txid}) async { - if (txid == null) txid = "txid${DateTime.now().millisecondsSinceEpoch}"; - final Map response = await client.jsonRequest( + {String type = 'answer', int version = 0, String txid}) async { + txid ??= 'txid${DateTime.now().millisecondsSinceEpoch}'; + final response = await client.jsonRequest( type: HTTPType.PUT, - action: "/client/r0/rooms/$id/send/m.call.answer/$txid", + action: '/client/r0/rooms/$id/send/m.call.answer/$txid', data: { - "call_id": callId, - "answer": {"sdp": sdp, "type": type}, - "version": version, + 'call_id': callId, + 'answer': {'sdp': sdp, 'type': type}, + 'version': version, }, ); - return response["event_id"]; + return response['event_id']; } /// This event is sent by the callee when they wish to answer the call. @@ -1441,24 +1436,24 @@ class Room { /// [version] is the version of the VoIP specification this message adheres to. This specification is version 0. Future hangupCall(String callId, {int version = 0, String txid}) async { - if (txid == null) txid = "txid${DateTime.now().millisecondsSinceEpoch}"; - final Map response = await client.jsonRequest( + txid ??= 'txid${DateTime.now().millisecondsSinceEpoch}'; + final response = await client.jsonRequest( type: HTTPType.PUT, - action: "/client/r0/rooms/$id/send/m.call.hangup/$txid", + action: '/client/r0/rooms/$id/send/m.call.hangup/$txid', data: { - "call_id": callId, - "version": version, + 'call_id': callId, + 'version': version, }, ); - return response["event_id"]; + return response['event_id']; } /// Returns all aliases for this room. List get aliases { - List aliases = []; - for (Event aliasEvent in states.states["m.room.aliases"].values) { - if (aliasEvent.content["aliases"] is List) { - aliases.addAll(aliasEvent.content["aliases"]); + var aliases = []; + for (var aliasEvent in states.states['m.room.aliases'].values) { + if (aliasEvent.content['aliases'] is List) { + aliases.addAll(aliasEvent.content['aliases']); } } return aliases; @@ -1468,11 +1463,11 @@ class Room { /// it can be invite meaning that a user who wishes to join the room must first receive an invite /// to the room from someone already inside of the room. Currently, knock and private are reserved /// keywords which are not implemented. - JoinRules get joinRules => getState("m.room.join_rules") != null + JoinRules get joinRules => getState('m.room.join_rules') != null ? JoinRules.values.firstWhere( (r) => - r.toString().replaceAll("JoinRules.", "") == - getState("m.room.join_rules").content["join_rule"], + r.toString().replaceAll('JoinRules.', '') == + getState('m.room.join_rules').content['join_rule'], orElse: () => null) : null; @@ -1480,24 +1475,24 @@ class Room { Future setJoinRules(JoinRules joinRules) async { await client.jsonRequest( type: HTTPType.PUT, - action: "/client/r0/rooms/$id/state/m.room.join_rules/", + action: '/client/r0/rooms/$id/state/m.room.join_rules/', data: { - "join_rule": joinRules.toString().replaceAll("JoinRules.", ""), + 'join_rule': joinRules.toString().replaceAll('JoinRules.', ''), }, ); return; } /// Whether the user has the permission to change the join rules. - bool get canChangeJoinRules => canSendEvent("m.room.join_rules"); + bool get canChangeJoinRules => canSendEvent('m.room.join_rules'); /// This event controls whether guest users are allowed to join rooms. If this event /// is absent, servers should act as if it is present and has the guest_access value "forbidden". - GuestAccess get guestAccess => getState("m.room.guest_access") != null + GuestAccess get guestAccess => getState('m.room.guest_access') != null ? GuestAccess.values.firstWhere( (r) => - r.toString().replaceAll("GuestAccess.", "") == - getState("m.room.guest_access").content["guest_access"], + r.toString().replaceAll('GuestAccess.', '') == + getState('m.room.guest_access').content['guest_access'], orElse: () => GuestAccess.forbidden) : GuestAccess.forbidden; @@ -1505,25 +1500,25 @@ class Room { Future setGuestAccess(GuestAccess guestAccess) async { await client.jsonRequest( type: HTTPType.PUT, - action: "/client/r0/rooms/$id/state/m.room.guest_access/", + action: '/client/r0/rooms/$id/state/m.room.guest_access/', data: { - "guest_access": guestAccess.toString().replaceAll("GuestAccess.", ""), + 'guest_access': guestAccess.toString().replaceAll('GuestAccess.', ''), }, ); return; } /// Whether the user has the permission to change the guest access. - bool get canChangeGuestAccess => canSendEvent("m.room.guest_access"); + bool get canChangeGuestAccess => canSendEvent('m.room.guest_access'); /// This event controls whether a user can see the events that happened in a room from before they joined. HistoryVisibility get historyVisibility => - getState("m.room.history_visibility") != null + getState('m.room.history_visibility') != null ? HistoryVisibility.values.firstWhere( (r) => - r.toString().replaceAll("HistoryVisibility.", "") == - getState("m.room.history_visibility") - .content["history_visibility"], + r.toString().replaceAll('HistoryVisibility.', '') == + getState('m.room.history_visibility') + .content['history_visibility'], orElse: () => null) : null; @@ -1531,10 +1526,10 @@ class Room { Future setHistoryVisibility(HistoryVisibility historyVisibility) async { await client.jsonRequest( type: HTTPType.PUT, - action: "/client/r0/rooms/$id/state/m.room.history_visibility/", + action: '/client/r0/rooms/$id/state/m.room.history_visibility/', data: { - "history_visibility": - historyVisibility.toString().replaceAll("HistoryVisibility.", ""), + 'history_visibility': + historyVisibility.toString().replaceAll('HistoryVisibility.', ''), }, ); return; @@ -1542,26 +1537,25 @@ class Room { /// Whether the user has the permission to change the history visibility. bool get canChangeHistoryVisibility => - canSendEvent("m.room.history_visibility"); + canSendEvent('m.room.history_visibility'); /// Returns the encryption algorithm. Currently only `m.megolm.v1.aes-sha2` is supported. /// Returns null if there is no encryption algorithm. - String get encryptionAlgorithm => getState("m.room.encryption") != null - ? getState("m.room.encryption").content["algorithm"].toString() + String get encryptionAlgorithm => getState('m.room.encryption') != null + ? getState('m.room.encryption').content['algorithm'].toString() : null; /// Checks if this room is encrypted. bool get encrypted => encryptionAlgorithm != null; Future enableEncryption({int algorithmIndex = 0}) async { - if (encrypted) throw ("Encryption is already enabled!"); - final String algorithm = - Client.supportedGroupEncryptionAlgorithms[algorithmIndex]; + if (encrypted) throw ('Encryption is already enabled!'); + final algorithm = Client.supportedGroupEncryptionAlgorithms[algorithmIndex]; await client.jsonRequest( type: HTTPType.PUT, - action: "/client/r0/rooms/$id/state/m.room.encryption/", + action: '/client/r0/rooms/$id/state/m.room.encryption/', data: { - "algorithm": algorithm, + 'algorithm': algorithm, }, ); return; @@ -1569,14 +1563,13 @@ class Room { /// Returns all known device keys for all participants in this room. Future> getUserDeviceKeys() async { - List deviceKeys = []; - List users = await requestParticipants(); + var deviceKeys = []; + var users = await requestParticipants(); for (final userDeviceKeyEntry in client.userDeviceKeys.entries) { if (users.indexWhere((u) => u.id == userDeviceKeyEntry.key) == -1) { continue; } - for (DeviceKeys deviceKeyEntry - in userDeviceKeyEntry.value.deviceKeys.values) { + for (var deviceKeyEntry in userDeviceKeyEntry.value.deviceKeys.values) { deviceKeys.add(deviceKeyEntry); } } @@ -1587,25 +1580,25 @@ class Room { /// payload. This will create a new outgoingGroupSession if necessary. Future> encryptGroupMessagePayload( Map payload, - {String type = "m.room.message"}) async { - if (!this.encrypted || !client.encryptionEnabled) return payload; - if (this.encryptionAlgorithm != "m.megolm.v1.aes-sha2") { - throw ("Unknown encryption algorithm"); + {String type = 'm.room.message'}) async { + if (!encrypted || !client.encryptionEnabled) return payload; + if (encryptionAlgorithm != 'm.megolm.v1.aes-sha2') { + throw ('Unknown encryption algorithm'); } if (_outboundGroupSession == null) { await createOutboundGroupSession(); } - final Map payloadContent = { - "content": payload, - "type": type, - "room_id": id, + final payloadContent = { + 'content': payload, + 'type': type, + 'room_id': id, }; - Map encryptedPayload = { - "algorithm": "m.megolm.v1.aes-sha2", - "ciphertext": _outboundGroupSession.encrypt(json.encode(payloadContent)), - "device_id": client.deviceID, - "sender_key": client.identityKey, - "session_id": _outboundGroupSession.session_id(), + var encryptedPayload = { + 'algorithm': 'm.megolm.v1.aes-sha2', + 'ciphertext': _outboundGroupSession.encrypt(json.encode(payloadContent)), + 'device_id': client.deviceID, + 'sender_key': client.identityKey, + 'session_id': _outboundGroupSession.session_id(), }; await _storeOutboundGroupSession(); return encryptedPayload; @@ -1621,22 +1614,22 @@ class Room { if (!client.encryptionEnabled) { throw (DecryptError.NOT_ENABLED); } - if (event.content["algorithm"] != "m.megolm.v1.aes-sha2") { + if (event.content['algorithm'] != 'm.megolm.v1.aes-sha2') { throw (DecryptError.UNKNOWN_ALGORITHM); } - final String sessionId = event.content["session_id"]; + final String sessionId = event.content['session_id']; if (!sessionKeys.containsKey(sessionId)) { throw (DecryptError.UNKNOWN_SESSION); } - final olm.DecryptResult decryptResult = sessionKeys[sessionId] + final decryptResult = sessionKeys[sessionId] .inboundGroupSession - .decrypt(event.content["ciphertext"]); - final String messageIndexKey = + .decrypt(event.content['ciphertext']); + final messageIndexKey = event.eventId + event.time.millisecondsSinceEpoch.toString(); if (sessionKeys[sessionId].indexes.containsKey(messageIndexKey) && sessionKeys[sessionId].indexes[messageIndexKey] != decryptResult.message_index) { - if ((_outboundGroupSession?.session_id() ?? "") == sessionId) { + if ((_outboundGroupSession?.session_id() ?? '') == sessionId) { clearOutboundGroupSession(); } throw (DecryptError.CHANNEL_CORRUPTED); @@ -1644,30 +1637,28 @@ class Room { sessionKeys[sessionId].indexes[messageIndexKey] = decryptResult.message_index; _storeOutboundGroupSession(); - // TODO: The client should check that the sender's fingerprint key matches the keys.ed25519 property of the event which established the Megolm session when marking the event as verified. - decryptedPayload = json.decode(decryptResult.plaintext); } catch (exception) { if (exception.toString() == DecryptError.UNKNOWN_SESSION) { decryptedPayload = { - "content": event.content, - "type": "m.room.encrypted", + 'content': event.content, + 'type': 'm.room.encrypted', }; - decryptedPayload["content"]["body"] = exception.toString(); - decryptedPayload["content"]["msgtype"] = "m.bad.encrypted"; + decryptedPayload['content']['body'] = exception.toString(); + decryptedPayload['content']['msgtype'] = 'm.bad.encrypted'; } else { decryptedPayload = { - "content": { - "msgtype": "m.bad.encrypted", - "body": exception.toString(), + 'content': { + 'msgtype': 'm.bad.encrypted', + 'body': exception.toString(), }, - "type": "m.room.encrypted", + 'type': 'm.room.encrypted', }; } } return Event( - content: decryptedPayload["content"], - typeKey: decryptedPayload["type"], + content: decryptedPayload['content'], + typeKey: decryptedPayload['type'], senderId: event.senderId, eventId: event.eventId, roomId: event.roomId, @@ -1682,10 +1673,10 @@ class Room { } abstract class DecryptError { - static const String NOT_ENABLED = "Encryption is not enabled in your client."; - static const String UNKNOWN_ALGORITHM = "Unknown encryption algorithm."; + static const String NOT_ENABLED = 'Encryption is not enabled in your client.'; + static const String UNKNOWN_ALGORITHM = 'Unknown encryption algorithm.'; static const String UNKNOWN_SESSION = - "The sender has not sent us the session key."; + 'The sender has not sent us the session key.'; static const String CHANNEL_CORRUPTED = - "The secure channel with the sender was corrupted."; + 'The secure channel with the sender was corrupted.'; } diff --git a/lib/src/room_account_data.dart b/lib/src/room_account_data.dart index 69402d0..dbc7386 100644 --- a/lib/src/room_account_data.dart +++ b/lib/src/room_account_data.dart @@ -39,8 +39,7 @@ class RoomAccountData extends AccountData { /// Get a State event from a table row or from the event stream. factory RoomAccountData.fromJson( Map jsonPayload, Room room) { - final Map content = - Event.getMapFromPayload(jsonPayload['content']); + final content = Event.getMapFromPayload(jsonPayload['content']); return RoomAccountData( content: content, typeKey: jsonPayload['type'], diff --git a/lib/src/store_api.dart b/lib/src/store_api.dart index 36ce5bd..ded6c2f 100644 --- a/lib/src/store_api.dart +++ b/lib/src/store_api.dart @@ -66,13 +66,14 @@ abstract class ExtendedStoreAPI extends StoreAPI { /// Whether this is a simple store which only stores the client credentials and /// end to end encryption stuff or the whole sync payloads. + @override final bool extended = true; /// The current trans Future setRoomPrevBatch(String roomId, String prevBatch); /// Performs these query or queries inside of an transaction. - Future transaction(void queries()); + Future transaction(void Function() queries); /// Will be automatically called on every synchronisation. Must be called inside of // /// [transaction]. diff --git a/lib/src/sync/event_update.dart b/lib/src/sync/event_update.dart index 504807d..19cce63 100644 --- a/lib/src/sync/event_update.dart +++ b/lib/src/sync/event_update.dart @@ -43,11 +43,11 @@ class EventUpdate { EventUpdate({this.eventType, this.roomID, this.type, this.content}); EventUpdate decrypt(Room room) { - if (eventType != "m.room.encrypted") { + if (eventType != 'm.room.encrypted') { return this; } try { - Event decrpytedEvent = + var decrpytedEvent = room.decryptGroupMessage(Event.fromJson(content, room)); return EventUpdate( eventType: eventType, @@ -56,7 +56,7 @@ class EventUpdate { content: decrpytedEvent.toJson(), ); } catch (e) { - print("[LibOlm] Could not decrypt megolm event: " + e.toString()); + print('[LibOlm] Could not decrypt megolm event: ' + e.toString()); return this; } } diff --git a/lib/src/timeline.dart b/lib/src/timeline.dart index 14ab727..6c7fffb 100644 --- a/lib/src/timeline.dart +++ b/lib/src/timeline.dart @@ -25,7 +25,6 @@ import 'dart:async'; import 'event.dart'; import 'room.dart'; -import 'user.dart'; import 'sync/event_update.dart'; typedef onTimelineUpdateCallback = void Function(); @@ -45,17 +44,17 @@ class Timeline { StreamSubscription sessionIdReceivedSub; bool _requestingHistoryLock = false; - Map _eventCache = {}; + final Map _eventCache = {}; /// Searches for the event in this timeline. If not /// found, requests from the server. Requested events /// are cached. Future getEventById(String id) async { - for (int i = 0; i < events.length; i++) { + for (var i = 0; i < events.length; i++) { if (events[i].eventId == id) return events[i]; } if (_eventCache.containsKey(id)) return _eventCache[id]; - final Event requestedEvent = await room.getEventById(id); + final requestedEvent = await room.getEventById(id); if (requestedEvent == null) return null; _eventCache[id] = requestedEvent; return _eventCache[id]; @@ -89,12 +88,12 @@ class Timeline { } void _sessionKeyReceived(String sessionId) { - bool decryptAtLeastOneEvent = false; - for (int i = 0; i < events.length; i++) { + var decryptAtLeastOneEvent = false; + for (var i = 0; i < events.length; i++) { if (events[i].type == EventTypes.Encrypted && events[i].messageType == MessageTypes.BadEncrypted && - events[i].content["body"] == DecryptError.UNKNOWN_SESSION && - events[i].content["session_id"] == sessionId) { + events[i].content['body'] == DecryptError.UNKNOWN_SESSION && + events[i].content['session_id'] == sessionId) { events[i] = events[i].decrypted; if (events[i].type != EventTypes.Encrypted) { decryptAtLeastOneEvent = true; @@ -117,26 +116,25 @@ class Timeline { try { if (eventUpdate.roomID != room.id) return; - if (eventUpdate.type == "timeline" || eventUpdate.type == "history") { + if (eventUpdate.type == 'timeline' || eventUpdate.type == 'history') { // Redaction events are handled as modification for existing events. - if (eventUpdate.eventType == "m.room.redaction") { - final int eventId = - _findEvent(event_id: eventUpdate.content["redacts"]); + if (eventUpdate.eventType == 'm.room.redaction') { + final eventId = _findEvent(event_id: eventUpdate.content['redacts']); if (eventId != null) { events[eventId] .setRedactionEvent(Event.fromJson(eventUpdate.content, room)); } - } else if (eventUpdate.content["status"] == -2) { - int i = _findEvent(event_id: eventUpdate.content["event_id"]); + } else if (eventUpdate.content['status'] == -2) { + var i = _findEvent(event_id: eventUpdate.content['event_id']); if (i < events.length) events.removeAt(i); } // Is this event already in the timeline? - else if (eventUpdate.content.containsKey("unsigned") && - eventUpdate.content["unsigned"]["transaction_id"] is String) { - int i = _findEvent( - event_id: eventUpdate.content["event_id"], - unsigned_txid: eventUpdate.content.containsKey("unsigned") - ? eventUpdate.content["unsigned"]["transaction_id"] + else if (eventUpdate.content.containsKey('unsigned') && + eventUpdate.content['unsigned']['transaction_id'] is String) { + var i = _findEvent( + event_id: eventUpdate.content['event_id'], + unsigned_txid: eventUpdate.content.containsKey('unsigned') + ? eventUpdate.content['unsigned']['transaction_id'] : null); if (i < events.length) { @@ -144,18 +142,18 @@ class Timeline { } } else { Event newEvent; - User senderUser = await room.client.store - ?.getUser(matrixID: eventUpdate.content["sender"], room: room); + var senderUser = await room.client.store + ?.getUser(matrixID: eventUpdate.content['sender'], room: room); if (senderUser != null) { - eventUpdate.content["displayname"] = senderUser.displayName; - eventUpdate.content["avatar_url"] = senderUser.avatarUrl.mxc; + eventUpdate.content['displayname'] = senderUser.displayName; + eventUpdate.content['avatar_url'] = senderUser.avatarUrl.mxc; } newEvent = Event.fromJson(eventUpdate.content, room); - if (eventUpdate.type == "history" && + if (eventUpdate.type == 'history' && events.indexWhere( - (e) => e.eventId == eventUpdate.content["event_id"]) != + (e) => e.eventId == eventUpdate.content['event_id']) != -1) return; events.insert(0, newEvent); @@ -165,14 +163,14 @@ class Timeline { sortAndUpdate(); } catch (e) { if (room.client.debug) { - print("[WARNING] (_handleEventUpdate) ${e.toString()}"); + print('[WARNING] (_handleEventUpdate) ${e.toString()}'); } } } bool sortLock = false; - sort() { + void sort() { if (sortLock || events.length < 2) return; sortLock = true; events?.sort((a, b) => @@ -180,7 +178,7 @@ class Timeline { sortLock = false; } - sortAndUpdate() { + void sortAndUpdate() async { sort(); if (onUpdate != null) onUpdate(); } diff --git a/lib/src/user.dart b/lib/src/user.dart index 49e94ff..af83737 100644 --- a/lib/src/user.dart +++ b/lib/src/user.dart @@ -37,14 +37,14 @@ class User extends Event { String avatarUrl, Room room, }) { - Map content = {}; - if (membership != null) content["membership"] = membership; - if (displayName != null) content["displayname"] = displayName; - if (avatarUrl != null) content["avatar_url"] = avatarUrl; + var content = {}; + if (membership != null) content['membership'] = membership; + if (displayName != null) content['displayname'] = displayName; + if (avatarUrl != null) content['avatar_url'] = avatarUrl; return User.fromState( stateKey: id, content: content, - typeKey: "m.room.member", + typeKey: 'm.room.member', roomId: room?.id, room: room, time: DateTime.now(), @@ -78,7 +78,7 @@ class User extends Event { String get id => stateKey; /// The displayname of the user if the user has set one. - String get displayName => content != null ? content["displayname"] : null; + String get displayName => content != null ? content['displayname'] : null; /// Returns the power level of this user. int get powerLevel => room?.getPowerLevelByUserId(id); @@ -89,21 +89,21 @@ class User extends Event { /// leave /// ban Membership get membership => Membership.values.firstWhere((e) { - if (content["membership"] != null) { + if (content['membership'] != null) { return e.toString() == 'Membership.' + content['membership']; } return false; }, orElse: () => Membership.join); /// The avatar if the user has one. - MxContent get avatarUrl => content != null && content["avatar_url"] is String - ? MxContent(content["avatar_url"]) - : MxContent(""); + MxContent get avatarUrl => content != null && content['avatar_url'] is String + ? MxContent(content['avatar_url']) + : MxContent(''); /// Returns the displayname or the local part of the Matrix ID if the user /// has no displayname. String calcDisplayname() => (displayName == null || displayName.isEmpty) - ? (stateKey != null ? stateKey.localpart : "Unknown User") + ? (stateKey != null ? stateKey.localpart : 'Unknown User') : displayName; /// Call the Matrix API to kick this user from this room. @@ -122,20 +122,20 @@ class User extends Event { /// Returns null on error. Future startDirectChat() async { // Try to find an existing direct chat - String roomID = await room.client?.getDirectChatFromUserId(id); + var roomID = await room.client?.getDirectChatFromUserId(id); if (roomID != null) return roomID; // Start a new direct chat final dynamic resp = await room.client.jsonRequest( type: HTTPType.POST, - action: "/client/r0/createRoom", + action: '/client/r0/createRoom', data: { - "invite": [id], - "is_direct": true, - "preset": "trusted_private_chat" + 'invite': [id], + 'is_direct': true, + 'preset': 'trusted_private_chat' }); - final String newRoomID = resp["room_id"]; + final String newRoomID = resp['room_id']; if (newRoomID == null) return newRoomID; diff --git a/lib/src/utils/device_keys_list.dart b/lib/src/utils/device_keys_list.dart index f24b229..f67a8e0 100644 --- a/lib/src/utils/device_keys_list.dart +++ b/lib/src/utils/device_keys_list.dart @@ -1,7 +1,6 @@ import 'dart:convert'; import '../client.dart'; -import '../room.dart'; class DeviceKeysList { String userId; @@ -19,18 +18,20 @@ class DeviceKeysList { } Map toJson() { - final Map data = Map(); - data['user_id'] = this.userId; - data['outdated'] = this.outdated ?? true; + var map = {}; + final data = map; + data['user_id'] = userId; + data['outdated'] = outdated ?? true; - Map rawDeviceKeys = {}; - for (final deviceKeyEntry in this.deviceKeys.entries) { + var rawDeviceKeys = {}; + for (final deviceKeyEntry in deviceKeys.entries) { rawDeviceKeys[deviceKeyEntry.key] = deviceKeyEntry.value.toJson(); } data['device_keys'] = rawDeviceKeys; return data; } + @override String toString() => json.encode(toJson()); DeviceKeysList(this.userId); @@ -46,8 +47,8 @@ class DeviceKeys { bool verified; bool blocked; - String get curve25519Key => keys["curve25519:$deviceId"]; - String get ed25519Key => keys["ed25519:$deviceId"]; + String get curve25519Key => keys['curve25519:$deviceId']; + String get ed25519Key => keys['ed25519:$deviceId']; Future setVerified(bool newVerified, Client client) { verified = newVerified; @@ -56,7 +57,7 @@ class DeviceKeys { Future setBlocked(bool newBlocked, Client client) { blocked = newBlocked; - for (Room room in client.rooms) { + for (var room in client.rooms) { if (!room.encrypted) continue; if (room.getParticipants().indexWhere((u) => u.id == userId) != -1) { room.clearOutboundGroupSession(); @@ -92,21 +93,21 @@ class DeviceKeys { } Map toJson() { - final Map data = Map(); - data['user_id'] = this.userId; - data['device_id'] = this.deviceId; - data['algorithms'] = this.algorithms; - if (this.keys != null) { - data['keys'] = this.keys; + final data = {}; + data['user_id'] = userId; + data['device_id'] = deviceId; + data['algorithms'] = algorithms; + if (keys != null) { + data['keys'] = keys; } - if (this.signatures != null) { - data['signatures'] = this.signatures; + if (signatures != null) { + data['signatures'] = signatures; } - if (this.unsigned != null) { - data['unsigned'] = this.unsigned; + if (unsigned != null) { + data['unsigned'] = unsigned; } - data['verified'] = this.verified; - data['blocked'] = this.blocked; + data['verified'] = verified; + data['blocked'] = blocked; return data; } } diff --git a/lib/src/utils/matrix_exception.dart b/lib/src/utils/matrix_exception.dart index e2b5140..e92be43 100644 --- a/lib/src/utils/matrix_exception.dart +++ b/lib/src/utils/matrix_exception.dart @@ -48,34 +48,34 @@ class MatrixException implements Exception { /// The unique identifier for this error. String get errcode => - raw["errcode"] ?? - (requireAdditionalAuthentication ? "M_FORBIDDEN" : "M_UNKNOWN"); + raw['errcode'] ?? + (requireAdditionalAuthentication ? 'M_FORBIDDEN' : 'M_UNKNOWN'); /// A human readable error description. String get errorMessage => - raw["error"] ?? + raw['error'] ?? (requireAdditionalAuthentication - ? "Require additional authentication" - : "Unknown error"); + ? 'Require additional authentication' + : 'Unknown error'); /// The frozen request which triggered this Error http.Response response; - MatrixException(this.response) : this.raw = json.decode(response.body); + MatrixException(this.response) : raw = json.decode(response.body); @override - String toString() => "$errcode: $errorMessage"; + String toString() => '$errcode: $errorMessage'; /// Returns the [ResponseError]. Is ResponseError.NONE if there wasn't an error. MatrixError get error => MatrixError.values.firstWhere( (e) => e.toString() == 'MatrixError.${(raw["errcode"] ?? "")}', orElse: () => MatrixError.M_UNKNOWN); - int get retryAfterMs => raw["retry_after_ms"]; + int get retryAfterMs => raw['retry_after_ms']; /// This is a session identifier that the client must pass back to the homeserver, if one is provided, /// in subsequent attempts to authenticate in the same API call. - String get session => raw["session"]; + String get session => raw['session']; /// Returns true if the server requires additional authentication. bool get requireAdditionalAuthentication => response.statusCode == 401; @@ -84,11 +84,11 @@ class MatrixException implements Exception { /// to authenticate itself. Each flow comprises a series of stages. If this request /// doesn't need additional authentication, then this is null. List get authenticationFlows { - if (!raw.containsKey("flows") || !(raw["flows"] is List)) return null; - List flows = []; - for (Map flow in raw["flows"]) { - if (flow["stages"] is List) { - flows.add(AuthenticationFlow(List.from(flow["stages"]))); + if (!raw.containsKey('flows') || !(raw['flows'] is List)) return null; + var flows = []; + for (Map flow in raw['flows']) { + if (flow['stages'] is List) { + flows.add(AuthenticationFlow(List.from(flow['stages']))); } } return flows; @@ -97,10 +97,11 @@ class MatrixException implements Exception { /// This section contains any information that the client will need to know in order to use a given type /// of authentication. For each authentication type presented, that type may be present as a key in this /// dictionary. For example, the public part of an OAuth client ID could be given here. - Map get authenticationParams => raw["params"]; + Map get authenticationParams => raw['params']; /// Returns the list of already completed authentication flows from previous requests. - List get completedAuthenticationFlows => List.from(raw["completed"] ?? []); + List get completedAuthenticationFlows => + List.from(raw['completed'] ?? []); } /// For each endpoint, a server offers one or more 'flows' that the client can use diff --git a/lib/src/utils/matrix_file.dart b/lib/src/utils/matrix_file.dart index a85fba0..30ed3a1 100644 --- a/lib/src/utils/matrix_file.dart +++ b/lib/src/utils/matrix_file.dart @@ -11,11 +11,12 @@ class MatrixFile { /// Encrypts this file, changes the [bytes] and returns the /// encryption information as an [EncryptedFile]. Future encrypt() async { - final EncryptedFile encryptedFile = await encryptFile(bytes); - this.bytes = encryptedFile.data; + var encryptFile2 = encryptFile(bytes); + final encryptedFile = await encryptFile2; + bytes = encryptedFile.data; return encryptedFile; } - MatrixFile({this.bytes, String path}) : this.path = path.toLowerCase(); + MatrixFile({this.bytes, String path}) : path = path.toLowerCase(); int get size => bytes.length; } diff --git a/lib/src/utils/matrix_id_string_extension.dart b/lib/src/utils/matrix_id_string_extension.dart index f25268f..296a780 100644 --- a/lib/src/utils/matrix_id_string_extension.dart +++ b/lib/src/utils/matrix_id_string_extension.dart @@ -1,27 +1,27 @@ extension MatrixIdExtension on String { - static const Set VALID_SIGILS = {"@", "!", "#", "\$", "+"}; + static const Set VALID_SIGILS = {'@', '!', '#', '\$', '+'}; static const int MAX_LENGTH = 255; bool get isValidMatrixId { - if (this?.isEmpty ?? true) return false; - if (this.length > MAX_LENGTH) return false; - if (!VALID_SIGILS.contains(this.substring(0, 1))) { + if (isEmpty ?? true) return false; + if (length > MAX_LENGTH) return false; + if (!VALID_SIGILS.contains(substring(0, 1))) { return false; } - final List parts = this.substring(1).split(":"); + final parts = substring(1).split(':'); if (parts.length != 2 || parts[0].isEmpty || parts[1].isEmpty) { return false; } return true; } - String get sigil => isValidMatrixId ? this.substring(0, 1) : null; + String get sigil => isValidMatrixId ? substring(0, 1) : null; String get localpart => - isValidMatrixId ? this.substring(1).split(":").first : null; + isValidMatrixId ? substring(1).split(':').first : null; - String get domain => isValidMatrixId ? this.substring(1).split(":")[1] : null; + String get domain => isValidMatrixId ? substring(1).split(':')[1] : null; - bool equals(String other) => this?.toLowerCase() == other?.toLowerCase(); + bool equals(String other) => toLowerCase() == other?.toLowerCase(); } diff --git a/lib/src/utils/mx_content.dart b/lib/src/utils/mx_content.dart index 61a09aa..00ea77d 100644 --- a/lib/src/utils/mx_content.dart +++ b/lib/src/utils/mx_content.dart @@ -29,7 +29,7 @@ class MxContent { final String _mxc; /// Insert a mxc:// uri here. - MxContent(String mxcUrl) : this._mxc = mxcUrl ?? ""; + MxContent(String mxcUrl) : _mxc = mxcUrl ?? ''; /// Returns the mxc uri. String get mxc => _mxc; @@ -37,20 +37,20 @@ class MxContent { /// Returns a download Link to this content. String getDownloadLink(Client matrix) => matrix.homeserver != null ? "${matrix.homeserver}/_matrix/media/r0/download/${_mxc.replaceFirst("mxc://", "")}" - : ""; + : ''; /// Returns a scaled thumbnail link to this content with the given [width] and /// [height]. [method] can be [ThumbnailMethod.crop] or /// [ThumbnailMethod.scale] and defaults to [ThumbnailMethod.scale]. String getThumbnail(Client matrix, {num width, num height, ThumbnailMethod method}) { - String methodStr = "crop"; - if (method == ThumbnailMethod.scale) methodStr = "scale"; + var methodStr = 'crop'; + if (method == ThumbnailMethod.scale) methodStr = 'scale'; width = width.round(); height = height.round(); return matrix.homeserver != null ? "${matrix.homeserver}/_matrix/media/r0/thumbnail/${_mxc.replaceFirst("mxc://", "")}?width=$width&height=$height&method=$methodStr" - : ""; + : ''; } } diff --git a/lib/src/utils/open_id_credentials.dart b/lib/src/utils/open_id_credentials.dart index 108f349..a2c79b6 100644 --- a/lib/src/utils/open_id_credentials.dart +++ b/lib/src/utils/open_id_credentials.dart @@ -18,11 +18,12 @@ class OpenIdCredentials { } Map toJson() { - final Map data = Map(); - data['access_token'] = this.accessToken; - data['token_type'] = this.tokenType; - data['matrix_server_name'] = this.matrixServerName; - data['expires_in'] = this.expiresIn; + var map = {}; + final data = map; + data['access_token'] = accessToken; + data['token_type'] = tokenType; + data['matrix_server_name'] = matrixServerName; + data['expires_in'] = expiresIn; return data; } } diff --git a/lib/src/utils/profile.dart b/lib/src/utils/profile.dart index 8dbd2de..f9737c8 100644 --- a/lib/src/utils/profile.dart +++ b/lib/src/utils/profile.dart @@ -16,7 +16,7 @@ class Profile { displayname = json['displayname'], content = json; + @override bool operator ==(dynamic other) => - this.avatarUrl.mxc == other.avatarUrl.mxc && - this.displayname == other.displayname; + avatarUrl.mxc == other.avatarUrl.mxc && displayname == other.displayname; } diff --git a/lib/src/utils/public_rooms_response.dart b/lib/src/utils/public_rooms_response.dart index c3db19f..738ca59 100644 --- a/lib/src/utils/public_rooms_response.dart +++ b/lib/src/utils/public_rooms_response.dart @@ -21,7 +21,7 @@ class PublicRoomsResponse { client = client, totalRoomCountEstimate = json['total_room_count_estimate'] { if (json['chunk'] != null) { - publicRooms = List(); + publicRooms = []; json['chunk'].forEach((v) { publicRooms.add(PublicRoomEntry.fromJson(v, client)); }); diff --git a/lib/src/utils/push_rules.dart b/lib/src/utils/push_rules.dart index dff91d7..31f463a 100644 --- a/lib/src/utils/push_rules.dart +++ b/lib/src/utils/push_rules.dart @@ -3,7 +3,7 @@ class PushRules { final GlobalPushRules global; PushRules.fromJson(Map json) - : this.global = GlobalPushRules.fromJson(json["global"]); + : global = GlobalPushRules.fromJson(json['global']); } /// The global ruleset. @@ -15,20 +15,20 @@ class GlobalPushRules { final List underride; GlobalPushRules.fromJson(Map json) - : this.content = json.containsKey("content") - ? PushRule.fromJsonList(json["content"]) + : content = json.containsKey('content') + ? PushRule.fromJsonList(json['content']) : null, - this.override = json.containsKey("override") - ? PushRule.fromJsonList(json["content"]) + override = json.containsKey('override') + ? PushRule.fromJsonList(json['content']) : null, - this.room = json.containsKey("room") - ? PushRule.fromJsonList(json["room"]) + room = json.containsKey('room') + ? PushRule.fromJsonList(json['room']) : null, - this.sender = json.containsKey("sender") - ? PushRule.fromJsonList(json["sender"]) + sender = json.containsKey('sender') + ? PushRule.fromJsonList(json['sender']) : null, - this.underride = json.containsKey("underride") - ? PushRule.fromJsonList(json["underride"]) + underride = json.containsKey('underride') + ? PushRule.fromJsonList(json['underride']) : null; } @@ -42,7 +42,7 @@ class PushRule { final String pattern; static List fromJsonList(List list) { - List objList = []; + var objList = []; list.forEach((json) { objList.add(PushRule.fromJson(json)); }); @@ -50,14 +50,14 @@ class PushRule { } PushRule.fromJson(Map json) - : this.actions = json["actions"], - this.isDefault = json["default"], - this.enabled = json["enabled"], - this.ruleId = json["rule_id"], - this.conditions = json.containsKey("conditions") - ? PushRuleConditions.fromJsonList(json["conditions"]) + : actions = json['actions'], + isDefault = json['default'], + enabled = json['enabled'], + ruleId = json['rule_id'], + conditions = json.containsKey('conditions') + ? PushRuleConditions.fromJsonList(json['conditions']) : null, - this.pattern = json["pattern"]; + pattern = json['pattern']; } /// Conditions when this pushrule should be active. @@ -68,7 +68,7 @@ class PushRuleConditions { final String is_; static List fromJsonList(List list) { - List objList = []; + var objList = []; list.forEach((json) { objList.add(PushRuleConditions.fromJson(json)); }); @@ -76,8 +76,8 @@ class PushRuleConditions { } PushRuleConditions.fromJson(Map json) - : this.kind = json["kind"], - this.key = json["key"], - this.pattern = json["pattern"], - this.is_ = json["is"]; + : kind = json['kind'], + key = json['key'], + pattern = json['pattern'], + is_ = json['is']; } diff --git a/lib/src/utils/room_key_request.dart b/lib/src/utils/room_key_request.dart index 9277ceb..4e99ef0 100644 --- a/lib/src/utils/room_key_request.dart +++ b/lib/src/utils/room_key_request.dart @@ -1,35 +1,33 @@ import 'package:famedlysdk/famedlysdk.dart'; -import 'package:famedlysdk/src/utils/session_key.dart'; class RoomKeyRequest extends ToDeviceEvent { Client client; RoomKeyRequest.fromToDeviceEvent(ToDeviceEvent toDeviceEvent, Client client) { this.client = client; - this.sender = toDeviceEvent.sender; - this.content = toDeviceEvent.content; - this.type = toDeviceEvent.type; + sender = toDeviceEvent.sender; + content = toDeviceEvent.content; + type = toDeviceEvent.type; } - Room get room => client.getRoomById(this.content["body"]["room_id"]); + Room get room => client.getRoomById(content['body']['room_id']); DeviceKeys get requestingDevice => - client.userDeviceKeys[sender].deviceKeys[content["requesting_device_id"]]; + client.userDeviceKeys[sender].deviceKeys[content['requesting_device_id']]; Future forwardKey() async { - Room room = this.room; - final SessionKey session = - room.sessionKeys[this.content["body"]["session_id"]]; - List forwardedKeys = [client.identityKey]; + var room = this.room; + final session = room.sessionKeys[content['body']['session_id']]; + var forwardedKeys = [client.identityKey]; for (final key in session.forwardingCurve25519KeyChain) { forwardedKeys.add(key); } await requestingDevice.setVerified(true, client); - Map message = session.content; - message["forwarding_curve25519_key_chain"] = forwardedKeys; - message["session_key"] = session.inboundGroupSession.export_session(0); + var message = session.content; + message['forwarding_curve25519_key_chain'] = forwardedKeys; + message['session_key'] = session.inboundGroupSession.export_session(0); await client.sendToDevice( [requestingDevice], - "m.forwarded_room_key", + 'm.forwarded_room_key', message, ); } diff --git a/lib/src/utils/session_key.dart b/lib/src/utils/session_key.dart index 13add08..414ea85 100644 --- a/lib/src/utils/session_key.dart +++ b/lib/src/utils/session_key.dart @@ -8,35 +8,36 @@ class SessionKey { InboundGroupSession inboundGroupSession; final String key; List get forwardingCurve25519KeyChain => - content["forwarding_curve25519_key_chain"] ?? []; + content['forwarding_curve25519_key_chain'] ?? []; String get senderClaimedEd25519Key => - content["sender_claimed_ed25519_key"] ?? ""; + content['sender_claimed_ed25519_key'] ?? ''; SessionKey({this.content, this.inboundGroupSession, this.key, this.indexes}); - SessionKey.fromJson(Map json, String key) : this.key = key { + SessionKey.fromJson(Map json, String key) : key = key { content = json['content'] != null ? Map.from(json['content']) : null; indexes = json['indexes'] != null ? Map.from(json['indexes']) - : Map(); - InboundGroupSession newInboundGroupSession = InboundGroupSession(); + : {}; + var newInboundGroupSession = InboundGroupSession(); newInboundGroupSession.unpickle(key, json['inboundGroupSession']); inboundGroupSession = newInboundGroupSession; } Map toJson() { - final Map data = Map(); - if (this.content != null) { - data['content'] = this.content; + final data = {}; + if (content != null) { + data['content'] = content; } - if (this.indexes != null) { - data['indexes'] = this.indexes; + if (indexes != null) { + data['indexes'] = indexes; } - data['inboundGroupSession'] = this.inboundGroupSession.pickle(this.key); + data['inboundGroupSession'] = inboundGroupSession.pickle(key); return data; } - String toString() => json.encode(this.toJson()); + @override + String toString() => json.encode(toJson()); } diff --git a/lib/src/utils/states_map.dart b/lib/src/utils/states_map.dart index a399516..b3b3a86 100644 --- a/lib/src/utils/states_map.dart +++ b/lib/src/utils/states_map.dart @@ -10,13 +10,13 @@ class StatesMap { dynamic operator [](String key) { //print("[Warning] This method will be depracated in the future!"); if (key == null) return null; - if (key.startsWith("@") && key.contains(":")) { - if (!states.containsKey("m.room.member")) states["m.room.member"] = {}; - return states["m.room.member"][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 Event) { - return states[key][""]; + if (states[key][''] is Event) { + return states[key]['']; } else if (states[key].isEmpty) { return null; } else { @@ -26,12 +26,12 @@ class StatesMap { void operator []=(String key, Event val) { //print("[Warning] This method will be depracated in the future!"); - if (key.startsWith("@") && key.contains(":")) { - if (!states.containsKey("m.room.member")) states["m.room.member"] = {}; - states["m.room.member"][key] = 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; + states[key][val.stateKey ?? ''] = val; } bool containsKey(String key) => states.containsKey(key); diff --git a/lib/src/utils/to_device_event.dart b/lib/src/utils/to_device_event.dart index 6f88fbc..11d0fa2 100644 --- a/lib/src/utils/to_device_event.dart +++ b/lib/src/utils/to_device_event.dart @@ -14,11 +14,12 @@ class ToDeviceEvent { } Map toJson() { - final Map data = Map(); - data['sender'] = this.sender; - data['type'] = this.type; - if (this.content != null) { - data['content'] = this.content; + var map = {}; + final data = map; + data['sender'] = sender; + data['type'] = type; + if (content != null) { + data['content'] = content; } return data; } diff --git a/lib/src/utils/user_device.dart b/lib/src/utils/user_device.dart index b81105d..190fe1c 100644 --- a/lib/src/utils/user_device.dart +++ b/lib/src/utils/user_device.dart @@ -20,8 +20,8 @@ class UserDevice { Future updateMetaData(String newName) async { await _client.jsonRequest( type: HTTPType.PUT, - action: "/client/r0/devices/$deviceId", - data: {"display_name": newName}, + action: '/client/r0/devices/$deviceId', + data: {'display_name': newName}, ); return; } @@ -30,8 +30,8 @@ class UserDevice { Future deleteDevice(Map auth) async { await _client.jsonRequest( type: HTTPType.DELETE, - action: "/client/r0/devices/$deviceId", - data: auth != null ? {"auth": auth} : null, + action: '/client/r0/devices/$deviceId', + data: auth != null ? {'auth': auth} : null, ); return; } diff --git a/pubspec.lock b/pubspec.lock index 30ef5f6..2e5d5f1 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -196,7 +196,7 @@ packages: name: http url: "https://pub.dartlang.org" source: hosted - version: "0.12.0+2" + version: "0.12.0+4" http_multi_server: dependency: transitive description: @@ -333,7 +333,7 @@ packages: name: pedantic url: "https://pub.dartlang.org" source: hosted - version: "1.8.0+1" + version: "1.9.0" pointycastle: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 7296819..75b9a72 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -25,4 +25,4 @@ dependencies: dev_dependencies: test: ^1.0.0 build_runner: ^1.5.2 - pedantic: ^1.5.0 # DO NOT UPDATE AS THIS WOULD CAUSE FLUTTER TO FAIL + pedantic: ^1.9.0 # DO NOT UPDATE AS THIS WOULD CAUSE FLUTTER TO FAIL diff --git a/test/canonical_json_test.dart b/test/canonical_json_test.dart index 9f9829f..a0b10dc 100644 --- a/test/canonical_json_test.dart +++ b/test/canonical_json_test.dart @@ -26,26 +26,26 @@ import 'package:test/test.dart'; void main() { /// All Tests related to the ChatTime - group("Canonical Json", () { - Map> textMap = { + group('Canonical Json', () { + var textMap = >{ '{}': {}, - '{"one":1,"two":"Two"}': {"one": 1, "two": "Two"}, - '{"a":"1","b":"2"}': {"b": "2", "a": "1"}, + '{"one":1,"two":"Two"}': {'one': 1, 'two': 'Two'}, + '{"a":"1","b":"2"}': {'b': '2', 'a': '1'}, '{"auth":{"mxid":"@john.doe:example.com","profile":{"display_name":"John Doe","three_pids":[{"address":"john.doe@example.org","medium":"email"},{"address":"123456789","medium":"msisdn"}]},"success":true}}': { - "auth": { - "success": true, - "mxid": "@john.doe:example.com", - "profile": { - "display_name": "John Doe", - "three_pids": [ - {"medium": "email", "address": "john.doe@example.org"}, - {"medium": "msisdn", "address": "123456789"} + 'auth': { + 'success': true, + 'mxid': '@john.doe:example.com', + 'profile': { + 'display_name': 'John Doe', + 'three_pids': [ + {'medium': 'email', 'address': 'john.doe@example.org'}, + {'medium': 'msisdn', 'address': '123456789'} ] } } }, - '{"a":null}': {"a": null}, + '{"a":null}': {'a': null}, }; for (final entry in textMap.entries) { test(entry.key, () async { diff --git a/test/client_test.dart b/test/client_test.dart index c46d596..f49d286 100644 --- a/test/client_test.dart +++ b/test/client_test.dart @@ -29,15 +29,12 @@ import 'package:famedlysdk/famedlysdk.dart'; import 'package:famedlysdk/src/account_data.dart'; import 'package:famedlysdk/src/client.dart'; import 'package:famedlysdk/src/presence.dart'; -import 'package:famedlysdk/src/room.dart'; import 'package:famedlysdk/src/user.dart'; import 'package:famedlysdk/src/sync/event_update.dart'; import 'package:famedlysdk/src/sync/room_update.dart'; import 'package:famedlysdk/src/sync/user_update.dart'; import 'package:famedlysdk/src/utils/matrix_exception.dart'; import 'package:famedlysdk/src/utils/matrix_file.dart'; -import 'package:famedlysdk/src/utils/profile.dart'; -import 'package:famedlysdk/src/utils/user_device.dart'; import 'package:olm/olm.dart' as olm; import 'package:test/test.dart'; @@ -52,35 +49,35 @@ void main() { Future> userUpdateListFuture; Future> toDeviceUpdateListFuture; - const String pickledOlmAccount = - "N2v1MkIFGcl0mQpo2OCwSopxPQJ0wnl7oe7PKiT4141AijfdTIhRu+ceXzXKy3Kr00nLqXtRv7kid6hU4a+V0rfJWLL0Y51+3Rp/ORDVnQy+SSeo6Fn4FHcXrxifJEJ0djla5u98fBcJ8BSkhIDmtXRPi5/oJAvpiYn+8zMjFHobOeZUAxYR0VfQ9JzSYBsSovoQ7uFkNks1M4EDUvHtuweStA+EKZvvHZO0SnwRp0Hw7sv8UMYvXw"; - const String identityKey = "7rvl3jORJkBiK4XX1e5TnGnqz068XfYJ0W++Ml63rgk"; - const String fingerprintKey = "gjL//fyaFHADt9KBADGag8g7F8Up78B/K1zXeiEPLJo"; + const pickledOlmAccount = + 'N2v1MkIFGcl0mQpo2OCwSopxPQJ0wnl7oe7PKiT4141AijfdTIhRu+ceXzXKy3Kr00nLqXtRv7kid6hU4a+V0rfJWLL0Y51+3Rp/ORDVnQy+SSeo6Fn4FHcXrxifJEJ0djla5u98fBcJ8BSkhIDmtXRPi5/oJAvpiYn+8zMjFHobOeZUAxYR0VfQ9JzSYBsSovoQ7uFkNks1M4EDUvHtuweStA+EKZvvHZO0SnwRp0Hw7sv8UMYvXw'; + const identityKey = '7rvl3jORJkBiK4XX1e5TnGnqz068XfYJ0W++Ml63rgk'; + const fingerprintKey = 'gjL//fyaFHADt9KBADGag8g7F8Up78B/K1zXeiEPLJo'; /// All Tests related to the Login - group("FluffyMatrix", () { + group('FluffyMatrix', () { /// Check if all Elements get created - matrix = Client("testclient", debug: true); + matrix = Client('testclient', debug: true); matrix.httpClient = FakeMatrixApi(); roomUpdateListFuture = matrix.onRoomUpdate.stream.toList(); eventUpdateListFuture = matrix.onEvent.stream.toList(); userUpdateListFuture = matrix.onUserEvent.stream.toList(); toDeviceUpdateListFuture = matrix.onToDeviceEvent.stream.toList(); - bool olmEnabled = true; + var olmEnabled = true; try { olm.init(); olm.Account(); } catch (_) { olmEnabled = false; - print("[LibOlm] Failed to load LibOlm: " + _.toString()); + print('[LibOlm] Failed to load LibOlm: ' + _.toString()); } - print("[LibOlm] Enabled: $olmEnabled"); + print('[LibOlm] Enabled: $olmEnabled'); test('Login', () async { - int presenceCounter = 0; - int accountDataCounter = 0; + var presenceCounter = 0; + var accountDataCounter = 0; matrix.onPresence.stream.listen((Presence data) { presenceCounter++; }); @@ -92,46 +89,45 @@ void main() { expect(matrix.matrixVersions, null); try { - await matrix.checkServer("https://fakeserver.wrongaddress"); + await matrix.checkServer('https://fakeserver.wrongaddress'); } on FormatException catch (exception) { expect(exception != null, true); } - await matrix.checkServer("https://fakeserver.notexisting"); - expect(matrix.homeserver, "https://fakeserver.notexisting"); + await matrix.checkServer('https://fakeserver.notexisting'); + expect(matrix.homeserver, 'https://fakeserver.notexisting'); expect(matrix.matrixVersions, - ["r0.0.1", "r0.1.0", "r0.2.0", "r0.3.0", "r0.4.0", "r0.5.0"]); + ['r0.0.1', 'r0.1.0', 'r0.2.0', 'r0.3.0', 'r0.4.0', 'r0.5.0']); - final Map resp = await matrix - .jsonRequest(type: HTTPType.POST, action: "/client/r0/login", data: { - "type": "m.login.password", - "user": "test", - "password": "1234", - "initial_device_display_name": "Fluffy Matrix Client" + final resp = await matrix + .jsonRequest(type: HTTPType.POST, action: '/client/r0/login', data: { + 'type': 'm.login.password', + 'user': 'test', + 'password': '1234', + 'initial_device_display_name': 'Fluffy Matrix Client' }); - final bool available = await matrix.usernameAvailable("testuser"); + final available = await matrix.usernameAvailable('testuser'); expect(available, true); - Map registerResponse = await matrix.register(username: "testuser"); - expect(registerResponse["user_id"], "@testuser:example.com"); + Map registerResponse = await matrix.register(username: 'testuser'); + expect(registerResponse['user_id'], '@testuser:example.com'); registerResponse = - await matrix.register(username: "testuser", kind: "user"); - expect(registerResponse["user_id"], "@testuser:example.com"); + await matrix.register(username: 'testuser', kind: 'user'); + expect(registerResponse['user_id'], '@testuser:example.com'); registerResponse = - await matrix.register(username: "testuser", kind: "guest"); - expect(registerResponse["user_id"], "@testuser:example.com"); + await matrix.register(username: 'testuser', kind: 'guest'); + expect(registerResponse['user_id'], '@testuser:example.com'); - Future loginStateFuture = - matrix.onLoginStateChanged.stream.first; - Future firstSyncFuture = matrix.onFirstSync.stream.first; - Future syncFuture = matrix.onSync.stream.first; + var loginStateFuture = matrix.onLoginStateChanged.stream.first; + var firstSyncFuture = matrix.onFirstSync.stream.first; + var syncFuture = matrix.onSync.stream.first; matrix.connect( - newToken: resp["access_token"], - newUserID: resp["user_id"], + newToken: resp['access_token'], + newUserID: resp['user_id'], newHomeserver: matrix.homeserver, - newDeviceName: "Text Matrix Client", - newDeviceID: resp["device_id"], + newDeviceName: 'Text Matrix Client', + newDeviceID: resp['device_id'], newMatrixVersions: matrix.matrixVersions, newLazyLoadMembers: matrix.lazyLoadMembers, newOlmAccount: pickledOlmAccount, @@ -139,13 +135,13 @@ void main() { await Future.delayed(Duration(milliseconds: 50)); - expect(matrix.accessToken == resp["access_token"], true); - expect(matrix.deviceName == "Text Matrix Client", true); - expect(matrix.deviceID == resp["device_id"], true); - expect(matrix.userID == resp["user_id"], true); + expect(matrix.accessToken == resp['access_token'], true); + expect(matrix.deviceName == 'Text Matrix Client', true); + expect(matrix.deviceID == resp['device_id'], true); + expect(matrix.userID == resp['user_id'], true); - LoginState loginState = await loginStateFuture; - bool firstSync = await firstSyncFuture; + var loginState = await loginStateFuture; + var firstSync = await firstSyncFuture; dynamic sync = await syncFuture; expect(loginState, LoginState.logged); @@ -156,91 +152,91 @@ void main() { expect(matrix.identityKey, identityKey); expect(matrix.fingerprintKey, fingerprintKey); } - expect(sync["next_batch"] == matrix.prevBatch, true); + expect(sync['next_batch'] == matrix.prevBatch, true); expect(matrix.accountData.length, 3); - expect(matrix.getDirectChatFromUserId("@bob:example.com"), - "!726s6s6q:example.com"); - expect(matrix.rooms[1].directChatMatrixID, "@bob:example.com"); - expect(matrix.directChats, matrix.accountData["m.direct"].content); + expect(matrix.getDirectChatFromUserId('@bob:example.com'), + '!726s6s6q:example.com'); + expect(matrix.rooms[1].directChatMatrixID, '@bob:example.com'); + expect(matrix.directChats, matrix.accountData['m.direct'].content); expect(matrix.presences.length, 1); expect(matrix.rooms[1].ephemerals.length, 2); expect(matrix.rooms[1].sessionKeys.length, 1); expect( matrix .rooms[1] - .sessionKeys["ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU"] - .content["session_key"], - "AgAAAAAQcQ6XrFJk6Prm8FikZDqfry/NbDz8Xw7T6e+/9Yf/q3YHIPEQlzv7IZMNcYb51ifkRzFejVvtphS7wwG2FaXIp4XS2obla14iKISR0X74ugB2vyb1AydIHE/zbBQ1ic5s3kgjMFlWpu/S3FQCnCrv+DPFGEt3ERGWxIl3Bl5X53IjPyVkz65oljz2TZESwz0GH/QFvyOOm8ci0q/gceaF3S7Dmafg3dwTKYwcA5xkcc+BLyrLRzB6Hn+oMAqSNSscnm4mTeT5zYibIhrzqyUTMWr32spFtI9dNR/RFSzfCw"); + .sessionKeys['ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU'] + .content['session_key'], + 'AgAAAAAQcQ6XrFJk6Prm8FikZDqfry/NbDz8Xw7T6e+/9Yf/q3YHIPEQlzv7IZMNcYb51ifkRzFejVvtphS7wwG2FaXIp4XS2obla14iKISR0X74ugB2vyb1AydIHE/zbBQ1ic5s3kgjMFlWpu/S3FQCnCrv+DPFGEt3ERGWxIl3Bl5X53IjPyVkz65oljz2TZESwz0GH/QFvyOOm8ci0q/gceaF3S7Dmafg3dwTKYwcA5xkcc+BLyrLRzB6Hn+oMAqSNSscnm4mTeT5zYibIhrzqyUTMWr32spFtI9dNR/RFSzfCw'); if (olmEnabled) { expect( matrix .rooms[1] - .sessionKeys["ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU"] + .sessionKeys['ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU'] .inboundGroupSession != null, true); } expect(matrix.rooms[1].typingUsers.length, 1); - expect(matrix.rooms[1].typingUsers[0].id, "@alice:example.com"); + expect(matrix.rooms[1].typingUsers[0].id, '@alice:example.com'); expect(matrix.rooms[1].roomAccountData.length, 3); expect(matrix.rooms[1].encrypted, true); expect(matrix.rooms[1].encryptionAlgorithm, Client.supportedGroupEncryptionAlgorithms.first); expect( - matrix.rooms[1].roomAccountData["m.receipt"] - .content["@alice:example.com"]["ts"], + matrix.rooms[1].roomAccountData['m.receipt'] + .content['@alice:example.com']['ts'], 1436451550453); expect( - matrix.rooms[1].roomAccountData["m.receipt"] - .content["@alice:example.com"]["event_id"], - "7365636s6r6432:example.com"); + matrix.rooms[1].roomAccountData['m.receipt'] + .content['@alice:example.com']['event_id'], + '7365636s6r6432:example.com'); expect(matrix.rooms.length, 2); expect(matrix.rooms[1].canonicalAlias, "#famedlyContactDiscovery:${matrix.userID.split(":")[1]}"); - final List contacts = await matrix.loadFamedlyContacts(); + final contacts = await matrix.loadFamedlyContacts(); expect(contacts.length, 1); - expect(contacts[0].senderId, "@alice:example.com"); + expect(contacts[0].senderId, '@alice:example.com'); expect( - matrix.presences["@alice:example.com"].presence, PresenceType.online); + matrix.presences['@alice:example.com'].presence, PresenceType.online); expect(presenceCounter, 1); expect(accountDataCounter, 3); await Future.delayed(Duration(milliseconds: 50)); expect(matrix.userDeviceKeys.length, 2); - expect(matrix.userDeviceKeys["@alice:example.com"].outdated, false); - expect(matrix.userDeviceKeys["@alice:example.com"].deviceKeys.length, 1); + expect(matrix.userDeviceKeys['@alice:example.com'].outdated, false); + expect(matrix.userDeviceKeys['@alice:example.com'].deviceKeys.length, 1); expect( - matrix.userDeviceKeys["@alice:example.com"].deviceKeys["JLAFKJWSCS"] + matrix.userDeviceKeys['@alice:example.com'].deviceKeys['JLAFKJWSCS'] .verified, false); matrix.handleSync({ - "device_lists": { - "changed": [ - "@alice:example.com", + 'device_lists': { + 'changed': [ + '@alice:example.com', ], - "left": [ - "@bob:example.com", + 'left': [ + '@bob:example.com', ], } }); await Future.delayed(Duration(milliseconds: 50)); expect(matrix.userDeviceKeys.length, 2); - expect(matrix.userDeviceKeys["@alice:example.com"].outdated, true); + expect(matrix.userDeviceKeys['@alice:example.com'].outdated, true); matrix.handleSync({ - "rooms": { - "join": { - "!726s6s6q:example.com": { - "state": { - "events": [ + 'rooms': { + 'join': { + '!726s6s6q:example.com': { + 'state': { + 'events': [ { - "sender": "@alice:example.com", - "type": "m.room.canonical_alias", - "content": {"alias": ""}, - "state_key": "", - "origin_server_ts": 1417731086799, - "event_id": "66697273743033:example.com" + 'sender': '@alice:example.com', + 'type': 'm.room.canonical_alias', + 'content': {'alias': ''}, + 'state_key': '', + 'origin_server_ts': 1417731086799, + 'event_id': '66697273743033:example.com' } ] } @@ -254,17 +250,17 @@ void main() { matrix.getRoomByAlias( "#famedlyContactDiscovery:${matrix.userID.split(":")[1]}"), null); - final List altContacts = await matrix.loadFamedlyContacts(); + final altContacts = await matrix.loadFamedlyContacts(); altContacts.forEach((u) => print(u.id)); expect(altContacts.length, 2); - expect(altContacts[0].senderId, "@alice:example.com"); + expect(altContacts[0].senderId, '@alice:example.com'); }); test('Try to get ErrorResponse', () async { MatrixException expectedException; try { await matrix.jsonRequest( - type: HTTPType.PUT, action: "/non/existing/path"); + type: HTTPType.PUT, action: '/non/existing/path'); } on MatrixException catch (exception) { expectedException = exception; } @@ -273,10 +269,9 @@ void main() { test('Logout', () async { await matrix.jsonRequest( - type: HTTPType.POST, action: "/client/r0/logout"); + type: HTTPType.POST, action: '/client/r0/logout'); - Future loginStateFuture = - matrix.onLoginStateChanged.stream.first; + var loginStateFuture = matrix.onLoginStateChanged.stream.first; matrix.clear(); @@ -289,27 +284,27 @@ void main() { expect(matrix.lazyLoadMembers == null, true); expect(matrix.prevBatch == null, true); - LoginState loginState = await loginStateFuture; + var loginState = await loginStateFuture; expect(loginState, LoginState.loggedOut); }); test('Room Update Test', () async { await matrix.onRoomUpdate.close(); - List roomUpdateList = await roomUpdateListFuture; + var roomUpdateList = await roomUpdateListFuture; expect(roomUpdateList.length, 3); - 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].prev_batch == "t34-23535_0_0", true); + expect(roomUpdateList[0].prev_batch == 't34-23535_0_0', true); expect(roomUpdateList[0].limitedTimeline == true, true); expect(roomUpdateList[0].notification_count == 2, true); expect(roomUpdateList[0].highlight_count == 2, true); - expect(roomUpdateList[1].id == "!696r7674:example.com", true); + expect(roomUpdateList[1].id == '!696r7674:example.com', true); expect(roomUpdateList[1].membership == Membership.invite, true); - expect(roomUpdateList[1].prev_batch == "", true); + expect(roomUpdateList[1].prev_batch == '', true); expect(roomUpdateList[1].limitedTimeline == false, true); expect(roomUpdateList[1].notification_count == 0, true); expect(roomUpdateList[1].highlight_count == 0, true); @@ -318,194 +313,193 @@ void main() { test('Event Update Test', () async { await matrix.onEvent.close(); - List eventUpdateList = await eventUpdateListFuture; + var eventUpdateList = await eventUpdateListFuture; expect(eventUpdateList.length, 13); - expect(eventUpdateList[0].eventType, "m.room.member"); - expect(eventUpdateList[0].roomID, "!726s6s6q:example.com"); - expect(eventUpdateList[0].type, "state"); + expect(eventUpdateList[0].eventType, 'm.room.member'); + expect(eventUpdateList[0].roomID, '!726s6s6q:example.com'); + expect(eventUpdateList[0].type, 'state'); - expect(eventUpdateList[1].eventType, "m.room.canonical_alias"); - expect(eventUpdateList[1].roomID, "!726s6s6q:example.com"); - expect(eventUpdateList[1].type, "state"); + expect(eventUpdateList[1].eventType, 'm.room.canonical_alias'); + expect(eventUpdateList[1].roomID, '!726s6s6q:example.com'); + expect(eventUpdateList[1].type, 'state'); - expect(eventUpdateList[2].eventType, "m.room.encryption"); - expect(eventUpdateList[2].roomID, "!726s6s6q:example.com"); - expect(eventUpdateList[2].type, "state"); + expect(eventUpdateList[2].eventType, 'm.room.encryption'); + expect(eventUpdateList[2].roomID, '!726s6s6q:example.com'); + expect(eventUpdateList[2].type, 'state'); - expect(eventUpdateList[3].eventType, "m.room.member"); - expect(eventUpdateList[3].roomID, "!726s6s6q:example.com"); - expect(eventUpdateList[3].type, "timeline"); + expect(eventUpdateList[3].eventType, 'm.room.member'); + expect(eventUpdateList[3].roomID, '!726s6s6q:example.com'); + expect(eventUpdateList[3].type, 'timeline'); - expect(eventUpdateList[4].eventType, "m.room.message"); - expect(eventUpdateList[4].roomID, "!726s6s6q:example.com"); - expect(eventUpdateList[4].type, "timeline"); + expect(eventUpdateList[4].eventType, 'm.room.message'); + expect(eventUpdateList[4].roomID, '!726s6s6q:example.com'); + expect(eventUpdateList[4].type, 'timeline'); - expect(eventUpdateList[5].eventType, "m.typing"); - expect(eventUpdateList[5].roomID, "!726s6s6q:example.com"); - expect(eventUpdateList[5].type, "ephemeral"); + expect(eventUpdateList[5].eventType, 'm.typing'); + expect(eventUpdateList[5].roomID, '!726s6s6q:example.com'); + expect(eventUpdateList[5].type, 'ephemeral'); - expect(eventUpdateList[6].eventType, "m.receipt"); - expect(eventUpdateList[6].roomID, "!726s6s6q:example.com"); - expect(eventUpdateList[6].type, "ephemeral"); + expect(eventUpdateList[6].eventType, 'm.receipt'); + expect(eventUpdateList[6].roomID, '!726s6s6q:example.com'); + expect(eventUpdateList[6].type, 'ephemeral'); - expect(eventUpdateList[7].eventType, "m.receipt"); - expect(eventUpdateList[7].roomID, "!726s6s6q:example.com"); - expect(eventUpdateList[7].type, "account_data"); + expect(eventUpdateList[7].eventType, 'm.receipt'); + expect(eventUpdateList[7].roomID, '!726s6s6q:example.com'); + expect(eventUpdateList[7].type, 'account_data'); - expect(eventUpdateList[8].eventType, "m.tag"); - expect(eventUpdateList[8].roomID, "!726s6s6q:example.com"); - expect(eventUpdateList[8].type, "account_data"); + expect(eventUpdateList[8].eventType, 'm.tag'); + expect(eventUpdateList[8].roomID, '!726s6s6q:example.com'); + expect(eventUpdateList[8].type, 'account_data'); - expect(eventUpdateList[9].eventType, "org.example.custom.room.config"); - expect(eventUpdateList[9].roomID, "!726s6s6q:example.com"); - expect(eventUpdateList[9].type, "account_data"); + expect(eventUpdateList[9].eventType, 'org.example.custom.room.config'); + expect(eventUpdateList[9].roomID, '!726s6s6q:example.com'); + expect(eventUpdateList[9].type, 'account_data'); - expect(eventUpdateList[10].eventType, "m.room.name"); - expect(eventUpdateList[10].roomID, "!696r7674:example.com"); - expect(eventUpdateList[10].type, "invite_state"); + expect(eventUpdateList[10].eventType, 'm.room.name'); + expect(eventUpdateList[10].roomID, '!696r7674:example.com'); + expect(eventUpdateList[10].type, 'invite_state'); - expect(eventUpdateList[11].eventType, "m.room.member"); - expect(eventUpdateList[11].roomID, "!696r7674:example.com"); - expect(eventUpdateList[11].type, "invite_state"); + expect(eventUpdateList[11].eventType, 'm.room.member'); + expect(eventUpdateList[11].roomID, '!696r7674:example.com'); + expect(eventUpdateList[11].type, 'invite_state'); }); test('User Update Test', () async { await matrix.onUserEvent.close(); - List eventUpdateList = await userUpdateListFuture; + var eventUpdateList = await userUpdateListFuture; expect(eventUpdateList.length, 4); - expect(eventUpdateList[0].eventType, "m.presence"); - expect(eventUpdateList[0].type, "presence"); + expect(eventUpdateList[0].eventType, 'm.presence'); + expect(eventUpdateList[0].type, 'presence'); - expect(eventUpdateList[1].eventType, "m.push_rules"); - expect(eventUpdateList[1].type, "account_data"); + expect(eventUpdateList[1].eventType, 'm.push_rules'); + expect(eventUpdateList[1].type, 'account_data'); - expect(eventUpdateList[2].eventType, "org.example.custom.config"); - expect(eventUpdateList[2].type, "account_data"); + expect(eventUpdateList[2].eventType, 'org.example.custom.config'); + expect(eventUpdateList[2].type, 'account_data'); }); test('To Device Update Test', () async { await matrix.onToDeviceEvent.close(); - List eventUpdateList = await toDeviceUpdateListFuture; + var eventUpdateList = await toDeviceUpdateListFuture; expect(eventUpdateList.length, 2); - expect(eventUpdateList[0].type, "m.new_device"); - expect(eventUpdateList[1].type, "m.room_key"); + expect(eventUpdateList[0].type, 'm.new_device'); + expect(eventUpdateList[1].type, 'm.room_key'); }); test('Login', () async { - matrix = Client("testclient", debug: true); + matrix = Client('testclient', debug: true); matrix.httpClient = FakeMatrixApi(); roomUpdateListFuture = matrix.onRoomUpdate.stream.toList(); eventUpdateListFuture = matrix.onEvent.stream.toList(); userUpdateListFuture = matrix.onUserEvent.stream.toList(); - final bool checkResp = - await matrix.checkServer("https://fakeServer.notExisting"); + final checkResp = + await matrix.checkServer('https://fakeServer.notExisting'); - final bool loginResp = await matrix.login("test", "1234"); + final loginResp = await matrix.login('test', '1234'); expect(checkResp, true); expect(loginResp, true); }); test('createRoom', () async { - final OpenIdCredentials openId = await matrix.requestOpenIdCredentials(); - expect(openId.accessToken, "SomeT0kenHere"); - expect(openId.tokenType, "Bearer"); - expect(openId.matrixServerName, "example.com"); + final openId = await matrix.requestOpenIdCredentials(); + expect(openId.accessToken, 'SomeT0kenHere'); + expect(openId.tokenType, 'Bearer'); + expect(openId.matrixServerName, 'example.com'); expect(openId.expiresIn, 3600); }); test('createRoom', () async { - final List users = [ - User("@alice:fakeServer.notExisting"), - User("@bob:fakeServer.notExisting") + final users = [ + User('@alice:fakeServer.notExisting'), + User('@bob:fakeServer.notExisting') ]; - final String newID = await matrix.createRoom(invite: users); - expect(newID, "!1234:fakeServer.notExisting"); + final newID = await matrix.createRoom(invite: users); + expect(newID, '!1234:fakeServer.notExisting'); }); test('setAvatar', () async { - final MatrixFile testFile = - MatrixFile(bytes: Uint8List(0), path: "fake/path/file.jpeg"); + final testFile = + MatrixFile(bytes: Uint8List(0), path: 'fake/path/file.jpeg'); await matrix.setAvatar(testFile); }); test('setPushers', () async { - await matrix.setPushers("abcdefg", "http", "com.famedly.famedlysdk", - "famedlySDK", "GitLabCi", "en", "https://examplepushserver.com", - format: "event_id_only"); + await matrix.setPushers('abcdefg', 'http', 'com.famedly.famedlysdk', + 'famedlySDK', 'GitLabCi', 'en', 'https://examplepushserver.com', + format: 'event_id_only'); }); test('joinRoomById', () async { - final String roomID = "1234"; + final roomID = '1234'; final Map resp = await matrix.joinRoomById(roomID); - expect(resp["room_id"], roomID); + expect(resp['room_id'], roomID); }); test('requestUserDevices', () async { - final List userDevices = await matrix.requestUserDevices(); + final userDevices = await matrix.requestUserDevices(); expect(userDevices.length, 1); - expect(userDevices.first.deviceId, "QBUAZIFURK"); - expect(userDevices.first.displayName, "android"); - expect(userDevices.first.lastSeenIp, "1.2.3.4"); + expect(userDevices.first.deviceId, 'QBUAZIFURK'); + expect(userDevices.first.displayName, 'android'); + expect(userDevices.first.lastSeenIp, '1.2.3.4'); expect( userDevices.first.lastSeenTs.millisecondsSinceEpoch, 1474491775024); }); test('get archive', () async { - List archive = await matrix.archive; + var archive = await matrix.archive; await Future.delayed(Duration(milliseconds: 50)); expect(archive.length, 2); - expect(archive[0].id, "!5345234234:example.com"); + expect(archive[0].id, '!5345234234:example.com'); expect(archive[0].membership, Membership.leave); - expect(archive[0].name, "The room name"); - expect(archive[0].lastMessage, "This is an example text message"); + expect(archive[0].name, 'The room name'); + expect(archive[0].lastMessage, 'This is an example text message'); expect(archive[0].roomAccountData.length, 1); - expect(archive[1].id, "!5345234235:example.com"); + expect(archive[1].id, '!5345234235:example.com'); expect(archive[1].membership, Membership.leave); - expect(archive[1].name, "The room name 2"); + expect(archive[1].name, 'The room name 2'); }); test('getProfileFromUserId', () async { - final Profile profile = - await matrix.getProfileFromUserId("@getme:example.com"); - expect(profile.avatarUrl.mxc, "mxc://test"); - expect(profile.displayname, "You got me"); - expect(profile.content["avatar_url"], profile.avatarUrl.mxc); - expect(profile.content["displayname"], profile.displayname); + final profile = await matrix.getProfileFromUserId('@getme:example.com'); + expect(profile.avatarUrl.mxc, 'mxc://test'); + expect(profile.displayname, 'You got me'); + expect(profile.content['avatar_url'], profile.avatarUrl.mxc); + expect(profile.content['displayname'], profile.displayname); }); test('signJson', () { if (matrix.encryptionEnabled) { expect(matrix.fingerprintKey.isNotEmpty, true); expect(matrix.identityKey.isNotEmpty, true); - Map payload = { - "unsigned": { - "foo": "bar", + var payload = { + 'unsigned': { + 'foo': 'bar', }, - "auth": { - "success": true, - "mxid": "@john.doe:example.com", - "profile": { - "display_name": "John Doe", - "three_pids": [ - {"medium": "email", "address": "john.doe@example.org"}, - {"medium": "msisdn", "address": "123456789"} + 'auth': { + 'success': true, + 'mxid': '@john.doe:example.com', + 'profile': { + 'display_name': 'John Doe', + 'three_pids': [ + {'medium': 'email', 'address': 'john.doe@example.org'}, + {'medium': 'msisdn', 'address': '123456789'} ] } } }; - Map payloadWithoutUnsigned = Map.from(payload); - payloadWithoutUnsigned.remove("unsigned"); + var payloadWithoutUnsigned = Map.from(payload); + payloadWithoutUnsigned.remove('unsigned'); expect( matrix.checkJsonSignature( @@ -517,8 +511,8 @@ void main() { false); payload = matrix.signJson(payload); payloadWithoutUnsigned = matrix.signJson(payloadWithoutUnsigned); - expect(payload["signatures"], payloadWithoutUnsigned["signatures"]); - print(payload["signatures"]); + expect(payload['signatures'], payloadWithoutUnsigned['signatures']); + print(payload['signatures']); expect( matrix.checkJsonSignature( matrix.fingerprintKey, payload, matrix.userID, matrix.deviceID), @@ -531,9 +525,9 @@ void main() { }); test('Track oneTimeKeys', () async { if (matrix.encryptionEnabled) { - DateTime last = matrix.lastTimeKeysUploaded ?? DateTime.now(); + var last = matrix.lastTimeKeysUploaded ?? DateTime.now(); matrix.handleSync({ - "device_one_time_keys_count": {"signed_curve25519": 49} + 'device_one_time_keys_count': {'signed_curve25519': 49} }); await Future.delayed(Duration(milliseconds: 50)); expect( @@ -548,12 +542,12 @@ void main() { await matrix.rooms[1].createOutboundGroupSession(); expect(matrix.rooms[1].outboundGroupSession != null, true); matrix.handleSync({ - "device_lists": { - "changed": [ - "@alice:example.com", + 'device_lists': { + 'changed': [ + '@alice:example.com', ], - "left": [ - "@bob:example.com", + 'left': [ + '@bob:example.com', ], } }); @@ -568,19 +562,19 @@ void main() { await matrix.rooms[1].createOutboundGroupSession(); expect(matrix.rooms[1].outboundGroupSession != null, true); matrix.handleSync({ - "rooms": { - "join": { - "!726s6s6q:example.com": { - "state": { - "events": [ + 'rooms': { + 'join': { + '!726s6s6q:example.com': { + 'state': { + 'events': [ { - "content": {"membership": "leave"}, - "event_id": "143273582443PhrSn:example.org", - "origin_server_ts": 1432735824653, - "room_id": "!726s6s6q:example.com", - "sender": "@alice:example.com", - "state_key": "@alice:example.com", - "type": "m.room.member" + 'content': {'membership': 'leave'}, + 'event_id': '143273582443PhrSn:example.org', + 'origin_server_ts': 1432735824653, + 'room_id': '!726s6s6q:example.com', + 'sender': '@alice:example.com', + 'state_key': '@alice:example.com', + 'type': 'm.room.member' } ] } @@ -592,18 +586,18 @@ void main() { expect(matrix.rooms[1].outboundGroupSession != null, true); } }); - DeviceKeys deviceKeys = DeviceKeys.fromJson({ - "user_id": "@alice:example.com", - "device_id": "JLAFKJWSCS", - "algorithms": ["m.olm.v1.curve25519-aes-sha2", "m.megolm.v1.aes-sha2"], - "keys": { - "curve25519:JLAFKJWSCS": "3C5BFWi2Y8MaVvjM8M22DBmh24PmgR0nPvJOIArzgyI", - "ed25519:JLAFKJWSCS": "lEuiRJBit0IG6nUf5pUzWTUEsRVVe/HJkoKuEww9ULI" + var deviceKeys = DeviceKeys.fromJson({ + 'user_id': '@alice:example.com', + 'device_id': 'JLAFKJWSCS', + 'algorithms': ['m.olm.v1.curve25519-aes-sha2', 'm.megolm.v1.aes-sha2'], + 'keys': { + 'curve25519:JLAFKJWSCS': '3C5BFWi2Y8MaVvjM8M22DBmh24PmgR0nPvJOIArzgyI', + 'ed25519:JLAFKJWSCS': 'lEuiRJBit0IG6nUf5pUzWTUEsRVVe/HJkoKuEww9ULI' }, - "signatures": { - "@alice:example.com": { - "ed25519:JLAFKJWSCS": - "dSO80A01XiigH3uBiDVx/EjzaoycHcjq9lfQX0uWsqxl2giMIiSPR8a4d291W1ihKJL/a+myXS367WT6NAIcBA" + 'signatures': { + '@alice:example.com': { + 'ed25519:JLAFKJWSCS': + 'dSO80A01XiigH3uBiDVx/EjzaoycHcjq9lfQX0uWsqxl2giMIiSPR8a4d291W1ihKJL/a+myXS367WT6NAIcBA' } } }); @@ -614,52 +608,51 @@ void main() { .startOutgoingOlmSessions([deviceKeys], checkSignature: false); expect(matrix.olmSessions.length, 1); expect(matrix.olmSessions.entries.first.key, - "3C5BFWi2Y8MaVvjM8M22DBmh24PmgR0nPvJOIArzgyI"); + '3C5BFWi2Y8MaVvjM8M22DBmh24PmgR0nPvJOIArzgyI'); } }); test('sendToDevice', () async { await matrix.sendToDevice( [deviceKeys], - "m.message", + 'm.message', { - "msgtype": "m.text", - "body": "Hello world", + 'msgtype': 'm.text', + 'body': 'Hello world', }); }); test('Logout when token is unknown', () async { - Future loginStateFuture = - matrix.onLoginStateChanged.stream.first; + var loginStateFuture = matrix.onLoginStateChanged.stream.first; try { await matrix.jsonRequest( - type: HTTPType.DELETE, action: "/unknown/token"); + type: HTTPType.DELETE, action: '/unknown/token'); } on MatrixException catch (exception) { expect(exception.error, MatrixError.M_UNKNOWN_TOKEN); } - LoginState state = await loginStateFuture; + var state = await loginStateFuture; expect(state, LoginState.loggedOut); expect(matrix.isLogged(), false); }); test('Test the fake store api', () async { - Client client1 = Client("testclient", debug: true); + var client1 = Client('testclient', debug: true); client1.httpClient = FakeMatrixApi(); - FakeStore fakeStore = FakeStore(client1, {}); + var fakeStore = FakeStore(client1, {}); client1.storeAPI = fakeStore; client1.connect( - newToken: "abc123", - newUserID: "@test:fakeServer.notExisting", - newHomeserver: "https://fakeServer.notExisting", - newDeviceName: "Text Matrix Client", - newDeviceID: "GHTYAJCE", + newToken: 'abc123', + newUserID: '@test:fakeServer.notExisting', + newHomeserver: 'https://fakeServer.notExisting', + newDeviceName: 'Text Matrix Client', + newDeviceID: 'GHTYAJCE', newMatrixVersions: [ - "r0.0.1", - "r0.1.0", - "r0.2.0", - "r0.3.0", - "r0.4.0", - "r0.5.0" + 'r0.0.1', + 'r0.1.0', + 'r0.2.0', + 'r0.3.0', + 'r0.4.0', + 'r0.5.0' ], newLazyLoadMembers: true, newOlmAccount: pickledOlmAccount, @@ -677,7 +670,7 @@ void main() { expect(client1.isLogged(), true); expect(client1.rooms.length, 2); - Client client2 = Client("testclient", debug: true); + var client2 = Client('testclient', debug: true); client2.httpClient = FakeMatrixApi(); client2.storeAPI = FakeStore(client2, fakeStore.storeMap); diff --git a/test/device_keys_list_test.dart b/test/device_keys_list_test.dart index af78f14..08b83e2 100644 --- a/test/device_keys_list_test.dart +++ b/test/device_keys_list_test.dart @@ -28,38 +28,38 @@ import 'package:test/test.dart'; void main() { /// All Tests related to device keys - group("Device keys", () { - test("fromJson", () async { - Map rawJson = { - "user_id": "@alice:example.com", - "device_id": "JLAFKJWSCS", - "algorithms": ["m.olm.v1.curve25519-aes-sha2", "m.megolm.v1.aes-sha2"], - "keys": { - "curve25519:JLAFKJWSCS": - "3C5BFWi2Y8MaVvjM8M22DBmh24PmgR0nPvJOIArzgyI", - "ed25519:JLAFKJWSCS": "lEuiRJBit0IG6nUf5pUzWTUEsRVVe/HJkoKuEww9ULI" + group('Device keys', () { + test('fromJson', () async { + var rawJson = { + 'user_id': '@alice:example.com', + 'device_id': 'JLAFKJWSCS', + 'algorithms': ['m.olm.v1.curve25519-aes-sha2', 'm.megolm.v1.aes-sha2'], + 'keys': { + 'curve25519:JLAFKJWSCS': + '3C5BFWi2Y8MaVvjM8M22DBmh24PmgR0nPvJOIArzgyI', + 'ed25519:JLAFKJWSCS': 'lEuiRJBit0IG6nUf5pUzWTUEsRVVe/HJkoKuEww9ULI' }, - "signatures": { - "@alice:example.com": { - "ed25519:JLAFKJWSCS": - "dSO80A01XiigH3uBiDVx/EjzaoycHcjq9lfQX0uWsqxl2giMIiSPR8a4d291W1ihKJL/a+myXS367WT6NAIcBA" + 'signatures': { + '@alice:example.com': { + 'ed25519:JLAFKJWSCS': + 'dSO80A01XiigH3uBiDVx/EjzaoycHcjq9lfQX0uWsqxl2giMIiSPR8a4d291W1ihKJL/a+myXS367WT6NAIcBA' } }, - "unsigned": {"device_display_name": "Alice's mobile phone"}, - "verified": false, - "blocked": true, + 'unsigned': {'device_display_name': "Alice's mobile phone"}, + 'verified': false, + 'blocked': true, }; - Map rawListJson = { - "user_id": "@alice:example.com", - "outdated": true, - "device_keys": {"JLAFKJWSCS": rawJson}, + var rawListJson = { + 'user_id': '@alice:example.com', + 'outdated': true, + 'device_keys': {'JLAFKJWSCS': rawJson}, }; - Map userDeviceKeys = { - "@alice:example.com": DeviceKeysList.fromJson(rawListJson), + var userDeviceKeys = { + '@alice:example.com': DeviceKeysList.fromJson(rawListJson), }; - Map userDeviceKeyRaw = { - "@alice:example.com": rawListJson, + var userDeviceKeyRaw = { + '@alice:example.com': rawListJson, }; expect(json.encode(DeviceKeys.fromJson(rawJson).toJson()), @@ -67,7 +67,7 @@ void main() { expect(json.encode(DeviceKeysList.fromJson(rawListJson).toJson()), json.encode(rawListJson)); - Map mapFromRaw = {}; + var mapFromRaw = {}; for (final rawListEntry in userDeviceKeyRaw.entries) { mapFromRaw[rawListEntry.key] = DeviceKeysList.fromJson(rawListEntry.value); diff --git a/test/event_test.dart b/test/event_test.dart index 574a648..56c5a08 100644 --- a/test/event_test.dart +++ b/test/event_test.dart @@ -31,34 +31,34 @@ import 'fake_matrix_api.dart'; void main() { /// All Tests related to the Event - group("Event", () { - final int timestamp = DateTime.now().millisecondsSinceEpoch; - final String id = "!4fsdfjisjf:server.abc"; - final String senderID = "@alice:server.abc"; - final String type = "m.room.message"; - final String msgtype = "m.text"; - final String body = "Hello World"; - final String formatted_body = "Hello World"; + group('Event', () { + final timestamp = DateTime.now().millisecondsSinceEpoch; + final id = '!4fsdfjisjf:server.abc'; + final senderID = '@alice:server.abc'; + final type = 'm.room.message'; + final msgtype = 'm.text'; + final body = 'Hello World'; + final formatted_body = 'Hello World'; - final String contentJson = + final contentJson = '{"msgtype":"$msgtype","body":"$body","formatted_body":"$formatted_body","m.relates_to":{"m.in_reply_to":{"event_id":"\$1234:example.com"}}}'; - Map jsonObj = { - "event_id": id, - "sender": senderID, - "origin_server_ts": timestamp, - "type": type, - "room_id": "1234", - "status": 2, - "content": contentJson, + var jsonObj = { + 'event_id': id, + 'sender': senderID, + 'origin_server_ts': timestamp, + 'type': type, + 'room_id': '1234', + 'status': 2, + 'content': contentJson, }; - test("Create from json", () async { - Event event = Event.fromJson(jsonObj, null); - jsonObj.remove("status"); - jsonObj["content"] = json.decode(contentJson); + test('Create from json', () async { + var event = Event.fromJson(jsonObj, null); + jsonObj.remove('status'); + jsonObj['content'] = json.decode(contentJson); expect(event.toJson(), jsonObj); - jsonObj["content"] = contentJson; + jsonObj['content'] = contentJson; expect(event.eventId, id); expect(event.senderId, senderID); @@ -68,181 +68,180 @@ void main() { expect(event.body, body); expect(event.type, EventTypes.Message); expect(event.isReply, true); - jsonObj["state_key"] = ""; - Event state = Event.fromJson(jsonObj, null); + jsonObj['state_key'] = ''; + var state = Event.fromJson(jsonObj, null); expect(state.eventId, id); - expect(state.stateKey, ""); + expect(state.stateKey, ''); expect(state.status, 2); }); - test("Test all EventTypes", () async { + test('Test all EventTypes', () async { Event event; - jsonObj["type"] = "m.room.avatar"; + jsonObj['type'] = 'm.room.avatar'; event = Event.fromJson(jsonObj, null); expect(event.type, EventTypes.RoomAvatar); - jsonObj["type"] = "m.room.name"; + jsonObj['type'] = 'm.room.name'; event = Event.fromJson(jsonObj, null); expect(event.type, EventTypes.RoomName); - jsonObj["type"] = "m.room.topic"; + jsonObj['type'] = 'm.room.topic'; event = Event.fromJson(jsonObj, null); expect(event.type, EventTypes.RoomTopic); - jsonObj["type"] = "m.room.aliases"; + jsonObj['type'] = 'm.room.aliases'; event = Event.fromJson(jsonObj, null); expect(event.type, EventTypes.RoomAliases); - jsonObj["type"] = "m.room.canonical_alias"; + jsonObj['type'] = 'm.room.canonical_alias'; event = Event.fromJson(jsonObj, null); expect(event.type, EventTypes.RoomCanonicalAlias); - jsonObj["type"] = "m.room.create"; + jsonObj['type'] = 'm.room.create'; event = Event.fromJson(jsonObj, null); expect(event.type, EventTypes.RoomCreate); - jsonObj["type"] = "m.room.join_rules"; + jsonObj['type'] = 'm.room.join_rules'; event = Event.fromJson(jsonObj, null); expect(event.type, EventTypes.RoomJoinRules); - jsonObj["type"] = "m.room.member"; + jsonObj['type'] = 'm.room.member'; event = Event.fromJson(jsonObj, null); expect(event.type, EventTypes.RoomMember); - jsonObj["type"] = "m.room.power_levels"; + jsonObj['type'] = 'm.room.power_levels'; event = Event.fromJson(jsonObj, null); expect(event.type, EventTypes.RoomPowerLevels); - jsonObj["type"] = "m.room.guest_access"; + jsonObj['type'] = 'm.room.guest_access'; event = Event.fromJson(jsonObj, null); expect(event.type, EventTypes.GuestAccess); - jsonObj["type"] = "m.room.history_visibility"; + jsonObj['type'] = 'm.room.history_visibility'; event = Event.fromJson(jsonObj, null); expect(event.type, EventTypes.HistoryVisibility); - jsonObj["type"] = "m.room.message"; - jsonObj["content"] = json.decode(jsonObj["content"]); + jsonObj['type'] = 'm.room.message'; + jsonObj['content'] = json.decode(jsonObj['content']); - jsonObj["content"]["msgtype"] = "m.notice"; + jsonObj['content']['msgtype'] = 'm.notice'; event = Event.fromJson(jsonObj, null); expect(event.messageType, MessageTypes.Notice); - jsonObj["content"]["msgtype"] = "m.emote"; + jsonObj['content']['msgtype'] = 'm.emote'; event = Event.fromJson(jsonObj, null); expect(event.messageType, MessageTypes.Emote); - jsonObj["content"]["msgtype"] = "m.image"; + jsonObj['content']['msgtype'] = 'm.image'; event = Event.fromJson(jsonObj, null); expect(event.messageType, MessageTypes.Image); - jsonObj["content"]["msgtype"] = "m.video"; + jsonObj['content']['msgtype'] = 'm.video'; event = Event.fromJson(jsonObj, null); expect(event.messageType, MessageTypes.Video); - jsonObj["content"]["msgtype"] = "m.audio"; + jsonObj['content']['msgtype'] = 'm.audio'; event = Event.fromJson(jsonObj, null); expect(event.messageType, MessageTypes.Audio); - jsonObj["content"]["msgtype"] = "m.file"; + jsonObj['content']['msgtype'] = 'm.file'; event = Event.fromJson(jsonObj, null); expect(event.messageType, MessageTypes.File); - jsonObj["content"]["msgtype"] = "m.location"; + jsonObj['content']['msgtype'] = 'm.location'; event = Event.fromJson(jsonObj, null); expect(event.messageType, MessageTypes.Location); - jsonObj["type"] = "m.room.message"; - jsonObj["content"]["msgtype"] = "m.text"; - jsonObj["content"]["m.relates_to"] = {}; - jsonObj["content"]["m.relates_to"]["m.in_reply_to"] = { - "event_id": "1234", + jsonObj['type'] = 'm.room.message'; + jsonObj['content']['msgtype'] = 'm.text'; + jsonObj['content']['m.relates_to'] = {}; + jsonObj['content']['m.relates_to']['m.in_reply_to'] = { + 'event_id': '1234', }; event = Event.fromJson(jsonObj, null); expect(event.messageType, MessageTypes.Reply); }); - test("redact", () async { - final Room room = - Room(id: "1234", client: Client("testclient", debug: true)); - final Map redactionEventJson = { - "content": {"reason": "Spamming"}, - "event_id": "143273582443PhrSn:example.org", - "origin_server_ts": 1432735824653, - "redacts": id, - "room_id": "1234", - "sender": "@example:example.org", - "type": "m.room.redaction", - "unsigned": {"age": 1234} + test('redact', () async { + final room = Room(id: '1234', client: Client('testclient', debug: true)); + final redactionEventJson = { + 'content': {'reason': 'Spamming'}, + 'event_id': '143273582443PhrSn:example.org', + 'origin_server_ts': 1432735824653, + 'redacts': id, + 'room_id': '1234', + 'sender': '@example:example.org', + 'type': 'm.room.redaction', + 'unsigned': {'age': 1234} }; - Event redactedBecause = Event.fromJson(redactionEventJson, room); - Event event = Event.fromJson(jsonObj, room); + var redactedBecause = Event.fromJson(redactionEventJson, room); + var event = Event.fromJson(jsonObj, room); event.setRedactionEvent(redactedBecause); expect(event.redacted, true); expect(event.redactedBecause.toJson(), redactedBecause.toJson()); expect(event.content.isEmpty, true); - redactionEventJson.remove("redacts"); - expect(event.unsigned["redacted_because"], redactionEventJson); + redactionEventJson.remove('redacts'); + expect(event.unsigned['redacted_because'], redactionEventJson); }); - test("remove", () async { - Event event = Event.fromJson( - jsonObj, Room(id: "1234", client: Client("testclient", debug: true))); - final bool removed1 = await event.remove(); + test('remove', () async { + var event = Event.fromJson( + jsonObj, Room(id: '1234', client: Client('testclient', debug: true))); + final removed1 = await event.remove(); event.status = 0; - final bool removed2 = await event.remove(); + final removed2 = await event.remove(); expect(removed1, false); expect(removed2, true); }); - test("sendAgain", () async { - Client matrix = Client("testclient", debug: true); + test('sendAgain', () async { + var matrix = Client('testclient', debug: true); matrix.httpClient = FakeMatrixApi(); - await matrix.checkServer("https://fakeServer.notExisting"); - await matrix.login("test", "1234"); + await matrix.checkServer('https://fakeServer.notExisting'); + await matrix.login('test', '1234'); - Event event = Event.fromJson( - jsonObj, Room(id: "!1234:example.com", client: matrix)); - final String resp1 = await event.sendAgain(); + var event = Event.fromJson( + jsonObj, Room(id: '!1234:example.com', client: matrix)); + final resp1 = await event.sendAgain(); event.status = -1; - final String resp2 = await event.sendAgain(txid: "1234"); + final resp2 = await event.sendAgain(txid: '1234'); expect(resp1, null); - expect(resp2, "42"); + expect(resp2, '42'); }); - test("requestKey", () async { - Client matrix = Client("testclient", debug: true); + test('requestKey', () async { + var matrix = Client('testclient', debug: true); matrix.httpClient = FakeMatrixApi(); - await matrix.checkServer("https://fakeServer.notExisting"); - await matrix.login("test", "1234"); + await matrix.checkServer('https://fakeServer.notExisting'); + await matrix.login('test', '1234'); - Event event = Event.fromJson( - jsonObj, Room(id: "!1234:example.com", client: matrix)); + var event = Event.fromJson( + jsonObj, Room(id: '!1234:example.com', client: matrix)); String exception; try { await event.requestKey(); } catch (e) { exception = e; } - expect(exception, "Session key not unknown"); + expect(exception, 'Session key not unknown'); event = Event.fromJson({ - "event_id": id, - "sender": senderID, - "origin_server_ts": timestamp, - "type": "m.room.encrypted", - "room_id": "1234", - "status": 2, - "content": json.encode({ - "msgtype": "m.bad.encrypted", - "body": DecryptError.UNKNOWN_SESSION, - "algorithm": "m.megolm.v1.aes-sha2", - "ciphertext": "AwgAEnACgAkLmt6qF84IK++J7UDH2Za1YVchHyprqTqsg...", - "device_id": "RJYKSTBOIE", - "sender_key": "IlRMeOPX2e0MurIyfWEucYBRVOEEUMrOHqn/8mLqMjA", - "session_id": "X3lUlvLELLYxeTx4yOVu6UDpasGEVO0Jbu+QFnm0cKQ" + 'event_id': id, + 'sender': senderID, + 'origin_server_ts': timestamp, + 'type': 'm.room.encrypted', + 'room_id': '1234', + 'status': 2, + 'content': json.encode({ + 'msgtype': 'm.bad.encrypted', + 'body': DecryptError.UNKNOWN_SESSION, + 'algorithm': 'm.megolm.v1.aes-sha2', + 'ciphertext': 'AwgAEnACgAkLmt6qF84IK++J7UDH2Za1YVchHyprqTqsg...', + 'device_id': 'RJYKSTBOIE', + 'sender_key': 'IlRMeOPX2e0MurIyfWEucYBRVOEEUMrOHqn/8mLqMjA', + 'session_id': 'X3lUlvLELLYxeTx4yOVu6UDpasGEVO0Jbu+QFnm0cKQ' }), - }, Room(id: "!1234:example.com", client: matrix)); + }, Room(id: '!1234:example.com', client: matrix)); await event.requestKey(); }); diff --git a/test/fake_matrix_api.dart b/test/fake_matrix_api.dart index 899904d..e00f579 100644 --- a/test/fake_matrix_api.dart +++ b/test/fake_matrix_api.dart @@ -31,44 +31,44 @@ class FakeMatrixApi extends MockClient { FakeMatrixApi() : super((request) async { // Collect data from Request - String action = - request.url.path.split("/_matrix")[1] + "?" + request.url.query; - if (action.endsWith("?")) action = action.replaceAll("?", ""); - final String method = request.method; + var action = + request.url.path.split('/_matrix')[1] + '?' + request.url.query; + if (action.endsWith('?')) action = action.replaceAll('?', ''); + final method = request.method; final dynamic data = - method == "GET" ? request.url.queryParameters : request.body; + method == 'GET' ? request.url.queryParameters : request.body; var res = {}; //print("$method request to $action with Data: $data"); // Sync requests with timeout - if (data is Map && data["timeout"] is String) { + if (data is Map && data['timeout'] is String) { await Future.delayed(Duration(seconds: 5)); } - if (request.url.origin != "https://fakeserver.notexisting") { + if (request.url.origin != 'https://fakeserver.notexisting') { return Response( - "Not found...", 404); + 'Not found...', 404); } // Call API if (api.containsKey(method) && api[method].containsKey(action)) { res = api[method][action](data); - if (res.containsKey("errcode")) { + if (res.containsKey('errcode')) { return Response(json.encode(res), 405); } - } else if (method == "PUT" && - action.contains("/client/r0/sendToDevice/")) { + } else if (method == 'PUT' && + action.contains('/client/r0/sendToDevice/')) { return Response(json.encode({}), 200); - } else if (method == "GET" && - action.contains("/client/r0/rooms/") && - action.contains("/state/m.room.member/")) { - res = {"displayname": ""}; + } else if (method == 'GET' && + action.contains('/client/r0/rooms/') && + action.contains('/state/m.room.member/')) { + res = {'displayname': ''}; return Response(json.encode(res), 200); } else { res = { - "errcode": "M_UNRECOGNIZED", - "error": "Unrecognized request" + 'errcode': 'M_UNRECOGNIZED', + 'error': 'Unrecognized request' }; return Response(json.encode(res), 405); } @@ -77,395 +77,395 @@ class FakeMatrixApi extends MockClient { }); static Map messagesResponse = { - "start": "t47429-4392820_219380_26003_2265", - "end": "t47409-4357353_219380_26003_2265", - "chunk": [ + 'start': 't47429-4392820_219380_26003_2265', + 'end': 't47409-4357353_219380_26003_2265', + 'chunk': [ { - "content": { - "body": "This is an example text message", - "msgtype": "m.text", - "format": "org.matrix.custom.html", - "formatted_body": "This is an example text message" + 'content': { + 'body': 'This is an example text message', + 'msgtype': 'm.text', + 'format': 'org.matrix.custom.html', + 'formatted_body': 'This is an example text message' }, - "type": "m.room.message", - "event_id": "3143273582443PhrSn:example.org", - "room_id": "!1234:example.com", - "sender": "@example:example.org", - "origin_server_ts": 1432735824653, - "unsigned": {"age": 1234} + 'type': 'm.room.message', + 'event_id': '3143273582443PhrSn:example.org', + 'room_id': '!1234:example.com', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234} }, { - "content": {"name": "The room name"}, - "type": "m.room.name", - "event_id": "2143273582443PhrSn:example.org", - "room_id": "!1234:example.com", - "sender": "@example:example.org", - "origin_server_ts": 1432735824653, - "unsigned": {"age": 1234}, - "state_key": "" + 'content': {'name': 'The room name'}, + 'type': 'm.room.name', + 'event_id': '2143273582443PhrSn:example.org', + 'room_id': '!1234:example.com', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234}, + 'state_key': '' }, { - "content": { - "body": "Gangnam Style", - "url": "mxc://example.org/a526eYUSFFxlgbQYZmo442", - "info": { - "thumbnail_url": "mxc://example.org/FHyPlCeYUSFFxlgbQYZmoEoe", - "thumbnail_info": { - "mimetype": "image/jpeg", - "size": 46144, - "w": 300, - "h": 300 + 'content': { + 'body': 'Gangnam Style', + 'url': 'mxc://example.org/a526eYUSFFxlgbQYZmo442', + 'info': { + 'thumbnail_url': 'mxc://example.org/FHyPlCeYUSFFxlgbQYZmoEoe', + 'thumbnail_info': { + 'mimetype': 'image/jpeg', + 'size': 46144, + 'w': 300, + 'h': 300 }, - "w": 480, - "h": 320, - "duration": 2140786, - "size": 1563685, - "mimetype": "video/mp4" + 'w': 480, + 'h': 320, + 'duration': 2140786, + 'size': 1563685, + 'mimetype': 'video/mp4' }, - "msgtype": "m.video" + 'msgtype': 'm.video' }, - "type": "m.room.message", - "event_id": "1143273582443PhrSn:example.org", - "room_id": "!1234:example.com", - "sender": "@example:example.org", - "origin_server_ts": 1432735824653, - "unsigned": {"age": 1234} + 'type': 'm.room.message', + 'event_id': '1143273582443PhrSn:example.org', + 'room_id': '!1234:example.com', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234} } ] }; static Map syncResponse = { - "next_batch": Random().nextDouble().toString(), - "presence": { - "events": [ + 'next_batch': Random().nextDouble().toString(), + 'presence': { + 'events': [ { - "sender": "@alice:example.com", - "type": "m.presence", - "content": {"presence": "online"} + 'sender': '@alice:example.com', + 'type': 'm.presence', + 'content': {'presence': 'online'} } ] }, - "account_data": { - "events": [ + 'account_data': { + 'events': [ { - "content": { - "global": { - "content": [ + 'content': { + 'global': { + 'content': [ { - "actions": [ - "notify", - {"set_tweak": "sound", "value": "default"}, - {"set_tweak": "highlight"} + 'actions': [ + 'notify', + {'set_tweak': 'sound', 'value': 'default'}, + {'set_tweak': 'highlight'} ], - "default": true, - "enabled": true, - "pattern": "alice", - "rule_id": ".m.rule.contains_user_name" + 'default': true, + 'enabled': true, + 'pattern': 'alice', + 'rule_id': '.m.rule.contains_user_name' } ], - "override": [ + 'override': [ { - "actions": ["dont_notify"], - "conditions": [], - "default": true, - "enabled": false, - "rule_id": ".m.rule.master" + 'actions': ['dont_notify'], + 'conditions': [], + 'default': true, + 'enabled': false, + 'rule_id': '.m.rule.master' }, { - "actions": ["dont_notify"], - "conditions": [ + 'actions': ['dont_notify'], + 'conditions': [ { - "key": "content.msgtype", - "kind": "event_match", - "pattern": "m.notice" + 'key': 'content.msgtype', + 'kind': 'event_match', + 'pattern': 'm.notice' } ], - "default": true, - "enabled": true, - "rule_id": ".m.rule.suppress_notices" + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.suppress_notices' } ], - "room": [ + 'room': [ { - "actions": ["dont_notify"], - "conditions": [ + 'actions': ['dont_notify'], + 'conditions': [ { - "key": "room_id", - "kind": "event_match", - "pattern": "!localpart:server.abc", + 'key': 'room_id', + 'kind': 'event_match', + 'pattern': '!localpart:server.abc', } ], - "default": true, - "enabled": true, - "rule_id": "!localpart:server.abc" + 'default': true, + 'enabled': true, + 'rule_id': '!localpart:server.abc' } ], - "sender": [], - "underride": [ + 'sender': [], + 'underride': [ { - "actions": [ - "notify", - {"set_tweak": "sound", "value": "ring"}, - {"set_tweak": "highlight", "value": false} + 'actions': [ + 'notify', + {'set_tweak': 'sound', 'value': 'ring'}, + {'set_tweak': 'highlight', 'value': false} ], - "conditions": [ + 'conditions': [ { - "key": "type", - "kind": "event_match", - "pattern": "m.call.invite" + 'key': 'type', + 'kind': 'event_match', + 'pattern': 'm.call.invite' } ], - "default": true, - "enabled": true, - "rule_id": ".m.rule.call" + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.call' }, { - "actions": [ - "notify", - {"set_tweak": "sound", "value": "default"}, - {"set_tweak": "highlight"} + 'actions': [ + 'notify', + {'set_tweak': 'sound', 'value': 'default'}, + {'set_tweak': 'highlight'} ], - "conditions": [ - {"kind": "contains_display_name"} + 'conditions': [ + {'kind': 'contains_display_name'} ], - "default": true, - "enabled": true, - "rule_id": ".m.rule.contains_display_name" + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.contains_display_name' }, { - "actions": [ - "notify", - {"set_tweak": "sound", "value": "default"}, - {"set_tweak": "highlight", "value": false} + 'actions': [ + 'notify', + {'set_tweak': 'sound', 'value': 'default'}, + {'set_tweak': 'highlight', 'value': false} ], - "conditions": [ - {"is": "2", "kind": "room_member_count"}, + 'conditions': [ + {'is': '2', 'kind': 'room_member_count'}, { - "key": "type", - "kind": "event_match", - "pattern": "m.room.message" + 'key': 'type', + 'kind': 'event_match', + 'pattern': 'm.room.message' } ], - "default": true, - "enabled": true, - "rule_id": ".m.rule.room_one_to_one" + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.room_one_to_one' }, { - "actions": [ - "notify", - {"set_tweak": "sound", "value": "default"}, - {"set_tweak": "highlight", "value": false} + 'actions': [ + 'notify', + {'set_tweak': 'sound', 'value': 'default'}, + {'set_tweak': 'highlight', 'value': false} ], - "conditions": [ + 'conditions': [ { - "key": "type", - "kind": "event_match", - "pattern": "m.room.member" + 'key': 'type', + 'kind': 'event_match', + 'pattern': 'm.room.member' }, { - "key": "content.membership", - "kind": "event_match", - "pattern": "invite" + 'key': 'content.membership', + 'kind': 'event_match', + 'pattern': 'invite' }, { - "key": "state_key", - "kind": "event_match", - "pattern": "@alice:example.com" + 'key': 'state_key', + 'kind': 'event_match', + 'pattern': '@alice:example.com' } ], - "default": true, - "enabled": true, - "rule_id": ".m.rule.invite_for_me" + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.invite_for_me' }, { - "actions": [ - "notify", - {"set_tweak": "highlight", "value": false} + 'actions': [ + 'notify', + {'set_tweak': 'highlight', 'value': false} ], - "conditions": [ + 'conditions': [ { - "key": "type", - "kind": "event_match", - "pattern": "m.room.member" + 'key': 'type', + 'kind': 'event_match', + 'pattern': 'm.room.member' } ], - "default": true, - "enabled": true, - "rule_id": ".m.rule.member_event" + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.member_event' }, { - "actions": [ - "notify", - {"set_tweak": "highlight", "value": false} + 'actions': [ + 'notify', + {'set_tweak': 'highlight', 'value': false} ], - "conditions": [ + 'conditions': [ { - "key": "type", - "kind": "event_match", - "pattern": "m.room.message" + 'key': 'type', + 'kind': 'event_match', + 'pattern': 'm.room.message' } ], - "default": true, - "enabled": true, - "rule_id": ".m.rule.message" + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.message' } ] } }, - "type": "m.push_rules" + 'type': 'm.push_rules' }, { - "type": "org.example.custom.config", - "content": {"custom_config_key": "custom_config_value"} + 'type': 'org.example.custom.config', + 'content': {'custom_config_key': 'custom_config_value'} }, { - "content": { - "@bob:example.com": [ - "!726s6s6q:example.com", - "!hgfedcba:example.com" + 'content': { + '@bob:example.com': [ + '!726s6s6q:example.com', + '!hgfedcba:example.com' ] }, - "type": "m.direct" + 'type': 'm.direct' }, ] }, - "to_device": { - "events": [ + 'to_device': { + 'events': [ { - "sender": "@alice:example.com", - "type": "m.new_device", - "content": { - "device_id": "XYZABCDE", - "rooms": ["!726s6s6q:example.com"] + 'sender': '@alice:example.com', + 'type': 'm.new_device', + 'content': { + 'device_id': 'XYZABCDE', + 'rooms': ['!726s6s6q:example.com'] } }, { - "sender": "@alice:example.com", - "content": { - "algorithm": "m.megolm.v1.aes-sha2", - "room_id": "!726s6s6q:example.com", - "session_id": "ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU", - "session_key": - "AgAAAAAQcQ6XrFJk6Prm8FikZDqfry/NbDz8Xw7T6e+/9Yf/q3YHIPEQlzv7IZMNcYb51ifkRzFejVvtphS7wwG2FaXIp4XS2obla14iKISR0X74ugB2vyb1AydIHE/zbBQ1ic5s3kgjMFlWpu/S3FQCnCrv+DPFGEt3ERGWxIl3Bl5X53IjPyVkz65oljz2TZESwz0GH/QFvyOOm8ci0q/gceaF3S7Dmafg3dwTKYwcA5xkcc+BLyrLRzB6Hn+oMAqSNSscnm4mTeT5zYibIhrzqyUTMWr32spFtI9dNR/RFSzfCw" + 'sender': '@alice:example.com', + 'content': { + 'algorithm': 'm.megolm.v1.aes-sha2', + 'room_id': '!726s6s6q:example.com', + 'session_id': 'ciM/JWTPrmiWPPZNkRLDPQYf9AW/I46bxyLSr+Bx5oU', + 'session_key': + 'AgAAAAAQcQ6XrFJk6Prm8FikZDqfry/NbDz8Xw7T6e+/9Yf/q3YHIPEQlzv7IZMNcYb51ifkRzFejVvtphS7wwG2FaXIp4XS2obla14iKISR0X74ugB2vyb1AydIHE/zbBQ1ic5s3kgjMFlWpu/S3FQCnCrv+DPFGEt3ERGWxIl3Bl5X53IjPyVkz65oljz2TZESwz0GH/QFvyOOm8ci0q/gceaF3S7Dmafg3dwTKYwcA5xkcc+BLyrLRzB6Hn+oMAqSNSscnm4mTeT5zYibIhrzqyUTMWr32spFtI9dNR/RFSzfCw' }, - "type": "m.room_key" + 'type': 'm.room_key' }, ] }, - "rooms": { - "join": { - "!726s6s6q:example.com": { - "unread_notifications": { - "highlight_count": 2, - "notification_count": 2, + 'rooms': { + 'join': { + '!726s6s6q:example.com': { + 'unread_notifications': { + 'highlight_count': 2, + 'notification_count': 2, }, - "state": { - "events": [ + '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.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" + '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" + 'state_key': '', + 'origin_server_ts': 1417731086796, + 'event_id': '66697273743032:example.com' }, { - "sender": "@alice:example.com", - "type": "m.room.encryption", - "state_key": "", - "content": {"algorithm": "m.megolm.v1.aes-sha2"}, - "origin_server_ts": 1417731086795, - "event_id": "666972737430353:example.com" + 'sender': '@alice:example.com', + 'type': 'm.room.encryption', + 'state_key': '', + 'content': {'algorithm': 'm.megolm.v1.aes-sha2'}, + 'origin_server_ts': 1417731086795, + 'event_id': '666972737430353:example.com' }, ] }, - "timeline": { - "events": [ + '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': '@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" + '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" + 'limited': true, + 'prev_batch': 't34-23535_0_0' }, - "ephemeral": { - "events": [ + 'ephemeral': { + 'events': [ { - "type": "m.typing", - "content": { - "user_ids": ["@alice:example.com"] + 'type': 'm.typing', + 'content': { + 'user_ids': ['@alice:example.com'] } }, { - "content": { - "7365636s6r6432:example.com": { - "m.read": { - "@alice:example.com": {"ts": 1436451550453} + 'content': { + '7365636s6r6432:example.com': { + 'm.read': { + '@alice:example.com': {'ts': 1436451550453} } } }, - "room_id": "!726s6s6q:example.com", - "type": "m.receipt" + 'room_id': '!726s6s6q:example.com', + 'type': 'm.receipt' } ] }, - "account_data": { - "events": [ + 'account_data': { + 'events': [ { - "type": "m.tag", - "content": { - "tags": { - "work": {"order": 1} + 'type': 'm.tag', + 'content': { + 'tags': { + 'work': {'order': 1} } } }, { - "type": "org.example.custom.room.config", - "content": {"custom_config_key": "custom_config_value"} + 'type': 'org.example.custom.room.config', + 'content': {'custom_config_key': 'custom_config_value'} } ] } } }, - "invite": { - "!696r7674:example.com": { - "invite_state": { - "events": [ + '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.name', + 'state_key': '', + 'content': {'name': 'My Room Name'} }, { - "sender": "@alice:example.com", - "type": "m.room.member", - "state_key": "@bob:example.com", - "content": {"membership": "invite"} + 'sender': '@alice:example.com', + 'type': 'm.room.member', + 'state_key': '@bob:example.com', + 'content': {'membership': 'invite'} } ] } @@ -475,69 +475,69 @@ class FakeMatrixApi extends MockClient { }; static Map archiveSyncResponse = { - "next_batch": Random().nextDouble().toString(), - "presence": {"events": []}, - "account_data": {"events": []}, - "to_device": {"events": []}, - "rooms": { - "join": {}, - "invite": {}, - "leave": { - "!5345234234:example.com": { - "timeline": { - "events": [ + 'next_batch': Random().nextDouble().toString(), + 'presence': {'events': []}, + 'account_data': {'events': []}, + 'to_device': {'events': []}, + 'rooms': { + 'join': {}, + 'invite': {}, + 'leave': { + '!5345234234:example.com': { + 'timeline': { + 'events': [ { - "content": { - "body": "This is an example text message", - "msgtype": "m.text", - "format": "org.matrix.custom.html", - "formatted_body": "This is an example text message" + 'content': { + 'body': 'This is an example text message', + 'msgtype': 'm.text', + 'format': 'org.matrix.custom.html', + 'formatted_body': 'This is an example text message' }, - "type": "m.room.message", - "event_id": "143273582443PhrSn:example.org", - "room_id": "!5345234234:example.com", - "sender": "@example:example.org", - "origin_server_ts": 1432735824653, - "unsigned": {"age": 1234} + 'type': 'm.room.message', + 'event_id': '143273582443PhrSn:example.org', + 'room_id': '!5345234234:example.com', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234} }, ] }, - "state": { - "events": [ + 'state': { + 'events': [ { - "content": {"name": "The room name"}, - "type": "m.room.name", - "event_id": "2143273582443PhrSn:example.org", - "room_id": "!5345234234:example.com", - "sender": "@example:example.org", - "origin_server_ts": 1432735824653, - "unsigned": {"age": 1234}, - "state_key": "" + 'content': {'name': 'The room name'}, + 'type': 'm.room.name', + 'event_id': '2143273582443PhrSn:example.org', + 'room_id': '!5345234234:example.com', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234}, + 'state_key': '' }, ] }, - "account_data": { - "events": [ + 'account_data': { + 'events': [ { - "type": "test.type.data", - "content": {"foo": "bar"}, + 'type': 'test.type.data', + 'content': {'foo': 'bar'}, }, ], }, }, - "!5345234235:example.com": { - "timeline": {"events": []}, - "state": { - "events": [ + '!5345234235:example.com': { + 'timeline': {'events': []}, + 'state': { + 'events': [ { - "content": {"name": "The room name 2"}, - "type": "m.room.name", - "event_id": "2143273582443PhrSn:example.org", - "room_id": "!5345234235:example.com", - "sender": "@example:example.org", - "origin_server_ts": 1432735824653, - "unsigned": {"age": 1234}, - "state_key": "" + 'content': {'name': 'The room name 2'}, + 'type': 'm.room.name', + 'event_id': '2143273582443PhrSn:example.org', + 'room_id': '!5345234235:example.com', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234}, + 'state_key': '' }, ] } @@ -547,280 +547,280 @@ class FakeMatrixApi extends MockClient { }; static final Map> api = { - "GET": { - "/client/r0/devices": (var req) => { - "devices": [ + 'GET': { + '/client/r0/devices': (var req) => { + 'devices': [ { - "device_id": "QBUAZIFURK", - "display_name": "android", - "last_seen_ip": "1.2.3.4", - "last_seen_ts": 1474491775024 + 'device_id': 'QBUAZIFURK', + 'display_name': 'android', + 'last_seen_ip': '1.2.3.4', + 'last_seen_ts': 1474491775024 } ] }, - "/client/r0/rooms/1/state/m.room.member/@alice:example.com": (var req) => - {"displayname": "Alice"}, - "/client/r0/profile/@getme:example.com": (var req) => { - "avatar_url": "mxc://test", - "displayname": "You got me", + '/client/r0/rooms/1/state/m.room.member/@alice:example.com': (var req) => + {'displayname': 'Alice'}, + '/client/r0/profile/@getme:example.com': (var req) => { + 'avatar_url': 'mxc://test', + 'displayname': 'You got me', }, - "/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': (var req) => { - "avatar_url": "mxc://test", - "displayname": "You got me", + 'avatar_url': 'mxc://test', + 'displayname': 'You got me', }, - "/client/r0/rooms/!localpart:server.abc/event/1234": (var req) => { - "content": { - "body": "This is an example text message", - "msgtype": "m.text", - "format": "org.matrix.custom.html", - "formatted_body": "This is an example text message" + '/client/r0/rooms/!localpart:server.abc/event/1234': (var req) => { + 'content': { + 'body': 'This is an example text message', + 'msgtype': 'm.text', + 'format': 'org.matrix.custom.html', + 'formatted_body': 'This is an example text message' }, - "type": "m.room.message", - "event_id": "143273582443PhrSn:example.org", - "room_id": "!localpart:server.abc", - "sender": "@example:example.org", - "origin_server_ts": 1432735824653, - "unsigned": {"age": 1234} + 'type': 'm.room.message', + 'event_id': '143273582443PhrSn:example.org', + 'room_id': '!localpart:server.abc', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234} }, - "/client/r0/rooms/!localpart:server.abc/messages?from=&dir=b&limit=10&filter=%7B%22room%22:%7B%22state%22:%7B%22lazy_load_members%22:true%7D%7D%7D": + '/client/r0/rooms/!localpart:server.abc/messages?from=&dir=b&limit=10&filter=%7B%22room%22:%7B%22state%22:%7B%22lazy_load_members%22:true%7D%7D%7D': (var req) => messagesResponse, - "/client/r0/rooms/!1234:example.com/messages?from=1234&dir=b&limit=100&filter=%7B%22room%22:%7B%22state%22:%7B%22lazy_load_members%22:true%7D%7D%7D": + '/client/r0/rooms/!1234:example.com/messages?from=1234&dir=b&limit=100&filter=%7B%22room%22:%7B%22state%22:%7B%22lazy_load_members%22:true%7D%7D%7D': (var req) => messagesResponse, - "/client/versions": (var req) => { - "versions": [ - "r0.0.1", - "r0.1.0", - "r0.2.0", - "r0.3.0", - "r0.4.0", - "r0.5.0" + '/client/versions': (var req) => { + 'versions': [ + 'r0.0.1', + 'r0.1.0', + 'r0.2.0', + 'r0.3.0', + 'r0.4.0', + 'r0.5.0' ], - "unstable_features": {"m.lazy_load_members": true}, + 'unstable_features': {'m.lazy_load_members': true}, }, - "/client/r0/login": (var req) => { - "flows": [ - {"type": "m.login.password"} + '/client/r0/login': (var req) => { + 'flows': [ + {'type': 'm.login.password'} ] }, - "/client/r0/rooms/!696r7674:example.com/members": (var req) => { - "chunk": [ + '/client/r0/rooms/!696r7674:example.com/members': (var req) => { + 'chunk': [ { - "content": { - "membership": "join", - "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF", - "displayname": "Alice Margatroid" + 'content': { + 'membership': 'join', + 'avatar_url': 'mxc://example.org/SEsfnsuifSDFSSEF', + 'displayname': 'Alice Margatroid' }, - "type": "m.room.member", - "event_id": "§143273582443PhrSn:example.org", - "room_id": "!636q39766251:example.com", - "sender": "@alice:example.com", - "origin_server_ts": 1432735824653, - "unsigned": {"age": 1234}, - "state_key": "@alice:example.com" + 'type': 'm.room.member', + 'event_id': '§143273582443PhrSn:example.org', + 'room_id': '!636q39766251:example.com', + 'sender': '@alice:example.com', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234}, + 'state_key': '@alice:example.com' } ] }, - "/client/r0/rooms/!726s6s6q:example.com/members": (var req) => { - "chunk": [ + '/client/r0/rooms/!726s6s6q:example.com/members': (var req) => { + 'chunk': [ { - "content": { - "membership": "join", - "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF", - "displayname": "Alice Margatroid" + 'content': { + 'membership': 'join', + 'avatar_url': 'mxc://example.org/SEsfnsuifSDFSSEF', + 'displayname': 'Alice Margatroid' }, - "type": "m.room.member", - "event_id": "§143273582443PhrSn:example.org", - "room_id": "!636q39766251:example.com", - "sender": "@alice:example.com", - "origin_server_ts": 1432735824653, - "unsigned": {"age": 1234}, - "state_key": "@alice:example.com" + 'type': 'm.room.member', + 'event_id': '§143273582443PhrSn:example.org', + 'room_id': '!636q39766251:example.com', + 'sender': '@alice:example.com', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234}, + 'state_key': '@alice:example.com' } ] }, - "/client/r0/rooms/!localpart:server.abc/members": (var req) => { - "chunk": [ + '/client/r0/rooms/!localpart:server.abc/members': (var req) => { + 'chunk': [ { - "content": { - "membership": "join", - "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF", - "displayname": "Alice Margatroid" + 'content': { + 'membership': 'join', + 'avatar_url': 'mxc://example.org/SEsfnsuifSDFSSEF', + 'displayname': 'Alice Margatroid' }, - "type": "m.room.member", - "event_id": "§143273582443PhrSn:example.org", - "room_id": "!636q39766251:example.com", - "sender": "@example:example.org", - "origin_server_ts": 1432735824653, - "unsigned": {"age": 1234}, - "state_key": "@alice:example.org" + 'type': 'm.room.member', + 'event_id': '§143273582443PhrSn:example.org', + 'room_id': '!636q39766251:example.com', + 'sender': '@example:example.org', + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234}, + 'state_key': '@alice:example.org' } ] }, - "/client/r0/pushrules/": (var req) => { - "global": { - "content": [ + '/client/r0/pushrules/': (var req) => { + 'global': { + 'content': [ { - "actions": [ - "notify", - {"set_tweak": "sound", "value": "default"}, - {"set_tweak": "highlight"} + 'actions': [ + 'notify', + {'set_tweak': 'sound', 'value': 'default'}, + {'set_tweak': 'highlight'} ], - "default": true, - "enabled": true, - "pattern": "alice", - "rule_id": ".m.rule.contains_user_name" + 'default': true, + 'enabled': true, + 'pattern': 'alice', + 'rule_id': '.m.rule.contains_user_name' } ], - "override": [ + 'override': [ { - "actions": ["dont_notify"], - "conditions": [], - "default": true, - "enabled": false, - "rule_id": ".m.rule.master" + 'actions': ['dont_notify'], + 'conditions': [], + 'default': true, + 'enabled': false, + 'rule_id': '.m.rule.master' }, { - "actions": ["dont_notify"], - "conditions": [ + 'actions': ['dont_notify'], + 'conditions': [ { - "key": "content.msgtype", - "kind": "event_match", - "pattern": "m.notice" + 'key': 'content.msgtype', + 'kind': 'event_match', + 'pattern': 'm.notice' } ], - "default": true, - "enabled": true, - "rule_id": ".m.rule.suppress_notices" + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.suppress_notices' } ], - "room": [], - "sender": [], - "underride": [ + 'room': [], + 'sender': [], + 'underride': [ { - "actions": [ - "notify", - {"set_tweak": "sound", "value": "ring"}, - {"set_tweak": "highlight", "value": false} + 'actions': [ + 'notify', + {'set_tweak': 'sound', 'value': 'ring'}, + {'set_tweak': 'highlight', 'value': false} ], - "conditions": [ + 'conditions': [ { - "key": "type", - "kind": "event_match", - "pattern": "m.call.invite" + 'key': 'type', + 'kind': 'event_match', + 'pattern': 'm.call.invite' } ], - "default": true, - "enabled": true, - "rule_id": ".m.rule.call" + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.call' }, { - "actions": [ - "notify", - {"set_tweak": "sound", "value": "default"}, - {"set_tweak": "highlight"} + 'actions': [ + 'notify', + {'set_tweak': 'sound', 'value': 'default'}, + {'set_tweak': 'highlight'} ], - "conditions": [ - {"kind": "contains_display_name"} + 'conditions': [ + {'kind': 'contains_display_name'} ], - "default": true, - "enabled": true, - "rule_id": ".m.rule.contains_display_name" + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.contains_display_name' }, { - "actions": [ - "notify", - {"set_tweak": "sound", "value": "default"}, - {"set_tweak": "highlight", "value": false} + 'actions': [ + 'notify', + {'set_tweak': 'sound', 'value': 'default'}, + {'set_tweak': 'highlight', 'value': false} ], - "conditions": [ - {"is": "2", "kind": "room_member_count"} + 'conditions': [ + {'is': '2', 'kind': 'room_member_count'} ], - "default": true, - "enabled": true, - "rule_id": ".m.rule.room_one_to_one" + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.room_one_to_one' }, { - "actions": [ - "notify", - {"set_tweak": "sound", "value": "default"}, - {"set_tweak": "highlight", "value": false} + 'actions': [ + 'notify', + {'set_tweak': 'sound', 'value': 'default'}, + {'set_tweak': 'highlight', 'value': false} ], - "conditions": [ + 'conditions': [ { - "key": "type", - "kind": "event_match", - "pattern": "m.room.member" + 'key': 'type', + 'kind': 'event_match', + 'pattern': 'm.room.member' }, { - "key": "content.membership", - "kind": "event_match", - "pattern": "invite" + 'key': 'content.membership', + 'kind': 'event_match', + 'pattern': 'invite' }, { - "key": "state_key", - "kind": "event_match", - "pattern": "@alice:example.com" + 'key': 'state_key', + 'kind': 'event_match', + 'pattern': '@alice:example.com' } ], - "default": true, - "enabled": true, - "rule_id": ".m.rule.invite_for_me" + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.invite_for_me' }, { - "actions": [ - "notify", - {"set_tweak": "highlight", "value": false} + 'actions': [ + 'notify', + {'set_tweak': 'highlight', 'value': false} ], - "conditions": [ + 'conditions': [ { - "key": "type", - "kind": "event_match", - "pattern": "m.room.member" + 'key': 'type', + 'kind': 'event_match', + 'pattern': 'm.room.member' } ], - "default": true, - "enabled": true, - "rule_id": ".m.rule.member_event" + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.member_event' }, { - "actions": [ - "notify", - {"set_tweak": "highlight", "value": false} + 'actions': [ + 'notify', + {'set_tweak': 'highlight', 'value': false} ], - "conditions": [ + 'conditions': [ { - "key": "type", - "kind": "event_match", - "pattern": "m.room.message" + 'key': 'type', + 'kind': 'event_match', + 'pattern': 'm.room.message' } ], - "default": true, - "enabled": true, - "rule_id": ".m.rule.message" + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.message' } ] } }, - "/client/r0/sync?filter=%7B%22room%22:%7B%22include_leave%22:true,%22timeline%22:%7B%22limit%22:10%7D%7D%7D&timeout=0": + '/client/r0/sync?filter=%7B%22room%22:%7B%22include_leave%22:true,%22timeline%22:%7B%22limit%22:10%7D%7D%7D&timeout=0': (var req) => archiveSyncResponse, - "/client/r0/sync?filter=%7B%22room%22:%7B%22state%22:%7B%22lazy_load_members%22:true%7D%7D%7D": + '/client/r0/sync?filter=%7B%22room%22:%7B%22state%22:%7B%22lazy_load_members%22:true%7D%7D%7D': (var req) => syncResponse, - "/client/r0/register/available?username=testuser": (var req) => - {"available": true}, + '/client/r0/register/available?username=testuser': (var req) => + {'available': true}, }, - "POST": { - "/client/r0/keys/claim": (var req) => { - "failures": {}, - "one_time_keys": { - "@alice:example.com": { - "JLAFKJWSCS": { - "signed_curve25519:AAAAHg": { - "key": "zKbLg+NrIjpnagy+pIY6uPL4ZwEG2v+8F9lmgsnlZzs", - "signatures": { - "@alice:example.com": { - "ed25519:JLAFKJWSCS": - "FLWxXqGbwrb8SM3Y795eB6OA8bwBcoMZFXBqnTn58AYWZSqiD45tlBVcDa2L7RwdKXebW/VzDlnfVJ+9jok1Bw" + 'POST': { + '/client/r0/keys/claim': (var req) => { + 'failures': {}, + 'one_time_keys': { + '@alice:example.com': { + 'JLAFKJWSCS': { + 'signed_curve25519:AAAAHg': { + 'key': 'zKbLg+NrIjpnagy+pIY6uPL4ZwEG2v+8F9lmgsnlZzs', + 'signatures': { + '@alice:example.com': { + 'ed25519:JLAFKJWSCS': + 'FLWxXqGbwrb8SM3Y795eB6OA8bwBcoMZFXBqnTn58AYWZSqiD45tlBVcDa2L7RwdKXebW/VzDlnfVJ+9jok1Bw' } } } @@ -828,102 +828,102 @@ class FakeMatrixApi extends MockClient { } } }, - "/client/r0/keys/upload": (var req) => { - "one_time_key_counts": { - "curve25519": 10, - "signed_curve25519": 100, + '/client/r0/keys/upload': (var req) => { + 'one_time_key_counts': { + 'curve25519': 10, + 'signed_curve25519': 100, } }, - "/client/r0/keys/query": (var req) => { - "failures": {}, - "device_keys": { - "@alice:example.com": { - "JLAFKJWSCS": { - "user_id": "@alice:example.com", - "device_id": "JLAFKJWSCS", - "algorithms": [ - "m.olm.v1.curve25519-aes-sha2", - "m.megolm.v1.aes-sha2" + '/client/r0/keys/query': (var req) => { + 'failures': {}, + 'device_keys': { + '@alice:example.com': { + 'JLAFKJWSCS': { + 'user_id': '@alice:example.com', + 'device_id': 'JLAFKJWSCS', + 'algorithms': [ + 'm.olm.v1.curve25519-aes-sha2', + 'm.megolm.v1.aes-sha2' ], - "keys": { - "curve25519:JLAFKJWSCS": - "3C5BFWi2Y8MaVvjM8M22DBmh24PmgR0nPvJOIArzgyI", - "ed25519:JLAFKJWSCS": - "lEuiRJBit0IG6nUf5pUzWTUEsRVVe/HJkoKuEww9ULI" + 'keys': { + 'curve25519:JLAFKJWSCS': + '3C5BFWi2Y8MaVvjM8M22DBmh24PmgR0nPvJOIArzgyI', + 'ed25519:JLAFKJWSCS': + 'lEuiRJBit0IG6nUf5pUzWTUEsRVVe/HJkoKuEww9ULI' }, - "signatures": { - "@alice:example.com": { - "ed25519:JLAFKJWSCS": - "dSO80A01XiigH3uBiDVx/EjzaoycHcjq9lfQX0uWsqxl2giMIiSPR8a4d291W1ihKJL/a+myXS367WT6NAIcBA" + 'signatures': { + '@alice:example.com': { + 'ed25519:JLAFKJWSCS': + 'dSO80A01XiigH3uBiDVx/EjzaoycHcjq9lfQX0uWsqxl2giMIiSPR8a4d291W1ihKJL/a+myXS367WT6NAIcBA' } }, - "unsigned": {"device_display_name": "Alice's mobile phone"} + 'unsigned': {'device_display_name': "Alice's mobile phone"} } } } }, - "/client/r0/register": (var req) => {"user_id": "@testuser:example.com"}, - "/client/r0/register?kind=user": (var req) => - {"user_id": "@testuser:example.com"}, - "/client/r0/register?kind=guest": (var req) => - {"user_id": "@testuser:example.com"}, - "/client/r0/user/@test:fakeServer.notExisting/openid/request_token": + '/client/r0/register': (var req) => {'user_id': '@testuser:example.com'}, + '/client/r0/register?kind=user': (var req) => + {'user_id': '@testuser:example.com'}, + '/client/r0/register?kind=guest': (var req) => + {'user_id': '@testuser:example.com'}, + '/client/r0/user/@test:fakeServer.notExisting/openid/request_token': (var req) => { - "access_token": "SomeT0kenHere", - "token_type": "Bearer", - "matrix_server_name": "example.com", - "expires_in": 3600 + 'access_token': 'SomeT0kenHere', + 'token_type': 'Bearer', + 'matrix_server_name': 'example.com', + 'expires_in': 3600 }, - "/client/r0/login": (var req) => { - "user_id": "@test:fakeServer.notExisting", - "access_token": "abc123", - "device_id": "GHTYAJCE" + '/client/r0/login': (var req) => { + 'user_id': '@test:fakeServer.notExisting', + 'access_token': 'abc123', + 'device_id': 'GHTYAJCE' }, - "/media/r0/upload?filename=file.jpeg": (var req) => - {"content_uri": "mxc://example.com/AQwafuaFswefuhsfAFAgsw"}, - "/client/r0/logout": (var reqI) => {}, - "/client/r0/pushers/set": (var reqI) => {}, - "/client/r0/join/1234": (var reqI) => {"room_id": "1234"}, - "/client/r0/logout/all": (var reqI) => {}, - "/client/r0/createRoom": (var reqI) => { - "room_id": "!1234:fakeServer.notExisting", + '/media/r0/upload?filename=file.jpeg': (var req) => + {'content_uri': 'mxc://example.com/AQwafuaFswefuhsfAFAgsw'}, + '/client/r0/logout': (var reqI) => {}, + '/client/r0/pushers/set': (var reqI) => {}, + '/client/r0/join/1234': (var reqI) => {'room_id': '1234'}, + '/client/r0/logout/all': (var reqI) => {}, + '/client/r0/createRoom': (var reqI) => { + 'room_id': '!1234:fakeServer.notExisting', }, - "/client/r0/rooms/!localpart:server.abc/read_markers": (var reqI) => {}, - "/client/r0/rooms/!localpart:server.abc/kick": (var reqI) => {}, - "/client/r0/rooms/!localpart:server.abc/ban": (var reqI) => {}, - "/client/r0/rooms/!localpart:server.abc/unban": (var reqI) => {}, - "/client/r0/rooms/!localpart:server.abc/invite": (var reqI) => {}, + '/client/r0/rooms/!localpart:server.abc/read_markers': (var reqI) => {}, + '/client/r0/rooms/!localpart:server.abc/kick': (var reqI) => {}, + '/client/r0/rooms/!localpart:server.abc/ban': (var reqI) => {}, + '/client/r0/rooms/!localpart:server.abc/unban': (var reqI) => {}, + '/client/r0/rooms/!localpart:server.abc/invite': (var reqI) => {}, }, - "PUT": { - "/client/r0/rooms/!localpart:server.abc/send/m.room.message/testtxid": + 'PUT': { + '/client/r0/rooms/!localpart:server.abc/send/m.room.message/testtxid': (var reqI) => { - "event_id": "42", + 'event_id': '42', }, - "/client/r0/rooms/!1234:example.com/send/m.room.message/1234": + '/client/r0/rooms/!1234:example.com/send/m.room.message/1234': (var reqI) => { - "event_id": "42", + 'event_id': '42', }, - "/client/r0/profile/@test:fakeServer.notExisting/avatar_url": + '/client/r0/profile/@test:fakeServer.notExisting/avatar_url': (var reqI) => {}, - "/client/r0/rooms/!localpart:server.abc/state/m.room.avatar/": - (var reqI) => {"event_id": "YUwRidLecu:example.com"}, - "/client/r0/rooms/!localpart:server.abc/state/m.room.name": (var reqI) => + '/client/r0/rooms/!localpart:server.abc/state/m.room.avatar/': + (var reqI) => {'event_id': 'YUwRidLecu:example.com'}, + '/client/r0/rooms/!localpart:server.abc/state/m.room.name': (var reqI) => { - "event_id": "42", + 'event_id': '42', }, - "/client/r0/rooms/!localpart:server.abc/state/m.room.topic": (var reqI) => + '/client/r0/rooms/!localpart:server.abc/state/m.room.topic': (var reqI) => { - "event_id": "42", + 'event_id': '42', }, - "/client/r0/rooms/!localpart:server.abc/state/m.room.power_levels": + '/client/r0/rooms/!localpart:server.abc/state/m.room.power_levels': (var reqI) => { - "event_id": "42", + 'event_id': '42', }, - "/client/r0/user/@test:fakeServer.notExisting/account_data/m.direct": + '/client/r0/user/@test:fakeServer.notExisting/account_data/m.direct': (var reqI) => {}, }, - "DELETE": { - "/unknown/token": (var req) => {"errcode": "M_UNKNOWN_TOKEN"}, + 'DELETE': { + '/unknown/token': (var req) => {'errcode': 'M_UNKNOWN_TOKEN'}, }, }; } diff --git a/test/fake_store.dart b/test/fake_store.dart index 0d97516..ab54cae 100644 --- a/test/fake_store.dart +++ b/test/fake_store.dart @@ -5,83 +5,91 @@ import 'package:famedlysdk/famedlysdk.dart'; class FakeStore implements StoreAPI { /// Whether this is a simple store which only stores the client credentials and /// end to end encryption stuff or the whole sync payloads. + @override final bool extended = false; Map storeMap = {}; /// Link back to the client. + @override Client client; FakeStore(this.client, this.storeMap) { _init(); } - _init() async { + Future _init() async { final credentialsStr = await getItem(client.clientName); if (credentialsStr == null || credentialsStr.isEmpty) { client.onLoginStateChanged.add(LoginState.loggedOut); return; } - print("[Matrix] Restoring account credentials"); + print('[Matrix] Restoring account credentials'); final Map credentials = json.decode(credentialsStr); client.connect( - newDeviceID: credentials["deviceID"], - newDeviceName: credentials["deviceName"], - newHomeserver: credentials["homeserver"], - newLazyLoadMembers: credentials["lazyLoadMembers"], - newMatrixVersions: List.from(credentials["matrixVersions"]), - newToken: credentials["token"], - newUserID: credentials["userID"], - newPrevBatch: credentials["prev_batch"], - newOlmAccount: credentials["olmAccount"], + newDeviceID: credentials['deviceID'], + newDeviceName: credentials['deviceName'], + newHomeserver: credentials['homeserver'], + newLazyLoadMembers: credentials['lazyLoadMembers'], + newMatrixVersions: List.from(credentials['matrixVersions']), + newToken: credentials['token'], + newUserID: credentials['userID'], + newPrevBatch: credentials['prev_batch'], + newOlmAccount: credentials['olmAccount'], ); } /// Will be automatically called when the client is logged in successfully. + @override Future storeClient() async { - final Map credentials = { - "deviceID": client.deviceID, - "deviceName": client.deviceName, - "homeserver": client.homeserver, - "lazyLoadMembers": client.lazyLoadMembers, - "matrixVersions": client.matrixVersions, - "token": client.accessToken, - "userID": client.userID, - "olmAccount": client.pickledOlmAccount, + final credentials = { + 'deviceID': client.deviceID, + 'deviceName': client.deviceName, + 'homeserver': client.homeserver, + 'lazyLoadMembers': client.lazyLoadMembers, + 'matrixVersions': client.matrixVersions, + 'token': client.accessToken, + 'userID': client.userID, + 'olmAccount': client.pickledOlmAccount, }; await setItem(client.clientName, json.encode(credentials)); return; } /// Clears all tables from the database. + @override Future clear() async { storeMap = {}; return; } + @override Future getItem(String key) async { return storeMap[key]; } + @override Future setItem(String key, String value) async { storeMap[key] = value; return; } - String get _UserDeviceKeysKey => "${client.clientName}.user_device_keys"; + String get _UserDeviceKeysKey => '${client.clientName}.user_device_keys'; + @override Future> getUserDeviceKeys() async { final deviceKeysListString = await getItem(_UserDeviceKeysKey); if (deviceKeysListString == null) return {}; Map rawUserDeviceKeys = json.decode(deviceKeysListString); - Map userDeviceKeys = {}; + var userDeviceKeys = {}; for (final entry in rawUserDeviceKeys.entries) { userDeviceKeys[entry.key] = DeviceKeysList.fromJson(entry.value); } return userDeviceKeys; } + @override Future storeUserDeviceKeys( Map userDeviceKeys) async { await setItem(_UserDeviceKeysKey, json.encode(userDeviceKeys)); diff --git a/test/matrix_id_string_extension_test.dart b/test/matrix_id_string_extension_test.dart index b33865c..4b0b425 100644 --- a/test/matrix_id_string_extension_test.dart +++ b/test/matrix_id_string_extension_test.dart @@ -26,25 +26,25 @@ import 'package:famedlysdk/src/utils/matrix_id_string_extension.dart'; void main() { /// All Tests related to the ChatTime - group("Matrix ID String Extension", () { - test("Matrix ID String Extension", () async { - final String mxId = "@test:example.com"; + group('Matrix ID String Extension', () { + test('Matrix ID String Extension', () async { + final mxId = '@test:example.com'; expect(mxId.isValidMatrixId, true); - expect("#test:example.com".isValidMatrixId, true); - expect("!test:example.com".isValidMatrixId, true); - expect("+test:example.com".isValidMatrixId, true); - expect("\$test:example.com".isValidMatrixId, true); - expect("test:example.com".isValidMatrixId, false); - expect("@testexample.com".isValidMatrixId, false); - expect("@:example.com".isValidMatrixId, false); - expect("@test:".isValidMatrixId, false); - expect(mxId.sigil, "@"); - expect("#test:example.com".sigil, "#"); - expect("!test:example.com".sigil, "!"); - expect("+test:example.com".sigil, "+"); - expect("\$test:example.com".sigil, "\$"); - expect(mxId.localpart, "test"); - expect(mxId.domain, "example.com"); + expect('#test:example.com'.isValidMatrixId, true); + expect('!test:example.com'.isValidMatrixId, true); + expect('+test:example.com'.isValidMatrixId, true); + expect('\$test:example.com'.isValidMatrixId, true); + expect('test:example.com'.isValidMatrixId, false); + expect('@testexample.com'.isValidMatrixId, false); + expect('@:example.com'.isValidMatrixId, false); + expect('@test:'.isValidMatrixId, false); + expect(mxId.sigil, '@'); + expect('#test:example.com'.sigil, '#'); + expect('!test:example.com'.sigil, '!'); + expect('+test:example.com'.sigil, '+'); + expect('\$test:example.com'.sigil, '\$'); + expect(mxId.localpart, 'test'); + expect(mxId.domain, 'example.com'); }); }); } diff --git a/test/mx_content_test.dart b/test/mx_content_test.dart index 38a5ef3..5161737 100644 --- a/test/mx_content_test.dart +++ b/test/mx_content_test.dart @@ -29,30 +29,30 @@ import 'fake_matrix_api.dart'; void main() { /// All Tests related to the MxContent - group("MxContent", () { - test("Formatting", () async { - Client client = Client("testclient"); + group('MxContent', () { + test('Formatting', () async { + var client = Client('testclient'); client.httpClient = FakeMatrixApi(); - await client.checkServer("https://fakeserver.notexisting"); - final String mxc = "mxc://exampleserver.abc/abcdefghijklmn"; - final MxContent content = MxContent(mxc); + await client.checkServer('https://fakeserver.notexisting'); + final mxc = 'mxc://exampleserver.abc/abcdefghijklmn'; + final content = MxContent(mxc); expect(content.getDownloadLink(client), - "${client.homeserver}/_matrix/media/r0/download/exampleserver.abc/abcdefghijklmn"); + '${client.homeserver}/_matrix/media/r0/download/exampleserver.abc/abcdefghijklmn'); expect(content.getThumbnail(client, width: 50, height: 50), - "${client.homeserver}/_matrix/media/r0/thumbnail/exampleserver.abc/abcdefghijklmn?width=50&height=50&method=crop"); + '${client.homeserver}/_matrix/media/r0/thumbnail/exampleserver.abc/abcdefghijklmn?width=50&height=50&method=crop'); expect( content.getThumbnail(client, width: 50, height: 50, method: ThumbnailMethod.scale), - "${client.homeserver}/_matrix/media/r0/thumbnail/exampleserver.abc/abcdefghijklmn?width=50&height=50&method=scale"); + '${client.homeserver}/_matrix/media/r0/thumbnail/exampleserver.abc/abcdefghijklmn?width=50&height=50&method=scale'); }); - test("Not crashing if null", () async { - Client client = Client("testclient"); + test('Not crashing if null', () async { + var client = Client('testclient'); client.httpClient = FakeMatrixApi(); - await client.checkServer("https://fakeserver.notexisting"); - final MxContent content = MxContent(null); + await client.checkServer('https://fakeserver.notexisting'); + final content = MxContent(null); expect(content.getDownloadLink(client), - "${client.homeserver}/_matrix/media/r0/download/"); + '${client.homeserver}/_matrix/media/r0/download/'); }); }); } diff --git a/test/presence_test.dart b/test/presence_test.dart index e0ace9c..788936e 100644 --- a/test/presence_test.dart +++ b/test/presence_test.dart @@ -26,26 +26,26 @@ import 'package:test/test.dart'; void main() { /// All Tests related to the ChatTime - group("Presence", () { - test("fromJson", () async { - Map rawPresence = { - "content": { - "avatar_url": "mxc://localhost:wefuiwegh8742w", - "currently_active": false, - "last_active_ago": 2478593, - "presence": "online", - "status_msg": "Making cupcakes" + group('Presence', () { + test('fromJson', () async { + var rawPresence = { + 'content': { + 'avatar_url': 'mxc://localhost:wefuiwegh8742w', + 'currently_active': false, + 'last_active_ago': 2478593, + 'presence': 'online', + 'status_msg': 'Making cupcakes' }, - "sender": "@example:localhost", - "type": "m.presence" + 'sender': '@example:localhost', + 'type': 'm.presence' }; - Presence presence = Presence.fromJson(rawPresence); - expect(presence.sender, "@example:localhost"); - expect(presence.avatarUrl.mxc, "mxc://localhost:wefuiwegh8742w"); + var presence = Presence.fromJson(rawPresence); + expect(presence.sender, '@example:localhost'); + expect(presence.avatarUrl.mxc, 'mxc://localhost:wefuiwegh8742w'); expect(presence.currentlyActive, false); expect(presence.lastActiveAgo, 2478593); expect(presence.presence, PresenceType.online); - expect(presence.statusMsg, "Making cupcakes"); + expect(presence.statusMsg, 'Making cupcakes'); }); }); } diff --git a/test/push_rules_test.dart b/test/push_rules_test.dart index 37caf4c..37e35f1 100644 --- a/test/push_rules_test.dart +++ b/test/push_rules_test.dart @@ -26,154 +26,154 @@ import 'package:test/test.dart'; void main() { /// All Tests related to the MxContent - group("PushRules", () { - test("Create", () async { - final Map json = { - "global": { - "content": [ + group('PushRules', () { + test('Create', () async { + final json = { + 'global': { + 'content': [ { - "actions": [ - "notify", - {"set_tweak": "sound", "value": "default"}, - {"set_tweak": "highlight"} + 'actions': [ + 'notify', + {'set_tweak': 'sound', 'value': 'default'}, + {'set_tweak': 'highlight'} ], - "default": true, - "enabled": true, - "pattern": "alice", - "rule_id": ".m.rule.contains_user_name" + 'default': true, + 'enabled': true, + 'pattern': 'alice', + 'rule_id': '.m.rule.contains_user_name' } ], - "override": [ + 'override': [ { - "actions": ["dont_notify"], - "conditions": [], - "default": true, - "enabled": false, - "rule_id": ".m.rule.master" + 'actions': ['dont_notify'], + 'conditions': [], + 'default': true, + 'enabled': false, + 'rule_id': '.m.rule.master' }, { - "actions": ["dont_notify"], - "conditions": [ + 'actions': ['dont_notify'], + 'conditions': [ { - "key": "content.msgtype", - "kind": "event_match", - "pattern": "m.notice" + 'key': 'content.msgtype', + 'kind': 'event_match', + 'pattern': 'm.notice' } ], - "default": true, - "enabled": true, - "rule_id": ".m.rule.suppress_notices" + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.suppress_notices' } ], - "room": [], - "sender": [], - "underride": [ + 'room': [], + 'sender': [], + 'underride': [ { - "actions": [ - "notify", - {"set_tweak": "sound", "value": "ring"}, - {"set_tweak": "highlight", "value": false} + 'actions': [ + 'notify', + {'set_tweak': 'sound', 'value': 'ring'}, + {'set_tweak': 'highlight', 'value': false} ], - "conditions": [ + 'conditions': [ { - "key": "type", - "kind": "event_match", - "pattern": "m.call.invite" + 'key': 'type', + 'kind': 'event_match', + 'pattern': 'm.call.invite' } ], - "default": true, - "enabled": true, - "rule_id": ".m.rule.call" + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.call' }, { - "actions": [ - "notify", - {"set_tweak": "sound", "value": "default"}, - {"set_tweak": "highlight"} + 'actions': [ + 'notify', + {'set_tweak': 'sound', 'value': 'default'}, + {'set_tweak': 'highlight'} ], - "conditions": [ - {"kind": "contains_display_name"} + 'conditions': [ + {'kind': 'contains_display_name'} ], - "default": true, - "enabled": true, - "rule_id": ".m.rule.contains_display_name" + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.contains_display_name' }, { - "actions": [ - "notify", - {"set_tweak": "sound", "value": "default"}, - {"set_tweak": "highlight", "value": false} + 'actions': [ + 'notify', + {'set_tweak': 'sound', 'value': 'default'}, + {'set_tweak': 'highlight', 'value': false} ], - "conditions": [ - {"kind": "room_member_count", "is": "2"}, + 'conditions': [ + {'kind': 'room_member_count', 'is': '2'}, { - "kind": "event_match", - "key": "type", - "pattern": "m.room.message" + 'kind': 'event_match', + 'key': 'type', + 'pattern': 'm.room.message' } ], - "default": true, - "enabled": true, - "rule_id": ".m.rule.room_one_to_one" + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.room_one_to_one' }, { - "actions": [ - "notify", - {"set_tweak": "sound", "value": "default"}, - {"set_tweak": "highlight", "value": false} + 'actions': [ + 'notify', + {'set_tweak': 'sound', 'value': 'default'}, + {'set_tweak': 'highlight', 'value': false} ], - "conditions": [ + 'conditions': [ { - "key": "type", - "kind": "event_match", - "pattern": "m.room.member" + 'key': 'type', + 'kind': 'event_match', + 'pattern': 'm.room.member' }, { - "key": "content.membership", - "kind": "event_match", - "pattern": "invite" + 'key': 'content.membership', + 'kind': 'event_match', + 'pattern': 'invite' }, { - "key": "state_key", - "kind": "event_match", - "pattern": "@alice:example.com" + 'key': 'state_key', + 'kind': 'event_match', + 'pattern': '@alice:example.com' } ], - "default": true, - "enabled": true, - "rule_id": ".m.rule.invite_for_me" + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.invite_for_me' }, { - "actions": [ - "notify", - {"set_tweak": "highlight", "value": false} + 'actions': [ + 'notify', + {'set_tweak': 'highlight', 'value': false} ], - "conditions": [ + 'conditions': [ { - "key": "type", - "kind": "event_match", - "pattern": "m.room.member" + 'key': 'type', + 'kind': 'event_match', + 'pattern': 'm.room.member' } ], - "default": true, - "enabled": true, - "rule_id": ".m.rule.member_event" + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.member_event' }, { - "actions": [ - "notify", - {"set_tweak": "highlight", "value": false} + 'actions': [ + 'notify', + {'set_tweak': 'highlight', 'value': false} ], - "conditions": [ + 'conditions': [ { - "key": "type", - "kind": "event_match", - "pattern": "m.room.message" + 'key': 'type', + 'kind': 'event_match', + 'pattern': 'm.room.message' } ], - "default": true, - "enabled": true, - "rule_id": ".m.rule.message" + 'default': true, + 'enabled': true, + 'rule_id': '.m.rule.message' } ] } diff --git a/test/room_key_request_test.dart b/test/room_key_request_test.dart index f7b1ce0c..cc400f7 100644 --- a/test/room_key_request_test.dart +++ b/test/room_key_request_test.dart @@ -29,39 +29,39 @@ import 'fake_store.dart'; void main() { /// All Tests related to device keys - group("Room Key Request", () { - test("fromJson", () async { - Map rawJson = { - "content": { - "action": "request", - "body": { - "algorithm": "m.megolm.v1.aes-sha2", - "room_id": "!726s6s6q:example.com", - "sender_key": "RF3s+E7RkTQTGF2d8Deol0FkQvgII2aJDf3/Jp5mxVU", - "session_id": "X3lUlvLELLYxeTx4yOVu6UDpasGEVO0Jbu+QFnm0cKQ" + group('Room Key Request', () { + test('fromJson', () async { + var rawJson = { + 'content': { + 'action': 'request', + 'body': { + 'algorithm': 'm.megolm.v1.aes-sha2', + 'room_id': '!726s6s6q:example.com', + 'sender_key': 'RF3s+E7RkTQTGF2d8Deol0FkQvgII2aJDf3/Jp5mxVU', + 'session_id': 'X3lUlvLELLYxeTx4yOVu6UDpasGEVO0Jbu+QFnm0cKQ' }, - "request_id": "1495474790150.19", - "requesting_device_id": "JLAFKJWSCS" + 'request_id': '1495474790150.19', + 'requesting_device_id': 'JLAFKJWSCS' }, - "type": "m.room_key_request", - "sender": "@alice:example.com" + 'type': 'm.room_key_request', + 'sender': '@alice:example.com' }; - ToDeviceEvent toDeviceEvent = ToDeviceEvent.fromJson(rawJson); - expect(toDeviceEvent.content, rawJson["content"]); - expect(toDeviceEvent.sender, rawJson["sender"]); - expect(toDeviceEvent.type, rawJson["type"]); + var toDeviceEvent = ToDeviceEvent.fromJson(rawJson); + expect(toDeviceEvent.content, rawJson['content']); + expect(toDeviceEvent.sender, rawJson['sender']); + expect(toDeviceEvent.type, rawJson['type']); - Client matrix = Client("testclient", debug: true); + var matrix = Client('testclient', debug: true); matrix.httpClient = FakeMatrixApi(); matrix.storeAPI = FakeStore(matrix, {}); - await matrix.checkServer("https://fakeServer.notExisting"); - await matrix.login("test", "1234"); - Room room = matrix.getRoomById("!726s6s6q:example.com"); + await matrix.checkServer('https://fakeServer.notExisting'); + await matrix.login('test', '1234'); + var room = matrix.getRoomById('!726s6s6q:example.com'); if (matrix.encryptionEnabled) { await room.createOutboundGroupSession(); - rawJson["content"]["body"]["session_id"] = room.sessionKeys.keys.first; + rawJson['content']['body']['session_id'] = room.sessionKeys.keys.first; - RoomKeyRequest roomKeyRequest = RoomKeyRequest.fromToDeviceEvent( + var roomKeyRequest = RoomKeyRequest.fromToDeviceEvent( ToDeviceEvent.fromJson(rawJson), matrix); await roomKeyRequest.forwardKey(); } diff --git a/test/room_test.dart b/test/room_test.dart index df94a7e..609b2bd 100644 --- a/test/room_test.dart +++ b/test/room_test.dart @@ -24,7 +24,6 @@ import 'package:famedlysdk/src/client.dart'; import 'package:famedlysdk/src/event.dart'; import 'package:famedlysdk/src/room.dart'; -import 'package:famedlysdk/src/timeline.dart'; import 'package:famedlysdk/src/user.dart'; import 'package:famedlysdk/src/utils/matrix_file.dart'; import 'package:test/test.dart'; @@ -38,61 +37,61 @@ void main() { Room room; /// All Tests related to the Event - group("Room", () { + group('Room', () { test('Login', () async { - matrix = Client("testclient", debug: true); + matrix = Client('testclient', debug: true); matrix.httpClient = FakeMatrixApi(); - final bool checkResp = - await matrix.checkServer("https://fakeServer.notExisting"); + final checkResp = + await matrix.checkServer('https://fakeServer.notExisting'); - final bool loginResp = await matrix.login("test", "1234"); + final loginResp = await matrix.login('test', '1234'); expect(checkResp, true); expect(loginResp, true); }); - test("Create from json", () async { - final String id = "!localpart:server.abc"; - final Membership membership = Membership.join; - final int notificationCount = 2; - final int highlightCount = 1; - final List heroes = [ - "@alice:matrix.org", - "@bob:example.com", - "@charley:example.org" + test('Create from json', () async { + final id = '!localpart:server.abc'; + final membership = Membership.join; + final notificationCount = 2; + final highlightCount = 1; + final heroes = [ + '@alice:matrix.org', + '@bob:example.com', + '@charley:example.org' ]; - Map jsonObj = { - "room_id": id, - "membership": membership.toString().split('.').last, - "avatar_url": "", - "notification_count": notificationCount, - "highlight_count": highlightCount, - "prev_batch": "", - "joined_member_count": notificationCount, - "invited_member_count": notificationCount, - "heroes": heroes.join(","), + var jsonObj = { + 'room_id': id, + 'membership': membership.toString().split('.').last, + 'avatar_url': '', + 'notification_count': notificationCount, + 'highlight_count': highlightCount, + 'prev_batch': '', + 'joined_member_count': notificationCount, + 'invited_member_count': notificationCount, + 'heroes': heroes.join(','), }; Function states = () async => [ { - "content": {"join_rule": "public"}, - "event_id": "143273582443PhrSn:example.org", - "origin_server_ts": 1432735824653, - "room_id": id, - "sender": "@example:example.org", - "state_key": "", - "type": "m.room.join_rules", - "unsigned": {"age": 1234} + 'content': {'join_rule': 'public'}, + 'event_id': '143273582443PhrSn:example.org', + 'origin_server_ts': 1432735824653, + 'room_id': id, + 'sender': '@example:example.org', + 'state_key': '', + 'type': 'm.room.join_rules', + 'unsigned': {'age': 1234} } ]; Function roomAccountData = () async => [ { - "content": {"foo": "bar"}, - "room_id": id, - "type": "com.test.foo" + 'content': {'foo': 'bar'}, + 'room_id': id, + 'type': 'com.test.foo' } ]; @@ -110,131 +109,131 @@ void main() { expect(room.mJoinedMemberCount, notificationCount); expect(room.mInvitedMemberCount, notificationCount); expect(room.mHeroes, heroes); - expect(room.displayname, "alice, bob, charley"); - expect(room.getState("m.room.join_rules").content["join_rule"], "public"); - expect(room.roomAccountData["com.test.foo"].content["foo"], "bar"); + expect(room.displayname, 'alice, bob, charley'); + expect(room.getState('m.room.join_rules').content['join_rule'], 'public'); + expect(room.roomAccountData['com.test.foo'].content['foo'], 'bar'); - room.states["m.room.canonical_alias"] = Event( - senderId: "@test:example.com", - typeKey: "m.room.canonical_alias", + room.states['m.room.canonical_alias'] = Event( + senderId: '@test:example.com', + typeKey: 'm.room.canonical_alias', roomId: room.id, room: room, - eventId: "123", - content: {"alias": "#testalias:example.com"}, - stateKey: ""); - expect(room.displayname, "testalias"); - expect(room.canonicalAlias, "#testalias:example.com"); + eventId: '123', + content: {'alias': '#testalias:example.com'}, + stateKey: ''); + expect(room.displayname, 'testalias'); + expect(room.canonicalAlias, '#testalias:example.com'); - room.states["m.room.name"] = Event( - senderId: "@test:example.com", - typeKey: "m.room.name", + room.states['m.room.name'] = Event( + senderId: '@test:example.com', + typeKey: 'm.room.name', roomId: room.id, room: room, - eventId: "123", - content: {"name": "testname"}, - stateKey: ""); - expect(room.displayname, "testname"); + eventId: '123', + content: {'name': 'testname'}, + stateKey: ''); + expect(room.displayname, 'testname'); - expect(room.topic, ""); - room.states["m.room.topic"] = Event( - senderId: "@test:example.com", - typeKey: "m.room.topic", + expect(room.topic, ''); + room.states['m.room.topic'] = Event( + senderId: '@test:example.com', + typeKey: 'm.room.topic', roomId: room.id, room: room, - eventId: "123", - content: {"topic": "testtopic"}, - stateKey: ""); - expect(room.topic, "testtopic"); + eventId: '123', + content: {'topic': 'testtopic'}, + stateKey: ''); + expect(room.topic, 'testtopic'); - expect(room.avatar.mxc, ""); - room.states["m.room.avatar"] = Event( - senderId: "@test:example.com", - typeKey: "m.room.avatar", + expect(room.avatar.mxc, ''); + room.states['m.room.avatar'] = Event( + senderId: '@test:example.com', + typeKey: 'm.room.avatar', roomId: room.id, room: room, - eventId: "123", - content: {"url": "mxc://testurl"}, - stateKey: ""); - expect(room.avatar.mxc, "mxc://testurl"); - room.states["m.room.message"] = Event( - senderId: "@test:example.com", - typeKey: "m.room.message", + eventId: '123', + content: {'url': 'mxc://testurl'}, + stateKey: ''); + expect(room.avatar.mxc, 'mxc://testurl'); + room.states['m.room.message'] = Event( + senderId: '@test:example.com', + typeKey: 'm.room.message', roomId: room.id, room: room, - eventId: "12345", + eventId: '12345', time: DateTime.now(), - content: {"msgtype": "m.text", "body": "test"}, - stateKey: ""); - expect(room.lastEvent.eventId, "12345"); - expect(room.lastMessage, "test"); + content: {'msgtype': 'm.text', 'body': 'test'}, + stateKey: ''); + expect(room.lastEvent.eventId, '12345'); + expect(room.lastMessage, 'test'); expect(room.timeCreated, room.lastEvent.time); }); - test("sendReadReceipt", () async { - await room.sendReadReceipt("§1234:fakeServer.notExisting"); + test('sendReadReceipt', () async { + await room.sendReadReceipt('§1234:fakeServer.notExisting'); }); - test("requestParticipants", () async { - final List participants = await room.requestParticipants(); + test('requestParticipants', () async { + final participants = await room.requestParticipants(); expect(participants.length, 1); - User user = participants[0]; - expect(user.id, "@alice:example.org"); - expect(user.displayName, "Alice Margatroid"); + var user = participants[0]; + expect(user.id, '@alice:example.org'); + expect(user.displayName, 'Alice Margatroid'); expect(user.membership, Membership.join); - expect(user.avatarUrl.mxc, "mxc://example.org/SEsfnsuifSDFSSEF"); - expect(user.room.id, "!localpart:server.abc"); + expect(user.avatarUrl.mxc, 'mxc://example.org/SEsfnsuifSDFSSEF'); + expect(user.room.id, '!localpart:server.abc'); }); - test("getEventByID", () async { - final Event event = await room.getEventById("1234"); - expect(event.eventId, "143273582443PhrSn:example.org"); + test('getEventByID', () async { + final event = await room.getEventById('1234'); + expect(event.eventId, '143273582443PhrSn:example.org'); }); - test("setName", () async { - final String eventId = await room.setName("Testname"); - expect(eventId, "42"); + test('setName', () async { + final eventId = await room.setName('Testname'); + expect(eventId, '42'); }); - test("setDescription", () async { - final String eventId = await room.setDescription("Testname"); - expect(eventId, "42"); + test('setDescription', () async { + final eventId = await room.setDescription('Testname'); + expect(eventId, '42'); }); - test("kick", () async { - await room.kick("Testname"); + test('kick', () async { + await room.kick('Testname'); }); - test("ban", () async { - await room.ban("Testname"); + test('ban', () async { + await room.ban('Testname'); }); - test("unban", () async { - await room.unban("Testname"); + test('unban', () async { + await room.unban('Testname'); }); - test("PowerLevels", () async { - room.states["m.room.power_levels"] = Event( - senderId: "@test:example.com", - typeKey: "m.room.power_levels", + test('PowerLevels', () async { + room.states['m.room.power_levels'] = Event( + senderId: '@test:example.com', + typeKey: 'm.room.power_levels', roomId: room.id, room: room, - eventId: "123", + eventId: '123', content: { - "ban": 50, - "events": {"m.room.name": 100, "m.room.power_levels": 100}, - "events_default": 0, - "invite": 50, - "kick": 50, - "notifications": {"room": 20}, - "redact": 50, - "state_default": 50, - "users": {"@test:fakeServer.notExisting": 100}, - "users_default": 10 + 'ban': 50, + 'events': {'m.room.name': 100, 'm.room.power_levels': 100}, + 'events_default': 0, + 'invite': 50, + 'kick': 50, + 'notifications': {'room': 20}, + 'redact': 50, + 'state_default': 50, + 'users': {'@test:fakeServer.notExisting': 100}, + 'users_default': 10 }, - stateKey: ""); + stateKey: ''); expect(room.ownPowerLevel, 100); expect(room.getPowerLevelByUserId(matrix.userID), room.ownPowerLevel); - expect(room.getPowerLevelByUserId("@nouser:example.com"), 10); + expect(room.getPowerLevelByUserId('@nouser:example.com'), 10); expect(room.ownPowerLevel, 100); expect(room.canBan, true); expect(room.canInvite, true); @@ -243,31 +242,31 @@ void main() { expect(room.canSendDefaultMessages, true); expect(room.canSendDefaultStates, true); expect(room.canChangePowerLevel, true); - expect(room.canSendEvent("m.room.name"), true); - expect(room.canSendEvent("m.room.power_levels"), true); - expect(room.canSendEvent("m.room.member"), true); + expect(room.canSendEvent('m.room.name'), true); + expect(room.canSendEvent('m.room.power_levels'), true); + expect(room.canSendEvent('m.room.member'), true); expect(room.powerLevels, - room.states["m.room.power_levels"].content["users"]); + room.states['m.room.power_levels'].content['users']); - room.states["m.room.power_levels"] = Event( - senderId: "@test:example.com", - typeKey: "m.room.power_levels", + room.states['m.room.power_levels'] = Event( + senderId: '@test:example.com', + typeKey: 'm.room.power_levels', roomId: room.id, room: room, - eventId: "123abc", + eventId: '123abc', content: { - "ban": 50, - "events": {"m.room.name": 0, "m.room.power_levels": 100}, - "events_default": 0, - "invite": 50, - "kick": 50, - "notifications": {"room": 20}, - "redact": 50, - "state_default": 50, - "users": {}, - "users_default": 0 + 'ban': 50, + 'events': {'m.room.name': 0, 'm.room.power_levels': 100}, + 'events_default': 0, + 'invite': 50, + 'kick': 50, + 'notifications': {'room': 20}, + 'redact': 50, + 'state_default': 50, + 'users': {}, + 'users_default': 0 }, - stateKey: ""); + stateKey: ''); expect(room.ownPowerLevel, 0); expect(room.canBan, false); expect(room.canInvite, false); @@ -276,70 +275,69 @@ void main() { expect(room.canSendDefaultMessages, true); expect(room.canSendDefaultStates, false); expect(room.canChangePowerLevel, false); - expect(room.canSendEvent("m.room.name"), true); - expect(room.canSendEvent("m.room.power_levels"), false); - expect(room.canSendEvent("m.room.member"), false); - expect(room.canSendEvent("m.room.message"), true); - final String resp = - await room.setPower("@test:fakeServer.notExisting", 90); - expect(resp, "42"); + expect(room.canSendEvent('m.room.name'), true); + expect(room.canSendEvent('m.room.power_levels'), false); + expect(room.canSendEvent('m.room.member'), false); + expect(room.canSendEvent('m.room.message'), true); + final resp = await room.setPower('@test:fakeServer.notExisting', 90); + expect(resp, '42'); }); - test("invite", () async { - await room.invite("Testname"); + test('invite', () async { + await room.invite('Testname'); }); - test("getParticipants", () async { + test('getParticipants', () async { room.setState(Event( - senderId: "@alice:test.abc", - typeKey: "m.room.member", + senderId: '@alice:test.abc', + typeKey: 'm.room.member', roomId: room.id, room: room, - eventId: "12345", + eventId: '12345', time: DateTime.now(), - content: {"displayname": "alice"}, - stateKey: "@alice:test.abc")); - final List userList = room.getParticipants(); + content: {'displayname': 'alice'}, + stateKey: '@alice:test.abc')); + final userList = room.getParticipants(); expect(userList.length, 5); - expect(userList[3].displayName, "Alice Margatroid"); + expect(userList[3].displayName, 'Alice Margatroid'); }); - test("addToDirectChat", () async { - await room.addToDirectChat("Testname"); + test('addToDirectChat', () async { + await room.addToDirectChat('Testname'); }); - test("getTimeline", () async { - final Timeline timeline = await room.getTimeline(); + test('getTimeline', () async { + final timeline = await room.getTimeline(); expect(timeline.events, []); }); - test("getUserByMXID", () async { + test('getUserByMXID', () async { User user; try { - user = await room.getUserByMXID("@getme:example.com"); + user = await room.getUserByMXID('@getme:example.com'); } catch (_) {} - expect(user.stateKey, "@getme:example.com"); - expect(user.calcDisplayname(), "You got me"); + expect(user.stateKey, '@getme:example.com'); + expect(user.calcDisplayname(), 'You got me'); }); test('setAvatar', () async { - final MatrixFile testFile = - MatrixFile(bytes: Uint8List(0), path: "fake/path/file.jpeg"); + final testFile = + MatrixFile(bytes: Uint8List(0), path: 'fake/path/file.jpeg'); final dynamic resp = await room.setAvatar(testFile); - expect(resp, "YUwRidLecu:example.com"); + expect(resp, 'YUwRidLecu:example.com'); }); test('sendEvent', () async { final dynamic resp = await room.sendEvent( - {"msgtype": "m.text", "body": "hello world"}, - txid: "testtxid"); - expect(resp, "42"); + {'msgtype': 'm.text', 'body': 'hello world'}, + txid: 'testtxid'); + expect(resp, '42'); }); test('sendEvent', () async { final dynamic resp = - await room.sendTextEvent("Hello world", txid: "testtxid"); - expect(resp, "42"); + await room.sendTextEvent('Hello world', txid: 'testtxid'); + expect(resp, '42'); }); // Not working because there is no real file to test it... @@ -351,38 +349,38 @@ void main() { });*/ test('sendFileEvent', () async { - final MatrixFile testFile = - MatrixFile(bytes: Uint8List(0), path: "fake/path/file.jpeg"); + final testFile = + MatrixFile(bytes: Uint8List(0), path: 'fake/path/file.jpeg'); final dynamic resp = await room.sendFileEvent(testFile, - msgType: "m.file", txid: "testtxid"); - expect(resp, "mxc://example.com/AQwafuaFswefuhsfAFAgsw"); + msgType: 'm.file', txid: 'testtxid'); + expect(resp, 'mxc://example.com/AQwafuaFswefuhsfAFAgsw'); }); test('pushRuleState', () async { expect(room.pushRuleState, PushRuleState.mentions_only); - matrix.accountData["m.push_rules"].content["global"]["override"] - .add(matrix.accountData["m.push_rules"].content["global"]["room"][0]); + matrix.accountData['m.push_rules'].content['global']['override'] + .add(matrix.accountData['m.push_rules'].content['global']['room'][0]); expect(room.pushRuleState, PushRuleState.dont_notify); }); test('Enable encryption', () async { room.setState( Event( - senderId: "@alice:test.abc", - typeKey: "m.room.encryption", + senderId: '@alice:test.abc', + typeKey: 'm.room.encryption', roomId: room.id, room: room, - eventId: "12345", + eventId: '12345', time: DateTime.now(), content: { - "algorithm": "m.megolm.v1.aes-sha2", - "rotation_period_ms": 604800000, - "rotation_period_msgs": 100 + 'algorithm': 'm.megolm.v1.aes-sha2', + 'rotation_period_ms': 604800000, + 'rotation_period_msgs': 100 }, - stateKey: ""), + stateKey: ''), ); expect(room.encrypted, true); - expect(room.encryptionAlgorithm, "m.megolm.v1.aes-sha2"); + expect(room.encryptionAlgorithm, 'm.megolm.v1.aes-sha2'); expect(room.outboundGroupSession, null); }); @@ -396,7 +394,7 @@ void main() { true); expect( room.sessionKeys[room.outboundGroupSession.session_id()] - .content["session_key"], + .content['session_key'], room.outboundGroupSession.session_key()); expect( room.sessionKeys[room.outboundGroupSession.session_id()].indexes @@ -412,30 +410,29 @@ void main() { test('encryptGroupMessagePayload and decryptGroupMessage', () async { if (!room.client.encryptionEnabled) return; - final Map payload = { - "msgtype": "m.text", - "body": "Hello world", + final payload = { + 'msgtype': 'm.text', + 'body': 'Hello world', }; - final Map encryptedPayload = - await room.encryptGroupMessagePayload(payload); - expect(encryptedPayload["algorithm"], "m.megolm.v1.aes-sha2"); - expect(encryptedPayload["ciphertext"].isNotEmpty, true); - expect(encryptedPayload["device_id"], room.client.deviceID); - expect(encryptedPayload["sender_key"], room.client.identityKey); - expect(encryptedPayload["session_id"], + final encryptedPayload = await room.encryptGroupMessagePayload(payload); + expect(encryptedPayload['algorithm'], 'm.megolm.v1.aes-sha2'); + expect(encryptedPayload['ciphertext'].isNotEmpty, true); + expect(encryptedPayload['device_id'], room.client.deviceID); + expect(encryptedPayload['sender_key'], room.client.identityKey); + expect(encryptedPayload['session_id'], room.outboundGroupSession.session_id()); - Event encryptedEvent = Event( + var encryptedEvent = Event( content: encryptedPayload, - typeKey: "m.room.encrypted", + typeKey: 'm.room.encrypted', senderId: room.client.userID, - eventId: "1234", + eventId: '1234', roomId: room.id, room: room, time: DateTime.now(), ); - Event decryptedEvent = room.decryptGroupMessage(encryptedEvent); - expect(decryptedEvent.typeKey, "m.room.message"); + var decryptedEvent = room.decryptGroupMessage(encryptedEvent); + expect(decryptedEvent.typeKey, 'm.room.message'); expect(decryptedEvent.content, payload); }); }); diff --git a/test/states_map_test.dart b/test/states_map_test.dart index 6462ee5..51fefc5 100644 --- a/test/states_map_test.dart +++ b/test/states_map_test.dart @@ -27,48 +27,48 @@ import 'package:famedlysdk/src/utils/states_map.dart'; void main() { /// All Tests related to the ChatTime - group("StateKeys", () { - test("Operator overload", () async { - StatesMap states = StatesMap(); - states["m.room.name"] = Event( - eventId: "1", - content: {"name": "test"}, - typeKey: "m.room.name", - stateKey: "", - roomId: "!test:test.test", - senderId: "@alice:test.test"); + group('StateKeys', () { + test('Operator overload', () async { + var states = StatesMap(); + states['m.room.name'] = Event( + eventId: '1', + content: {'name': 'test'}, + typeKey: 'm.room.name', + stateKey: '', + roomId: '!test:test.test', + senderId: '@alice:test.test'); - states["@alice:test.test"] = Event( - eventId: "2", - content: {"membership": "join"}, - typeKey: "m.room.name", - stateKey: "@alice:test.test", - roomId: "!test:test.test", - senderId: "@alice:test.test"); + states['@alice:test.test'] = Event( + 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"] = Event( - eventId: "3", - content: {"membership": "join"}, - typeKey: "m.room.name", - stateKey: "@bob:test.test", - roomId: "!test:test.test", - senderId: "@bob:test.test"); + states['m.room.member']['@bob:test.test'] = Event( + 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"] = Event( - eventId: "4", - content: {"custom": "stuff"}, - typeKey: "com.test.custom", - stateKey: "customStateKey", - roomId: "!test:test.test", - senderId: "@bob:test.test"); + states['com.test.custom'] = Event( + 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"); + 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'); }); }); } diff --git a/test/timeline_test.dart b/test/timeline_test.dart index 92ac2f8..bf7a49b 100644 --- a/test/timeline_test.dart +++ b/test/timeline_test.dart @@ -31,18 +31,18 @@ import 'fake_matrix_api.dart'; void main() { /// All Tests related to the MxContent - group("Timeline", () { - final String roomID = "!1234:example.com"; + group('Timeline', () { + final roomID = '!1234:example.com'; final testTimeStamp = DateTime.now().millisecondsSinceEpoch; - int updateCount = 0; - List insertList = []; + var updateCount = 0; + var insertList = []; - Client client = Client("testclient", debug: true); + var client = Client('testclient', debug: true); client.httpClient = FakeMatrixApi(); - Room room = Room( - id: roomID, client: client, prev_batch: "1234", roomAccountData: {}); - Timeline timeline = Timeline( + var room = Room( + id: roomID, client: client, prev_batch: '1234', roomAccountData: {}); + var timeline = Timeline( room: room, events: [], onUpdate: () { @@ -52,32 +52,32 @@ void main() { insertList.add(insertID); }); - test("Create", () async { - await client.checkServer("https://fakeServer.notExisting"); + test('Create', () async { + await client.checkServer('https://fakeServer.notExisting'); client.onEvent.add(EventUpdate( - type: "timeline", + type: 'timeline', roomID: roomID, - eventType: "m.room.message", + eventType: 'm.room.message', content: { - "type": "m.room.message", - "content": {"msgtype": "m.text", "body": "Testcase"}, - "sender": "@alice:example.com", - "status": 2, - "event_id": "1", - "origin_server_ts": testTimeStamp + 'type': 'm.room.message', + 'content': {'msgtype': 'm.text', 'body': 'Testcase'}, + 'sender': '@alice:example.com', + 'status': 2, + 'event_id': '1', + 'origin_server_ts': testTimeStamp })); client.onEvent.add(EventUpdate( - type: "timeline", + type: 'timeline', roomID: roomID, - eventType: "m.room.message", + eventType: 'm.room.message', content: { - "type": "m.room.message", - "content": {"msgtype": "m.text", "body": "Testcase"}, - "sender": "@alice:example.com", - "status": 2, - "event_id": "2", - "origin_server_ts": testTimeStamp - 1000 + 'type': 'm.room.message', + 'content': {'msgtype': 'm.text', 'body': 'Testcase'}, + 'sender': '@alice:example.com', + 'status': 2, + 'event_id': '2', + 'origin_server_ts': testTimeStamp - 1000 })); expect(timeline.sub != null, true); @@ -88,43 +88,43 @@ void main() { expect(insertList, [0, 0]); expect(insertList.length, timeline.events.length); expect(timeline.events.length, 2); - expect(timeline.events[0].eventId, "1"); - expect(timeline.events[0].sender.id, "@alice:example.com"); + expect(timeline.events[0].eventId, '1'); + expect(timeline.events[0].sender.id, '@alice:example.com'); expect(timeline.events[0].time.millisecondsSinceEpoch, testTimeStamp); - expect(timeline.events[0].body, "Testcase"); + expect(timeline.events[0].body, 'Testcase'); expect( timeline.events[0].time.millisecondsSinceEpoch > timeline.events[1].time.millisecondsSinceEpoch, true); expect(timeline.events[0].receipts, []); - room.roomAccountData["m.receipt"] = RoomAccountData.fromJson({ - "type": "m.receipt", - "content": { - "@alice:example.com": { - "event_id": "1", - "ts": 1436451550453, + room.roomAccountData['m.receipt'] = RoomAccountData.fromJson({ + 'type': 'm.receipt', + 'content': { + '@alice:example.com': { + 'event_id': '1', + 'ts': 1436451550453, } }, - "room_id": roomID, + 'room_id': roomID, }, room); await Future.delayed(Duration(milliseconds: 50)); expect(timeline.events[0].receipts.length, 1); - expect(timeline.events[0].receipts[0].user.id, "@alice:example.com"); + expect(timeline.events[0].receipts[0].user.id, '@alice:example.com'); client.onEvent.add(EventUpdate( - type: "timeline", + type: 'timeline', roomID: roomID, - eventType: "m.room.redaction", + eventType: 'm.room.redaction', content: { - "type": "m.room.redaction", - "content": {"reason": "spamming"}, - "sender": "@alice:example.com", - "redacts": "2", - "event_id": "3", - "origin_server_ts": testTimeStamp + 1000 + 'type': 'm.room.redaction', + 'content': {'reason': 'spamming'}, + 'sender': '@alice:example.com', + 'redacts': '2', + 'event_id': '3', + 'origin_server_ts': testTimeStamp + 1000 })); await Future.delayed(Duration(milliseconds: 50)); @@ -136,29 +136,29 @@ void main() { expect(timeline.events[1].redacted, true); }); - test("Send message", () async { - await room.sendTextEvent("test", txid: "1234"); + test('Send message', () async { + await room.sendTextEvent('test', txid: '1234'); await Future.delayed(Duration(milliseconds: 50)); expect(updateCount, 5); expect(insertList, [0, 0, 0]); expect(insertList.length, timeline.events.length); - expect(timeline.events[0].eventId, "42"); + expect(timeline.events[0].eventId, '42'); expect(timeline.events[0].status, 1); client.onEvent.add(EventUpdate( - type: "timeline", + type: 'timeline', roomID: roomID, - eventType: "m.room.message", + eventType: 'm.room.message', content: { - "type": "m.room.message", - "content": {"msgtype": "m.text", "body": "test"}, - "sender": "@alice:example.com", - "status": 2, - "event_id": "42", - "unsigned": {"transaction_id": "1234"}, - "origin_server_ts": DateTime.now().millisecondsSinceEpoch + 'type': 'm.room.message', + 'content': {'msgtype': 'm.text', 'body': 'test'}, + 'sender': '@alice:example.com', + 'status': 2, + 'event_id': '42', + 'unsigned': {'transaction_id': '1234'}, + 'origin_server_ts': DateTime.now().millisecondsSinceEpoch })); await Future.delayed(Duration(milliseconds: 50)); @@ -166,29 +166,29 @@ void main() { expect(updateCount, 6); expect(insertList, [0, 0, 0]); expect(insertList.length, timeline.events.length); - expect(timeline.events[0].eventId, "42"); + expect(timeline.events[0].eventId, '42'); expect(timeline.events[0].status, 2); }); - test("Send message with error", () async { + test('Send message with error', () async { client.onEvent.add(EventUpdate( - type: "timeline", + type: 'timeline', roomID: roomID, - eventType: "m.room.message", + eventType: 'm.room.message', content: { - "type": "m.room.message", - "content": {"msgtype": "m.text", "body": "Testcase"}, - "sender": "@alice:example.com", - "status": 0, - "event_id": "abc", - "origin_server_ts": testTimeStamp + 'type': 'm.room.message', + 'content': {'msgtype': 'm.text', 'body': 'Testcase'}, + 'sender': '@alice:example.com', + 'status': 0, + 'event_id': 'abc', + 'origin_server_ts': testTimeStamp })); await Future.delayed(Duration(milliseconds: 50)); - await room.sendTextEvent("test", txid: "errortxid"); + await room.sendTextEvent('test', txid: 'errortxid'); await Future.delayed(Duration(milliseconds: 50)); - await room.sendTextEvent("test", txid: "errortxid2"); + await room.sendTextEvent('test', txid: 'errortxid2'); await Future.delayed(Duration(milliseconds: 50)); - await room.sendTextEvent("test", txid: "errortxid3"); + await room.sendTextEvent('test', txid: 'errortxid3'); await Future.delayed(Duration(milliseconds: 50)); expect(updateCount, 13); @@ -199,7 +199,7 @@ void main() { expect(timeline.events[2].status, -1); }); - test("Remove message", () async { + test('Remove message', () async { await timeline.events[0].remove(); await Future.delayed(Duration(milliseconds: 50)); @@ -211,8 +211,8 @@ void main() { expect(timeline.events[0].status, -1); }); - test("Resend message", () async { - await timeline.events[0].sendAgain(txid: "1234"); + test('Resend message', () async { + await timeline.events[0].sendAgain(txid: '1234'); await Future.delayed(Duration(milliseconds: 50)); @@ -223,17 +223,17 @@ void main() { expect(timeline.events[0].status, 1); }); - test("Request history", () async { + test('Request history', () async { await room.requestHistory(); await Future.delayed(Duration(milliseconds: 50)); expect(updateCount, 20); expect(timeline.events.length, 9); - expect(timeline.events[6].eventId, "1143273582443PhrSn:example.org"); - expect(timeline.events[7].eventId, "2143273582443PhrSn:example.org"); - expect(timeline.events[8].eventId, "3143273582443PhrSn:example.org"); - expect(room.prev_batch, "t47409-4357353_219380_26003_2265"); + expect(timeline.events[6].eventId, '1143273582443PhrSn:example.org'); + expect(timeline.events[7].eventId, '2143273582443PhrSn:example.org'); + expect(timeline.events[8].eventId, '3143273582443PhrSn:example.org'); + expect(room.prev_batch, 't47409-4357353_219380_26003_2265'); }); }); } diff --git a/test/user_test.dart b/test/user_test.dart index a671a03..081dae5 100644 --- a/test/user_test.dart +++ b/test/user_test.dart @@ -27,29 +27,29 @@ import 'package:test/test.dart'; void main() { /// All Tests related to the Event - group("User", () { - test("Create from json", () async { - final String id = "@alice:server.abc"; - final Membership membership = Membership.join; - final String displayName = "Alice"; - final String avatarUrl = ""; + group('User', () { + test('Create from json', () async { + final id = '@alice:server.abc'; + final membership = Membership.join; + final displayName = 'Alice'; + final avatarUrl = ''; - final Map jsonObj = { - "content": { - "membership": "join", - "avatar_url": avatarUrl, - "displayname": displayName + final jsonObj = { + 'content': { + 'membership': 'join', + 'avatar_url': avatarUrl, + 'displayname': displayName }, - "type": "m.room.member", - "event_id": "143273582443PhrSn:example.org", - "room_id": "!636q39766251:example.com", - "sender": id, - "origin_server_ts": 1432735824653, - "unsigned": {"age": 1234}, - "state_key": id + 'type': 'm.room.member', + 'event_id': '143273582443PhrSn:example.org', + 'room_id': '!636q39766251:example.com', + 'sender': id, + 'origin_server_ts': 1432735824653, + 'unsigned': {'age': 1234}, + 'state_key': id }; - User user = Event.fromJson(jsonObj, null).asUser; + var user = Event.fromJson(jsonObj, null).asUser; expect(user.id, id); expect(user.membership, membership); @@ -58,13 +58,13 @@ void main() { expect(user.calcDisplayname(), displayName); }); - test("calcDisplayname", () async { - final User user1 = User("@alice:example.com"); - final User user2 = User("@SuperAlice:example.com"); - final User user3 = User("@alice:example.com"); - expect(user1.calcDisplayname(), "alice"); - expect(user2.calcDisplayname(), "SuperAlice"); - expect(user3.calcDisplayname(), "alice"); + test('calcDisplayname', () async { + final user1 = User('@alice:example.com'); + final user2 = User('@SuperAlice:example.com'); + final user3 = User('@alice:example.com'); + expect(user1.calcDisplayname(), 'alice'); + expect(user2.calcDisplayname(), 'SuperAlice'); + expect(user3.calcDisplayname(), 'alice'); }); }); } diff --git a/test_driver/famedlysdk_test.dart b/test_driver/famedlysdk_test.dart index 5551cc2..f07e21c 100644 --- a/test_driver/famedlysdk_test.dart +++ b/test_driver/famedlysdk_test.dart @@ -3,36 +3,36 @@ import '../test/fake_store.dart'; void main() => test(); -const String homeserver = "https://matrix.test.famedly.de"; -const String testUserA = "@tick:test.famedly.de"; -const String testPasswordA = "test"; -const String testUserB = "@trick:test.famedly.de"; -const String testPasswordB = "test"; -const String testMessage = "Hello world"; -const String testMessage2 = "Hello moon"; -const String testMessage3 = "Hello sun"; -const String testMessage4 = "Hello star"; -const String testMessage5 = "Hello earth"; -const String testMessage6 = "Hello mars"; +const String homeserver = 'https://matrix.test.famedly.de'; +const String testUserA = '@tick:test.famedly.de'; +const String testPasswordA = 'test'; +const String testUserB = '@trick:test.famedly.de'; +const String testPasswordB = 'test'; +const String testMessage = 'Hello world'; +const String testMessage2 = 'Hello moon'; +const String testMessage3 = 'Hello sun'; +const String testMessage4 = 'Hello star'; +const String testMessage5 = 'Hello earth'; +const String testMessage6 = 'Hello mars'; void test() async { - print("++++ Login $testUserA ++++"); - Client testClientA = Client("TestClient", debug: false); - testClientA.storeAPI = FakeStore(testClientA, Map()); + print('++++ Login $testUserA ++++'); + var testClientA = Client('TestClient', debug: false); + testClientA.storeAPI = FakeStore(testClientA, {}); await testClientA.checkServer(homeserver); await testClientA.login(testUserA, testPasswordA); assert(testClientA.encryptionEnabled); - print("++++ Login $testUserB ++++"); - Client testClientB = Client("TestClient", debug: false); - testClientB.storeAPI = FakeStore(testClientB, Map()); + print('++++ Login $testUserB ++++'); + var testClientB = Client('TestClient', debug: false); + testClientB.storeAPI = FakeStore(testClientB, {}); await testClientB.checkServer(homeserver); await testClientB.login(testUserB, testPasswordA); assert(testClientB.encryptionEnabled); - print("++++ ($testUserA) Leave all rooms ++++"); + print('++++ ($testUserA) Leave all rooms ++++'); while (testClientA.rooms.isNotEmpty) { - Room room = testClientA.rooms.first; + var room = testClientA.rooms.first; if (room.canonicalAlias?.isNotEmpty ?? false) { break; } @@ -44,10 +44,10 @@ void test() async { } } - print("++++ ($testUserB) Leave all rooms ++++"); - for (int i = 0; i < 3; i++) { + print('++++ ($testUserB) Leave all rooms ++++'); + for (var i = 0; i < 3; i++) { if (testClientB.rooms.isNotEmpty) { - Room room = testClientB.rooms.first; + var room = testClientB.rooms.first; try { await room.leave(); await room.forget(); @@ -57,7 +57,7 @@ void test() async { } } - print("++++ Check if own olm device is verified by default ++++"); + print('++++ Check if own olm device is verified by default ++++'); assert(testClientA.userDeviceKeys.containsKey(testUserA)); assert(testClientA.userDeviceKeys[testUserA].deviceKeys .containsKey(testClientA.deviceID)); @@ -73,27 +73,27 @@ void test() async { assert(!testClientB .userDeviceKeys[testUserB].deviceKeys[testClientB.deviceID].blocked); - print("++++ ($testUserA) Create room and invite $testUserB ++++"); + print('++++ ($testUserA) Create room and invite $testUserB ++++'); await testClientA.createRoom(invite: [User(testUserB)]); await Future.delayed(Duration(seconds: 1)); - Room room = testClientA.rooms.first; + var room = testClientA.rooms.first; assert(room != null); - final String roomId = room.id; + final roomId = room.id; - print("++++ ($testUserB) Join room ++++"); - Room inviteRoom = testClientB.getRoomById(roomId); + print('++++ ($testUserB) Join room ++++'); + var inviteRoom = testClientB.getRoomById(roomId); await inviteRoom.join(); await Future.delayed(Duration(seconds: 1)); assert(inviteRoom.membership == Membership.join); - print("++++ ($testUserA) Enable encryption ++++"); + print('++++ ($testUserA) Enable encryption ++++'); assert(room.encrypted == false); await room.enableEncryption(); await Future.delayed(Duration(seconds: 5)); assert(room.encrypted == true); assert(room.outboundGroupSession == null); - print("++++ ($testUserA) Check known olm devices ++++"); + print('++++ ($testUserA) Check known olm devices ++++'); assert(testClientA.userDeviceKeys.containsKey(testUserB)); assert(testClientA.userDeviceKeys[testUserB].deviceKeys .containsKey(testClientB.deviceID)); @@ -111,7 +111,7 @@ void test() async { await testClientA.userDeviceKeys[testUserB].deviceKeys[testClientB.deviceID] .setVerified(true, testClientA); - print("++++ Check if own olm device is verified by default ++++"); + print('++++ Check if own olm device is verified by default ++++'); assert(testClientA.userDeviceKeys.containsKey(testUserA)); assert(testClientA.userDeviceKeys[testUserA].deviceKeys .containsKey(testClientA.deviceID)); @@ -127,7 +127,7 @@ void test() async { await room.sendTextEvent(testMessage); await Future.delayed(Duration(seconds: 5)); assert(room.outboundGroupSession != null); - String currentSessionIdA = room.outboundGroupSession.session_id(); + var currentSessionIdA = room.outboundGroupSession.session_id(); assert(room.sessionKeys.containsKey(room.outboundGroupSession.session_id())); assert(testClientA.olmSessions[testClientB.identityKey].length == 1); assert(testClientB.olmSessions[testClientA.identityKey].length == 1); @@ -172,9 +172,9 @@ void test() async { print( "++++ ($testUserA) Received decrypted message: '${room.lastMessage}' ++++"); - print("++++ Login $testUserB in another client ++++"); - Client testClientC = Client("TestClient", debug: false); - testClientC.storeAPI = FakeStore(testClientC, Map()); + print('++++ Login $testUserB in another client ++++'); + var testClientC = Client('TestClient', debug: false); + testClientC.storeAPI = FakeStore(testClientC, {}); await testClientC.checkServer(homeserver); await testClientC.login(testUserB, testPasswordA); await Future.delayed(Duration(seconds: 3)); @@ -200,7 +200,7 @@ void test() async { print( "++++ ($testUserB) Received decrypted message: '${inviteRoom.lastMessage}' ++++"); - print("++++ Logout $testUserB another client ++++"); + print('++++ Logout $testUserB another client ++++'); await testClientC.logout(); testClientC = null; await Future.delayed(Duration(seconds: 5)); @@ -223,20 +223,20 @@ void test() async { print( "++++ ($testUserB) Received decrypted message: '${inviteRoom.lastMessage}' ++++"); - print("++++ ($testUserA) Restore user ++++"); + print('++++ ($testUserA) Restore user ++++'); FakeStore clientAStore = testClientA.storeAPI; testClientA = null; - testClientA = Client("TestClient", debug: false); + testClientA = Client('TestClient', debug: false); testClientA.storeAPI = FakeStore(testClientA, clientAStore.storeMap); await Future.delayed(Duration(seconds: 3)); - Room restoredRoom = testClientA.rooms.first; + var restoredRoom = testClientA.rooms.first; assert(room != null); assert(restoredRoom.id == room.id); assert(restoredRoom.outboundGroupSession.session_id() == room.outboundGroupSession.session_id()); assert(restoredRoom.sessionKeys.length == 4); assert(restoredRoom.sessionKeys.length == room.sessionKeys.length); - for (int i = 0; i < restoredRoom.sessionKeys.length; i++) { + for (var i = 0; i < restoredRoom.sessionKeys.length; i++) { assert(restoredRoom.sessionKeys.keys.toList()[i] == room.sessionKeys.keys.toList()[i]); } @@ -261,16 +261,16 @@ void test() async { print( "++++ ($testUserB) Received decrypted message: '${inviteRoom.lastMessage}' ++++"); - print("++++ Logout $testUserA and $testUserB ++++"); + print('++++ Logout $testUserA and $testUserB ++++'); await room.leave(); await room.forget(); await inviteRoom.leave(); await inviteRoom.forget(); await Future.delayed(Duration(seconds: 1)); await testClientA.jsonRequest( - type: HTTPType.POST, action: "/client/r0/logout/all"); + type: HTTPType.POST, action: '/client/r0/logout/all'); await testClientB.jsonRequest( - type: HTTPType.POST, action: "/client/r0/logout/all"); + type: HTTPType.POST, action: '/client/r0/logout/all'); testClientA = null; testClientB = null; return;