From bc074a9e71d02550c1e87a514ac868f1370e574d Mon Sep 17 00:00:00 2001 From: mattsigal Date: Thu, 11 Jun 2026 08:56:29 -0700 Subject: [PATCH 1/3] feat: pull and apply anime defaults from Seerr if configured - Add seriesType property and mapping to SeerrTvDetails - Implement seriesType check for TV shows to identify anime - Default request dialog options to activeAnimeProfileId and activeAnimeDirectory if isAnime matches and settings exist --- lib/data/services/seerr/seerr_api_models.dart | 2 ++ .../services/seerr/seerr_api_models.g.dart | 2 ++ .../seerr_media_detail_view_model.dart | 6 ++++ .../seerr/seerr_media_detail_screen.dart | 35 +++++++++++++++++-- 4 files changed, 42 insertions(+), 3 deletions(-) diff --git a/lib/data/services/seerr/seerr_api_models.dart b/lib/data/services/seerr/seerr_api_models.dart index 159c4f71..323c4ae9 100644 --- a/lib/data/services/seerr/seerr_api_models.dart +++ b/lib/data/services/seerr/seerr_api_models.dart @@ -380,6 +380,7 @@ class SeerrTvDetails { final SeerrMediaInfo? mediaInfo; final List keywords; final List relatedVideos; + final String? seriesType; const SeerrTvDetails({ required this.id, @@ -404,6 +405,7 @@ class SeerrTvDetails { this.mediaInfo, this.keywords = const [], this.relatedVideos = const [], + this.seriesType, }); String get displayTitle => name ?? title ?? ''; diff --git a/lib/data/services/seerr/seerr_api_models.g.dart b/lib/data/services/seerr/seerr_api_models.g.dart index 798b4573..1cc3afa4 100644 --- a/lib/data/services/seerr/seerr_api_models.g.dart +++ b/lib/data/services/seerr/seerr_api_models.g.dart @@ -356,6 +356,7 @@ SeerrTvDetails _$SeerrTvDetailsFromJson(Map json) => ?.map((e) => SeerrVideo.fromJson(e as Map)) .toList() ?? const [], + seriesType: json['seriesType'] as String?, ); Map _$SeerrTvDetailsToJson(SeerrTvDetails instance) => @@ -382,6 +383,7 @@ Map _$SeerrTvDetailsToJson(SeerrTvDetails instance) => 'mediaInfo': instance.mediaInfo, 'keywords': instance.keywords, 'relatedVideos': instance.relatedVideos, + 'seriesType': instance.seriesType, }; SeerrGenre _$SeerrGenreFromJson(Map json) => SeerrGenre( diff --git a/lib/data/viewmodels/seerr_media_detail_view_model.dart b/lib/data/viewmodels/seerr_media_detail_view_model.dart index 458883e1..3d9fb0ec 100644 --- a/lib/data/viewmodels/seerr_media_detail_view_model.dart +++ b/lib/data/viewmodels/seerr_media_detail_view_model.dart @@ -31,6 +31,12 @@ class SeerrMediaDetailState { bool get isMovie => movie != null; bool get isTv => tv != null; + bool get isAnime { + if (tv != null) { + return tv!.seriesType?.toLowerCase() == 'anime'; + } + return false; + } String get displayTitle { if (movie != null) return movie!.title; diff --git a/lib/ui/screens/seerr/seerr_media_detail_screen.dart b/lib/ui/screens/seerr/seerr_media_detail_screen.dart index 0ac3d298..692c1a68 100644 --- a/lib/ui/screens/seerr/seerr_media_detail_screen.dart +++ b/lib/ui/screens/seerr/seerr_media_detail_screen.dart @@ -1905,8 +1905,24 @@ class _RequestDialogState extends State<_RequestDialog> { final server = _activeServer; if (server == null) return; _selectedServerId ??= server.server.id; - _selectedProfileId ??= server.server.activeProfileId; - final dir = server.server.activeDirectory; + + final isAnime = widget.vm.state.isAnime; + final int? animeProfileId = server.server.activeAnimeProfileId; + final String? animeDir = server.server.activeAnimeDirectory; + + if (isAnime && animeProfileId != null) { + _selectedProfileId ??= animeProfileId; + } else { + _selectedProfileId ??= server.server.activeProfileId; + } + + final String dir; + if (isAnime && animeDir != null && animeDir.isNotEmpty) { + dir = animeDir; + } else { + dir = server.server.activeDirectory; + } + if (_selectedRootFolderId == null && dir.isNotEmpty) { final match = server.rootFolders .where((f) => f.path == dir) @@ -1923,6 +1939,11 @@ class _RequestDialogState extends State<_RequestDialog> { if (_selectedProfileId != null) return _selectedProfileId; final server = _activeServer; if (server == null) return null; + final isAnime = widget.vm.state.isAnime; + final int? animeProfileId = server.server.activeAnimeProfileId; + if (isAnime && animeProfileId != null) { + return animeProfileId; + } return server.server.activeProfileId; } @@ -1937,7 +1958,15 @@ class _RequestDialogState extends State<_RequestDialog> { ?.path; } - final dir = server.server.activeDirectory; + final isAnime = widget.vm.state.isAnime; + final String? animeDir = server.server.activeAnimeDirectory; + final String dir; + if (isAnime && animeDir != null && animeDir.isNotEmpty) { + dir = animeDir; + } else { + dir = server.server.activeDirectory; + } + if (dir.isNotEmpty) { final match = server.rootFolders.where((f) => f.path == dir).firstOrNull; From ac8c44535ba6c301da92a13d3520f482311b8d26 Mon Sep 17 00:00:00 2001 From: Axl <103554043+RadicalMuffinMan@users.noreply.github.com> Date: Thu, 11 Jun 2026 18:44:03 -0400 Subject: [PATCH 2/3] Update lib/data/services/seerr/seerr_api_models.dart --- lib/data/services/seerr/seerr_api_models.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/data/services/seerr/seerr_api_models.dart b/lib/data/services/seerr/seerr_api_models.dart index 323c4ae9..a4f88ee5 100644 --- a/lib/data/services/seerr/seerr_api_models.dart +++ b/lib/data/services/seerr/seerr_api_models.dart @@ -380,7 +380,6 @@ class SeerrTvDetails { final SeerrMediaInfo? mediaInfo; final List keywords; final List relatedVideos; - final String? seriesType; const SeerrTvDetails({ required this.id, From bf5be07d9c3dafd759f65c7baa0a9d97d6716b1d Mon Sep 17 00:00:00 2001 From: mattsigal Date: Thu, 11 Jun 2026 15:49:58 -0700 Subject: [PATCH 3/3] fix: correct seerr model compilation and update anime detection to use keyword id --- lib/data/services/seerr/seerr_api_models.dart | 1 - lib/data/services/seerr/seerr_api_models.g.dart | 2 -- lib/data/viewmodels/seerr_media_detail_view_model.dart | 2 +- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/data/services/seerr/seerr_api_models.dart b/lib/data/services/seerr/seerr_api_models.dart index a4f88ee5..159c4f71 100644 --- a/lib/data/services/seerr/seerr_api_models.dart +++ b/lib/data/services/seerr/seerr_api_models.dart @@ -404,7 +404,6 @@ class SeerrTvDetails { this.mediaInfo, this.keywords = const [], this.relatedVideos = const [], - this.seriesType, }); String get displayTitle => name ?? title ?? ''; diff --git a/lib/data/services/seerr/seerr_api_models.g.dart b/lib/data/services/seerr/seerr_api_models.g.dart index 1cc3afa4..798b4573 100644 --- a/lib/data/services/seerr/seerr_api_models.g.dart +++ b/lib/data/services/seerr/seerr_api_models.g.dart @@ -356,7 +356,6 @@ SeerrTvDetails _$SeerrTvDetailsFromJson(Map json) => ?.map((e) => SeerrVideo.fromJson(e as Map)) .toList() ?? const [], - seriesType: json['seriesType'] as String?, ); Map _$SeerrTvDetailsToJson(SeerrTvDetails instance) => @@ -383,7 +382,6 @@ Map _$SeerrTvDetailsToJson(SeerrTvDetails instance) => 'mediaInfo': instance.mediaInfo, 'keywords': instance.keywords, 'relatedVideos': instance.relatedVideos, - 'seriesType': instance.seriesType, }; SeerrGenre _$SeerrGenreFromJson(Map json) => SeerrGenre( diff --git a/lib/data/viewmodels/seerr_media_detail_view_model.dart b/lib/data/viewmodels/seerr_media_detail_view_model.dart index 3d9fb0ec..996ff58e 100644 --- a/lib/data/viewmodels/seerr_media_detail_view_model.dart +++ b/lib/data/viewmodels/seerr_media_detail_view_model.dart @@ -33,7 +33,7 @@ class SeerrMediaDetailState { bool get isTv => tv != null; bool get isAnime { if (tv != null) { - return tv!.seriesType?.toLowerCase() == 'anime'; + return tv!.keywords.any((keyword) => keyword.id == 210024); } return false; }