Withhold a component's freshness while it is being built

Nothing re-reads the manifest during a run, so the "out of date" note
beside a running progress bar is the answer from before the button was
pressed -- shown for the length of a build, next to the work that is
making it wrong.

The card now reads a busy component's freshness as unknown, in the one
place the list of components is built for the cards, so the row's note
and the sibling-mismatch warning both go quiet. Same condition as the
one that disables the Update button.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
irisandClaude Opus 5 committed 2026-09-01 10:09:29 -04:00
1 parent aa8e2b97a5
commit c35f84a373
2 files changed
+40 -5

No files matched your search

+15
View File
@@ -494,6 +494,21 @@ mutable at runtime from the phone.
the Retry that acts on it, in the one place that reports that
component's failures whether they came from a build, a download or a
service action.
- **A card being worked on has no freshness, rather than the one from
before the press.** Nothing re-reads the manifest during a run -- the
entry was fetched before the button was pressed and read again only
once the run is over -- so "out of date" drawn beside the bar that is
making it current is last minute's answer wearing this minute's
clothes. `UpdaterScreen` therefore maps a busy component's `freshness`
to `unknown` in the one place the component list is built for the
cards, which is what makes both readers of it -- the row's own note and
`MismatchedPairNote` -- go quiet without either having to know why. The
condition is deliberately the same pair that disables the Update button
(`projectState.busy || componentState.busy`): what cannot be acted on
is exactly what cannot be measured just now. It comes back the instant
the run ends, still saying "out of date" if the build failed, because
by then the entry has been read again -- withheld is not the same as
cleared.
- **A project's own `.dev-updater.ron` is a request, never an
instruction.** It only runs once accepted from the phone, which copies
it into `config.ron`; `AppEntry::pending_declaration` is the whole gate.
@@ -1580,9 +1580,30 @@ private fun AppCard(
// order is the *build* order -- dev-updater builds its
// server before its APK on purpose -- and that stays as
// it is; this sort is stable, so anything else keeps it.
//
// Freshness is withheld from a component being worked
// on, because it is the one thing on the card that the
// work is *about* and nothing re-reads it while the
// work runs: the entry was fetched before the button
// was pressed and is read again only once the run is
// over. So "out of date" beside the bar that is making
// it current is not a measurement, it is the answer
// from before the press -- and unknown is what this
// card already says when it has no reading, so both
// readers of it (the row's own note, and the sibling
// warning) go quiet without either having to know why.
// Deliberately the same pair of conditions that
// disables the Update button: what cannot be acted on
// is exactly what cannot be measured just now.
val components =
entry.components
.sortedBy { it.isServer }
.forEach { component ->
.map { component ->
if (projectState.busy || componentStates[component.name].busy)
component.copy(freshness = "unknown")
else component
}
components.forEach { component ->
val installed = installedTimes[component.name]
val installedSize = installedSizes[component.name]
val chosenVariantPath = chosenVariants[component.name]
@@ -1590,9 +1611,8 @@ private fun AppCard(
// reach for a sibling's by accident.
val componentState = componentStates[component.name]
val upToDate =
component.apk?.let {
isUpToDate(it, installed, chosenVariantPath)
} == true
component.apk?.let { isUpToDate(it, installed, chosenVariantPath) } ==
true
ComponentCard(
entryKey = entry.key,
component = component,
@@ -1642,7 +1662,7 @@ private fun AppCard(
// qualifies what pressing it gets you.
MismatchedPairNote(
self = component,
others = entry.components,
others = components,
)
// The button that asked for it, then
// how far along it is: a bar reports on