@@ -83,22 +83,33 @@ class MessageListOutboxMessageItem extends MessageListMessageBaseItem {
8383 ]);
8484}
8585
86- /// The status of outstanding or recent fetch requests from a [MessageListView] .
87- enum FetchingStatus {
88- /// The model has not made any fetch requests (since its last reset, if any).
86+ /// The status of outstanding or recent `fetchInitial` request from a [MessageListView] .
87+ enum FetchingInitialStatus {
88+ /// The model has not made a `fetchInitial` request (since its last reset, if any).
8989 unstarted,
9090
9191 /// The model has made a `fetchInitial` request, which hasn't succeeded.
92- fetchInitial ,
92+ fetching ,
9393
94- /// The model made a successful `fetchInitial` request,
95- /// and has no outstanding requests or backoff.
94+ /// The model made a successful `fetchInitial` request.
9695 idle,
96+ }
97+
98+ /// The status of outstanding or recent "fetch more" request from a [MessageListView] .
99+ ///
100+ /// By a "fetch more" request we mean a `fetchOlder` or a `fetchNewer` request.
101+ enum FetchingMoreStatus {
102+ /// The model has not made the "fetch more" request (since its last reset, if any).
103+ unstarted,
104+
105+ /// The model has made the "fetch more" request, which hasn't succeeded.
106+ fetching,
97107
98- /// The model has an active `fetchOlder` or `fetchNewer` request.
99- fetchingMore,
108+ /// The model made a successful "fetch more" request,
109+ /// and has no outstanding request of the same kind or backoff.
110+ idle,
100111
101- /// The model is in a backoff period from a failed request.
112+ /// The model is in a backoff period from the failed "fetch more" request.
102113 backoff,
103114}
104115
@@ -125,7 +136,7 @@ mixin _MessageSequence {
125136 ///
126137 /// This may or may not represent all the message history that
127138 /// conceptually belongs in this message list.
128- /// That information is expressed in [fetched ] , [haveOldest] , [haveNewest] .
139+ /// That information is expressed in [initialFetched ] , [haveOldest] , [haveNewest] .
129140 ///
130141 /// This also may or may not represent all the message history that
131142 /// conceptually belongs in this narrow because some messages might be
@@ -165,12 +176,15 @@ mixin _MessageSequence {
165176 int ? get newMessageId => _newMessageId;
166177 int ? _newMessageId;
167178
168- /// Whether [messages] and [items] represent the results of a fetch .
179+ /// Whether the first batch of messages for this narrow is fetched yet .
169180 ///
170- /// This allows the UI to distinguish "still working on fetching messages"
171- /// from "there are in fact no messages here".
172- bool get fetched => switch (_status) {
173- FetchingStatus .unstarted || FetchingStatus .fetchInitial => false ,
181+ /// Some or all of the fetched messages may not make it to [messages]
182+ /// and [items] if they're muted in one way or another.
183+ ///
184+ /// This allows the UI to distinguish "still working on fetching first batch
185+ /// of messages" from "there are in fact no messages here".
186+ bool get initialFetched => switch (_fetchInitialStatus) {
187+ .unstarted || .fetching => false ,
174188 _ => true ,
175189 };
176190
@@ -187,19 +201,34 @@ mixin _MessageSequence {
187201 bool _haveNewest = false ;
188202
189203 /// Whether this message list is currently busy when it comes to
190- /// fetching more messages.
204+ /// fetching older messages.
205+ ///
206+ /// Here "busy" means a new call to fetch older messages would do nothing,
207+ /// rather than make any request to the server,
208+ /// as a result of an existing recent request.
209+ /// This is true both when the recent request is still outstanding,
210+ /// and when it failed and the backoff from that is still in progress.
211+ bool get busyFetchingOlder => switch (_fetchOlderStatus) {
212+ .fetching || .backoff => true ,
213+ _ => false ,
214+ };
215+
216+ /// Whether this message list is currently busy when it comes to
217+ /// fetching newer messages.
191218 ///
192- /// Here "busy" means a new call to fetch more messages would do nothing,
219+ /// Here "busy" means a new call to fetch older messages would do nothing,
193220 /// rather than make any request to the server,
194221 /// as a result of an existing recent request.
195222 /// This is true both when the recent request is still outstanding,
196223 /// and when it failed and the backoff from that is still in progress.
197- bool get busyFetchingMore => switch (_status ) {
198- FetchingStatus .fetchingMore || FetchingStatus .backoff => true ,
224+ bool get busyFetchingNewer => switch (_fetchNewerStatus ) {
225+ .fetching || .backoff => true ,
199226 _ => false ,
200227 };
201228
202- FetchingStatus _status = FetchingStatus .unstarted;
229+ FetchingInitialStatus _fetchInitialStatus = .unstarted;
230+ FetchingMoreStatus _fetchOlderStatus = .unstarted;
231+ FetchingMoreStatus _fetchNewerStatus = .unstarted;
203232
204233 BackoffMachine ? _fetchBackoffMachine;
205234
@@ -228,7 +257,7 @@ mixin _MessageSequence {
228257 /// [MessageListOutboxMessageItem] s corresponding to [outboxMessages] .
229258 ///
230259 /// This information is completely derived from [messages] , [outboxMessages] ,
231- /// and the flags [haveOldest] , [haveNewest] , and [busyFetchingMore ] .
260+ /// and the flags [haveOldest] , [haveNewest] , [busyFetchingNewer] , and [busyFetchingOlder ] .
232261 /// It exists as an optimization, to memoize that computation.
233262 ///
234263 /// See also [middleItem] , an index which divides this list
@@ -434,7 +463,9 @@ mixin _MessageSequence {
434463 outboxMessages.clear ();
435464 _haveOldest = false ;
436465 _haveNewest = false ;
437- _status = FetchingStatus .unstarted;
466+ _fetchInitialStatus = .unstarted;
467+ _fetchOlderStatus = .unstarted;
468+ _fetchNewerStatus = .unstarted;
438469 _fetchBackoffMachine = null ;
439470 contents.clear ();
440471 items.clear ();
@@ -786,16 +817,29 @@ class MessageListView with ChangeNotifier, _MessageSequence {
786817 }
787818 }
788819
789- void _setStatus (FetchingStatus value, {FetchingStatus ? was}) {
790- assert (was == null || _status == was);
791- _status = value;
792- if (! fetched) return ;
820+ void _setInitialStatus (FetchingInitialStatus value, {FetchingInitialStatus ? was}) {
821+ assert (was == null || _fetchInitialStatus == was);
822+ _fetchInitialStatus = value;
823+ if (! initialFetched) return ;
824+ notifyListeners ();
825+ }
826+
827+ void _setOlderStatus (FetchingMoreStatus value, {FetchingMoreStatus ? was}) {
828+ assert (was == null || _fetchOlderStatus == was);
829+ _fetchOlderStatus = value;
830+ notifyListeners ();
831+ }
832+
833+ void _setNewerStatus (FetchingMoreStatus value, {FetchingMoreStatus ? was}) {
834+ assert (was == null || _fetchNewerStatus == was);
835+ _fetchNewerStatus = value;
793836 notifyListeners ();
794837 }
795838
796839 /// Fetch messages, starting from scratch.
797840 Future <void > fetchInitial () async {
798- assert (! fetched && ! haveOldest && ! haveNewest && ! busyFetchingMore);
841+ assert (! initialFetched && ! haveOldest && ! haveNewest
842+ && ! busyFetchingOlder && ! busyFetchingNewer);
799843 assert (messages.isEmpty && contents.isEmpty);
800844 assert (oldMessageId == null && newMessageId == null );
801845
@@ -805,11 +849,11 @@ class MessageListView with ChangeNotifier, _MessageSequence {
805849 // probably better if the UI code doesn't take it to this point.
806850 _haveOldest = true ;
807851 _haveNewest = true ;
808- _setStatus ( FetchingStatus .idle, was: FetchingStatus .unstarted);
852+ _setInitialStatus ( .idle, was: .unstarted);
809853 return ;
810854 }
811855
812- _setStatus ( FetchingStatus .fetchInitial , was: FetchingStatus .unstarted);
856+ _setInitialStatus (.fetching , was: .unstarted);
813857 // TODO schedule all this in another isolate
814858 final generation = this .generation;
815859 final result = await getMessages (store.connection,
@@ -851,7 +895,7 @@ class MessageListView with ChangeNotifier, _MessageSequence {
851895 _syncOutboxMessagesFromStore ();
852896 }
853897
854- _setStatus ( FetchingStatus .idle, was: FetchingStatus .fetchInitial );
898+ _setInitialStatus ( .idle, was: .fetching );
855899 }
856900
857901 /// Update [narrow] for the result of a "with" narrow (topic permalink) fetch.
@@ -889,23 +933,24 @@ class MessageListView with ChangeNotifier, _MessageSequence {
889933 /// Fetch the next batch of older messages, if applicable.
890934 ///
891935 /// If there are no older messages to fetch (i.e. if [haveOldest] ),
892- /// or if this message list is already busy fetching more messages
893- /// (i.e. if [busyFetchingMore ] , which includes backoff from failed requests),
936+ /// or if this message list is already busy fetching older messages
937+ /// (i.e. if [busyFetchingOlder ] , which includes backoff from failed requests),
894938 /// then this method does nothing and immediately returns.
895939 /// That makes this method suitable to call frequently, e.g. every frame,
896- /// whenever it looks likely to be useful to have more messages.
940+ /// whenever it looks likely to be useful to have older messages.
897941 Future <void > fetchOlder () async {
898942 final generation = this .generation;
899943 int visibleMessageCount = 0 ;
900944 do {
901945 if (haveOldest) return ;
902- if (busyFetchingMore ) return ;
903- assert (fetched );
946+ if (busyFetchingOlder ) return ;
947+ assert (initialFetched );
904948 assert (oldMessageId != null );
905949 await _fetchMore (
906950 anchor: NumericAnchor (oldMessageId! ),
907951 numBefore: kMessageListFetchBatchSize,
908952 numAfter: 0 ,
953+ setStatus: _setOlderStatus,
909954 processResult: (result) {
910955 _oldMessageId = result.messages.firstOrNull? .id ?? oldMessageId;
911956 store.reconcileMessages (result.messages);
@@ -926,23 +971,24 @@ class MessageListView with ChangeNotifier, _MessageSequence {
926971 /// Fetch the next batch of newer messages, if applicable.
927972 ///
928973 /// If there are no newer messages to fetch (i.e. if [haveNewest] ),
929- /// or if this message list is already busy fetching more messages
930- /// (i.e. if [busyFetchingMore ] , which includes backoff from failed requests),
974+ /// or if this message list is already busy fetching newer messages
975+ /// (i.e. if [busyFetchingNewer ] , which includes backoff from failed requests),
931976 /// then this method does nothing and immediately returns.
932977 /// That makes this method suitable to call frequently, e.g. every frame,
933- /// whenever it looks likely to be useful to have more messages.
978+ /// whenever it looks likely to be useful to have newer messages.
934979 Future <void > fetchNewer () async {
935980 final generation = this .generation;
936981 int visibleMessageCount = 0 ;
937982 do {
938983 if (haveNewest) return ;
939- if (busyFetchingMore ) return ;
940- assert (fetched );
984+ if (busyFetchingNewer ) return ;
985+ assert (initialFetched );
941986 assert (newMessageId != null );
942987 await _fetchMore (
943988 anchor: NumericAnchor (newMessageId! ),
944989 numBefore: 0 ,
945990 numAfter: kMessageListFetchBatchSize,
991+ setStatus: _setNewerStatus,
946992 processResult: (result) {
947993 _newMessageId = result.messages.lastOrNull? .id ?? newMessageId;
948994 store.reconcileMessages (result.messages);
@@ -968,12 +1014,13 @@ class MessageListView with ChangeNotifier, _MessageSequence {
9681014 required Anchor anchor,
9691015 required int numBefore,
9701016 required int numAfter,
1017+ required void Function (FetchingMoreStatus value, {FetchingMoreStatus ? was}) setStatus,
9711018 required void Function (GetMessagesResult ) processResult,
9721019 }) async {
9731020 assert (narrow is ! TopicNarrow
9741021 // We only intend to send "with" in [fetchInitial]; see there.
9751022 || (narrow as TopicNarrow ).with_ == null );
976- _setStatus ( FetchingStatus .fetchingMore, was : FetchingStatus .idle );
1023+ setStatus (.fetching );
9771024 final generation = this .generation;
9781025 bool hasFetchError = false ;
9791026 try {
@@ -994,14 +1041,14 @@ class MessageListView with ChangeNotifier, _MessageSequence {
9941041 } finally {
9951042 if (this .generation == generation) {
9961043 if (hasFetchError) {
997- _setStatus ( FetchingStatus .backoff, was: FetchingStatus .fetchingMore );
1044+ setStatus ( .backoff, was: .fetching );
9981045 unawaited ((_fetchBackoffMachine ?? = BackoffMachine ())
9991046 .wait ().then ((_) {
10001047 if (this .generation != generation) return ;
1001- _setStatus ( FetchingStatus .idle, was: FetchingStatus .backoff);
1048+ setStatus ( .idle, was: .backoff);
10021049 }));
10031050 } else {
1004- _setStatus ( FetchingStatus .idle, was: FetchingStatus .fetchingMore );
1051+ setStatus ( .idle, was: .fetching );
10051052 _fetchBackoffMachine = null ;
10061053 }
10071054 }
@@ -1013,7 +1060,7 @@ class MessageListView with ChangeNotifier, _MessageSequence {
10131060 /// This will set [anchor] to [AnchorCode.newest] ,
10141061 /// and cause messages to be re-fetched from scratch.
10151062 void jumpToEnd () {
1016- assert (fetched );
1063+ assert (initialFetched );
10171064 assert (! haveNewest);
10181065 assert (anchor != AnchorCode .newest);
10191066 _anchor = AnchorCode .newest;
@@ -1095,7 +1142,7 @@ class MessageListView with ChangeNotifier, _MessageSequence {
10951142 // TODO get the newly-unmuted messages from the message store
10961143 // For now, we simplify the task by just refetching this message list
10971144 // from scratch.
1098- if (fetched ) {
1145+ if (initialFetched ) {
10991146 _reset ();
11001147 notifyListeners ();
11011148 fetchInitial ();
@@ -1123,7 +1170,7 @@ class MessageListView with ChangeNotifier, _MessageSequence {
11231170 // TODO get the newly-unmuted messages from the message store
11241171 // For now, we simplify the task by just refetching this message list
11251172 // from scratch.
1126- if (fetched ) {
1173+ if (initialFetched ) {
11271174 _reset ();
11281175 notifyListeners ();
11291176 fetchInitial ();
0 commit comments