-
Notifications
You must be signed in to change notification settings - Fork 28.2k
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
Exclude focus for child when it is hidden in Visibility if maintainInteractivity is not set, add possibility to set maintainInteractivity in IndexedStack #159133
base: master
Are you sure you want to change the base?
Conversation
Adding @chunhtai for context on this resolving the go_router issue |
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 @skimm3 welcome! Thanks for contributing. Is there a test that verifies this fixes the go_router issue you have linked as well?
return Visibility.maintain( | ||
visible: i == index, | ||
child: children[i], | ||
return ExcludeFocus( |
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.
This feels something should be added to Visibility widget.
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.
Also it seems it should not use Visibility.maintain since the maintain by default allows interactivity and semantics and animation unecessarily it should use
Visibility(
visible: i == index,
maintainSize: true,
maintainState: true,
child: children[i]
)
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.
Thanks for the feedback! Fixed the issue in Visibility widget instead. The new solution makes Visibility ignore focus when child is hidden for all combinations of maintain-parameters. I'm a bit unsure if it should be ignored when maintainInteractivity
is true, what do you think?
Removed maintain interactivity and semantics from indexed stack and added a test. Could not remove maintainAnimation
since that is needed if maintainSize
is set.
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.
It should ignore when maintainInteractivity is true since focus is part of interaction
bc8c4fe
to
025bee5
Compare
Thanks! I have a test that verifies the bug and that passes with my fix. Not sure what to do with it since the bug will be fixed when the user is using a flutter version containing this fix and not depending on a go_router version. Here is the code for the test:
|
Hmm good question. @chunhtai do you think we should add this test to go_router after this lands to prevent regressions there? |
I think we can create a simple test with indexed stack to make sure it hides focus of child underneath since this is the root cause of the go_router issue |
bfc5c95
to
651d851
Compare
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, thanks for fixing the issue!!
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 too! 🎊 Thanks!
auto label is removed for flutter/flutter/159133, due to - The status or check suite Google testing has failed. Please fix the issues identified (or deflake) before re-applying this label. |
Currently taking a look at the google testing failures. |
This may be a breaking change if customers have been utilizing the focusability of children in the IndexedStack regardless of their visibility. An option to make this non-breaking would be to make the new behavior opt in through a flag on IndexedStack. |
@skimm3 Do you have plans to come back to this PR to address the feedback given above (i.e. making this non-breaking by making the new behavior opt-in via a flag)? |
651d851
to
49b0f60
Compare
Hey @Piinks & @goderbauer! Called the flag |
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.
Thank you for the update, and for your patience over the holidays. 🙏
@@ -4134,6 +4135,11 @@ class IndexedStack extends StatelessWidget { | |||
/// See [Stack.fit] for more information. | |||
final StackFit sizing; | |||
|
|||
/// If hidden [children] should be able to receive focus. |
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.
/// If hidden [children] should be able to receive focus. | |
/// Whether or not [children] in the stack that are not visible should be able to receive focus. |
return Visibility.maintain(visible: i == index, child: children[i]); | ||
return Visibility( | ||
visible: i == index, | ||
maintainInteractivity: maintainFocusability, |
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.
Maybe we can match with the same name for consistency? :)
maintainInteractivity: maintainFocusability, | |
maintainInteractivity: maintainInteractivity, |
@@ -245,7 +246,10 @@ class Visibility extends StatelessWidget { | |||
|
|||
@override | |||
Widget build(BuildContext context) { | |||
Widget result = child; | |||
Widget result = ExcludeFocus( | |||
excluding: !visible && !maintainInteractivity, |
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.
This makes me wonder if this PR should be split into two changes, since this changes the behavior of the Visibility widget.
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.
Can you share some context for why this change was added? Is there a separate problem with Visibility this is solving?
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.
Thanks for the great feedback, resolved the other comments.
Reason for adding the change to Visibility
:
In the first iteration of this PR I added the ExcludeFocus
widget to IndexedStack. That solved the original problem but I got feedback from chunhtai that the fix should probably be in Visibility
, since the root cause of the bug was that Visibility
did not handle focus correctly for hidden children. I then moved my implementation there to make the fix more general and not only cover IndexedStack
but other widgets that might have the same issue.
On splitting PR into two:
I could do that but the bug would only be solved after both PR lands, it seems easier to keep it in one. I'm also unsure how to practically split them. One way would be to file a new issue that describes the bug in Visibility
in which hidden children can receive focus if maintainInteractivity is false. After that issue is fixed I could go back to this and "only" add the flag in IndexedStack
.
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.
Yeah I see what you mean. My hesitation is that this change to visibility does not just have to do with maintainInteractivity, visible is also part of it. We haven't seen any regressions in the tests though, so I think it is ok.
49b0f60
to
73432bb
Compare
@@ -4134,6 +4135,11 @@ class IndexedStack extends StatelessWidget { | |||
/// See [Stack.fit] for more information. | |||
final StackFit sizing; | |||
|
|||
/// Wether or not [children] in the stack that are not visible should be able to receive focus. |
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.
/// Wether or not [children] in the stack that are not visible should be able to receive focus. | |
/// Whether or not [children] in the stack that are not visible should be able to receive focus. |
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.
If that was my typo from an earlier review, my bad. 😅
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.
it has been a while since my last review. but may I know what's the use case that people would want the interactivity on the hidden children?
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.
The reason for adding it was to not make a breaking change since that is the current behavior. I would argue that since it is a bug and not expected behavior it is fine to not be backwards compatible in this case but that's for you to decide since this is my first contribution and I'm not really sure on how you go about these things.
Removing the flag would fix the bug in go_router directly instead of having to wait for go_router to use the flutter version with this fix and then add the flag. But I also understand that breaking changes are not wanted :)
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.
ah ok, I saw the previous comment as well, I think this is probably due to a lot of internal test failures. yeah making this opt in for now sgtm, can you add a todo at this line explain we should remove this at some day and this flag is for backward compatibility
@@ -245,7 +246,10 @@ class Visibility extends StatelessWidget { | |||
|
|||
@override | |||
Widget build(BuildContext context) { | |||
Widget result = child; | |||
Widget result = ExcludeFocus( | |||
excluding: !visible && !maintainInteractivity, |
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.
Yeah I see what you mean. My hesitation is that this change to visibility does not just have to do with maintainInteractivity, visible is also part of it. We haven't seen any regressions in the tests though, so I think it is ok.
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.
Sorry if my comments have been addressed before, it has been a long time
@@ -4134,6 +4135,11 @@ class IndexedStack extends StatelessWidget { | |||
/// See [Stack.fit] for more information. | |||
final StackFit sizing; | |||
|
|||
/// Wether or not [children] in the stack that are not visible should be able to receive focus. |
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.
it has been a while since my last review. but may I know what's the use case that people would want the interactivity on the hidden children?
maintainInteractivity: maintainInteractivity, | ||
maintainSize: true, | ||
maintainState: true, | ||
maintainAnimation: true, |
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.
This is abit surprising, why do we want to keep the animation for if they are not visible?
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.
It's due to an assertion in Visibility
that requires maintainAnimation to be set if maintainSize or maintainState is true.
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.
thanks for explanation sgtm
6801038
to
e64e210
Compare
6c7ace8
to
1776a01
Compare
Rebasing here to start a new run for Google Testing |
…emantics in indexedstack, add tests
1776a01
to
24bacae
Compare
@@ -245,7 +246,7 @@ class Visibility extends StatelessWidget { | |||
|
|||
@override | |||
Widget build(BuildContext context) { | |||
Widget result = child; | |||
Widget result = ExcludeFocus(excluding: !visible && !maintainInteractivity, child: child); |
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.
It looks like this change is breaking, I have looked into the google testing failure and it does break expected existing behavior there. Does this need to factor in whether or not it is visible?
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.
If it does not factor in visible it will exclude focus even if the child is visible which I do not think is wanted.
To not break any existing behavior we could add a new flag, maintainFocusability
, that decides wether we should exclude focus for hidden children. Another solution is to revert my changes to Visibility and add ExcludeFocus in IndexedStack instead. That however is more of a band aid fix since the problem was that hidden children in Visibility can receive focus. I also remember @chunhtai suggested against the the second option.
Btw, thanks a lot for being patient and helping me out!
This pull request executed golden file tests, but it has not been updated in a while (20+ days). Test results from Gold expire after as many days, so this pull request will need to be updated with a fresh commit in order to get results from Gold. For more guidance, visit Writing a golden file test for Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. |
Fixes: #114213 and is a prerequisite for fixing: #148405
Pre-launch Checklist
///
).If you need help, consider asking for advice on the #hackers-new channel on Discord.