Commit Graph
27 Commits
Author SHA1 Message Date
edde746 4c8272d5b1 refactor(trackers): drive Trakt through the tracker coordinator
Trakt was the one service outside the tracker abstraction. TraktScrobbleService
re-implemented the whole playback lifecycle beside TrackerCoordinator, and
TraktSyncService pushed watched state from its own WatchStateNotifier
subscription, so the player called two objects at every lifecycle point and one
watch could be written twice. TraktTracker now implements RealtimeScrobbleTracker
like Simkl; the duplicated player call sites collapse to one each, and Trakt
shares the coordinator's ID resolver instead of re-fetching show ids every
episode.

Capabilities are split so a tracker declares what it is rather than being
special-cased: ScrobblePolicy carries each service's own resend/seek rules,
EpisodeHistoryTracker names the remote row a per-item history write targets, and
SeriesProgressTracker covers one-counter-per-series services. Writes from all
four trackers go through a shared TrackerWriteQueue, generalised from the
Trakt-only queue, with the legacy Trakt payload migrated on load. Trakt becomes
the fourth TrackersProvider slot and TraktAccountProvider is deleted, so one
object owns the active session per profile.

Two failure paths found while consolidating are fixed here too.

The queue's retries only ran on profile bind, connect and app foreground, so a
network blip mid-session left queued watches waiting for the next foreground.
OfflineModeProvider now notifies on connectivity changes, not just offline-state
or WiFi-flag changes, and main.dart flushes the queue when the network returns.

The queue also counted every failure toward the five attempts that permanently
drop an item, so a rate limit or a service having a bad hour could discard a
pending watch - the loss the queue exists to prevent. Only an answer about the
write itself now spends an attempt: 4xx counts, while rate limits, 5xx,
recoverable token-refresh failures and requests that never arrived do not. A
back-off answer also defers that service for the rest of the flush, so a queue
holding many rows does not fire all of them at a service that just asked for
quiet.
2026-07-30 14:51:32 +02:00
edde746 a56b9a3dfb Merge the deduplication and dead-code removal pass
Consolidates duplicated logic behind shared implementations — paginated
grid tabs, focus chrome, cached remote stores, sheet selection columns,
the server artifact store and a test fixture layer — and removes code
that had become unreachable. Net reduction of about 5,500 lines with no
behaviour change.

Where a fix had landed separately in code that moved into a shared
helper, the fix was re-applied inside the helper rather than left behind
in the copy that went away.
2026-07-26 19:41:23 +02:00
edde746 4307c49cd2 refactor: remove unreachable code paths and unused members
Drops dead code across services, models, utils and widgets, including the
connection auth service, which had no implementer, and the Live TV DVR
provisioning models, which had no caller.

Tests that only covered deleted behaviour are removed or trimmed. No
behaviour change.
2026-07-26 06:09:47 +02:00
edde746 4af77f4696 fix(app): restore playback and state lifecycle contracts 2026-07-25 16:16:04 +02:00
edde746 e0bf66eea8 fix(runtime): harden application service boundaries 2026-07-24 03:46:46 +02:00
edde746 e32fcc2190 feat(explore): add AniList, Simkl, and Plex catalogs 2026-07-20 10:28:31 +02:00
edde746 2101f1d7f0 perf: isolate focus and media rebuilds 2026-07-12 19:00:11 +02:00
edde746 7ecadffdb1 refactor(features): consolidate shared feature primitives 2026-07-12 17:31:13 +02:00
edde746 aa230983d5 refactor(navigation): centralize sidebar focus 2026-07-12 08:42:22 +02:00
edde746 04daf89a20 feat(explore): Explore tab with catalog detail, search, and Seerr requests 2026-07-10 07:10:15 +02:00
edde746 7d6a747aa7 feat(music): now-playing, mini-player, queue and lyrics UI
Persistent mini-player over the profile navigator (route-aware
suppression, bottom-bar inset), slide-up now-playing screen with
mobile/desktop/TV layouts (blurred-art background, pause shape morphs,
dpad seek chain), queue sheet with reorder/remove/jump, synced lyrics
view, TV rail now-playing item, sleep timer, and audio playlist
playback. Adds download affordances on music surfaces.
2026-07-05 21:50:11 +02:00
edde746 422db75b5b feat(music): mpv audio playback engine with gapless queue service
Audio-only mpv core on every platform (dedicated
com.plezy/mpv_audio_player channels): parameterized android/windows/
linux mpv plugins and a new apple MpvAudioPlayerCore, all skipping
video/window paths (vid=no, audio-display=no, gapless-audio=weak).
MusicPlaybackService drives an in-memory queue with shuffle/repeat,
file-loaded-event gapless arming (property edges coalesce and the
android bridge drops them), per-track progress reporting, OS media
controls, audio focus, sleep timer, and error auto-skip.
PlaybackCoordinator enforces one live native player: starting video
disposes the audio core first.
2026-07-05 19:26:28 +02:00
edde746 05a631415e feat(music): music browsing UI — square cards, library groupings, artist/album screens
Un-gates music libraries; adds CardShape.square plumbing (circular
artists), artists/albums/tracks browse groupings with per-grouping
sorts, audio playlists tab, artist + album detail screens with dpad
track rows, music context-menu actions, and a stub MusicPlaybackService
seam for the upcoming engine.
2026-07-05 17:20:28 +02:00
edde746 87aea49ab6 fix(servers): stop rebinds from flashing an empty home screen after sign-in
Signing in triggered two back-to-back profile rebinds; the second re-added
the same Jellyfin connection, which tore down the live client and aborted
the home screen's in-flight fetches. The aborted pass was committed as
loaded-empty, flashing 'no content available' until the follow-up load
landed. Fix at the root instead of patching the sign-in window:

- addJellyfinConnection now reuses the live client when the connection is
  unchanged (token, deviceId, URL set), matching the existing Plex
  refreshTokensForProfile behavior; material changes still recreate it.
- Cancelled requests are classified end-to-end: the client's
  treat-as-empty helpers rethrow cancellations, and the aggregation
  fan-outs report cancelledServerIds alongside succeededServerIds.
- A fetch pass in which zero servers succeeded is never authoritative:
  it keeps existing content instead of wiping it (also fixes the
  pre-existing blanking of home/sidebar on a totally failed refresh),
  stays in loading while disrupted (cancellation or binding in flight),
  and only commits loaded-empty on a settled failure.
2026-07-04 23:44:38 +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 f9123eb40f fix(profiles): binder settle, active-id, and rebind correctness 2026-07-02 11:41:25 +02:00
edde746 cd1978ee1c fix: scope hidden libraries to profiles
close #1388
2026-06-23 00:21:01 +02:00
edde746 6f39a286d3 fix(profiles): remount profile session
close #1371
2026-06-18 00:53:48 +02:00
edde746 2b34f4a9d7 perf(tv): reduced visual-effects tier for low-end devices 2026-06-12 06:30:38 +02:00
edde746 1ef4032666 feat: add startup section setting
close #1240
2026-06-06 13:08:02 +02:00
edde746 2479e1faaa feat: tvos support 2026-04-24 14:11:24 +02:00
edde746 3da51f9d64 chore: pre-commit ci hook, dart format 2026-04-18 12:40:35 +02:00
edde746 db6161d84e refactor: replace numeric tab indexes with NavigationTabId 2026-03-15 22:31:54 +01:00
edde746 403b1f6776 feat: live tv 2026-02-11 16:27:49 +01:00
edde746 6e9b78e5b5 fix: missing translations, simplify translations 2026-02-10 21:37:27 +01:00
edde746 3c89d0eba8 refactor: update formatting 2025-12-15 02:29:03 +01:00
edde746 18c322f66a refactor: navigation/offline handling
and other improvments
2025-12-13 00:16:50 +01:00