// 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 = 12; const double _vipBadgeSize = 36; const double _vipButtonHeight = 34; /// 金色会员横幅。 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( colors: [AppColors.vipGoldStart, AppColors.vipGoldEnd], ), 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.symmetric( horizontal: AppDimens.cardPadding, vertical: AppDimens.spaceMd, ), child: Row( children: [ Container( width: _vipBadgeSize, height: _vipBadgeSize, decoration: const BoxDecoration( color: AppColors.vipBadgeSurface, shape: BoxShape.circle, ), child: const Icon( Icons.workspace_premium_rounded, color: AppColors.onGold, size: 22, ), ), const SizedBox(width: AppDimens.spaceMd), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( l10n.vipBrandName, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( color: AppColors.onGold, fontSize: AppDimens.sectionTitle, fontWeight: FontWeight.w700, ), ), const SizedBox(height: 2), Text( l10n.mineVipSubtitle, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( color: AppColors.onGold, fontSize: AppDimens.caption, ), ), ], ), ), const SizedBox(width: AppDimens.spaceSm), TextButton( key: const Key('mine-vip-open'), onPressed: onOpen, style: TextButton.styleFrom( minimumSize: const Size(0, _vipButtonHeight), padding: const EdgeInsets.symmetric( horizontal: AppDimens.spaceMd, ), backgroundColor: AppColors.onGold, foregroundColor: AppColors.textPrimary, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(_vipButtonHeight), ), ), child: Text(l10n.joinVip), ), ], ), ), ), ), ); } } /// 「我的」页 4 列功能入口。 class MineMenuList extends StatelessWidget { const MineMenuList({ super.key, required this.onOpen, required this.onLanguage, }); final ValueChanged onOpen; final VoidCallback onLanguage; @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; return Container( key: const Key('mine-menu'), decoration: BoxDecoration( color: AppColors.mineGridSurface, borderRadius: BorderRadius.circular(AppDimens.mineGridRadius), ), child: Material( color: AppColors.transparent, borderRadius: BorderRadius.circular(AppDimens.mineGridRadius), clipBehavior: Clip.antiAlias, child: Table( key: const Key('mine-menu-grid'), defaultColumnWidth: const FlexColumnWidth(), defaultVerticalAlignment: TableCellVerticalAlignment.middle, border: const TableBorder( horizontalInside: BorderSide( color: AppColors.mineGridDivider, width: AppDimens.mineGridDividerWidth, ), verticalInside: BorderSide( color: AppColors.mineGridDivider, width: AppDimens.mineGridDividerWidth, ), ), children: [ TableRow( children: [ _cell( index: 0, actionKey: const Key('mine-wallet'), icon: Icons.account_balance_wallet_outlined, iconColor: AppColors.mineIconWallet, label: l10n.wallet, onTap: () => onOpen(MineDestination.wallet), ), _cell( index: 1, actionKey: const Key('mine-downloads'), icon: Icons.download_outlined, iconColor: AppColors.mineIconDownloads, label: l10n.offlineDownloads, onTap: () => onOpen(MineDestination.downloads), ), _cell( index: 2, actionKey: const Key('mine-history'), icon: Icons.history_rounded, iconColor: AppColors.mineIconHistory, label: l10n.watchHistory, onTap: () => onOpen(MineDestination.history), ), _cell( index: 3, actionKey: const Key('mine-watch-preferences'), icon: Icons.tune_rounded, iconColor: AppColors.mineIconPreferences, label: l10n.watchPreferences, onTap: () => onOpen(MineDestination.preferences), ), ], ), TableRow( children: [ _cell( index: 4, actionKey: const Key('mine-help'), icon: Icons.support_agent_rounded, iconColor: AppColors.mineIconSupport, label: l10n.contactSupport, onTap: () => onOpen(MineDestination.help), ), _cell( index: 5, actionKey: const Key('mine-language'), icon: Icons.language_rounded, iconColor: AppColors.mineIconLanguage, label: l10n.language, onTap: onLanguage, ), _cell( index: 6, actionKey: const Key('mine-settings'), icon: Icons.settings_outlined, iconColor: AppColors.mineIconSettings, label: l10n.settings, onTap: () => onOpen(MineDestination.settings), ), _cell(index: 7), ], ), ], ), ), ); } Widget _cell({ required int index, Key? actionKey, IconData? icon, Color? iconColor, String? label, VoidCallback? onTap, }) { return SizedBox( key: Key('mine-menu-cell-$index'), height: AppDimens.mineGridCellHeight, child: actionKey == null ? const SizedBox.shrink() : InkWell( key: actionKey, onTap: onTap, child: Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( width: AppDimens.mineGridIconSurface, height: AppDimens.mineGridIconSurface, decoration: const BoxDecoration( color: AppColors.mineGridIconSurface, shape: BoxShape.circle, ), child: DecoratedBox( decoration: BoxDecoration( color: iconColor?.withValues(alpha: 0.08), shape: BoxShape.circle, ), child: Icon( icon, color: iconColor, size: AppDimens.mineGridIcon, ), ), ), const SizedBox(height: AppDimens.spaceXs + 2), Padding( padding: const EdgeInsets.symmetric(horizontal: 4), child: Text( label ?? '', maxLines: 1, overflow: TextOverflow.ellipsis, textAlign: TextAlign.center, style: const TextStyle( color: AppColors.mineGridLabel, fontSize: AppDimens.mineGridLabel, fontWeight: FontWeight.w500, height: 1.2, ), ), ), ], ), ), ), ); } }