@@ -22,97 +22,106 @@ Future<bool> markNarrowAsRead(
22
22
Narrow narrow,
23
23
bool useLegacy, // TODO(server-6)
24
24
) async {
25
- final store = PerAccountStoreWidget .of (context);
26
- final connection = store.connection;
27
- if (useLegacy) {
28
- await _legacyMarkNarrowAsRead (context, narrow);
29
- return true ;
30
- }
25
+ try {
26
+ final store = PerAccountStoreWidget .of (context);
27
+ final connection = store.connection;
28
+ if (useLegacy) {
29
+ await _legacyMarkNarrowAsRead (context, narrow);
30
+ return true ;
31
+ }
31
32
32
- // Compare web's `mark_all_as_read` in web/src/unread_ops.js
33
- // and zulip-mobile's `markAsUnreadFromMessage` in src/action-sheets/index.js .
34
- final zulipLocalizations = ZulipLocalizations .of (context);
35
- final scaffoldMessenger = ScaffoldMessenger .of (context);
36
- // Use [AnchorCode.oldest], because [AnchorCode.firstUnread]
37
- // will be the oldest non-muted unread message, which would
38
- // result in muted unreads older than the first unread not
39
- // being processed.
40
- Anchor anchor = AnchorCode .oldest;
41
- int responseCount = 0 ;
42
- int updatedCount = 0 ;
33
+ // Compare web's `mark_all_as_read` in web/src/unread_ops.js
34
+ // and zulip-mobile's `markAsUnreadFromMessage` in src/action-sheets/index.js .
35
+ final zulipLocalizations = ZulipLocalizations .of (context);
36
+ final scaffoldMessenger = ScaffoldMessenger .of (context);
37
+ // Use [AnchorCode.oldest], because [AnchorCode.firstUnread]
38
+ // will be the oldest non-muted unread message, which would
39
+ // result in muted unreads older than the first unread not
40
+ // being processed.
41
+ Anchor anchor = AnchorCode .oldest;
42
+ int responseCount = 0 ;
43
+ int updatedCount = 0 ;
43
44
44
- // Include `is:unread` in the narrow. That has a database index, so
45
- // this can be an important optimization in narrows with a lot of history.
46
- // The server applies the same optimization within the (deprecated)
47
- // specialized endpoints for marking messages as read; see
48
- // `do_mark_stream_messages_as_read` in `zulip:zerver/actions/message_flags.py`.
49
- final apiNarrow = narrow.apiEncode ()..add (ApiNarrowIsUnread ());
45
+ // Include `is:unread` in the narrow. That has a database index, so
46
+ // this can be an important optimization in narrows with a lot of history.
47
+ // The server applies the same optimization within the (deprecated)
48
+ // specialized endpoints for marking messages as read; see
49
+ // `do_mark_stream_messages_as_read` in `zulip:zerver/actions/message_flags.py`.
50
+ final apiNarrow = narrow.apiEncode ()..add (ApiNarrowIsUnread ());
50
51
51
- while (true ) {
52
- final result = await updateMessageFlagsForNarrow (connection,
53
- anchor: anchor,
54
- // [AnchorCode.oldest] is an anchor ID lower than any valid
55
- // message ID; and follow-up requests will have already
56
- // processed the anchor ID, so we just want this to be
57
- // unconditionally false.
58
- includeAnchor: false ,
59
- // There is an upper limit of 5000 messages per batch
60
- // (numBefore + numAfter <= 5000) enforced on the server.
61
- // See `update_message_flags_in_narrow` in zerver/views/message_flags.py .
62
- // zulip-mobile uses `numAfter` of 5000, but web uses 1000
63
- // for more responsive feedback. See zulip@f0d87fcf6.
64
- numBefore: 0 ,
65
- numAfter: 1000 ,
66
- narrow: apiNarrow,
67
- op: UpdateMessageFlagsOp .add,
68
- flag: MessageFlag .read);
69
- if (! context.mounted) {
70
- scaffoldMessenger.clearSnackBars ();
71
- return false ;
72
- }
73
- responseCount++ ;
74
- updatedCount += result.updatedCount;
52
+ while (true ) {
53
+ final result = await updateMessageFlagsForNarrow (connection,
54
+ anchor: anchor,
55
+ // [AnchorCode.oldest] is an anchor ID lower than any valid
56
+ // message ID; and follow-up requests will have already
57
+ // processed the anchor ID, so we just want this to be
58
+ // unconditionally false.
59
+ includeAnchor: false ,
60
+ // There is an upper limit of 5000 messages per batch
61
+ // (numBefore + numAfter <= 5000) enforced on the server.
62
+ // See `update_message_flags_in_narrow` in zerver/views/message_flags.py .
63
+ // zulip-mobile uses `numAfter` of 5000, but web uses 1000
64
+ // for more responsive feedback. See zulip@f0d87fcf6.
65
+ numBefore: 0 ,
66
+ numAfter: 1000 ,
67
+ narrow: apiNarrow,
68
+ op: UpdateMessageFlagsOp .add,
69
+ flag: MessageFlag .read);
70
+ if (! context.mounted) {
71
+ scaffoldMessenger.clearSnackBars ();
72
+ return false ;
73
+ }
74
+ responseCount++ ;
75
+ updatedCount += result.updatedCount;
75
76
76
- if (result.foundNewest) {
77
- if (responseCount > 1 ) {
78
- // We previously showed an in-progress [SnackBar], so say we're done.
79
- // There may be a backlog of [SnackBar]s accumulated in the queue
80
- // so be sure to clear them out here.
81
- scaffoldMessenger
82
- ..clearSnackBars ()
83
- ..showSnackBar (SnackBar (behavior: SnackBarBehavior .floating,
84
- content: Text (zulipLocalizations.markAsReadComplete (updatedCount))));
77
+ if (result.foundNewest) {
78
+ if (responseCount > 1 ) {
79
+ // We previously showed an in-progress [SnackBar], so say we're done.
80
+ // There may be a backlog of [SnackBar]s accumulated in the queue
81
+ // so be sure to clear them out here.
82
+ scaffoldMessenger
83
+ ..clearSnackBars ()
84
+ ..showSnackBar (SnackBar (behavior: SnackBarBehavior .floating,
85
+ content: Text (zulipLocalizations.markAsReadComplete (updatedCount))));
86
+ }
87
+ return true ;
85
88
}
86
- return true ;
87
- }
88
89
89
- if (result.lastProcessedId == null ) {
90
- // No messages were in the range of the request.
91
- // This should be impossible given that `foundNewest` was false
92
- // (and that our `numAfter` was positive.)
93
- await showErrorDialog (context: context,
94
- title: zulipLocalizations.errorMarkAsReadFailedTitle,
95
- message: zulipLocalizations.errorInvalidResponse);
96
- return false ;
97
- }
98
- anchor = NumericAnchor (result.lastProcessedId! );
90
+ if (result.lastProcessedId == null ) {
91
+ // No messages were in the range of the request.
92
+ // This should be impossible given that `foundNewest` was false
93
+ // (and that our `numAfter` was positive.)
94
+ showErrorDialog (context: context,
95
+ title: zulipLocalizations.errorMarkAsReadFailedTitle,
96
+ message: zulipLocalizations.errorInvalidResponse);
97
+ return false ;
98
+ }
99
+ anchor = NumericAnchor (result.lastProcessedId! );
99
100
100
- // The task is taking a while, so tell the user we're working on it.
101
- // No need to say how many messages, as the [MarkAsUnread] widget
102
- // should follow along.
103
- // TODO: Ideally we'd have a progress widget here that showed up based
104
- // on actual time elapsed -- so it could appear before the first
105
- // batch returns, if that takes a while -- and that then stuck
106
- // around continuously until the task ends. For now we use a
107
- // series of [SnackBar]s, which may feel a bit janky.
108
- // There is complexity in tracking the status of each [SnackBar],
109
- // due to having no way to determine which is currently active,
110
- // or if there is an active one at all. Resetting the [SnackBar] here
111
- // results in the same message popping in and out and the user experience
112
- // is better for now if we allow them to run their timer through
113
- // and clear the backlog later.
114
- scaffoldMessenger.showSnackBar (SnackBar (behavior: SnackBarBehavior .floating,
115
- content: Text (zulipLocalizations.markAsReadInProgress)));
101
+ // The task is taking a while, so tell the user we're working on it.
102
+ // No need to say how many messages, as the [MarkAsUnread] widget
103
+ // should follow along.
104
+ // TODO: Ideally we'd have a progress widget here that showed up based
105
+ // on actual time elapsed -- so it could appear before the first
106
+ // batch returns, if that takes a while -- and that then stuck
107
+ // around continuously until the task ends. For now we use a
108
+ // series of [SnackBar]s, which may feel a bit janky.
109
+ // There is complexity in tracking the status of each [SnackBar],
110
+ // due to having no way to determine which is currently active,
111
+ // or if there is an active one at all. Resetting the [SnackBar] here
112
+ // results in the same message popping in and out and the user experience
113
+ // is better for now if we allow them to run their timer through
114
+ // and clear the backlog later.
115
+ scaffoldMessenger.showSnackBar (SnackBar (behavior: SnackBarBehavior .floating,
116
+ content: Text (zulipLocalizations.markAsReadInProgress)));
117
+ }
118
+ } catch (e) {
119
+ if (! context.mounted) return false ;
120
+ final zulipLocalizations = ZulipLocalizations .of (context);
121
+ showErrorDialog (context: context,
122
+ title: zulipLocalizations.errorMarkAsReadFailedTitle,
123
+ message: e.toString ()); // TODO(#741): extract user-facing message better
124
+ return false ;
116
125
}
117
126
}
118
127
0 commit comments