Commit Graph
100 Commits
Author SHA1 Message Date
edde746 6d95e35448 feat(tvos): AVPlayer Atmos sink wiring + Atmos output diagnostics
Re-enables Audio Passthrough on Apple TV against the MPVKit EAC3-JOC
AVPlayer sink (pin bump to v1.0.8 follows), adds an AVPlayer test
harness + diagnostics screen for #1300, and makes loudnorm yield while
passthrough is active (fixes a latent spdif conflict on desktop too).
2026-07-02 15:52:10 +02:00
edde746 86abf3e9da fix(watch-together): retry guest media switches until they commit
Guest switch dispatch pre-marked its dedup key and fired-and-forgot, so
any failure (fetch error, reload busy with an auto-advance, navigation
race with the host exiting) silently stranded the guest on the old media.
A CurrentPlaybackDispatcher now marks a key handled only after the sink
reports success against the committed identity, with a serialized
in-flight slot, timeout, and generation reset; the reconciler re-offers
unattached media on every host heartbeat, making the heartbeat the retry
channel. Fetches that outlive their dispatch are re-validated against the
current snapshot so a stale switch can't override the live one.
hostExitedPlayer now rides the controller's ordered message queue with
host authentication instead of racing state handling in the provider.
2026-07-02 12:44:15 +02:00
edde746 0e3c592205 fix(windows): marshal mpv events onto the platform thread
close #1453

Events were delivered to the Flutter event sink directly on the mpv event
thread while method replies were already marshaled; concurrent messenger
use from two threads intermittently crashed guests during the event burst
of an in-place media switch. Also joins the event thread before draining
platform tasks in the plugin destructor (reverse member destruction order
would otherwise let the event thread enqueue into a destroyed queue) and
coalesces the wakeup PostMessage behind a retry-safe flag.
2026-07-02 12:43:10 +02:00
edde746 5f49dddb4d feat(ui): M3E restyle for settings, auth, and profile screens 2026-07-02 11:47:43 +02:00
edde746 074f92d144 fix(tv): bleed the unfocused-rail dim under the side nav
The rail dim (and its top fade band) was clipped to the rail's footprint,
so it terminated in a vertical seam at the nav edge while the backdrop
continued behind the nav. Generalize _RailBackgroundBleed into
_RailBleedPositioned and render the dim through it, full-width like the
background gradient. Row stripes now apply only while the rail itself is
focused — under the full-width dim they'd re-introduce level seams at the
nav edge (and read as noise anyway).
2026-07-02 11:41:25 +02:00
edde746 6274facc3c fix(tv): fade dim-scrim edges instead of hard rect boundaries
Unlike the content opacity it replaced, the dim quad also darkens the
backdrop showing through around the rows, so its rectangle edge read as
a hard line across the spotlight artwork. Ramp the dim in over narrow
top/bottom gradient bands (flat quad interior, non-AA to avoid seams);
band area keeps the gradient-shader cost negligible on weak TV GPUs.
Browse pass on the Mali-G31 box unchanged: draw p50 7.2ms, 2% janky.
2026-07-02 11:41:25 +02:00
edde746 b08b3b846a perf(tv): rasterize axis-aligned gradients into strip textures
Skia's dithered gradient shaders cost ~10ms per full-screen pass on
Mali-class TV GPUs: the two spotlight scrims alone were ~20ms of a 27ms
raster frame, while flat blended quads at the same coverage are ~free.
Bake axis-aligned LinearGradients once into cached 1x1024 premultiplied
strip textures drawn as stretched quads (shader fallback for unsupported
shapes and the first frame). Converted the spotlight, TV detail backdrop,
app-bar scrims, rail bleed, person-card overlay, and the video-controls
scrim, which now also keeps one widget type across hasFrame flips so the
controls subtree survives in-place source switches.

Scripted-browse on a Mali-G31 box: draw p50 27.5ms -> 7.1ms, swap block
20.3ms -> 0.9ms, janky draws 69% -> 2%; screenshots pixel-identical.
2026-07-02 11:41:25 +02:00
edde746 1059658515 refactor(profiles): remove dead registry surface
Delete unused registry members (ProfileConnectionRegistry.insertIfAbsent /
removeAllForProfile, ProfileRegistry.reorder, ProfilesView.countFor,
ConnectionRegistry.getDefault) and their orphan tests, refreshing the stale
docs that named removeAllForProfile as the profile-delete cleanup path.

Repair the "one default per profile" join-row invariant: the connectionId FK
cascade (foreign_keys=ON) silently drops a profile's default row while its
other rows survive, leaving it defaultless. Add promoteMissingDefaults, share
a deterministic re-promotion helper with remove(), and re-promote in
removeAllForConnection.
2026-07-02 11:41:25 +02:00
edde746 d193633a5d fix(remote): live auth-context refresh + lifecycle races
Keep a running companion-remote host's crypto identity in sync with the
active profile: subscribe to PlexHome/connection/join streams and rebuild
auth contexts (restarting the broadcast when they change) so a removed
home user or revoked borrowed connection stops controlling the host.

Serialize host start/stop/crypto-rebuild through a lifecycle lock, clean
up peer subscriptions before re-listening, and guard the replaced-client
onDone against clobbering the new client's session. Drop the context.mounted
guards that aborted an app-level host start, fix the DiscoveryView
init-flash/stuck-on-throw, and delete the dead initialize*Crypto helpers.
2026-07-02 11:41:25 +02:00
edde746 2b7142bdcd fix(downloads): profile-scoped ownership and watch-sync integrity 2026-07-02 11:41:25 +02:00
edde746 44be03d39c refactor(profiles): shared auth/mint flows + screen fixes 2026-07-02 11:41:25 +02:00
edde746 f9123eb40f fix(profiles): binder settle, active-id, and rebind correctness 2026-07-02 11:41:25 +02:00
edde746 2025e1f9fd fix(profiles): clean up orphaned connections on Plex sign-out
close #1423
2026-07-02 11:41:25 +02:00
edde746 6e8320f782 fix(profiles): parse real Plex Home uuids + migrate pref scopes 2026-07-02 11:41:25 +02:00
edde746 bfcd11538e fix(security): redact Plex Home PIN from logs 2026-07-02 11:41:25 +02:00
edde746 72d37f2362 perf(tv): dim action bars once at row level while unfocused
In d-pad mode every unfocused FocusableActionBar button held its own
AnimatedOpacity(0.6) — 4-5 permanent saveLayers (one render pass each
on tiled TV GPUs) on discover and detail alike, every frame. While no
button in the row has focus (the entire time the user browses content)
the whole row now shares a single dim layer; per-button dims apply only
while the row holds focus.
2026-07-02 11:41:25 +02:00
edde746 e8a99c1108 fix(tv): harden spotlight crossfade broken-artwork path
The base image shared the incoming's fade-riding errorBuilder, so a
404'd backdrop flashed transparent on the next swap, could start the
fade before any frame existed, and an errored provider got promoted
into the base (re-resolve loop). Base now uses a static fallback,
error/frame state is tracked per incoming (keyed by provider), and
promotion settles on the fallback color when no frame ever arrived.
2026-07-02 11:41:25 +02:00
edde746 48568fd412 perf(tv): exclude inactive hub rows from semantics
Their cards can't take focus until the row activates (locked-hub
model), and the per-frame semantics pass scales with node count.
2026-07-02 11:41:25 +02:00
edde746 320bde7f33 perf(tv): spotlight backdrop cross-fades by paint alpha
The whole-stack AnimatedSwitcher kept two full-screen saveLayers (each
compositing backdrop + two full-screen gradients) blending on every
focus move — with CachedNetworkImage's own fade nested inside, the
dominant GPU load while browsing. Gradients are identical between items
so they never fade now; the incoming artwork fades in via Image.opacity
over the still-opaque previous one (no placeholder flash), and only the
bounded info block keeps a real cross-fade.
2026-07-02 11:41:25 +02:00
edde746 868a1469a3 perf: slim per-card build cost
Memoize the per-image SHA-1 disk-cache key (ran on the UI thread on
every image build), fade images in via paint alpha instead of an
AnimatedSwitcher saveLayer per in-flight tile, create SettingsBuilder's
merged listenable once instead of per build, and drop the pointer
chrome (InkWell ink machinery, cursor MouseRegions) from cards on TV
where no pointer exists.
2026-07-02 11:41:25 +02:00
edde746 43ab5d3246 perf: shrink semantics tree on media lists
Poster images are decorative (the card exposes one merged node), and
the default per-child AutomaticKeepAlive/_SelectionKeepAlive/
IndexedSemantics wrappers are inert here — no keep-alive clients or
SelectionArea exist. The semantics phase ran ~9ms every frame on TV
devices with an accessibility service; it scales with node count.
2026-07-02 11:41:25 +02:00
edde746 c38f24aee9 perf(tv): isolate rail rebuilds; dim rows via scrims, not opacity
Hub moves, focus flips and item selects now flow through the rail focus
model + ListenableSelectors (two headers/cards repaint instead of every
visible card rebuilding). DiscoverScreen memoizes the hubs list, gates
provider notifies on a render signature and caches the rail widget so
no-op refreshes skip the subtree entirely. The whole-rail 0.6 and
inactive-row 0.7 AnimatedOpacity layers are replaced by AnimatedDimScrim
quads, removing the permanent per-frame saveLayers that kept low-end TV
GPUs raster-bound.
2026-07-02 11:41:25 +02:00
edde746 a5041cb3db perf(tv): opaque detail route + isolate focused-episode updates
Covered routes stop painting/building once the fade settles, and d-pad
episode scrubbing rebuilds only the foreground info panel instead of
the whole screen with its rail.
2026-07-02 11:41:25 +02:00
edde746 7143bb380f fix(tv): skip desktop hover-arrows machinery on TV 2026-07-02 11:41:25 +02:00
edde746 d5df426ab6 build(libass): bump to 0.18.2 2026-07-02 11:41:24 +02:00
edde746 1d2dea214c ci(windows): set up arm64 Flutter 3.44.0 from git tag 2026-07-01 07:10:24 +02:00
edde746 e07f54921c ci(windows): install patched DComp engine for x64 and arm64 2026-07-01 06:37:51 +02:00
edde746 ba112d7aa6 refactor(windows): remove legacy mpv compositing, require DComp engine 2026-07-01 06:37:35 +02:00
edde746 28e6e349b3 fix(android): restore ExoPlayer audio for tunneled decoded PCM 2026-06-30 18:58:08 +02:00
edde746 2d30686857 fix: decouple library grouping from provider context 2026-06-30 06:57:21 +02:00
edde746 ea86ce5a4b fix(android): preserve bitmap subtitle aspect
close #1444
2026-06-30 02:31:18 +02:00
edde746 4cf94683ae fix: send correct streamID for same-language forced subtitles
close #1443
2026-06-29 07:10:25 +02:00
edde746 6c96830033 fix(android): never-drop multi-page subtitle atlas 2026-06-29 02:31:14 +02:00
edde746 ec1473af5e fix(android): tile oversized subtitle images so the atlas never drops them 2026-06-28 21:49:19 +02:00
edde746 79b75483bd style: fix CI formatting 2026-06-27 10:36:21 +02:00
edde746 78090d8bd6 refactor(trackers): unify session and account store across services
Replace the per-tracker json_serializable session classes and account stores with a shared TrackerSession (service-aware persisted validation), a single TrackerAccountStore, a shared TrackerHttpClient, and an AnimeListTrackerBase mixin for MAL/AniList. Scope the per-service rebind guard so a disconnect can't abort a racing profile load. Add migration-safety, MAL refresh, episode-count cache, and content-type tests.
2026-06-27 10:05:03 +02:00
edde746 2fe0fdb975 fix: hide player queue spoilers
close #1426
2026-06-27 07:22:21 +02:00
edde746 930534ee31 fix: avoid duplicate timeline seek
close #1421
2026-06-27 07:05:06 +02:00
edde746 3b611a1e18 fix: avoid early playback completion 2026-06-27 06:46:32 +02:00
edde746 120749e442 fix(android): regenerate libass prebuilt archive 2026-06-27 06:43:37 +02:00
edde746 d333ac2382 fix(apple): pin MPVKit 1.0.6 2026-06-27 06:03:07 +02:00
edde746 c3ca6e4c49 fix: clear subtitle overlays when disabling subtitles
close #1387
2026-06-26 10:09:45 +02:00
edde746 ad6ed04901 style: abbreviate episode date on TV media detail
close #1380
2026-06-26 08:48:30 +02:00
edde746 25e5ea042f fix: server-qualify TvBrowseRail hub keys to avoid duplicate GlobalKey 2026-06-26 08:34:54 +02:00
edde746 4462b44e9b fix: show server name on TV hubs with multiple servers
close #1319
2026-06-26 07:57:21 +02:00
edde746 7df969cb90 style: compact episode rows, align thumbnails to page margin 2026-06-26 07:40:51 +02:00
edde746 719f317b5d feat: show genres on the media detail screen
close #1390
2026-06-26 07:16:39 +02:00
edde746 c32806d987 fix: show server name on all hubs with multiple servers
close #1319
2026-06-26 05:16:41 +02:00
edde746 86637012dc fix: show server name on all libraries with multiple servers
close #1319
2026-06-26 04:54:28 +02:00
edde746 bd7f37a3f6 test: align spoiler progress expectation 2026-06-26 01:30:06 +02:00
edde746 d5c575cbfe fix: keep download toggle label on one line 2026-06-26 01:19:38 +02:00
edde746 f29030c3a0 fix: correct jellyfin trickplay sheet geometry
close #1417
2026-06-26 00:26:26 +02:00
edde746 f04691d321 feat: add "Include Specials" toggle to the show download dialog
The aired-order rework can sweep correctly-placed Specials into "download
next N"; this toggle lets users opt out. Shown only for whole shows
(reusing FocusableSwitchListTile via an optional toggle on the shared
option-picker dialog), remembered across opens via a BoolPref
(default on = unchanged behavior). Filters Specials at the single
collect choke point (_collectPlayable), with a guard so explicitly
downloading the Specials season still queues its episodes.
2026-06-25 23:41:31 +02:00
edde746 dbe804f8db fix: order episodes by air date for offline, Jellyfin, and downloads
Extends the Plex play-queue fix (#1416) to the shared episode comparator
so Specials interleave by air date everywhere, not just Plex streaming:
offline next/prev, the Jellyfin online queue, offline OnDeck, and the
download/sync "next N" selection. Undated episodes fall back to
Specials-last, preserving the #1414 "never front-load the Specials
folder" guarantee. Jellyfin queue now requests PremiereDate.
2026-06-25 23:05:16 +02:00
edde746 37e4153602 fix(plex): interleave Specials in show play queue
close #1416
2026-06-25 19:45:58 +02:00
edde746 b0b14bcd18 fix: hide episode spoilers until marked watched
close #1397
2026-06-25 11:13:57 +02:00
edde746 791433bceb fix: download and queue episodes in watch order, Specials last
close #1414
2026-06-25 10:47:13 +02:00
edde746 e90835c234 fix(ci): restore sanity checks 2026-06-25 07:21:16 +02:00
edde746 8affbb7af6 fix(tvos): align embedded framework minimum os 2026-06-25 06:19:29 +02:00
edde746 21c4ab430e feat(android): tune frame rate and subtitle rendering 2026-06-24 01:34:03 +02:00
edde746 c9dc15b1d8 fix(android): improve libass frame timing 2026-06-24 01:26:46 +02:00
edde746 b4967ca075 fix: expose offline settings 2026-06-23 05:11:39 +02:00
edde746 cd1978ee1c fix: scope hidden libraries to profiles
close #1388
2026-06-23 00:21:01 +02:00
edde746 a5e422d284 fix(trackers): parse new Fribb imdb_id/themoviedb_id shapes
close #1402
2026-06-22 23:58:17 +02:00
edde746 5a1d378b42 fix(player): stop writing show-wide track defaults 2026-06-21 16:23:54 +02:00
edde746 0d78020fbf fix(images): reduce artwork decode pressure 2026-06-18 18:00:23 +02:00
edde746 7e1d5ad4c4 fix: add Jellyfin episode-added sort
close #1274
2026-06-18 16:22:01 +02:00
edde746 94f2daa22e feat: add episode action setting
close #1351
2026-06-18 11:16:38 +02:00
edde746 075e4aeb32 fix(player): restore OSD auto-hide
close #1360
2026-06-18 10:18:57 +02:00
edde746 52d70dd97d fix(libraries): add Plex TV date added sort
close #1369
2026-06-18 09:05:09 +02:00
edde746 d9b03160f0 fix(video-controls): activate skip marker on select when controls hidden
close #1374
2026-06-18 07:59:26 +02:00
edde746 b11c63f557 fix: restore sidebar focus visibility 2026-06-18 04:29:34 +02:00
edde746 a75cf5fd35 fix(player): dismiss prompts on back
close #1373
2026-06-18 03:25:30 +02:00
edde746 6f39a286d3 fix(profiles): remount profile session
close #1371
2026-06-18 00:53:48 +02:00
edde746 66b80a33ba fix(libraries): preserve Jellyfin alpha focus
close #1367
2026-06-17 20:55:26 +02:00
edde746 84b9eac09b fix(ci): restore sanity checks 2026-06-16 22:43:56 +02:00
edde746 39788ab64a fix(android): guard missing HDR capabilities 2026-06-16 22:00:19 +02:00
edde746 4cd289b4b8 fix(profiles): forget removed Jellyfin connections
close #1355
2026-06-16 20:08:47 +02:00
edde746 d49bd20fa0 fix(libraries): restore top-row focus escape
close #1354
2026-06-16 16:03:18 +02:00
edde746 618251b8eb fix(player): attach external subtitles during open 2026-06-15 17:21:08 +02:00
edde746 9437956b83 fix(livetv): keep timeline heartbeat on active endpoint 2026-06-15 14:59:06 +02:00
edde746 f602925896 fix(trakt): persist refreshed auth sessions
close #1347
2026-06-15 14:42:24 +02:00
edde746 1aecb9d2d2 fix(trakt): publish refreshed sessions 2026-06-15 14:42:18 +02:00
edde746 4a5731976a refactor(platform): centralize Apple TV detection 2026-06-15 13:32:54 +02:00
edde746 8198ea9522 fix(android): wire ExoPlayer passthrough control 2026-06-15 13:31:42 +02:00
edde746 e069d30555 fix(android): block direct audio without passthrough 2026-06-15 13:28:54 +02:00
edde746 1aa06ffe90 fix(tv): restore passthrough setting visibility 2026-06-15 13:28:38 +02:00
edde746 1b29cb3ef7 fix(player): apply stored passthrough setting 2026-06-15 13:28:23 +02:00
edde746 ba22dca9e5 fix(platform): gate audio passthrough support 2026-06-15 13:28:10 +02:00
edde746 b5a9f09f12 fix(player): wait for autoplay subtitle tracks
close #1348
2026-06-15 13:09:09 +02:00
edde746 8bf5dbb379 fix(player): resume mpv startup frame after subtitles 2026-06-15 12:06:04 +02:00
edde746 5fc599439e fix(player): wire playback streams before open 2026-06-15 12:05:48 +02:00
edde746 27723e6f29 fix(video): sync first-frame background state 2026-06-15 12:05:29 +02:00
edde746 a4c444435f fix(player): avoid overlapping performance stat fetches 2026-06-15 12:05:15 +02:00
edde746 6292685b5d fix(player): fetch Android mpv stats off main thread 2026-06-15 12:04:58 +02:00
edde746 7195702242 fix(player): repair Plex transcode seeking
close #1341
2026-06-14 23:39:05 +02:00
edde746 01a5d11ef5 fix(jellyfin): use season episode endpoint 2026-06-14 18:34:12 +02:00
edde746 5e2bd4efa8 fix(video): release scrub chrome hold
close #1340
2026-06-14 18:34:12 +02:00
edde746 d6487e24c9 fix(tv): keep sidebar transparent 2026-06-14 14:53:56 +02:00
edde746 c404589382 style(native): fix formatting 2026-06-14 14:04:52 +02:00