• JellyTau v0.11.0
    Build & Release / Create Release (push) Blocked by required conditions
    Publish Documentation / Build & publish docs to gitea-pages (push) Successful in 6m5s
    Traceability Validation / Check Requirement Traces (push) Successful in 19s
    Build & Release / Run Tests (push) Successful in 15m20s
    Build & Release / Build Linux (push) Waiting to run
    Build & Release / Build Windows (push) Waiting to run
    Build & Release / Build Android (push) Waiting to run
    Stable

    dtourolle released this 2026-08-23 09:53:57 +00:00 | 0 commits to master since this release

    Video can play through the native renderer on Linux, and the machinery every
    platform's playback goes through was rebuilt around one contract. Nine defects
    fell out of doing it — each one a capability the code had written down as a
    fact about the platform rather than asking the thing that would know.

    Changes

    • Video can decode natively on Linux, without the server re-encoding it.
      Until now every video played on the desktop was transcoded by Jellyfin to
      h264 and handed to the browser engine, whatever the file actually was — so the
      server burned CPU on every play, and quality was capped by that conversion.
      mpv can now draw the picture directly, composited beneath the interface so the
      controls, subtitles and overlays still sit on top of it. Direct play means the
      original file, hardware decoding, and no server work at all. This is off by
      default while it settles: set JELLYTAU_NATIVE_VIDEO=1 to try it. The browser
      path is untouched and remains what you get otherwise. (UR-080 → DR-231 …
      DR-237)

    • Playback speaks one language across every player. Linux, Android and
      Windows each drove their engine through a different set of calls, and a rule
      learned on one did not reach the others — which is why several of the fixes
      below existed on one platform and not another. All three now go through a
      single contract, and one suite of behaviours runs against every engine,
      including ExoPlayer on a real device. An engine is either correct or visibly
      failing. Nothing about this is visible while it works, which is the point.
      (UR-081 → DR-242 … DR-247)

    🐛 Fixes

    • Resuming a film starts where you left it, instead of at the beginning.
      Asking a player to open a file and asking it to start at a position were two
      separate steps, and the second was issued before the first had finished — so
      it failed, was discarded, and playback began at zero. It affected resume and
      any skip on a stream the server was converting. The position is now part of
      opening the file, so there is no gap for it to fall into. (DR-241)

    • Skipping works on films the server is converting. A skip was routed by the
      shape of the stream rather than by what the player could do with it. That
      happened to be right while one particular player handled those streams and
      became wrong the moment another did — after which skipping simply did nothing,
      silently. Players now say what they can do and are asked. (DR-238, DR-246)

    • The play and pause button follows the player again. The code that reacted
      to pausing was never subscribed to the event it was waiting for, so the button
      stayed where it was while playback did something else. (DR-239)

    • Fullscreen fills the screen. It expanded the page rather than the window,
      which was invisible while the picture was drawn inside the page and obvious as
      soon as it was not. (DR-240)

    • The seek bar knows how long the film is. A player that had not yet worked
      out the duration reported zero, and zero was believed — leaving the bar with
      no scale and nothing to drag against, even though the length had been known
      since the library listed it. (DR-251)

    • Leaving the player stops the sound. The stop was aimed at whichever
      renderer the app believed was in charge. Enabling background audio hands over
      to a different one, so afterwards the app stopped something that was no longer
      playing and the film carried on as an audio track in the mini player. Closing
      now stops everything, regardless of who was in charge. (DR-250)

    • Coming back from background audio no longer leaves a black screen. The
      stream that plays while the app is hidden has no fixed length, and the value a
      player uses to say so is a very large negative number. Converting it crashed
      the playback engine outright, which looked like a dead player with no
      controls. (DR-252)

    • Android builds again. A rule that only applied to Linux stayed attached to
      code that had stopped being Linux-only, and the Android build had not compiled
      since. (DR-247)

    🧹 Under the hood

    • The conformance suite can be run on its own: bun run test:player for the
      desktop engines, bun run test:player:android for ExoPlayer on a connected
      device. Both build a test fixture rather than carrying media in the
      repository.

    • docs/native-player-verification.md
      records what to check before a release, including the exact sequences that
      found two of the defects above — both of which passed every automated test.

    Known limitations

    • Resume reads progress saved on the device, not from the server, so a fresh
      install or a second device will not offer to resume something watched
      elsewhere.
    • Native video on Linux is opt-in and is not yet the default.

    Downloads

    Platform File
    Linux (portable) *.AppImagechmod +x and run
    Linux (Debian/Ubuntu) *.debsudo dpkg -i
    Linux (Fedora/openSUSE) *.rpmsudo rpm -i
    Windows *-setup.exe (NSIS). Unsigned — SmartScreen may warn on first run.
    Android *.apk sideload, or *.aab for Play Console

    Desktop builds check for updates from here and can install a new
    version in place, verifying its signature first.

    Verifying your download

    sha256sum -c SHA256SUMS
    

    SHA256SUMS covers every file in this release. An SBOM
    (*.cdx.json, frontend-dependencies.txt) lists what went into it.

    Requirements

    • Linux: 64-bit, GLIBC 2.29+
    • Windows: 64-bit Windows 10 or later
    • Android: 8.0 or later, ~50 MB free

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

    Downloads
  • JellyTau v0.10.1
    🏗️ Build and Test JellyTau / Run Tests (push) Successful in 18m44s
    🏗️ Build and Test JellyTau / Supply Chain (push) Failing after 49s
    Publish Documentation / Build & publish docs to gitea-pages (push) Successful in 5m27s
    Traceability Validation / Check Requirement Traces (push) Successful in 10s
    Build & Release / Run Tests (push) Successful in 14m48s
    🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 4m19s
    Build & Release / Build Linux (push) Successful in 20m20s
    Build & Release / Build Windows (push) Successful in 15m36s
    Build & Release / Build Android (push) Successful in 30m46s
    Build & Release / Create Release (push) Successful in 38s
    Stable

    dtourolle released this 2026-08-22 08:10:12 +00:00 | 6 commits to master since this release

    A single fix, for something that had been quietly overriding a choice you made.

    🐛 Fixes

    • Locking the screen no longer keeps playing a video's audio unless you asked
      it to.
      The player has a background-audio button: turn it on and the sound
      carries on when you lock the screen or leave the app, turn it off and playback
      stops. It stopped working when video moved to the native renderer — which plays
      through a media service designed to keep going while the app is hidden — and
      nothing was left to stop it. So the audio continued whether the button was on
      or off, and there was no way to make it behave otherwise. The button governs it
      again: with it off, locking the screen pauses the video and unlocking resumes
      where you were; with it on, the audio continues as before. Music is untouched —
      it keeps playing when backgrounded, as a music player should — and a video in a
      picture-in-picture window keeps playing too, because the window is still on
      screen. If you had already paused before locking, it stays paused.
      (UR-040 → DR-224)

    Downloads

    Platform File
    Linux (portable) *.AppImagechmod +x and run
    Linux (Debian/Ubuntu) *.debsudo dpkg -i
    Linux (Fedora/openSUSE) *.rpmsudo rpm -i
    Windows *-setup.exe (NSIS). Unsigned — SmartScreen may warn on first run.
    Android *.apk sideload, or *.aab for Play Console

    Desktop builds check for updates from here and can install a new
    version in place, verifying its signature first.

    Verifying your download

    sha256sum -c SHA256SUMS
    

    SHA256SUMS covers every file in this release. An SBOM
    (*.cdx.json, frontend-dependencies.txt) lists what went into it.

    Requirements

    • Linux: 64-bit, GLIBC 2.29+
    • Windows: 64-bit Windows 10 or later
    • Android: 8.0 or later, ~50 MB free

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

    Downloads
  • JellyTau v0.10.0
    🏗️ Build and Test JellyTau / Run Tests (push) Successful in 15m52s
    🏗️ Build and Test JellyTau / Supply Chain (push) Failing after 29s
    Publish Documentation / Build & publish docs to gitea-pages (push) Successful in 5m35s
    Traceability Validation / Check Requirement Traces (push) Successful in 11s
    Build & Release / Run Tests (push) Successful in 14m53s
    🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 4m22s
    Build & Release / Build Linux (push) Successful in 20m53s
    Build & Release / Build Windows (push) Successful in 15m41s
    Build & Release / Build Android (push) Successful in 30m46s
    Build & Release / Create Release (push) Successful in 38s
    Stable

    dtourolle released this 2026-08-22 00:52:36 +00:00 | 7 commits to master since this release

    Two things you can see, and a great deal of work on how this project builds and
    ships itself. The app can now update itself, and it can tell you what it did
    when something goes wrong — both of which existed as gaps rather than as bugs,
    which is why they lasted so long.

    Changes

    • JellyTau can update itself. Anyone who installed an AppImage or ran the
      Windows installer was frozen on that version permanently: nothing in the app
      ever mentioned that a newer one existed, and the release page was the only
      announcement. Settings → Updates now checks, shows what changed, and installs
      and restarts on request. Each download is verified against JellyTau's signing
      key before anything is installed, so a substituted file is refused rather than
      run. Android is deliberately not wired to this — an app may not replace its own
      APK, that is the system installer's job — and is given a link to the releases
      page instead of a button that would fail. (UR-077 → DR-217)

    • You can export a diagnostics bundle. Until now the app forgot everything it
      had done the moment it closed. Logs went to standard output, which nobody sees
      when launching from a desktop icon, and on Android went nowhere at all — so the
      backend was invisible on the platform where the hardest playback bugs live. A
      crash left nothing behind. Logs are now kept in a size-capped file that
      survives a restart, a crash is recorded before the app dies, and Settings →
      Diagnostics exports the lot as one file to attach to a bug report. Access
      tokens and passwords are stripped before anything is written to disk, not
      merely before it is exported. Nothing is transmitted anywhere; you attach the
      file yourself. (UR-078 → DR-218)

    • Linux gets an AppImage again. The release notes have advertised one for
      months while the build never produced it — the packaging step looked for the
      file, found nothing, and said nothing. (DR-217)

    🐛 Fixes

    • Releases no longer ship every Windows installer ever built. Every release
      from v0.1.0 to v0.8.2 carried its predecessors': sixteen installers on v0.8.2,
      thirteen of them stale, and a download list on v0.5.0 reaching back to 0.1.0.
      The build directory is never cleaned and the build machine reuses it, so each
      release collected whatever was left behind. It went unnoticed for eight months
      because nothing looked wrong — the files were real and the page merely looked
      busy. The stale files have been removed from the published releases, the build
      now clears that directory first, and a check refuses to publish a release
      containing an artifact from a different version. (DR-220)

    • Release notes now say what changed. All 35 previous releases published the
      same block of generic install instructions, whose "What's New" section was a
      link to a file that does not resolve from a release page. Every release page
      now carries its own entry from this changelog, and the past ones have been
      filled in. (DR-219)

    🔒 Security and supply chain

    • Dependencies are now checked against a vulnerability database on every
      build.
      They never had been. The first run found eight vulnerabilities and one
      unsoundness in the Rust dependency graph — all of them fixed by an update
      nobody had a reason to run. Licences are checked against an allow-list too, so
      nothing gets redistributed inside a release that does not permit it.
      (DR-216)

    • Every release publishes checksums and a bill of materials. SHA256SUMS
      lets you verify a download (sha256sum -c SHA256SUMS); the SBOM lists what
      went into the build, so "does this release contain ?" has
      an answer that is not "rebuild it and find out". (DR-216)

    • Builds are reproducible again. Every CI job named a container image tag
      that was rewritten in place, so rebuilding an old release did not necessarily
      rebuild the same thing. Jobs now pin an immutable tag. The one dependency that
      comes from a git branch rather than a package registry is pinned to an exact
      revision, closing a path by which new upstream code could arrive unreviewed in
      a library linked into the player. (DR-216)

    🧹 Under the hood

    • Formatting, linting and type-checking now run in CI. All three were configured
      and enforced by nothing: 199 files did not match the project's own formatter, a
      type error could sit on the main branch until somebody cut a release, and the
      test-coverage command had been broken for months by a dependency mismatch.
      Coverage now has a floor that only moves up. (DR-215)

    • The traceability matrix counts requirements implemented by configuration.
      Several carried the necessary annotations and were being counted as uncovered
      because the extraction tool only read source files. (DR-215)

    • The project now has a security policy, contribution guide, code of conduct,
      issue and pull-request templates, and an operations document covering the
      builder image, the release secrets, and what losing the signing key would mean.

    • The app framework moved from Tauri 2.9.5 to 2.11.5. Nothing about this is
      visible in use, but it is worth recording that it did not go quietly: the
      windowing layer beneath Tauri quietly stopped publishing the Android JavaVM
      and application handle that this app's credential storage had been reading for
      its whole life. Nothing here had changed; a side effect several dependencies
      down had simply gone away, and the app aborted on launch on every Android
      device. JellyTau now sets that handle itself rather than relying on someone
      else to do it. Caught by installing on a real tablet before release — no test
      suite runs the app. (UR-012 → DR-223)

    Downloads

    Platform File
    Linux (portable) *.AppImagechmod +x and run
    Linux (Debian/Ubuntu) *.debsudo dpkg -i
    Linux (Fedora/openSUSE) *.rpmsudo rpm -i
    Windows *-setup.exe (NSIS). Unsigned — SmartScreen may warn on first run.
    Android *.apk sideload, or *.aab for Play Console

    Desktop builds check for updates from here and can install a new
    version in place, verifying its signature first.

    Verifying your download

    sha256sum -c SHA256SUMS
    

    SHA256SUMS covers every file in this release. An SBOM
    (*.cdx.json, frontend-dependencies.txt) lists what went into it.

    Requirements

    • Linux: 64-bit, GLIBC 2.29+
    • Windows: 64-bit Windows 10 or later
    • Android: 8.0 or later, ~50 MB free

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

    Downloads
  • v0.9.1 d095e1f410

    JellyTau v0.9.1
    🏗️ Build and Test JellyTau / Run Tests (push) Successful in 13m55s
    Publish Documentation / Build & publish docs to gitea-pages (push) Successful in 5m22s
    Traceability Validation / Check Requirement Traces (push) Successful in 16s
    Build & Release / Run Tests (push) Successful in 14m0s
    🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 4m9s
    Build & Release / Build Linux (push) Successful in 16m39s
    Build & Release / Build Windows (push) Successful in 20m42s
    Build & Release / Build Android (push) Successful in 29m18s
    Build & Release / Create Release (push) Successful in 13s
    Stable

    dtourolle released this 2026-08-21 11:34:28 +00:00 | 29 commits to master since this release

    A one-line fix to the home screen, released on its own because it is the kind of
    small wrongness you notice every time.

    🐛 Fixes

    • Swiping the hero banner now buys you a full six seconds. The rotation
      timer was started once when the banner appeared and then left alone, so a
      swipe, arrow or dot tap inherited whatever was left of the running countdown
      — swipe five and a half seconds in and the banner moved on half a second
      later, before you had read the title. Any manual change now restarts the
      countdown from that moment. (UR-034 → DR-038)

    Downloads

    Platform File
    Linux (Fedora/openSUSE) JellyTau-0.9.1-1.x86_64.rpmsudo rpm -i
    Linux (Debian/Ubuntu) JellyTau_0.9.1_amd64.debsudo dpkg -i
    Windows JellyTau_0.9.1_x64-setup.exe (NSIS installer)
    Android jellytau-release.apk — sideload or adb install
    Windows (portable) jellytau.exe

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

    Downloads
  • v0.8.2 61df2730bc

    JellyTau v0.8.2
    🏗️ Build and Test JellyTau / Run Tests (push) Successful in 24m47s
    Publish Documentation / Build & publish docs to gitea-pages (push) Successful in 5m40s
    Traceability Validation / Check Requirement Traces (push) Successful in 20s
    Build & Release / Run Tests (push) Successful in 25m19s
    🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 11m18s
    Build & Release / Build Linux (push) Successful in 30m51s
    Build & Release / Build Windows (push) Successful in 14m55s
    Build & Release / Build Android (push) Successful in 32m54s
    Build & Release / Create Release (push) Successful in 20s
    Stable

    dtourolle released this 2026-08-19 15:29:42 +00:00 | 78 commits to master since this release

    A single fix, for Android background audio.

    🐛 Fixes

    • Listening to a video in the background no longer jumps back to where you
      started.
      Handing a video off to background audio streams a live mp3
      transcode, which is chunked — no length, and no duration the player can read.
      ExoPlayer resumes a failed load in place only when it knows one of those two
      things; with neither it assumes the source is live and re-requests the URL from
      the beginning. That URL starts at the moment you locked the screen, so a
      network blip left a retry armed, and when the buffer eventually ran dry —
      minutes later, with nothing in between — playback silently resumed from the
      handoff point and carried on. No error was raised and nothing ended, so none of
      the existing stream-recovery paths could see it; the only sign was a position
      that went backwards, which is why it looked random. The player is now refused
      its own retry for exactly that kind of stream, so the failure surfaces and the
      backend re-opens the stream at the position playback actually reached, keeping
      your selected audio track. Music and video are untouched: both declare their
      timeline, and the player resumes them where the load stopped.
      (UR-040, UR-004 → DR-203)

    Downloads

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

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

    Downloads
  • v0.8.0 2c52077b1d

    JellyTau v0.8.0
    🏗️ Build and Test JellyTau / Run Tests (push) Successful in 25m14s
    Publish Documentation / Build & publish docs to gitea-pages (push) Successful in 5m47s
    Traceability Validation / Check Requirement Traces (push) Successful in 36s
    Build & Release / Run Tests (push) Successful in 26m3s
    🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 11m2s
    Build & Release / Build Linux (push) Successful in 32m23s
    Build & Release / Build Windows (push) Successful in 14m59s
    Build & Release / Build Android (push) Successful in 31m22s
    Build & Release / Create Release (push) Successful in 31s
    Stable

    dtourolle released this 2026-08-16 22:00:10 +00:00 | 85 commits to master since this release

    A security and correctness release, from an audit of the codebase against its own
    requirements and against current Android/Tauri practice. Most of it is invisible
    in use; three things change behaviour you can see, listed first.

    Changes

    • The app no longer backs its data up to your Google account. It never
      should have: allowBackup was on by default, which sent the library catalogue
      and watch history off the device — and the credentials went with it in a form
      that could never be read again, because they are encrypted under an Android
      Keystore key and Keystore keys are never backed up. Restoring onto a new phone
      therefore produced ciphertext with no key: an authentication failure with no
      explanation. Backup is now off, for device-to-device transfer as well as cloud
      (a separate channel with the identical failure), and an unreadable credential
      blob is now treated as "logged out" rather than an error, so the next sign-in
      repairs it. (UR-012 → DR-135)

    • The app no longer offers itself as an Android TV app. (This is about the
      app icon on a TV device's home screen — your TV shows library is untouched.)
      It advertised a leanback launcher entry without any of what makes a TV app work — no D-pad focus model,
      no banner, and a missing touchscreen declaration that fails Play's TV
      validation. Launching it on a TV would have landed you in a UI you could not
      navigate. It can be re-declared when TV support is actually built.

    • Lockscreen skip scrubs a film instead of leaving it. While a video's audio
      plays in the background, the skip buttons jump 30 seconds forward and 10
      seconds back, rather than advancing to the next episode. There is no "next
      track" inside a film, and pressing skip to re-hear a line should not eject you
      from what you are watching. Music is unchanged: skip still moves through the
      queue. (UR-040, UR-006 → DR-201)

    🔒 Security

    • The webview now runs under a Content-Security-Policy. It had none, so any
      script reaching the web layer inherited the full IPC surface. script-src is
      now 'self' with no inline or eval, and plugins and frames are refused
      outright. (UR-071 → DR-198)

    • The webview stops undoing the network security config. It set a blanket
      cleartext opt-in by hand, along with file and content access it never used —
      defeating the config that exists to block exactly that, and whose own comment
      warned against it. (UR-071 → DR-199)

    • The asset protocol no longer reaches the database or the credential store.
      Its scope was the whole app data directory; it is now the one subdirectory it
      serves. (UR-012, UR-071 → DR-198)

    🐛 Fixes

    • A credential store that could not be read is now recoverable. The decrypt
      failure surfaced as a hard error rather than a logged-out state, so the app got
      stuck instead of offering the login screen. (UR-012 → DR-135)

    🔧 Internal

    • CI now enforces the checks the contributor rules already required —
      cargo fmt --check and clippy — neither of which had ever run there. The
      traceability gate was also raised from 50% to 82%, a floor low enough that half
      the matrix could rot before it fired, and a new check fails the build on a
      requirement ID that no longer exists.
    • Twelve requirements marked "Done" carried no implementation trace at all;
      they are now tagged, and stale integration requirements that named a backend
      never built have been re-scoped to the ones that actually deliver them.
      Coverage moved 86% → 90%.
    • The Rust lint backlog is cleared (51 warnings → 0), and a flaky test that
      intermittently reddened CI is fixed — it was paying a cold module-transform
      cost inside a test body, not waiting on a timer.

    Downloads

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

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

    Downloads
  • 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 | 101 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.debsudo 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 | 107 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.debsudo 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 | 145 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.debsudo 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 | 157 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.debsudo dpkg -i
    Windows jellytau_0.5.0_x64-setup.exe (NSIS installer)

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

    Downloads