// Author: fruit.com.cn import 'package:flutter/material.dart'; import '../../core/theme/app_colors.dart'; import '../../core/theme/app_dimens.dart'; import '../../core/widgets/app_press_scale.dart'; import '../../core/widgets/cover_play_count.dart'; import '../../core/widgets/remote_image.dart'; import '../../l10n/app_localizations.dart'; class FollowingHistoryCard extends StatelessWidget { const FollowingHistoryCard({ super.key, required this.dramaId, required this.title, required this.posterUrl, required this.viewCount, required this.subtitle, required this.onTap, required this.onContinue, this.progress, this.progressLabel, this.editing = false, this.onRemove, }); final String dramaId; final String title; final String posterUrl; final int viewCount; final String subtitle; final VoidCallback onTap; final VoidCallback onContinue; final double? progress; final String? progressLabel; final bool editing; final VoidCallback? onRemove; @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; return InkWell( key: Key('following-history-card-$dramaId'), borderRadius: BorderRadius.circular( AppDimens.followingHistoryCoverRadius, ), onTap: onTap, child: AppPressScale( child: SizedBox( height: AppDimens.followingHistoryCoverHeight, child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ _cover(), const SizedBox(width: AppDimens.followingHistoryContentGap), Expanded(child: _details(l10n)), ], ), ), ), ); } Widget _cover() { return SizedBox( key: Key('following-history-cover-$dramaId'), width: AppDimens.followingHistoryCoverWidth, height: AppDimens.followingHistoryCoverHeight, child: Stack( clipBehavior: Clip.hardEdge, children: [ Positioned.fill( child: ClipRRect( borderRadius: BorderRadius.circular( AppDimens.followingHistoryCoverRadius, ), child: RemoteImage( posterUrl, fit: BoxFit.cover, fallbackColor: AppColors.contentSurface, ), ), ), const Positioned( left: 0, right: 0, bottom: 0, child: CoverBottomScrim(), ), Positioned( right: AppDimens.cardPlayCountRight, bottom: AppDimens.cardPlayCountBottom, child: CoverPlayCount( key: Key('following-history-views-$dramaId'), count: viewCount, ), ), ], ), ); } Widget _details(AppLocalizations l10n) { final hasProgress = progress != null; return Stack( children: [ Align( alignment: Alignment.center, child: Padding( padding: const EdgeInsets.only(bottom: 8), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.only(right: editing ? 28 : 0), child: Text( title, maxLines: 2, overflow: TextOverflow.ellipsis, textAlign: TextAlign.left, style: const TextStyle( color: AppColors.textPrimary, fontSize: AppDimens.cardTitleFont, fontWeight: FontWeight.w500, height: AppDimens.cardTitleLineHeight, ), ), ), const SizedBox(height: AppDimens.followingSubtitleGap), Row( children: [ Expanded( child: Text( subtitle, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( color: AppColors.textTertiary, fontSize: AppDimens.followingSubtitleFont, ), ), ), if (!editing && hasProgress) ...[ const SizedBox(width: AppDimens.spaceSm), _continueButton(l10n), ], ], ), if (hasProgress) ...[ const SizedBox(height: AppDimens.followingHistoryProgressGap), ClipRRect( borderRadius: BorderRadius.circular( AppDimens.followingHistoryProgressRadius, ), child: LinearProgressIndicator( key: Key('following-progress-$dramaId'), value: progress!.clamp(0.0, 1.0).toDouble(), minHeight: AppDimens.followingHistoryProgressHeight, backgroundColor: AppColors.inactiveTrack, valueColor: const AlwaysStoppedAnimation( AppColors.brandRed, ), ), ), if (progressLabel != null) ...[ const SizedBox(height: AppDimens.followingHistoryLabelGap), Text( progressLabel!, key: Key('following-history-percent-$dramaId'), maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( color: AppColors.textTertiary, fontSize: AppDimens.followingSubtitleFont, ), ), ], ], ], ), ), ), if (editing) Positioned( top: 0, right: 0, child: GestureDetector( key: Key('following-history-remove-$dramaId'), onTap: onRemove, child: const CircleAvatar( radius: 12, backgroundColor: AppColors.contentChip, child: Icon( Icons.remove_rounded, color: AppColors.textPrimary, size: 17, ), ), ), ), ], ); } Widget _continueButton(AppLocalizations l10n) { return SizedBox( height: AppDimens.followingHistoryActionHeight, child: TextButton( key: Key('following-history-continue-$dramaId'), onPressed: onContinue, style: ButtonStyle( foregroundColor: WidgetStateProperty.resolveWith( (states) => states.contains(WidgetState.pressed) ? AppColors.primary : AppColors.textTabInactive, ), backgroundColor: const WidgetStatePropertyAll(AppColors.transparent), overlayColor: const WidgetStatePropertyAll(AppColors.transparent), padding: const WidgetStatePropertyAll(EdgeInsets.zero), minimumSize: const WidgetStatePropertyAll(Size.zero), tapTargetSize: MaterialTapTargetSize.shrinkWrap, visualDensity: VisualDensity.compact, textStyle: const WidgetStatePropertyAll( TextStyle( fontSize: AppDimens.followingSubtitleFont, fontWeight: FontWeight.w500, ), ), ), child: Text(l10n.continueWatching), ), ); } }