Repository navigation
Collapsed issue card for 1.0.0 - #24
Merged
Merged
Conversation
This was referenced Oct 20, 2026
Harrys76
force-pushed
the
wp28/overlay-chrome
branch
from
October 23, 2026 18:11
9fccb8e to
a7dded6
Compare
Harrys76
force-pushed
the
wp29/overlay-collapsed-card
branch
from
October 23, 2026 18:11
023a479 to
234de72
Compare
Harrys76
force-pushed
the
wp28/overlay-chrome
branch
from
October 23, 2026 19:22
a7dded6 to
af9ac70
Compare
Harrys76
force-pushed
the
wp29/overlay-collapsed-card
branch
from
October 23, 2026 19:22
234de72 to
eee3b63
Compare
Harrys76
force-pushed
the
wp28/overlay-chrome
branch
from
October 26, 2026 16:44
af9ac70 to
15ca6a5
Compare
Harrys76
force-pushed
the
wp29/overlay-collapsed-card
branch
from
October 26, 2026 16:45
8a43ecb to
10c07b5
Compare
jank_detected and sustained_jank carried no observation source, and slow_startup_ttff said structural although its time ends at the first frame's FrameTiming raster end. All three now carry ObservationSource.frameTiming. Detection is unchanged; the source shows in exports, the AI context and the expanded card, and the collapsed card's Debug timing tag reads it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The card is flat with no source bar. A severity icon in the severity's text colour replaces the emoji, and the title runs to 2 lines (3 above 1.3x text), or in full while expanded. One meta line replaces the badges: category, confidence, "seen X of Y scans, label" and effects, led by the Jank and New tags, as one paragraph so a wrapped line keeps each separator with the part before it. A Debug timing tag takes the confidence slot on a time-based measurement from the VM timeline or FrameTiming in a debug run, replacing the per-card debug note. A crosshair replaces the highlight checkbox and shows only for an issue that names a widget: a 48 px Positioned hit box in the card corner with its face on the title's first line, read as on or off. The card body and the crosshair draw the focus outline in keyboard mode. The pin icon is gone; an expanded card's hint carries "Pinned while expanded". The overlay no longer uses Checkbox, so it leaves the framework denylist. The guide legend describes the new card, without the never-drawn Jank flash colour or the dead jankFlash prop. Collapsed cards are shorter, so the build-cost budget for a title change rises to 400 issue-card builds (8 per change instead of 6). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
wrap_layout_bottleneck, excessive_repaint_boundary and issues from SimpleStructuralDetector.report set an occurrence id that matches their highlight but no widgetName, so the collapsed card, which shows the crosshair only for an issue that names a widget, dropped a highlight that worked. Each now carries the name its highlight carries: Wrap, the scrollable's type, or the reported widget's runtime type. Their overlay keys gain the name, so such a card hidden under an older release shows again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…expanded cards stay Device feedback on the 1.0.0 card: - The severity mark is a disc or triangle filled with the severity colour, with a white or near-black mark inside at 3:1 or more against the fill (SleuthSeverityIcon), in the card and the guide legend. The tinted Material icons read pale on the card. - The resize grip works on a maximized card: the first drag or resize step makes it a normal card at the size and place it has, then resizes that. - SleuthFocusInkWell draws no ripple, only a light textPrimary tint while pressed. Above the app's MaterialApp the fallback theme's 40 % grey splash flooded the card and the menu. - An expanded card stays until it is collapsed, even when its issue stops being reported or folds under another card. A card whose issue is gone leads its meta line with "Not detected right now" and offers no crosshair, and the empty states wait for the collapse. applyFreezeZone keeps expanded entries from the snapshot, and the prune no longer drops them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An expanded card that outlives its issue now: - goes when the user hides it, also through a twin card sharing its hide key; the prune drops hidden expanded cards before keeping the rest; - is stale only when its own occurrence is gone: it is matched to the visible list by occurrence key, else to the reported issues by list key and element identity, so of two cards sharing a key only the one that went loses its crosshair; - shows its last reported instance, not the one it was expanded with: the host keeps the latest instance per expanded card and applyFreezeZone takes it in place of the snapshot's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
As the design draws them: a 1.8-unit ring in textPrimary around the critical and OK discs, which reads white on the dark card and also sets the disc's edge apart from it. The warning triangle keeps its own edge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t report - With two cards sharing a list key, the first one going moved the second onto its occurrence key, so a kept card could be replaced by its twin and the twin shown twice. Kept cards are now matched to reports by list key and element identity, and applyFreezeZone shows each issue once, excluding by identity what the frozen zone already shows. - The prune judged hiding on the kept instance. A card hidden at warning that came back critical, was expanded and fell back to warning stayed. The check now resolves the current report first. - The "Not detected right now" tag text uses badgeTextOn, so it keeps 4.5:1 on the high-contrast presets' opaque badge fill. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Expanding only the second of two cards sharing a list key, then losing the first, moved the second onto the first's occurrence key: it showed collapsed and its expansion entry lingered. Expanded slots now claim their issues before collapsed ones, a kept expanded card keeps the key its expansion is stored under (_cardKeys), and a re-captured snapshot repoints expansions by identity, renaming a key that moved. - A kept card no longer reported was skipped by the hide check, so hiding its live twin left it on screen. The check falls back to the kept instance. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Theme row matches the design: no icon before the label, and Auto, Light and Dark in one outlined bar split by thin lines. The current choice fills its cell edge to edge and reads in bold, with no border of its own, and Light and Dark keep their outline icons in both states. Each choice is still a 48 x 48 target with a 32 px tall cell, and draws the focus outline in keyboard mode. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
After a card's twin was replaced by a new occurrence under the same list key, tapping the new card stored its expansion under a key whose snapshot slot still held the old twin: the old twin came back and the new card showed collapsed. The tap now records the tapped issue as the kept instance of its key, and a collapse drops it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The light preset drew chip borders, chip icons and the run label dot in its severity text shades, red-800 and amber-800, which read as two dark browns. The dark default drew them in its pale text shades. New optional severityCriticalGraphic, severityWarningGraphic and severityOkGraphic tokens, read through severityGraphicColor, colour these graphics: the dark default uses the severity fills and the light preset red-600, amber-600 and emerald-600, each at 3:1 or more on the card. The high-contrast presets and fromColorScheme keep the text shades. The ring on the critical and OK discs is white in both themes. It was the text colour, so a light card drew it black. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Occurrence keys are positional, so a kept expanded card can show under a key that differs from its place in the visible list. Pruning checked the selected key against the visible keys and could clear the crosshair of a card that was still on screen. The card now keeps the selected issue and prunes the selection when that issue has no report in the list. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
While a card was expanded, the cards above it lived in three places: a list snapshot, a map from occurrence key to snapshot index, and a map of kept issues. Occurrence keys number the cards sharing a list key by position, so when a twin ahead of an expanded card went, the three drifted apart. A re-captured snapshot renumbered the keys, so a new twin took over the kept card's expanded state. A kept card whose report had been replaced could be dropped. A card expanded next to a kept twin was left out of the snapshot and vanished when its issue went. The frozen zone is now one list of cards. Each card holds the key it rendered under when the zone was captured, its latest report, and whether it is expanded. Every update matches the cards to their reports by list key and occurrence id, and the cards below take keys that skip the frozen ones. Expanding a card below the zone captures the rows on screen down to it, under the keys they rendered with. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Wrap layout, excessive RepaintBoundary and custom structural issues
now carry a widget name, which their list keys include, so a key a
0.38 store held for them ("wrap_layout_bottleneck") no longer matched
and the card showed again. The overlay state moves to schemaVersion 2.
Loading a version 1 store turns each key without a widget name into
one that matches any widget of its stable id ("wrap_layout_bottleneck|*"),
the Hidden issues list names a card such a key still hides, and
Restore removes it. Keys written by 1.0 are read as stored. A card
shown again while the store read was pending stays shown, whether the
app unhid the stored key or a key of the same stable id with a widget
name.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A key migrated from a version 1 store showed as `raster_hot_spot|*` on the Hidden page, and widget keys as `id|Widget!critical`. hideKeyLabel reads them as `id · Widget` or `id · every widget`; the critical suffix is left out, since the row already says when a key stops hiding a card that turned critical. A key with nothing detected uses the label as its title, and the label gets two lines, so a long stable id keeps the widget name at its end. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Guide's legend and tip said the Jank tag marks an issue that can explain "the latest slow frame". The tag now stays for 10 s after a slow frame names the issue and clears on a route change, so both say "a slow frame from the last 10 seconds on this screen". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Harrys76
force-pushed
the
wp29/overlay-collapsed-card
branch
from
October 26, 2026 17:59
10c07b5 to
22f281a
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fourth PR of the 1.0.0 overlay stack, on top of #23. It redesigns the collapsed issue card (plan step 12). The expanded content below the meta line comes in the next PR.
What changes
Card surface. The card is flat (
Card(elevation: 0)) with no source bar on its left edge.Severity icon.
Icons.error,Icons.warningorIcons.check_circleinseverityTextColorreplaces the emoji. It sits on the title's first line, placed by the measured line height.Title.
fontLgw600, 2 lines, or 3 above 1.3×. An expanded card shows the whole title.Meta line. One paragraph replaces the badge line: category · confidence · "seen X of Y scans, label" · "N effects", in
fontMdtextTertiarywith tabular figures.Debug timing tag. It takes the confidence slot, as in the mock, on a timing issue in a debug run. That means:
debugModeDisclaimer;FrameTiming;Rates, counts and sizes stay untagged, and so do the raster cache issues, whose frames count cache changes. The per-card "Debug mode result" note is gone. The tag uses the
badgeDbg*pair.Crosshair. It replaces the highlight checkbox.
Icons.my_location18 px, with a 32 px face in a 48 pxPositionedhit box in the card corner. The face is centred on the title's first line._isLocatableIssueis now "has a widget name", which closes the gap Overlay data for the 1.0.0 card #22 left for layout and paint cards without one. Issues whose highlight matched by element only now carry their widget's name (see Review).Focus. The card body and the crosshair draw the 2 px
checkboxActiveoutline in keyboard mode (SleuthFocusInkWell, which gainsexcludeFromSemantics). The InkWell's own focus fill comes fromThemeData.fallback()above the app'sMaterialAppand measured 1.13:1 on the dark card.Pin. The icon is gone. An expanded card's semantics hint reads "Pinned while expanded", after "New" when both apply.
Denylist. The overlay no longer uses
Checkbox, so it leaves the framework section (51 entries, pinned by the growth test). Host-app checkboxes now count; the CHANGELOG says so.Source metadata (own commit, 703f32d).
jank_detected,sustained_jankandslow_startup_ttffcarryObservationSource.frameTiming. The jank issues had no source, and startup saidstructuralalthough its time ends at the first frame's FrameTiming raster end. Detection is unchanged. The source shows in exports, the AI context and the expanded card, and the Debug timing tag reads it.Different from the plan
jankFlash: false. The row and the dead prop are gone.cardJankFlashstayed here for custom themes, and 1.0 public API, API enforcement and list-card crosshair #27 removes it with the other unread tokens.sourceAccentWidth,effectsBadge,disclaimerTextandcardJankFlashare no longer read. Their docs say so, as Overlay chrome for the 1.0.0 card: run label, More menu, status row #23 did for the VM/FRAME badge tokens. The API PR removes them.Verification
fvm flutter analyze: 0 issues. Format check clean.fvm dart doc --dry-run: 0 warnings.fvm flutter test --exclude-tags benchmark: 4,899 passed.--tags benchmark --concurrency=1): 44 passed.Device feedback (735b30b)
Tried on the iPhone 12 in profile mode with
--no-dds:SleuthSeverityIcon): a disc or triangle in the bright severity colour with a white or near-black mark inside at 3:1 or more against the fill. The tinted Material icons read pale.SleuthFocusInkWelldraws no ripple, only a lighttextPrimarytint while pressed. Above the app'sMaterialApp, the fallback theme's 40 % grey splash flooded the card and the menu.applyFreezeZonekeeps expanded entries from the snapshot, and the prune no longer drops them.Review
Codex reviewed the branch nine times; the ninth round, on the frozen-zone rewrite, found nothing. The first round found one defect, fixed in 35685b3; the second found none. The third reviewed the device-feedback commit and found three edge cases in the kept expanded card, fixed in 68adf2e with a regression test each:
The fourth round found three more, fixed in 35332bc with a regression test each:
badgeTextOn.The fifth round found two more twin cases, fixed in 1db254b with a regression test each:
The sixth round found one more: after a twin was replaced by a new occurrence under the same key, tapping the new card stored its expansion against the old twin's slot, which came back while the new card showed collapsed. Fixed in 485e5cd: the tap records the tapped issue as its key's kept instance.
The seventh round found that the crosshair selection was pruned by its positional key, so a kept card showing under a key that differs from its place in the visible list could lose its highlight on the next update. Fixed in d98691a with a regression test: the card keeps the selected issue and prunes the selection when that issue has no report in the list.
The eighth round found three more twin cases in the same bookkeeping: a re-captured snapshot renumbered keys, so a new twin took over a kept card's expanded state; a kept card whose report had been replaced could be dropped; a card expanded next to a kept twin was left out of the snapshot and vanished when its issue went. Each came from three structures (snapshot, key-to-index map, kept issues) keyed by position among twins. 023a479 replaces them with one frozen-zone list: each card holds the key it rendered under when the zone was captured, its latest report and its expanded flag, and every update matches cards to reports by list key and occurrence id. A regression test for each case fails on the previous code; every earlier twin test passes unchanged.
After a look on the device, the disc marks gained a ring (b038fec), and the Theme row became the mock's single outlined bar with thin dividers, a filled bold current choice and no leading icon (c19d235).
wrap_layout_bottleneck,excessive_repaint_boundaryand issues fromSimpleStructuralDetector.reportset an occurrence id that matches their highlight, but nowidgetName, so the new crosshair rule dropped a highlight that worked. Each now carries the name its highlight carries:Wrap, the scrollable's type, or the reported widget's runtime type. Their overlay keys gain the name, and a store written before 1.0 keeps hiding them (next section).In light mode the severity chips read as two dark browns, and in dark mode the run label dot was pale (1ff53d8). Both drew in the severity text shades. Optional
severityCriticalGraphic,severityWarningGraphicandseverityOkGraphictokens, read throughseverityGraphicColor, now colour chip borders, chip icons and the dot: the mock's severity fills in the dark default, red-600, amber-600 and emerald-600 in the light preset, each at 3:1 or more on the card. The high-contrast presets andfromColorSchemekeep the text shades. The disc ring is white in both themes; the text colour drew it black on a light card.Hidden cards across the upgrade (8a43ecb)
Cards of those three families hidden under 0.38 showed again after the upgrade, because their stored hide keys named no widget.
OverlayUiState.schemaVersionis now 2.loadJsonreads a version 1 hide key that names no widget as an any-widget key (legacyHideKey:id|*, keeping!critical), andisHiddenByand the Hidden page match it against every card of that id. A version 2 store's keys are read as written. 0.38 reads a version 2 store as empty and leaves it as it is, as it does for any newer version. A card shown again while the store read is pending stays shown, whether the app unhid the stored key or a key of the same stable id with a widget name, and the Hidden page names a card the key still hides before one that turned critical. Tests cover the version 1 read, the version 2 read, both pending-read cases, the severity rule for an any-widget key and the Hidden page; each fails without its part of the change.Not in this PR
ShaderMask.Hidden page labels (Galaxy follow-up)
The Hidden page printed hide keys raw:
raster_hot_spot|*for a key migrated from 0.38, andid|Widget!criticalfor others.hideKeyLabelshowsid · Widgetorid · every widgetand leaves out the critical suffix, since the row already says when a key stops hiding a card that turned critical. A key with nothing detected uses the label as its title. The subtitle takes two lines, so a long stable id keeps the widget name at its end. Tests cover the label, the row with nothing detected and the two-line fit; each fails without the change.On the Galaxy A07, keys saved by a real 0.38.0 build (
raster_hot_spotandtooltip_usage::This tooltip triggers cookbook detector 01) loaded as|*keys and kept both Cookbook cards hidden, including the tooltip card that now namesTooltip. Restore wrote the store asschemaVersion2.Guide text (doc audit follow-up)
The Guide's legend and tip said the Jank tag marks an issue that can explain "the latest slow frame". Since #22's follow-up the tag stays for 10 s after a slow frame names the issue and clears on a route change, so both now say "a slow frame from the last 10 seconds on this screen".
🤖 Generated with Claude Code