ab95f5013d277a23c8f290b2d2c7ac0e1f4f990f
5
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
f46d7bf676 |
fix(player): make native Android video opt-in again — it shipped as audio with no picture
Publish Documentation / Build & publish docs to gitea-pages (push) Canceled after 0s
🏗️ Build and Test JellyTau / Run Tests (push) Failing after 4m55s
🏗️ Build and Test JellyTau / Android Compile Check (push) Skipped
Traceability Validation / Check Requirement Traces (push) Successful in 20s
DR-161 flipped experimentalNativeVideo on by default so picture-in-picture could shrink a real video surface. On a device that shipped sound with a blank screen. The decode path was never at fault. Logcat shows ExoPlayer running and feeding a live SurfaceView with an active BufferQueue. The compositing was: the SurfaceView sits behind the WebView, and the step that clears the opaque layers above it never took effect — `WebView transparent = false` is logged, `= true` never appears. The video was rendering correctly the whole time, behind an opaque page. This is precisely the defect the flag existed to contain; VideoPlayer.scrubRegression.test.ts had already recorded that "the native SurfaceView has never been visible through the webview". Enabling it by default shipped a verified decode path on top of an unverified display path. Reverting costs nothing that matters: PiP does not depend on it — DR-160 drives PiP from the WebView <video> — and working video outranks PiP showing a native surface. The flag stays in Settings, now described as incomplete rather than as a performance win, so anyone helping test it still can. Fixing the compositing is the prerequisite for trying this default again (DR-172). |
||
|
|
7387f35c7e |
docs(player): correct the stale "native video defaults to off" comments
DR-161 made `experimentalNativeVideo` default to on, but three comments still described the pre-flip world and one of them was load-bearing: - `nativeVideo.ts` labelled the store "Default off" directly above a `load()` that returns true when nothing is stored. - The two PiP comments explained themselves as "what makes PiP work in the shipping configuration", which stopped being true when Android started shrinking the real ExoPlayer surface. They still describe the Linux path and the flag-off case, so they say that instead. - `video_audio_codecs` justified its narrow codec list with "video does not play through ExoPlayer", which is no longer so on Android. The narrow list is still right, for a different reason now recorded: the flag is a user setting and a download outlives it, so only the intersection holds on both sides of the switch. DR-171 carries the same caveat. No behaviour change. |
||
|
|
9f5f57cba4 |
fix(ui,player): scroll restore, immersive fullscreen, watched toggle, handoff timeline, PiP
Batch of reported bugs and enhancements. UI - Pages no longer inherit the previous page's scroll position (DR-156, UR-072). The shell keeps its scrollers alive across navigation by design, so the element never remounts and its scrollTop survived the route change; SvelteKit restores window scroll, which this app never uses. ScrollMemory records the offset per route and per container: forward moves reset to the top, Back restores where the route was left. - Season header stacks on narrow screens, and the title span gets min-w-0 so it actually truncates instead of overflowing under the action buttons. - Favourites gets a labelled tile at the head of the library grid rather than only an unlabelled heart icon in the header. Playback - Full-screen video on Android hides the system bars (DR-157, UR-066). requestFullscreen() cannot touch the Activity window from inside a WebView, so the control did nothing visible while the bars stayed painted over the video. ImmersiveModeBridge hides them, restored on exit, Escape and teardown. - Background-audio handoff stops leaking its relative timeline (DR-159). background_audio_base was a display-only correction applied in two places while progress reports to Jellyfin, the frontend and media3's own seeks all worked in the relative timeline treating it as absolute — each crossing losing exactly `base` seconds. The conversion now happens once, in the position tick, and inbound seeks resolve through seek_absolute, which re-opens the stream at the requested position because the handoff transcode cannot seek. - Picture-in-picture works on the path that actually plays video (DR-160). canEnterPip demanded a native ExoPlayer surface, but that path is behind a flag defaulting to off, so PiP could never engage. It now accepts the WebView <video> too, keeping the WebView visible and routing play/pause to the element. - Native video is now the default so PiP has a real surface (DR-161). The scrub-regression tests pinned the flag-off path implicitly; they now mock it off explicitly. The native scrub/seek path is not covered by the suite and needs device verification. Watched state - Watched toggle on the episode row, season header, series and movie hero, and the Episode Focus View (DR-158, UR-073). Both backend halves already existed with no caller. storage_set_watched covers a container's episodes so the toggle is honest offline, and QueuedOp::MarkUnplayed gives the sync queue the missing direction. Release - Fix the Android versionCode floor (set-version.sh). v0.5.2 shipped code 5002 under an earlier minor*1000 scheme, but the current minor*100 formula yields 1502 for that version and 1503 for 0.5.3 — so every 0.5.x release built from it was an un-installable downgrade for anyone already on v0.5.2. Widened to 10000 + major*1000000 + minor*1000 + patch (0.5.3 -> 15003). - Bump to 0.5.3. |
||
|
|
3fbf6afdbc |
Background-audio handoff for video + repository/player refactor
Hand video playback off to a native audio-only stream when the app is backgrounded or locked, with no on-device video decode (UR-040). Adds player_enter/exit_background_audio commands, an audio-only stream URL for video items across the repository layer, and the frontend handoff state machine wired into VideoPlayer. Includes accompanying repository/offline/player refactoring and regenerates the traceability matrix. |
||
|
|
1fa5aa46f9 |
Android picture-in-picture, and fix three dead Android config files
Add PiP for native (ExoPlayer) video on Android. Video renders into a SurfaceView behind the WebView, so PiP is driven by the Activity shrinking into a floating window rather than the HTML5 PiP API (which WebKitGTK does not implement, hence Android-only). - PictureInPictureManager.kt: enter PiP with the video's aspect ratio (clamped to the 1:2.39-2.39:1 range Android accepts, outside which it throws), plus a play/pause RemoteAction. Hides the WebView while in PiP - it is opaque and sits above the surface, so it would otherwise occlude the video entirely - and re-fits the surface on exit. - MainActivity.kt: onUserLeaveHint auto-PiP, onPictureInPictureModeChanged, and an AndroidPictureInPicture JS interface following the existing AndroidAudioFocus pattern. - pictureInPicture.ts + VideoPlayer.svelte: PiP button, rendered only when the native bridge reports support. - proguard: keep rules for @JavascriptInterface methods, which are only referenced from JS and would be stripped in minified release builds. Casting needs no special handling: canEnterPip() checks natively that a local video surface is attached and playing, which a remote session lacks. While wiring the manifest, found that three tracked files under src-tauri/android/ were never reaching any build. Gradle reads only gen/android/app/src/main/, and sync-android-sources.sh did not copy them: - src/main/AndroidManifest.xml was a partial <application> fragment written as if Tauri merged it. It does not - there is no manifest-merger hook here, so its hardwareAccelerated flag never reached an APK. Promoted to the complete authoritative manifest (folding in that flag) and synced. - src/main/res/values/themes.xml (transparent status bar, fitsSystemWindows) was never copied; the sync only globbed mipmap-*. Now synced. - build.gradle.kts was a leftover com.android.library module config with stale media3 1.5.1 deps. The live deps are in app/build.gradle.kts at 1.5.0. Deleted. Verified: merged manifest now carries hardwareAccelerated, supportsPictureInPicture, resizeableActivity and the density configChange; themes.xml compiles into merged resources; Kotlin builds warning-free; svelte-check clean; 537 frontend tests pass. Not verified: PiP behaviour on a device, and the release keep rules against a minified build. assembleUniversalDebug cannot complete in this environment - the Rust step wants a dev-server addr file that only exists under `tauri android dev`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |