@@ -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
@@ -188,18 +202,37 @@ mixin _MessageSequence {
188202
189203 /// Whether this message list is currently busy when it comes to
190204 /// fetching more messages.
205+ bool get busyFetchingMore => busyFetchingOlder || busyFetchingNewer;
206+
207+ /// Whether this message list is currently busy when it comes to
208+ /// fetching older messages.
209+ ///
210+ /// Here "busy" means a new call to fetch older messages would do nothing,
211+ /// rather than make any request to the server,
212+ /// as a result of an existing recent request.
213+ /// This is true both when the recent request is still outstanding,
214+ /// and when it failed and the backoff from that is still in progress.
215+ bool get busyFetchingOlder => switch (_fetchOlderStatus) {
216+ .fetching || .backoff => true ,
217+ _ => false ,
218+ };
219+
220+ /// Whether this message list is currently busy when it comes to
221+ /// fetching newer messages.
191222 ///
192- /// Here "busy" means a new call to fetch more messages would do nothing,
223+ /// Here "busy" means a new call to fetch older messages would do nothing,
193224 /// rather than make any request to the server,
194225 /// as a result of an existing recent request.
195226 /// This is true both when the recent request is still outstanding,
196227 /// 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 ,
228+ bool get busyFetchingNewer => switch (_fetchNewerStatus ) {
229+ .fetching || .backoff => true ,
199230 _ => false ,
200231 };
201232
202- FetchingStatus _status = FetchingStatus .unstarted;
233+ FetchingInitialStatus _fetchInitialStatus = .unstarted;
234+ FetchingMoreStatus _fetchOlderStatus = .unstarted;
235+ FetchingMoreStatus _fetchNewerStatus = .unstarted;
203236
204237 BackoffMachine ? _fetchBackoffMachine;
205238
@@ -434,7 +467,9 @@ mixin _MessageSequence {
434467 outboxMessages.clear ();
435468 _haveOldest = false ;
436469 _haveNewest = false ;
437- _status = FetchingStatus .unstarted;
470+ _fetchInitialStatus = .unstarted;
471+ _fetchOlderStatus = .unstarted;
472+ _fetchNewerStatus = .unstarted;
438473 _fetchBackoffMachine = null ;
439474 contents.clear ();
440475 items.clear ();
@@ -786,16 +821,28 @@ class MessageListView with ChangeNotifier, _MessageSequence {
786821 }
787822 }
788823
789- void _setStatus (FetchingStatus value, {FetchingStatus ? was}) {
790- assert (was == null || _status == was);
791- _status = value;
792- if (! fetched) return ;
824+ void _setInitialStatus (FetchingInitialStatus value, {FetchingInitialStatus ? was}) {
825+ assert (was == null || _fetchInitialStatus == was);
826+ _fetchInitialStatus = value;
827+ if (! initialFetched) return ;
828+ notifyListeners ();
829+ }
830+
831+ void _setOlderStatus (FetchingMoreStatus value, {FetchingMoreStatus ? was}) {
832+ assert (was == null || _fetchOlderStatus == was);
833+ _fetchOlderStatus = value;
834+ notifyListeners ();
835+ }
836+
837+ void _setNewerStatus (FetchingMoreStatus value, {FetchingMoreStatus ? was}) {
838+ assert (was == null || _fetchNewerStatus == was);
839+ _fetchNewerStatus = value;
793840 notifyListeners ();
794841 }
795842
796843 /// Fetch messages, starting from scratch.
797844 Future <void > fetchInitial () async {
798- assert (! fetched && ! haveOldest && ! haveNewest && ! busyFetchingMore);
845+ assert (! initialFetched && ! haveOldest && ! haveNewest && ! busyFetchingMore);
799846 assert (messages.isEmpty && contents.isEmpty);
800847 assert (oldMessageId == null && newMessageId == null );
801848
@@ -805,11 +852,11 @@ class MessageListView with ChangeNotifier, _MessageSequence {
805852 // probably better if the UI code doesn't take it to this point.
806853 _haveOldest = true ;
807854 _haveNewest = true ;
808- _setStatus ( FetchingStatus .idle, was: FetchingStatus .unstarted);
855+ _setInitialStatus ( .idle, was: .unstarted);
809856 return ;
810857 }
811858
812- _setStatus ( FetchingStatus .fetchInitial , was: FetchingStatus .unstarted);
859+ _setInitialStatus (.fetching , was: .unstarted);
813860 // TODO schedule all this in another isolate
814861 final generation = this .generation;
815862 final result = await getMessages (store.connection,
@@ -850,7 +897,7 @@ class MessageListView with ChangeNotifier, _MessageSequence {
850897 _syncOutboxMessagesFromStore ();
851898 }
852899
853- _setStatus ( FetchingStatus .idle, was: FetchingStatus .fetchInitial );
900+ _setInitialStatus ( .idle, was: .fetching );
854901 }
855902
856903 /// Update [narrow] for the result of a "with" narrow (topic permalink) fetch.
@@ -888,23 +935,24 @@ class MessageListView with ChangeNotifier, _MessageSequence {
888935 /// Fetch the next batch of older messages, if applicable.
889936 ///
890937 /// If there are no older messages to fetch (i.e. if [haveOldest] ),
891- /// or if this message list is already busy fetching more messages
892- /// (i.e. if [busyFetchingMore ] , which includes backoff from failed requests),
938+ /// or if this message list is already busy fetching older messages
939+ /// (i.e. if [busyFetchingOlder ] , which includes backoff from failed requests),
893940 /// then this method does nothing and immediately returns.
894941 /// That makes this method suitable to call frequently, e.g. every frame,
895- /// whenever it looks likely to be useful to have more messages.
942+ /// whenever it looks likely to be useful to have older messages.
896943 Future <void > fetchOlder () async {
897944 final generation = this .generation;
898945 int visibleMessageCount = 0 ;
899946 do {
900947 if (haveOldest) return ;
901- if (busyFetchingMore ) return ;
902- assert (fetched );
948+ if (busyFetchingOlder ) return ;
949+ assert (initialFetched );
903950 assert (oldMessageId != null );
904951 await _fetchMore (
905952 anchor: NumericAnchor (oldMessageId! ),
906953 numBefore: kMessageListFetchBatchSize,
907954 numAfter: 0 ,
955+ setStatus: _setOlderStatus,
908956 processResult: (result) {
909957 _oldMessageId = result.messages.firstOrNull? .id ?? oldMessageId;
910958 store.reconcileMessages (result.messages);
@@ -925,23 +973,24 @@ class MessageListView with ChangeNotifier, _MessageSequence {
925973 /// Fetch the next batch of newer messages, if applicable.
926974 ///
927975 /// If there are no newer messages to fetch (i.e. if [haveNewest] ),
928- /// or if this message list is already busy fetching more messages
929- /// (i.e. if [busyFetchingMore ] , which includes backoff from failed requests),
976+ /// or if this message list is already busy fetching newer messages
977+ /// (i.e. if [busyFetchingNewer ] , which includes backoff from failed requests),
930978 /// then this method does nothing and immediately returns.
931979 /// That makes this method suitable to call frequently, e.g. every frame,
932- /// whenever it looks likely to be useful to have more messages.
980+ /// whenever it looks likely to be useful to have newer messages.
933981 Future <void > fetchNewer () async {
934982 final generation = this .generation;
935983 int visibleMessageCount = 0 ;
936984 do {
937985 if (haveNewest) return ;
938- if (busyFetchingMore ) return ;
939- assert (fetched );
986+ if (busyFetchingNewer ) return ;
987+ assert (initialFetched );
940988 assert (newMessageId != null );
941989 await _fetchMore (
942990 anchor: NumericAnchor (newMessageId! ),
943991 numBefore: 0 ,
944992 numAfter: kMessageListFetchBatchSize,
993+ setStatus: _setNewerStatus,
945994 processResult: (result) {
946995 _newMessageId = result.messages.lastOrNull? .id ?? newMessageId;
947996 store.reconcileMessages (result.messages);
@@ -967,12 +1016,13 @@ class MessageListView with ChangeNotifier, _MessageSequence {
9671016 required Anchor anchor,
9681017 required int numBefore,
9691018 required int numAfter,
1019+ required void Function (FetchingMoreStatus value, {FetchingMoreStatus ? was}) setStatus,
9701020 required void Function (GetMessagesResult ) processResult,
9711021 }) async {
9721022 assert (narrow is ! TopicNarrow
9731023 // We only intend to send "with" in [fetchInitial]; see there.
9741024 || (narrow as TopicNarrow ).with_ == null );
975- _setStatus ( FetchingStatus .fetchingMore, was : FetchingStatus .idle );
1025+ setStatus (.fetching );
9761026 final generation = this .generation;
9771027 bool hasFetchError = false ;
9781028 try {
@@ -993,14 +1043,14 @@ class MessageListView with ChangeNotifier, _MessageSequence {
9931043 } finally {
9941044 if (this .generation == generation) {
9951045 if (hasFetchError) {
996- _setStatus ( FetchingStatus .backoff, was: FetchingStatus .fetchingMore );
1046+ setStatus ( .backoff, was: .fetching );
9971047 unawaited ((_fetchBackoffMachine ?? = BackoffMachine ())
9981048 .wait ().then ((_) {
9991049 if (this .generation != generation) return ;
1000- _setStatus ( FetchingStatus .idle, was: FetchingStatus .backoff);
1050+ setStatus ( .idle, was: .backoff);
10011051 }));
10021052 } else {
1003- _setStatus ( FetchingStatus .idle, was: FetchingStatus .fetchingMore );
1053+ setStatus ( .idle, was: .fetching );
10041054 _fetchBackoffMachine = null ;
10051055 }
10061056 }
@@ -1012,7 +1062,7 @@ class MessageListView with ChangeNotifier, _MessageSequence {
10121062 /// This will set [anchor] to [AnchorCode.newest] ,
10131063 /// and cause messages to be re-fetched from scratch.
10141064 void jumpToEnd () {
1015- assert (fetched );
1065+ assert (initialFetched );
10161066 assert (! haveNewest);
10171067 assert (anchor != AnchorCode .newest);
10181068 _anchor = AnchorCode .newest;
@@ -1094,7 +1144,7 @@ class MessageListView with ChangeNotifier, _MessageSequence {
10941144 // TODO get the newly-unmuted messages from the message store
10951145 // For now, we simplify the task by just refetching this message list
10961146 // from scratch.
1097- if (fetched ) {
1147+ if (initialFetched ) {
10981148 _reset ();
10991149 notifyListeners ();
11001150 fetchInitial ();
@@ -1122,7 +1172,7 @@ class MessageListView with ChangeNotifier, _MessageSequence {
11221172 // TODO get the newly-unmuted messages from the message store
11231173 // For now, we simplify the task by just refetching this message list
11241174 // from scratch.
1125- if (fetched ) {
1175+ if (initialFetched ) {
11261176 _reset ();
11271177 notifyListeners ();
11281178 fetchInitial ();
0 commit comments