56 Commits
Author SHA1 Message Date
edde746 74d3af3ae1 perf(home): load the home screen once instead of twice per cold start
The Discover tab fanned out its whole request set twice on every cold
start and replayed slow rows on a shrinking timeout ladder, so a healthy
remote server produced anywhere from 4s to 15s of loading.

Measured against a remote Jellyfin server with four libraries, 24
interleaved cold-start samples per side:

  requests  19 -> 9      payload  219 KB -> 94 KB
  settled   5231ms -> 2502ms median, 13222ms -> 5927ms p95

Four independent causes:

- Retry policy. `Client.send` resolves on response headers, so the
  connect budget covers the server's think time and a slow-but-alive
  query raises `connectionTimeout`. Replaying it made the server re-run
  the query with a shorter budget than the one it just missed; the
  `[10s, 8s, 5s]` ladder turned an 11s answer into an empty row after
  23s. Hub surfaces now get one whole-request deadline, retry only
  immediate connection errors, and the deadline bounds the whole call
  including the request still in flight.

- Request shape. `/Items/Latest` groups a TV library by series, so its
  rows are Series folder dtos and `RecursiveItemCount`/`ChildCount` cost
  a DB count each, per row. Hub rows now ask for `Overview` only; watch
  state survives because Jellyfin derives `UserData.Played` from
  `UnplayedItemCount` when the count fields are absent. `/Shows/NextUp`
  sends `NextUpDateCutoff` to bound the server's series-key scan, and
  `Thumb` leaves `EnableImageTypes` since nothing reads it. `UserData`
  and `PremiereDate` leave the browse set: neither is an `ItemFields`
  member, so the server dropped them anyway.

- Fan-out. Per-library hubs ran in batches of three separated by a
  barrier, so one slow library stalled every library behind it. A
  sliding window keeps the same peak concurrency without head-of-line
  blocking. Concurrent `fetchLibraries` calls now share one `/Views`
  instead of racing two identical round trips, Plex's global and music
  hub legs start together, and Jellyfin gets Plex's pool tuning.

- Duplicate pass. `DiscoverScreen.initState` starts a load and the
  online-entry hook asked for a full refresh on top of it, which
  `CoalescedLoadCoordinator` correctly queued as a trailing pass. The
  hook now calls `primeRefresh`, which rides along with a load already
  in flight; profile switches still go through `fullRefresh`.

Refs #1784
2026-08-04 04:35:06 +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 1fea9ef6e3 fix(search): recover omitted Plex media categories
close #1598
2026-07-26 14:58:38 +02:00
edde746 9429a76acc refactor: share search field, auth dialog, and list-download plumbing
The search screens, the out-of-band auth dialogs, the live TV guide and the
list-download paths each carried their own copy of the same shell. Extracts
SearchInputField and PendingAuthDialog and routes the duplicated download
and guide helpers through one implementation.
2026-07-26 06:09:49 +02:00
edde746 352b88109b refactor: extract shared mixins and helpers, drop dead abstractions
Introduces shared seams for paginated views, D-pad reorder, media control
routing, async singletons and the device method channel, then points the
open-coded copies at them.

Also removes unused models and duplicated provider/server plumbing, folds
the twice-implemented artifact store in the server, and factors the
repeated Flutter toolchain prologue in CI into a composite action.
2026-07-26 06:09:48 +02:00
edde746 102ef46d00 feat(jellyfin): lazily page recently added hubs
close #1611
2026-07-24 20:29:21 +02:00
edde746 b41fb4fe75 fix(ui): harden settings focus and semantics 2026-07-24 03:46:50 +02:00
edde746 d5f3e581df fix: eliminate cross-app consistency drift 2026-07-13 23:13:53 +02:00
edde746 0ef1e773bb fix: scope navigation callbacks to active owners 2026-07-12 18:59:27 +02:00
edde746 cd88f73f05 fix: serialize async state transitions 2026-07-12 18:59:14 +02:00
edde746 97f7508067 refactor(core): consolidate shared app foundations 2026-07-12 17:31:12 +02:00
edde746 aa230983d5 refactor(navigation): centralize sidebar focus 2026-07-12 08:42:22 +02:00
edde746 8a8b4f3a61 refactor: remove unused convenience APIs 2026-07-12 08:42:20 +02:00
edde746andl3gitpanda b46107cb58 fix(tv): dismiss on-screen keyboard on companion-remote search submit
close #1514

A query submitted from the companion remote now behaves like a submit
instead of focus-to-type: TvKeyboardController closes an already-open
OSK and lands focus on the input without reopening it, then the shared
handleSearchSubmit path runs the search and focuses the first result.
Also guard DebouncedMediaSearch against selection-only controller
notifications re-arming the debounce into a duplicate fetch.

Co-authored-by: l3gitpanda <12003346+l3gitpanda@users.noreply.github.com>
2026-07-10 08:48:38 +02:00
edde746 04daf89a20 feat(explore): Explore tab with catalog detail, search, and Seerr requests 2026-07-10 07:10:15 +02:00
edde746 ef75887504 style: apply analyzer lint fixes across lib
Initializing formals, unawaited() on fire-and-forget futures, unused
import removal, wildcard params, and mounted vs context.mounted.
2026-07-06 15:56:56 +02:00
edde746 d816d82a38 fix(folders): row context menus, dpad left to sidebar, faster Jellyfin listings 2026-06-12 02:00:42 +02:00
edde746 32421e4c84 fix(tv): reach app bar actions via up from tabs
close #1202
2026-06-06 08:51:08 +02:00
edde746 145881318e fix: harden server-scoped state 2026-06-04 13:47:06 +02:00
edde746 74b8dc4561 refactor: type server identifiers 2026-06-01 11:06:03 +02:00
edde746 eeaa831cc2 fix(search): guard stale refresh callbacks 2026-05-24 07:37:02 +02:00
edde746 fea973a72a fix(tv): smooth sidebar expansion behavior 2026-05-22 03:54:34 +02:00
edde746 c855dba3be fix(media): paginate large server lists 2026-05-17 20:25:39 +02:00
edde746 3a6012cc21 fix(lifecycle): guard async state updates 2026-05-12 06:11:14 +02:00
edde746 ed4be7b96d refactor: strip obvious comments 2026-05-04 22:40:18 +02:00
edde746 244b291255 refactor: share controller disposal and Plex DTO parsing 2026-05-02 09:43:08 +02:00
edde746 130e0d6f40 refactor: streamline settings bindings 2026-05-02 08:44:27 +02:00
edde746 31d2d9dc98 feat: jellyfin 2026-05-01 01:20:36 +02:00
edde746 d0a93d57dd refactor: codebase review cleanup 2026-04-25 03:16:11 +02:00
edde746 eb49ead83b fix: paginate collection/playlist/person endpoints
close #903
2026-04-21 21:51:20 +02:00
edde746 ee020d81bd refactor: trakt/download hardening and cleanup sweep 2026-04-21 13:57:03 +02:00
edde746 3da51f9d64 chore: pre-commit ci hook, dart format 2026-04-18 12:40:35 +02:00
edde746 8d56171bd2 perf: library grid scroll and idle frame rendering
- Window _loadedItems and focus nodes to bound memory growth
- Eager prefetch and image precaching near viewport
- Static skeleton placeholders during active scroll
- Throttle alpha bar updates, dynamic initial fetch size
- Fix discover timer scheduling frames when tab hidden
- Disable tickers for offscreen IndexedStack children
- Static image placeholder with fade-in transition
2026-03-24 17:19:28 +01:00
edde746 db6161d84e refactor: replace numeric tab indexes with NavigationTabId 2026-03-15 22:31:54 +01:00
edde746 e0d9b4ee93 refactor: unify focus restoration for main screen tabs
Replace per-tab if-chains in _focusContent() and _selectTab() with
generic FocusableTab/TabVisibilityAware dispatch. Fixes search screen
focus on Android TV (sidebar → Search now works).
2026-03-15 21:55:22 +01:00
edde746 551be5bbef feat: dynamic library tabs and shared library navigation
- Replace hardcoded 4-tab system with data-driven visible tab list
- Shared libraries show only Browse + Playlists tabs
- Fix dpad navigation for shared libraries (no hidden tab targets)
- Switch to TickerProviderStateMixin to support tab controller recreation
- Navigate to library screen when tapping shared library sections
- Persist tab selection by name instead of index
2026-03-15 21:36:17 +01:00
edde746 c1e2bc36ea refactor: share Apple MPV core and media helpers 2026-03-06 10:16:33 +01:00
edde746 e6ee83d9c2 fix: preserve home screen scroll position on back navigation 2026-03-04 16:34:36 +01:00
edde746 edbe2a06be refactor: deduplicate sheet, key handler, and service patterns 2026-02-23 10:25:57 +01:00
edde746 04438c8e45 refactor: code quality & format 2026-02-15 04:07:09 +01:00
Matt Vogel 372767b142 Add Companion Remote for mobile-to-desktop control 2026-02-09 14:19:54 -05:00
edde746 bbee74ef9d fix(propagation): scope events by server 2026-02-06 09:58:57 +01:00
Micah Morrison f6aa8e51e0 Improve media deletion propagation throughout the app 2026-02-05 21:55:04 -05:00
edde746 3d3c8641ed fix: suspend hero animation when not visible 2026-02-05 10:57:29 +01:00
edde746 a7ac681fdc refactor: extract shared mixins and helpers 2026-02-04 11:11:01 +01:00
edde746 1d67a5d992 feat: reactive watch state updates 2026-01-01 22:05:55 +01:00
edde746 18c322f66a refactor: navigation/offline handling
and other improvments
2025-12-13 00:16:50 +01:00
edde746 d9ea099727 refactor: deduplicate 2025-12-07 15:00:28 +01:00
edde746 7b0aa12c38 refactor: remove keyboard navigation 2025-12-05 23:29:37 +01:00
edde746 8f817815e6 refactor: simplify file structure 2025-12-04 08:36:07 +01:00