Merge branch 'sdk-refactor-harder-analyzer' into 'master'
[SDK] Make analyzer much more happy See merge request famedly/famedlysdk!143
This commit is contained in:
commit
877ebe7f1f
|
@ -2,7 +2,7 @@ include: package:pedantic/analysis_options.yaml
|
|||
|
||||
linter:
|
||||
rules:
|
||||
#- camel_case_types
|
||||
- camel_case_types
|
||||
|
||||
analyzer:
|
||||
# exclude:
|
||||
|
|
|
@ -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<dynamic> &&
|
||||
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<dynamic>)
|
||||
.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<String> versions = List<String>.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<User> contacts = [];
|
||||
Room contactDiscoveryRoom =
|
||||
this.getRoomByAlias("#famedlyContactDiscovery:${userID.split(":")[1]}");
|
||||
if (contactDiscoveryRoom != null)
|
||||
if (contactDiscoveryRoom != null) {
|
||||
contacts = await contactDiscoveryRoom.requestParticipants();
|
||||
else {
|
||||
} else {
|
||||
Map<String, bool> userMap = {};
|
||||
for (int i = 0; i < this.rooms.length; i++) {
|
||||
List<User> roomUsers = this.rooms[i].getParticipants();
|
||||
|
@ -366,8 +370,11 @@ class Client {
|
|||
Future<String> createRoom(
|
||||
{List<User> invite, Map<String, dynamic> params}) async {
|
||||
List<String> 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<EventUpdate> onEvent =
|
||||
new StreamController.broadcast();
|
||||
final StreamController<EventUpdate> onEvent = StreamController.broadcast();
|
||||
|
||||
/// Outside of the events there are updates for the global chat states which
|
||||
/// are handled by this signal:
|
||||
final StreamController<RoomUpdate> onRoomUpdate =
|
||||
new StreamController.broadcast();
|
||||
StreamController.broadcast();
|
||||
|
||||
/// Outside of rooms there are account updates like account_data or presences.
|
||||
final StreamController<UserUpdate> onUserEvent =
|
||||
new StreamController.broadcast();
|
||||
final StreamController<UserUpdate> onUserEvent = StreamController.broadcast();
|
||||
|
||||
/// Called when the login state e.g. user gets logged out.
|
||||
final StreamController<LoginState> onLoginStateChanged =
|
||||
new StreamController.broadcast();
|
||||
StreamController.broadcast();
|
||||
|
||||
/// Synchronization erros are coming here.
|
||||
final StreamController<MatrixException> onError =
|
||||
new StreamController.broadcast();
|
||||
StreamController.broadcast();
|
||||
|
||||
/// This is called once, when the first sync has received.
|
||||
final StreamController<bool> onFirstSync = new StreamController.broadcast();
|
||||
final StreamController<bool> onFirstSync = StreamController.broadcast();
|
||||
|
||||
/// When a new sync response is coming in, this gives the complete payload.
|
||||
final StreamController<dynamic> onSync = new StreamController.broadcast();
|
||||
final StreamController<dynamic> 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<String, String> 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<String, dynamic> jsonResp = {};
|
||||
|
@ -650,8 +659,9 @@ class Client {
|
|||
/// and returns the mxc url as a string.
|
||||
Future<String> 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,13 +711,16 @@ class Client {
|
|||
|
||||
void handleSync(dynamic sync) {
|
||||
if (sync["rooms"] is Map<String, dynamic>) {
|
||||
if (sync["rooms"]["join"] is Map<String, dynamic>)
|
||||
if (sync["rooms"]["join"] is Map<String, dynamic>) {
|
||||
_handleRooms(sync["rooms"]["join"], Membership.join);
|
||||
if (sync["rooms"]["invite"] is Map<String, dynamic>)
|
||||
}
|
||||
if (sync["rooms"]["invite"] is Map<String, dynamic>) {
|
||||
_handleRooms(sync["rooms"]["invite"], Membership.invite);
|
||||
if (sync["rooms"]["leave"] is Map<String, dynamic>)
|
||||
}
|
||||
if (sync["rooms"]["leave"] is Map<String, dynamic>) {
|
||||
_handleRooms(sync["rooms"]["leave"], Membership.leave);
|
||||
}
|
||||
}
|
||||
if (sync["presence"] is Map<String, dynamic> &&
|
||||
sync["presence"]["events"] is List<dynamic>) {
|
||||
_handleGlobalEvents(sync["presence"]["events"], "presence");
|
||||
|
@ -731,19 +745,23 @@ class Client {
|
|||
bool limitedTimeline = false;
|
||||
|
||||
if (room["unread_notifications"] is Map<String, dynamic>) {
|
||||
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<String, dynamic>) {
|
||||
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<String, dynamic> &&
|
||||
room["state"]["events"] is List<dynamic>)
|
||||
room["state"]["events"] is List<dynamic>) {
|
||||
_handleRoomEvents(id, room["state"]["events"], "state");
|
||||
}
|
||||
|
||||
if (room["invite_state"] is Map<String, dynamic> &&
|
||||
room["invite_state"]["events"] is List<dynamic>)
|
||||
room["invite_state"]["events"] is List<dynamic>) {
|
||||
_handleRoomEvents(id, room["invite_state"]["events"], "invite_state");
|
||||
}
|
||||
|
||||
if (room["timeline"] is Map<String, dynamic> &&
|
||||
room["timeline"]["events"] is List<dynamic>)
|
||||
room["timeline"]["events"] is List<dynamic>) {
|
||||
_handleRoomEvents(id, room["timeline"]["events"], "timeline");
|
||||
}
|
||||
|
||||
if (room["ephemeral"] is Map<String, dynamic> &&
|
||||
room["ephemeral"]["events"] is List<dynamic>)
|
||||
room["ephemeral"]["events"] is List<dynamic>) {
|
||||
_handleEphemerals(id, room["ephemeral"]["events"]);
|
||||
}
|
||||
|
||||
if (room["account_data"] is Map<String, dynamic> &&
|
||||
room["account_data"]["events"] is List<dynamic>)
|
||||
room["account_data"]["events"] is List<dynamic>) {
|
||||
_handleRoomEvents(id, room["account_data"]["events"], "account_data");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -839,7 +862,7 @@ class Client {
|
|||
}
|
||||
|
||||
void _handleGlobalEvents(List<dynamic> 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<String, dynamic>) {
|
||||
UserUpdate update = UserUpdate(
|
||||
|
@ -851,6 +874,7 @@ class Client {
|
|||
onUserEvent.add(update);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _handleEvent(Map<String, dynamic> event, String roomID, String type) {
|
||||
if (event["type"] is String && event["content"] is Map<String, dynamic>) {
|
||||
|
@ -908,16 +932,20 @@ 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();
|
||||
}
|
||||
sortAndUpdate();
|
||||
|
|
|
@ -105,12 +105,13 @@ class Event {
|
|||
this.room});
|
||||
|
||||
static Map<String, dynamic> getMapFromPayload(dynamic payload) {
|
||||
if (payload is String)
|
||||
if (payload is String) {
|
||||
try {
|
||||
return json.decode(payload);
|
||||
} catch (e) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
if (payload is Map<String, dynamic>) return payload;
|
||||
return {};
|
||||
}
|
||||
|
@ -141,18 +142,20 @@ class Event {
|
|||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
final Map<String, dynamic> data = Map<String, dynamic>();
|
||||
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<String> contentKeyWhiteList = [];
|
||||
switch (type) {
|
||||
case EventTypes.RoomMember:
|
||||
contentKeyWhiteList.add("membership");
|
||||
break;
|
||||
case EventTypes.RoomMember:
|
||||
contentKeyWhiteList.add("membership");
|
||||
break;
|
||||
|
@ -278,7 +278,7 @@ class Event {
|
|||
}
|
||||
List<String> toRemoveList = [];
|
||||
for (var entry in content.entries) {
|
||||
if (contentKeyWhiteList.indexOf(entry.key) == -1) {
|
||||
if (!contentKeyWhiteList.contains(entry.key)) {
|
||||
toRemoveList.add(entry.key);
|
||||
}
|
||||
}
|
||||
|
@ -304,10 +304,11 @@ class Event {
|
|||
if (!(room.roomAccountData.containsKey("m.receipt"))) return [];
|
||||
List<Receipt> 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<bool> 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<String> sendAgain({String txid}) async {
|
||||
if (status != -1) return null;
|
||||
remove();
|
||||
await remove();
|
||||
final String eventID = await room.sendTextEvent(text, txid: txid);
|
||||
return eventID;
|
||||
}
|
||||
|
|
|
@ -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,16 +127,17 @@ 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<String, dynamic>) {
|
||||
client.directChats.forEach((String userId, dynamic roomIds) {
|
||||
if (roomIds is List<dynamic>) {
|
||||
for (int i = 0; i < roomIds.length; i++)
|
||||
for (int i = 0; i < roomIds.length; i++) {
|
||||
if (roomIds[i] == this.id) {
|
||||
returnUserId = userId;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return returnUserId;
|
||||
|
@ -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<dynamic> typingMxid = ephemerals["m.typing"].content["user_ids"];
|
||||
List<User> 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<String> 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,17 +239,18 @@ 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();
|
||||
}
|
||||
|
||||
|
@ -267,7 +274,7 @@ class Room {
|
|||
}
|
||||
|
||||
Future<String> _sendRawEventNow(Map<String, dynamic> content,
|
||||
{String txid = null}) async {
|
||||
{String txid}) async {
|
||||
if (txid == null) txid = "txid${DateTime.now().millisecondsSinceEpoch}";
|
||||
final Map<String, dynamic> res = await client.jsonRequest(
|
||||
type: HTTPType.PUT,
|
||||
|
@ -276,13 +283,13 @@ class Room {
|
|||
return res["event_id"];
|
||||
}
|
||||
|
||||
Future<String> sendTextEvent(String message, {String txid = null}) =>
|
||||
Future<String> 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<String> 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<String> 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<String, dynamic> content = {
|
||||
|
@ -322,7 +329,7 @@ class Room {
|
|||
}
|
||||
|
||||
Future<String> 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<String, dynamic> content = {
|
||||
|
@ -340,7 +347,7 @@ class Room {
|
|||
}
|
||||
|
||||
Future<String> 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<String> sendEvent(Map<String, dynamic> content,
|
||||
{String txid = null}) async {
|
||||
Future<String> sendEvent(Map<String, dynamic> 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<void> 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<dynamic> &&
|
||||
resp["chunk"].length > 0 &&
|
||||
resp["end"] is String)) return;
|
||||
|
||||
if (resp["state"] is List<dynamic>) {
|
||||
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<dynamic> 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<void> addToDirectChat(String userID) async {
|
||||
Map<String, dynamic> directChats = client.directChats;
|
||||
if (directChats.containsKey(userID)) if (!directChats[userID].contains(id))
|
||||
if (directChats.containsKey(userID)) {
|
||||
if (!directChats[userID].contains(id)) {
|
||||
directChats[userID].add(id);
|
||||
else
|
||||
return; // Is already in direct chats
|
||||
else
|
||||
} else {
|
||||
return;
|
||||
} // Is already in direct chats
|
||||
} else {
|
||||
directChats[userID] = [id];
|
||||
}
|
||||
|
||||
await client.jsonRequest(
|
||||
type: HTTPType.PUT,
|
||||
|
@ -638,10 +649,11 @@ class Room {
|
|||
Future<void> removeFromDirectChat() async {
|
||||
Map<String, dynamic> 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<void> 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<Event> 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<String, dynamic> &&
|
||||
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<String, int> get powerLevels {
|
||||
Event powerLevelState = states["m.room.power_levels"];
|
||||
if (powerLevelState.content["users"] is Map<String, int>)
|
||||
if (powerLevelState.content["users"] is Map<String, int>) {
|
||||
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<String, dynamic> 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<String, dynamic> data = {};
|
||||
if (reason != null) data["reason"] = reason;
|
||||
final dynamic resp = await client.jsonRequest(
|
||||
|
|
|
@ -14,13 +14,14 @@ 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) {
|
||||
//print("[Warning] This method will be depracated in the future!");
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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<RoomUpdate> roomUpdateList = await roomUpdateListFuture;
|
||||
|
||||
|
@ -231,7 +231,7 @@ void main() {
|
|||
});
|
||||
|
||||
test('Event Update Test', () async {
|
||||
matrix.onEvent.close();
|
||||
await matrix.onEvent.close();
|
||||
|
||||
List<EventUpdate> eventUpdateList = await eventUpdateListFuture;
|
||||
|
||||
|
@ -283,7 +283,7 @@ void main() {
|
|||
});
|
||||
|
||||
test('User Update Test', () async {
|
||||
matrix.onUserEvent.close();
|
||||
await matrix.onUserEvent.close();
|
||||
|
||||
List<UserUpdate> eventUpdateList = await userUpdateListFuture;
|
||||
|
||||
|
@ -358,7 +358,7 @@ void main() {
|
|||
test('get archive', () async {
|
||||
List<Room> 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);
|
||||
|
|
|
@ -43,26 +43,28 @@ class FakeMatrixApi extends MockClient {
|
|||
|
||||
// Sync requests with timeout
|
||||
if (data is Map<String, dynamic> && 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(
|
||||
"<html><head></head><body>Not found...</body></html>", 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);
|
||||
});
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue