// Author: fruit.com.cn import 'package:flutter/material.dart'; import '../../../core/data/models/drama.dart'; import '../../../core/formatting/localized_content.dart'; import '../../../core/theme/app_colors.dart'; import '../../../core/widgets/remote_image.dart'; import '../../../l10n/app_localizations.dart'; /// 播放页快捷菜单:当前剧、发现、追剧与历史。 class HomeMenuSheet extends StatelessWidget { const HomeMenuSheet({ super.key, required this.drama, required this.onOpenSeries, required this.onDiscover, required this.onHistory, required this.onWatchlist, }); final Drama drama; final VoidCallback onOpenSeries; final VoidCallback onDiscover; final VoidCallback onHistory; final VoidCallback onWatchlist; @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; void closeThen(VoidCallback action) { Navigator.pop(context); action(); } return SafeArea( child: SingleChildScrollView( padding: const EdgeInsets.fromLTRB(16, 4, 16, 20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ _DramaSummary( drama: drama, l10n: l10n, onOpenSeries: () => closeThen(onOpenSeries), ), const SizedBox(height: 14), _quickAccess(l10n, closeThen), ], ), ), ); } Widget _quickAccess( AppLocalizations l10n, void Function(VoidCallback) closeThen, ) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( l10n.quickAccess, style: const TextStyle( color: AppColors.onSurface, fontSize: 13, fontWeight: FontWeight.w800, ), ), const SizedBox(height: 8), Row( children: [ _item( key: const Key('drawer-discover'), icon: Icons.explore_outlined, label: l10n.discoverTab, onTap: () => closeThen(onDiscover), ), _item( key: const Key('drawer-watchlist'), icon: Icons.bookmark_border_rounded, label: l10n.watchlist, onTap: () => closeThen(onWatchlist), ), _item( key: const Key('drawer-history'), icon: Icons.history_rounded, label: l10n.history, onTap: () => closeThen(onHistory), ), ], ), ], ); } Widget _item({ required Key key, required IconData icon, required String label, required VoidCallback onTap, }) { return Expanded( child: Padding( padding: const EdgeInsets.only(right: 8), child: _MenuTile(key: key, icon: icon, label: label, onTap: onTap), ), ); } } class _DramaSummary extends StatelessWidget { const _DramaSummary({ required this.drama, required this.l10n, required this.onOpenSeries, }); final Drama drama; final AppLocalizations l10n; final VoidCallback onOpenSeries; @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( color: AppColors.cardAlt, borderRadius: BorderRadius.circular(12), ), child: Row( children: [ ClipRRect( borderRadius: BorderRadius.circular(10), child: RemoteImage(drama.posterUrl, width: 64, height: 86), ), const SizedBox(width: 10), Expanded(child: _details()), ], ), ); } Widget _details() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( localizedDramaTitle(l10n, drama), maxLines: 2, overflow: TextOverflow.ellipsis, style: const TextStyle( color: AppColors.onSurface, fontSize: 15, fontWeight: FontWeight.w800, ), ), const SizedBox(height: 4), Text( l10n.episodeCount(drama.episodeCount), style: const TextStyle(color: AppColors.muted, fontSize: 9), ), const SizedBox(height: 8), _button(), ], ); } Widget _button() { return SizedBox( height: 34, child: FilledButton.icon( key: const Key('drawer-open-series'), onPressed: onOpenSeries, style: FilledButton.styleFrom( backgroundColor: AppColors.blue, foregroundColor: AppColors.onPrimary, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(9)), textStyle: const TextStyle(fontSize: 11), ), icon: const Icon(Icons.play_arrow_rounded, size: 15), label: Text(l10n.exploreSeries), ), ); } } class _MenuTile extends StatelessWidget { const _MenuTile({ 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 Material( color: AppColors.quick, borderRadius: BorderRadius.circular(12), clipBehavior: Clip.antiAlias, child: InkWell( onTap: onTap, child: SizedBox( height: 58, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(icon, color: AppColors.secondary, size: 16), const SizedBox(height: 4), Text( label, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle(color: AppColors.muted, fontSize: 9), ), ], ), ), ), ); } }