The path from find was relative to the repo root, but the script cd'd
into a tmpdir before using it, so the appimage-extract call resolved
against the wrong directory and failed with "No such file or
directory". Resolve to an absolute path up front.
Tauri's bundler hardcodes linuxdeploy --plugin gtk for AppImage
builds, which bundles a full GTK3/WebKit2GTK stack built against
whatever Ubuntu's CI image ships. That bundled WebKitGTK version
(Ubuntu 24.04's ~2.44.x) behaves differently than a typical desktop's
system WebKitGTK when the player surface reparents the webview into
a GtkOverlay at runtime — confirmed locally that stripping it and
falling back to the host's WebKitGTK (matching dev mode, which never
had this bug) fixes the player controls overlay not rendering.
libmpv/ffmpeg/codec libraries are unaffected — they live in a
separate app-specific resource directory, not Tauri's own bundling,
so they stay bundled since codec ABI genuinely varies across distros
in ways system packages can't be relied on for.
ErrorBoundary was imported in App.tsx but never actually used. An
uncaught render error in ReactPlayerOverlay unmounts the whole React
tree with no boundary to catch it, and since the webview background
is transparent during native playback, that looked exactly like
"video plays, no controls" instead of surfacing any error. Also log
caught errors via debug_log so they land in the app log file too.
Playback itself now works on Linux, but the React controls overlay
doesn't appear. nativePlayerActive only flips on the native-player-show
Tauri event, so log both sides: whether Rust actually emits it, and
whether the App.tsx listener is registered in time to receive it.
Found via the new debug_log checkpoints: the bundled Linux libmpv was
built without lua, so mpv_set_option_string("osc", "no") returned
"option not found" and player_init bailed out entirely before ever
creating a renderer. We only set this to turn OSC off, which is moot
if OSC doesn't exist in the first place, so treat it as a warning
instead of a fatal error.
player_load already logs but player_init never did, and handlePlay had
no top-level error handling, so a failure anywhere before the
playInEmbeddedMpv try/catch silently dropped the player back to the
previous screen with nothing in any log. Add debug_log checkpoints
through handlePlay and log player_init's outcome, to find where the
AppImage build actually fails since it isn't where we assumed.
find_libmpv_path() only checked <exe_dir>/lib, but Tauri's Linux
packaging (deb/rpm/AppImage) puts bundled resources at
<exe_dir>/../lib/<ProductName>/lib per the FHS convention, since /usr/bin
can't hold arbitrary app files. The executable sits at /usr/bin/fluxa-desktop
while libmpv was actually at /usr/lib/Fluxa Desktop/lib/. That mismatch
made every AppImage build silently fall back to a system libmpv.so.2 that
doesn't exist on most distros, so the player never loaded. Scan /usr/lib's
subdirectories for the bundled lib instead of assuming a fixed layout.
Bumping the crate's own version touched Cargo.lock on every release,
busting Swatinem/rust-cache's key (which hashes Cargo.lock) and forcing
a full from-scratch dependency rebuild on every single release across
all three platforms. Tauri natively supports reading the app version
from package.json, so pin Cargo.toml's version and let that carry it.
Controls could get stuck hidden after a fullscreen transition since they
only re-show on a mousemove. Also hide the OS cursor via Tauri's window
API when controls auto-hide on idle: the CSS cursor:none class only
affects the webview, but on Windows the video renders into a separate
native child window that doesn't know about it.
actions/checkout's fetch-depth: 0 doesn't reliably fetch other tag
refs on its own, so git describe found no previous tag and the
release notes silently fell back to the entire repo history.
Removes the manual round-trip of tagging a fork release, then coming
back here to bump MPV_FORK_TAG and cut another release. Safe since
this repo is the fork's only consumer.
tauri.conf.json no longer carries its own version -- it now inherits
from Cargo.toml, so a release bump only touches package.json and
Cargo.toml (scripts/bump-version.sh handles both plus Cargo.lock).
Previously every thumbnail request paid a fixed 200ms (and 500ms on
first load) regardless of how fast the actual seek was. Polling exits
as soon as it's actually ready, capped at the same ceilings as before.
vo=libmpv requires a render context to exist before any loadfile/seek
command runs (unlike vo=null, which needs nothing). The context was
previously created lazily inside render_thumbnail(), called after
load/seek already failed with 'error running command'.
vo=null discards all decoded video frames before they can reach any
render API, so render_thumbnail() always got a black/empty buffer
despite the render call itself reporting success.
The backend flag previously only got set when SettingsScreen mounted,
so a user who enabled the preference in a past session and never
revisits Settings would silently get no thumbnails -- the backend
default stays false with no error, since it returns early before
ever touching the renderer.
video-codec reflects the container's track list, available right
after the file opens, independent of decode/buffering progress.
Replaces the previous fixed-timeout heuristic, which was firing
early for legitimately slow torrent buffering and revealing a black
player view before the real frame was ready.
load() now stays paused; the frontend unpauses once vo-configured
(or a 4s safety timeout for video-less streams) is observed, so
audio no longer plays ahead of the picture during the loading screen.
User commands like pause must actually take effect; try_lock() was
silently failing with 'player renderer busy' whenever it collided
with the render thread's per-frame lock, requiring multiple clicks.
child_hwnd is created on the render thread via CreateWindowExW, but
nothing ever ran a message loop for it. Windows expects the thread
that creates a window to process its message queue; without that,
compositor/system messages sent to the window go unanswered, which
plausibly explains both the freeze after WS_CLIPSIBLINGS removal made
this window actively participate in compositing, and the crash when
moving the parent window (synchronous WM_WINDOWPOSCHANGING messages
propagate through the window hierarchy including this child).