diff --git a/analysis_options.yaml b/analysis_options.yaml index 2ff74f1..b7c304f 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -2,7 +2,7 @@ include: package:pedantic/analysis_options.yaml linter: rules: - #- camel_case_types + - camel_case_types analyzer: # exclude: diff --git a/lib/src/Client.dart b/lib/src/Client.dart index da6f757..f4fa2c4 100644 --- a/lib/src/Client.dart +++ b/lib/src/Client.dart @@ -30,6 +30,7 @@ import 'package:famedlysdk/src/Presence.dart'; import 'package:famedlysdk/src/StoreAPI.dart'; import 'package:famedlysdk/src/sync/UserUpdate.dart'; import 'package:famedlysdk/src/utils/MatrixFile.dart'; +import 'package:pedantic/pedantic.dart'; import 'Room.dart'; import 'Event.dart'; import 'User.dart'; @@ -161,8 +162,9 @@ class Client { 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) + 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( @@ -171,11 +173,13 @@ class Client { data: directChats); return getDirectChatFromUserId(userId); } - for (int i = 0; i < this.rooms.length; i++) + 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) + this.rooms[i].states[userID].content["is_direct"] == true) { return this.rooms[i].id; + } + } return null; } @@ -192,9 +196,9 @@ class Client { final List versions = List.from(versionResp["versions"]); for (int i = 0; i < versions.length; i++) { - if (versions[i] == "r0.5.0") + if (versions[i] == "r0.5.0") { break; - else if (i == versions.length - 1) { + } else if (i == versions.length - 1) { return false; } } @@ -216,9 +220,9 @@ class Client { for (int i = 0; i < flows.length; i++) { if (flows[i].containsKey("type") && - flows[i]["type"] == "m.login.password") + flows[i]["type"] == "m.login.password") { break; - else if (i == flows.length - 1) { + } else if (i == flows.length - 1) { return false; } } @@ -341,9 +345,9 @@ class Client { List contacts = []; Room contactDiscoveryRoom = this.getRoomByAlias("#famedlyContactDiscovery:${userID.split(":")[1]}"); - if (contactDiscoveryRoom != null) + if (contactDiscoveryRoom != null) { contacts = await contactDiscoveryRoom.requestParticipants(); - else { + } else { Map userMap = {}; for (int i = 0; i < this.rooms.length; i++) { List roomUsers = this.rooms[i].getParticipants(); @@ -366,8 +370,11 @@ class Client { Future createRoom( {List invite, Map params}) async { List inviteIDs = []; - if (params == null && invite != null) - for (int i = 0; i < invite.length; i++) inviteIDs.add(invite[i].id); + if (params == null && invite != null) { + for (int i = 0; i < invite.length; i++) { + inviteIDs.add(invite[i].id); + } + } try { final dynamic resp = await this.jsonRequest( @@ -440,31 +447,29 @@ class Client { /// the app receives a new synchronization, this event is called for every signal /// to update the GUI. For example, for a new message, it is called: /// onRoomEvent( "m.room.message", "!chat_id:server.com", "timeline", {sender: "@bob:server.com", body: "Hello world"} ) - final StreamController onEvent = - new StreamController.broadcast(); + final StreamController onEvent = StreamController.broadcast(); /// Outside of the events there are updates for the global chat states which /// are handled by this signal: final StreamController onRoomUpdate = - new StreamController.broadcast(); + StreamController.broadcast(); /// Outside of rooms there are account updates like account_data or presences. - final StreamController onUserEvent = - new StreamController.broadcast(); + final StreamController onUserEvent = StreamController.broadcast(); /// Called when the login state e.g. user gets logged out. final StreamController onLoginStateChanged = - new StreamController.broadcast(); + StreamController.broadcast(); /// Synchronization erros are coming here. final StreamController onError = - new StreamController.broadcast(); + StreamController.broadcast(); /// This is called once, when the first sync has received. - final StreamController onFirstSync = new StreamController.broadcast(); + final StreamController onFirstSync = StreamController.broadcast(); /// When a new sync response is coming in, this gives the complete payload. - final StreamController onSync = new StreamController.broadcast(); + final StreamController onSync = StreamController.broadcast(); /// Matrix synchronisation is done with https long polling. This needs a /// timeout which is usually 30 seconds. @@ -525,7 +530,7 @@ class Client { this.prevBatch = newPrevBatch; if (this.store != null) { - this.store.storeClient(); + await this.store.storeClient(); this._rooms = await this.store.getRoomList(onlyLeft: false); this.accountData = await this.store.getAccountData(); this.presences = await this.store.getPresences(); @@ -535,7 +540,7 @@ class Client { onLoginStateChanged.add(LoginState.logged); - _sync(); + return _sync(); } StreamSubscription _userEventSub; @@ -574,8 +579,9 @@ class Client { dynamic data = "", int timeout, String contentType = "application/json"}) async { - if (this.isLogged() == false && this.homeserver == null) + if (this.isLogged() == false && this.homeserver == null) { throw ("No homeserver specified."); + } if (timeout == null) timeout = syncTimeoutSec + 5; dynamic json; if (data is Map) data.removeWhere((k, v) => v == null); @@ -585,14 +591,17 @@ class Client { final url = "${this.homeserver}/_matrix${action}"; Map headers = {}; - if (type == HTTPType.PUT || type == HTTPType.POST) + if (type == HTTPType.PUT || type == HTTPType.POST) { headers["Content-Type"] = contentType; - if (this.isLogged()) + } + if (this.isLogged()) { headers["Authorization"] = "Bearer ${this.accessToken}"; + } - if (this.debug) + if (this.debug) { print( "[REQUEST ${type.toString().split('.').last}] Action: $action, Data: $data"); + } http.Response resp; Map jsonResp = {}; @@ -650,8 +659,9 @@ class Client { /// and returns the mxc url as a string. Future upload(MatrixFile file) async { dynamic fileBytes; - if (this.homeserver != "https://fakeServer.notExisting") + if (this.homeserver != "https://fakeServer.notExisting") { fileBytes = file.bytes; + } String fileName = file.path.split("/").last.toLowerCase(); String mimeType = mime(file.path); print("[UPLOADING] $fileName, type: $mimeType, size: ${fileBytes?.length}"); @@ -679,17 +689,18 @@ class Client { final int hash = _syncRequest.hashCode; final syncResp = await _syncRequest; if (hash != _syncRequest.hashCode) return; - if (this.store != null) + if (this.store != null) { await this.store.transaction(() { handleSync(syncResp); this.store.storePrevBatch(syncResp); return; }); - else + } else { await handleSync(syncResp); + } if (this.prevBatch == null) this.onFirstSync.add(true); this.prevBatch = syncResp["next_batch"]; - if (hash == _syncRequest.hashCode) _sync(); + if (hash == _syncRequest.hashCode) unawaited(_sync()); } on MatrixException catch (exception) { onError.add(exception); await Future.delayed(Duration(seconds: syncErrorTimeoutSec), _sync); @@ -700,12 +711,15 @@ class Client { void handleSync(dynamic sync) { if (sync["rooms"] is Map) { - if (sync["rooms"]["join"] is Map) + if (sync["rooms"]["join"] is Map) { _handleRooms(sync["rooms"]["join"], Membership.join); - if (sync["rooms"]["invite"] is Map) + } + if (sync["rooms"]["invite"] is Map) { _handleRooms(sync["rooms"]["invite"], Membership.invite); - if (sync["rooms"]["leave"] is Map) + } + if (sync["rooms"]["leave"] is Map) { _handleRooms(sync["rooms"]["leave"], Membership.leave); + } } if (sync["presence"] is Map && sync["presence"]["events"] is List) { @@ -731,18 +745,22 @@ class Client { bool limitedTimeline = false; if (room["unread_notifications"] is Map) { - if (room["unread_notifications"]["highlight_count"] is num) + 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"]; + } } if (room["timeline"] is Map) { - if (room["timeline"]["limited"] is bool) + if (room["timeline"]["limited"] is bool) { limitedTimeline = room["timeline"]["limited"]; - if (room["timeline"]["prev_batch"] is String) + } + if (room["timeline"]["prev_batch"] is String) { prev_batch = room["timeline"]["prev_batch"]; + } } RoomSummary summary; @@ -761,29 +779,34 @@ class Client { summary: summary, ); _updateRoomsByRoomUpdate(update); - this.store?.storeRoomUpdate(update); + unawaited(this.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) + room["state"]["events"] is List) { _handleRoomEvents(id, room["state"]["events"], "state"); + } if (room["invite_state"] is Map && - room["invite_state"]["events"] is List) + room["invite_state"]["events"] is List) { _handleRoomEvents(id, room["invite_state"]["events"], "invite_state"); + } if (room["timeline"] is Map && - room["timeline"]["events"] is List) + room["timeline"]["events"] is List) { _handleRoomEvents(id, room["timeline"]["events"], "timeline"); + } if (room["ephemeral"] is Map && - room["ephemeral"]["events"] is List) + room["ephemeral"]["events"] is List) { _handleEphemerals(id, room["ephemeral"]["events"]); + } if (room["account_data"] is Map && - room["account_data"]["events"] is List) + room["account_data"]["events"] is List) { _handleRoomEvents(id, room["account_data"]["events"], "account_data"); + } }); } @@ -839,7 +862,7 @@ class Client { } void _handleGlobalEvents(List events, String type) { - for (int i = 0; i < events.length; i++) + for (int i = 0; i < events.length; i++) { if (events[i]["type"] is String && events[i]["content"] is Map) { UserUpdate update = UserUpdate( @@ -850,6 +873,7 @@ class Client { this.store?.storeUserEventUpdate(update); onUserEvent.add(update); } + } } void _handleEvent(Map event, String roomID, String type) { @@ -908,15 +932,19 @@ class Client { rooms[j].membership = chatUpdate.membership; rooms[j].notificationCount = chatUpdate.notification_count; rooms[j].highlightCount = chatUpdate.highlight_count; - if (chatUpdate.prev_batch != null) + if (chatUpdate.prev_batch != null) { rooms[j].prev_batch = chatUpdate.prev_batch; + } if (chatUpdate.summary != null) { - if (chatUpdate.summary.mHeroes != null) + if (chatUpdate.summary.mHeroes != null) { rooms[j].mHeroes = chatUpdate.summary.mHeroes; - if (chatUpdate.summary.mJoinedMemberCount != null) + } + if (chatUpdate.summary.mJoinedMemberCount != null) { rooms[j].mJoinedMemberCount = chatUpdate.summary.mJoinedMemberCount; - if (chatUpdate.summary.mInvitedMemberCount != null) + } + if (chatUpdate.summary.mInvitedMemberCount != null) { rooms[j].mInvitedMemberCount = chatUpdate.summary.mInvitedMemberCount; + } } if (rooms[j].onUpdate != null) rooms[j].onUpdate(); } diff --git a/lib/src/Event.dart b/lib/src/Event.dart index cb09ec6..adb0290 100644 --- a/lib/src/Event.dart +++ b/lib/src/Event.dart @@ -105,12 +105,13 @@ class Event { this.room}); static Map getMapFromPayload(dynamic payload) { - if (payload is String) + if (payload is String) { try { return json.decode(payload); } catch (e) { return {}; } + } if (payload is Map) return payload; return {}; } @@ -141,18 +142,20 @@ class Event { } Map toJson() { - final Map data = new Map(); + final Map data = Map(); if (this.stateKey != null) data['state_key'] = this.stateKey; - if (this.prevContent != null && this.prevContent.isNotEmpty) + if (this.prevContent != null && this.prevContent.isNotEmpty) { data['prev_content'] = this.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) + if (this.unsigned != null && this.unsigned.isNotEmpty) { data['unsigned'] = this.unsigned; + } return data; } @@ -245,9 +248,6 @@ class Event { prevContent = null; List contentKeyWhiteList = []; switch (type) { - case EventTypes.RoomMember: - contentKeyWhiteList.add("membership"); - break; case EventTypes.RoomMember: contentKeyWhiteList.add("membership"); break; @@ -278,7 +278,7 @@ class Event { } List toRemoveList = []; for (var entry in content.entries) { - if (contentKeyWhiteList.indexOf(entry.key) == -1) { + if (!contentKeyWhiteList.contains(entry.key)) { toRemoveList.add(entry.key); } } @@ -304,9 +304,10 @@ class Event { 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 (entry.value["event_id"] == eventId) { receiptsList.add(Receipt(room.getUserByMXIDSync(entry.key), DateTime.fromMillisecondsSinceEpoch(entry.value["ts"]))); + } } return receiptsList; } @@ -315,8 +316,9 @@ class Event { /// from the database and the timelines. Returns false if not removed. Future remove() async { if (status < 1) { - if (room.client.store != null) + if (room.client.store != null) { await room.client.store.removeEvent(eventId); + } room.client.onEvent.add(EventUpdate( roomID: room.id, @@ -335,7 +337,7 @@ class Event { /// Try to send this event again. Only works with events of status -1. Future sendAgain({String txid}) async { if (status != -1) return null; - remove(); + await remove(); final String eventID = await room.sendTextEvent(text, txid: txid); return eventID; } diff --git a/lib/src/Room.dart b/lib/src/Room.dart index e272261..6f7f57f 100644 --- a/lib/src/Room.dart +++ b/lib/src/Room.dart @@ -29,7 +29,6 @@ import 'package:famedlysdk/src/sync/RoomUpdate.dart'; import 'package:famedlysdk/src/utils/MatrixException.dart'; import 'package:famedlysdk/src/utils/MatrixFile.dart'; import 'package:famedlysdk/src/utils/MxContent.dart'; -//import 'package:image/image.dart'; import 'package:mime_type/mime_type.dart'; import './User.dart'; @@ -81,8 +80,9 @@ class Room { /// Adds the [state] to this room and overwrites a state with the same /// typeKey/stateKey key pair if there is one. void setState(Event state) { - if (!states.states.containsKey(state.typeKey)) + if (!states.states.containsKey(state.typeKey)) { states.states[state.typeKey] = {}; + } states.states[state.typeKey][state.stateKey ?? ""] = state; } @@ -106,10 +106,12 @@ class Room { /// The avatar of the room if set by a participant. MxContent get avatar { - if (states["m.room.avatar"] != null) + if (states["m.room.avatar"] != null) { return MxContent(states["m.room.avatar"].content["url"]); - if (mHeroes != null && mHeroes.length == 1 && states[mHeroes[0]] != null) + } + 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; @@ -125,15 +127,16 @@ class Room { /// If this room is a direct chat, this is the matrix ID of the user. /// Returns null otherwise. String get directChatMatrixID { - String returnUserId = null; + String returnUserId; if (client.directChats is Map) { client.directChats.forEach((String userId, dynamic roomIds) { if (roomIds is List) { - for (int i = 0; i < roomIds.length; i++) + for (int i = 0; i < roomIds.length; i++) { if (roomIds[i] == this.id) { returnUserId = userId; break; } + } } }); } @@ -149,7 +152,7 @@ class Room { Event get lastEvent { DateTime lastTime = DateTime.fromMillisecondsSinceEpoch(0); Event lastEvent = getState("m.room.message")?.timelineEvent; - if (lastEvent == null) + if (lastEvent == null) { states.forEach((final String key, final entry) { if (!entry.containsKey("")) return; final Event state = entry[""]; @@ -160,6 +163,7 @@ class Room { lastEvent = state.timelineEvent; } }); + } return lastEvent; } @@ -168,8 +172,9 @@ class Room { if (!ephemerals.containsKey("m.typing")) return []; List typingMxid = ephemerals["m.typing"].content["user_ids"]; List typingUsers = []; - for (int i = 0; i < typingMxid.length; i++) + for (int i = 0; i < typingMxid.length; i++) { typingUsers.add(getUserByMXIDSync(typingMxid[i])); + } return typingUsers; } @@ -199,12 +204,13 @@ class Room { String get displayname { if (name != null && name.isNotEmpty) return name; if (canonicalAlias != null && - !canonicalAlias.isEmpty && - canonicalAlias.length > 3) + canonicalAlias.isNotEmpty && + canonicalAlias.length > 3) { return canonicalAlias.substring(1, canonicalAlias.length).split(":")[0]; + } List heroes = []; if (mHeroes != null && - mHeroes.length > 0 && + mHeroes.isNotEmpty && mHeroes.any((h) => h.isNotEmpty)) { heroes = mHeroes; } else { @@ -216,7 +222,7 @@ class Room { } } } - if (heroes.length > 0) { + if (heroes.isNotEmpty) { String displayname = ""; for (int i = 0; i < heroes.length; i++) { if (heroes[i].isEmpty) continue; @@ -233,18 +239,19 @@ class Room { /// The last message sent to this room. String get lastMessage { - if (lastEvent != null) + if (lastEvent != null) { return lastEvent.getBody(); - else + } else { return ""; + } } /// When the last message received. DateTime get timeCreated { - if (lastEvent != null) + if (lastEvent != null) { return lastEvent.time; - else - return DateTime.now(); + } + return DateTime.now(); } /// Call the Matrix API to change the name of this room. Returns the event ID of the @@ -267,7 +274,7 @@ class Room { } Future _sendRawEventNow(Map content, - {String txid = null}) async { + {String txid}) async { if (txid == null) txid = "txid${DateTime.now().millisecondsSinceEpoch}"; final Map res = await client.jsonRequest( type: HTTPType.PUT, @@ -276,13 +283,13 @@ class Room { return res["event_id"]; } - Future sendTextEvent(String message, {String txid = null}) => + Future sendTextEvent(String message, {String txid}) => sendEvent({"msgtype": "m.text", "body": message}, txid: txid); /// Sends a [file] to this room after uploading it. The [msgType] is optional /// and will be detected by the mimetype of the file. Future sendFileEvent(MatrixFile file, - {String msgType = "m.file", String txid = null}) async { + {String msgType = "m.file", String txid}) async { if (msgType == "m.image") return sendImageEvent(file); if (msgType == "m.audio") return sendVideoEvent(file); if (msgType == "m.video") return sendAudioEvent(file); @@ -305,7 +312,7 @@ class Room { } Future sendAudioEvent(MatrixFile file, - {String txid = null, int width, int height}) async { + {String txid, int width, int height}) async { String fileName = file.path.split("/").last; final String uploadResp = await client.upload(file); Map content = { @@ -322,7 +329,7 @@ class Room { } Future sendImageEvent(MatrixFile file, - {String txid = null, int width, int height}) async { + {String txid, int width, int height}) async { String fileName = file.path.split("/").last; final String uploadResp = await client.upload(file); Map content = { @@ -340,7 +347,7 @@ class Room { } Future sendVideoEvent(MatrixFile file, - {String txid = null, + {String txid, int videoWidth, int videoHeight, int duration, @@ -385,8 +392,7 @@ class Room { return await sendEvent(content, txid: txid); } - Future sendEvent(Map content, - {String txid = null}) async { + Future sendEvent(Map content, {String txid}) async { final String type = "m.room.message"; // Create new transaction id @@ -394,8 +400,9 @@ class Room { final int now = DateTime.now().millisecondsSinceEpoch; if (txid == null) { messageID = "msg$now"; - } else + } else { messageID = txid; + } // Display a *sending* event and store it. EventUpdate eventUpdate = @@ -447,11 +454,12 @@ class Room { type: HTTPType.POST, action: "/client/r0/rooms/${id}/join"); if (states.containsKey(client.userID) && states[client.userID].content["is_direct"] is bool && - states[client.userID].content["is_direct"]) - addToDirectChat(states[client.userID].sender.id); + states[client.userID].content["is_direct"]) { + await addToDirectChat(states[client.userID].sender.id); + } } on MatrixException catch (exception) { if (exception.errorMessage == "No known servers") { - client.store?.forgetRoom(id); + await client.store?.forgetRoom(id); client.onRoomUpdate.add( RoomUpdate( id: id, @@ -475,7 +483,7 @@ class Room { /// Call the Matrix API to forget this room if you already left it. Future forget() async { - client.store.forgetRoom(id); + await client.store?.forgetRoom(id); await client.jsonRequest( type: HTTPType.POST, action: "/client/r0/rooms/${id}/forget"); return; @@ -546,14 +554,14 @@ class Room { if (onHistoryReceived != null) onHistoryReceived(); prev_batch = resp["end"]; - client.store?.storeRoomPrevBatch(this); + await client.store?.storeRoomPrevBatch(this); if (!(resp["chunk"] is List && resp["chunk"].length > 0 && resp["end"] is String)) return; if (resp["state"] is List) { - client.store?.transaction(() { + await client.store?.transaction(() { for (int i = 0; i < resp["state"].length; i++) { EventUpdate eventUpdate = EventUpdate( type: "state", @@ -580,7 +588,7 @@ class Room { } List history = resp["chunk"]; - client.store?.transaction(() { + await client.store?.transaction(() { for (int i = 0; i < history.length; i++) { EventUpdate eventUpdate = EventUpdate( type: "history", @@ -620,12 +628,15 @@ class Room { /// Sets this room as a direct chat for this user if not already. Future addToDirectChat(String userID) async { Map directChats = client.directChats; - if (directChats.containsKey(userID)) if (!directChats[userID].contains(id)) - directChats[userID].add(id); - else - return; // Is already in direct chats - else + if (directChats.containsKey(userID)) { + if (!directChats[userID].contains(id)) { + directChats[userID].add(id); + } else { + return; + } // Is already in direct chats + } else { directChats[userID] = [id]; + } await client.jsonRequest( type: HTTPType.PUT, @@ -638,10 +649,11 @@ class Room { Future removeFromDirectChat() async { Map directChats = client.directChats; if (directChats.containsKey(directChatMatrixID) && - directChats[directChatMatrixID].contains(id)) + directChats[directChatMatrixID].contains(id)) { directChats[directChatMatrixID].remove(id); - else - return; // Nothing to do here + } else { + return; + } // Nothing to do here await client.jsonRequest( type: HTTPType.PUT, @@ -653,8 +665,8 @@ class Room { /// Sends *m.fully_read* and *m.read* for the given event ID. Future sendReadReceipt(String eventID) async { this.notificationCount = 0; - client?.store?.resetNotificationCount(this.id); - client.jsonRequest( + await client?.store?.resetNotificationCount(this.id); + await client.jsonRequest( type: HTTPType.POST, action: "/client/r0/rooms/$id/read_markers", data: { @@ -712,11 +724,11 @@ class Room { {onTimelineUpdateCallback onUpdate, onTimelineInsertCallback onInsert}) async { List events = []; - if (client.store != null) + if (client.store != null) { events = await client.store.getEventList(this); - else { + } else { prev_batch = ""; - requestHistory(); + await requestHistory(); } return Timeline( room: this, @@ -772,9 +784,9 @@ class Room { /// Returns the [User] object for the given [mxID] or requests it from /// the homeserver and returns a default [User] object while waiting. User getUserByMXIDSync(String mxID) { - if (states[mxID] != null) + if (states[mxID] != null) { return states[mxID].asUser; - else { + } else { try { requestUser(mxID); } catch (_) {} @@ -802,8 +814,8 @@ class Room { avatarUrl: resp["avatar_url"], room: this); states[mxID] = user; - if (client.store != null) - client.store.transaction(() { + if (client.store != null) { + await client.store.transaction(() { client.store.storeEventUpdate( EventUpdate( content: resp, @@ -813,6 +825,7 @@ class Room { ); return; }); + } if (onUpdate != null) onUpdate(); _requestingMatrixIds.remove(mxID); return user; @@ -830,11 +843,13 @@ class Room { int powerLevel = 0; Event powerLevelState = states["m.room.power_levels"]; if (powerLevelState == null) return powerLevel; - if (powerLevelState.content["users_default"] is int) + if (powerLevelState.content["users_default"] is int) { powerLevel = powerLevelState.content["users_default"]; + } if (powerLevelState.content["users"] is Map && - powerLevelState.content["users"][userId] != null) + powerLevelState.content["users"][userId] != null) { powerLevel = powerLevelState.content["users"][userId]; + } return powerLevel; } @@ -844,8 +859,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) + if (powerLevelState.content["users"] is Map) { return powerLevelState.content["users"]; + } return null; } @@ -889,10 +905,11 @@ class Room { bool canSendEvent(String eventType) { if (getState("m.room.power_levels") == null) return false; if (getState("m.room.power_levels").content["events"] == null || - getState("m.room.power_levels").content["events"][eventType] == 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]; } @@ -901,8 +918,9 @@ class Room { /// the account_data. PushRuleState get pushRuleState { if (!client.accountData.containsKey("m.push_rules") || - !(client.accountData["m.push_rules"].content["global"] is Map)) + !(client.accountData["m.push_rules"].content["global"] is Map)) { return PushRuleState.notify; + } final Map globalPushRules = client.accountData["m.push_rules"].content["global"]; if (globalPushRules == null) return PushRuleState.notify; @@ -943,16 +961,17 @@ class Room { switch (newState) { // All push notifications should be sent to the user case PushRuleState.notify: - if (pushRuleState == PushRuleState.dont_notify) + if (pushRuleState == PushRuleState.dont_notify) { resp = await client.jsonRequest( type: HTTPType.DELETE, action: "/client/r0/pushrules/global/override/$id", data: {}); - else if (pushRuleState == PushRuleState.mentions_only) + } else if (pushRuleState == PushRuleState.mentions_only) { resp = await client.jsonRequest( type: HTTPType.DELETE, action: "/client/r0/pushrules/global/room/$id", data: {}); + } break; // Only when someone mentions the user, a push notification should be sent case PushRuleState.mentions_only: @@ -967,13 +986,14 @@ class Room { data: { "actions": ["dont_notify"] }); - } else if (pushRuleState == PushRuleState.notify) + } else if (pushRuleState == PushRuleState.notify) { resp = await client.jsonRequest( type: HTTPType.PUT, action: "/client/r0/pushrules/global/room/$id", data: { "actions": ["dont_notify"] }); + } break; // No push notification should be ever sent for this room. case PushRuleState.dont_notify: @@ -1004,8 +1024,9 @@ class Room { final int now = DateTime.now().millisecondsSinceEpoch; if (txid == null) { messageID = "msg$now"; - } else + } else { messageID = txid; + } Map data = {}; if (reason != null) data["reason"] = reason; final dynamic resp = await client.jsonRequest( diff --git a/lib/src/utils/StatesMap.dart b/lib/src/utils/StatesMap.dart index a92f933..ca08617 100644 --- a/lib/src/utils/StatesMap.dart +++ b/lib/src/utils/StatesMap.dart @@ -14,12 +14,13 @@ class StatesMap { return states["m.room.member"][key]; } if (!states.containsKey(key)) states[key] = {}; - if (states[key][""] is Event) + if (states[key][""] is Event) { return states[key][""]; - else if (states[key].length == 0) + } else if (states[key].isEmpty) { return null; - else + } else { return states[key]; + } } void operator []=(String key, Event val) { diff --git a/pubspec.lock b/pubspec.lock index 976f101..3194e8b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -303,7 +303,7 @@ packages: source: hosted version: "1.6.4" pedantic: - dependency: "direct dev" + dependency: "direct main" description: name: pedantic url: "https://pub.dartlang.org" diff --git a/test/Client_test.dart b/test/Client_test.dart index 1551c33..4133bda 100644 --- a/test/Client_test.dart +++ b/test/Client_test.dart @@ -100,7 +100,7 @@ void main() { newDeviceID: resp["device_id"], newMatrixVersions: matrix.matrixVersions, newLazyLoadMembers: matrix.lazyLoadMembers); - await new Future.delayed(new Duration(milliseconds: 50)); + await Future.delayed(Duration(milliseconds: 50)); expect(matrix.accessToken == resp["access_token"], true); expect(matrix.deviceName == "Text Matrix Client", true); @@ -164,7 +164,7 @@ void main() { } } }); - await new Future.delayed(new Duration(milliseconds: 50)); + await Future.delayed(Duration(milliseconds: 50)); expect( matrix.getRoomByAlias( @@ -209,7 +209,7 @@ void main() { }); test('Room Update Test', () async { - matrix.onRoomUpdate.close(); + await matrix.onRoomUpdate.close(); List roomUpdateList = await roomUpdateListFuture; @@ -231,7 +231,7 @@ void main() { }); test('Event Update Test', () async { - matrix.onEvent.close(); + await matrix.onEvent.close(); List eventUpdateList = await eventUpdateListFuture; @@ -283,7 +283,7 @@ void main() { }); test('User Update Test', () async { - matrix.onUserEvent.close(); + await matrix.onUserEvent.close(); List eventUpdateList = await userUpdateListFuture; @@ -358,7 +358,7 @@ void main() { test('get archive', () async { List archive = await matrix.archive; - await new Future.delayed(new Duration(milliseconds: 50)); + await Future.delayed(Duration(milliseconds: 50)); expect(archive.length, 2); expect(archive[0].id, "!5345234234:example.com"); expect(archive[0].membership, Membership.leave); diff --git a/test/FakeMatrixApi.dart b/test/FakeMatrixApi.dart index 5c4f471..e0ef058 100644 --- a/test/FakeMatrixApi.dart +++ b/test/FakeMatrixApi.dart @@ -43,26 +43,28 @@ class FakeMatrixApi extends MockClient { // Sync requests with timeout if (data is Map && data["timeout"] is String) { - await new Future.delayed(Duration(seconds: 5)); + 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); + } // Call API - if (api.containsKey(method) && api[method].containsKey(action)) + if (api.containsKey(method) && api[method].containsKey(action)) { res = api[method][action](data); - else if (method == "GET" && + } else if (method == "GET" && action.contains("/client/r0/rooms/") && action.contains("/state/m.room.member/")) { res = {"displayname": ""}; return Response(json.encode(res), 200); - } else + } else { res = { "errcode": "M_UNRECOGNIZED", "error": "Unrecognized request" }; + } return Response(json.encode(res), 100); }); diff --git a/test/Timeline_test.dart b/test/Timeline_test.dart index abaf4e1..059f59a 100644 --- a/test/Timeline_test.dart +++ b/test/Timeline_test.dart @@ -82,7 +82,7 @@ void main() { expect(timeline.sub != null, true); - await new Future.delayed(new Duration(milliseconds: 50)); + await Future.delayed(Duration(milliseconds: 50)); expect(updateCount, 2); expect(insertList, [0, 0]); @@ -109,7 +109,7 @@ void main() { "room_id": roomID, }, room); - await new Future.delayed(new Duration(milliseconds: 50)); + await Future.delayed(Duration(milliseconds: 50)); expect(timeline.events[0].receipts.length, 1); expect(timeline.events[0].receipts[0].user.id, "@alice:example.com"); @@ -127,7 +127,7 @@ void main() { "origin_server_ts": testTimeStamp + 1000 })); - await new Future.delayed(new Duration(milliseconds: 50)); + await Future.delayed(Duration(milliseconds: 50)); expect(updateCount, 3); expect(insertList, [0, 0]); @@ -137,9 +137,9 @@ void main() { }); test("Send message", () async { - room.sendTextEvent("test", txid: "1234"); + await room.sendTextEvent("test", txid: "1234"); - await new Future.delayed(new Duration(milliseconds: 50)); + await Future.delayed(Duration(milliseconds: 50)); expect(updateCount, 5); expect(insertList, [0, 0, 0]); @@ -161,7 +161,7 @@ void main() { "origin_server_ts": DateTime.now().millisecondsSinceEpoch })); - await new Future.delayed(new Duration(milliseconds: 50)); + await Future.delayed(Duration(milliseconds: 50)); expect(updateCount, 6); expect(insertList, [0, 0, 0]); @@ -183,13 +183,13 @@ void main() { "event_id": "abc", "origin_server_ts": testTimeStamp })); - await new Future.delayed(new Duration(milliseconds: 50)); - room.sendTextEvent("test", txid: "errortxid"); - await new Future.delayed(new Duration(milliseconds: 50)); - room.sendTextEvent("test", txid: "errortxid2"); - await new Future.delayed(new Duration(milliseconds: 50)); - room.sendTextEvent("test", txid: "errortxid3"); - await new Future.delayed(new Duration(milliseconds: 50)); + await Future.delayed(Duration(milliseconds: 50)); + await room.sendTextEvent("test", txid: "errortxid"); + await Future.delayed(Duration(milliseconds: 50)); + await room.sendTextEvent("test", txid: "errortxid2"); + await Future.delayed(Duration(milliseconds: 50)); + await room.sendTextEvent("test", txid: "errortxid3"); + await Future.delayed(Duration(milliseconds: 50)); expect(updateCount, 13); expect(insertList, [0, 0, 0, 0, 0, 0, 0]); @@ -200,9 +200,9 @@ void main() { }); test("Remove message", () async { - timeline.events[0].remove(); + await timeline.events[0].remove(); - await new Future.delayed(new Duration(milliseconds: 50)); + await Future.delayed(Duration(milliseconds: 50)); expect(updateCount, 14); @@ -212,9 +212,9 @@ void main() { }); test("Resend message", () async { - timeline.events[0].sendAgain(txid: "1234"); + await timeline.events[0].sendAgain(txid: "1234"); - await new Future.delayed(new Duration(milliseconds: 50)); + await Future.delayed(Duration(milliseconds: 50)); expect(updateCount, 17); @@ -226,7 +226,7 @@ void main() { test("Request history", () async { await room.requestHistory(); - await new Future.delayed(new Duration(milliseconds: 50)); + await Future.delayed(Duration(milliseconds: 50)); expect(updateCount, 20); expect(timeline.events.length, 9);