import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../providers/di_providers.dart'; import '../../../shared/utils/media_nav.dart'; import '../../../shared/widgets/card_progress_bar.dart'; import '../../../shared/widgets/hover_scrollable_row.dart'; import '../../../shared/widgets/media_row_metrics.dart'; import '../../../shared/widgets/media_poster_card.dart'; import '../../../shared/widgets/section_header.dart'; import '../../../shared/widgets/smart_image.dart'; import '../../../shared/widgets/skeleton_media_row.dart'; import '../trakt_continue_watching_item.dart'; class TraktContinueWatchingRow extends ConsumerWidget { const TraktContinueWatchingRow({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final asyncItems = ref.watch(traktContinueWatchingProvider); final compact = MediaRowMetrics.isCompact(context); final rowHeight = MediaRowMetrics.rowHeight( MediaCardVariant.landscape, compact: compact, ); final cardWidth = MediaRowMetrics.cardWidth( MediaCardVariant.landscape, compact: compact, ); return asyncItems.when( loading: () => const SkeletonMediaRow( title: '继续观看', cardVariant: MediaCardVariant.landscape, titleColor: Colors.white, ), error: (_, _) => const SizedBox.shrink(), data: (items) { if (items.isEmpty) return const SizedBox.shrink(); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Padding( padding: EdgeInsets.fromLTRB(24, 16, 24, 4), child: SectionHeader(label: '继续观看', labelColor: Colors.white), ), SizedBox( height: rowHeight, child: HoverScrollableRow( builder: (_, controller) => ListView.separated( controller: controller, scrollDirection: Axis.horizontal, padding: const EdgeInsets.symmetric(horizontal: 24), itemCount: items.length, separatorBuilder: (_, _) => const SizedBox(width: 14), itemBuilder: (_, i) { final item = items[i]; return _TraktContinueCard( key: ValueKey('${item.mediaType}:${item.tmdbId}'), item: item, width: cardWidth, onTap: () => goTmdbDetail( context, tmdbId: item.tmdbId, mediaType: item.mediaType, ), ); }, ), ), ), ], ); }, ); } } class _TraktContinueCard extends StatelessWidget { final TraktContinueWatchingItem item; final double width; final VoidCallback onTap; const _TraktContinueCard({ super.key, required this.item, required this.width, required this.onTap, }); @override Widget build(BuildContext context) { final theme = Theme.of(context); return SizedBox( width: width, child: GestureDetector( onTap: onTap, behavior: HitTestBehavior.opaque, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Flexible( child: Stack( children: [ SmartImage( url: item.backdropUrl, aspectRatio: 16 / 9, borderRadius: 8, fallbackIcon: Icons.movie_outlined, ), if (item.progress > 0) CardProgressBar(progress: item.progress), ], ), ), const SizedBox(height: 10), Text( item.title, maxLines: 1, overflow: TextOverflow.ellipsis, style: theme.textTheme.bodyMedium?.copyWith( color: Colors.white, fontWeight: FontWeight.w500, ), ), if (item.subtitle != null) Text( item.subtitle!, maxLines: 1, overflow: TextOverflow.ellipsis, style: theme.textTheme.bodySmall?.copyWith( color: Colors.white.withValues(alpha: 0.6), ), ), ], ), ), ); } }