feat(app): 完善播放协议搜索与空状态

This commit is contained in:
Zhou Weidong committed 2026-10-23 12:38:47 +08:00
1 parent 671e0ce143
commit ef29fc5f15
85 files changed
+2976 -768

No files matched your search

+34 -11
View File
@@ -22,19 +22,25 @@ const double _segmentTrackRadius = 10;
const double _segmentTrackPadding = 4;
const double _segmentPadding = 10;
const List<double> _speedOptions = [0.75, 1.0, 1.25, 1.5, 2.0, 3.0];
const List<String> _qualityOptions = ['AUTO', '720P', '1080P'];
const String _autoQuality = 'AUTO';
const List<String> _qualityOptions = ['AUTO', '360P', '480P', '720P', '1080P'];
/// 更多面板运行状态。
class PlayerMoreState {
/// 创建更多面板状态。
const PlayerMoreState({required this.speed, required this.qualities});
const PlayerMoreState({
required this.speed,
required this.qualities,
this.selectedQuality = 'AUTO',
});
/// 当前倍速。
final double speed;
/// 后端下发的清晰度档位。
final List<String> qualities;
/// 当前选中的档位,如 AUTO / 720P。
final String selectedQuality;
}
/// 更多面板动作集合。
@@ -44,6 +50,7 @@ class PlayerMoreActions {
required this.onSpeedChanged,
required this.onClear,
required this.onDownload,
required this.onQualityChanged,
this.onPip,
});
@@ -56,6 +63,9 @@ class PlayerMoreActions {
/// 离线缓存当前集。
final VoidCallback onDownload;
/// 切换清晰度。成功返回 true;失败时面板恢复到上一档。
final Future<bool> Function(String quality) onQualityChanged;
/// 进入小窗播放;平台不支持时为 null。
final VoidCallback? onPip;
}
@@ -85,6 +95,7 @@ class PlayerMoreSheet extends StatefulWidget {
class _PlayerMoreSheetState extends State<PlayerMoreSheet> {
late double _speed = widget.state.speed;
late String _quality = widget.state.selectedQuality.toUpperCase();
@override
Widget build(BuildContext context) {
@@ -247,19 +258,31 @@ class _PlayerMoreSheetState extends State<PlayerMoreSheet> {
);
}
Future<void> _chooseQuality(String quality) async {
if (_quality == quality) return;
final previous = _quality;
setState(() => _quality = quality);
final switched = await widget.actions.onQualityChanged(quality);
if (!mounted || switched) return;
setState(() => _quality = previous);
}
bool _hasQuality(String quality) {
final wanted = quality.toUpperCase();
for (final item in widget.state.qualities) {
if (item.toUpperCase() == wanted) return true;
}
return false;
}
Widget _qualitySegment(AppLocalizations l10n, String quality) {
final enabled = widget.state.qualities.contains(quality);
final selected =
quality == _autoQuality && enabled ||
!widget.state.qualities.contains(_autoQuality) &&
widget.state.qualities.isNotEmpty &&
widget.state.qualities.first == quality;
final enabled = _hasQuality(quality);
return _SegmentButton(
key: Key('player-more-quality-$quality'),
label: enabled ? quality : '$quality · ${l10n.qualityUnavailable}',
selected: selected,
selected: enabled && _quality == quality,
enabled: enabled,
onTap: enabled ? () {} : null,
onTap: enabled ? () => _chooseQuality(quality) : null,
);
}