// Author: fruit.com.cn import 'package:flutter/material.dart'; import '../../../core/theme/app_colors.dart'; import '../../../core/theme/app_dimens.dart'; import '../../../l10n/app_localizations.dart'; import '../mine_types.dart'; const double _vipRadius = 14; /// 「我的」页金色 VIP 卡:品牌行 + 立即开通 + 2×2 权益宫格。 class MineVipBanner extends StatelessWidget { const MineVipBanner({super.key, required this.onOpen}); final VoidCallback onOpen; @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; return Container( key: const Key('mine-vip'), decoration: BoxDecoration( gradient: const LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [AppColors.vipCardStart, AppColors.vipCardEnd], ), borderRadius: BorderRadius.circular(_vipRadius), ), child: Material( color: AppColors.transparent, borderRadius: BorderRadius.circular(_vipRadius), clipBehavior: Clip.antiAlias, child: InkWell( onTap: onOpen, child: Padding( padding: const EdgeInsets.fromLTRB( AppDimens.cardPadding, AppDimens.spaceSm + 2, AppDimens.cardPadding, AppDimens.spaceSm + 2, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ const Icon( Icons.diamond_outlined, color: AppColors.onGold, size: 24, ), const SizedBox(width: AppDimens.spaceSm), Expanded( child: Text( l10n.vipBrandName, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( color: AppColors.onGold, fontSize: 18, fontWeight: FontWeight.w400, ), ), ), const SizedBox(width: AppDimens.spaceSm), _openButton(l10n), ], ), Transform.translate( offset: const Offset(0, -7), child: Text( l10n.mineVipSubtitle, maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle( color: AppColors.onGold.withValues(alpha: 0.7), fontSize: AppDimens.caption, ), ), ), const SizedBox(height: AppDimens.mineVipBenefitRowGap), Container( height: 1, color: AppColors.onGold.withValues(alpha: 0.15), ), const SizedBox(height: AppDimens.mineVipBenefitRowGap), Table( defaultColumnWidth: const FlexColumnWidth(), children: [ TableRow( children: [ _benefit( key: const Key('mine-vip-benefit-0'), icon: Icons.play_circle_outline_rounded, label: l10n.vipBenefitFree, ), _benefit( key: const Key('mine-vip-benefit-1'), icon: Icons.ads_click_rounded, label: l10n.vipBenefitNoAds, ), ], ), TableRow( children: [ _benefit( key: const Key('mine-vip-benefit-2'), icon: Icons.hd_outlined, label: l10n.vipBenefitHd, ), _benefit( key: const Key('mine-vip-benefit-3'), icon: Icons.download_for_offline_outlined, label: l10n.vipBenefitFastCache, ), ], ), ], ), ], ), ), ), ), ); } Widget _openButton(AppLocalizations l10n) { return TextButton( key: const Key('mine-vip-open'), onPressed: onOpen, style: TextButton.styleFrom( minimumSize: const Size(0, AppDimens.mineVipButtonHeight), padding: const EdgeInsets.symmetric(horizontal: AppDimens.spaceMd), backgroundColor: AppColors.onGold, foregroundColor: AppColors.vipGoldStart, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular( AppDimens.mineVipButtonHeight / 2, ), ), textStyle: const TextStyle( fontSize: AppDimens.body, fontWeight: FontWeight.w400, ), ), child: Text(l10n.vipOpenNow), ); } Widget _benefit({required Key key, required IconData icon, required String label}) { return Padding( key: key, padding: const EdgeInsets.symmetric(vertical: AppDimens.mineVipBenefitRowGap), child: Row( children: [ Container( width: AppDimens.mineVipBenefitBox, height: AppDimens.mineVipBenefitBox, decoration: BoxDecoration( border: Border.all( color: AppColors.onGold.withValues(alpha: 0.6), width: 1.2, ), borderRadius: BorderRadius.circular( AppDimens.mineVipBenefitBoxRadius, ), ), child: Icon( icon, color: AppColors.onGold, size: AppDimens.mineVipBenefitGlyph, ), ), const SizedBox(width: AppDimens.spaceSm), Expanded( child: Text( label, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( color: AppColors.onGold, fontSize: AppDimens.mineVipBenefitFont, ), ), ), ], ), ); } } /// 快捷图标行:钱包 / 我的收藏 / 离线缓存 / 播放历史(设计稿的「奖励」暂不做)。 class MineQuickActions extends StatelessWidget { const MineQuickActions({ super.key, required this.onWallet, required this.onFavorites, required this.onDownloads, required this.onHistory, }); final VoidCallback onWallet; final VoidCallback onFavorites; final VoidCallback onDownloads; final VoidCallback onHistory; @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; return Row( children: [ _action( key: const Key('mine-wallet'), icon: Icons.wallet_outlined, label: l10n.wallet, onTap: onWallet, ), _action( key: const Key('mine-favorites'), icon: Icons.star_border_rounded, label: l10n.myFavorites, onTap: onFavorites, ), _action( key: const Key('mine-downloads'), icon: Icons.download_outlined, label: l10n.offlineDownloads, onTap: onDownloads, ), _action( key: const Key('mine-history'), icon: Icons.history_rounded, label: l10n.watchHistory, onTap: onHistory, ), ], ); } Widget _action({ required Key key, required IconData icon, required String label, required VoidCallback onTap, }) { return Expanded( child: InkWell( key: key, onTap: onTap, borderRadius: BorderRadius.circular(10), child: Padding( padding: const EdgeInsets.symmetric(vertical: AppDimens.spaceSm), child: Column( mainAxisSize: MainAxisSize.min, children: [ Icon(icon, color: AppColors.textPrimary, size: AppDimens.mineQuickActionIcon), const SizedBox(height: AppDimens.mineQuickActionGap), Text( label, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( color: AppColors.textPrimary, fontSize: AppDimens.mineQuickActionLabelFont, ), ), ], ), ), ), ); } } /// 「更多服务」列表行:白图标 + 标题 + 可选值 + chevron,行间细分隔线。 class MineServiceList extends StatelessWidget { const MineServiceList({ super.key, required this.onOpen, required this.onLanguage, required this.languageName, }); final ValueChanged onOpen; final VoidCallback onLanguage; final String languageName; @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; final rows = [ _row( key: const Key('mine-help'), icon: Icons.headset_outlined, label: l10n.contactSupport, onTap: () => onOpen(MineDestination.help), ), _divider(), _row( key: const Key('mine-language'), icon: Icons.language_rounded, label: l10n.language, value: languageName, onTap: onLanguage, ), _divider(), _row( key: const Key('mine-settings'), icon: Icons.settings_outlined, label: l10n.settings, onTap: () => onOpen(MineDestination.settings), ), _divider(), _row( key: const Key('mine-notices'), icon: Icons.notifications_none_rounded, label: l10n.notices, onTap: () => onOpen(MineDestination.notices), ), ]; return Column(key: const Key('mine-menu'), children: rows); } Widget _divider() => const Divider( height: AppDimens.mineGridDividerWidth, thickness: AppDimens.mineGridDividerWidth, color: AppColors.contentBorder, ); Widget _row({ required Key key, required IconData icon, required String label, String? value, required VoidCallback onTap, }) { return SizedBox( height: AppDimens.mineServiceRowHeight, child: InkWell( key: key, onTap: onTap, child: Row( children: [ Icon(icon, color: AppColors.textPrimary, size: AppDimens.mineServiceIcon), const SizedBox(width: AppDimens.spaceMd), Expanded( child: Text( label, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( color: AppColors.textPrimary, fontSize: AppDimens.mineServiceTitleFont, ), ), ), if (value != null && value.isNotEmpty) ...[ const SizedBox(width: AppDimens.spaceSm), Text( value, style: const TextStyle( color: AppColors.textTertiary, fontSize: AppDimens.mineServiceValueFont, ), ), ], const SizedBox(width: AppDimens.spaceXs), const Icon( Icons.chevron_right_rounded, color: AppColors.textSecondary, size: 22, ), ], ), ), ); } }