Skip to content

fix: 0.5.1 — liked songs, sign-in errors and desktop release tooling - #11

Merged
Nxssie merged 6 commits into
mainfrom
fix/0.5.1
Sep 11, 2026
Merged

Nxssie merged 6 commits into
mainfrom
fix/0.5.1

Conversation

@Nxssie

@Nxssie Nxssie commented Sep 11, 2026

Copy link
Copy Markdown
Owner

The 0.5.1 batch.

Library fetches (the reported bug — three separate causes, same symptom)

  • fetchPlaylistTracks read the access token without refreshing it, so an expired one answered 401 on every page and the liked songs came back empty — while any search (which does refresh) made the next attempt work.
  • runCatching also catches CancellationException, so switching between the inner tabs while the fetch was in flight cancelled it and stored emptyList() as data; the songs == null guard then blocked any retry, which is why it stayed empty until the whole screen was rebuilt (bottom-tab switch) and never healed on its own. Pagination made that fetch long enough for this to happen often. Cancellation now propagates (runCatchingExceptCancellation); only real failures reach the UI, with the reason and a retry;.
  • A page that never loaded, and an enrichment that could not verify a track, now raise instead of returning an empty list: "nothing is liked" and "the request failed" were indistinguishable.

Sign-in copy

  • The accounts dialog printed the raw exception, so a Private DNS resolver that stopped answering surfaced as Unable to resolve host "oauth2.googleapis.com": …. Connection failures now read no_dns; / timeout; / no_connection; / tls_error; with the host that failed, in both apps.

Release tooling

  • desktop/build.gradle.kts still said 0.4.0, so the CI packages for this release would carry the previous version while the APK reports the tag.
  • scripts/attach-desktop-release.sh (+ mise run desktop:release) publishes the CI-built .deb/.msi/.dmg for a tag, matched on the tagged commit, with DRY_RUN=1 to inspect first.

- The accounts dialog printed the raw exception, so a Private DNS resolver
  that stopped answering surfaced as "Unable to resolve host
  oauth2.googleapis.com: No address associated with hostname" — accurate and
  useless. The three connection failures that a user can act on now read as
  `no_dns;`, `timeout;` and `no_connection;`, and the host that failed is
  named.
- The cause chain is walked because OkHttp and coroutines hand the UI a
  wrapper, and anything unrecognised keeps its own message: an OAuth
  error_description is more specific than anything generic.
- `fetchPlaylistTracks` read the access token without refreshing it, so an
  expired one answered 401 on every page and the liked songs came back empty.
  The other listings already called ensureValidToken, which is why leaving the
  tab and coming back sometimes filled it in: something else had refreshed the
  token in the meantime.
- A page that never loaded, and an enrichment that could not verify a track,
  now raise instead of returning an empty list. "No liked songs" and "the
  request failed" are not the same thing, and only one of them is true.
- Both screens stored `runCatching { … }.getOrDefault(emptyList())` and then
  guarded the fetch on that list being null, so a failure was cached as data:
  "no liked songs" and "the request never arrived" rendered identically and
  nothing retried until the tab was rebuilt.
- A failure now leaves the list null and shows the reason with a retry, which
  is also what makes the automatic retry on re-entering the tab work.
- It still said 0.4.0, so the packages the CI builds for this release would
  have carried the previous version (the dry run against the v0.5.0 run lists
  `wren_0.4.0_amd64.deb`, `Wren-0.4.0.msi`, `Wren-0.4.0.dmg`) while the APK
  reports 0.5.0 from the tag.
- The .deb, .msi and .dmg are the one thing this machine cannot build (they
  need Windows and macOS), and the CI already builds all three for every push
  to main — so publishing them is a fetch of the run for the tagged commit,
  still by hand, with no workflow change.
- The run is matched on the commit the tag points at, so what gets published
  can always be traced to a revision; `DRY_RUN=1` downloads and lists without
  uploading.
- `--jq`, not `--template`, to read the run id: a Go template renders it as
  3.4576914953e+10 and the download 404s.
- `runCatching` catches CancellationException too, so leaving the tab while a
  fetch was in flight became a result: before, an empty library cached as
  data — which is how the liked songs went missing, since pagination made that
  fetch long enough to be interrupted — and now, the message "The coroutine
  scope left the composition" shown as a network error.
- Cancellation propagates from `runCatchingExceptCancellation`; only real
  failures reach the UI, in the library screens of both apps and the discover
  screen that caches its sections the same way.
@Nxssie
Nxssie merged commit 981f52b into main Sep 11, 2026
5 checks passed
@Nxssie
Nxssie deleted the fix/0.5.1 branch September 11, 2026 09:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant