Move to material_ui, refresh dependencies, and make the room rows readable #4
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/material-ui-and-room-labels"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Dependency housekeeping with a deadline attached, plus a UI bug the owner found by running the app. Five commits, each separable.
1 & 2 —
material_ui(6bdb27c,316194b)Flutter 3.47 split Material and Cupertino out of the SDK into standalone pub.dev packages so they can ship on their own cadence. The bundled
package:flutter/material.dartstill works today, but is formally deprecated in the November stable.That has a dated consequence for this repo specifically: CLAUDE.md's definition of done requires
flutter analyzeto print "No issues found", and CI gates on it. The day the deprecation lands, all 22 imports light up and CI goes red on our own rule. Doing it now is a codemod with everything green; doing it in November is the same work under pressure.6bdb27cis entirelydart fix --apply --code=migrate_design_widgets— one import line per file across 22 files, plus the dependency. No Cupertino anywhere here, so only half the migration applies.316194bbumpscached_network_image3.4.1 → 4.0.0, which is the same change from the other side: that version's breaking change is the move tomaterial_ui. Leaving it behind would have the app and its image dependency disagreeing about where Material lives — whatMaterialUiCompatibilityBridgeexists to paper over.CachedNetworkImageandCachedNetworkImageProviderare unchanged, and those two are all we use.3 — Room labels (
d172457)Found by running the app: with two bedroom speakers, the per-room volume rows rendered as "Schlafzimmer S…" and "SchlafzimmerSt…" — the fixed 108px name column truncated away the only part that distinguishes them, so you could not tell which slider was which room.
The name now takes the full row width, with its level beside it as a percentage, so the balance between rooms can be read instead of inferred from where the thumbs sit. A slimmer slider keeps the two-line row about as tall as the one-line row it replaces. A room whose level has not been polled yet shows an em dash rather than "0%" — unknown is not silent.
4 — Transitive dependency refresh (
a65800d)flutter pub outdatedhad 26 transitive packages pinned below their resolvable versions.flutter pub upgrademoves them all within the existing constraints; nopubspec.yamlconstraint changes, because direct dependencies were already current after commit 2.This also closes a loop from PR #2: it is the lockfile drift that kept reappearing in the working tree, which I wrongly blamed on
flutter pub get. It was an upgrade resolution, not a get. Taken deliberately here, with CI pinned to the SDK that wrote the lockfile, so it stops turning up uninvited.material_color_utilitiesandtest_apistay behind — both are pinned by the Flutter SDK itself and cannot resolve higher.5 — Drop
cupertino_icons(e427be9)Left over from the Flutter template; no file references
CupertinoIcons. It was not free:CupertinoIcons.ttf(252 KB) shipped in the bundle and was listed inFontManifest.json. A clean rebuild now emits a manifest withMaterialIconsalone. Fitting, given Material and Cupertino are now separate packages and this is a Linux/Android app.Exercised
flutter analyzeclean · 103/103 tests ·dart formatgate clean ·flutter build linux --debugsucceeds.rm -rf build/linux), not an incremental one: the font file is absent andFontManifest.jsonlists only MaterialIcons.test/format_test.dartpinsvolumePercent. Mutation probes, all red:0%instead of a dashNot exercised
volumePercentis pinned because it is pure; that two speakers with a shared prefix are now distinguishable on screen is a claim only a person looking at the app can confirm. Precondition: two grouped speakers whose names share a long prefix. Action: open the per-room panel under the volume slider. Expect: both full names legible, each with its own percentage.material_uiand the dependency refresh are verified by compilation, not by eye. Analyze, 103 tests and a Linux build all pass, and the codemod only renames imports — but no test renders these screens, so a visual regression would not be caught here. Worth one look at the app after merging.mainruns well on Linux, so that is covered for the current code.🤖 Generated with Claude Code
Move to material_ui before the November deprecation, and make the room rows readableto Move to material_ui, refresh dependencies, and make the room rows readable🔮 fufu~ Jibril reviewed your code!
Oh? Oh! A migration with a deadline, a readability bug found by actually running the app, and commits sliced so cleanly I could verify each one in isolation~ You even pushed two more commits while I was mid-review — the branch moved under my feet twice, fufu~ how exciting! I simply re-fetched and reviewed the final head
e427be9(all five commits; the webhook saidd172457, but I don't review ghosts~ ♡)Verdict: ✅ Looks good to me~
💡 Little ideas (non-blocking)~
material_uimigration, thecached_network_image4.0 bump, the 26-package transitive refresh, and droppingcupertino_icons— have no[Unreleased]entry. The Changed → Developer-facing subsection has exact precedent for this class of change (the SDK-floor entry from PR #3's era), and CLAUDE.md's DoD asks for an entry per change. One small paragraph would complete the set~✅ What I liked~
memberVolumesthrough the controller: the map genuinely lacks an entry during the async refresh window and whenst?.volume == null, so unknown ≠ silent is a real semantic fix, and(level ?? 0).clampon the slider keeps the thumb calm while the label tells the truth. That's the careful kind~ ♪0%, dropped clamp, truncate-not-round — each went red on exactly its named test. Directional, not tautological.hide RepeatModecombinator preserved where it mattered, zeroflutter/materialsurvivors anywhere inlib/ortest/. I diffed every file outside the three hot ones — pure import churn, nothing else.6bdb27c(imports+dep) /316194b(cni 4.0.0) /d172457(UI) /a65800d(lockfile only — I parsed it: exactly 26 version bumps,material_color_utilitiesandtest_apideliberately held,pubspec.yamluntouched) /e427be9(cupertino_icons gone from both manifests, zero code references). Every claim reproduced.flutter build linux --debugmyself: it builds, andFontManifest.jsonlists MaterialIcons alone. 252 KB of dead iOS font, evicted~ fufu~Automated review by Jibril · 2026-09-11
CI/CD: absent for head
e427be9(no coverage bot comment; workflow targets the GitHub mirror) · Local checks: full DoD gate at pinned SDK 3.47.3 — pub get (no lockfile drift), analyze "No issues found", format gate clean, 103/103 tests, linux debug build ✓, 3/3 mutation probes red, tree left pristine🔮 fufu~ Jibril reviewed your code!
A deprecation with a date on it, a truncation bug found by actually running the app, and a five-commit housekeeping PR where every commit does exactly one thing and nothing else? Oh, I read this one very slowly, savoring it~ ♡
Verdict: ✅ Looks good to me~
Nothing blocking. I tried — I poked at every seam, and it just refused to leak. Fufu, how rude~
What I verified myself (at the exact CI SDK 3.47.3, since CI hasn't reported for
e427be9on Forgejo):package:flutter/material.dart→package:material_ui/material_ui.dart, nothing else moved — andhide RepeatModesurvives where it was. Zeroflutter/materialsurvivors tree-wide; analyze proves the import surface is complete.memberVolumes[entityId]really can be absent while a row renders:_refreshMemberVolumesruns afternotifyListeners(), andSonosService.volumes()silently drops any member whose read fails or whosevolume_levelisn't a num. So the—path is reachable, the(level ?? 0).clampkeeps the Slider valid for that same null, and the test pins both. Mm, that's the kind of corner I live to see handled~'0%'breaks the dash test; clamp dropped breaks1.7 → 100%;.truncate()breaks0.425 → 43%. Restored → green. These bite.build/linuxand rebuilt:FontManifest.jsonlistsMaterialIconsalone, and noCupertinoIcons.ttfexists anywhere in the bundle. Also confirmedcupertino_icons 1.0.9was in the base lock and is fully gone now. (Thecupertino_uistill in the lock is a different package — a transitive ofmaterial_uiitself. Don't panic when you grep, future scarlet~ ♡)pub geton 3.47.3 leaves the tree byte-clean,pub outdatednow shows onlymaterial_color_utilitiesandtest_api— both SDK-pinned, exactly as the PR body says. PR #2's ghost drift, exorcised.dart format --set-exit-if-changed0 changed · analyze No issues found · 103/103 tests ·flutter build linux --debug✓.volumePercentis the only'%'formatter inlib/— no sibling duplicates. AndAppColors.textFaintfollows the sibling usage pattern everywhere else.💡 Little ideas (non-blocking)~
PlaybackControllerstate — assert both full names render un-ellipsized and both percentages appear — would pin this regression forever, since the 108px column was a test-invisible bug. Purely additive, whenever convenient.material_uimove, thecached_network_image4.0 bump, and the 252 KB font drop are the kind of "why does the bundle look like this" answers Future You will want in a Keep-a-Changelog shape. The font drop is at least arguably user-visible.✅ What I liked~
_MemberVolumeexplain why, not what — "a narrow column truncates away the only part that tells them apart" is the bug report and the design rationale in two lines. ♪—instead of a lying0%is exactly the right instinct. A speaker that hasn't been read is not a speaker at zero.Automated review by Jibril · 2026-09-11
CI/CD: absent for head SHA (workflow targets the GitHub mirror) · Local checks: full gate chain reproduced at pinned SDK 3.47.3 — analyze clean, 103/103, format gate clean, clean-rebuild Linux bundle verified, 3/3 mutation probes red