[CP-beta] fixes a status bar tap crash#182688
Conversation
|
This pull request was opened from and to a release candidate branch. This should only be done as part of the official Flutter release process. If you are attempting to make a regular contribution to the Flutter project, please close this PR and follow the instructions at Tree Hygiene for detailed instructions on contributing to Flutter. Reviewers: Use caution before merging pull requests to release branches. Ensure the proper procedure has been followed. |
|
An existing Git SHA, To re-trigger presubmits after closing or re-opeing a PR, or pushing a HEAD commit (i.e. with |
There was a problem hiding this comment.
Code Review
The pull request addresses a crash on iOS when tapping the status bar to scroll to top by ensuring that only the foreground Scaffold handles the event. This is a valuable fix for UX and stability. However, the implementation in Material Scaffold is currently broken because it references a new enum value _ScaffoldSlot.statusBar that has not been defined, and the _ScaffoldLayout delegate has not been updated to handle this new child. This will lead to compilation errors and runtime assertion failures. Additionally, the changes in flutter_tools to convert web-define errors into warnings have some minor issues in the warning message logic and terminology that should be addressed for clarity.
I am having trouble creating individual review comments. Click here to see my feedback.
packages/flutter/lib/src/material/scaffold.dart (3200)
The code references _ScaffoldSlot.statusBar, but this value is missing from the _ScaffoldSlot enum definition (lines 64-76). This will result in a compilation error. Please ensure the enum is updated to include the statusBar slot.
packages/flutter/lib/src/material/scaffold.dart (3198-3205)
The statusBar widget is added as a child to the CustomMultiChildLayout here, but the _ScaffoldLayout delegate (lines 1026-1290) does not contain logic to layout or position this child. In Flutter's CustomMultiChildLayout, every child must be explicitly laid out using layoutChild and positioned using positionChild within the delegate's performLayout method. Failing to do so will cause an assertion failure in debug mode and the widget will not be rendered correctly.
packages/flutter_tools/lib/src/web_template.dart (204)
The warning message should be pluralized when multiple variables are missing. Additionally, the term 'skipped' is slightly misleading because the implementation actually preserves the original placeholders (e.g., {{VAR}}) in the output rather than removing them. Clarifying this behavior in the message would improve developer clarity.
'${missingVariables.length == 1 ? "This variable" : "These variables"} will be skipped (the placeholder will remain in the output).\n',
…9643)" (flutter#182223) This reverts commit f4c83de. See b/482565401. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
…on status bar tap (flutter#182391) Reland flutter#179643, with [changes](flutter@3f7d345) to fix flutter#182233. The reland closes flutter#177992, closes flutter#175606. The crash happened because `Scaffold.handleStatusBar` (and subsequently `ScrollController.animateTo`) is called on a scaffold that [has never been laid out](flutter#182233 (comment)). Before flutter#179643, the iOS embedder sends a fake touch down pointer event at `(0, 0)` to the framework, followed by a touch up pointer event at the same location. That ensured only the foreground `Scaffold` could claim the tap gesture and handle the status bar tap. The fix tries to restore the previous behavior (where the iOS behavior sends fake touches instead of platform messages) by performing a hit-test at `(0, 0)` before trying to scroll the primary controller of a `Scaffold` to the top, this should make sure that only the foreground scaffold (in theory it's still possible for more than one Scaffold to receive the hittest and handle the status bar tap event, but the foreground scaffold should block the hit-test on background ones instead of relying on gesture disambiguation). - [ ] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [ ] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [ ] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [ ] I signed the [CLA]. - [ ] I listed at least one issue that this PR fixes in the description above. - [ ] I updated/added relevant documentation (doc comments with `///`). - [ ] I added new tests to check the change I am making, or this PR is [test-exempt]. - [ ] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [ ] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
|
Had to cherry pick the revert commit since it doesn't exist on beta. Ready for review now. |
There was a problem hiding this comment.
Code Review
The pull request addresses a crash on iOS when tapping the status bar to scroll to top, specifically when a primary scroll view hasn't been laid out. The fix introduces a hit-test check at Offset.zero to ensure only the foreground hit-testable scaffold handles the tap. This also improves UX by preventing multiple scroll views from scrolling simultaneously. The addition of simulateStatusBarTap in the test framework is a valuable improvement for testing this behavior. I've noted a few minor issues regarding comment typos and consistency in assert messages.
| static bool hitTestableAtOrigin(GlobalKey key) { | ||
| final context = key.currentContext as Element?; | ||
| if (context == null) { | ||
| assert(false, 'BuildContext associated with $key is not mounted.'); |
There was a problem hiding this comment.
For consistency with the implementation in material/scaffold.dart, consider using a more descriptive assert message here to help debug tests on non-iOS platforms.
assert(
false,
'BuildContext associated with $key is not mounted. '
'If you see this in a test, this is likely because the test was trying '
'to simulate status bar tap on a non-iOS platform',
);References
- Error messages should be useful: Every error message is an opportunity to make someone love our product. (link)
There was a problem hiding this comment.
Release engineer approval.
This still needs domain expertise approval so I added @vashworth. You can add autosubmit after your review.
|
The changes are all on the framework side, so reassigning to @chunhtai for review |
642297e
into
flutter:flutter-3.42-candidate.0
This pull request is manually created because there were merge conflicts.
Click here for the conflicts
Issue Link:
What is the link to the issue this cherry-pick is addressing?
#182233
The bug was introduced in #179643 which was cherry picked to 3.41 beta (so the crash should exist on both current beta and stable).
Impact Description:
On iOS, the app may crash when the user taps on the status bar to scroll to top, when the app has a primary scroll view that has never been laid out (for example, in a route that has been obstructed by other routes since its creation).
Changelog Description:
Additionally this patch only dispatches the "scroll to top" command to the topmost Scaffold which is generally better UX for most apps (this doesn't have to be in the changlog)
Workaround:
No known easy workarounds.
Risk:
What is the risk level of this cherry-pick?
Test Coverage:
Are you confident that your fix is well-tested by automated tests?
Validation Steps:
What are the steps to validate that this fix works?
I've manually tested the fix on iOS/iPadOS simulators. There are also unit tests.