Skip to content

Commit 5395f48

Browse files
committed
wip msglist: Jump, not scroll, to end when it might be far; TODO test
When the message list is truly far back in history -- for example, at first unread in the combined feed or a busy channel, for a user who has some old unreads going back months and years -- trying to scroll smoothly to the bottom is hopeless. The only way to get to the newest messages in any reasonable amount of time is to jump there. So, do that.
1 parent bbb6704 commit 5395f48

File tree

2 files changed

+47
-4
lines changed

2 files changed

+47
-4
lines changed

lib/model/message_list.dart

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@ class MessageListView with ChangeNotifier, _MessageSequence {
479479
/// which might be made internally by this class in order to
480480
/// fetch the messages from scratch, e.g. after certain events.
481481
Anchor get anchor => _anchor;
482-
final Anchor _anchor;
482+
Anchor _anchor;
483483

484484
void _register() {
485485
store.registerMessageList(this);
@@ -756,6 +756,20 @@ class MessageListView with ChangeNotifier, _MessageSequence {
756756
}
757757
}
758758

759+
/// Reset this view to start from the newest messages.
760+
///
761+
/// This will set [anchor] to [AnchorCode.newest],
762+
/// and cause messages to be re-fetched from scratch.
763+
void jumpToEnd() {
764+
assert(fetched);
765+
assert(!haveNewest);
766+
assert(anchor != AnchorCode.newest);
767+
_anchor = AnchorCode.newest;
768+
_reset();
769+
notifyListeners();
770+
fetchInitial();
771+
}
772+
759773
/// Add [outboxMessage] if it belongs to the view.
760774
void addOutboxMessage(OutboxMessage outboxMessage) {
761775
// TODO(#1441) implement this

lib/widgets/message_list.dart

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,7 @@ class _MessageListState extends State<MessageList> with PerAccountStoreAwareStat
552552
// redirected us to the new location of the operand message ID.
553553
widget.onNarrowChanged(model.narrow);
554554
}
555+
// TODO when model reset, reset scroll
555556
setState(() {
556557
// The actual state lives in the [MessageListView] model.
557558
// This method was called because that just changed.
@@ -627,6 +628,7 @@ class _MessageListState extends State<MessageList> with PerAccountStoreAwareStat
627628
// MessageList's dartdoc.
628629
child: SafeArea(
629630
child: ScrollToBottomButton(
631+
model: model,
630632
scrollController: scrollController,
631633
visible: _scrollToBottomVisible))),
632634
])))));
@@ -826,13 +828,40 @@ class _MessageListLoadingMore extends StatelessWidget {
826828
}
827829

828830
class ScrollToBottomButton extends StatelessWidget {
829-
const ScrollToBottomButton({super.key, required this.scrollController, required this.visible});
831+
const ScrollToBottomButton({
832+
super.key,
833+
required this.model,
834+
required this.scrollController,
835+
required this.visible,
836+
});
830837

831-
final ValueNotifier<bool> visible;
838+
final MessageListView model;
832839
final MessageListScrollController scrollController;
840+
final ValueNotifier<bool> visible;
833841

834842
void _scrollToBottom() {
835-
scrollController.position.scrollToEnd();
843+
if (model.haveNewest) {
844+
// Scrolling smoothly from here to the bottom won't require any requests
845+
// to the server.
846+
// It also probably isn't *that* far away: the user must have scrolled
847+
// here from there (or from near enough that a fetch reached there),
848+
// so scrolling back there -- at top speed -- shouldn't take too long.
849+
// Go for it.
850+
scrollController.position.scrollToEnd();
851+
} else {
852+
// This message list doesn't have the messages for the bottom of history.
853+
// There could be quite a lot of history between here and there --
854+
// for example, at first unread in the combined feed or a busy channel,
855+
// for a user who has some old unreads going back months and years.
856+
// In that case trying to scroll smoothly to the bottom is hopeless.
857+
//
858+
// Given that there were at least 100 messages between this message list's
859+
// initial anchor and the end of history (or else `fetchInitial` would
860+
// have reached the end at the outset), that situation is very likely.
861+
// Even if the end is close by, it's at least one fetch away.
862+
// Instead of scrolling, jump to the end, which is always just one fetch.
863+
model.jumpToEnd();
864+
}
836865
}
837866

838867
@override

0 commit comments

Comments
 (0)