chore(release): v0.11.6
🏗️ Build and Test JellyTau / Run Tests (push) Skipped
🏗️ Build and Test JellyTau / Android Compile Check (push) Skipped
Build & Release / Create Release (push) Blocked by required conditions
🏗️ Build and Test JellyTau / Supply Chain (push) Successful in 4m4s
📱 Test APK / Build test APK (push) Successful in 48m6s
Publish Documentation / Build & publish docs to gitea-pages (push) Successful in 9m17s
Traceability Validation / Check Requirement Traces (push) Successful in 20s
Build & Release / Run Tests (push) Successful in 22m27s
Build & Release / Build Android (push) Waiting to run
Build & Release / Build Linux (push) Successful in 31m18s
Build & Release / Build Windows (push) In progress
🏗️ Build and Test JellyTau / Run Tests (push) Skipped
🏗️ Build and Test JellyTau / Android Compile Check (push) Skipped
Build & Release / Create Release (push) Blocked by required conditions
🏗️ Build and Test JellyTau / Supply Chain (push) Successful in 4m4s
📱 Test APK / Build test APK (push) Successful in 48m6s
Publish Documentation / Build & publish docs to gitea-pages (push) Successful in 9m17s
Traceability Validation / Check Requirement Traces (push) Successful in 20s
Build & Release / Run Tests (push) Successful in 22m27s
Build & Release / Build Android (push) Waiting to run
Build & Release / Build Linux (push) Successful in 31m18s
Build & Release / Build Windows (push) In progress
Seven fixes from an audit of the stack's most fragile seams, each with a test that fails without it. Two could take the app out entirely: an interrupted database migration left it unable to launch at all, and an unguarded panic at the Android JNI boundary aborted the process outright. Frontend gates (bun run test/check/lint/format:check) were not run for this release — node on the release machine is missing libada.so.3 and exits 127. All changes are under src-tauri/; CI runs those gates.
This commit is contained in:
@@ -9,6 +9,84 @@ generated trace matrix lives in [docs/traceability.md](docs/traceability.md).
|
||||
For how long each fixed defect had been shipping before it was found, see
|
||||
[docs/defect-windows.md](docs/defect-windows.md).
|
||||
|
||||
## v0.11.6
|
||||
|
||||
Found by an audit of the stack's most fragile seams rather than by hitting them,
|
||||
so most of these are faults that had not yet been reported — several could only
|
||||
be reached on a bad day, and the worst of them only once.
|
||||
|
||||
### 🐛 Fixes
|
||||
|
||||
- **An interrupted update can no longer stop the app from ever opening again.**
|
||||
Changes to the local database were applied one statement at a time with no way
|
||||
to undo a half-finished one. If an update was interrupted partway — a full
|
||||
disk, the phone reclaiming memory, the app being killed mid-launch — the
|
||||
earlier statements stuck while nothing recorded that the change had happened.
|
||||
On the next launch it started again from the beginning, immediately hit the
|
||||
part that was already done, and gave up; and since the app treats a database
|
||||
it cannot prepare as fatal, it stopped opening at all, on every launch, with
|
||||
the only way out being to clear its data and lose downloads and sign-ins. Each
|
||||
change is now all-or-nothing, so an interrupted one leaves no trace and the
|
||||
next launch simply tries again. (UR-002 → DR-012)
|
||||
|
||||
- **The app no longer vanishes without trace when the player hits trouble.**
|
||||
The parts of the Android player that report back into the app — position,
|
||||
state changes, errors, the end of a track — had no protection around them, and
|
||||
a failure inside one killed the whole app instantly: no error, no message, not
|
||||
even a crash report worth sending. One such failure was reachable in ordinary
|
||||
use, on the position report that fires four times a second: under memory
|
||||
pressure the app could fail to build the small worker it needs to send that
|
||||
report, and that alone was enough to take everything down. A dropped position
|
||||
report is now just a dropped position report. (UR-005 → DR-052)
|
||||
|
||||
- **One internal failure no longer disables the whole app until it is restarted.**
|
||||
Every part of the app that reads or writes local data shares a single gate to
|
||||
it. If anything failed while holding that gate, the gate stayed jammed: from
|
||||
then on every library page, download, setting and sign-in returned an error for
|
||||
the rest of the session, and only quitting and reopening cleared it. The gate
|
||||
now recovers instead of jamming. (UR-002 → DR-012)
|
||||
|
||||
- **Browsing offline no longer reports a network error over content already on
|
||||
the device.** A read of local data was given a tenth of a second to answer and
|
||||
otherwise abandoned and treated as "nothing stored". That is easily exceeded
|
||||
on phone storage whenever something else is writing — a sync catching up, a
|
||||
batch of artwork being saved — and offline, where there is no server to fall
|
||||
back to, the result was a network error shown over a library that was sitting
|
||||
on disk. Worse, the abandoned read kept running and kept the storage busy,
|
||||
making the next one slower still. A slow read is now waited for rather than
|
||||
thrown away, and a fast one still answers immediately as before. (UR-002 →
|
||||
DR-013)
|
||||
|
||||
- **A download that arrived empty is no longer presented as ready to play.** If
|
||||
the server answered a download with nothing at all — an error page, a
|
||||
conversion that produced no output — the empty file was moved into place and
|
||||
the item was marked available offline. Opening it then hung: the app's own
|
||||
media server promised one byte of it and sent none, so the player waited
|
||||
forever with nothing on screen to say why. An empty download is now treated as
|
||||
the failure it is, keeping the partial file so it can resume, and a request for
|
||||
an empty file gets an honest refusal instead of a promise. (UR-019, UR-071 →
|
||||
DR-168, DR-137)
|
||||
|
||||
- **Renaming your computer no longer signs you out.** On systems without a
|
||||
password manager, sign-in tokens are kept in a file whose key was rebuilt from
|
||||
the machine's name and the current username each time the app started. Rename
|
||||
the machine, or launch it from somewhere the username is not set, and the key
|
||||
came out different, the file could no longer be read, and the app treated that
|
||||
as never having been signed in — with nothing shown to explain it. The key is
|
||||
now made once, kept, and unaffected by what the machine is called. Existing
|
||||
saved sign-ins are carried over automatically. This file has never been a
|
||||
substitute for a real password manager, and the app now says so plainly rather
|
||||
than implying otherwise. (UR-012 → IR-014)
|
||||
|
||||
- **The player's internal locking is now checked rather than merely careful.**
|
||||
The playback controller coordinates seventeen separate pieces of shared state
|
||||
across the audio engine, the lock screen, timers and every screen in the app.
|
||||
Nothing stopped two of them being taken in opposite orders by different parts
|
||||
of the code, which freezes playback outright with no error anywhere — a fault
|
||||
this part of the app has produced before. The correct order is now written down
|
||||
and enforced automatically, so a future change cannot quietly reintroduce it.
|
||||
No such fault existed; this keeps it that way. (UR-005 → DR-052)
|
||||
|
||||
## v0.11.5
|
||||
|
||||
### 🐛 Fixes
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jellytau",
|
||||
"version": "0.11.5",
|
||||
"version": "0.11.6",
|
||||
"description": "A cross-platform Jellyfin client built with Tauri, SvelteKit and Rust.",
|
||||
"author": "Duncan Tourolle <duncan@tourolle.paris>",
|
||||
"license": "MIT",
|
||||
|
||||
Generated
+1
-1
@@ -2209,7 +2209,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "jellytau"
|
||||
version = "0.11.5"
|
||||
version = "0.11.6"
|
||||
dependencies = [
|
||||
"aes-gcm",
|
||||
"argon2",
|
||||
|
||||
@@ -4,7 +4,7 @@ name = "jellytau"
|
||||
# `player-conformance`, and a second binary makes a bare `cargo run` —
|
||||
# which `tauri dev` issues — ambiguous.
|
||||
default-run = "jellytau"
|
||||
version = "0.11.5"
|
||||
version = "0.11.6"
|
||||
description = "A cross-platform Jellyfin client"
|
||||
authors = ["Duncan Tourolle <duncan@tourolle.paris>"]
|
||||
license = "MIT"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "JellyTau",
|
||||
"version": "0.11.5",
|
||||
"version": "0.11.6",
|
||||
"identifier": "com.dtourolle.jellytau",
|
||||
"build": {
|
||||
"beforeDevCommand": "bun run dev",
|
||||
|
||||
Reference in New Issue
Block a user