-
released this
2026-07-31 23:38:11 -04:00 | 3 commits to main since this releasePer-day CalVer. Android-only — no server or web changes, no schema migrations.
mainCI green on0cea8298(lint + detekt + unit tests + signed-debug assemble, plus the image build). Merged via PR #114; closes issue #2327.The "Updating your mixes…" veil from v2026.07.14 was reported as "swipes on and off before the update completes in most cases", with "a number of other times where the contents will visibly update without the veil triggering." This is that, fixed at the root rather than re-tuned.
Most of the churn no longer happens at all
The veil was papering over a data-layer bug.
replaceSectionwas delete-then-insert, per section and un-transacted, so the observing Flow genuinely emittedemptyList()— a real, visible collapse — before the new ids landed, and did it seven times in sequence. Even unchanged tiles flickered.- One
@Transactionswap across all seven sections. Room notifies observers only on commit, so the empty gap is never observed and Home swaps in a single emission. (CachedQuarantineDaoalready carried this exact fix for this exact reason; Home never got it.) distinctUntilChangedon the id list ahead offlatMapLatest, so a section whose contents didn't move no longer tears down and rebuilds every tile's hydration flow.
The veil is now driven by the screen, not a stopwatch
Three separate reasons it used to lower early: the old
refresh().join() + 500msmeasured the network pull, which finishes long before the visible work (ids land → tiles hydrate → artwork loads); a plainisUpdatingBoolean cleared in afinallygot cleared by whichever of two overlapping refreshes finished first (reconnect and the 03:00 rebuild routinely arrive together); and failures were swallowed, so a failed pull reported success with no retry.It now raises, works (retrying behind the veil), then holds until the content has been still for a quiet window and nothing is still loading — with a floor so it can't flash and a hard ceiling so it can never strand you. The ceiling caps the veil, never the refresh.
It only appears when something actually changed
A refresh that returns what's already cached raises nothing, so a launch over a warm cache is immediate — no veil hiding an update that isn't happening.
Artwork no longer pops in after the veil lifts
Art was the most visible offender and the refresh coroutine can't see it, so the composition reports upward:
ServerImage— the single choke point behind every album, artist and playlist cover — counts its in-flight loads into a tracker the veil waits on. Art also crossfades app-wide now, with the placeholder fading out over the same window, which softens the pop everywhere the veil isn't involved.And it tells you when nothing changed
Because an unchanged refresh raises no veil, a pull that found nothing new would otherwise give no response at all. A pull now always produces exactly one piece of feedback: the veil if something changed, "Already up to date" if not, "Couldn't check for updates" if it couldn't reach the server. Only for refreshes you asked for — background checks stay silent rather than toasting on every launch.
Also veiled now: library-scan completion (Home never reacted to it before), playlist create/update/delete/tracks-changed, manual pull, and the initial load over a warm cache.
Install
Install the attached signed APK. Redeploying the server image is optional — it carries no changes in this release; it only matters for offering the new APK to other devices via in-app update.
Verify on device
This release is almost entirely about feel, which is the part CI cannot sign off:
- Open the app on a warm cache → content appears immediately. No veil, no sections collapsing and refilling.
- Pull to refresh with nothing new → "Already up to date".
- Pull to refresh after the 03:00 rebuild → the veil wipes on and holds until tiles and their artwork have landed, then wipes off. Nothing should pop in after it lifts.
- Pull with the server unreachable → "Couldn't check for updates" after it retries; your cached content stays put.
- First run / cleared cache → skeleton as before, no veil over an empty screen.
Known and deliberate
The background freshness sweeper still re-fetches stale metadata, so a single tile can change unannounced. Left unveiled on purpose — raising a full-screen panel for one tile would be worse than the pop, and the new crossfade softens it. Worth revisiting only if it's noticeable in use.
🤖 Generated with Claude Code
Downloads
- One