Initial commit

This commit is contained in:
admin1
2026-07-14 11:11:36 +08:00
commit 656499cf94
604 changed files with 119518 additions and 0 deletions
@@ -0,0 +1,105 @@
import 'package:flutter/widgets.dart';
import '../../../core/contracts/tmdb.dart';
import '../../../shared/mappers/tmdb_image_selector.dart';
import '../../../shared/mappers/tmdb_image_url.dart';
import '../../../shared/utils/format_utils.dart';
import '../utils/detail_helpers.dart';
import '../model/detail_hero_model.dart';
import '../model/detail_image_model.dart';
import '../model/detail_section_model.dart';
import '../model/detail_view_state.dart';
import '../widgets/tmdb_cast_section.dart';
import '../widgets/tmdb_recommendation_section.dart';
DetailViewState buildTmdbDetailViewState({
required String mediaType,
required TmdbEnrichedDetail? enriched,
required TmdbRecommendation? seed,
required String imageBaseUrl,
required String language,
required Widget? heroActions,
required List<DetailSection> hitStateSections,
required bool showSpinner,
}) {
final detail = enriched?.detail;
final title = (detail?.title.isNotEmpty ?? false)
? detail!.title
: (seed?.title ?? '');
final posterPath = detail?.posterPath ?? seed?.posterPath;
final backdropPath = detail?.backdropPath ?? seed?.backdropPath;
final voteAverage = detail?.voteAverage ?? seed?.voteAverage;
final overview = (detail?.overview?.trim().isNotEmpty ?? false)
? detail!.overview!.trim()
: (seed?.overview?.trim() ?? '');
final tagline = detail?.tagline?.trim();
final metaParts = <String>[];
final year = yearOf(detail?.releaseDate);
if (year != null) metaParts.add(year);
final runtime = formatRuntimeMinutes(detail?.runtime);
if (runtime != null) metaParts.add(runtime);
final genreNames = [
for (final g in detail?.genres ?? const <TmdbGenre>[])
if (g.name.isNotEmpty) g.name,
];
final cast = enriched?.credits?.cast ?? const <TmdbCastMember>[];
final recommendations =
enriched?.recommendations?.results ?? const <TmdbRecommendation>[];
final posterUrl = TmdbImageUrl.poster(imageBaseUrl, posterPath);
final backdropUrl = TmdbImageUrl.backdrop(imageBaseUrl, backdropPath);
final logoUrl = TmdbImageSelector.logoUrl(
enriched?.images,
imageBaseUrl,
language: language,
);
final fallbackUrls = TmdbImageSelector.buildFallbackUrls(
primaryUrl: backdropUrl,
candidates: [posterUrl],
);
final sections = <DetailSection>[
...hitStateSections,
if (cast.isNotEmpty)
DetailSection(
id: 'tmdb_cast',
child: TmdbCastSection(cast: cast, imageBaseUrl: imageBaseUrl),
),
if (recommendations.isNotEmpty)
DetailSection(
id: 'tmdb_recommendations',
child: TmdbRecommendationSection(
items: recommendations,
imageBaseUrl: imageBaseUrl,
fallbackMediaType: mediaType,
),
),
];
return DetailViewState(
image: DetailImageModel(
backdropUrl: backdropUrl,
fallbackUrls: fallbackUrls,
),
navTitle: title,
hero: DetailHeroModel(
title: title,
logoUrl: logoUrl,
posterUrl: posterUrl,
imageHeaders: null,
rating: voteAverage,
metaParts: metaParts,
genres: genreNames,
tagline: tagline,
overview: overview,
actions: heroActions,
),
sections: sections,
showLoadingBelowHero: showSpinner,
);
}