feat: relative slide (#662)

This commit is contained in:
My-Responsitories
2025-04-11 09:57:22 +08:00
committed by GitHub
parent de029b7043
commit 5aa5308a50
3 changed files with 47 additions and 11 deletions

View File

@@ -774,13 +774,30 @@ List<SettingsModel> get playSettings => [
), ),
_getVideoFilterSelectModel( _getVideoFilterSelectModel(
context: Get.context!, context: Get.context!,
title: '快进/快退时长', title: '双击快进/快退时长',
suffix: 's', suffix: 's',
key: SettingBoxKey.fastForBackwardDuration, key: SettingBoxKey.fastForBackwardDuration,
values: [5, 10, 15], values: [5, 10, 15],
defaultValue: 10, defaultValue: 10,
isFilter: false, isFilter: false,
), ),
SettingsModel(
settingsType: SettingsType.sw1tch,
title: '滑动快进/快退使用相对时长',
leading: const Icon(Icons.swap_horiz_outlined),
setKey: SettingBoxKey.useRelativeSlide,
defaultVal: false,
),
_getVideoFilterSelectModel(
context: Get.context!,
title: '滑动快进/快退时长',
subtitle: '从播放器一端滑到另一端的快进/快退时长',
suffix: GStorage.useRelativeSlide ? '%' : 's',
key: SettingBoxKey.sliderDuration,
values: [25, 50, 90, 100],
defaultValue: 90,
isFilter: false,
),
SettingsModel( SettingsModel(
settingsType: SettingsType.normal, settingsType: SettingsType.normal,
title: '自动启用字幕', title: '自动启用字幕',
@@ -2512,6 +2529,7 @@ SettingsModel _getBanwordModel(
SettingsModel _getVideoFilterSelectModel({ SettingsModel _getVideoFilterSelectModel({
required BuildContext context, required BuildContext context,
required String title, required String title,
String? subtitle,
String? suffix, String? suffix,
required String key, required String key,
required List<int> values, required List<int> values,
@@ -2523,9 +2541,12 @@ SettingsModel _getVideoFilterSelectModel({
settingsType: SettingsType.normal, settingsType: SettingsType.normal,
title: '$title${isFilter ? '过滤' : ''}', title: '$title${isFilter ? '过滤' : ''}',
leading: const Icon(Icons.timelapse_outlined), leading: const Icon(Icons.timelapse_outlined),
getSubtitle: () => isFilter subtitle: subtitle,
? '过滤掉$title小于$value${suffix ?? ""}」的视频' getSubtitle: subtitle == null
: '当前$title:「$value${suffix ?? ""}', ? () => isFilter
? '过滤掉$title小于$value${suffix ?? ""}」的视频'
: '当前$title:「$value${suffix ?? ""}'
: null,
onTap: (setState) async { onTap: (setState) async {
var result = await showDialog<int>( var result = await showDialog<int>(
context: context, context: context,

View File

@@ -110,6 +110,15 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
late final RxBool showRestoreScaleBtn = false.obs; late final RxBool showRestoreScaleBtn = false.obs;
late final _isRelative = GStorage.useRelativeSlide;
late final _offset = _isRelative
? GStorage.sliderDuration / 100
: GStorage.sliderDuration * 1000;
num get sliderScale => _isRelative
? plPlayerController.duration.value.inMilliseconds * _offset
: _offset;
Offset _initialFocalPoint = Offset.zero; Offset _initialFocalPoint = Offset.zero;
String? _gestureType; String? _gestureType;
//播放器放缩 //播放器放缩
@@ -820,18 +829,16 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
final int curSliderPosition = final int curSliderPosition =
plPlayerController.sliderPosition.value.inMilliseconds; plPlayerController.sliderPosition.value.inMilliseconds;
final double scale = 90000 / renderBox.size.width; final double width = renderBox.size.width;
final Duration pos = Duration( final Duration pos = Duration(
milliseconds: milliseconds: curSliderPosition +
curSliderPosition + (delta.dx * scale).round()); (sliderScale * delta.dx / width).round()); // TODO
final Duration result = final Duration result =
pos.clamp(Duration.zero, plPlayerController.duration.value); pos.clamp(Duration.zero, plPlayerController.duration.value);
final height = renderBox.size.height * 0.125; final height = renderBox.size.height * 0.125;
if (details.localFocalPoint.dy <= height && if (details.localFocalPoint.dy <= height &&
(details.localFocalPoint.dx >= (details.localFocalPoint.dx >= width * 0.875 ||
renderBox.size.width * 0.875 || details.localFocalPoint.dx <= width * 0.125)) {
details.localFocalPoint.dx <=
renderBox.size.width * 0.125)) {
plPlayerController.cancelSeek = true; plPlayerController.cancelSeek = true;
plPlayerController.showPreview.value = false; plPlayerController.showPreview.value = false;
if (plPlayerController.hasToast != true) { if (plPlayerController.hasToast != true) {

View File

@@ -145,6 +145,12 @@ class GStorage {
setting.get(SettingBoxKey.subtitlePreference, setting.get(SettingBoxKey.subtitlePreference,
defaultValue: SubtitlePreference.values.first.code); defaultValue: SubtitlePreference.values.first.code);
static bool get useRelativeSlide =>
setting.get(SettingBoxKey.useRelativeSlide, defaultValue: false);
static int get sliderDuration =>
setting.get(SettingBoxKey.sliderDuration, defaultValue: 90);
static int get defaultVideoQa => setting.get( static int get defaultVideoQa => setting.get(
SettingBoxKey.defaultVideoQa, SettingBoxKey.defaultVideoQa,
defaultValue: VideoQuality.values.last.code, defaultValue: VideoQuality.values.last.code,
@@ -639,6 +645,8 @@ class SettingBoxKey {
pipNoDanmaku = 'pipNoDanmaku', pipNoDanmaku = 'pipNoDanmaku',
enableAutoLongPressSpeed = 'enableAutoLongPressSpeed', enableAutoLongPressSpeed = 'enableAutoLongPressSpeed',
subtitlePreference = 'subtitlePreference', subtitlePreference = 'subtitlePreference',
useRelativeSlide = 'useRelativeSlide',
sliderDuration = 'sliderOffset',
// youtube 双击快进快退 // youtube 双击快进快退
enableQuickDouble = 'enableQuickDouble', enableQuickDouble = 'enableQuickDouble',