diff --git a/lib/pages/setting/widgets/model.dart b/lib/pages/setting/widgets/model.dart index c5dd35766..da22b9953 100644 --- a/lib/pages/setting/widgets/model.dart +++ b/lib/pages/setting/widgets/model.dart @@ -2098,6 +2098,13 @@ List get extraSettings => [ setKey: SettingBoxKey.showDynActionBar, defaultVal: true, ), + SettingsModel( + settingsType: SettingsType.sw1tch, + title: '启用拖拽字幕调整底部边距', + leading: Icon(MdiIcons.dragVariant), + setKey: SettingBoxKey.enableDragSubtitle, + defaultVal: false, + ), SettingsModel( settingsType: SettingsType.sw1tch, enableFeedback: true, diff --git a/lib/pages/video/detail/widgets/header_control.dart b/lib/pages/video/detail/widgets/header_control.dart index 552f1c662..1fbc29d12 100644 --- a/lib/pages/video/detail/widgets/header_control.dart +++ b/lib/pages/video/detail/widgets/header_control.dart @@ -1238,9 +1238,9 @@ class HeaderControlState extends State { data: sliderTheme, child: Slider( min: 0, - max: 100, + max: 200, value: subtitlePaddingB.toDouble(), - divisions: 100, + divisions: 200, label: '$subtitlePaddingB', onChanged: (double val) { updateBottomPadding(val.round()); diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index ab5132dc4..450be3273 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -256,6 +256,7 @@ class PlPlayerController { late final darkVideoPage = GStorage.darkVideoPage; late final enableSlideVolumeBrightness = GStorage.enableSlideVolumeBrightness; late final enableSlideFS = GStorage.enableSlideFS; + late final enableDragSubtitle = GStorage.enableDragSubtitle; /// 弹幕权重 int danmakuWeight = 0; @@ -324,6 +325,11 @@ class PlPlayerController { ); } + void onUpdatePadding(EdgeInsets padding) { + subtitlePaddingB = padding.bottom.round().clamp(0, 200); + putSubtitleSettings(); + } + void updateSliderPositionSecond() { int newSecond = _sliderPosition.value.inSeconds; if (sliderPositionSeconds.value != newSecond) { diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index b2f17355a..a15c68f4b 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -949,6 +949,132 @@ class _PLVideoPlayerState extends State }, flipX: plPlayerController.flipX.value, flipY: plPlayerController.flipY.value, + onVerticalDragStart: (details) { + if (plPlayerController.controlsLock.value) return; + if (details.localPosition.dy < 40) return; + if (details.localPosition.dx < 40) return; + if (details.localPosition.dx > context.width - 40) return; + if (details.localPosition.dy > context.height - 40) return; + _initialFocalPoint = details.localPosition; + _gestureType = null; + }, + onVerticalDragUpdate: (details) { + if (plPlayerController.controlsLock.value) return; + if (plPlayerController.enableSlideVolumeBrightness.not && + plPlayerController.enableSlideFS.not) { + return; + } + RenderBox renderBox = + _playerKey.currentContext!.findRenderObject() as RenderBox; + final double totalWidth = renderBox.size.width; + final double tapPosition = details.localPosition.dx; + final double sectionWidth = totalWidth / 3; + late String gestureType; + if (tapPosition < sectionWidth) { + if (plPlayerController.enableSlideVolumeBrightness.not) { + return; + } + // 左边区域 + gestureType = 'left'; + } else if (tapPosition < sectionWidth * 2) { + if (plPlayerController.enableSlideFS.not) { + return; + } + // 全屏 + gestureType = 'center'; + } else { + if (plPlayerController.enableSlideVolumeBrightness.not) { + return; + } + // 右边区域 + gestureType = 'right'; + } + + if (_gestureType != null && _gestureType != gestureType) { + return; + } + _gestureType = gestureType; + + if (_gestureType == 'left') { + // 左边区域 👈 + final double level = renderBox.size.height * 3; + final double brightness = + _brightnessValue.value - details.delta.dy / level; + final double result = brightness.clamp(0.0, 1.0); + setBrightness(result); + } else if (_gestureType == 'center') { + // 全屏 + const double threshold = 2.5; // 滑动阈值 + double cumulativeDy = + details.localPosition.dy - _initialFocalPoint.dy; + + void fullScreenTrigger(bool status) { + plPlayerController.triggerFullScreen(status: status); + } + + if (cumulativeDy > threshold) { + _gestureType = 'center_down'; + if (isFullScreen ^ fullScreenGestureReverse) { + fullScreenTrigger(fullScreenGestureReverse); + } + // debugPrint('center_down:$cumulativeDy'); + } else if (cumulativeDy < -threshold) { + _gestureType = 'center_up'; + if (!isFullScreen ^ fullScreenGestureReverse) { + fullScreenTrigger(!fullScreenGestureReverse); + } + // debugPrint('center_up:$cumulativeDy'); + } + } else if (_gestureType == 'right') { + // 右边区域 + final double level = renderBox.size.height * 0.5; + EasyThrottle.throttle( + 'setVolume', const Duration(milliseconds: 20), () { + final double volume = + _volumeValue.value - details.delta.dy / level; + final double result = volume.clamp(0.0, 1.0); + setVolume(result); + }); + } + }, + onVerticalDragEnd: (details) { + interacting = false; + _initialFocalPoint = Offset.zero; + _gestureType = null; + }, + onTap: () { + plPlayerController.controls = + !plPlayerController.showControls.value; + }, + onDoubleTapDown: (TapDownDetails details) { + // live模式下禁用 锁定时🔒禁用 + if (plPlayerController.videoType.value == 'live' || + plPlayerController.controlsLock.value) { + return; + } + RenderBox renderBox = + _playerKey.currentContext!.findRenderObject() as RenderBox; + final double totalWidth = renderBox.size.width; + final double tapPosition = details.localPosition.dx; + final double sectionWidth = totalWidth / 4; + String type = 'left'; + if (tapPosition < sectionWidth) { + type = 'left'; + } else if (tapPosition < sectionWidth * 3) { + type = 'center'; + } else { + type = 'right'; + } + doubleTapFuc(type); + }, + onLongPressStart: (LongPressStartDetails detail) { + plPlayerController.setLongPressStatus(true); + }, + onLongPressEnd: (LongPressEndDetails details) { + plPlayerController.setLongPressStatus(false); + }, + enableDragSubtitle: plPlayerController.enableDragSubtitle, + onUpdatePadding: plPlayerController.onUpdatePadding, ), ), @@ -1155,143 +1281,6 @@ class _PLVideoPlayerState extends State // } // }), - /// 手势 - Positioned.fill( - left: 16, - top: 25, - right: 15, - bottom: 15, - child: Semantics( - label: '双击开关控件', - child: GestureDetector( - onVerticalDragStart: (details) { - if (plPlayerController.controlsLock.value) return; - if (details.localPosition.dy < 40) return; - if (details.localPosition.dx < 40) return; - if (details.localPosition.dx > context.width - 40) return; - if (details.localPosition.dy > context.height - 40) return; - _initialFocalPoint = details.localPosition; - _gestureType = null; - }, - onVerticalDragUpdate: (details) { - if (plPlayerController.controlsLock.value) return; - if (plPlayerController.enableSlideVolumeBrightness.not && - plPlayerController.enableSlideFS.not) { - return; - } - RenderBox renderBox = - _playerKey.currentContext!.findRenderObject() as RenderBox; - final double totalWidth = renderBox.size.width; - final double tapPosition = details.localPosition.dx; - final double sectionWidth = totalWidth / 3; - late String gestureType; - if (tapPosition < sectionWidth) { - if (plPlayerController.enableSlideVolumeBrightness.not) { - return; - } - // 左边区域 - gestureType = 'left'; - } else if (tapPosition < sectionWidth * 2) { - if (plPlayerController.enableSlideFS.not) { - return; - } - // 全屏 - gestureType = 'center'; - } else { - if (plPlayerController.enableSlideVolumeBrightness.not) { - return; - } - // 右边区域 - gestureType = 'right'; - } - - if (_gestureType != null && _gestureType != gestureType) { - return; - } - _gestureType = gestureType; - - if (_gestureType == 'left') { - // 左边区域 👈 - final double level = renderBox.size.height * 3; - final double brightness = - _brightnessValue.value - details.delta.dy / level; - final double result = brightness.clamp(0.0, 1.0); - setBrightness(result); - } else if (_gestureType == 'center') { - // 全屏 - const double threshold = 2.5; // 滑动阈值 - double cumulativeDy = - details.localPosition.dy - _initialFocalPoint.dy; - - void fullScreenTrigger(bool status) { - plPlayerController.triggerFullScreen(status: status); - } - - if (cumulativeDy > threshold) { - _gestureType = 'center_down'; - if (isFullScreen ^ fullScreenGestureReverse) { - fullScreenTrigger(fullScreenGestureReverse); - } - // debugPrint('center_down:$cumulativeDy'); - } else if (cumulativeDy < -threshold) { - _gestureType = 'center_up'; - if (!isFullScreen ^ fullScreenGestureReverse) { - fullScreenTrigger(!fullScreenGestureReverse); - } - // debugPrint('center_up:$cumulativeDy'); - } - } else if (_gestureType == 'right') { - // 右边区域 - final double level = renderBox.size.height * 0.5; - EasyThrottle.throttle( - 'setVolume', const Duration(milliseconds: 20), () { - final double volume = - _volumeValue.value - details.delta.dy / level; - final double result = volume.clamp(0.0, 1.0); - setVolume(result); - }); - } - }, - onVerticalDragEnd: (details) { - interacting = false; - _initialFocalPoint = Offset.zero; - _gestureType = null; - }, - onTap: () { - plPlayerController.controls = - !plPlayerController.showControls.value; - }, - onDoubleTapDown: (TapDownDetails details) { - // live模式下禁用 锁定时🔒禁用 - if (plPlayerController.videoType.value == 'live' || - plPlayerController.controlsLock.value) { - return; - } - RenderBox renderBox = - _playerKey.currentContext!.findRenderObject() as RenderBox; - final double totalWidth = renderBox.size.width; - final double tapPosition = details.localPosition.dx; - final double sectionWidth = totalWidth / 4; - String type = 'left'; - if (tapPosition < sectionWidth) { - type = 'left'; - } else if (tapPosition < sectionWidth * 3) { - type = 'center'; - } else { - type = 'right'; - } - doubleTapFuc(type); - }, - onLongPressStart: (LongPressStartDetails detail) { - plPlayerController.setLongPressStatus(true); - }, - onLongPressEnd: (LongPressEndDetails details) { - plPlayerController.setLongPressStatus(false); - }, - ), - ), - ), - // 头部、底部控制条 Obx( () => Positioned.fill( diff --git a/lib/utils/storage.dart b/lib/utils/storage.dart index 178db79e4..8f58c1305 100644 --- a/lib/utils/storage.dart +++ b/lib/utils/storage.dart @@ -436,6 +436,9 @@ class GStorage { static int get appFontWeight => GStorage.setting.get(SettingBoxKey.appFontWeight, defaultValue: -1); + static bool get enableDragSubtitle => GStorage.setting + .get(SettingBoxKey.enableDragSubtitle, defaultValue: false); + static List get dynamicDetailRatio => List.from(setting .get(SettingBoxKey.dynamicDetailRatio, defaultValue: [60.0, 40.0])); @@ -716,6 +719,7 @@ class SettingBoxKey { liveQuality = 'liveQuality', liveQualityCellular = 'liveQualityCellular', appFontWeight = 'appFontWeight', + enableDragSubtitle = 'enableDragSubtitle', // Sponsor Block enableSponsorBlock = 'enableSponsorBlock', diff --git a/pubspec.lock b/pubspec.lock index 5ee29e9aa..30e27abfd 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1212,7 +1212,7 @@ packages: description: path: media_kit_video ref: "version_1.2.5" - resolved-ref: "134abc2548eea0f8d31a99964aed51ff03a91a5d" + resolved-ref: a74d1af2bcc6b5c88b2216c594e7e3eba0c7cee5 url: "https://github.com/bggRGjQaUbCoE/media-kit.git" source: git version: "1.2.5"