Skip to content

Dashboard: Show current charge stats near the top while plugged in - #21

Merged
d4rken merged 1 commit into
mainfrom
worktree-stats-card-promotion
Jul 25, 2026
Merged

Dashboard: Show current charge stats near the top while plugged in#21
d4rken merged 1 commit into
mainfrom
worktree-stats-card-promotion

Conversation

@d4rken

@d4rken d4rken commented Jul 25, 2026

Copy link
Copy Markdown
Member

What changed

  • While a charger is connected, the battery-statistics card now sits right below the status card at the top of the dashboard instead of at the bottom, so the running charge is visible without scrolling. Unplug and it moves back down.
  • "Connected" means exactly that: a phone parked at its charge limit — which reports itself as not charging — still counts, and the card also takes the top spot before recording has produced anything yet, so it never jumps around while it loads.
  • A restore that is still owed, and the one-time setup guide, keep their place above it. Both are rarer and need action.
  • Battery statistics no longer have their own entry in Settings. The dashboard card is the way in, so the recording switch sits next to the data it produces.
  • While a charge is being recorded the card opens that charge, so it now carries a History action for the list of past sessions.

Technical Context

Placement is plug-driven, not content-driven. statsPromoted reads only the raw battery readout via the new BatteryReadout.onCharger (plugged != 0, null → false), the same rule StatsCardPresentation.from uses — deliberately not status, because a device holding at its limit reports BATTERY_STATUS_NOT_CHARGING while still connected. It is also independent of the card's own state, so Promo/Loading/Unavailable are promoted too and the slot cannot shift under the user as the stats DB answers. This partially reverses the fixed-slot decision from #17; the single construction site stays (one lexical StatsDashboardCard(...), so the supported and unsupported branches cannot drift), only the placement is conditional.

Every dashboard item gained a stable LazyColumn key. Without keys a lazy list identifies items by index, so the stats card changing slot renumbers everything after it and discards their remembered state — plugging in mid-drag would have snapped the charge-alarm slider back to its persisted value. Keys are unique per render; the pairs that appear in both branches (full charge, reconnect, Shizuku banner) are mutually exclusive.

Navigation. With the settings row gone there is one entry point, so statsOrigin is deleted and both back paths — the top-bar action and the BackHandler branch — return to the dashboard. detailOrigin stays: the session detail is still reached from the dashboard card (live deep-link) and from the list.

Card contract. AmplyNavigationCard's KDoc claimed it must contain no interactive controls, which its own tested "Retry" button already contradicted. It now states the real contract: the surface owns the primary tap plus at most one small trailing text action that must not bubble — asserted for both History and Retry.

Review guidance for the tests. Bounds-ordering assertions run under @Config(qualifiers = "+h2400dp") so every compared card is composed; on the default screen a LazyColumn may not have composed the far card and a failure would mean "scrolled out", not "wrong order". Above-the-fold assertions deliberately stay at the real screen height, where the fold means something. A plug → unplug transition test drives the move through one live composition and asserts exactly one stats card after each step.

Not covered by automated tests: system-back from the statistics screen and its session detail (needs instrumentation) — on the manual list below. Play Store screenshots need no regeneration; their fixtures leave the battery readout unset, so those shots keep the tail placement.

Manual verification

Not yet run on hardware — planned pass: promoted placement plus tap-through to the live session; History → list; unplug → back to the tail; both back paths out of the statistics screen; adb shell dumpsys battery set ac 1 then set status 4 to confirm the plugged-but-not-charging case.

The battery-statistics card sat permanently at the tail of the dashboard,
so a live charge was several scrolls below the fold. It now claims the
second slot whenever external power is reported, and returns to the tail
when unplugged.

Promotion is plug-driven only: a device held at its limit reports
BATTERY_STATUS_NOT_CHARGING while still connected, so charge status must
not gate it. It is also independent of the card's content state — promo,
loading and unavailable are promoted too, so the slot can't shift under
the user while the stats DB answers. The promoted slot sits below the
interrupted-session warning and the access setup guide, which are rarer
and actionable.

The single "on the charger" rule moves to BatteryReadout.onCharger,
shared with the card's presentation mapping. The card keeps one lexical
construction site; only its placement is conditional. Every dashboard
item gains a stable LazyColumn key: index-keyed items would renumber when
the stats card moves and lose their remembered state — plugging in
mid-drag would have snapped the alarm slider back.

Statistics also lose their settings entry: the dashboard card is now the
only way in, so the capture switch lives next to the data it produces.
While a session is live the card's own tap deep-links into that session,
so the live state carries an explicit "History" action for the
past-sessions list; it must not bubble to the card's navigation, which is
asserted. With one entry point left, the stats screen's back paths
(top-bar and system) both return to the dashboard, so statsOrigin is gone.

AmplyNavigationCard's KDoc claimed it must hold no interactive controls,
which its own tested "Retry" button already contradicted; it now
describes the real contract (surface tap plus at most one small
non-bubbling text action).

Ordering assertions run at a tall Robolectric qualifier so every compared
card is composed — otherwise a failure would mean "scrolled out", not
"wrong order" — while above-the-fold assertions stay at the real screen
height. A live plug/unplug transition test covers the move itself.
@d4rken d4rken added the enhancement New feature or request label Jul 25, 2026
@d4rken
d4rken merged commit 01bafb0 into main Jul 25, 2026
12 checks passed
@d4rken
d4rken deleted the worktree-stats-card-promotion branch July 25, 2026 14:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant