-
Notifications
You must be signed in to change notification settings - Fork 29.7k
[widgets/raw_menu_anchor.dart] Switch from MediaQuery.sizeOf to didChangeMetrics for RawMenuAnchor #168623
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
|
@LongCatIsLooong I tagged you for review since this relates with OverlayPortal. |
| _overlayController.hide(); | ||
| }, debugLabel: 'MenuAnchor.hide'); | ||
| } | ||
| _overlayController.hide(); |
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.
Is close public? If so then it should be added to the API docs that it can't be called during build.
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.
MenuController.close() redirects to close(), so I'll add documentation to MenuController.close()
Considering this is a breaking change, I'm curious whether you think we should close this PR. While all tests passed, this could lead to annoying bugs for end users.
That said, open() currently throws an error during builds since OverlayController.show() is called. I realize now that I overlooked the SchedulerPhase check in the open() method when copying over from MenuAnchor. Considering OverlayController.show() will throw, checking the SchedulerPhase in open() doesn't appear to have any effect.
If you do think we should close this PR, do you think we should add similar phase checking/post-frame callback logic to the open() method?
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.
All the CI checks are passing so by definition this doesn't seem to be a breaking change?
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.
You're right:
A breaking change is one that breaks the tests in the flutter/tests repo, and those need a migration guide.
I'm misusing the term to mean a change that may reasonably break another developer's code. I believe calling close() during didChangeDependencies should have worked before, but implementing this change would break this behavior.
|
|
||
| @override | ||
| void didChangeMetrics() { | ||
| super.didChangeMetrics(); |
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.
Hypothetically you can reparent a MenuAnchor from one window to another right? I don't think you'll get notified (or not in the .idle phase) if that happens? Or the menu is not supposed to hide if that happens?
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.
I think this is my bigger concern (even if multi-window isn't fully implemented). Should the menu close if I move the menu anchor from one window to another using a global key?
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.
I was trying to write a test to simulate this behavior, but I couldn't figure out if there was a simple way to do so using standard flutter testing libraries. Let me know if you know of a good example widget I can model my tests off of...
In my opinion, it seems more intuitive to leave the menu open if the window changes. This is based on the fact that the RawMenuAnchor's state lives within RawMenuAnchor (rather than on an external variable or on MenuController). AFAIK, the only reason why RawMenuAnchor closes on scroll and on resize is because the overlay isn't rebuilt when the menu anchor is repositioned, so the menu appears fixed on the screen when its anchor changes position. Assuming reparenting using a GlobalKey would lead to the overlay rebuilding with a new anchor position, I think the overlay should reposition upon entering a new window? I could be completely wrong.
Also, if #168785 is addressed, there would no longer be a need to automatically close the menu, since the menu would be expected to always follow its anchor.
To your point, as far as I know, the only way to observe the current view would be to call View.of(context), which would not be notified in the idle phase. If we did want to close the menu on reparenting, I believe I'd have to introduce a different way of listening to view changes.
| void didChangeMetrics() { | ||
| super.didChangeMetrics(); | ||
| // Close the root menu if the screen size changes | ||
| if (isRoot) { |
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.
So this looks a bit different from the original implementation, now the menu will also dismiss on view inset change, if I recall correctly. Is that intended that things like keyboard popping up also dismisses all menus? What if there's a text field in one of the menu items?
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.
You're right, and this is not the intended behavior. The didChangeMetrics docs made it sound as if didChangeMetrics was analogous to MediaQuery.sizeOf(context), but this is not the case. I'll update this code to diff the logical view size.
|
@LongCatIsLooong Sorry for the delay. We just bought a house, so I haven't had much time to contribute. |
Congrats on your new home @davidhicks980! 🎊 |
|
Hey @davidhicks980 no pressure, just circling back on this one in triage. Would you like to keep this open to return to? |
|
Sorry, @Piinks! I'm moved in but I've been prioritizing older issues, particularly the CupertinoMenuAnchor implementation. If possible, let's keep this one open for now. |
|
@davidhicks980 Checking in again since it's been a few months. Are you still planning to come back to this? |
|
@justinmc I'll go ahead and close it. At some point, we may have a declarative OverlayPortal, which would fix this issue. Also, this PR precludes the use of using MediaQueries to close the menu in testing. |
Currently, we close RawMenuAnchor and derivatives during the persistent callback phase (didChangeDependencies).
As a result, there are phase checks in several parts of RawMenuAnchor:
I was under the impression that these phase checks were used for more than just closing on MediaQuery changes, but, as far as I can tell, that is their sole purpose:
#130534 (comment)
#136769
So, this PR closes the menu during didChangeMetrics, since didChangeMetrics is called during the idle phase.
The downside to didChangeMetrics is that it will not be called when MediaQuery.sizeOf(context) updates without the screen changing size. This may occur if a user inserts a different size into an ancestor MediaQuery. If this is untenable, we can close this PR.
List which issues are fixed by this PR. You must list at least one issue. An issue is not required if the PR fixes something trivial like a typo.
Fixes #168539
If you had to change anything in the flutter/tests repo, include a link to the migration guide as per the breaking change policy.
The only change that was made is a test simplification. The new menu passes all old tests.
Old:

New:

As discussed, even if all original tests pass, this is a breaking change.
Pre-launch Checklist
///).If you need help, consider asking for advice on the #hackers-new channel on Discord.