Skip to content

Update TickerMode.getValuesNotifier to handle initialization during State.dispose - #185248

Merged
auto-submit[bot] merged 4 commits into
flutter:masterfrom
nate-thegrate:late-animation
Apr 29, 2026
Merged

auto-submit[bot] merged 4 commits into
flutter:masterfrom
nate-thegrate:late-animation

Conversation

@nate-thegrate

@nate-thegrate nate-thegrate commented Apr 18, 2026 •

Copy link
Copy Markdown
Contributor

Currently, TickerMode.getValuesNotifier assumes that getInheritedWidgetOfExactType is safe to call, but there's an edge case where a widget defines an animation controller field and then is disposed of before that field is referenced elsewhere.

This PR updates the logic in getValuesNotifier() to handle that situation instead of throwing an error.

related to #153644

@github-actions github-actions Bot added the framework flutter/packages/flutter repository. See also f: labels. label Apr 18, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates TickerMode.getValuesNotifier to return a fallback value when the context is unmounted, preventing assertion errors that occur when late final animation controllers are disposed. It also adds regression tests for SingleTickerProviderStateMixin and TickerProviderStateMixin. The review feedback suggests removing the kDebugMode check to simplify the logic and ensure consistent behavior across all build modes.

// The getInheritedWidgetOfExactType() method throws an assertion error if called during
// State.dispose(), which becomes a problem when an animation controller is set as a
// late final class member and isn't referenced until then.
if (kDebugMode && !context.mounted) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The kDebugMode check is not strictly necessary here. If context.mounted is false, the element is defunct and getInheritedWidgetOfExactType would return null in release mode anyway (after a more expensive lookup). Removing kDebugMode simplifies the logic and provides a consistent, slightly more efficient path in all modes when the context is unmounted. This also aligns with the general practice of using context.mounted to guard against using a defunct context.

    if (!context.mounted) {
References
  1. Optimize for readability and avoid unnecessary complexity. (link)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SGTM :)

const fallback = _ConstantTickerModeDataListenable(TickerModeData.fallback);

// The getInheritedWidgetOfExactType() method throws an assertion error if called during
// State.dispose(), which becomes a problem when an animation controller is set as a

@navaronbracke navaronbracke Apr 20, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is technically not tied to animation controller, but the consumer of the VSync? (the class that mixes in the ticker provider)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When getValuesNotifier is called during State.dispose, I guess you could say the call is tied to both the animation controller and the State subclass that mixes in the ticker provider.

When the animation controller object is being referenced for the first time, the AnimationController constructor is called, which then calls the ticker provider's createTicker method, and inside that method is where TickerMode.getValuesNotifier is eventually called.

Please let me know if I misunderstood your question!

@victorsanni victorsanni left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would normally think we should throw the error anyways. But the fact that getValuesNotifier already has a fallback mechanism makes me think this PR is 👍

// The getInheritedWidgetOfExactType() method throws an assertion error if called during
// State.dispose(), which becomes a problem when an animation controller is set as a
// late final class member and isn't referenced until then.
if (!context.mounted) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

context.getInheritedWidgetOfExactType throws if the current lifecycle state is not _ElementLifecycle.active. Is this == context.mounted?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good question!

If we land this change, hypothetically TickerMode.getValuesNotifier could still throw an error if a late animation controller is referenced for the first time while an element is in the middle of GlobalKey re-parenting.

But realistically, I don't think this a cause for concern.

@victorsanni victorsanni added the CICD Run CI/CD label Apr 24, 2026

@justinmc justinmc left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍 . Is this the only thing blocking #153644? I think I missed that issue when you first created it, but reading through it now, I'm cautiously excited about it. It really simplifies things in the examples you gave at least.

@nate-thegrate

Copy link
Copy Markdown
Contributor Author

Is this the only thing blocking #153644?

I think so! I believe we can do a really nice cleanup once this PR lands.
The point made in #153644 (comment) still stands though; we'd need to consider potential side effects of late initialization, for example:

late final controller = AnimationController(vsync: this)..forward();

The forward() call would probably need to be moved to initState to ensure that it's actually called when we expect it to be.

@justinmc justinmc added the autosubmit Merge PR when tree becomes green via auto submit App label Apr 29, 2026
@auto-submit
auto-submit Bot added this pull request to the merge queue Apr 29, 2026
Merged via the queue into flutter:master with commit 143c87d Apr 29, 2026
87 of 88 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Apr 29, 2026
auto-submit Bot pushed a commit to flutter/packages that referenced this pull request May 1, 2026
Roll Flutter from 81bc3d69535f to 707dbc0420a3 (85 revisions)

flutter/flutter@81bc3d6...707dbc0

2026-05-01 [email protected] Removing TODOs from the WebParagraph code and addressing technical debts. (flutter/flutter#185168)
2026-05-01 [email protected] Ensure that vulkan_interface.h gets included before vk_mem_alloc.h (flutter/flutter#185777)
2026-05-01 [email protected] [flutter_tools] Bump dwds dependency to v27.1.1 (flutter/flutter#185357)
2026-05-01 [email protected] Roll Dart SDK from 6d4a319cbdac to 9aa7097f2e3e (3 revisions) (flutter/flutter#185888)
2026-05-01 [email protected] Roll Skia from fa1dcb289709 to 7ac6d42f2fd0 (1 revision) (flutter/flutter#185887)
2026-05-01 [email protected] Roll Skia from 54cc00adde38 to fa1dcb289709 (3 revisions) (flutter/flutter#185880)
2026-05-01 [email protected] [iOS] Migrate to FlutterFMLTaskRunner(s) (flutter/flutter#185815)
2026-05-01 [email protected] Remove material imports from navigator_on_did_remove_page_test and scrollable_in_overlay_test (flutter/flutter#182546)
2026-05-01 [email protected] Roll Skia from 2e279266f06a to 54cc00adde38 (3 revisions) (flutter/flutter#185872)
2026-05-01 [email protected] dev: Remove unused parameters (flutter/flutter#185345)
2026-05-01 [email protected] Roll Fuchsia Linux SDK from HN5VYzftnf_B8T-n9... to VnzuUefDQR0UhQ1L1... (flutter/flutter#185870)
2026-05-01 [email protected] Use g_free when using glib memory allocation (flutter/flutter#185519)
2026-05-01 [email protected] Roll Dart SDK from d30df3428f2e to 6d4a319cbdac (2 revisions) (flutter/flutter#185862)
2026-05-01 [email protected] Remove trivial test utility cross-imports from material and cupertino… (flutter/flutter#184295)
2026-05-01 [email protected] Inline test callback painter in tab scaffold test (flutter/flutter#184851)
2026-05-01 [email protected] [a11y] Add support for high contrast themes in the a11y assessments app  (flutter/flutter#185801)
2026-05-01 [email protected] [a11y assessment app] Use default color for banner (flutter/flutter#185804)
2026-04-30 [email protected] Added name to AUTHORS (flutter/flutter#185586)
2026-04-30 [email protected] Remove semantics_tester import from raw_material_button_test.dart (flutter/flutter#184806)
2026-04-30 [email protected] Remove semantics_tester import from user_accounts_drawer_header_test.dart (flutter/flutter#184809)
2026-04-30 [email protected] Roll Skia from 7b88c5c281e5 to 2e279266f06a (5 revisions) (flutter/flutter#185854)
2026-04-30 [email protected] Handle symmetric rectangular and elliptical round super ellipses in the uber SDF renderer  (flutter/flutter#185695)
2026-04-30 [email protected] Match on process name before killing for SwiftPM (flutter/flutter#185774)
2026-04-30 [email protected] Sync CHANGELOG.md from stable (flutter/flutter#185838)
2026-04-30 [email protected] Roll Dart SDK from 25910e31a6d2 to d30df3428f2e (5 revisions) (flutter/flutter#185839)
2026-04-30 [email protected] Check cross imports test subfolders (flutter/flutter#185493)
2026-04-30 [email protected] test: inline TestCallbackPainter in cupertino/picker_test.dart (flutter/flutter#185398)
2026-04-30 [email protected] Update customer testing version (flutter/flutter#185830)
2026-04-30 [email protected] Adapt the Metal shader library output list for debug versus release mode (flutter/flutter#185798)
2026-04-30 [email protected] [Impeller] Port a recent Vulkan swapchain fence waiting fix to the AHB version of the swapchain (flutter/flutter#185763)
2026-04-30 [email protected] Roll Skia from 26a59aa71eff to 7b88c5c281e5 (1 revision) (flutter/flutter#185821)
2026-04-30 [email protected] Roll Skia from 6b4167b4e204 to 26a59aa71eff (4 revisions) (flutter/flutter#185808)
2026-04-30 [email protected] [a11y] Mark SemanticsNode dirty when customSemanticsActions change  (flutter/flutter#185707)
2026-04-30 [email protected] Roll Skia from 1bd2f1cc2746 to 6b4167b4e204 (8 revisions) (flutter/flutter#185799)
2026-04-30 [email protected] [iOS] Extract FlutterVSyncClient from vsync_waiter_ios (flutter/flutter#185737)
2026-04-30 [email protected] Roll Fuchsia Linux SDK from nnv8-SSam6yE8dw4z... to HN5VYzftnf_B8T-n9... (flutter/flutter#185782)
2026-04-29 [email protected] [iOS] Soften TaskRunner.postTask(delay:task:) delay check (flutter/flutter#185729)
2026-04-29 [email protected] Add reportErrors to ImageStreamListener (flutter/flutter#180327)
2026-04-29 [email protected] Roll Skia from f5c781c083c7 to 1bd2f1cc2746 (5 revisions) (flutter/flutter#185761)
2026-04-29 [email protected] Update merge semantics logic to merge sibling nodes (flutter/flutter#183745)
2026-04-29 [email protected] Roll Packages from ba80f8f to cde5b36 (12 revisions) (flutter/flutter#185748)
2026-04-29 [email protected] examples: Remove unused parameters (flutter/flutter#185346)
2026-04-29 [email protected] Update TickerMode.getValuesNotifier to handle initialization during State.dispose (flutter/flutter#185248)
2026-04-29 [email protected] Update triage links (flutter/flutter#185714)
2026-04-29 [email protected] Add support for high contrast and color inversion on Android (flutter/flutter#182263)
2026-04-29 [email protected] Roll Skia from 05251260fda6 to f5c781c083c7 (2 revisions) (flutter/flutter#185743)
...
creatorpiyush pushed a commit to creatorpiyush/packages that referenced this pull request Jun 10, 2026
…r#11630)

Roll Flutter from 81bc3d69535f to 707dbc0420a3 (85 revisions)

flutter/flutter@81bc3d6...707dbc0

2026-05-01 [email protected] Removing TODOs from the WebParagraph code and addressing technical debts. (flutter/flutter#185168)
2026-05-01 [email protected] Ensure that vulkan_interface.h gets included before vk_mem_alloc.h (flutter/flutter#185777)
2026-05-01 [email protected] [flutter_tools] Bump dwds dependency to v27.1.1 (flutter/flutter#185357)
2026-05-01 [email protected] Roll Dart SDK from 6d4a319cbdac to 9aa7097f2e3e (3 revisions) (flutter/flutter#185888)
2026-05-01 [email protected] Roll Skia from fa1dcb289709 to 7ac6d42f2fd0 (1 revision) (flutter/flutter#185887)
2026-05-01 [email protected] Roll Skia from 54cc00adde38 to fa1dcb289709 (3 revisions) (flutter/flutter#185880)
2026-05-01 [email protected] [iOS] Migrate to FlutterFMLTaskRunner(s) (flutter/flutter#185815)
2026-05-01 [email protected] Remove material imports from navigator_on_did_remove_page_test and scrollable_in_overlay_test (flutter/flutter#182546)
2026-05-01 [email protected] Roll Skia from 2e279266f06a to 54cc00adde38 (3 revisions) (flutter/flutter#185872)
2026-05-01 [email protected] dev: Remove unused parameters (flutter/flutter#185345)
2026-05-01 [email protected] Roll Fuchsia Linux SDK from HN5VYzftnf_B8T-n9... to VnzuUefDQR0UhQ1L1... (flutter/flutter#185870)
2026-05-01 [email protected] Use g_free when using glib memory allocation (flutter/flutter#185519)
2026-05-01 [email protected] Roll Dart SDK from d30df3428f2e to 6d4a319cbdac (2 revisions) (flutter/flutter#185862)
2026-05-01 [email protected] Remove trivial test utility cross-imports from material and cupertino… (flutter/flutter#184295)
2026-05-01 [email protected] Inline test callback painter in tab scaffold test (flutter/flutter#184851)
2026-05-01 [email protected] [a11y] Add support for high contrast themes in the a11y assessments app  (flutter/flutter#185801)
2026-05-01 [email protected] [a11y assessment app] Use default color for banner (flutter/flutter#185804)
2026-04-30 [email protected] Added name to AUTHORS (flutter/flutter#185586)
2026-04-30 [email protected] Remove semantics_tester import from raw_material_button_test.dart (flutter/flutter#184806)
2026-04-30 [email protected] Remove semantics_tester import from user_accounts_drawer_header_test.dart (flutter/flutter#184809)
2026-04-30 [email protected] Roll Skia from 7b88c5c281e5 to 2e279266f06a (5 revisions) (flutter/flutter#185854)
2026-04-30 [email protected] Handle symmetric rectangular and elliptical round super ellipses in the uber SDF renderer  (flutter/flutter#185695)
2026-04-30 [email protected] Match on process name before killing for SwiftPM (flutter/flutter#185774)
2026-04-30 [email protected] Sync CHANGELOG.md from stable (flutter/flutter#185838)
2026-04-30 [email protected] Roll Dart SDK from 25910e31a6d2 to d30df3428f2e (5 revisions) (flutter/flutter#185839)
2026-04-30 [email protected] Check cross imports test subfolders (flutter/flutter#185493)
2026-04-30 [email protected] test: inline TestCallbackPainter in cupertino/picker_test.dart (flutter/flutter#185398)
2026-04-30 [email protected] Update customer testing version (flutter/flutter#185830)
2026-04-30 [email protected] Adapt the Metal shader library output list for debug versus release mode (flutter/flutter#185798)
2026-04-30 [email protected] [Impeller] Port a recent Vulkan swapchain fence waiting fix to the AHB version of the swapchain (flutter/flutter#185763)
2026-04-30 [email protected] Roll Skia from 26a59aa71eff to 7b88c5c281e5 (1 revision) (flutter/flutter#185821)
2026-04-30 [email protected] Roll Skia from 6b4167b4e204 to 26a59aa71eff (4 revisions) (flutter/flutter#185808)
2026-04-30 [email protected] [a11y] Mark SemanticsNode dirty when customSemanticsActions change  (flutter/flutter#185707)
2026-04-30 [email protected] Roll Skia from 1bd2f1cc2746 to 6b4167b4e204 (8 revisions) (flutter/flutter#185799)
2026-04-30 [email protected] [iOS] Extract FlutterVSyncClient from vsync_waiter_ios (flutter/flutter#185737)
2026-04-30 [email protected] Roll Fuchsia Linux SDK from nnv8-SSam6yE8dw4z... to HN5VYzftnf_B8T-n9... (flutter/flutter#185782)
2026-04-29 [email protected] [iOS] Soften TaskRunner.postTask(delay:task:) delay check (flutter/flutter#185729)
2026-04-29 [email protected] Add reportErrors to ImageStreamListener (flutter/flutter#180327)
2026-04-29 [email protected] Roll Skia from f5c781c083c7 to 1bd2f1cc2746 (5 revisions) (flutter/flutter#185761)
2026-04-29 [email protected] Update merge semantics logic to merge sibling nodes (flutter/flutter#183745)
2026-04-29 [email protected] Roll Packages from ba80f8f to cde5b36 (12 revisions) (flutter/flutter#185748)
2026-04-29 [email protected] examples: Remove unused parameters (flutter/flutter#185346)
2026-04-29 [email protected] Update TickerMode.getValuesNotifier to handle initialization during State.dispose (flutter/flutter#185248)
2026-04-29 [email protected] Update triage links (flutter/flutter#185714)
2026-04-29 [email protected] Add support for high contrast and color inversion on Android (flutter/flutter#182263)
2026-04-29 [email protected] Roll Skia from 05251260fda6 to f5c781c083c7 (2 revisions) (flutter/flutter#185743)
...
@nate-thegrate
nate-thegrate deleted the late-animation branch June 12, 2026 21:47
PlugFox added a commit to PlugFox/g1455 that referenced this pull request Oct 10, 2026
* g1455 0.1.5: a backdrop that is declared instead of captured, a floor of 3.47.0, and the common errors

GlassBackdrop declares what a subtree's glass samples — a colour, a
gradient, an image, a texture the application owns, or any
GlassProxyPainter — so a static wallpaper or a solid fill is never
captured. It is scoped: the innermost declaration wins and
GlassBackdrop.live hands a part of the tree back to the capture, so a
lockscreen's cards read the wallpaper while the feed under its bar is
captured as before. The declared texture is rendered once per finish
and size at the divisor the pipeline would pick, with the residual blur
in quadrature, and the pixels agree with the captured twin to 2 code
values (4 for regularDark over a gradient); a declaration that lies
differs by more than 20, and a shifted sample is the negative control.

What turned out wrong on the way: a declared surface never repainted
when its shader program arrived, because only capture readers listened
to the publish, so it drew without optics; and materialize re-rendered
the texture every frame of its animation (60 textures for 12 steps)
until the sigma was quantized to a quarter.

The floor is Flutter 3.47.0 / Dart 3.13.0: ^3.13.1 had shut out 3.47.0
for nothing. 3.44 fails the modal tests (a late controller created from
dispose, flutter/flutter#185248) and 3.41 does not compile; between
3.44.9 and 3.47.0 there are only pre-releases. CI's matrix floor is
3.47.0 and formats only there.

README, the site and the skill gain a section on misuse and common
errors, and a page for the declared backdrop. Tests cover 98.95% of
lib/, up from 89.64%; three defects they found are left as skipped
tests with the reason: OpacityLayer alpha is not folded into the
filter, a dismissible sheet barely follows the finger, and
dropMaskFiltered documents more than it checks.

* GlassStepper, GlassPageControl, GlassSearchBar and GlassBadge

Four controls iOS 26 has and the package did not. The stepper and the
page control are one glass capsule each, and a press, a hold or a page
turn takes no capture and repaints no backdrop; the controls for that
are a repainted backdrop, which takes one. The search bar is the search
field with a clear button inside the glass and a Cancel beside it that
is text, not glass. The badge is not glass either, as Apple's is not: an
opaque systemRed capsule that costs no surface.

What it costs that is not free: the search bar's Cancel slide resizes
the field, and the host takes a capture a frame for the 250 ms of the
slide (16), one with reduced motion. GlassTravel does not remove it, and
neither does an empty box in place of Cancel, so it is the resize. A
PageView beside a page control is retaken while it scrolls, 43 captures
a swipe, and the same 43 with dots that do not move, so that belongs to
the view, not the control.

The sizes are layout choices, not measurements of Apple's controls, and
their documentation says so.

* Sheet detents with an opaque large one, a sheet that follows the finger, and a tab bar that minimizes

A dismissible sheet moved about 4.5 px for 116 px of drag: the drag
drove the route's controller through easeOutCubic. It now moves by its
own offset in pixels, 1:1, and dismisses past a third of its height or
on a flick; the test that recorded the defect is unskipped.

showGlassSheet takes detents (medium, large). Large is the full height
with no inset, and when its finish is opaque the sheet steps down to
the cheap rung and reads no backdrop: 1 of 2 surfaces captured instead
of 2, 20,608 px² of capture instead of 337,408. What moves the other
way: an opaque sheet is ordinary content in the capture, so a change
inside it retakes (1 against 0). A translucent largeFinish keeps glass.
While a finger or a settle moves the sheet it declares where it can
travel: 1 retake for a drag against 16 without.

GlassTabBar.minimizeBehavior collapses the bar to the selected tab's
circle on scrolling down and expands it on scrolling up, with an
optional bottomAccessory; GlassScaffold provides the minimizer. The
change of shape happens inside travel regions: 0 records over 60 frames
against 60 without them. A bare setState on GlassTabBar costs a capture
(it did before this change, and is not traced yet), so the collapse
drives its widgets through a notifier.

Defaults are unchanged: one detent and the same tree for a tab bar that
does not minimize. The large detent's gap, the circle and the accessory
sizes are layout choices, not measurements of Apple's.

* A press that swells the glass, slider divisions, keyboard focus and RTL for the controls

GlassButton grows by a fixed 12 px on its longest side when pressed and
leans toward a dragged finger (GlassPress; off under reduced motion, on
disabled buttons, and with GlassPress.none). Apple's press is not
measured here (D104), so the law is borrowed and the number is a chosen
feel: 17 px, as another package uses, is 1.39x on a 44 px target. A
Transform would scale the draw but not the shader's map into its slot,
so the glass is laid out inside its own boundary and declares a travel
region: 0 captures across a press against 46 without it.

GlassSlider.divisions snaps every input to a stop. The switch and the
slider drag from touch-down, and claim the pointer under a horizontal
scrollable: the drop now lifts on the next frame instead of after the
tap timeout. In a vertical list a swipe that starts on a switch still
scrolls. A switch in a PageView already won its drags headless; the
claim is about the lift, not the win.

GlassConcentric gives an inner radius as the outer minus the inset; the
segmented control's capsule uses it and is pixel-identical. Buttons,
switch, slider, segmented control and toolbar cells take focus, with a
ring drawn inside the glass's own subtree, and mirror under RTL. Two RTL
defects are fixed on the way: the segmented capsule sat under the wrong
label, and GlassButtonGroup brightened the wrong cell.

* A press declares its region only while it moves; segmented control claims under a PageView

Declaring the press's travel region at rest doubled every enabled
button's captured area (3600 -> 7056 logical px² for a 44 px circle)
to save the two captures a press now costs: one at touch-down, one when
the spring settles. Nothing draws from the old slot: the spring's first
tick is at rest, and the 12 frames after touch-down match the
always-declared arm (the break is to start the press at 0.5). A side
effect: a resting button no longer draws its rim against a larger slot,
which had moved a few rim pixels by up to 15 code values.

GlassSegmentedControl followed raw pointer events and was in no arena,
so under a PageView both the page and the segment followed a drag (the
page moved 0.25 with the claim off). It now claims on touch-down under a
horizontal scrollable, by the same rule as the switch and the slider.
The switch's PageView arm had dragged rightward on the first page, where
a page cannot move, so it proved nothing; the control now sits on the
middle page.

* Uniforms packed into vec4s: on Metal a declared float is a bind per draw

runtime_effect_contents.cc:316-334 binds every declared float uniform of
a runtime effect on its own, per draw, on Metal (setFragmentBuffer per
uniform, render_pass_mtl.mm:194-214); Vulkan takes one struct
(reflector.cc:427-440). The 31 people quote is Metal's per-stage limit,
which Impeller does not check; the shaders were at 19, 19 and 24.

Packed in the order Dart writes them, the old names now macros over
lanes: 9 binds for the surface and the group, 12 for the ripple. No
setFloat index moved but the ripple's tail (count, reach and light now
follow the arrays). main() is unchanged in both programs.

Byte-identical against 0.1.5: 5 scenes x 480,000 px on Skia, 0
differing; Metal hashes match for finishes, contrast, group and a direct
ripple render. The gate's controls: a repeat moves 0, a tint 1e-3 off
moves 8338 px, swapped uSlotMax lanes 172,779. Raster thread, one
binary, packed against unpacked, 240 draws: 0.9-1.4 us less per surface
draw and 1.0-1.8 per group draw, dearer unpacked in every round; the
surface bench cannot resolve it. Not measured on an iPad or Adreno.

The superellipse corner made with it stays on feat/shader-sdf: 22% more
fragment time on a Mac, and native Skia draws an RSuperellipse as an
RRect.

* Docs, site and skill for the 0.1.5 components, sheet detents, tab bar minimize, press and keyboard

README rows and patterns, the misuse section, CHANGELOG and ROADMAP for
everything merged into 0.1.5; four site pages (stepper, page control,
search bar, badge) with a capture meter under their demos, and the
button, slider, segmented control, tab bar, sheet and host pages
updated; the skill's references regenerated and rules 23-27 added.

* A press never shrinks the glass below its box; the tab bar's glass hears touches again

Found by the example's tests after the merge. The showcase's alert
overflowed by 0.727 px: the label is laid out inside the pressed glass,
and on the spring-back the press undershoots to 1 - maxOvershoot, so a
Row that filled its button no longer fit. GlassPress.rect now floors
each side at the resting box; the sweep through the unfloored formula
is the control that it reaches a shrinking press, and without the floor
the widget arm overflows by 0.546 px.

The minimizer moved the tab bar's press Listener from the bar's
ancestor to a sibling over it, and an opaque one ended the hit test
there: the bar's glass never heard a touch, and a declared ripple never
answered. Selection still worked, which is why only the example's
ripple test saw it. The listener is translucent; with it opaque the new
arm's ripple count stays 0.

* Pubspec comments say what a reader of the package needs

They narrated how the values were chosen, named a research decision number
and walked through flutter_tools internals. Each now keeps only the reason
that still holds.

* Version 0.2.0 instead of 0.1.5

The release adds components, new parameters on the sheet, the tab bar and
the controls, and a declared backdrop: more than a patch. The changelog says
so, and that the ripple shader's uniform layout is the one change visible to
code that writes uniforms by hand.

* Test comments: drop research-repo references and lab history

The test comments still cited decision and spike numbers, phases, the
benchmark corpus and files of the research repository the package was
extracted from, none of which a contributor here can look up. Each
reference is replaced by the fact it stood for, history is cut to the
reason that still holds, and the run commands in file headers point at
test/ instead of the old test/glass/ path.

Comments only: test names, reason strings and expectations are
unchanged, including the few that still carry a decision number.

* Rewrite surface comments for the package's reader, not the research notebook

The comments in lib/src/surface/ (finish, host, ledger, group, tier, surface,
components, theme) still cited the research repository: decision numbers,
FINDINGS/roadmap pointers, benchmark jargon and the history of how each
default was reached. They now state what each thing is, why a default or
constant exists, and the measured number with its device.

The shadow-filter doc used to claim skipping shadows costs 0.00 ΔE; that
figure was taken without real shadows, and with them it is under 0.2 ΔE.
The noteChange doc described the host's detection as it was before the
layer watch; it now says what is actually left to declare.

Comments only: no code, identifiers or string literals changed.

* Test names and failure reasons: drop research-repo references

Test descriptions and reason strings still cited decision, spike and
milestone numbers from the research repository. They now say what they
check without the reference; identifiers and provenance file names are
unchanged.

* Rewrite lab-notebook comments in the surface widgets, shaders, library files and changelog

The comments still cited the research repository's decision and spike
numbers, its bench/ files and benchmark jargon (arms, negative controls, the
corpus), none of which a reader of the package has seen. Each reference is
dropped or replaced by the fact it stood for; the reasons and the measured
numbers, with their device, stay. The shader headers no longer point at the
research repository's probe and preview shaders, and glass_group.frag names
this repository's test/glass_group_test.dart. CHANGELOG and ROADMAP keep
every entry and lose only the D-numbers and the research-application
wording. Comments and prose only; no code changed.

* Three error messages no longer cite research decision numbers

A user reads these in a FlutterError; D26, D204 and D179 pointed into a
repository they cannot see.

* Scroll edge: one cost figure for the unnamed finish, not two that disagree

* Rewrite proxy, hardware and thermal comments for package readers

The comments under lib/src/proxy/, lib/src/hardware.dart and
lib/src/thermal.dart still read as the research repository's notebook:
decision and milestone numbers, pointers to FINDINGS and spikes, benchmark
jargon (arms, corpus, ladder rungs) and stories of how each policy was
reached. A reader of the package has none of that context.

Each comment now keeps the reason and the number that justifies it, with
the device it was measured on, and drops the history. Test paths that
pointed at the research layout (test/glass/...) now name this repository's
tests. Two misplaced doc comments in proxy_pipeline.dart (GlassProxyFrame
and GlassProxyPipeline.snapshots) are moved onto the members they describe.

Comments only: no code, identifiers or string literals change.

* Front page for the release: what is new, and three gallery scenes on the new components

"New in this release" lists the release's own pages: the stepper, the page
control, the search bar, the badge, the declared backdrop, sheet detents,
the tab bar that folds away on scroll and the press.

Three scenes join the gallery:
- Shop: a product page whose stepper sets how many are in the bag and a
  GlassBadge on the bag that counts them. Its backdrop is a GlassBackdrop
  painter, so the scene's glass captures nothing at all.
- Onboarding: painted pages in a PageView, with a GlassPageControl that
  follows the swipe and turns the page, and Skip / Next / Start buttons.
- Library: songs under a GlassSearchBar that filters them and a GlassTabBar
  that collapses on a scroll down, with the playing song in its
  bottomAccessory. As in the chat, the list scrolls by mouse, wheel or
  trackpad and leaves a finger to the page.

The tabs scene's hand-made badge is a GlassBadge now, and the lock screen's
mail names 0.2.0.

test/home_scenes_test.dart mounts each new scene at two widths and with
larger text, checks that it takes no capture at rest (with a swipe as the
control that the counter counts), and drives each one: the stepper and the
badge, the dots following a fling and turning the page, the bar folding and
coming back, and the search. The Shop arm checks every surface reads the
declaration; with the declaration swapped for GlassBackdrop.live it fails.

* The skill describes 0.2.x

* Review fixes: a declared texture outlives its draw, controls yield a vertical swipe, sheet and tab bar edges

A review of the release found these, each now with a test that failed first.

Declared backdrop:
- Glass over a GlassBackdrop could go blank. The declaration kept four
  blurred textures and disposed the oldest; a materializing surface asks for
  a new blur every frame, so a still surface's texture was evicted, and when
  its draw layer re-recorded after a move the painter asked again, got a new
  texture (rendered during compositing), failed the identity check and drew
  nothing until something repainted it. Textures are reference counted now:
  a draw holds the one it was recorded with, and the composite-time painter
  never asks the declaration.
- A fused member decided its capture exclusion from its own declaration while
  its ledger record followed the group; it follows the group now.
- A replaced GlassBackdrop.image kept declaring the old image; the glass goes
  back to the capture until the new one loads, as documented.

Controls:
- Inside a horizontal scrollable the switch, slider and segmented control won
  the arena on touch-down, so a vertical swipe toggled or moved them and the
  outer list never scrolled. They now compete as horizontal drags: a
  horizontal drag still beats the page, a vertical swipe scrolls the list.
- The slider's onChangeStart/onChangeEnd now pair as Material's do, with the
  end carrying the last value sent.
- GlassButtonGroup threw or kept a ring on a removed item.
- The stepper and page control mirror under RTL (the stepper's hit areas
  were mirrored but its glyphs were not, so the minus incremented), take the
  keyboard focus, and the page control clamps a page past a shrunk count.
  The search bar shows Cancel when showsCancelButton turns on while focused.

Sheet and tab bar:
- A tap on a settling sheet re-picked the nearer detent (a never-started drag
  still reaches end or cancel); a release only settles after a real drag.
- A pop during a drag popped the page underneath on release; a drag from
  large after a content or width change jumped; the sheet now stands on the
  keyboard and hides the bottom inset from its content.
- GlassTabBarMinimizer.notificationPredicate (and
  GlassScaffold.minimizeNotificationPredicate) reaches lists in a PageView,
  and the collapse direction is read on screen, so reverse lists behave.

Pixel gate: the byte-identity test never ran in CI, and committed hashes
would not help (macOS and Linux differ by 1-46 px per scene). Every run now
compares the packed shaders against unpacked copies compiled in the test,
with a uSlotMax lane swap as the control (172,779 px in "finishes").

Docs: CHANGELOG, README, topics and the skill (regenerated from the catalog)
describe the above; the example reads its version from the pubspec and each
home scene's at-rest check has a control of its own.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants