@@ -219,6 +219,9 @@ abstract class MediaServerClient {
|
||||
/// "More like this" recommendations for [id].
|
||||
Future<List<MediaHub>> fetchRelatedHubs(String id, {int count = 10});
|
||||
|
||||
/// Media featuring a specific person/actor.
|
||||
Future<List<MediaItem>> fetchPersonMedia(String personId);
|
||||
|
||||
/// Page through items in [hubId] when the hub previewed only the first N
|
||||
/// items (`MediaHub.more == true`). Plex hits `/hubs/{key}` (the same
|
||||
/// id used in [fetchGlobalHubs]); Jellyfin re-runs the synthesised query
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'package:material_symbols_icons/symbols.dart';
|
||||
import '../media/media_backend.dart';
|
||||
import '../media/media_item.dart';
|
||||
import '../media/media_kind.dart';
|
||||
import '../services/plex_client.dart';
|
||||
import '../media/media_server_client.dart';
|
||||
import '../utils/provider_extensions.dart';
|
||||
import '../widgets/desktop_app_bar.dart';
|
||||
import '../widgets/optimized_media_image.dart';
|
||||
@@ -15,10 +15,6 @@ import '../mixins/grid_focus_node_mixin.dart';
|
||||
import '../focus/focusable_action_bar.dart';
|
||||
|
||||
/// Screen to browse all media featuring a specific actor.
|
||||
///
|
||||
/// Plex-only today: uses `fetchAllPersonMediaAsMediaItems` which has no
|
||||
/// Jellyfin counterpart yet. Callers must guard the navigation by backend
|
||||
/// (see `_navigateToActorMedia` in media_detail_screen.dart).
|
||||
class ActorMediaScreen extends StatefulWidget {
|
||||
final String actorName;
|
||||
final String personId;
|
||||
@@ -75,13 +71,10 @@ class _ActorMediaScreenState extends BaseMediaListDetailScreen<ActorMediaScreen>
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
PlexClient get _plexClient => context.getPlexClientForServer(widget.serverId);
|
||||
MediaServerClient get _mediaClient => context.getMediaClientForServer(widget.serverId);
|
||||
|
||||
@override
|
||||
Future<List<MediaItem>> fetchItems() async {
|
||||
// Plex-only — guarded at the call site in media_detail_screen.dart.
|
||||
return _plexClient.fetchAllPersonMediaAsMediaItems(widget.personId);
|
||||
}
|
||||
Future<List<MediaItem>> fetchItems() => _mediaClient.fetchPersonMedia(widget.personId);
|
||||
|
||||
@override
|
||||
Future<void> loadItems() async {
|
||||
@@ -104,7 +97,7 @@ class _ActorMediaScreenState extends BaseMediaListDetailScreen<ActorMediaScreen>
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(40),
|
||||
child: OptimizedMediaImage(
|
||||
client: _plexClient,
|
||||
client: _mediaClient,
|
||||
imagePath: widget.actorThumb,
|
||||
width: 80,
|
||||
height: 80,
|
||||
|
||||
@@ -853,10 +853,6 @@ class _MediaDetailScreenState extends State<MediaDetailScreen>
|
||||
}
|
||||
|
||||
void _navigateToActorMedia(MediaRole actor) {
|
||||
// Plex-only today — Jellyfin's `/Persons/{id}/Items` isn't wired yet.
|
||||
// Cast cards still render for parity, but tapping is a no-op until the
|
||||
// Jellyfin path lands.
|
||||
if (_metadata.backend != MediaBackend.plex) return;
|
||||
final personId = actor.id;
|
||||
if (personId == null || _metadata.serverId == null) return;
|
||||
|
||||
|
||||
@@ -499,6 +499,26 @@ mixin _JellyfinBrowseMethods on MediaServerCacheMixin {
|
||||
return _mapItems(_itemsArray(response.data));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<MediaItem>> fetchPersonMedia(String personId) async {
|
||||
final response = await _http.get(
|
||||
'/Items',
|
||||
queryParameters: {
|
||||
'userId': connection.userId,
|
||||
'PersonIds': personId,
|
||||
'IncludeItemTypes': 'Movie,Series',
|
||||
'Recursive': 'true',
|
||||
'Fields': _browseFields,
|
||||
'SortBy': 'PremiereDate,ProductionYear,SortName',
|
||||
'SortOrder': 'Descending,Descending,Ascending',
|
||||
'CollapseBoxSetItems': 'false',
|
||||
...jellyfinImageQueryParameters,
|
||||
},
|
||||
);
|
||||
throwIfHttpError(response);
|
||||
return _mapItems(_itemsArray(response.data));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<MediaItem>> fetchRecentlyAdded({int limit = 50}) async {
|
||||
// Matches userLibraryApi.getLatestMedia in the Jellyfin SDK.
|
||||
|
||||
@@ -3209,6 +3209,9 @@ class PlexClient with MediaServerCacheMixin, _PlexLiveTvClientMethods implements
|
||||
return (items: result.items.map((m) => PlexMappers.mediaItem(m)).toList(), totalSize: result.totalSize);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<MediaItem>> fetchPersonMedia(String personId) => fetchAllPersonMediaAsMediaItems(personId);
|
||||
|
||||
/// Plex-specific: full person-media listing across pages.
|
||||
Future<List<MediaItem>> fetchAllPersonMediaAsMediaItems(String personId) async {
|
||||
final raw = await _fetchAllPersonMediaDto(personId);
|
||||
|
||||
Reference in New Issue
Block a user