feat(tvos): fetch Top Shelf content live and show poster art
The Top Shelf extension now fetches Continue Watching directly from Plex/Jellyfin/Emby instead of replaying a cache the app wrote on its last foreground Discover pass. The app publishes per-profile server descriptors on every shelf sync (`updateSources`): token-free metadata in the app group, tokens in an app-group-shared keychain item, both wiped by `clear`. On success the extension rewrites the cached payload as the offline fallback; any fetch failure falls back to the previous cache-replay behavior. Poster images are passed as remote URLs, so the extension no longer depends on app-side artwork downloads. Episodes now render season/series poster art (2:3, `.poster` shape) instead of 16:9 episode stills, and labels lead with the S/E marker so long titles no longer hide it behind the focused-item marquee. Shelf schema v3 (Dart, Android, tvOS envelopes bumped together) discards stale wide-art caches instead of letterboxing them into poster slots. close #1474 close #1835
This commit is contained in:
@@ -82,10 +82,12 @@ class DiscoverProvider extends ChangeNotifier with DisposableChangeNotifierMixin
|
||||
required this.isProfileBinding,
|
||||
WatchStateStore? watchStateStore,
|
||||
Future<void> Function(String profileId, List<MediaItem>)? syncSystemShelf,
|
||||
Future<void> Function(String profileId, List<MediaServerClient> clients)? syncServerSources,
|
||||
// A private field cannot be a named initializing formal callers can pass.
|
||||
// ignore: prefer_initializing_formals
|
||||
}) : _watchStateStore = watchStateStore,
|
||||
_syncSystemShelfOverride = syncSystemShelf {
|
||||
_syncSystemShelfOverride = syncSystemShelf,
|
||||
_syncServerSourcesOverride = syncServerSources {
|
||||
_loadCoordinator = CoalescedLoadCoordinator<String>(onFull: _loadOnce, onDelta: _loadDeltaOnce);
|
||||
// Late server connects (reconnect after outage, slow wave) refresh
|
||||
// discover the same way they refresh libraries. Removed in [dispose] so a
|
||||
@@ -162,6 +164,7 @@ class DiscoverProvider extends ChangeNotifier with DisposableChangeNotifierMixin
|
||||
/// load once binding settles).
|
||||
final bool Function() isProfileBinding;
|
||||
final Future<void> Function(String profileId, List<MediaItem>)? _syncSystemShelfOverride;
|
||||
final Future<void> Function(String profileId, List<MediaServerClient> clients)? _syncServerSourcesOverride;
|
||||
|
||||
StreamSubscription<WatchStateEvent>? _watchStateSubscription;
|
||||
StreamSubscription<DeletionEvent>? _deletionSubscription;
|
||||
@@ -938,7 +941,16 @@ class DiscoverProvider extends ChangeNotifier with DisposableChangeNotifierMixin
|
||||
if (isDisposed) return;
|
||||
|
||||
try {
|
||||
// tvOS pulls Continue Watching itself; hand the Top Shelf extension
|
||||
// the current online server sources before publishing items.
|
||||
final sourcesOverride = _syncServerSourcesOverride;
|
||||
final syncOverride = _syncSystemShelfOverride;
|
||||
if (sourcesOverride != null) {
|
||||
await sourcesOverride(owner, _onlineShelfSourceClients());
|
||||
} else if (syncOverride == null) {
|
||||
await SystemShelfService().syncServerSources(owner, _onlineShelfSourceClients());
|
||||
}
|
||||
if (isDisposed) return;
|
||||
if (syncOverride != null) {
|
||||
await syncOverride(owner, onDeck);
|
||||
continue;
|
||||
@@ -972,6 +984,9 @@ class DiscoverProvider extends ChangeNotifier with DisposableChangeNotifierMixin
|
||||
throw Exception('No owning client available for $serverId');
|
||||
}
|
||||
|
||||
List<MediaServerClient> _onlineShelfSourceClients() =>
|
||||
_multiServer.serverManager.onlineClients.values.toList(growable: false);
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_multiServer.removeOnlineServersListener(syncToOnlineServers);
|
||||
|
||||
Reference in New Issue
Block a user