refactor: Move setreadmarker functionality to timeline

Apps had a hard time to just set
the marker for the last event.
The lastEvent in the Room may
not be the actual last event
because we ignore several
event types there. Therefore
it makes sense to refactor
the setUnread method.
Now the timeline class has an
easy method to set the read
marker to the last synced
event, which can only be
known by the timeline if we
want to avoid another DB access.
This commit is contained in:
Krille Fear 2021-11-09 09:22:13 +01:00
parent 0e2542b172
commit e313426dd9
5 changed files with 41 additions and 15 deletions

View File

@ -506,10 +506,14 @@ class Room {
/// Returns true if this room is unread
bool get isUnread => notificationCount > 0 || markedUnread;
/// Sets an unread flag manually for this room. Similar to the setUnreadMarker
/// this changes the local account data model before syncing it to make sure
/// this works if there is no connection to the homeserver.
Future<void> setUnread(bool unread) async {
@Deprecated('Use [markUnread] instead')
Future<void> setUnread(bool unread) => markUnread(unread);
/// Sets an unread flag manually for this room. This changes the local account
/// data model before syncing it to make sure
/// this works if there is no connection to the homeserver. This does **not**
/// set a read marker!
Future<void> markUnread(bool unread) async {
final content = MarkedUnread(unread).toJson();
await _handleFakeSync(SyncUpdate(nextBatch: '')
..rooms = (RoomsUpdate()
@ -527,13 +531,6 @@ class Room {
EventType.markedUnread,
content,
);
final lastEvent = this.lastEvent;
if (!unread && lastEvent != null) {
await setReadMarker(
lastEvent.eventId,
mRead: lastEvent.eventId,
);
}
}
/// Returns true if this room has a m.favourite tag.

View File

@ -18,6 +18,8 @@
import 'dart:async';
import 'package:collection/src/iterable_extensions.dart';
import '../matrix.dart';
import 'event.dart';
import 'event_status.dart';
@ -172,6 +174,14 @@ class Timeline {
}
}
/// Set the read marker to the last synced event in this timeline.
Future<void> setReadMarker([String? eventId]) async {
eventId ??=
events.firstWhereOrNull((event) => event.status.isSynced)?.eventId;
if (eventId == null) return;
return room.setReadMarker(eventId, mRead: eventId);
}
int _findEvent({String? event_id, String? unsigned_txid}) {
// we want to find any existing event where either the passed event_id or the passed unsigned_txid
// matches either the event_id or transaction_id of the existing event.

View File

@ -1779,6 +1779,7 @@ class FakeMatrixApi extends MockClient {
'/client/r0/rooms/!localpart%3Aexample.com/receipt/m.read/%241234%3Aexample.com':
(var req) => {},
'/client/r0/rooms/!localpart%3Aexample.com/read_markers': (var req) => {},
'/client/r0/rooms/!1234%3Aexample.com/read_markers': (var req) => {},
'/client/r0/user/${Uri.encodeComponent('@othertest:fakeServer.notExisting')}/filter':
(var req) => {'filter_id': '1234'},
'/client/r0/user/${Uri.encodeComponent('@test:fakeServer.notExisting')}/filter':

View File

@ -743,15 +743,15 @@ void main() {
});
test('Test marked unread room', () async {
await room.setUnread(true);
await room.setUnread(false);
expect(room.isUnread, false);
await room.markUnread(true);
await room.markUnread(false);
expect(room.markedUnread, false);
room.roomAccountData['com.famedly.marked_unread'] =
BasicRoomEvent.fromJson({
'content': {'unread': true},
'type': 'com.famedly.marked_unread'
});
expect(room.isUnread, true);
expect(room.markedUnread, true);
});
test('joinRules', () async {

View File

@ -372,6 +372,24 @@ void main() {
expect(timeline.events[0].status, EventStatus.error);
expect(timeline.events.length, 1);
});
test('setReadMarker', () async {
client.onEvent.add(EventUpdate(
type: EventUpdateType.timeline,
roomID: roomID,
content: {
'type': 'm.room.message',
'content': {'msgtype': 'm.text', 'body': 'Testcase'},
'sender': '@alice:example.com',
'status': EventStatus.synced.intValue,
'event_id': 'will-work',
'origin_server_ts': DateTime.now().millisecondsSinceEpoch,
},
));
await Future.delayed(Duration(milliseconds: 50));
room.notificationCount = 1;
await timeline.setReadMarker();
expect(room.notificationCount, 0);
});
test('sending an event and the http request finishes first, 0 -> 1 -> 2',
() async {
timeline.events.clear();