Skip to content

Commit b270ba6

Browse files
committed
api: Add markAllAsRead, markStreamAsRead, and markTopicAsRead routes
1 parent 2aab833 commit b270ba6

File tree

2 files changed

+132
-0
lines changed

2 files changed

+132
-0
lines changed

lib/api/route/messages.dart

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,3 +375,63 @@ class UpdateMessageFlagsForNarrowResult {
375375

376376
Map<String, dynamic> toJson() => _$UpdateMessageFlagsForNarrowResultToJson(this);
377377
}
378+
379+
/// https://zulip.com/api/mark-all-as-read
380+
///
381+
/// This binding is deprecated, in FL 155+ use
382+
/// [updateMessageFlagsForNarrow] instead.
383+
// TODO(server-6): Remove as deprecated by updateMessageFlagsForNarrow
384+
//
385+
// For FL < 153 this call was atomic on the server and would
386+
// not mark any messages as read if it timed out.
387+
// From FL 153 and onward the server started processing
388+
// in batches so progress could still be made in the event
389+
// of a timeout interruption. Thus, in FL 153 this call
390+
// started returning `result: partially_completed` and
391+
// `code: REQUEST_TIMEOUT` for timeouts.
392+
//
393+
// In FL 211 the `partially_completed` variant of
394+
// `result` was removed, the string `code` field also
395+
// removed, and a boolean `complete` field introduced.
396+
//
397+
// For full support of this endpoint we would need three
398+
// variants of the return structure based on feature
399+
// level (`{}`, `{code: string}`, and `{complete: bool}`)
400+
// as well as handling of `partially_completed` variant
401+
// of `result` in `lib/api/core.dart`. For simplicity we
402+
// ignore these return values.
403+
//
404+
// We don't use this method for FL 155+ (it is replaced
405+
// by `updateMessageFlagsForNarrow`) so there are only
406+
// two versions (FL 153 and FL 154) affected.
407+
Future<void> markAllAsRead(ApiConnection connection) {
408+
return connection.post('markAllAsRead', (_) {}, 'mark_all_as_read', {});
409+
}
410+
411+
/// https://zulip.com/api/mark-stream-as-read
412+
///
413+
/// This binding is deprecated, in FL 155+ use
414+
/// updateMessageFlagsForNarrow instead.
415+
// TODO(server-6): Remove as deprecated by updateMessageFlagsForNarrow
416+
Future<void> markStreamAsRead(ApiConnection connection, {
417+
required int streamId,
418+
}) {
419+
return connection.post('markStreamAsRead', (_) {}, 'mark_stream_as_read', {
420+
'stream_id': streamId,
421+
});
422+
}
423+
424+
/// https://zulip.com/api/mark-topic-as-read
425+
///
426+
/// This binding is deprecated, in FL 155+ use
427+
/// updateMessageFlagsForNarrow instead.
428+
// TODO(server-6): Remove as deprecated by updateMessageFlagsForNarrow
429+
Future<void> markTopicAsRead(ApiConnection connection, {
430+
required int streamId,
431+
required String topicName,
432+
}) {
433+
return connection.post('markTopicAsRead', (_) {}, 'mark_topic_as_read', {
434+
'stream_id': streamId,
435+
'topic_name': RawParameter(topicName),
436+
});
437+
}

test/api/route/messages_test.dart

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,4 +571,76 @@ void main() {
571571
});
572572
});
573573
});
574+
575+
group('markAllAsRead', () {
576+
Future<void> checkMarkAllAsRead(
577+
FakeApiConnection connection, {
578+
required Map<String, String> expected,
579+
}) async {
580+
connection.prepare(json: {});
581+
await markAllAsRead(connection);
582+
check(connection.lastRequest).isNotNull().isA<http.Request>()
583+
..method.equals('POST')
584+
..url.path.equals('/api/v1/mark_all_as_read')
585+
..bodyFields.deepEquals(expected);
586+
}
587+
588+
test('smoke', () {
589+
return FakeApiConnection.with_((connection) async {
590+
await checkMarkAllAsRead(connection, expected: {});
591+
});
592+
});
593+
});
594+
595+
group('markStreamAsRead', () {
596+
Future<void> checkMarkStreamAsRead(
597+
FakeApiConnection connection, {
598+
required int streamId,
599+
required Map<String, String> expected,
600+
}) async {
601+
connection.prepare(json: {});
602+
await markStreamAsRead(connection, streamId: streamId);
603+
check(connection.lastRequest).isNotNull().isA<http.Request>()
604+
..method.equals('POST')
605+
..url.path.equals('/api/v1/mark_stream_as_read')
606+
..bodyFields.deepEquals(expected);
607+
}
608+
609+
test('smoke', () {
610+
return FakeApiConnection.with_((connection) async {
611+
await checkMarkStreamAsRead(connection,
612+
streamId: 10,
613+
expected: {'stream_id': '10'});
614+
});
615+
});
616+
});
617+
618+
group('markTopicAsRead', () {
619+
Future<void> checkMarkTopicAsRead(
620+
FakeApiConnection connection, {
621+
required int streamId,
622+
required String topicName,
623+
required Map<String, String> expected,
624+
}) async {
625+
connection.prepare(json: {});
626+
await markTopicAsRead(connection,
627+
streamId: streamId, topicName: topicName);
628+
check(connection.lastRequest).isNotNull().isA<http.Request>()
629+
..method.equals('POST')
630+
..url.path.equals('/api/v1/mark_topic_as_read')
631+
..bodyFields.deepEquals(expected);
632+
}
633+
634+
test('smoke', () {
635+
return FakeApiConnection.with_((connection) async {
636+
await checkMarkTopicAsRead(connection,
637+
streamId: 10,
638+
topicName: 'topic',
639+
expected: {
640+
'stream_id': '10',
641+
'topic_name': 'topic',
642+
});
643+
});
644+
});
645+
});
574646
}

0 commit comments

Comments
 (0)