• v0.7.0 73641e192c

    JellyTau v0.7.0
    Publish Documentation / Build & publish docs to gitea-pages (push) Canceled after 0s
    🏗️ Build and Test JellyTau / Run Tests (push) Successful in 21m50s
    Traceability Validation / Check Requirement Traces (push) Successful in 44s
    🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 10m50s
    Build & Release / Run Tests (push) Successful in 18m46s
    Build & Release / Build Linux (push) Successful in 30m52s
    Build & Release / Build Windows (push) Successful in 15m13s
    Build & Release / Build Android (push) Successful in 31m53s
    Build & Release / Create Release (push) Successful in 12s
    Stable

    dtourolle released this 2026-08-16 20:28:16 +00:00 | 173 commits to master since this release

    ✨ Changes

    • Native Android video is now the default. Video decodes on the device's
      hardware decoder instead of the built-in web player, which is easier on the
      battery and lets picture-in-picture show the video rather than the app. The
      default had been held back deliberately since the picture defects were fixed,
      because returning from background audio left playback dead on that path; both
      blockers below are fixed and verified on a device, which is the standard this
      default has been held to since it last shipped early. The Settings toggle
      remains, now as the fallback to the web player, and an explicit choice still
      wins in both directions — anyone who turned it off keeps it off.
      (UR-003, UR-004 → DR-188)

    🐛 Fixes

    • The letterbox bars stop showing things that are no longer there. With
      native video on, the padding around the picture kept whatever had last been
      drawn in it: the previous frame flashing on rotation, a ghost copy of the
      control bar stranded at the top of the screen, each new clock digit drawn over
      the one before it, and the sleep-timer and quality menus leaving their imprint
      after closing. One cause under all of it — nothing painted those bars. The
      window surface is opaque, and for an opaque surface Android's renderer skips
      clearing the damaged region and assumes the view hierarchy covers every pixel;
      the video view covers only the letterboxed rect, so the bars were the window
      background's alone to paint, and enabling compositing had cleared that
      background to transparent. Three earlier attempts missed because they aimed at
      the window's rotation animation and at video-frame retention — which is also
      why the artefact reproduced standing still, with no rotation involved.
      (UR-003, UR-066 → DR-194)

    • Returning from background audio brings the picture back. On the native
      path, coming back from the lockscreen left a black screen: a play overlay
      pinned at 0:00 and a play button that did nothing. Nothing had crashed — the
      transition was simply dropped. The two render paths resume by different means,
      and only one of them was performed: the web player reloads from its stream URL,
      while the native player owns no element and nothing watches that URL on its
      behalf, so it has to be handed the item again explicitly. It now is, at the
      position the audio reached. (UR-040, UR-003 → DR-196)

    • Next Up stops repeating what Continue Watching already shows. The same
      episode could occupy both home rows at once. (UR-023 → DR-197)

    Downloads

    Platform File
    Android jellytau-release.apk — sideload or adb install
    Windows (portable) jellytau.exe
    Linux (Debian/Ubuntu) jellytau_0.7.0_amd64.deb — sudo dpkg -i
    Windows jellytau_0.7.0_x64-setup.exe (NSIS installer)

    Report a problem: https://gitea.tourolle.paris/dtourolle/jellytau/issues

    Downloads
  • v0.6.0 8e98e1c37a

    JellyTau v0.6.0
    🏗️ Build and Test JellyTau / Run Tests (push) Successful in 22m57s
    Publish Documentation / Build & publish docs to gitea-pages (push) Successful in 5m50s
    Traceability Validation / Check Requirement Traces (push) Successful in 24s
    Build & Release / Run Tests (push) Successful in 7m21s
    🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 10m3s
    Build & Release / Build Linux (push) Successful in 20m32s
    Build & Release / Build Windows (push) Successful in 14m29s
    Build & Release / Build Android (push) Successful in 31m5s
    Build & Release / Create Release (push) Successful in 12s
    Stable

    dtourolle released this 2026-08-16 19:24:34 +00:00 | 179 commits to master since this release

    🐛 Fixes

    • Android native video actually shows a picture. It shipped once as audio
      with no picture
      and was reverted with the compositing named as the suspect
      (DR-172). The compositing was not at fault; five independent defects sat
      between ExoPlayer and the screen, each able to produce that symptom alone. The
      app shell painted over the video surface through a CSS rule targeting
      [data-app-shell], an attribute no component had ever set in any commit
      (DR-185). The poster/title card had no way to lift on a path that renders no
      <video> element, so a black card covered the surface for the whole session
      (DR-182). The JavaScript bridges were installed by a 500 ms tree walk that
      raced the page load — and lost permanently when it lost, because the
      re-injection guard then declined to retry — so setTransparent(true) could
      never arrive (DR-183). The SurfaceView was never detached, leaking one per
      video and leaving picture-in-picture's gate stuck open (DR-184). Verified on a
      device: logcat now carries WebView transparent = true and
      Marking media ready with video on screen, the pair the original
      investigation went looking for and could not find.
      (UR-003, UR-004, UR-041 → DR-182, DR-183, DR-184, DR-185)

    • Play and pause reach the player that is actually rendering. Transport did
      nothing on the native video path — from the on-screen tap, from the control
      bar, and from a direct command invocation — while seek and skip kept working,
      because those decide elsewhere. Rust routes play/pause to the webview <video>
      whenever it believes one is active, and the player route mirrored element state
      into that belief unconditionally, including from a ten-second progress
      interval. So on the native path the frontend re-declared every ten seconds that
      an element was playing when none existed, and every intent was emitted at
      something that was not there. The mirror now lives where useHtml5Element is
      known. This also explains the flashing transport controls, since they key off
      the play state that was being contradicted on every tick.
      (UR-005, UR-003 → DR-193, DR-195)

    • The player's controls hide themselves on a touchscreen. The auto-hide timer
      was armed only from mousemove, which a touch device never fires, so the
      control bar stayed over the video for the whole film. It is now armed on entry
      and on every touch, and pinned open while paused, seeking, or with a menu open.
      (UR-003, UR-066 → DR-189)

    • The system bars go away with the player. Immersive mode had exactly one
      caller — the fullscreen button — so opening a video left the status and
      navigation bars painted over it until the user pressed a control most never
      press. (UR-066, UR-003 → DR-187)

    🔬 Internal

    • Native video presents through a TextureView rather than a SurfaceView. A
      SurfaceView renders on its own layer outside the app window and punches a
      transparent region through it, and Android's own graphics documentation warns
      that overlays do not composite reliably above one. (UR-003, UR-004 → DR-192)

    • Native Android video remains opt-in, and is not yet the default. Turning it
      on surfaced a further unverified path: returning from background audio is
      implemented only for the webview element, so playback stays dead on the native
      path (DR-190, proposed). Rotation still needs device confirmation (DR-194).
      (UR-003 → DR-188)

    Downloads

    Platform File
    Android jellytau-release.apk — sideload or adb install
    Windows (portable) jellytau.exe
    Linux (Debian/Ubuntu) jellytau_0.6.0_amd64.deb — sudo dpkg -i
    Windows jellytau_0.6.0_x64-setup.exe (NSIS installer)

    Report a problem: https://gitea.tourolle.paris/dtourolle/jellytau/issues

    Downloads
  • v0.5.2 50934e2ac6

    JellyTau v0.5.2
    🏗️ Build and Test JellyTau / Run Tests (push) Successful in 10m7s
    Publish Documentation / Build & publish docs to gitea-pages (push) Successful in 5m28s
    Traceability Validation / Check Requirement Traces (push) Successful in 19s
    Build & Release / Run Tests (push) Successful in 7m35s
    🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 3m2s
    Build & Release / Build Linux (push) Successful in 20m0s
    Build & Release / Build Windows (push) Successful in 8m36s
    Build & Release / Build Android (push) Successful in 30m30s
    Build & Release / Create Release (push) Successful in 21s
    Stable

    dtourolle released this 2026-08-13 05:48:01 +00:00 | 217 commits to master since this release

    🔧 Internal

    • Gradle ships in the builder image instead of being downloaded per build.
      The release APK job died at the Gradle wrapper step after the 11-minute Rust
      compile had already succeeded, on a socket exception mid-transfer.
      tauri android init regenerates a wrapper pointing at services.gradle.org, so
      every Android job re-downloaded ~130MB — slow on a good day, a hard build
      failure when the CDN drops the connection, and a standing violation of the rule
      that every build tool already lives in the image. The sync script now repoints
      the regenerated wrapper at the local distribution, parsing the version the
      wrapper actually requests so a future Tauri bump logs a miss instead of pointing
      at a missing file. Dev machines are untouched.

    Downloads

    Platform File
    Android jellytau-release.apk — sideload or adb install
    Windows (portable) jellytau.exe
    Linux (Debian/Ubuntu) jellytau_0.5.2_amd64.deb — sudo dpkg -i
    Windows jellytau_0.5.2_x64-setup.exe (NSIS installer)

    Report a problem: https://gitea.tourolle.paris/dtourolle/jellytau/issues

    Downloads
  • v0.5.0 3619f71aba

    JellyTau v0.5.0
    🏗️ Build and Test JellyTau / Run Tests (push) Successful in 6m55s
    Publish Documentation / Build & publish docs to gitea-pages (push) Successful in 5m21s
    Traceability Validation / Check Requirement Traces (push) Successful in 15s
    Build & Release / Run Tests (push) Successful in 7m36s
    🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 2m57s
    Build & Release / Build Linux (push) Successful in 20m4s
    Build & Release / Build Windows (push) Successful in 8m42s
    Build & Release / Build Android (push) Successful in 30m30s
    Build & Release / Create Release (push) Successful in 17s
    Stable

    dtourolle released this 2026-08-11 19:22:21 +00:00 | 229 commits to master since this release

    ✨ Features

    • Android video can render on the device's own video surface. Settings →
      Video Playback → Native Video (experimental, off by default) hands
      decoding to ExoPlayer, which draws into a surface composited behind a
      transparent WebView, with the player controls layered on top of it.

      The backend had reported "this platform has a native video surface" on Android
      all along, but the frontend threw that answer away in two separate places, so
      the path had never actually run. Both are lifted. The setting can only ever
      suppress the backend's choice, never override it upward: turning it off
      forces the web player even where native is available, and turning it on does
      nothing on platforms whose backend never offered it — Linux cannot composite
      behind its webview, so it stays on the web player either way.

      Verified playing on a physical device. Still unverified: the mini-player
      transition, audio-track switching on the native path, and whether hardware
      decoding measurably improves battery or CPU — so the toggle stays off by
      default. (UR-003, UR-004 → DR-150)

    🐛 Fixes

    • The video surface now reaches the screen at all. The player built its
      video surface, handed it to ExoPlayer, and then never added it to the view
      hierarchy, because the Activity reference it needed was never supplied — so
      native video would have decoded to a surface nobody could see, whatever else
      was fixed. This also silently disabled picture-in-picture for video, which
      gated on that same never-attached surface. (UR-003, UR-041 → DR-151)

    • Platform playback support is no longer guessed from the browser user
      agent.
      The frontend re-derived "does this platform decode audio natively" by
      string-matching navigator.userAgent — a second copy of a decision the
      backend already makes, free to drift out of step with the backends it was
      describing. The backend now reports its own capabilities and the frontend
      consumes them. (UR-003, UR-005 → DR-152)

    🔧 Internal

    • The git tag is now the single source of truth for a release version. The
      version lived in four files that had to be edited in lockstep, and the release
      workflow rewrote exactly one of them — so a tagged build produced an installer
      named for the tag wrapped around package metadata naming the previous
      release, and the Linux job, which had no version step at all, shipped whatever
      happened to be committed. scripts/set-version.sh now writes all four from
      one argument and every release job calls it with the tag. The Android
      versionCode is derived in the same place, guarded by tests for the property
      that actually matters: it must increase monotonically and stay above the value
      already installed in the field, or Android silently refuses the update.
      (DR-153)

    Downloads

    Platform File
    Android jellytau-release.apk — sideload or adb install
    Windows (portable) jellytau.exe
    Linux (Debian/Ubuntu) jellytau_0.5.0_amd64.deb — sudo dpkg -i
    Windows jellytau_0.5.0_x64-setup.exe (NSIS installer)

    Report a problem: https://gitea.tourolle.paris/dtourolle/jellytau/issues

    Downloads
  • v0.4.8 07d10dfed7

    JellyTau v0.4.8
    🏗️ Build and Test JellyTau / Run Tests (push) Successful in 19m31s
    Publish Documentation / Build & publish docs to gitea-pages (push) Successful in 5m28s
    Traceability Validation / Check Requirement Traces (push) Successful in 22s
    Build & Release / Run Tests (push) Successful in 6m47s
    🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 10m6s
    Build & Release / Build Linux (push) Successful in 19m57s
    Build & Release / Build Windows (push) Successful in 14m14s
    Build & Release / Build Android (push) Successful in 30m26s
    Build & Release / Create Release (push) Successful in 19s
    Stable

    dtourolle released this 2026-08-11 18:11:42 +00:00 | 235 commits to master since this release

    🐛 Fixes

    • Video with an undecodable soundtrack now transcodes instead of playing
      silent.
      Advertising a webview-shaped profile (v0.4.7) turned out not to be
      enough: Jellyfin 10.11.5 enforces a direct-play profile's container and video
      codec but ignores its audio codec, offering an E-AC-3 track for direct play
      against a profile listing only AAC — and no CodecProfile or channel limit
      changes that. The client now checks the track it would actually be served
      against what its renderer can decode and forces the h264/AAC HLS transcode
      when it cannot, rather than trusting the negotiation.
      (UR-004 → DR-149)

    Downloads

    Platform File
    Android jellytau-release.apk — sideload or adb install
    Windows (portable) jellytau.exe
    Linux (Debian/Ubuntu) jellytau_0.4.8_amd64.deb — sudo dpkg -i
    Windows jellytau_0.4.8_x64-setup.exe (NSIS installer)

    Report a problem: https://gitea.tourolle.paris/dtourolle/jellytau/issues

    Downloads
  • v0.4.6 1b70926c36

    JellyTau v0.4.6
    🏗️ Build and Test JellyTau / Run Tests (push) Successful in 20m34s
    Publish Documentation / Build & publish docs to gitea-pages (push) Successful in 6m6s
    Traceability Validation / Check Requirement Traces (push) Successful in 18s
    Build & Release / Run Tests (push) Successful in 20m26s
    🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 10m3s
    Build & Release / Build Linux (push) Successful in 37m59s
    Build & Release / Build Windows (push) Successful in 23m0s
    Build & Release / Build Android (push) Successful in 40m26s
    Build & Release / Create Release (push) Successful in 1m20s
    Stable

    dtourolle released this 2026-08-09 14:38:47 +00:00 | 240 commits to master since this release

    ✨ Features

    • Downloaded video plays offline. Four separate defects each stopped it on
      their own. A completed download's file_path is already absolute — the worker
      rewrites it on completion — but the player rooted it a second time and handed
      the webview /data/user/0/app//data/user/0/app/videos/x.mp4; audio was
      unaffected because it resolves the same column through Rust, which is why this
      read as a video-only fault (DR-133). The asset protocol was never enabled at
      all: convertFileSrc rewrites a path to asset.localhost unconditionally, but
      Tauri only answers that origin when the cargo feature and the config are both
      present, and neither was — which also silently defeated the cached-thumbnail
      path, whose soft fallback to the server copy hid the breakage whenever the
      server was reachable (DR-134). Tauri's asset protocol then answers a range-less
      request by reading the whole file into memory and only advertises
      Accept-Ranges from inside its range branch, so the first request never learns
      ranges exist and Chromium gave up after ~31s; local media now comes from a
      loopback HTTP server streaming bounded 4 MiB chunks, confined by a per-session
      token and to the app data directory, because loopback is shared between apps on
      Android (DR-137). And release builds set usesCleartextTraffic=false, so
      Android rejected the request before any I/O — a network-security config now
      exempts 127.0.0.1 only, and a remote server must still be HTTPS (DR-138).

      Known limitation: a download taken at original quality is a byte copy, so it
      can be any container — an AVI holding XVID is served correctly and refused by
      the webview regardless.

    🐛 Fixes

    • A video queued from a media card no longer downloads as audio.
      download_item never recorded media_type, and the reconnect resolver read
      that NULL as 'audio', so a movie's URL was resolved by the audio builder and
      completed as an audio-only transcode. The item's own type now decides, and rows
      already downloaded that way are requeued on reconnect — prevention alone leaves
      them reading "downloaded" and still unplayable. (DR-135, DR-136)

    • Some videos no longer play with no sound. Jellyfin's MediaStream.Index is
      global across every stream in a media source, so index 0 is the video stream on
      virtually all files — and AudioStreamIndex=0 was sent as "the first audio
      track" on the HLS transcode URL, the background-audio handoff URL, the
      direct-play fallback and the negotiation body, asking the server to use the
      video stream as audio. Servers that honour it produce a picture with no sound;
      only those that silently correct the index hid it, which is why it surfaced as
      "some videos have no audio". The parameter is now omitted unless a track was
      actually chosen. (DR-140)

    • A multichannel track is no longer direct-played to a two-channel sink.
      MediaCodecList answers "can this device decode 5.1", which is not the question
      that decides whether anything is audible: a phone decodes AC-3 5.1 happily and
      still has two channels to play it out of. The profile carried no
      MaxAudioChannels, so the server was free to hand over the multichannel track —
      silence, or dialogue folded into surround channels that go nowhere. The route's
      actual channel count now bounds the profile; no codec is ever removed, so a
      device with genuine surround output keeps direct-playing it. (DR-141)

    • Video waits for audio focus instead of rolling silently. Video manages focus
      by hand, and all three outcomes of the request were treated as success —
      including REQUEST_DELAYED, which means the system is withholding our audio
      until it calls back. The picture rolled with no sound, indistinguishable from a
      broken stream. (DR-145)

    • The no-audio fallback picks a track the device can decode. When ExoPlayer
      selected no audio track, recovery forced group 0 / track 0 unconditionally — but
      the most likely reason nothing was selected is that this very track cannot be
      decoded here, so the override reinstated the silence it was meant to fix.
      (DR-146)

    Downloads

    Platform File
    Android jellytau-release.apk — sideload or adb install
    Windows (portable) jellytau.exe
    Linux (Debian/Ubuntu) jellytau_0.4.6_amd64.deb — sudo dpkg -i
    Windows jellytau_0.4.6_x64-setup.exe (NSIS installer)

    Report a problem: https://gitea.tourolle.paris/dtourolle/jellytau/issues

    Downloads
  • v0.4.1 1ef6180776

    JellyTau v0.4.1
    🏗️ Build and Test JellyTau / Run Tests (push) Successful in 18m39s
    Publish Documentation / Build & publish docs to gitea-pages (push) Successful in 5m40s
    Traceability Validation / Check Requirement Traces (push) Successful in 16s
    Build & Release / Run Tests (push) Successful in 6m1s
    🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 9m26s
    Build & Release / Build Linux (push) Successful in 19m41s
    Build & Release / Build Windows (push) Successful in 13m57s
    Build & Release / Build Android (push) Successful in 30m6s
    Build & Release / Create Release (push) Successful in 24s
    Stable

    dtourolle released this 2026-08-05 10:31:16 +00:00 | 246 commits to master since this release

    🐛 Fixes

    • The lockscreen pause works while a video's audio plays in the background.
      The handoff starts native audio and only then tears the WebView <video>
      down — and that teardown fires a DOM pause the frontend reports like any
      other, which left the controller believing webview media was still the
      player. Transport stayed aimed at it: pressing pause on the lockscreen sent a
      control command to a <video> that no longer existed while the native player
      carried on, and the element's parting position report dragged the displayed
      time backwards. A handoff is now tracked explicitly, so it hands transport to
      the native backend and ignores what the dying element still reports. A pause
      made from the lockscreen also survives the return to the app, instead of being
      undone by the play state captured when the handoff began.
      (UR-040, UR-005 → DR-052, DR-097)

    Downloads

    Platform File
    Android jellytau-release.apk — sideload or adb install
    Windows (portable) jellytau.exe
    Linux (Debian/Ubuntu) jellytau_0.4.1_amd64.deb — sudo dpkg -i
    Windows jellytau_0.4.1_x64-setup.exe (NSIS installer)

    Report a problem: https://gitea.tourolle.paris/dtourolle/jellytau/issues

    Downloads
  • v0.4.0 6aaa80ff92

    JellyTau v0.4.0
    🏗️ Build and Test JellyTau / Run Tests (push) Successful in 17m21s
    Publish Documentation / Build & publish docs to gitea-pages (push) Successful in 5m46s
    Traceability Validation / Check Requirement Traces (push) Successful in 16s
    Build & Release / Run Tests (push) Successful in 5m38s
    🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 8m54s
    Build & Release / Build Linux (push) Successful in 19m22s
    Build & Release / Build Windows (push) Successful in 13m55s
    Build & Release / Build Android (push) Successful in 30m12s
    Build & Release / Create Release (push) Successful in 15s
    Stable

    dtourolle released this 2026-08-04 18:22:01 +00:00 | 248 commits to master since this release

    ✨ Features

    • Favourites, across libraries. A /library/favorites page renders
      favourites from every library with All / Movies / Shows / Music scope tabs,
      reusing the standard grid so card shape still follows the media — a mixed All
      tab reads as posters, squares and thumbnails side by side. Home carries
      favourite rows below Recently Added, and a row with no items does not render
      at all, so a fresh install shows no empty rows. Server favourite state is
      mirrored into the local database as results are cached, so offline browsing
      sees the same favourites as the server; a toggle made offline is never
      overwritten by a stale server value before it has been pushed.
      (UR-067, UR-069 → DR-113, DR-114, DR-115, DR-117, DR-118)

    • Search answers from the local index. The instant leg read only downloaded
      items, so with no downloads it returned nothing and every keystroke fell
      through to a full Recursive=true server query. It now reads the whole synced
      catalog through the same availability CTE get_items uses, gated on the same
      include_catalog_browse flag, so search and browse cannot diverge. The index
      also gained MusicArtist, Playlist and People — the very groups search sorts
      results into. Re-indexing moved from a frontend startup call to a Rust
      background task with a 6h TTL, so a long session no longer searches a stale
      catalog. (UR-065 → DR-108, DR-110, DR-111)

    🐛 Fixes

    • Playback no longer restarts an episode at random on a flaky connection.
      Background audio-only playback of a video streams a progressive mp3 transcode
      over plain HTTP, which is chunked and so declares no length: when the
      connection dropped mid-episode, ExoPlayer saw end-of-input and reported
      STATE_ENDED, indistinguishable from the real end. The app ran its
      end-of-episode logic mid-episode and playback parked in STATE_ENDED, where
      the next play intent from the lockscreen, notification or a Bluetooth
      reconnect seeks an ended player to position 0 — surfacing as "the episode
      randomly restarted". The item's runtime is now what decides: an end reported
      well short of it re-opens the stream where it stopped. (UR-040 → DR-129)

    • A network hiccup no longer kills playback outright. Music and video
      declare a length, so a cut connection reaches them as an error rather than a
      phantom end — and every error stopped the player. A recoverable error now gets
      one bounded attempt at re-opening the stream where it stopped, with a growing
      backoff, leaving the rest of the queue intact. On Linux, MPV additionally
      reconnects inside the demuxer so ordinary blips never surface at all, and
      EndFile(ERROR) — previously a bare log line that left playback halted while
      the UI still showed "playing" — is now reported and recovered.
      (UR-004, UR-040 → DR-129, DR-130)

    • The player no longer reads 0:00 as a track ends on Linux. MPV exposes
      time-pos and duration as properties of the loaded file, so at EOF it
      unloads and both stop resolving — reporting zero at exactly the moment
      end-of-file handling asks where playback reached. The last reading seen while
      media was loaded is now kept and used as the fallback. (UR-005 → DR-130)

    • Server-side deletions propagate to the local catalog. DELETE FROM items
      existed nowhere, so items removed on the server lingered locally forever. A
      post-crawl mark-and-sweep now removes them, scoped to crawled types, skipping
      downloaded items, and refusing to run after a partial crawl. Separately,
      items_fts grew a full duplicate index on every catalog pass; it is now a
      real upsert, with a migration rebuilding existing indexes. (DR-110)

    • Android system bars and display cutout are handled correctly. (UR-066)

    Downloads

    Platform File
    Android jellytau-release.apk — sideload or adb install
    Windows (portable) jellytau.exe
    Linux (Debian/Ubuntu) jellytau_0.4.0_amd64.deb — sudo dpkg -i
    Windows jellytau_0.4.0_x64-setup.exe (NSIS installer)

    Report a problem: https://gitea.tourolle.paris/dtourolle/jellytau/issues

    Downloads
  • v0.3.0 58f2506966

    JellyTau v0.3.0
    🏗️ Build and Test JellyTau / Run Tests (push) Successful in 16m59s
    Publish Documentation / Build & publish docs to gitea-pages (push) Successful in 5m36s
    Traceability Validation / Check Requirement Traces (push) Successful in 18s
    Build & Release / Run Tests (push) Successful in 5m9s
    🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 8m54s
    Build & Release / Build Linux (push) Successful in 18m49s
    Build & Release / Build Windows (push) Successful in 14m4s
    Build & Release / Build Android (push) Successful in 30m17s
    Build & Release / Create Release (push) Successful in 18s
    Stable

    dtourolle released this 2026-08-03 18:37:49 +00:00 | 254 commits to master since this release

    ✨ Features

    • Opening a series lands on the current episode, not season 1. The viewer was
      dumped at the top of season 1, and the Play button played nothing at all: it
      resolved the first season by SortName and navigated to /player/<seasonId>,
      which the player route bounced straight back to the library. The backend could
      already answer "where is this viewer in this show" — get_next_up_episodes had
      accepted a series_id since it was written and no caller had ever passed one.
      pick_current_episode now resolves in progress → Next Up → first unwatched →
      the premiere, with the third rung serving offline where Next Up is always empty,
      and specials sorted after the numbered seasons. Seasons collapse to the current
      one, the current episode is badged and scrolled into view, and the hero button
      reads Resume S2E4 / Play S1E1. Seasons stop being a destination — a season
      URL redirects into the series — and the "More Episodes" strip spans the whole
      series, so a finale offers the next premiere instead of dead-ending. Six video
      routes collapse to two via ?view= tabs. Clear-history is wired to Jellyfin's
      recursive mark-unplayed, and refuses to run offline rather than diverging state
      the next sync would undo. (UR-062, UR-063, UR-064 → DR-101, DR-102, DR-103,
      DR-104, DR-105, DR-106, DR-107)

    🐛 Fixes

    • Re-entering a video no longer opens the audio player. Closing a
      webview-rendered video deliberately emits no "stopped" state — that would break
      the autoplay handoff — and the direct-play path does not stop the backend on
      unmount, so the controller still reported that item as its loaded media.
      Re-entering took the "already playing, just show the UI" shortcut, which returns
      before a stream URL is fetched, and the render fell through to the audio
      surface. Mostly visible on Android, where video direct-plays; Linux transcodes
      and stops the backend on unmount. (DR-100)

    Downloads

    Platform File
    Android jellytau-release.apk — sideload or adb install
    Windows (portable) jellytau.exe
    Linux (Debian/Ubuntu) jellytau_0.3.0_amd64.deb — sudo dpkg -i
    Windows jellytau_0.3.0_x64-setup.exe (NSIS installer)

    Report a problem: https://gitea.tourolle.paris/dtourolle/jellytau/issues

    Downloads
  • v0.2.9 a26a853f01

    JellyTau v0.2.9
    Publish Documentation / Build & publish docs to gitea-pages (push) Successful in 5m33s
    Traceability Validation / Check Requirement Traces (push) Successful in 25s
    🏗️ Build and Test JellyTau / Run Tests (push) Successful in 17m25s
    Build & Release / Run Tests (push) Successful in 6m7s
    🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 8m38s
    Build & Release / Build Linux (push) Successful in 19m23s
    Build & Release / Build Windows (push) Successful in 13m43s
    Build & Release / Build Android (push) Successful in 29m47s
    Build & Release / Create Release (push) Successful in 19s
    Stable

    dtourolle released this 2026-08-02 16:10:37 +00:00 | 256 commits to master since this release

    🐛 Fixes

    • A backgrounded audio-only episode advances instead of stalling. It stopped
      at the episode boundary and ExoPlayer parked in STATE_ENDED, where any later
      play intent — lockscreen, headset, Bluetooth reconnect — replays the ended item,
      surfacing as the episode randomly restarting. End-of-playback is dispatched from
      two places and they disagreed: the Android JNI callback carried the
      background-audio branch but can never reach it, because every load sets
      EndReason::NewTrackLoaded and nothing clears it, so the first real end consumes
      it and the decision is always Stop. The path that actually decides is the
      frontend's echo, which had no background-audio case at all and started a
      countdown whose advance is a goto() that cannot start audio while
      backgrounded. Both dispatchers now share one auto_advance_to_next_episode.
      (UR-040)

    Downloads

    Platform File
    Android jellytau-release.apk — sideload or adb install
    Windows (portable) jellytau.exe
    Linux (Debian/Ubuntu) jellytau_0.2.9_amd64.deb — sudo dpkg -i
    Windows jellytau_0.2.9_x64-setup.exe (NSIS installer)

    Report a problem: https://gitea.tourolle.paris/dtourolle/jellytau/issues

    Downloads