opt: play speed

Closes #11

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2024-11-26 18:02:33 +08:00
parent 4df9f55e00
commit 1df218b313
6 changed files with 124 additions and 155 deletions

View File

@@ -29,7 +29,6 @@ class BottomControl extends StatefulWidget implements PreferredSizeWidget {
class _BottomControlState extends State<BottomControl> { class _BottomControlState extends State<BottomControl> {
late PlayUrlModel videoInfo; late PlayUrlModel videoInfo;
List<PlaySpeed> playSpeed = PlaySpeed.values;
TextStyle subTitleStyle = const TextStyle(fontSize: 12); TextStyle subTitleStyle = const TextStyle(fontSize: 12);
TextStyle titleStyle = const TextStyle(fontSize: 14); TextStyle titleStyle = const TextStyle(fontSize: 14);
Size get preferredSize => const Size(double.infinity, kToolbarHeight); Size get preferredSize => const Size(double.infinity, kToolbarHeight);

View File

@@ -1,10 +1,10 @@
import 'package:PiliPalaX/utils/extension.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:hive/hive.dart';
import 'package:PiliPalaX/pages/setting/widgets/switch_item.dart'; import 'package:PiliPalaX/pages/setting/widgets/switch_item.dart';
import 'package:PiliPalaX/plugin/pl_player/index.dart'; import 'package:PiliPalaX/plugin/pl_player/index.dart';
import 'package:PiliPalaX/plugin/pl_player/models/play_speed.dart';
import 'package:PiliPalaX/utils/storage.dart'; import 'package:PiliPalaX/utils/storage.dart';
class PlaySpeedPage extends StatefulWidget { class PlaySpeedPage extends StatefulWidget {
@@ -15,11 +15,9 @@ class PlaySpeedPage extends StatefulWidget {
} }
class _PlaySpeedPageState extends State<PlaySpeedPage> { class _PlaySpeedPageState extends State<PlaySpeedPage> {
Box videoStorage = GStorage.video;
Box settingStorage = GStorage.setting;
late double playSpeedDefault; late double playSpeedDefault;
late double longPressSpeedDefault; late double longPressSpeedDefault;
late List customSpeedsList; late List speedList;
late bool enableAutoLongPressSpeed; late bool enableAutoLongPressSpeed;
List<Map<dynamic, dynamic>> sheetMenu = [ List<Map<dynamic, dynamic>> sheetMenu = [
{ {
@@ -29,7 +27,6 @@ class _PlaySpeedPageState extends State<PlaySpeedPage> {
Icons.speed, Icons.speed,
size: 21, size: 21,
), ),
'show': true,
}, },
{ {
'id': 2, 'id': 2,
@@ -38,7 +35,6 @@ class _PlaySpeedPageState extends State<PlaySpeedPage> {
Icons.speed_sharp, Icons.speed_sharp,
size: 21, size: 21,
), ),
'show': true,
}, },
{ {
'id': -1, 'id': -1,
@@ -47,7 +43,6 @@ class _PlaySpeedPageState extends State<PlaySpeedPage> {
Icons.delete_outline, Icons.delete_outline,
size: 21, size: 21,
), ),
'show': true,
}, },
]; ];
@@ -60,10 +55,9 @@ class _PlaySpeedPageState extends State<PlaySpeedPage> {
// 默认长按倍速 // 默认长按倍速
longPressSpeedDefault = longPressSpeedDefault =
videoStorage.get(VideoBoxKey.longPressSpeedDefault, defaultValue: 3.0); videoStorage.get(VideoBoxKey.longPressSpeedDefault, defaultValue: 3.0);
// 自定义倍速 // 倍速
customSpeedsList = speedList = GStorage.speedList;
videoStorage.get(VideoBoxKey.customSpeedsList, defaultValue: []); enableAutoLongPressSpeed = GStorage.setting
enableAutoLongPressSpeed = settingStorage
.get(SettingBoxKey.enableAutoLongPressSpeed, defaultValue: false); .get(SettingBoxKey.enableAutoLongPressSpeed, defaultValue: false);
if (enableAutoLongPressSpeed) { if (enableAutoLongPressSpeed) {
Map newItem = sheetMenu[1]; Map newItem = sheetMenu[1];
@@ -76,7 +70,7 @@ class _PlaySpeedPageState extends State<PlaySpeedPage> {
// 添加自定义倍速 // 添加自定义倍速
void onAddSpeed() { void onAddSpeed() {
double customSpeed = 1.0; double? customSpeed;
showDialog( showDialog(
context: context, context: context,
builder: (context) { builder: (context) {
@@ -88,33 +82,43 @@ class _PlaySpeedPageState extends State<PlaySpeedPage> {
// const Text('输入你想要的视频倍速例如1.0'), // const Text('输入你想要的视频倍速例如1.0'),
const SizedBox(height: 12), const SizedBox(height: 12),
TextField( TextField(
keyboardType: TextInputType.number, autofocus: true,
keyboardType: TextInputType.numberWithOptions(decimal: true),
decoration: InputDecoration( decoration: InputDecoration(
labelText: '自定义倍速', labelText: '自定义倍速',
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(6.0), borderRadius: BorderRadius.circular(6.0),
), ),
), ),
onChanged: (e) { onChanged: (value) {
customSpeed = double.parse(e); customSpeed = double.tryParse(value);
}, },
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp(r'[\d\.]+')),
],
), ),
], ],
), ),
actions: [ actions: [
TextButton( TextButton(
onPressed: () => Get.back(), onPressed: Get.back,
child: const Text('取消'), child: const Text('取消'),
), ),
TextButton( TextButton(
onPressed: () async { onPressed: () async {
customSpeedsList.add(customSpeed); if (customSpeed == null) {
await videoStorage.put( SmartDialog.showToast('输入倍数不合法');
VideoBoxKey.customSpeedsList, customSpeedsList); } else if (speedList.contains(customSpeed)) {
setState(() {}); SmartDialog.showToast('该倍速已存在');
Get.back(); } else {
Get.back();
speedList.add(customSpeed);
speedList.sort();
await videoStorage.put(VideoBoxKey.speedsList, speedList);
setState(() {});
}
}, },
child: const Text('确认添加'), child: const Text('确认'),
) )
], ],
); );
@@ -123,85 +127,83 @@ class _PlaySpeedPageState extends State<PlaySpeedPage> {
} }
// 设定倍速弹窗 // 设定倍速弹窗
void showBottomSheet(type, i) { void showBottomSheet(index) {
showModalBottomSheet<void>( showModalBottomSheet(
context: context, context: context,
isScrollControlled: true, isScrollControlled: true,
builder: (BuildContext context) { clipBehavior: Clip.hardEdge,
return Container( builder: (context) {
padding: const EdgeInsets.only(top: 10), return Column(
child: ListView.builder( mainAxisSize: MainAxisSize.min,
shrinkWrap: true, children: [
physics: const ClampingScrollPhysics(), const SizedBox(height: 10),
//重要 ...sheetMenu.map(
itemCount: sheetMenu.length, (item) => ListTile(
itemBuilder: (BuildContext context, int index) { onTap: () {
return sheetMenu[index]['show'] Navigator.pop(context);
? ListTile( menuAction(index, item['id']);
onTap: () { },
Navigator.pop(context); minLeadingWidth: 0,
menuAction(type, i, sheetMenu[index]['id']); iconColor: Theme.of(context).colorScheme.onSurface,
}, leading: item['leading'],
minLeadingWidth: 0, title: Text(
iconColor: Theme.of(context).colorScheme.onSurface, item['title'],
leading: sheetMenu[index]['leading'], style: Theme.of(context).textTheme.titleSmall,
title: Text( ),
sheetMenu[index]['title'], ),
style: Theme.of(context).textTheme.titleSmall, ),
), SizedBox(height: 25 + MediaQuery.paddingOf(context).bottom),
) ],
: const SizedBox();
},
),
); );
}, },
); );
} }
// //
void menuAction(type, index, id) async { void menuAction(index, id) async {
double chooseSpeed = 1.0; double speed = speedList[index];
if (type == 'system' && id == -1) {
SmartDialog.showToast('系统预设倍速不支持删除');
return;
}
// 获取当前选中的倍速值
if (type == 'system') {
chooseSpeed = PlaySpeed.values[index].value;
} else {
chooseSpeed = customSpeedsList[index];
}
// 设置 // 设置
if (id == 1) { if (id == 1) {
// 设置默认倍速 // 设置默认倍速
playSpeedDefault = chooseSpeed; playSpeedDefault = speed;
videoStorage.put(VideoBoxKey.playSpeedDefault, playSpeedDefault); videoStorage.put(VideoBoxKey.playSpeedDefault, playSpeedDefault);
} else if (id == 2) { } else if (id == 2) {
// 设置默认长按倍速 // 设置默认长按倍速
longPressSpeedDefault = chooseSpeed; longPressSpeedDefault = speed;
videoStorage.put( videoStorage.put(
VideoBoxKey.longPressSpeedDefault, longPressSpeedDefault); VideoBoxKey.longPressSpeedDefault, longPressSpeedDefault);
} else if (id == -1) { } else if (id == -1) {
if (customSpeedsList[index] == playSpeedDefault) { if ([
playSpeedDefault = 1.0; 1.0,
videoStorage.put(VideoBoxKey.playSpeedDefault, playSpeedDefault); playSpeedDefault,
longPressSpeedDefault,
].contains(speed)) {
SmartDialog.showToast('不支持删除默认倍速');
return;
} }
if (customSpeedsList[index] == longPressSpeedDefault) { speedList.removeAt(index);
longPressSpeedDefault = 3.0; await videoStorage.put(VideoBoxKey.speedsList, speedList);
videoStorage.put(
VideoBoxKey.longPressSpeedDefault, longPressSpeedDefault);
}
customSpeedsList.removeAt(index);
await videoStorage.put(VideoBoxKey.customSpeedsList, customSpeedsList);
} }
setState(() {}); setState(() {});
SmartDialog.showToast('操作成功');
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar(title: Text('倍速设置')), appBar: AppBar(
title: Text('倍速设置'),
actions: [
TextButton(
onPressed: () async {
await videoStorage.delete(VideoBoxKey.speedsList);
speedList = GStorage.speedList;
setState(() {});
},
child: Text('重置'),
),
const SizedBox(width: 16),
],
),
body: SingleChildScrollView( body: SingleChildScrollView(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@@ -233,13 +235,12 @@ class _PlaySpeedPageState extends State<PlaySpeedPage> {
}); });
}, },
), ),
!enableAutoLongPressSpeed if (!enableAutoLongPressSpeed)
? ListTile( ListTile(
dense: false, dense: false,
title: const Text('默认长按倍速'), title: const Text('默认长按倍速'),
subtitle: Text(longPressSpeedDefault.toString()), subtitle: Text(longPressSpeedDefault.toString()),
) ),
: const SizedBox(),
Padding( Padding(
padding: const EdgeInsets.only( padding: const EdgeInsets.only(
left: 14, left: 14,
@@ -247,9 +248,18 @@ class _PlaySpeedPageState extends State<PlaySpeedPage> {
bottom: 10, bottom: 10,
top: 20, top: 20,
), ),
child: Text( child: Row(
'系统预设倍速', children: [
style: Theme.of(context).textTheme.titleMedium, Text(
'倍速列表',
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(width: 12),
TextButton(
onPressed: onAddSpeed,
child: const Text('添加'),
),
],
), ),
), ),
Padding( Padding(
@@ -262,64 +272,14 @@ class _PlaySpeedPageState extends State<PlaySpeedPage> {
alignment: WrapAlignment.start, alignment: WrapAlignment.start,
spacing: 8, spacing: 8,
runSpacing: 2, runSpacing: 2,
children: [ children: List.generate(
for (var i in PlaySpeed.values) ...[ speedList.length,
FilledButton.tonal( (index) => FilledButton.tonal(
onPressed: () => showBottomSheet('system', i.index), onPressed: () => showBottomSheet(index),
child: Text(i.description), child: Text(speedList[index].toString()),
), ),
]
],
),
),
Padding(
padding: const EdgeInsets.only(
left: 14,
right: 14,
), ),
child: Row(
children: [
Text(
'自定义倍速',
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(width: 12),
TextButton(
onPressed: () => onAddSpeed(),
child: const Text('添加'),
)
],
)),
Padding(
padding: EdgeInsets.only(
left: 18,
right: 18,
bottom: MediaQuery.of(context).padding.bottom + 40,
), ),
child: customSpeedsList.isNotEmpty
? Wrap(
alignment: WrapAlignment.start,
spacing: 8,
runSpacing: 2,
children: [
for (int i = 0; i < customSpeedsList.length; i++) ...[
FilledButton.tonal(
onPressed: () => showBottomSheet('custom', i),
child: Text(customSpeedsList[i].toString()),
),
]
],
)
: SizedBox(
height: 80,
child: Center(
child: Text(
'未添加',
style: TextStyle(
color: Theme.of(context).colorScheme.outline),
),
),
),
), ),
], ],
), ),

View File

@@ -49,7 +49,6 @@ class HeaderControl extends StatefulWidget implements PreferredSizeWidget {
class _HeaderControlState extends State<HeaderControl> { class _HeaderControlState extends State<HeaderControl> {
late PlayUrlModel videoInfo; late PlayUrlModel videoInfo;
List<PlaySpeed> playSpeed = PlaySpeed.values;
static const TextStyle subTitleStyle = TextStyle(fontSize: 12); static const TextStyle subTitleStyle = TextStyle(fontSize: 12);
static const TextStyle titleStyle = TextStyle(fontSize: 14); static const TextStyle titleStyle = TextStyle(fontSize: 14);
Size get preferredSize => const Size(double.infinity, kToolbarHeight); Size get preferredSize => const Size(double.infinity, kToolbarHeight);

View File

@@ -251,7 +251,7 @@ class PlPlayerController {
late double strokeWidth; late double strokeWidth;
late int fontWeight; late int fontWeight;
late double danmakuDurationVal; late double danmakuDurationVal;
late List<double> speedsList; late List<double> speedList;
double? defaultDuration; double? defaultDuration;
late bool enableAutoLongPressSpeed = false; late bool enableAutoLongPressSpeed = false;
late bool enableLongShowControl; late bool enableLongShowControl;
@@ -374,12 +374,7 @@ class PlPlayerController {
} }
enableLongShowControl = enableLongShowControl =
setting.get(SettingBoxKey.enableLongShowControl, defaultValue: false); setting.get(SettingBoxKey.enableLongShowControl, defaultValue: false);
speedsList = List<double>.from(videoStorage speedList = GStorage.speedList;
.get(VideoBoxKey.customSpeedsList, defaultValue: <double>[]));
for (final PlaySpeed i in PlaySpeed.values) {
speedsList.add(i.value);
}
speedsList.sort();
// _playerEventSubs = onPlayerStatusChanged.listen((PlayerStatus status) { // _playerEventSubs = onPlayerStatusChanged.listen((PlayerStatus status) {
// if (status == PlayerStatus.playing) { // if (status == PlayerStatus.playing) {

View File

@@ -461,7 +461,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
initialValue: plPlayerController.playbackSpeed, initialValue: plPlayerController.playbackSpeed,
color: Colors.black.withOpacity(0.8), color: Colors.black.withOpacity(0.8),
itemBuilder: (BuildContext context) { itemBuilder: (BuildContext context) {
return plPlayerController.speedsList.map((double speed) { return plPlayerController.speedList.map((double speed) {
return PopupMenuItem<double>( return PopupMenuItem<double>(
height: 35, height: 35,
padding: const EdgeInsets.only(left: 30), padding: const EdgeInsets.only(left: 30),

View File

@@ -23,6 +23,22 @@ class GStorage {
static late final Box<dynamic> setting; static late final Box<dynamic> setting;
static late final Box<dynamic> video; static late final Box<dynamic> video;
static List<double> get speedList => List<double>.from(
video.get(
VideoBoxKey.speedsList,
defaultValue: [
0.5,
0.75,
1.0,
1.25,
1.5,
1.75,
2.0,
3.0,
],
),
);
static List<Pair<SegmentType, SkipType>> get blockSettings { static List<Pair<SegmentType, SkipType>> get blockSettings {
List list = setting.get( List list = setting.get(
SettingBoxKey.blockSettings, SettingBoxKey.blockSettings,
@@ -339,8 +355,8 @@ class VideoBoxKey {
playSpeedDefault = 'playSpeedDefault', playSpeedDefault = 'playSpeedDefault',
// 默认长按倍速 // 默认长按倍速
longPressSpeedDefault = 'longPressSpeedDefault', longPressSpeedDefault = 'longPressSpeedDefault',
// 自定义倍速集合 // 倍速集合
customSpeedsList = 'customSpeedsList', speedsList = 'speedsList',
// 画面填充比例 // 画面填充比例
cacheVideoFit = 'cacheVideoFit'; cacheVideoFit = 'cacheVideoFit';
} }