From 763995b9ce89e85dc9d55d589b226fcc305ccf65 Mon Sep 17 00:00:00 2001 From: Chris Bobbe Date: Wed, 15 Nov 2023 14:53:10 -0500 Subject: [PATCH] unreads: Add handleAllMessagesReadSuccess method, to be used soon --- lib/model/unreads.dart | 36 +++++++++++++++++++++++++++++++++++- test/model/unreads_test.dart | 14 ++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/lib/model/unreads.dart b/lib/model/unreads.dart index d8485c3e0b..db0db493c1 100644 --- a/lib/model/unreads.dart +++ b/lib/model/unreads.dart @@ -127,7 +127,7 @@ class Unreads extends ChangeNotifier { /// Whether the model is missing data on old unread messages. /// /// Initialized to the value of [UnreadMessagesSnapshot.oldUnreadsMissing]. - /// Is set to false when the user clears out all unreads at once. + /// Is set to false when the user clears out all unreads. bool oldUnreadsMissing; final int selfUserId; @@ -390,6 +390,40 @@ class Unreads extends ChangeNotifier { notifyListeners(); } + /// To be called on success of a mark-all-as-read task in the modern protocol. + /// + /// When the user successfully marks all messages as read, + /// there can't possibly be ancient unreads we don't know about. + /// So this updates [oldUnreadsMissing] to false and calls [notifyListeners]. + /// + /// When we use POST /messages/flags/narrow (FL 155+) for mark-all-as-read, + /// we don't expect to get a mark-as-read event with `all: true`, + /// even on completion of the last batch of unreads. + /// If we did get an event with `all: true` (as we do in the legacy mark-all- + /// as-read protocol), this would be handled naturally, in + /// [handleUpdateMessageFlagsEvent]. + /// + /// Discussion: + /// + // TODO(server-6) Delete mentions of legacy protocol. + void handleAllMessagesReadSuccess() { + oldUnreadsMissing = false; + + // Best not to actually clear any unreads out of the model. + // That'll be handled naturally when the event comes in, with a list of which + // messages were marked as read. When a mark-all-as-read task is complete, + // I don't think the server will always have zero unreads in its state. + // For example, I assume a new unread message could arrive while the work is + // in progress, and not get caught and marked as read. We should faithfully + // match that state. (This point seems especially relevant when the + // mark-as-read work is done in batches.) + // + // Even considering races like that, it does seem basically impossible for + // `oldUnreadsMissing: false` to be the wrong state at this point. + + notifyListeners(); + } + // TODO use efficient lookups bool _slowIsPresentInStreams(int messageId) { return streams.values.any( diff --git a/test/model/unreads_test.dart b/test/model/unreads_test.dart index 2725af0649..7307ca0851 100644 --- a/test/model/unreads_test.dart +++ b/test/model/unreads_test.dart @@ -985,4 +985,18 @@ void main() { }); }); }); + + group('handleAllMessagesReadSuccess', () { + prepare(); + fillWithMessages([]); + + // We didn't fill the model with 50k unreads, so this is questionably + // realistic… but the 50k cap isn't actually API-guaranteed, and this is + // plausibly realistic for a hypothetical server that decides based on + // message age rather than the 50k cap. + model.oldUnreadsMissing = true; + model.handleAllMessagesReadSuccess(); + checkNotifiedOnce(); + check(model).oldUnreadsMissing.isFalse(); + }); }