Merge pull request #1992 from famedly/krille/remove-event-update-type

refactor: Use Event instead of EventUpdate for storing in db
This commit is contained in:
Krille-chan 2025-01-08 09:06:37 +01:00 committed by GitHub
commit b23ad952a4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 594 additions and 578 deletions

View File

@ -154,20 +154,20 @@ class Encryption {
} }
} }
Future<void> handleEventUpdate(EventUpdate update) async { Future<void> handleEventUpdate(Event event, EventUpdateType type) async {
if (update.type == EventUpdateType.history) { if (type == EventUpdateType.history) {
return; return;
} }
if (update.content['type'].startsWith('m.key.verification.') || if (event.type.startsWith('m.key.verification.') ||
(update.content['type'] == EventTypes.Message && (event.type == EventTypes.Message &&
(update.content['content']['msgtype'] is String) && event.content
update.content['content']['msgtype'] .tryGet<String>('msgtype')
.startsWith('m.key.verification.'))) { ?.startsWith('m.key.verification.') ==
true)) {
// "just" key verification, no need to do this in sync // "just" key verification, no need to do this in sync
runInRoot(() => keyVerificationManager.handleEventUpdate(update)); runInRoot(() => keyVerificationManager.handleEventUpdate(event));
} }
if (update.content['sender'] == client.userID && if (event.senderId == client.userID && event.status.isSynced) {
update.content['unsigned']?['transaction_id'] == null) {
// maybe we need to re-try SSSS secrets // maybe we need to re-try SSSS secrets
runInRoot(() => ssss.periodicallyRequestMissingCache()); runInRoot(() => ssss.periodicallyRequestMissingCache());
} }
@ -348,11 +348,9 @@ class Encryption {
event.room.setState(event); event.room.setState(event);
} }
await client.database?.storeEventUpdate( await client.database?.storeEventUpdate(
EventUpdate( event.room.id,
content: event.toJson(), event,
roomID: event.room.id, updateType,
type: updateType,
),
client, client,
); );
} }

View File

@ -88,29 +88,29 @@ class KeyVerificationManager {
} }
} }
Future<void> handleEventUpdate(EventUpdate update) async { Future<void> handleEventUpdate(Event update) async {
final event = update.content; final type = update.type.startsWith('m.key.verification.')
final type = event['type'].startsWith('m.key.verification.') ? update.type
? event['type'] : update.content.tryGet<String>('msgtype');
: event['content']['msgtype'];
if (type == null || if (type == null ||
!type.startsWith('m.key.verification.') || !type.startsWith('m.key.verification.') ||
client.verificationMethods.isEmpty) { client.verificationMethods.isEmpty) {
return; return;
} }
if (type == EventTypes.KeyVerificationRequest) { if (type == EventTypes.KeyVerificationRequest) {
event['content']['timestamp'] = event['origin_server_ts']; update.content['timestamp'] =
update.originServerTs.millisecondsSinceEpoch;
} }
final transactionId = final transactionId =
KeyVerification.getTransactionId(event['content']) ?? event['event_id']; KeyVerification.getTransactionId(update.content) ?? update.eventId;
final req = _requests[transactionId]; final req = _requests[transactionId];
if (req != null) { if (req != null) {
final otherDeviceId = event['content']['from_device']; final otherDeviceId = update.content.tryGet<String>('from_device');
if (event['sender'] != client.userID) { if (update.senderId != client.userID) {
await req.handlePayload(type, event['content'], event['event_id']); await req.handlePayload(type, update.content, update.eventId);
} else if (event['sender'] == client.userID && } else if (update.senderId == client.userID &&
otherDeviceId != null && otherDeviceId != null &&
otherDeviceId != client.deviceID) { otherDeviceId != client.deviceID) {
// okay, another of our devices answered // okay, another of our devices answered
@ -118,22 +118,22 @@ class KeyVerificationManager {
req.dispose(); req.dispose();
_requests.remove(transactionId); _requests.remove(transactionId);
} }
} else if (event['sender'] != client.userID) { } else if (update.senderId != client.userID) {
if (!{EventTypes.KeyVerificationRequest, EventTypes.KeyVerificationStart} if (!{EventTypes.KeyVerificationRequest, EventTypes.KeyVerificationStart}
.contains(type)) { .contains(type)) {
return; // we can only start on these return; // we can only start on these
} }
final room = client.getRoomById(update.roomID) ?? final room = client.getRoomById(update.roomId!) ??
Room(id: update.roomID, client: client); Room(id: update.roomId!, client: client);
final newKeyRequest = KeyVerification( final newKeyRequest = KeyVerification(
encryption: encryption, encryption: encryption,
userId: event['sender'], userId: update.senderId,
room: room, room: room,
); );
await newKeyRequest.handlePayload( await newKeyRequest.handlePayload(
type, type,
event['content'], update.content,
event['event_id'], update.eventId,
); );
if (newKeyRequest.state != KeyVerificationState.askAccept) { if (newKeyRequest.state != KeyVerificationState.askAccept) {
// something went wrong, let's just dispose the request // something went wrong, let's just dispose the request

View File

@ -1647,8 +1647,28 @@ class Client extends MatrixApi {
/// the app receives a new synchronization, this event is called for every signal /// 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: /// 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"} ) /// onRoomEvent( "m.room.message", "!chat_id:server.com", "timeline", {sender: "@bob:server.com", body: "Hello world"} )
// ignore: deprecated_member_use_from_same_package
@Deprecated(
'Use `onTimelineEvent`, `onHistoryEvent` or `onNotification` instead.',
)
final CachedStreamController<EventUpdate> onEvent = CachedStreamController(); final CachedStreamController<EventUpdate> onEvent = CachedStreamController();
/// A stream of all incoming timeline events for all rooms **after**
/// decryption. The events are coming in the same order as they come down from
/// the sync.
final CachedStreamController<Event> onTimelineEvent =
CachedStreamController();
/// A stream for all incoming historical timeline events **after** decryption
/// triggered by a `Room.requestHistory()` call or a method which calls it.
final CachedStreamController<Event> onHistoryEvent = CachedStreamController();
/// A stream of incoming Events **after** decryption which **should** trigger
/// a (local) notification. This includes timeline events but also
/// invite states. Excluded events are those sent by the user themself or
/// not matching the push rules.
final CachedStreamController<Event> onNotification = CachedStreamController();
/// The onToDeviceEvent is called when there comes a new to device event. It is /// The onToDeviceEvent is called when there comes a new to device event. It is
/// already decrypted if necessary. /// already decrypted if necessary.
final CachedStreamController<ToDeviceEvent> onToDeviceEvent = final CachedStreamController<ToDeviceEvent> onToDeviceEvent =
@ -1889,11 +1909,9 @@ class Client extends MatrixApi {
if (storeInDatabase) { if (storeInDatabase) {
await database?.transaction(() async { await database?.transaction(() async {
await database.storeEventUpdate( await database.storeEventUpdate(
EventUpdate( roomId,
roomID: roomId, event,
type: EventUpdateType.timeline, EventUpdateType.timeline,
content: event.toJson(),
),
this, this,
); );
}); });
@ -2768,12 +2786,6 @@ class Client extends MatrixApi {
} }
} }
final update = EventUpdate(
roomID: room.id,
type: type,
content: event.toJson(),
);
// Any kind of member change? We should invalidate the profile then: // Any kind of member change? We should invalidate the profile then:
if (event.type == EventTypes.RoomMember) { if (event.type == EventTypes.RoomMember) {
final userId = event.stateKey; final userId = event.stateKey;
@ -2797,23 +2809,70 @@ class Client extends MatrixApi {
room.setState(user); room.setState(user);
} }
} }
_updateRoomsByEventUpdate(room, update); _updateRoomsByEventUpdate(room, event, type);
if (store) { if (store) {
await database?.storeEventUpdate(update, this); await database?.storeEventUpdate(room.id, event, type, this);
} }
if (encryptionEnabled) { if (event is MatrixEvent && encryptionEnabled) {
await encryption?.handleEventUpdate(update); await encryption?.handleEventUpdate(
Event.fromMatrixEvent(event, room),
type,
);
}
// ignore: deprecated_member_use_from_same_package
onEvent.add(
// ignore: deprecated_member_use_from_same_package
EventUpdate(
roomID: room.id,
type: type,
content: event.toJson(),
),
);
if (event is MatrixEvent) {
final timelineEvent = Event.fromMatrixEvent(event, room);
switch (type) {
case EventUpdateType.timeline:
onTimelineEvent.add(timelineEvent);
if (prevBatch != null &&
timelineEvent.senderId != userID &&
room.notificationCount > 0 &&
pushruleEvaluator.match(timelineEvent).notify) {
onNotification.add(timelineEvent);
}
break;
case EventUpdateType.history:
onHistoryEvent.add(timelineEvent);
break;
default:
break;
}
}
// Trigger local notification for a new invite:
if (prevBatch != null &&
type == EventUpdateType.inviteState &&
event.type == EventTypes.RoomMember &&
event.stateKey == userID) {
onNotification.add(
Event(
type: event.type,
eventId: 'invite_for_${room.id}',
senderId: event.senderId,
originServerTs: DateTime.now(),
stateKey: event.stateKey,
content: event.content,
room: room,
),
);
} }
onEvent.add(update);
if (prevBatch != null && if (prevBatch != null &&
(type == EventUpdateType.timeline || (type == EventUpdateType.timeline ||
type == EventUpdateType.decryptedTimelineQueue)) { type == EventUpdateType.decryptedTimelineQueue)) {
if ((update.content if (event is MatrixEvent &&
.tryGet<String>('type') (event.type.startsWith(CallConstants.callEventsRegxp))) {
?.startsWith(CallConstants.callEventsRegxp) ?? final callEvent = Event.fromMatrixEvent(event, room);
false)) {
final callEvent = Event.fromJson(update.content, room);
callEvents.add(callEvent); callEvents.add(callEvent);
} }
} }
@ -2913,23 +2972,34 @@ class Client extends MatrixApi {
return room; return room;
} }
void _updateRoomsByEventUpdate(Room room, EventUpdate eventUpdate) { void _updateRoomsByEventUpdate(
if (eventUpdate.type == EventUpdateType.history) return; Room room,
StrippedStateEvent eventUpdate,
EventUpdateType type,
) {
if (type == EventUpdateType.history) return;
switch (eventUpdate.type) { switch (type) {
case EventUpdateType.inviteState: case EventUpdateType.inviteState:
room.setState(StrippedStateEvent.fromJson(eventUpdate.content)); room.setState(eventUpdate);
break; break;
case EventUpdateType.state: case EventUpdateType.state:
case EventUpdateType.timeline: case EventUpdateType.timeline:
final event = Event.fromJson(eventUpdate.content, room); if (eventUpdate is! MatrixEvent) {
Logs().wtf(
'Passed in a ${eventUpdate.runtimeType} with $type to _updateRoomsByEventUpdate(). This should never happen!',
);
assert(eventUpdate is! MatrixEvent);
return;
}
final event = Event.fromMatrixEvent(eventUpdate, room);
// Update the room state: // Update the room state:
if (event.stateKey != null && if (event.stateKey != null &&
(!room.partial || importantStateEvents.contains(event.type))) { (!room.partial || importantStateEvents.contains(event.type))) {
room.setState(event); room.setState(event);
} }
if (eventUpdate.type != EventUpdateType.timeline) break; if (type != EventUpdateType.timeline) break;
// If last event is null or not a valid room preview event anyway, // If last event is null or not a valid room preview event anyway,
// just use this: // just use this:

View File

@ -80,7 +80,12 @@ abstract class DatabaseApi {
/// Stores an EventUpdate object in the database. Must be called inside of /// Stores an EventUpdate object in the database. Must be called inside of
/// [transaction]. /// [transaction].
Future<void> storeEventUpdate(EventUpdate eventUpdate, Client client); Future<void> storeEventUpdate(
String roomId,
StrippedStateEvent event,
EventUpdateType type,
Client client,
);
Future<Event?> getEventById(String eventId, Room room); Future<Event?> getEventById(String eventId, Room room);

View File

@ -1105,7 +1105,17 @@ class HiveCollectionsDatabase extends DatabaseApi {
} }
@override @override
Future<void> storeEventUpdate(EventUpdate eventUpdate, Client client) async { Future<void> storeEventUpdate(
String roomId,
StrippedStateEvent event,
EventUpdateType type,
Client client,
) async {
final eventUpdate = EventUpdate(
roomID: roomId,
content: event.toJson(),
type: type,
);
final tmpRoom = client.getRoomById(eventUpdate.roomID) ?? final tmpRoom = client.getRoomById(eventUpdate.roomID) ??
Room(id: eventUpdate.roomID, client: client); Room(id: eventUpdate.roomID, client: client);

View File

@ -1093,45 +1093,37 @@ class MatrixSdkDatabase extends DatabaseApi with DatabaseFileStorage {
} }
@override @override
Future<void> storeEventUpdate(EventUpdate eventUpdate, Client client) async { Future<void> storeEventUpdate(
final tmpRoom = client.getRoomById(eventUpdate.roomID) ?? String roomId,
Room(id: eventUpdate.roomID, client: client); StrippedStateEvent event,
EventUpdateType type,
Client client,
) async {
final tmpRoom =
client.getRoomById(roomId) ?? Room(id: roomId, client: client);
// In case of this is a redaction event // In case of this is a redaction event
if (eventUpdate.content['type'] == EventTypes.Redaction) { if (event.type == EventTypes.Redaction && event is MatrixEvent) {
final eventId = eventUpdate.content.tryGet<String>('redacts'); final redactionEvent = Event.fromMatrixEvent(event, tmpRoom);
final event = final eventId = redactionEvent.redacts;
final redactedEvent =
eventId != null ? await getEventById(eventId, tmpRoom) : null; eventId != null ? await getEventById(eventId, tmpRoom) : null;
if (event != null) { if (redactedEvent != null) {
event.setRedactionEvent(Event.fromJson(eventUpdate.content, tmpRoom)); redactedEvent.setRedactionEvent(redactionEvent);
await _eventsBox.put( await _eventsBox.put(
TupleKey(eventUpdate.roomID, event.eventId).toString(), TupleKey(roomId, redactedEvent.eventId).toString(),
event.toJson(), redactedEvent.toJson(),
); );
if (tmpRoom.lastEvent?.eventId == event.eventId) {
if (client.importantStateEvents.contains(event.type)) {
await _preloadRoomStateBox.put(
TupleKey(eventUpdate.roomID, event.type, '').toString(),
event.toJson(),
);
} else {
await _nonPreloadRoomStateBox.put(
TupleKey(eventUpdate.roomID, event.type, '').toString(),
event.toJson(),
);
}
}
} }
} }
// Store a common message event // Store a common message event
if ({EventUpdateType.timeline, EventUpdateType.history} if ({EventUpdateType.timeline, EventUpdateType.history}.contains(type) &&
.contains(eventUpdate.type)) { event is MatrixEvent) {
final eventId = eventUpdate.content['event_id']; final timelineEvent = Event.fromMatrixEvent(event, tmpRoom);
// Is this ID already in the store? // Is this ID already in the store?
final prevEvent = await _eventsBox final prevEvent =
.get(TupleKey(eventUpdate.roomID, eventId).toString()); await _eventsBox.get(TupleKey(roomId, event.eventId).toString());
final prevStatus = prevEvent == null final prevStatus = prevEvent == null
? null ? null
: () { : () {
@ -1144,13 +1136,7 @@ class MatrixSdkDatabase extends DatabaseApi with DatabaseFileStorage {
}(); }();
// calculate the status // calculate the status
final newStatus = eventStatusFromInt( final newStatus = timelineEvent.status;
eventUpdate.content.tryGet<int>('status') ??
eventUpdate.content
.tryGetMap<String, dynamic>('unsigned')
?.tryGet<int>(messageSendingStatusKey) ??
EventStatus.synced.intValue,
);
// Is this the response to a sending event which is already synced? Then // Is this the response to a sending event which is already synced? Then
// there is nothing to do here. // there is nothing to do here.
@ -1165,29 +1151,25 @@ class MatrixSdkDatabase extends DatabaseApi with DatabaseFileStorage {
newStatus, newStatus,
); );
// Add the status and the sort order to the content so it get stored timelineEvent.status = status;
eventUpdate.content['unsigned'] ??= <String, dynamic>{};
eventUpdate.content['unsigned'][messageSendingStatusKey] =
eventUpdate.content['status'] = status.intValue;
final eventId = timelineEvent.eventId;
// In case this event has sent from this account we have a transaction ID // In case this event has sent from this account we have a transaction ID
final transactionId = eventUpdate.content final transactionId =
.tryGetMap<String, dynamic>('unsigned') timelineEvent.unsigned?.tryGet<String>('transaction_id');
?.tryGet<String>('transaction_id');
await _eventsBox.put( await _eventsBox.put(
TupleKey(eventUpdate.roomID, eventId).toString(), TupleKey(roomId, eventId).toString(),
eventUpdate.content, timelineEvent.toJson(),
); );
// Update timeline fragments // Update timeline fragments
final key = TupleKey(eventUpdate.roomID, status.isSent ? '' : 'SENDING') final key = TupleKey(roomId, status.isSent ? '' : 'SENDING').toString();
.toString();
final eventIds = final eventIds =
List<String>.from(await _timelineFragmentsBox.get(key) ?? []); List<String>.from(await _timelineFragmentsBox.get(key) ?? []);
if (!eventIds.contains(eventId)) { if (!eventIds.contains(eventId)) {
if (eventUpdate.type == EventUpdateType.history) { if (type == EventUpdateType.history) {
eventIds.add(eventId); eventIds.add(eventId);
} else { } else {
eventIds.insert(0, eventId); eventIds.insert(0, eventId);
@ -1196,7 +1178,7 @@ class MatrixSdkDatabase extends DatabaseApi with DatabaseFileStorage {
} else if (status.isSynced && } else if (status.isSynced &&
prevStatus != null && prevStatus != null &&
prevStatus.isSent && prevStatus.isSent &&
eventUpdate.type != EventUpdateType.history) { type != EventUpdateType.history) {
// Status changes from 1 -> 2? Make sure event is correctly sorted. // Status changes from 1 -> 2? Make sure event is correctly sorted.
eventIds.remove(eventId); eventIds.remove(eventId);
eventIds.insert(0, eventId); eventIds.insert(0, eventId);
@ -1204,7 +1186,7 @@ class MatrixSdkDatabase extends DatabaseApi with DatabaseFileStorage {
// If event comes from server timeline, remove sending events with this ID // If event comes from server timeline, remove sending events with this ID
if (status.isSent) { if (status.isSent) {
final key = TupleKey(eventUpdate.roomID, 'SENDING').toString(); final key = TupleKey(roomId, 'SENDING').toString();
final eventIds = final eventIds =
List<String>.from(await _timelineFragmentsBox.get(key) ?? []); List<String>.from(await _timelineFragmentsBox.get(key) ?? []);
final i = eventIds.indexWhere((id) => id == eventId); final i = eventIds.indexWhere((id) => id == eventId);
@ -1215,37 +1197,38 @@ class MatrixSdkDatabase extends DatabaseApi with DatabaseFileStorage {
// Is there a transaction id? Then delete the event with this id. // Is there a transaction id? Then delete the event with this id.
if (!status.isError && !status.isSending && transactionId != null) { if (!status.isError && !status.isSending && transactionId != null) {
await removeEvent(transactionId, eventUpdate.roomID); await removeEvent(transactionId, roomId);
} }
} }
final stateKey = eventUpdate.content['state_key']; final stateKey = event.stateKey;
// Store a common state event // Store a common state event
if (stateKey != null && if (stateKey != null &&
// Don't store events as state updates when paginating backwards. // Don't store events as state updates when paginating backwards.
(eventUpdate.type == EventUpdateType.timeline || {
eventUpdate.type == EventUpdateType.state || EventUpdateType.timeline,
eventUpdate.type == EventUpdateType.inviteState)) { EventUpdateType.state,
if (eventUpdate.content['type'] == EventTypes.RoomMember) { EventUpdateType.inviteState,
}.contains(type)) {
if (event.type == EventTypes.RoomMember) {
await _roomMembersBox.put( await _roomMembersBox.put(
TupleKey( TupleKey(
eventUpdate.roomID, roomId,
eventUpdate.content['state_key'], stateKey,
).toString(), ).toString(),
eventUpdate.content, event.toJson(),
); );
} else { } else {
final type = eventUpdate.content['type'] as String; final roomStateBox = client.importantStateEvents.contains(event.type)
final roomStateBox = client.importantStateEvents.contains(type)
? _preloadRoomStateBox ? _preloadRoomStateBox
: _nonPreloadRoomStateBox; : _nonPreloadRoomStateBox;
final key = TupleKey( final key = TupleKey(
eventUpdate.roomID, roomId,
type, event.type,
stateKey, stateKey,
).toString(); ).toString();
await roomStateBox.put(key, eventUpdate.content); await roomStateBox.put(key, event.toJson());
} }
} }
} }

View File

@ -88,6 +88,7 @@ class Event extends MatrixEvent {
Map<String, dynamic>? unsigned, Map<String, dynamic>? unsigned,
Map<String, dynamic>? prevContent, Map<String, dynamic>? prevContent,
String? stateKey, String? stateKey,
super.redacts,
required this.room, required this.room,
MatrixEvent? originalSource, MatrixEvent? originalSource,
}) : _originalSource = originalSource, }) : _originalSource = originalSource,
@ -171,7 +172,7 @@ class Event extends MatrixEvent {
status: status ?? status: status ??
eventStatusFromInt( eventStatusFromInt(
matrixEvent.unsigned matrixEvent.unsigned
?.tryGet<int>('messageSendingStatusKey') ?? ?.tryGet<int>(messageSendingStatusKey) ??
defaultStatus.intValue, defaultStatus.intValue,
), ),
content: matrixEvent.content, content: matrixEvent.content,
@ -212,6 +213,7 @@ class Event extends MatrixEvent {
), ),
unsigned: unsigned, unsigned: unsigned,
room: room, room: room,
redacts: jsonPayload['redacts'],
originalSource: originalSource:
originalSource.isEmpty ? null : MatrixEvent.fromJson(originalSource), originalSource.isEmpty ? null : MatrixEvent.fromJson(originalSource),
); );

View File

@ -1674,11 +1674,9 @@ class Room {
for (final user in users) { for (final user in users) {
setState(user); // at *least* cache this in-memory setState(user); // at *least* cache this in-memory
await client.database?.storeEventUpdate( await client.database?.storeEventUpdate(
EventUpdate( id,
roomID: id, user,
type: EventUpdateType.state, EventUpdateType.state,
content: user.toJson(),
),
client, client,
); );
} }
@ -1755,11 +1753,9 @@ class Room {
// Store user in database: // Store user in database:
await client.database?.transaction(() async { await client.database?.transaction(() async {
await client.database?.storeEventUpdate( await client.database?.storeEventUpdate(
EventUpdate( id,
content: foundUser.toJson(), foundUser,
roomID: id, EventUpdateType.state,
type: EventUpdateType.state,
),
client, client,
); );
}); });

View File

@ -41,7 +41,8 @@ class Timeline {
final void Function(int index)? onRemove; final void Function(int index)? onRemove;
final void Function()? onNewEvent; final void Function()? onNewEvent;
StreamSubscription<EventUpdate>? sub; StreamSubscription<Event>? timelineSub;
StreamSubscription<Event>? historySub;
StreamSubscription<SyncUpdate>? roomSub; StreamSubscription<SyncUpdate>? roomSub;
StreamSubscription<String>? sessionIdReceivedSub; StreamSubscription<String>? sessionIdReceivedSub;
StreamSubscription<String>? cancelSendEventSub; StreamSubscription<String>? cancelSendEventSub;
@ -322,7 +323,18 @@ class Timeline {
this.onNewEvent, this.onNewEvent,
required this.chunk, required this.chunk,
}) { }) {
sub = room.client.onEvent.stream.listen(_handleEventUpdate); timelineSub = room.client.onTimelineEvent.stream.listen(
(event) => _handleEventUpdate(
event,
EventUpdateType.timeline,
),
);
historySub = room.client.onHistoryEvent.stream.listen(
(event) => _handleEventUpdate(
event,
EventUpdateType.history,
),
);
// If the timeline is limited we want to clear our events cache // If the timeline is limited we want to clear our events cache
roomSub = room.client.onSync.stream roomSub = room.client.onSync.stream
@ -368,7 +380,9 @@ class Timeline {
/// Don't forget to call this before you dismiss this object! /// Don't forget to call this before you dismiss this object!
void cancelSubscriptions() { void cancelSubscriptions() {
// ignore: discarded_futures // ignore: discarded_futures
sub?.cancel(); timelineSub?.cancel();
// ignore: discarded_futures
historySub?.cancel();
// ignore: discarded_futures // ignore: discarded_futures
roomSub?.cancel(); roomSub?.cancel();
// ignore: discarded_futures // ignore: discarded_futures
@ -512,43 +526,35 @@ class Timeline {
} }
} }
void _handleEventUpdate(EventUpdate eventUpdate, {bool update = true}) { void _handleEventUpdate(
Event event,
EventUpdateType type, {
bool update = true,
}) {
try { try {
if (eventUpdate.roomID != room.id) return; if (event.roomId != room.id) return;
if (eventUpdate.type != EventUpdateType.timeline && if (type != EventUpdateType.timeline && type != EventUpdateType.history) {
eventUpdate.type != EventUpdateType.history) {
return; return;
} }
if (eventUpdate.type == EventUpdateType.timeline) { if (type == EventUpdateType.timeline) {
onNewEvent?.call(); onNewEvent?.call();
} }
if (!allowNewEvent) return; if (!allowNewEvent) return;
final status = eventStatusFromInt( final status = event.status;
eventUpdate.content['status'] ??
(eventUpdate.content['unsigned'] is Map<String, dynamic>
? eventUpdate.content['unsigned'][messageSendingStatusKey]
: null) ??
EventStatus.synced.intValue,
);
final i = _findEvent( final i = _findEvent(
event_id: eventUpdate.content['event_id'], event_id: event.eventId,
unsigned_txid: eventUpdate.content['unsigned'] is Map unsigned_txid: event.unsigned?.tryGet<String>('transaction_id'),
? eventUpdate.content['unsigned']['transaction_id']
: null,
); );
if (i < events.length) { if (i < events.length) {
// if the old status is larger than the new one, we also want to preserve the old status // if the old status is larger than the new one, we also want to preserve the old status
final oldStatus = events[i].status; final oldStatus = events[i].status;
events[i] = Event.fromJson( events[i] = event;
eventUpdate.content,
room,
);
// do we preserve the status? we should allow 0 -> -1 updates and status increases // do we preserve the status? we should allow 0 -> -1 updates and status increases
if ((latestEventStatus(status, oldStatus) == oldStatus) && if ((latestEventStatus(status, oldStatus) == oldStatus) &&
!(status.isError && oldStatus.isSending)) { !(status.isError && oldStatus.isSending)) {
@ -557,34 +563,28 @@ class Timeline {
addAggregatedEvent(events[i]); addAggregatedEvent(events[i]);
onChange?.call(i); onChange?.call(i);
} else { } else {
final newEvent = Event.fromJson( if (type == EventUpdateType.history &&
eventUpdate.content,
room,
);
if (eventUpdate.type == EventUpdateType.history &&
events.indexWhere( events.indexWhere(
(e) => e.eventId == eventUpdate.content['event_id'], (e) => e.eventId == event.eventId,
) != ) !=
-1) { -1) {
return; return;
} }
var index = events.length; var index = events.length;
if (eventUpdate.type == EventUpdateType.history) { if (type == EventUpdateType.history) {
events.add(newEvent); events.add(event);
} else { } else {
index = events.firstIndexWhereNotError; index = events.firstIndexWhereNotError;
events.insert(index, newEvent); events.insert(index, event);
} }
onInsert?.call(index); onInsert?.call(index);
addAggregatedEvent(newEvent); addAggregatedEvent(event);
} }
// Handle redaction events // Handle redaction events
if (eventUpdate.content['type'] == EventTypes.Redaction) { if (event.type == EventTypes.Redaction) {
final index = final index = _findEvent(event_id: event.redacts);
_findEvent(event_id: eventUpdate.content.tryGet<String>('redacts'));
if (index < events.length) { if (index < events.length) {
removeAggregatedEvent(events[index]); removeAggregatedEvent(events[index]);
@ -598,12 +598,7 @@ class Timeline {
} }
} }
events[index].setRedactionEvent( events[index].setRedactionEvent(event);
Event.fromJson(
eventUpdate.content,
room,
),
);
onChange?.call(index); onChange?.call(index);
} }
} }

View File

@ -33,8 +33,7 @@ enum EventUpdateType {
decryptedTimelineQueue, decryptedTimelineQueue,
} }
/// Represents a new event (e.g. a message in a room) or an update for an @Deprecated('Use `Event` class directly instead.')
/// already known event.
class EventUpdate { class EventUpdate {
/// Usually 'timeline', 'state' or whatever. /// Usually 'timeline', 'state' or whatever.
final EventUpdateType type; final EventUpdateType type;

View File

@ -114,7 +114,7 @@ void main() {
httpClient: FakeMatrixApi(), httpClient: FakeMatrixApi(),
databaseBuilder: getDatabase, databaseBuilder: getDatabase,
); );
final eventUpdateListFuture = matrix.onEvent.stream.toList(); final eventUpdateListFuture = matrix.onTimelineEvent.stream.toList();
final toDeviceUpdateListFuture = matrix.onToDeviceEvent.stream.toList(); final toDeviceUpdateListFuture = matrix.onToDeviceEvent.stream.toList();
var presenceCounter = 0; var presenceCounter = 0;
var accountDataCounter = 0; var accountDataCounter = 0;
@ -278,43 +278,20 @@ void main() {
null, null,
); );
await matrix.onEvent.close(); await matrix.onTimelineEvent.close();
final eventUpdateList = await eventUpdateListFuture; final eventUpdateList = await eventUpdateListFuture;
expect(eventUpdateList.length, 13); expect(eventUpdateList.length, 3);
expect(eventUpdateList[0].content['type'], 'm.room.member'); expect(eventUpdateList[0].type, 'm.room.member');
expect(eventUpdateList[0].roomID, '!726s6s6q:example.com'); expect(eventUpdateList[0].roomId, '!726s6s6q:example.com');
expect(eventUpdateList[0].type, EventUpdateType.state);
expect(eventUpdateList[1].content['type'], 'm.room.canonical_alias'); expect(eventUpdateList[1].type, 'm.room.message');
expect(eventUpdateList[1].roomID, '!726s6s6q:example.com'); expect(eventUpdateList[1].roomId, '!726s6s6q:example.com');
expect(eventUpdateList[1].type, EventUpdateType.state);
expect(eventUpdateList[2].content['type'], 'm.room.encryption'); expect(eventUpdateList[2].type, 'm.room.message');
expect(eventUpdateList[2].roomID, '!726s6s6q:example.com'); expect(eventUpdateList[2].roomId, '!726s6s6f:example.com');
expect(eventUpdateList[2].type, EventUpdateType.state);
expect(eventUpdateList[3].content['type'], 'm.room.pinned_events');
expect(eventUpdateList[3].roomID, '!726s6s6q:example.com');
expect(eventUpdateList[3].type, EventUpdateType.state);
expect(eventUpdateList[4].content['type'], 'm.room.member');
expect(eventUpdateList[4].roomID, '!726s6s6q:example.com');
expect(eventUpdateList[4].type, EventUpdateType.timeline);
expect(eventUpdateList[5].content['type'], 'm.room.message');
expect(eventUpdateList[5].roomID, '!726s6s6q:example.com');
expect(eventUpdateList[5].type, EventUpdateType.timeline);
expect(eventUpdateList[6].content['type'], 'm.room.member');
expect(eventUpdateList[6].roomID, '!calls:example.com');
expect(eventUpdateList[6].type, EventUpdateType.state);
expect(eventUpdateList[7].content['type'], 'm.room.member');
expect(eventUpdateList[7].roomID, '!calls:example.com');
expect(eventUpdateList[7].type, EventUpdateType.state);
expect( expect(
matrix matrix

View File

@ -219,10 +219,9 @@ void main() {
}); });
test('storeEventUpdate', () async { test('storeEventUpdate', () async {
await database.storeEventUpdate( await database.storeEventUpdate(
EventUpdate( '!testroom:example.com',
roomID: '!testroom:example.com', MatrixEvent.fromJson(
type: EventUpdateType.timeline, {
content: {
'type': EventTypes.Message, 'type': EventTypes.Message,
'content': { 'content': {
'body': '* edit 3', 'body': '* edit 3',
@ -236,10 +235,12 @@ void main() {
'rel_type': RelationshipTypes.edit, 'rel_type': RelationshipTypes.edit,
}, },
}, },
'origin_server_ts': DateTime.now().millisecondsSinceEpoch,
'event_id': '\$event:example.com', 'event_id': '\$event:example.com',
'sender': '@bob:example.org', 'sender': '@bob:example.org',
}, },
), ),
EventUpdateType.timeline,
Client('testclient'), Client('testclient'),
); );
}); });
@ -263,10 +264,9 @@ void main() {
); );
await database.storeEventUpdate( await database.storeEventUpdate(
EventUpdate( roomid,
roomID: roomid, MatrixEvent.fromJson(
type: EventUpdateType.timeline, {
content: {
'type': EventTypes.RoomName, 'type': EventTypes.RoomName,
'content': { 'content': {
'name': 'start', 'name': 'start',
@ -274,8 +274,10 @@ void main() {
'event_id': '\$eventstart:example.com', 'event_id': '\$eventstart:example.com',
'sender': '@bob:example.org', 'sender': '@bob:example.org',
'state_key': '', 'state_key': '',
'origin_server_ts': DateTime.now().millisecondsSinceEpoch,
}, },
), ),
EventUpdateType.timeline,
client, client,
); );
@ -288,10 +290,9 @@ void main() {
expect(room?.roomAccountData['m.test']?.content, {'foo': 'bar'}); expect(room?.roomAccountData['m.test']?.content, {'foo': 'bar'});
await database.storeEventUpdate( await database.storeEventUpdate(
EventUpdate( roomid,
roomID: roomid, MatrixEvent.fromJson(
type: EventUpdateType.timeline, {
content: {
'type': EventTypes.RoomName, 'type': EventTypes.RoomName,
'content': { 'content': {
'name': 'update', 'name': 'update',
@ -299,8 +300,10 @@ void main() {
'event_id': '\$eventupdate:example.com', 'event_id': '\$eventupdate:example.com',
'sender': '@bob:example.org', 'sender': '@bob:example.org',
'state_key': '', 'state_key': '',
'origin_server_ts': DateTime.now().millisecondsSinceEpoch,
}, },
), ),
EventUpdateType.timeline,
client, client,
); );
@ -309,10 +312,9 @@ void main() {
expect(room?.name, 'update'); expect(room?.name, 'update');
await database.storeEventUpdate( await database.storeEventUpdate(
EventUpdate( roomid,
roomID: roomid, MatrixEvent.fromJson(
type: EventUpdateType.state, {
content: {
'type': EventTypes.RoomName, 'type': EventTypes.RoomName,
'content': { 'content': {
'name': 'update2', 'name': 'update2',
@ -320,8 +322,10 @@ void main() {
'event_id': '\$eventupdate2:example.com', 'event_id': '\$eventupdate2:example.com',
'sender': '@bob:example.org', 'sender': '@bob:example.org',
'state_key': '', 'state_key': '',
'origin_server_ts': DateTime.now().millisecondsSinceEpoch,
}, },
), ),
EventUpdateType.state,
client, client,
); );
@ -330,10 +334,9 @@ void main() {
expect(room?.name, 'update2'); expect(room?.name, 'update2');
await database.storeEventUpdate( await database.storeEventUpdate(
EventUpdate( roomid,
roomID: roomid, StrippedStateEvent.fromJson(
type: EventUpdateType.inviteState, {
content: {
'type': EventTypes.RoomName, 'type': EventTypes.RoomName,
'content': { 'content': {
'name': 'update3', 'name': 'update3',
@ -343,6 +346,7 @@ void main() {
'state_key': '', 'state_key': '',
}, },
), ),
EventUpdateType.inviteState,
client, client,
); );
@ -351,10 +355,9 @@ void main() {
expect(room?.name, 'update3'); expect(room?.name, 'update3');
await database.storeEventUpdate( await database.storeEventUpdate(
EventUpdate( roomid,
roomID: roomid, MatrixEvent.fromJson(
type: EventUpdateType.history, {
content: {
'type': EventTypes.RoomName, 'type': EventTypes.RoomName,
'content': { 'content': {
'name': 'notupdate', 'name': 'notupdate',
@ -362,8 +365,10 @@ void main() {
'event_id': '\$eventnotupdate:example.com', 'event_id': '\$eventnotupdate:example.com',
'sender': '@bob:example.org', 'sender': '@bob:example.org',
'state_key': '', 'state_key': '',
'origin_server_ts': DateTime.now().millisecondsSinceEpoch,
}, },
), ),
EventUpdateType.history,
client, client,
); );

View File

@ -28,21 +28,20 @@ import 'package:matrix/matrix.dart';
import '../fake_client.dart'; import '../fake_client.dart';
import '../fake_database.dart'; import '../fake_database.dart';
EventUpdate getLastSentEvent(KeyVerification req) { Event getLastSentEvent(KeyVerification req) {
final entry = FakeMatrixApi.calledEndpoints.entries final entry = FakeMatrixApi.calledEndpoints.entries
.firstWhere((p) => p.key.contains('/send/')); .firstWhere((p) => p.key.contains('/send/'));
final type = entry.key.split('/')[6]; final type = entry.key.split('/')[6];
final content = json.decode(entry.value.first); final content = json.decode(entry.value.first);
return EventUpdate( return Event.fromJson(
content: { {
'event_id': req.transactionId, 'event_id': req.transactionId,
'type': type, 'type': type,
'content': content, 'content': content,
'origin_server_ts': DateTime.now().millisecondsSinceEpoch, 'origin_server_ts': DateTime.now().millisecondsSinceEpoch,
'sender': req.client.userID, 'sender': req.client.userID,
}, },
type: EventUpdateType.timeline, req.room!,
roomID: req.room!.id,
); );
} }
@ -615,8 +614,8 @@ void main() async {
await sub.cancel(); await sub.cancel();
await client2.encryption!.keyVerificationManager.handleEventUpdate( await client2.encryption!.keyVerificationManager.handleEventUpdate(
EventUpdate( Event.fromJson(
content: { {
'event_id': req2.transactionId, 'event_id': req2.transactionId,
'type': EventTypes.KeyVerificationReady, 'type': EventTypes.KeyVerificationReady,
'content': { 'content': {
@ -630,8 +629,7 @@ void main() async {
'origin_server_ts': DateTime.now().millisecondsSinceEpoch, 'origin_server_ts': DateTime.now().millisecondsSinceEpoch,
'sender': client2.userID, 'sender': client2.userID,
}, },
type: EventUpdateType.timeline, req2.room!,
roomID: req2.room!.id,
), ),
); );
expect(req2.state, KeyVerificationState.error); expect(req2.state, KeyVerificationState.error);

View File

@ -46,89 +46,105 @@ void main() {
final client = Client('testclient'); final client = Client('testclient');
final database = await getDatabase(client); final database = await getDatabase(client);
// store a simple update // store a simple update
var update = EventUpdate( await database.storeEventUpdate(
type: EventUpdateType.timeline, room.id,
roomID: room.id, MatrixEvent.fromJson(
content: { {
'type': 'm.room.message', 'type': 'm.room.message',
'origin_server_ts': 100, 'origin_server_ts': 100,
'content': <String, dynamic>{'blah': 'blubb'}, 'content': <String, dynamic>{'blah': 'blubb'},
'event_id': '\$event-1', 'event_id': '\$event-1',
'sender': '@blah:blubb', 'sender': '@blah:blubb',
}, },
),
EventUpdateType.timeline,
client,
); );
await database.storeEventUpdate(update, client);
var event = await database.getEventById('\$event-1', room); var event = await database.getEventById('\$event-1', room);
expect(event?.eventId, '\$event-1'); expect(event?.eventId, '\$event-1');
// insert a transaction id // insert a transaction id
update = EventUpdate( await database.storeEventUpdate(
type: EventUpdateType.timeline, room.id,
roomID: room.id, Event.fromJson(
content: { {
'type': 'm.room.message', 'type': 'm.room.message',
'origin_server_ts': 100, 'origin_server_ts': 100,
'content': <String, dynamic>{'blah': 'blubb'}, 'content': <String, dynamic>{'blah': 'blubb'},
'event_id': 'transaction-1', 'event_id': 'transaction-1',
'sender': '@blah:blubb', 'sender': '@blah:blubb',
'status': EventStatus.sending.intValue, 'status': EventStatus.sending.intValue,
}, },
room,
),
EventUpdateType.timeline,
client,
); );
await database.storeEventUpdate(update, client);
event = await database.getEventById('transaction-1', room); event = await database.getEventById('transaction-1', room);
expect(event?.eventId, 'transaction-1'); expect(event?.eventId, 'transaction-1');
update = EventUpdate(
type: EventUpdateType.timeline, await database.storeEventUpdate(
roomID: room.id, room.id,
content: { Event.fromJson(
'type': 'm.room.message', {
'origin_server_ts': 100, 'type': 'm.room.message',
'content': <String, dynamic>{'blah': 'blubb'}, 'origin_server_ts': 100,
'event_id': '\$event-2', 'content': <String, dynamic>{'blah': 'blubb'},
'sender': '@blah:blubb', 'event_id': '\$event-2',
'unsigned': <String, dynamic>{ 'sender': '@blah:blubb',
'transaction_id': 'transaction-1', 'unsigned': <String, dynamic>{
'transaction_id': 'transaction-1',
},
'status': EventStatus.sent.intValue,
}, },
'status': EventStatus.sent.intValue, room,
}, ),
EventUpdateType.timeline,
client,
); );
await database.storeEventUpdate(update, client);
event = await database.getEventById('transaction-1', room); event = await database.getEventById('transaction-1', room);
expect(event, null); expect(event, null);
event = await database.getEventById('\$event-2', room); event = await database.getEventById('\$event-2', room);
// insert a transaction id if the event id for it already exists // insert a transaction id if the event id for it already exists
update = EventUpdate( await database.storeEventUpdate(
type: EventUpdateType.timeline, room.id,
roomID: room.id, Event.fromJson(
content: { {
'type': 'm.room.message', 'type': 'm.room.message',
'origin_server_ts': 100, 'origin_server_ts': 100,
'content': {'blah': 'blubb'}, 'content': {'blah': 'blubb'},
'event_id': '\$event-3', 'event_id': '\$event-3',
'sender': '@blah:blubb', 'sender': '@blah:blubb',
'status': EventStatus.sending.intValue, 'status': EventStatus.sending.intValue,
}, },
room,
),
EventUpdateType.timeline,
client,
); );
await database.storeEventUpdate(update, client);
event = await database.getEventById('\$event-3', room); event = await database.getEventById('\$event-3', room);
expect(event?.eventId, '\$event-3'); expect(event?.eventId, '\$event-3');
update = EventUpdate(
type: EventUpdateType.timeline, await database.storeEventUpdate(
roomID: room.id, room.id,
content: { Event.fromJson(
'type': 'm.room.message', {
'origin_server_ts': 100, 'type': 'm.room.message',
'content': {'blah': 'blubb'}, 'origin_server_ts': 100,
'event_id': '\$event-3', 'content': {'blah': 'blubb'},
'sender': '@blah:blubb', 'event_id': '\$event-3',
'status': EventStatus.sent.intValue, 'sender': '@blah:blubb',
'unsigned': <String, dynamic>{ 'status': EventStatus.sent.intValue,
'transaction_id': 'transaction-2', 'unsigned': <String, dynamic>{
'transaction_id': 'transaction-2',
},
}, },
}, room,
),
EventUpdateType.timeline,
client,
); );
await database.storeEventUpdate(update, client);
event = await database.getEventById('\$event-3', room); event = await database.getEventById('\$event-3', room);
expect(event?.eventId, '\$event-3'); expect(event?.eventId, '\$event-3');
expect(event?.status, EventStatus.sent); expect(event?.status, EventStatus.sent);
@ -136,37 +152,44 @@ void main() {
expect(event, null); expect(event, null);
// insert transaction id and not update status // insert transaction id and not update status
update = EventUpdate( await database.storeEventUpdate(
type: EventUpdateType.timeline, room.id,
roomID: room.id, Event.fromJson(
content: { {
'type': 'm.room.message', 'type': 'm.room.message',
'origin_server_ts': 100, 'origin_server_ts': 100,
'content': {'blah': 'blubb'}, 'content': {'blah': 'blubb'},
'event_id': '\$event-4', 'event_id': '\$event-4',
'sender': '@blah:blubb', 'sender': '@blah:blubb',
'status': EventStatus.synced.intValue, 'status': EventStatus.synced.intValue,
}, },
room,
),
EventUpdateType.timeline,
client,
); );
await database.storeEventUpdate(update, client);
event = await database.getEventById('\$event-4', room); event = await database.getEventById('\$event-4', room);
expect(event?.eventId, '\$event-4'); expect(event?.eventId, '\$event-4');
update = EventUpdate(
type: EventUpdateType.timeline, await database.storeEventUpdate(
roomID: room.id, room.id,
content: { Event.fromJson(
'type': 'm.room.message', {
'origin_server_ts': 100, 'type': 'm.room.message',
'content': {'blah': 'blubb'}, 'origin_server_ts': 100,
'event_id': '\$event-4', 'content': {'blah': 'blubb'},
'sender': '@blah:blubb', 'event_id': '\$event-4',
'status': EventStatus.sent.intValue, 'sender': '@blah:blubb',
'unsigned': <String, dynamic>{ 'status': EventStatus.sent.intValue,
'transaction_id': 'transaction-3', 'unsigned': <String, dynamic>{
'transaction_id': 'transaction-3',
},
}, },
}, room,
),
EventUpdateType.timeline,
client,
); );
await database.storeEventUpdate(update, client);
event = await database.getEventById('\$event-4', room); event = await database.getEventById('\$event-4', room);
expect(event?.eventId, '\$event-4'); expect(event?.eventId, '\$event-4');
expect(event?.status, EventStatus.synced); expect(event?.status, EventStatus.synced);

View File

@ -142,11 +142,9 @@ void main() {
); // expect no new events to have been added ); // expect no new events to have been added
final eventId = '1844295642248BcDkn:example.org'; final eventId = '1844295642248BcDkn:example.org';
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'test'}, 'content': {'msgtype': 'm.text', 'body': 'test'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -155,6 +153,7 @@ void main() {
'unsigned': {'transaction_id': '1234'}, 'unsigned': {'transaction_id': '1234'},
'origin_server_ts': DateTime.now().millisecondsSinceEpoch, 'origin_server_ts': DateTime.now().millisecondsSinceEpoch,
}, },
room,
), ),
); // just assume that it was on the server for this call but not for the following. ); // just assume that it was on the server for this call but not for the following.
@ -208,11 +207,9 @@ void main() {
expect(eventId.startsWith('\$event'), true); expect(eventId.startsWith('\$event'), true);
expect(timeline.events[0].status, EventStatus.sent); expect(timeline.events[0].status, EventStatus.sent);
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'test'}, 'content': {'msgtype': 'm.text', 'body': 'test'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -221,6 +218,7 @@ void main() {
'unsigned': {'transaction_id': '1234'}, 'unsigned': {'transaction_id': '1234'},
'origin_server_ts': DateTime.now().millisecondsSinceEpoch, 'origin_server_ts': DateTime.now().millisecondsSinceEpoch,
}, },
room,
), ),
); );
@ -238,11 +236,9 @@ void main() {
await timeline.requestFuture(); await timeline.requestFuture();
await waitForCount(6); await waitForCount(6);
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -250,6 +246,7 @@ void main() {
'event_id': 'abc', 'event_id': 'abc',
'origin_server_ts': testTimeStamp, 'origin_server_ts': testTimeStamp,
}, },
room,
), ),
); );
@ -296,11 +293,9 @@ void main() {
await timeline.requestFuture(); await timeline.requestFuture();
await timeline.requestFuture(); await timeline.requestFuture();
// send a failed message // send a failed message
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -308,6 +303,7 @@ void main() {
'event_id': 'abc', 'event_id': 'abc',
'origin_server_ts': testTimeStamp, 'origin_server_ts': testTimeStamp,
}, },
room,
), ),
); );
await waitForCount(7); await waitForCount(7);
@ -327,11 +323,9 @@ void main() {
test('getEventById', () async { test('getEventById', () async {
await timeline.requestFuture(); await timeline.requestFuture();
await timeline.requestFuture(); await timeline.requestFuture();
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -339,6 +333,7 @@ void main() {
'event_id': 'abc', 'event_id': 'abc',
'origin_server_ts': testTimeStamp, 'origin_server_ts': testTimeStamp,
}, },
room,
), ),
); );
await waitForCount(7); await waitForCount(7);
@ -360,11 +355,9 @@ void main() {
timeline.events.clear(); timeline.events.clear();
await timeline.requestFuture(); await timeline.requestFuture();
await timeline.requestFuture(); await timeline.requestFuture();
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -373,6 +366,7 @@ void main() {
'origin_server_ts': testTimeStamp, 'origin_server_ts': testTimeStamp,
'unsigned': {'transaction_id': 'newresend'}, 'unsigned': {'transaction_id': 'newresend'},
}, },
room,
), ),
); );
await waitForCount(7); await waitForCount(7);
@ -438,11 +432,9 @@ void main() {
timeline.events.clear(); timeline.events.clear();
await timeline.requestFuture(); await timeline.requestFuture();
await timeline.requestFuture(); await timeline.requestFuture();
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -450,13 +442,12 @@ void main() {
'event_id': 'abc', 'event_id': 'abc',
'origin_server_ts': testTimeStamp, 'origin_server_ts': testTimeStamp,
}, },
room,
), ),
); );
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -464,6 +455,7 @@ void main() {
'event_id': 'def', 'event_id': 'def',
'origin_server_ts': testTimeStamp + 5, 'origin_server_ts': testTimeStamp + 5,
}, },
room,
), ),
); );
await waitForCount(8); await waitForCount(8);
@ -475,11 +467,9 @@ void main() {
timeline.events.clear(); timeline.events.clear();
await timeline.requestFuture(); await timeline.requestFuture();
await timeline.requestFuture(); await timeline.requestFuture();
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -487,16 +477,15 @@ void main() {
'event_id': 'will-fail', 'event_id': 'will-fail',
'origin_server_ts': DateTime.now().millisecondsSinceEpoch, 'origin_server_ts': DateTime.now().millisecondsSinceEpoch,
}, },
room,
), ),
); );
await waitForCount(7); await waitForCount(7);
expect(timeline.events[0].status, EventStatus.sending); expect(timeline.events[0].status, EventStatus.sending);
expect(timeline.events.length, 4); expect(timeline.events.length, 4);
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -504,6 +493,7 @@ void main() {
'event_id': 'will-fail', 'event_id': 'will-fail',
'origin_server_ts': testTimeStamp, 'origin_server_ts': testTimeStamp,
}, },
room,
), ),
); );
await waitForCount(8); await waitForCount(8);
@ -513,11 +503,9 @@ void main() {
test('setReadMarker', () async { test('setReadMarker', () async {
await timeline.requestFuture(); await timeline.requestFuture();
await timeline.requestFuture(); await timeline.requestFuture();
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -525,6 +513,7 @@ void main() {
'event_id': 'will-work', 'event_id': 'will-work',
'origin_server_ts': DateTime.now().millisecondsSinceEpoch, 'origin_server_ts': DateTime.now().millisecondsSinceEpoch,
}, },
room,
), ),
); );
await waitForCount(7); await waitForCount(7);
@ -539,11 +528,9 @@ void main() {
await timeline.requestFuture(); await timeline.requestFuture();
await timeline.requestFuture(); await timeline.requestFuture();
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -551,16 +538,15 @@ void main() {
'event_id': 'transaction', 'event_id': 'transaction',
'origin_server_ts': DateTime.now().millisecondsSinceEpoch, 'origin_server_ts': DateTime.now().millisecondsSinceEpoch,
}, },
room,
), ),
); );
await waitForCount(7); await waitForCount(7);
expect(timeline.events[0].status, EventStatus.sending); expect(timeline.events[0].status, EventStatus.sending);
expect(timeline.events.length, 4); expect(timeline.events.length, 4);
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -569,16 +555,15 @@ void main() {
'origin_server_ts': testTimeStamp, 'origin_server_ts': testTimeStamp,
'unsigned': {'transaction_id': 'transaction'}, 'unsigned': {'transaction_id': 'transaction'},
}, },
room,
), ),
); );
await waitForCount(8); await waitForCount(8);
expect(timeline.events[0].status, EventStatus.sent); expect(timeline.events[0].status, EventStatus.sent);
expect(timeline.events.length, 4); expect(timeline.events.length, 4);
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -587,6 +572,7 @@ void main() {
'origin_server_ts': testTimeStamp, 'origin_server_ts': testTimeStamp,
'unsigned': {'transaction_id': 'transaction'}, 'unsigned': {'transaction_id': 'transaction'},
}, },
room,
), ),
); );
await waitForCount(9); await waitForCount(9);
@ -599,11 +585,9 @@ void main() {
await timeline.requestFuture(); await timeline.requestFuture();
await timeline.requestFuture(); await timeline.requestFuture();
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -614,16 +598,15 @@ void main() {
'transaction_id': 'transaction', 'transaction_id': 'transaction',
}, },
}, },
room,
), ),
); );
await waitForCount(7); await waitForCount(7);
expect(timeline.events[0].status, EventStatus.sending); expect(timeline.events[0].status, EventStatus.sending);
expect(timeline.events.length, 4); expect(timeline.events.length, 4);
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -634,16 +617,15 @@ void main() {
messageSendingStatusKey: EventStatus.synced.intValue, messageSendingStatusKey: EventStatus.synced.intValue,
}, },
}, },
room,
), ),
); );
await waitForCount(8); await waitForCount(8);
expect(timeline.events[0].status, EventStatus.synced); expect(timeline.events[0].status, EventStatus.synced);
expect(timeline.events.length, 4); expect(timeline.events.length, 4);
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -654,6 +636,7 @@ void main() {
messageSendingStatusKey: EventStatus.sent.intValue, messageSendingStatusKey: EventStatus.sent.intValue,
}, },
}, },
room,
), ),
); );
await waitForCount(9); await waitForCount(9);
@ -665,11 +648,9 @@ void main() {
await timeline.requestFuture(); await timeline.requestFuture();
await timeline.requestFuture(); await timeline.requestFuture();
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -677,16 +658,15 @@ void main() {
'event_id': 'transaction', 'event_id': 'transaction',
'origin_server_ts': DateTime.now().millisecondsSinceEpoch, 'origin_server_ts': DateTime.now().millisecondsSinceEpoch,
}, },
room,
), ),
); );
await waitForCount(7); await waitForCount(7);
expect(timeline.events[0].status, EventStatus.sending); expect(timeline.events[0].status, EventStatus.sending);
expect(timeline.events.length, 4); expect(timeline.events.length, 4);
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -694,16 +674,15 @@ void main() {
'origin_server_ts': testTimeStamp, 'origin_server_ts': testTimeStamp,
'unsigned': {'transaction_id': 'transaction'}, 'unsigned': {'transaction_id': 'transaction'},
}, },
room,
), ),
); );
await waitForCount(8); await waitForCount(8);
expect(timeline.events[0].status, EventStatus.error); expect(timeline.events[0].status, EventStatus.error);
expect(timeline.events.length, 4); expect(timeline.events.length, 4);
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -712,6 +691,7 @@ void main() {
'origin_server_ts': testTimeStamp, 'origin_server_ts': testTimeStamp,
'unsigned': {'transaction_id': 'transaction'}, 'unsigned': {'transaction_id': 'transaction'},
}, },
room,
), ),
); );
await waitForCount(9); await waitForCount(9);
@ -723,11 +703,9 @@ void main() {
await timeline.requestFuture(); await timeline.requestFuture();
await timeline.requestFuture(); await timeline.requestFuture();
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -735,16 +713,15 @@ void main() {
'event_id': 'transaction', 'event_id': 'transaction',
'origin_server_ts': DateTime.now().millisecondsSinceEpoch, 'origin_server_ts': DateTime.now().millisecondsSinceEpoch,
}, },
room,
), ),
); );
await waitForCount(7); await waitForCount(7);
expect(timeline.events[0].status, EventStatus.sending); expect(timeline.events[0].status, EventStatus.sending);
expect(timeline.events.length, 4); expect(timeline.events.length, 4);
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -753,16 +730,15 @@ void main() {
'origin_server_ts': testTimeStamp, 'origin_server_ts': testTimeStamp,
'unsigned': {'transaction_id': 'transaction'}, 'unsigned': {'transaction_id': 'transaction'},
}, },
room,
), ),
); );
await waitForCount(8); await waitForCount(8);
expect(timeline.events[0].status, EventStatus.synced); expect(timeline.events[0].status, EventStatus.synced);
expect(timeline.events.length, 4); expect(timeline.events.length, 4);
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -770,6 +746,7 @@ void main() {
'origin_server_ts': testTimeStamp, 'origin_server_ts': testTimeStamp,
'unsigned': {'transaction_id': 'transaction'}, 'unsigned': {'transaction_id': 'transaction'},
}, },
room,
), ),
); );
await waitForCount(9); await waitForCount(9);

View File

@ -115,11 +115,9 @@ void main() {
); );
test('Create', () async { test('Create', () async {
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -127,13 +125,12 @@ void main() {
'event_id': '2', 'event_id': '2',
'origin_server_ts': testTimeStamp - 1000, 'origin_server_ts': testTimeStamp - 1000,
}, },
room,
), ),
); );
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -141,10 +138,12 @@ void main() {
'event_id': '\$1', 'event_id': '\$1',
'origin_server_ts': testTimeStamp, 'origin_server_ts': testTimeStamp,
}, },
room,
), ),
); );
expect(timeline.sub != null, true); expect(timeline.timelineSub != null, true);
expect(timeline.historySub != null, true);
await waitForCount(2); await waitForCount(2);
@ -202,11 +201,9 @@ void main() {
expect(timeline.events[0].receipts.length, 1); 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( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.redaction', 'type': 'm.room.redaction',
'content': {'reason': 'spamming'}, 'content': {'reason': 'spamming'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -214,6 +211,7 @@ void main() {
'event_id': '3', 'event_id': '3',
'origin_server_ts': testTimeStamp + 1000, 'origin_server_ts': testTimeStamp + 1000,
}, },
room,
), ),
); );
@ -269,7 +267,8 @@ void main() {
), ),
); );
expect(timeline.sub != null, true); expect(timeline.timelineSub != null, true);
expect(timeline.historySub != null, true);
await waitForCount(3); await waitForCount(3);
@ -584,7 +583,8 @@ void main() {
), ),
); );
expect(timeline.sub != null, true); expect(timeline.timelineSub != null, true);
expect(timeline.historySub != null, true);
await waitForCount(1); await waitForCount(1);
@ -604,11 +604,9 @@ void main() {
expect(eventId.startsWith('\$event'), true); expect(eventId.startsWith('\$event'), true);
expect(timeline.events[0].status, EventStatus.sent); expect(timeline.events[0].status, EventStatus.sent);
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'test'}, 'content': {'msgtype': 'm.text', 'body': 'test'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -617,6 +615,7 @@ void main() {
'unsigned': {'transaction_id': '1234'}, 'unsigned': {'transaction_id': '1234'},
'origin_server_ts': DateTime.now().millisecondsSinceEpoch, 'origin_server_ts': DateTime.now().millisecondsSinceEpoch,
}, },
room,
), ),
); );
@ -629,11 +628,9 @@ void main() {
}); });
test('Send message with error', () async { test('Send message with error', () async {
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': { 'content': {
'msgtype': 'm.text', 'msgtype': 'm.text',
@ -644,6 +641,7 @@ void main() {
'event_id': 'abc', 'event_id': 'abc',
'origin_server_ts': testTimeStamp, 'origin_server_ts': testTimeStamp,
}, },
room,
), ),
); );
await waitForCount(1); await waitForCount(1);
@ -668,11 +666,9 @@ void main() {
test('Remove message', () async { test('Remove message', () async {
// send a failed message // send a failed message
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -680,6 +676,7 @@ void main() {
'event_id': 'abc', 'event_id': 'abc',
'origin_server_ts': testTimeStamp, 'origin_server_ts': testTimeStamp,
}, },
room,
), ),
); );
await waitForCount(1); await waitForCount(1);
@ -695,11 +692,9 @@ void main() {
}); });
test('getEventById', () async { test('getEventById', () async {
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -707,6 +702,7 @@ void main() {
'event_id': 'abc', 'event_id': 'abc',
'origin_server_ts': testTimeStamp, 'origin_server_ts': testTimeStamp,
}, },
room,
), ),
); );
await waitForCount(1); await waitForCount(1);
@ -726,11 +722,9 @@ void main() {
test('Resend message', () async { test('Resend message', () async {
timeline.events.clear(); timeline.events.clear();
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -739,6 +733,7 @@ void main() {
'origin_server_ts': testTimeStamp, 'origin_server_ts': testTimeStamp,
'unsigned': {'transaction_id': 'newresend'}, 'unsigned': {'transaction_id': 'newresend'},
}, },
room,
), ),
); );
await waitForCount(1); await waitForCount(1);
@ -799,11 +794,9 @@ void main() {
test('sort errors on top', () async { test('sort errors on top', () async {
timeline.events.clear(); timeline.events.clear();
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -811,13 +804,12 @@ void main() {
'event_id': 'abc', 'event_id': 'abc',
'origin_server_ts': testTimeStamp, 'origin_server_ts': testTimeStamp,
}, },
room,
), ),
); );
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -825,6 +817,7 @@ void main() {
'event_id': 'def', 'event_id': 'def',
'origin_server_ts': testTimeStamp + 5, 'origin_server_ts': testTimeStamp + 5,
}, },
room,
), ),
); );
await Future.delayed(Duration(milliseconds: 50)); await Future.delayed(Duration(milliseconds: 50));
@ -834,11 +827,9 @@ void main() {
test('sending event to failed update', () async { test('sending event to failed update', () async {
timeline.events.clear(); timeline.events.clear();
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -846,16 +837,15 @@ void main() {
'event_id': 'will-fail', 'event_id': 'will-fail',
'origin_server_ts': DateTime.now().millisecondsSinceEpoch, 'origin_server_ts': DateTime.now().millisecondsSinceEpoch,
}, },
room,
), ),
); );
await Future.delayed(Duration(milliseconds: 50)); await Future.delayed(Duration(milliseconds: 50));
expect(timeline.events[0].status, EventStatus.sending); expect(timeline.events[0].status, EventStatus.sending);
expect(timeline.events.length, 1); expect(timeline.events.length, 1);
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -863,6 +853,7 @@ void main() {
'event_id': 'will-fail', 'event_id': 'will-fail',
'origin_server_ts': testTimeStamp, 'origin_server_ts': testTimeStamp,
}, },
room,
), ),
); );
await Future.delayed(Duration(milliseconds: 50)); await Future.delayed(Duration(milliseconds: 50));
@ -870,11 +861,9 @@ void main() {
expect(timeline.events.length, 1); expect(timeline.events.length, 1);
}); });
test('setReadMarker', () async { test('setReadMarker', () async {
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -882,6 +871,7 @@ void main() {
'event_id': 'will-work', 'event_id': 'will-work',
'origin_server_ts': DateTime.now().millisecondsSinceEpoch, 'origin_server_ts': DateTime.now().millisecondsSinceEpoch,
}, },
room,
), ),
); );
await Future.delayed(Duration(milliseconds: 50)); await Future.delayed(Duration(milliseconds: 50));
@ -892,11 +882,9 @@ void main() {
test('sending an event and the http request finishes first, 0 -> 1 -> 2', test('sending an event and the http request finishes first, 0 -> 1 -> 2',
() async { () async {
timeline.events.clear(); timeline.events.clear();
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -904,16 +892,15 @@ void main() {
'event_id': 'transaction', 'event_id': 'transaction',
'origin_server_ts': DateTime.now().millisecondsSinceEpoch, 'origin_server_ts': DateTime.now().millisecondsSinceEpoch,
}, },
room,
), ),
); );
await Future.delayed(Duration(milliseconds: 50)); await Future.delayed(Duration(milliseconds: 50));
expect(timeline.events[0].status, EventStatus.sending); expect(timeline.events[0].status, EventStatus.sending);
expect(timeline.events.length, 1); expect(timeline.events.length, 1);
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -922,16 +909,15 @@ void main() {
'origin_server_ts': testTimeStamp, 'origin_server_ts': testTimeStamp,
'unsigned': {'transaction_id': 'transaction'}, 'unsigned': {'transaction_id': 'transaction'},
}, },
room,
), ),
); );
await Future.delayed(Duration(milliseconds: 50)); await Future.delayed(Duration(milliseconds: 50));
expect(timeline.events[0].status, EventStatus.sent); expect(timeline.events[0].status, EventStatus.sent);
expect(timeline.events.length, 1); expect(timeline.events.length, 1);
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -940,6 +926,7 @@ void main() {
'origin_server_ts': testTimeStamp, 'origin_server_ts': testTimeStamp,
'unsigned': {'transaction_id': 'transaction'}, 'unsigned': {'transaction_id': 'transaction'},
}, },
room,
), ),
); );
await Future.delayed(Duration(milliseconds: 50)); await Future.delayed(Duration(milliseconds: 50));
@ -949,11 +936,9 @@ void main() {
test('sending an event where the sync reply arrives first, 0 -> 2 -> 1', test('sending an event where the sync reply arrives first, 0 -> 2 -> 1',
() async { () async {
timeline.events.clear(); timeline.events.clear();
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -964,16 +949,15 @@ void main() {
'transaction_id': 'transaction', 'transaction_id': 'transaction',
}, },
}, },
room,
), ),
); );
await Future.delayed(Duration(milliseconds: 50)); await Future.delayed(Duration(milliseconds: 50));
expect(timeline.events[0].status, EventStatus.sending); expect(timeline.events[0].status, EventStatus.sending);
expect(timeline.events.length, 1); expect(timeline.events.length, 1);
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -984,16 +968,15 @@ void main() {
messageSendingStatusKey: EventStatus.synced.intValue, messageSendingStatusKey: EventStatus.synced.intValue,
}, },
}, },
room,
), ),
); );
await Future.delayed(Duration(milliseconds: 50)); await Future.delayed(Duration(milliseconds: 50));
expect(timeline.events[0].status, EventStatus.synced); expect(timeline.events[0].status, EventStatus.synced);
expect(timeline.events.length, 1); expect(timeline.events.length, 1);
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -1004,6 +987,7 @@ void main() {
messageSendingStatusKey: EventStatus.sent.intValue, messageSendingStatusKey: EventStatus.sent.intValue,
}, },
}, },
room,
), ),
); );
await Future.delayed(Duration(milliseconds: 50)); await Future.delayed(Duration(milliseconds: 50));
@ -1012,11 +996,9 @@ void main() {
}); });
test('sending an event 0 -> -1 -> 2', () async { test('sending an event 0 -> -1 -> 2', () async {
timeline.events.clear(); timeline.events.clear();
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -1024,16 +1006,15 @@ void main() {
'event_id': 'transaction', 'event_id': 'transaction',
'origin_server_ts': DateTime.now().millisecondsSinceEpoch, 'origin_server_ts': DateTime.now().millisecondsSinceEpoch,
}, },
room,
), ),
); );
await Future.delayed(Duration(milliseconds: 50)); await Future.delayed(Duration(milliseconds: 50));
expect(timeline.events[0].status, EventStatus.sending); expect(timeline.events[0].status, EventStatus.sending);
expect(timeline.events.length, 1); expect(timeline.events.length, 1);
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -1041,16 +1022,15 @@ void main() {
'origin_server_ts': testTimeStamp, 'origin_server_ts': testTimeStamp,
'unsigned': {'transaction_id': 'transaction'}, 'unsigned': {'transaction_id': 'transaction'},
}, },
room,
), ),
); );
await Future.delayed(Duration(milliseconds: 50)); await Future.delayed(Duration(milliseconds: 50));
expect(timeline.events[0].status, EventStatus.error); expect(timeline.events[0].status, EventStatus.error);
expect(timeline.events.length, 1); expect(timeline.events.length, 1);
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -1059,6 +1039,7 @@ void main() {
'origin_server_ts': testTimeStamp, 'origin_server_ts': testTimeStamp,
'unsigned': {'transaction_id': 'transaction'}, 'unsigned': {'transaction_id': 'transaction'},
}, },
room,
), ),
); );
await Future.delayed(Duration(milliseconds: 50)); await Future.delayed(Duration(milliseconds: 50));
@ -1067,11 +1048,9 @@ void main() {
}); });
test('sending an event 0 -> 2 -> -1', () async { test('sending an event 0 -> 2 -> -1', () async {
timeline.events.clear(); timeline.events.clear();
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -1079,16 +1058,15 @@ void main() {
'event_id': 'transaction', 'event_id': 'transaction',
'origin_server_ts': DateTime.now().millisecondsSinceEpoch, 'origin_server_ts': DateTime.now().millisecondsSinceEpoch,
}, },
room,
), ),
); );
await Future.delayed(Duration(milliseconds: 50)); await Future.delayed(Duration(milliseconds: 50));
expect(timeline.events[0].status, EventStatus.sending); expect(timeline.events[0].status, EventStatus.sending);
expect(timeline.events.length, 1); expect(timeline.events.length, 1);
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -1097,16 +1075,15 @@ void main() {
'origin_server_ts': testTimeStamp, 'origin_server_ts': testTimeStamp,
'unsigned': {'transaction_id': 'transaction'}, 'unsigned': {'transaction_id': 'transaction'},
}, },
room,
), ),
); );
await Future.delayed(Duration(milliseconds: 50)); await Future.delayed(Duration(milliseconds: 50));
expect(timeline.events[0].status, EventStatus.synced); expect(timeline.events[0].status, EventStatus.synced);
expect(timeline.events.length, 1); expect(timeline.events.length, 1);
client.onEvent.add( client.onTimelineEvent.add(
EventUpdate( Event.fromJson(
type: EventUpdateType.timeline, {
roomID: roomID,
content: {
'type': 'm.room.message', 'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'}, 'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com', 'sender': '@alice:example.com',
@ -1114,6 +1091,7 @@ void main() {
'origin_server_ts': testTimeStamp, 'origin_server_ts': testTimeStamp,
'unsigned': {'transaction_id': 'transaction'}, 'unsigned': {'transaction_id': 'transaction'},
}, },
room,
), ),
); );
await Future.delayed(Duration(milliseconds: 50)); await Future.delayed(Duration(milliseconds: 50));