Files
kadence/android/app
timka123andClaude Opus 5 71a0389029 android: a command's reply is the answer, not a conflict
Half of "the buttons do nothing" happens with the network working perfectly.

`command()` passed `PendingOps(hasAny = true, …)` into `applyServer`, and
`PendingOps` is the *outbox's* vocabulary — it means "something of ours is
queued and has not landed". For a direct reply that is simply untrue, and
because the reply is for the interval already running, `reconcile` answered
`KeepOptimistic` and `applyServer` returned early, discarding the server's
status, remaining and planned seconds. Pause, resume, +5 min, Interrupted and
attach-task therefore changed nothing until the next poll, up to ten seconds
later. `toggle()` read the stale state, so the second tap fired another pause.

Two changes. `KeepOptimistic` now short-circuits only for *polls* — a poll
racing a queued intent is a real conflict and still keeps the dial still. And
the commands whose effect is knowable without asking apply it on the tap, then
let the server's reply overwrite it: paused, resumed, extendedBy, one more
interruption. Three small extension functions, deliberately a preview of the
server's answer rather than a second implementation of the timer.

`toggle()` returns its Job now, so the Glyph toy's long press, the Live Update's
buttons and the tests can all wait for the reply.

5 tests, on MockWebServer and the committed fixtures. The first of them fails
on the old code in the obvious way: the reply says paused, the UI says running.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-22 17:35:46 +03:00
..