-
Notifications
You must be signed in to change notification settings - Fork 28.9k
Assert for valid ScrollController in Scrollbar gestures #81278
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption to this rule, contact Hixie on the #hackers channel in Chat. If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix? Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. |
Update: This same check can also be found in the other CupertinoScrollbar gestures:
|
Thanks for the contribution! Is there a test you can add that shows what issue this fixes (that would have failed before your patch)? |
@tvolkert I tried looking into related tests in the framework but I didn't find any. In fact, I removed the checks from all gestures in the scrollbar and tests were still passing. |
@tvolkert I've added some tests. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @davidmartos96 thank you for filing an issue and writing a PR for it! :)
This one in particular happens when we pass a scroll controller to a scroll view but not to the scrollbar.
This is the cause of the issue. You are seeing this error in your code because the Scrollbar
is trying to use the PrimaryScrollController
. It uses this ScrollController
when one has not been provided. Since you have provided a ScrollController
to the ListView
, the Scrollbar and ListView are essentially detached. The Scrollbar still updates, since it listens to ScrollNotifications
that bubble up, but when you try to interact with it, it is trying to use a different controller than the one your ListView actually has.
Providing your ListView's ScrollController to the Scrollbar should resolve your issue, or if not needed, you can remove the scroll controller from the ListView.
So, while this change prevents an exception from being thrown, it actually introduces a way for users to break their scrollbar without knowing why. I've updated the bug to reflect a need for better error messaging here, we recently added some in #77107 for isAlwaysShown
, I think we could benefit from the same here too. :)
Would you like to update this PR to pursue that?
await scrollGesture.up(); | ||
await tester.pump(); | ||
|
||
// Scroll doesn't move because the scrollbar doesn't handle gestures |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of allowing a misconfiguration between user-provided scroll controller and primary scroll controller, you can disable gestures with Scrollbar.interactive
. Making this do nothing may be confusing to users that otherwise would not understand why their scrollbar does not work.
@Piinks Thanks! Yes, I've ended up figuring out the cause. |
It was only until now that we included a crash reporting tool that we found those errors on production code. We've never found those while developing all this time. |
Visually, no it does not need a This is because we wanted to support multiple options for the
We do have a new feature that recently landed that allows you to add a Scrollbar as part of the
I do not think we want the early returns as it breaks the scrollbar without any explanation to the user.
I don't think this is related to isAlwaysShown, the PR I linked was meant to illustrate the type of error messaging |
@Piinks Oh, lots of new things coming to the scrollbar. Thanks for the info!
I'm looking into the error message improvement. How should we go about it? Currently the void handleThumbPressStart(Offset localPosition) {
final Axis? direction = getScrollbarDirection();
if (direction == null) {
return;
}
.... How do you think it would be better?
void handleThumbPressStart(Offset localPosition) {
final Axis? direction = getScrollbarDirection();
if (direction == null) {
// Call an assertion that throws the explanation like on the isAlwaysShown situation.
assertion();
return;
}
....
void handleThumbPressStart(Offset localPosition) {
// Throws the FlutterError internally
_checkForValidScrollPosition();
....
We could also change the API of getScrollbarDirection to not return null and call the check at the start as in 3) |
Something along the lines of 3 sounds good to me! Thank you for continuing to work on this and making the error messaging better! :) You could probably take most of the error from the |
@Piinks I've updated the PR and tests with the suggestions |
I've been thinking a bit more about this. Do you think we should have this assertion check when building the scrollbar for the first time?. In the same place as the
Otherwise, even if the error is more explicit now, it will only be shown when using the thumb or the track gestures + an incorrect injection of the controller. That has low chances of being noticed while developing. I think it would be better if users notice that they have something wrong in the scrollbar as early as possible. I've been using them incorrectly for over 2 years without noticing 😅 What do you think? |
I think that sounds like a great idea! If RawScrollbar.interactive is true, we could definitely surface that error sooner for gestures. You can have a scrollbar that is not interactive, but isAlwaysShown, so I think those would be two separate checks still. |
@Piinks Any update on this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @davidmartos96, apologies for the delay. I've been away for a bit. Can you add tests for the changes to the Cupertino widgets you have made here?
child: SingleChildScrollView( | ||
controller: controller, | ||
child: const SizedBox(width: 4000.0, height: 4000.0), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NICE
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No problem! What kind of test are you thinking of? Actually, I had to add the small extra code so that the current Cupertino tests pass. Maybe the current tests are enough?
I've included 2 tests that check that the controllers used internally are different because the primary one can't be attached to multiple scroll views at the same time. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Thank you for the contribution!
@Piinks Thanks to you! |
It looks like this PR introduced issues for flutter_gallery. For example, just running flutter_gallery ends up triggering asserts introduced by this PR now. |
I thould add that this seems to only happen on macOS desktop. |
@dnfield I've just tested the flutter_gallery on Linux and I also get the asserts. But I'd say it is a legitimate warning. If you disable the asserts you will notice that scrolling with a mouse press in the main scroll in the home screen doesn't work.
The fact that it is such an "invisible" bug was the main reason I tried to improve the situation with this PR by warning about it. Everything works normally but it fails when interacting with the scrollbar either with the thumb on mobile or with the mouse on desktop. As an extra note, I think it will be great to further improve the message by including the location of the failing widget. In the case of the Flutter Gallery just in the home screen there are 5-6 active scrolls, so knowing which one is failing is very precious information. |
@davidmartos96 can you confirm if this means trying to drag the scrollable with the mouse pointer? That is most likely disabled by ScrollBehavior.dragDevices on desktop if that is the case. I'm filing a bug for this so we can discuss further, will link back in a sec |
Also just connecting discussions - this came up here: https://discord.com/channels/608014603317936148/608021234516754444/854798350246215751 |
Let's follow-up here: flutter/gallery#523 |
Yes, it is by dragging with the mouse pointer. Running the app on profile (no asserts) on Linux desktop will throw when dragging the thumb. |
Could you please also check out this related issue #84735 |
Followed up there. |
Fixes #81277
This PR includes a check for scrollbar track taps when there is no scroll position available.
The check is the same as in the other scrollbar gestures:
flutter/packages/flutter/lib/src/widgets/scrollbar.dart
Line 1103 in 519c8e0
flutter/packages/flutter/lib/src/widgets/scrollbar.dart
Line 1125 in 519c8e0
flutter/packages/flutter/lib/src/widgets/scrollbar.dart
Line 1145 in 519c8e0
I wasn't able to find similar tests for error situations with the other scrollbar gestures. This one in particular happens when we pass a scroll controller to a scroll view but not to the scrollbar. Edit: Added some tests
Kindly pinging @Piinks because these checks were added in the previous refactor of the scrollbar.dart file.
Pre-launch Checklist
///
).If you need help, consider asking for advice on the #hackers-new channel on Discord.