msglist: add scroll-to-bottom button to MessageList#223
Conversation
013c739 to
fdc9d0c
Compare
|
@gnprice @chrisbobbe Looking for some draft-stage comments on this! |
gnprice
left a comment
There was a problem hiding this comment.
Thanks @sirpengi! Generally this direction looks good — I think the only comment on the high-level direction is about how to listen for scroll events. Please see that and a few other comments below, and a couple of tests would also be very helpful.
It looks like we don't currently have any tests for this MessageList widget. I think at this point we have all the test infrastructure to be able to write tests for it, but there might still be something we're missing — please ask in #mobile-team if you run into any trouble.
gnprice
left a comment
There was a problem hiding this comment.
Thanks @sirpengi! I've now gone through the code for a full review; detailed comments below.
I think this structure is working well, and I'm happy to see that the tests turned out pretty clean too. Most of the comments I have are stylistic, and many of those are minor nits; there's a few that are more substantive, but I don't think any of them will be complex to deal with.
There was a problem hiding this comment.
It looks like there are some tab characters in here. I don't actually notice when reading in Android Studio — I guess I have tab stops of 2 columns and that must be the same as you were writing with — but it makes things harder to read on GitHub and in git log.
There was a problem hiding this comment.
nit: separate these with a blank line
There was a problem hiding this comment.
analyzer complains this ! is redundant
There was a problem hiding this comment.
nit: This comment doesn't really add information that isn't in the name, so better to leave out.
There was a problem hiding this comment.
Rather than look at visibleValue, I'd prefer to have the test check more directly that the button is visible, or isn't. That seems like it's the real contract we're asking this part of the UI logic to fulfill; so testing at that layer lets visibleValue (and even the ScrollToBottomButton class, I think) be an implementation detail that can be freely refactored. It also enables the test to catch bugs in a wider swath of the code, in case some future change were to break something in the connection from visibleValue to the actual showing of the button.
I think find.byTooltip gives a good way to do that.
There was a problem hiding this comment.
nit: this line is awfully long — let's break the arguments onto their own lines
There was a problem hiding this comment.
Since we're having this state create these resources, let's have it dispose them in its own dispose method.
I'm not sure that ultimately affects anything in this case — maybe nothing else is left that has a reference to them by the time this state gets disposed — but I don't know a reason to be sure it doesn't matter here, and the pattern "always dispose all the state's resources in dispose" seems like a good one to consistently follow because sometimes it does matter.
There was a problem hiding this comment.
nit: break these arguments onto separate lines — in particular the value for curve is a meaningful UI choice, and it's easy for it to get lost off on the right past 80 columns
There was a problem hiding this comment.
Can you tell me about your reasoning for picking Curves.easeIn?
There was a problem hiding this comment.
I hate to admit I didn't review all the curve behaviors fully. I did notice that the web behavior is to jump to the bottom and the mobile behavior seems linear. In my previous work with UI I've always found ease-type functions to feel more natural. I must admit my 300ms timer was also a sort of "default practice" for UI based on previous work with animation timings. To evaluate this topic more, I've looked over the material design guidance for motion, see https://m2.material.io/design/motion/speed.html#controlling-speed and https://m3.material.io/styles/motion/easing-and-duration/applying-easing-and-duration and while I got the 300ms perfectly right for their recommended default animation they both recommend a quick-start and slow down for easing, which I believe maps more to the Curves.ease rather than Curves.easeIn. I'd conclude I should switch this to Curves.ease instead to match? Unless there is another style guide to consider in this design?
There was a problem hiding this comment.
Cool. Yeah, that fast-start, slow-finish curve sounds good.
There was a problem hiding this comment.
Let's have one more test case — testing that the button actually works :-)
e8b9cca to
fccf8c6
Compare
gnprice
left a comment
There was a problem hiding this comment.
Thanks @sirpengi for the revision! This is very close to merge now — one substantive comment on the new test case, and a few nits.
See below, and also two small things above that remain open:
#223 (comment)
#223 (comment)
When I merge this, I'll also squash all the commits into one, because ultimately they're all revisions to a single coherent change.
Many PRs end up as several commits because they make preparatory refactors, or add a feature in one place and then another feature that builds on that; in order to support those, our usual workflow is that each revision is a new draft of the whole final sequence of commits to merge, which means the author does this sort of squashing. (That does cause GitHub to be less helpful about comparing different revisions; the reviewer instead relies on having fetched a local copy, and we have a couple of scripts to help make that easy.)
But for this PR, go ahead and carry on adding commits on top. Squashing at merge time is easy when it's all going to be a single commit (as this is), and having gone most of the way in this style it's probably simplest all around to finish it that way.
There was a problem hiding this comment.
Let's check instead that the scroll controller's actual position is at the bottom — that way this test wouldn't accidentally pass if we introduced some bug where the button didn't actually work, but did cause the button to go away 🙂
There was a problem hiding this comment.
nit:
| visibleValue: _scrollToBottomVisibleValue))]))))))); | |
| visibleValue: _scrollToBottomVisibleValue)), | |
| ]))))))); |
(For lists […] we end the last item with comma-newline just like the other items, while for child arguments and many other function arguments, as you've seen, we stack up parens on the final line.
This reflects the fact that the different elements of a list one often wants to think of as relatively equal/symmetric siblings, and one may well remove the last element or insert more after it; whereas a child argument one thinks of differently from the more metadata-like other arguments, and we'll never insert another argument after a widget's child.)
f556b8d to
e4cf32b
Compare
|
@gnprice okay I believe this is ready again, with all comments addressed. I've rebased onto an updated |
There was a problem hiding this comment.
nit:
| import '../model/binding.dart'; | |
| Future<void> setupMessageListPage(WidgetTester tester, { | |
| import '../model/binding.dart'; | |
| Future<void> setupMessageListPage(WidgetTester tester, { |
e4cf32b to
5abeb88
Compare
Fixes zulip#1485. This logic for deciding how long the scroll-to-bottom animation should take, introduced in 5abeb88 (zulip#223), didn't have any tests. As a result, when its unstated assumption about the message list -- that scrolling up from the end was represented by positive scroll positions -- was broken a few months later (in bdac26f), nothing alerted us to that. I did notice a few times over the past year or so that the effect of the scroll-to-bottom button seemed jerky, as if it were trying to move much farther in each frame than it should. Now I know why. (Discovered this in the course of revisiting this code in order to adapt it to the more radical change to the message list's scroll positions which is coming up: "zero" won't be the end, but somewhere in the middle.)
Fixes #1485. This logic for deciding how long the scroll-to-bottom animation should take, introduced in 5abeb88 (#223), didn't have any tests. As a result, when its unstated assumption about the message list -- that scrolling up from the end was represented by positive scroll positions -- was broken a few months later (in bdac26f), nothing alerted us to that. I did notice a few times over the past year or so that the effect of the scroll-to-bottom button seemed jerky, as if it were trying to move much farther in each frame than it should. Now I know why. (Discovered this in the course of revisiting this code in order to adapt it to the more radical change to the message list's scroll positions which is coming up: "zero" won't be the end, but somewhere in the middle.)
Introducing a scroll-to-bottom button in the
MessageListcomponent that shows up only if the user is not at the bottom of the list. Clicking on that button triggers a scroll to the bottom.Notes