// Author: fruit.com.cn import 'package:flutter/material.dart'; import '../../../core/theme/app_colors.dart'; import '../../../core/theme/app_dimens.dart'; import '../../../core/theme/app_theme.dart'; import '../../../l10n/app_localizations.dart'; import '../mine_types.dart'; /// 我的页三宫格快捷入口。 class MineShortcutGrid extends StatelessWidget { const MineShortcutGrid({super.key, required this.onOpen}); final ValueChanged onOpen; @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; return Row( children: [ Expanded( child: _ShortcutTile( key: const Key('mine-watchlist'), icon: Icons.bookmark_rounded, label: l10n.watchlist, onTap: () => onOpen(MineDestination.watchlist), ), ), const SizedBox(width: 10), Expanded( child: _ShortcutTile( key: const Key('mine-history'), icon: Icons.history_rounded, label: l10n.watchHistory, onTap: () => onOpen(MineDestination.history), ), ), const SizedBox(width: 10), Expanded( child: _ShortcutTile( key: const Key('mine-downloads'), icon: Icons.download_rounded, label: l10n.downloads, onTap: () => onOpen(MineDestination.downloads), ), ), ], ); } } class _ShortcutTile extends StatelessWidget { const _ShortcutTile({ super.key, required this.icon, required this.label, required this.onTap, }); final IconData icon; final String label; final VoidCallback onTap; @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( color: AppColors.card, borderRadius: BorderRadius.circular(AppDimens.cardRadius), boxShadow: const [AppTheme.cardShadow], ), child: Material( color: Colors.transparent, borderRadius: BorderRadius.circular(AppDimens.cardRadius), clipBehavior: Clip.antiAlias, child: InkWell( onTap: onTap, child: SizedBox( height: 88, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(icon, color: AppColors.blue, size: 24), const SizedBox(height: AppDimens.spaceSm), Text( label, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( color: AppColors.onSurface, fontSize: AppDimens.caption, fontWeight: FontWeight.w600, ), ), ], ), ), ), ), ); } } /// 金币余额卡。 class MineWalletCard extends StatelessWidget { const MineWalletCard({ super.key, required this.balance, required this.onOpen, required this.onRecharge, }); final String balance; final VoidCallback onOpen; final VoidCallback onRecharge; @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; return Container( key: const Key('mine-wallet'), padding: const EdgeInsets.all(AppDimens.cardPadding), decoration: BoxDecoration( gradient: const LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [AppColors.goldCard, AppColors.card], ), borderRadius: BorderRadius.circular(AppDimens.cardRadius), boxShadow: const [AppTheme.cardShadow], ), child: Row( children: [ const Icon( Icons.monetization_on_rounded, color: AppColors.gold, size: 30, ), const SizedBox(width: AppDimens.spaceMd), Expanded( child: InkWell( onTap: onOpen, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( l10n.coinBalance, style: const TextStyle( color: AppColors.muted, fontSize: AppDimens.caption, ), ), const SizedBox(height: 3), Text( balance, style: const TextStyle( color: AppColors.onSurface, fontSize: AppDimens.pageTitle, fontWeight: FontWeight.w800, ), ), ], ), ), ), TextButton( key: const Key('mine-wallet-recharge'), onPressed: onRecharge, style: TextButton.styleFrom( backgroundColor: AppColors.blue, foregroundColor: AppColors.onPrimary, minimumSize: const Size(64, AppDimens.buttonCompact), shape: const StadiumBorder(), ), child: Text(l10n.topUpWallet), ), ], ), ); } } /// 会员权益卡。 class MineVipCard extends StatelessWidget { const MineVipCard({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( color: AppColors.card, borderRadius: BorderRadius.circular(AppDimens.cardRadius), boxShadow: const [AppTheme.cardShadow], ), child: Material( color: Colors.transparent, borderRadius: BorderRadius.circular(AppDimens.cardRadius), clipBehavior: Clip.antiAlias, child: InkWell( onTap: onOpen, child: Padding( padding: const EdgeInsets.all(AppDimens.cardPadding), child: Row( children: [ Container( width: AppDimens.buttonLarge, height: AppDimens.buttonLarge, decoration: const BoxDecoration( color: AppColors.badgePink, shape: BoxShape.circle, ), child: const Icon( Icons.workspace_premium_rounded, color: AppColors.badgePinkText, size: 22, ), ), const SizedBox(width: AppDimens.spaceMd), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( l10n.vipMembership, style: const TextStyle( color: AppColors.onSurface, fontSize: AppDimens.listTitle, fontWeight: FontWeight.w700, ), ), const SizedBox(height: 3), Text( l10n.vipUnlockMessage, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( color: AppColors.muted, fontSize: AppDimens.caption, ), ), ], ), ), Text( l10n.joinVip, style: const TextStyle( color: AppColors.blue, fontSize: AppDimens.caption, fontWeight: FontWeight.w700, ), ), ], ), ), ), ), ); } } /// 我的页功能菜单。 class MineMenuList extends StatelessWidget { const MineMenuList({ super.key, required this.onOpen, required this.onLanguage, required this.languageLabel, }); final ValueChanged onOpen; final VoidCallback onLanguage; final String languageLabel; @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; return Container( key: const Key('mine-menu'), decoration: BoxDecoration( color: AppColors.card, borderRadius: BorderRadius.circular(AppDimens.cardRadius), boxShadow: const [AppTheme.cardShadow], ), child: Material( color: Colors.transparent, borderRadius: BorderRadius.circular(AppDimens.cardRadius), clipBehavior: Clip.antiAlias, child: Column( children: [ _row( key: const Key('mine-works'), icon: Icons.video_collection_outlined, title: l10n.myWorks, destination: MineDestination.works, ), _divider(), _row( key: const Key('mine-creator-center'), icon: Icons.auto_awesome_rounded, title: l10n.creatorCenter, destination: MineDestination.creatorCenter, ), _divider(), _row( key: const Key('mine-notices'), icon: Icons.notifications_none_rounded, title: l10n.notices, destination: MineDestination.notices, ), _divider(), _row( key: const Key('mine-settings'), icon: Icons.settings_outlined, title: l10n.settings, destination: MineDestination.settings, ), _divider(), _languageRow(context), _divider(), _row( key: const Key('mine-help'), icon: Icons.help_outline_rounded, title: l10n.helpFeedback, destination: MineDestination.help, ), ], ), ), ); } Widget _languageRow(BuildContext context) { final l10n = AppLocalizations.of(context)!; return ListTile( key: const Key('mine-language'), minTileHeight: 48, contentPadding: const EdgeInsets.symmetric(horizontal: 14), leading: const Icon( Icons.language_rounded, color: AppColors.blue, size: 20, ), title: Text( l10n.language, style: const TextStyle( color: AppColors.onSurface, fontSize: AppDimens.body, ), ), trailing: Row( mainAxisSize: MainAxisSize.min, children: [ Text( languageLabel, style: const TextStyle(color: AppColors.muted, fontSize: 11), ), const SizedBox(width: 4), const Icon( Icons.chevron_right_rounded, color: AppColors.subtle, size: 18, ), ], ), onTap: onLanguage, ); } Widget _row({ required Key key, required IconData icon, required String title, required MineDestination destination, }) { return ListTile( key: key, minTileHeight: 48, contentPadding: const EdgeInsets.symmetric(horizontal: 14), leading: Icon(icon, color: AppColors.blue, size: 20), title: Text( title, style: const TextStyle( color: AppColors.onSurface, fontSize: AppDimens.body, ), ), trailing: const Icon( Icons.chevron_right_rounded, color: AppColors.subtle, size: 18, ), onTap: () => onOpen(destination), ); } Widget _divider() { return const Divider(height: 1, indent: 14, endIndent: 14); } }