Repository navigation
[stable] [Widget Preview] Isolate PageStorage scope in widget preview group expansion tile - #192255
Conversation
…pansion tile (flutter#191378) ## Description When a preview group is collapsed and re-expanded in the Widget Previewer, descendant scrollables (which search ancestor elements for a `PageStorageKey` when restoring scroll offset) inherit the `PageStorageKey` from the `ExpansionTile`. They then attempt to read the `ExpansionTile`'s boolean expansion state as a double, throwing a `TypeError: true: type 'bool' is not a subtype of type 'double?'`. This PR wraps the `ExpansionTile` children in a `PageStorage` widget with a new `PageStorageBucket`, preventing descendant scrollable widgets from inheriting the `ExpansionTile`'s `PageStorageKey`. ## Related Issues Fixes flutter#191242 ## Tests - Tested in widget preview scaffold template.
|
@bkonyi please fill out the PR description above, afterwards the release team will review this request. |
|
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. |
There was a problem hiding this comment.
Code Review
This pull request converts WidgetPreviewGroupWidget from a StatelessWidget to a StatefulWidget and wraps the children of ExpansionTile in a PageStorage widget to prevent a TypeError in descendant scrollables. The review feedback suggests recreating the PageStorageBucket in didUpdateWidget when the group changes to prevent scroll state bleeding between different groups.
| } | ||
|
|
||
| class _WidgetPreviewGroupWidgetState extends State<WidgetPreviewGroupWidget> { | ||
| final _bucket = PageStorageBucket(); |
There was a problem hiding this comment.
When WidgetPreviewGroupWidget is rebuilt with a different group, the state instance may be reused by the framework. Since _bucket is currently a final field initialized once, the same PageStorageBucket instance will be shared across different groups. This can cause descendant scrollables in the new group to incorrectly restore scroll offsets from the previous group if they share similar keys or structures.
To prevent scroll state bleeding between different groups, make _bucket non-final and recreate it in didUpdateWidget if the group changes.
PageStorageBucket _bucket = PageStorageBucket();
@override
void didUpdateWidget(WidgetPreviewGroupWidget oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.group != oldWidget.group) {
_bucket = PageStorageBucket();
}
}| } | ||
|
|
||
| class _WidgetPreviewGroupWidgetState extends State<WidgetPreviewGroupWidget> { | ||
| final _bucket = PageStorageBucket(); |
There was a problem hiding this comment.
When WidgetPreviewGroupWidget is rebuilt with a different group, the state instance may be reused by the framework. Since _bucket is currently a final field initialized once, the same PageStorageBucket instance will be shared across different groups. This can cause descendant scrollables in the new group to incorrectly restore scroll offsets from the previous group if they share similar keys or structures.
To prevent scroll state bleeding between different groups, make _bucket non-final and recreate it in didUpdateWidget if the group changes.
PageStorageBucket _bucket = PageStorageBucket();
@override
void didUpdateWidget(WidgetPreviewGroupWidget oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.group != oldWidget.group) {
_bucket = PageStorageBucket();
}
}
|
@bkonyi, Can you please ass a secondary reviewer on this PR? |
|
@bkonyi this needs a domain expert reviewer. I checked the release engineer stuff after a review from you or someone else add autosubmit. |
64d4f62
into
flutter:flutter-3.47-candidate.0
Adds the changelog section for 3.47.5, tracked by #192828. <details> <summary>Agent authored info</summary> Covers the cherry-picks that landed on `flutter-3.47-candidate.0` since the `3.47.4` tag. Each entry uses the **Changelog Description** exactly as authored in the corresponding cherry-pick PR. | Cherry-pick PR | Landed | Changelog reference | | --- | --- | --- | | [#192810](#192810) [CP-stable] On iOS 27+ devices, manually process lldb stops | `d3c78d8b3` | [flutter/190307](#190307) | | [#192255](#192255) [stable] [Widget Preview] Isolate PageStorage scope in widget preview group expansion tile | `64d4f6282` | [flutter/191242](#191242) | | [#192295](#192295) [stable] [flutter_tools] Roll package:dds to 5.4.0 | `0a12baff2` | [flutter/189507](#189507) | Entries are ordered by the order the cherry-picks landed on the branch, matching the convention used for 3.47.4. ### Intentionally excluded Two commits also landed in this range but are routine release infrastructure, not user-facing cherry-picks: - [#192875](#192875) Update Flutter DEPS to Dart `b530c21f7de367b94fb04787bfed9d8e989d75e8` - [#192894](#192894) Sync `engine.version` to `af7e796e161ae0bb1ff0758c71a7105418bd9ded` This matches every prior hotfix in this series: the 3.47.1, 3.47.2, and 3.47.3 ranges each contained a Dart DEPS roll and an `engine.version` sync, and none were listed as changelog bullets. ### Note for the release manager The `Issue Link` on [#192295](#192295) points at [#189507](#189507) ("Bump devtools_shared to 13.1.0", merged 2026-07-23), which does not appear to relate to the `package:dds` 5.4.0 roll that PR actually performs. The authored changelog text has been preserved verbatim rather than silently corrected. If that reference is wrong, the bullet should be repointed before this lands. ### Verification - All three entry links return HTTP 200. - The `3.47.5` tag link currently 404s because the release has not been tagged yet; it will resolve once "Push release with MPA" completes. This is expected, since the checklist places "Add changelog for stable release" before the release is pushed. </details> I have double checked with @bkonyi that there is no issue for the dds change because the issue when discovered was already fixed on master.
Adds the changelog section for 3.47.5, tracked by flutter#192828. <details> <summary>Agent authored info</summary> Covers the cherry-picks that landed on `flutter-3.47-candidate.0` since the `3.47.4` tag. Each entry uses the **Changelog Description** exactly as authored in the corresponding cherry-pick PR. | Cherry-pick PR | Landed | Changelog reference | | --- | --- | --- | | [flutter#192810](flutter#192810) [CP-stable] On iOS 27+ devices, manually process lldb stops | `d3c78d8b3` | [flutter/190307](flutter#190307) | | [flutter#192255](flutter#192255) [stable] [Widget Preview] Isolate PageStorage scope in widget preview group expansion tile | `64d4f6282` | [flutter/191242](flutter#191242) | | [flutter#192295](flutter#192295) [stable] [flutter_tools] Roll package:dds to 5.4.0 | `0a12baff2` | [flutter/189507](flutter#189507) | Entries are ordered by the order the cherry-picks landed on the branch, matching the convention used for 3.47.4. Two commits also landed in this range but are routine release infrastructure, not user-facing cherry-picks: - [flutter#192875](flutter#192875) Update Flutter DEPS to Dart `b530c21f7de367b94fb04787bfed9d8e989d75e8` - [flutter#192894](flutter#192894) Sync `engine.version` to `af7e796e161ae0bb1ff0758c71a7105418bd9ded` This matches every prior hotfix in this series: the 3.47.1, 3.47.2, and 3.47.3 ranges each contained a Dart DEPS roll and an `engine.version` sync, and none were listed as changelog bullets. The `Issue Link` on [flutter#192295](flutter#192295) points at [flutter#189507](flutter#189507) ("Bump devtools_shared to 13.1.0", merged 2026-07-23), which does not appear to relate to the `package:dds` 5.4.0 roll that PR actually performs. The authored changelog text has been preserved verbatim rather than silently corrected. If that reference is wrong, the bullet should be repointed before this lands. - All three entry links return HTTP 200. - The `3.47.5` tag link currently 404s because the release has not been tagged yet; it will resolve once "Push release with MPA" completes. This is expected, since the checklist places "Add changelog for stable release" before the release is pushed. </details> I have double checked with @bkonyi that there is no issue for the dds change because the issue when discovered was already fixed on master.
Adds the changelog section for 3.47.5, tracked by flutter#192828. <details> <summary>Agent authored info</summary> Covers the cherry-picks that landed on `flutter-3.47-candidate.0` since the `3.47.4` tag. Each entry uses the **Changelog Description** exactly as authored in the corresponding cherry-pick PR. | Cherry-pick PR | Landed | Changelog reference | | --- | --- | --- | | [flutter#192810](flutter#192810) [CP-stable] On iOS 27+ devices, manually process lldb stops | `d3c78d8b3` | [flutter/190307](flutter#190307) | | [flutter#192255](flutter#192255) [stable] [Widget Preview] Isolate PageStorage scope in widget preview group expansion tile | `64d4f6282` | [flutter/191242](flutter#191242) | | [flutter#192295](flutter#192295) [stable] [flutter_tools] Roll package:dds to 5.4.0 | `0a12baff2` | [flutter/189507](flutter#189507) | Entries are ordered by the order the cherry-picks landed on the branch, matching the convention used for 3.47.4. Two commits also landed in this range but are routine release infrastructure, not user-facing cherry-picks: - [flutter#192875](flutter#192875) Update Flutter DEPS to Dart `b530c21f7de367b94fb04787bfed9d8e989d75e8` - [flutter#192894](flutter#192894) Sync `engine.version` to `af7e796e161ae0bb1ff0758c71a7105418bd9ded` This matches every prior hotfix in this series: the 3.47.1, 3.47.2, and 3.47.3 ranges each contained a Dart DEPS roll and an `engine.version` sync, and none were listed as changelog bullets. The `Issue Link` on [flutter#192295](flutter#192295) points at [flutter#189507](flutter#189507) ("Bump devtools_shared to 13.1.0", merged 2026-07-23), which does not appear to relate to the `package:dds` 5.4.0 roll that PR actually performs. The authored changelog text has been preserved verbatim rather than silently corrected. If that reference is wrong, the bullet should be repointed before this lands. - All three entry links return HTTP 200. - The `3.47.5` tag link currently 404s because the release has not been tagged yet; it will resolve once "Push release with MPA" completes. This is expected, since the checklist places "Add changelog for stable release" before the release is pushed. </details> I have double checked with @bkonyi that there is no issue for the dds change because the issue when discovered was already fixed on master.
Adds the changelog section for 3.47.5, tracked by flutter#192828. <details> <summary>Agent authored info</summary> Covers the cherry-picks that landed on `flutter-3.47-candidate.0` since the `3.47.4` tag. Each entry uses the **Changelog Description** exactly as authored in the corresponding cherry-pick PR. | Cherry-pick PR | Landed | Changelog reference | | --- | --- | --- | | [flutter#192810](flutter#192810) [CP-stable] On iOS 27+ devices, manually process lldb stops | `d3c78d8b3` | [flutter/190307](flutter#190307) | | [flutter#192255](flutter#192255) [stable] [Widget Preview] Isolate PageStorage scope in widget preview group expansion tile | `64d4f6282` | [flutter/191242](flutter#191242) | | [flutter#192295](flutter#192295) [stable] [flutter_tools] Roll package:dds to 5.4.0 | `0a12baff2` | [flutter/189507](flutter#189507) | Entries are ordered by the order the cherry-picks landed on the branch, matching the convention used for 3.47.4. Two commits also landed in this range but are routine release infrastructure, not user-facing cherry-picks: - [flutter#192875](flutter#192875) Update Flutter DEPS to Dart `b530c21f7de367b94fb04787bfed9d8e989d75e8` - [flutter#192894](flutter#192894) Sync `engine.version` to `af7e796e161ae0bb1ff0758c71a7105418bd9ded` This matches every prior hotfix in this series: the 3.47.1, 3.47.2, and 3.47.3 ranges each contained a Dart DEPS roll and an `engine.version` sync, and none were listed as changelog bullets. The `Issue Link` on [flutter#192295](flutter#192295) points at [flutter#189507](flutter#189507) ("Bump devtools_shared to 13.1.0", merged 2026-07-23), which does not appear to relate to the `package:dds` 5.4.0 roll that PR actually performs. The authored changelog text has been preserved verbatim rather than silently corrected. If that reference is wrong, the bullet should be repointed before this lands. - All three entry links return HTTP 200. - The `3.47.5` tag link currently 404s because the release has not been tagged yet; it will resolve once "Push release with MPA" completes. This is expected, since the checklist places "Add changelog for stable release" before the release is pushed. </details> I have double checked with @bkonyi that there is no issue for the dds change because the issue when discovered was already fixed on master.
This pull request is created by automatic cherry pick workflow
Please fill in the form below, and a flutter domain expert will evaluate this cherry pick request.
Issue Link:
#191242
Impact Description:
In the Widget Previewer, collapsing and re-expanding a preview group causes descendant scrollables to inherit the
PageStorageKeyfrom theExpansionTile. When the scrollables attempt to restore their scroll offset, they read theExpansionTile's boolean expansion state as a double, throwingTypeError: true: type 'bool' is not a subtype of type 'double?'. This crashes the preview and renders it unusable in the previewer UI.Changelog Description:
[flutter/191242] When re-expanding a preview group in the Widget Previewer, previews crash due to a type error in scroll restoration.
Workaround:
Avoid collapsing preview groups in the Widget Previewer, or do not use groups for previews containing scrollable widgets.
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:
flutter widget-preview start --no-pub --web-serverand open the URL in Chrome.Probepreview group, then re-expand it.TypeError: true: type 'bool' is not a subtype of type 'double?'is thrown.