From 7a50e0cb0fcbdb2efe91c207dc129161cfa2f0fe Mon Sep 17 00:00:00 2001 From: PartyDonut <42371342+PartyDonut@users.noreply.github.com> Date: Sat, 5 Apr 2025 22:19:24 +0200 Subject: [PATCH] feature: Add guest actors to episode view (#299) Co-authored-by: PartyDonut --- lib/l10n/app_en.arb | 13 ++++++++++++- lib/providers/items/episode_details_provider.dart | 5 +++++ .../details_screens/episode_detail_screen.dart | 14 ++++++++++++++ .../details_screens/season_detail_screen.dart | 10 ++++++++-- .../details_screens/series_detail_screen.dart | 2 +- lib/screens/shared/media/people_row.dart | 11 ++++++++--- lib/util/people_extension.dart | 7 +++++++ 7 files changed, 55 insertions(+), 7 deletions(-) create mode 100644 lib/util/people_extension.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 0069b2d..f32ae7e 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -1184,5 +1184,16 @@ "segmentActionNone": "None", "segmentActionAskToSkip": "Ask to skip", "segmentActionSkip": "Skip", - "loading": "Loading" + "loading": "Loading", + "castAndCrew": "Cast & Crew", + "guestActor": "{count, plural, other{Guest Actors} one{Guest Actor}}", + "@guestActor": { + "description": "Guest actors", + "placeholders": { + "count": { + "type": "int", + "example": "1" + } + } + } } \ No newline at end of file diff --git a/lib/providers/items/episode_details_provider.dart b/lib/providers/items/episode_details_provider.dart index 1f3fef6..dcbcdd3 100644 --- a/lib/providers/items/episode_details_provider.dart +++ b/lib/providers/items/episode_details_provider.dart @@ -4,6 +4,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:fladder/models/item_base_model.dart'; import 'package:fladder/models/items/episode_model.dart'; +import 'package:fladder/models/items/item_shared_models.dart'; import 'package:fladder/models/items/series_model.dart'; import 'package:fladder/providers/api_provider.dart'; import 'package:fladder/providers/service_provider.dart'; @@ -13,21 +14,25 @@ class EpisodeDetailModel { final SeriesModel? series; final List episodes; final EpisodeModel? episode; + final List guestActors; EpisodeDetailModel({ this.series, this.episodes = const [], this.episode, + this.guestActors = const [], }); EpisodeDetailModel copyWith({ SeriesModel? series, List? episodes, EpisodeModel? episode, + List? guestActors, }) { return EpisodeDetailModel( series: series ?? this.series, episodes: episodes ?? this.episodes, episode: episode ?? this.episode, + guestActors: guestActors ?? this.guestActors, ); } } diff --git a/lib/screens/details_screens/episode_detail_screen.dart b/lib/screens/details_screens/episode_detail_screen.dart index 2660510..2b7700a 100644 --- a/lib/screens/details_screens/episode_detail_screen.dart +++ b/lib/screens/details_screens/episode_detail_screen.dart @@ -17,11 +17,13 @@ import 'package:fladder/screens/shared/media/components/media_play_button.dart'; import 'package:fladder/screens/shared/media/episode_posters.dart'; import 'package:fladder/screens/shared/media/expanding_overview.dart'; import 'package:fladder/screens/shared/media/external_urls.dart'; +import 'package:fladder/screens/shared/media/people_row.dart'; import 'package:fladder/util/adaptive_layout.dart'; import 'package:fladder/util/item_base_model/item_base_model_extensions.dart'; import 'package:fladder/util/item_base_model/play_item_helpers.dart'; import 'package:fladder/util/list_padding.dart'; import 'package:fladder/util/localization_helper.dart'; +import 'package:fladder/util/people_extension.dart'; import 'package:fladder/util/router_extension.dart'; import 'package:fladder/util/widget_extensions.dart'; import 'package:fladder/widgets/shared/selectable_icon_button.dart'; @@ -46,6 +48,8 @@ class _ItemDetailScreenState extends ConsumerState { final wrapAlignment = AdaptiveLayout.viewSizeOf(context) != ViewSize.phone ? WrapAlignment.start : WrapAlignment.center; + final actors = details.episode?.overview.people ?? []; + return DetailScaffold( label: widget.item.name, item: details.episode, @@ -155,6 +159,16 @@ class _ItemDetailScreenState extends ConsumerState { ref.read(providerInstance.notifier).fetchDetails(widget.item); }, ), + if (actors.mainCast.isNotEmpty == true) + PeopleRow( + people: actors.mainCast, + contentPadding: padding, + ), + if (actors.guestActors.isNotEmpty == true) + PeopleRow( + people: actors.guestActors, + contentPadding: padding, + ), if (details.episodes.length > 1) EpisodePosters( contentPadding: padding, diff --git a/lib/screens/details_screens/season_detail_screen.dart b/lib/screens/details_screens/season_detail_screen.dart index 2a08dc4..d96a465 100644 --- a/lib/screens/details_screens/season_detail_screen.dart +++ b/lib/screens/details_screens/season_detail_screen.dart @@ -17,6 +17,7 @@ import 'package:fladder/screens/shared/media/person_list_.dart'; import 'package:fladder/util/item_base_model/item_base_model_extensions.dart'; import 'package:fladder/util/list_padding.dart'; import 'package:fladder/util/localization_helper.dart'; +import 'package:fladder/util/people_extension.dart'; import 'package:fladder/util/string_extensions.dart'; import 'package:fladder/util/theme_extensions.dart'; import 'package:fladder/util/widget_extensions.dart'; @@ -154,9 +155,14 @@ class _SeasonDetailScreenState extends ConsumerState { episodes: details.episodes, padding: padding, ), - if (details.overview.people.isNotEmpty) + if (details.overview.people.mainCast.isNotEmpty) PeopleRow( - people: details.overview.people, + people: details.overview.people.mainCast, + contentPadding: padding, + ), + if (details.overview.people.guestActors.isNotEmpty) + PeopleRow( + people: details.overview.people.guestActors, contentPadding: padding, ), if (details.overview.externalUrls?.isNotEmpty == true) diff --git a/lib/screens/details_screens/series_detail_screen.dart b/lib/screens/details_screens/series_detail_screen.dart index 7bd66bd..c347b71 100644 --- a/lib/screens/details_screens/series_detail_screen.dart +++ b/lib/screens/details_screens/series_detail_screen.dart @@ -1,4 +1,3 @@ -import 'package:fladder/models/settings/home_settings_model.dart'; import 'package:flutter/material.dart'; import 'package:auto_route/auto_route.dart'; @@ -7,6 +6,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:fladder/models/item_base_model.dart'; import 'package:fladder/models/items/series_model.dart'; +import 'package:fladder/models/settings/home_settings_model.dart'; import 'package:fladder/providers/items/series_details_provider.dart'; import 'package:fladder/providers/user_provider.dart'; import 'package:fladder/screens/details_screens/components/overview_header.dart'; diff --git a/lib/screens/shared/media/people_row.dart b/lib/screens/shared/media/people_row.dart index 60870d7..f7b89d0 100644 --- a/lib/screens/shared/media/people_row.dart +++ b/lib/screens/shared/media/people_row.dart @@ -1,4 +1,9 @@ +import 'package:flutter/material.dart'; + import 'package:animations/animations.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import 'package:fladder/jellyfin/jellyfin_open_api.enums.swagger.dart'; import 'package:fladder/models/items/item_shared_models.dart'; import 'package:fladder/screens/details_screens/person_detail_screen.dart'; import 'package:fladder/screens/shared/flat_button.dart'; @@ -8,8 +13,6 @@ import 'package:fladder/util/localization_helper.dart'; import 'package:fladder/util/string_extensions.dart'; import 'package:fladder/widgets/shared/clickable_text.dart'; import 'package:fladder/widgets/shared/horizontal_list.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; class PeopleRow extends ConsumerWidget { final List people; @@ -36,7 +39,9 @@ class PeopleRow extends ConsumerWidget { } return HorizontalList( - label: context.localized.actor(people.length), + label: people.any((e) => e.type != PersonKind.gueststar) + ? context.localized.castAndCrew + : context.localized.guestActor(people.length), height: AdaptiveLayout.poster(context).size * 0.9, contentPadding: contentPadding, items: people, diff --git a/lib/util/people_extension.dart b/lib/util/people_extension.dart new file mode 100644 index 0000000..f02f57a --- /dev/null +++ b/lib/util/people_extension.dart @@ -0,0 +1,7 @@ +import 'package:fladder/jellyfin/jellyfin_open_api.enums.swagger.dart'; +import 'package:fladder/models/items/item_shared_models.dart'; + +extension PeopleExtension on List { + List get guestActors => where((person) => person.type == PersonKind.gueststar).toList(); + List get mainCast => where((person) => person.type != PersonKind.gueststar).toList(); +}