One notification per thing running, grouped, and an em dash between the two names

Two builds at once were two lines inside one notification; they are now
two notifications in one group, each with its own title and its own bar,
which is what the shade is for -- and what lets a component that
finishes take its own row down while its sibling carries on. Rows are
keyed by a tag (<key>/<component>) rather than an id, so an update
replaces the row it is about and two components cannot collide, and
`drawn` is the path out for one whose work is over.

A foreground service needs one notification that outlives every row, so
the service's own is the row itself while one thing is running and the
group's summary once there are more. Measured on API 36: a group of one
is collapsed to its header, which is the line of text with the bar left
out of it -- so grouping a single row would cost it the progress it had.
Verified on the emulator through all four states: one row with its
count, two grouped rows with a bar each, the fast one finishing and
leaving the other as a single row again, and everything gone when the
last build lands.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
iris-aiandClaude Opus 5 committed 2026-09-19 20:30:35 -04:00
1 parent bb65526230
commit ded6df559d
4 files changed
+147 -70

No files matched your search

+20 -8
View File
@@ -865,14 +865,26 @@ mutable at runtime from the phone.
The words are shared rather than written twice: `componentWorkLine` and
`buildLine` are read by the card's own bars and by the notification, for
the reason the note about two words for one measurement gives.
Three things measured on API 36 rather than assumed. **The collapsed row
drops the content text the moment there is a progress bar**, so with one
thing running the title carries both the component and what is happening
to it (`Test Tablet / tablet: building 14/30`) and nothing is set
beside it, which expanded would be the same words twice. **Several at
once get an indeterminate bar** and a line each in the expanded view:
there is no honest single number for two builds, and averaging them
draws something that moves like a measurement without being one.
**There is one notification per thing running, not one for all of
them**, grouped so they arrive together -- which is what the shade is
for, and what lets a component that finishes take its own row down while
its sibling carries on. Rows are keyed by a *tag* (`<key>/<component>`)
rather than by an id, so an update replaces the row it is about and two
components cannot collide; `drawn` is the path out, since nothing
removes a row by itself and one left behind would sit there reporting a
build that is over.
The foreground service needs one notification that outlives every row,
so **the service's own notification is the row itself while one thing is
running, and the group's summary once there are more.** Measured on API
36: a group of one is collapsed to its header, which is the line of text
with the bar left out of it -- so grouping a single row costs it its
progress. Measured there too: **a collapsed row drops the content text
the moment there is a bar to draw**, which is why a row's title carries
both the component and what is happening to it (`Test Tablet — tablet:
building 14/40`) with nothing set beside it, that being the same words
twice once expanded. The summary draws no bar at all, because the only
number it could show is an average of the rows' and that is nobody's
measurement.
**An app may only start a foreground service while it is in front of
somebody**, which is ordinarily where this one is -- work begins with a
button, and the service outlives the press; everything after the start