// Author: fruit.com.cn import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import '../../../core/data/models/drama.dart'; import '../../../core/formatting/localized_content.dart'; import '../../../core/theme/app_colors.dart'; import '../../../core/theme/app_dimens.dart'; import '../../../l10n/app_localizations.dart'; import 'episode_picker_cell.dart'; const int _columns = 6; const double _sheetHeightFactor = 0.52; const double _cellAspect = 1.05; const double _sheetRadius = 20; /// K28 选集面板:六列等宽网格、当前集高亮、锁定集显示锁标。 class EpisodePickerSheet extends StatelessWidget { /// 创建选集面板。 const EpisodePickerSheet({ super.key, required this.drama, required this.currentNumber, required this.onSelect, }); /// 当前短剧。 final Drama drama; /// 当前集号。 final int currentNumber; /// 点击某集,参数为该集在原始列表中的索引。 final ValueChanged onSelect; @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; final episodes = drama.episodes; return AnnotatedRegion( key: const Key('player-episodes-system-overlay'), value: SystemUiOverlayStyle.dark.copyWith( statusBarColor: Colors.transparent, systemNavigationBarColor: AppColors.card, systemNavigationBarDividerColor: Colors.transparent, systemNavigationBarIconBrightness: Brightness.dark, systemNavigationBarContrastEnforced: false, ), child: Container( key: const Key('player-episodes-sheet'), height: MediaQuery.sizeOf(context).height * _sheetHeightFactor, decoration: const BoxDecoration( color: AppColors.card, borderRadius: BorderRadius.vertical( top: Radius.circular(_sheetRadius), ), ), child: SafeArea( top: false, bottom: true, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.fromLTRB(20, 14, 8, 4), child: Row( children: [ Expanded( child: Text( l10n.episodes, style: const TextStyle( color: AppColors.onSurface, fontSize: 20, fontWeight: FontWeight.w800, ), ), ), IconButton( key: const Key('player-episodes-close'), tooltip: l10n.close, onPressed: () => Navigator.pop(context), icon: const Icon(Icons.close_rounded), ), ], ), ), Padding( padding: const EdgeInsets.fromLTRB(20, 0, 20, 12), child: Row( children: [ Expanded( child: Text( localizedDramaTitle(l10n, drama), maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle( color: AppColors.onSurface, fontSize: 14, fontWeight: FontWeight.w600, ), ), ), Text( l10n.episodeCountLabel(episodes.length), style: const TextStyle( color: AppColors.muted, fontSize: 12, ), ), ], ), ), Expanded( child: GridView.builder( padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: _columns, mainAxisSpacing: AppDimens.spaceSm, crossAxisSpacing: AppDimens.spaceSm, childAspectRatio: _cellAspect, ), itemCount: episodes.length, itemBuilder: (context, index) { final episode = episodes[index]; return EpisodePickerCell( key: Key('player-episode-${episode.number}'), episode: episode, selected: episode.number == currentNumber, lockLabel: l10n.locked, onTap: () { Navigator.pop(context); onSelect(index); }, ); }, ), ), ], ), ), ), ); } }