Every subtitle line arrived in an opaque black box wide enough to sit across the picture. That box is what Android hands back when the viewer has set no captioning preferences: SubtitleView.setUserDefaultStyle() reads the system style and falls back to media3's DEFAULT, which is white on opaque black. Dropping the box is not the same as replacing the style. Someone who has configured captions in accessibility settings has said something specific about colour, typeface and edges, and overriding all of it to remove a background would answer a question they did not ask. Their style is kept and only the two colours that paint a box — background and window — are cleared. A style specifying no edge gets a black outline, since without a box the text must supply its own contrast or it is unreadable over a bright scene. One that already names an edge keeps it: that viewer has said how they want their captions separated from the picture. Compiles and packages, but NOT yet seen on a device — the tablet was disconnected before it could be deployed, so the requirement is recorded as "Done (pending device verification)" and this must not be tagged into a release until someone has looked at it. TRACES: UR-020 | DR-261

JellyTau
A cross-platform Jellyfin client built with Tauri, SvelteKit, and TypeScript.
Business logic lives in a Rust backend; a UI-rich Svelte frontend handles presentation and talks to it over Tauri's IPC. Targets Linux (libmpv) and Android (ExoPlayer).
Getting Started
This project uses bun as its package manager.
# Activate the Rust environment (fish shell)
source "$HOME/.cargo/env.fish"
# Install dependencies
bun install
# Run in development
bun run tauri dev
# Type-check the frontend
bun run check
# Build for Linux
bun run tauri build
# Build for Android
bun run tauri android build
For the full set of build, test, and Android helper scripts, see scripts/README.md.
Documentation
| Topic | Location |
|---|---|
| Architecture overview & subsystem docs | docs/architecture/ |
| Requirements, traceability & technical debt | docs/requirements.md |
| Build & release process | docs/build/build-release.md |
| Docker builds | docs/build/docker.md |
| Traceability tooling & CI | docs/traceability.md, docs/traceability-ci.md |
| Release checklist | docs/release-checklist.md |
| UX flows | docs/ux-flows.md |
| CI operations (builder image, secrets, runner) | docs/build/ci-operations.md |
Contributing
CONTRIBUTING.md covers the setup, the gates a change has to pass, and the two rules that catch people out (bug fixes start with a failing test; Jellyfin's taxonomy stays in Rust). Please also read the Code of Conduct.
Found a security problem? Do not open an issue — see SECURITY.md.
Verifying a download
Every release publishes SHA256SUMS covering all of its artifacts, plus an SBOM
of what went into the build:
sha256sum -c SHA256SUMS
Desktop builds update themselves from Settings → Updates, verifying each payload against JellyTau's signing key before installing. Android installs are handled by the system installer, so the app links to the releases page instead.
Recommended IDE Setup
VS Code + Svelte + Tauri + rust-analyzer.
License
MIT