Initial commit
This commit is contained in:
@@ -0,0 +1,204 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../../core/contracts/library.dart';
|
||||
import '../../providers/di_providers.dart';
|
||||
import 'android/android_media_info_section.dart';
|
||||
import 'widgets/additional_parts_section.dart';
|
||||
import 'widgets/emby_cast_section.dart';
|
||||
import 'widgets/episode_list_section.dart';
|
||||
import 'widgets/similar_section.dart';
|
||||
import 'widgets/special_features_section.dart';
|
||||
import 'emby_detail_helpers.dart';
|
||||
import 'model/detail_section_model.dart';
|
||||
import 'model/episode_auto_select_args.dart';
|
||||
import 'widgets/source_selection_section.dart';
|
||||
|
||||
List<DetailSection> buildEmbyDetailSections({
|
||||
required WidgetRef ref,
|
||||
required EmbyRawItem baseItem,
|
||||
required EmbyRawItem displayItem,
|
||||
required String? seriesId,
|
||||
required String similarItemId,
|
||||
required TmdbMediaRef? tmdbMediaRef,
|
||||
required String? detailServerId,
|
||||
required String? initialSeasonId,
|
||||
required EmbyRawItem? tmdbSeriesItem,
|
||||
required List<EmbyRawMediaSource> sortedSources,
|
||||
required int selectedSourceIdx,
|
||||
required CrossServerSourceCard? selectedCrossServerCard,
|
||||
required String? currentServerName,
|
||||
required ValueChanged<EmbyRawItem> onEpisodeTap,
|
||||
required ValueChanged<int> onSelectSourceIndex,
|
||||
required ValueChanged<CrossServerSourceCard> onSelectCrossServerSource,
|
||||
EmbyRawMediaSource? activeSource,
|
||||
List<String> studioNames = const [],
|
||||
List<String> directors = const [],
|
||||
|
||||
|
||||
Widget? sectionLeading,
|
||||
}) {
|
||||
return <DetailSection>[
|
||||
if (seriesId != null)
|
||||
DetailSection(
|
||||
id: 'emby_episodes',
|
||||
child: _buildEpisodesSection(
|
||||
ref: ref,
|
||||
baseItem: baseItem,
|
||||
displayItem: displayItem,
|
||||
seriesId: seriesId,
|
||||
tmdbMediaRef: tmdbMediaRef,
|
||||
detailServerId: detailServerId,
|
||||
initialSeasonId: initialSeasonId,
|
||||
tmdbSeriesItem: tmdbSeriesItem,
|
||||
onEpisodeTap: onEpisodeTap,
|
||||
leading: sectionLeading,
|
||||
),
|
||||
),
|
||||
if (displayItem.Type == 'Movie' || displayItem.Type == 'Episode')
|
||||
DetailSection(
|
||||
id: 'emby_source',
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 24),
|
||||
child: _buildSourceSection(
|
||||
baseItem: baseItem,
|
||||
displayItem: displayItem,
|
||||
tmdbSeriesItem: tmdbSeriesItem,
|
||||
sortedSources: sortedSources,
|
||||
selectedSourceIdx: selectedSourceIdx,
|
||||
selectedCrossServerCard: selectedCrossServerCard,
|
||||
currentServerName: currentServerName,
|
||||
onSelectSourceIndex: onSelectSourceIndex,
|
||||
onSelectCrossServerSource: onSelectCrossServerSource,
|
||||
leading: sectionLeading,
|
||||
),
|
||||
),
|
||||
),
|
||||
DetailSection(
|
||||
id: 'emby_cast',
|
||||
child: EmbyCastSection(
|
||||
item: baseItem,
|
||||
embedded: true,
|
||||
leading: sectionLeading,
|
||||
),
|
||||
),
|
||||
DetailSection(
|
||||
id: 'emby_media_detail',
|
||||
child: AndroidMediaInfoSection(
|
||||
source: activeSource,
|
||||
studioNames: studioNames,
|
||||
directors: directors,
|
||||
leading: sectionLeading,
|
||||
),
|
||||
),
|
||||
if (baseItem.Type != 'Series')
|
||||
DetailSection(
|
||||
id: 'emby_additional_parts',
|
||||
child: AdditionalPartsSection(
|
||||
itemId: displayItem.Id,
|
||||
embedded: true,
|
||||
leading: sectionLeading,
|
||||
),
|
||||
),
|
||||
if (baseItem.Type != 'Series')
|
||||
DetailSection(
|
||||
id: 'emby_special_features',
|
||||
child: SpecialFeaturesSection(
|
||||
itemId: displayItem.Id,
|
||||
embedded: true,
|
||||
leading: sectionLeading,
|
||||
),
|
||||
),
|
||||
DetailSection(
|
||||
id: 'emby_similar',
|
||||
child: SimilarSection(
|
||||
itemId: similarItemId,
|
||||
embedded: true,
|
||||
leading: sectionLeading,
|
||||
),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
Widget _buildEpisodesSection({
|
||||
required WidgetRef ref,
|
||||
required EmbyRawItem baseItem,
|
||||
required EmbyRawItem displayItem,
|
||||
required String seriesId,
|
||||
required TmdbMediaRef? tmdbMediaRef,
|
||||
required String? detailServerId,
|
||||
required String? initialSeasonId,
|
||||
required EmbyRawItem? tmdbSeriesItem,
|
||||
required ValueChanged<EmbyRawItem> onEpisodeTap,
|
||||
Widget? leading,
|
||||
}) {
|
||||
final showItem = baseItem.Type == 'Series' ? baseItem : tmdbSeriesItem;
|
||||
final resumeAsync = baseItem.Type == 'Series' && detailServerId != null
|
||||
? ref.watch(
|
||||
seriesResumeTargetProvider((
|
||||
serverId: detailServerId,
|
||||
seriesId: seriesId,
|
||||
)),
|
||||
)
|
||||
: null;
|
||||
final autoSelect = EpisodeAutoSelectArgs.fromResume(resumeAsync);
|
||||
return EpisodeListSection(
|
||||
seriesId: seriesId,
|
||||
tmdbSeriesId: tmdbMediaRef != null && tmdbMediaRef.mediaType == 'tv'
|
||||
? tmdbMediaRef.id
|
||||
: null,
|
||||
currentEpisodeId: displayItem.Type == 'Episode' ? displayItem.Id : null,
|
||||
currentEpisodeSeasonId: displayItem.Type == 'Episode'
|
||||
? displayItem.SeasonId
|
||||
: null,
|
||||
currentEpisodeSeasonNumber: displayItem.Type == 'Episode'
|
||||
? (displayItem.extra['ParentIndexNumber'] as num?)?.toInt()
|
||||
: null,
|
||||
currentEpisodeIndexNumber: displayItem.Type == 'Episode'
|
||||
? displayItem.IndexNumber
|
||||
: null,
|
||||
initialSeasonId: initialSeasonId,
|
||||
autoSelectFirstEpisode: autoSelect.autoSelectFirstEpisode,
|
||||
autoSelectEpisodeId: autoSelect.autoSelectEpisodeId,
|
||||
autoSelectSeasonId: autoSelect.autoSelectSeasonId,
|
||||
onEpisodeTap: onEpisodeTap,
|
||||
embedded: true,
|
||||
showProviderIds: showItem != null
|
||||
? lowercaseProviderIds(providerIdsOfItem(showItem))
|
||||
: null,
|
||||
showTitle: showItem?.Name,
|
||||
showYear: showItem?.ProductionYear,
|
||||
leading: leading,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSourceSection({
|
||||
required EmbyRawItem baseItem,
|
||||
required EmbyRawItem displayItem,
|
||||
required EmbyRawItem? tmdbSeriesItem,
|
||||
required List<EmbyRawMediaSource> sortedSources,
|
||||
required int selectedSourceIdx,
|
||||
required CrossServerSourceCard? selectedCrossServerCard,
|
||||
required String? currentServerName,
|
||||
required ValueChanged<int> onSelectSourceIndex,
|
||||
required ValueChanged<CrossServerSourceCard> onSelectCrossServerSource,
|
||||
Widget? leading,
|
||||
}) {
|
||||
final seriesItemForReq = baseItem.Type == 'Series'
|
||||
? baseItem
|
||||
: tmdbSeriesItem;
|
||||
final req = buildCrossServerReqForDetail(displayItem, seriesItemForReq);
|
||||
return SourceSelectionSection(
|
||||
req: req,
|
||||
localSources: sortedSources,
|
||||
selectedSourceIdx: selectedSourceIdx,
|
||||
selectedCrossServerCard: selectedCrossServerCard,
|
||||
currentServerName: currentServerName,
|
||||
localMediaInfoItem: displayItem,
|
||||
showLoadingWhenEmpty: true,
|
||||
loadingText: '正在查找可用版本…',
|
||||
onLocalSourceTap: (src, index) => onSelectSourceIndex(index),
|
||||
onCrossServerSourceTap: onSelectCrossServerSource,
|
||||
leading: leading,
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user