Files
ReelShort/lib/pages/player/widgets/player_more_sheet.dart
T

229 lines
6.3 KiB
Dart

// Author: fruit.com.cn
import 'package:flutter/material.dart';
import '../../../core/theme/app_colors.dart';
import '../../../l10n/app_localizations.dart';
import 'player_text_size_sheet.dart';
import 'quality_sheet.dart';
const double _sheetRadius = 20;
/// 更多面板运行状态。
class PlayerMoreState {
/// 创建更多面板状态。
const PlayerMoreState({
required this.speed,
required this.qualities,
required this.textScale,
required this.pipAvailable,
});
/// 当前倍速。
final double speed;
/// 后端下发的清晰度档位。
final List<String> qualities;
/// 当前信息文字缩放比例。
final double textScale;
/// 设备是否提供画中画入口。
final bool pipAvailable;
}
/// 更多面板动作集合。
class PlayerMoreActions {
/// 创建动作集合。
const PlayerMoreActions({
required this.onSpeed,
required this.onQuality,
required this.onDownload,
required this.onTextSize,
required this.onReport,
this.onPip,
});
/// 打开倍速面板。
final VoidCallback onSpeed;
/// 打开清晰度面板。
final VoidCallback onQuality;
/// 下载当前集。
final VoidCallback onDownload;
/// 打开文字大小面板。
final VoidCallback onTextSize;
/// 举报当前剧。
final VoidCallback onReport;
/// 进入画中画。
final VoidCallback? onPip;
}
/// K28 播放页更多操作面板。
class PlayerMoreSheet extends StatelessWidget {
/// 创建更多操作面板。
const PlayerMoreSheet({
super.key,
required this.l10n,
required this.state,
required this.actions,
});
/// 当前语言包。
final AppLocalizations l10n;
/// 面板状态。
final PlayerMoreState state;
/// 面板动作。
final PlayerMoreActions actions;
@override
Widget build(BuildContext context) {
return Container(
key: const Key('player-more-sheet'),
decoration: const BoxDecoration(
color: AppColors.card,
borderRadius: BorderRadius.vertical(top: Radius.circular(_sheetRadius)),
),
child: SafeArea(
top: false,
child: Padding(
padding: const EdgeInsets.fromLTRB(16, 14, 16, 16),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(4, 0, 4, 10),
child: Text(
l10n.more,
style: const TextStyle(
color: AppColors.onSurface,
fontSize: 20,
fontWeight: FontWeight.w800,
),
),
),
_MoreRow(
key: const Key('player-more-speed'),
icon: Icons.speed_rounded,
title: l10n.playbackSpeed,
value: '${state.speed}x',
action: actions.onSpeed,
),
if (state.qualities.isNotEmpty)
_MoreRow(
key: const Key('player-more-quality'),
icon: Icons.high_quality_rounded,
title: l10n.playbackQuality,
value: state.qualities.contains(QualitySheet.autoQuality)
? l10n.qualityAuto
: state.qualities.first,
action: actions.onQuality,
),
_MoreRow(
key: const Key('player-more-download'),
icon: Icons.download_rounded,
title: l10n.downloads,
value: '',
action: actions.onDownload,
),
_MoreRow(
key: const Key('player-more-text-size'),
icon: Icons.format_size_rounded,
title: l10n.textSize,
value: playerTextSizeLabel(l10n, state.textScale),
action: actions.onTextSize,
),
if (state.pipAvailable && actions.onPip != null)
_MoreRow(
key: const Key('player-more-pip'),
icon: Icons.picture_in_picture_alt_rounded,
title: l10n.pictureInPicture,
value: '',
action: actions.onPip!,
),
_MoreRow(
key: const Key('player-more-report'),
icon: Icons.flag_outlined,
title: l10n.reportDrama,
value: '',
action: actions.onReport,
),
],
),
),
),
);
}
}
class _MoreRow extends StatelessWidget {
const _MoreRow({
super.key,
required this.icon,
required this.title,
required this.value,
required this.action,
});
final IconData icon;
final String title;
final String value;
final VoidCallback action;
@override
Widget build(BuildContext context) {
return Material(
color: Colors.transparent,
borderRadius: BorderRadius.circular(12),
child: InkWell(
borderRadius: BorderRadius.circular(12),
onTap: () {
Navigator.pop(context);
WidgetsBinding.instance.addPostFrameCallback((_) => action());
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 13),
child: Row(
children: [
Icon(icon, color: AppColors.muted, size: 21),
const SizedBox(width: 12),
Expanded(
child: Text(
title,
style: const TextStyle(
color: AppColors.onSurface,
fontSize: 14,
fontWeight: FontWeight.w700,
),
),
),
if (value.isNotEmpty)
Text(
value,
style: const TextStyle(
color: AppColors.blue,
fontSize: 12,
fontWeight: FontWeight.w700,
),
),
const SizedBox(width: 4),
const Icon(
Icons.chevron_right_rounded,
color: AppColors.subtle,
size: 20,
),
],
),
),
),
);
}
}