diff --git a/lib/pages/setting/models/play_settings.dart b/lib/pages/setting/models/play_settings.dart index d6e922026..101d19c17 100644 --- a/lib/pages/setting/models/play_settings.dart +++ b/lib/pages/setting/models/play_settings.dart @@ -29,6 +29,13 @@ List get playSettings => [ setKey: SettingBoxKey.enableShowDanmaku, defaultVal: true, ), + const SettingsModel( + settingsType: SettingsType.sw1tch, + title: '启用点击弹幕', + leading: Icon(Icons.touch_app_outlined), + setKey: SettingBoxKey.enableTapDm, + defaultVal: true, + ), SettingsModel( settingsType: SettingsType.normal, onTap: (setState) => Get.toNamed('/playSpeedSet'), diff --git a/lib/pages/video/widgets/header_control.dart b/lib/pages/video/widgets/header_control.dart index fcfe7986a..e7a2226b1 100644 --- a/lib/pages/video/widgets/header_control.dart +++ b/lib/pages/video/widgets/header_control.dart @@ -78,6 +78,7 @@ class HeaderControl extends StatefulWidget { ); if (res.isSuccess) { extra.isLike = !extra.isLike; + SmartDialog.showToast('点赞成功'); return true; } else { res.toast(); @@ -2011,7 +2012,7 @@ class HeaderControlState extends State { }, icon: extra.isLike ? const Icon(Icons.thumb_up_off_alt_sharp) - : const Icon(Icons.thumb_up_off_alt_rounded), + : const Icon(Icons.thumb_up_off_alt_outlined), ), ), if (item.content.selfSend) diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index 2f1082ae0..653ced158 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -324,6 +324,7 @@ class PlPlayerController { } /// 弹幕权重 + late final enableTapDm = Pref.enableTapDm; late int danmakuWeight = Pref.danmakuWeight; late RuleFilter filters = Pref.danmakuFilterRule; // 关联弹幕控制器 diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index 3fa1c49d8..cbdcea52c 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -139,6 +139,16 @@ class _PLVideoPlayerState extends State StreamSubscription? _listener; StreamSubscription? _controlsListener; + @override + void didUpdateWidget(PLVideoPlayer oldWidget) { + super.didUpdateWidget(oldWidget); + if (plPlayerController.enableTapDm && + (widget.maxWidth != oldWidget.maxWidth || + widget.maxHeight != maxHeight)) { + _removeOverlay(); + } + } + @override void initState() { super.initState(); @@ -1056,20 +1066,20 @@ class _PLVideoPlayerState extends State void onTapUp(TapDownDetails? event) { switch (event?.kind) { - case ui.PointerDeviceKind.mouse when (!kDebugMode && Utils.isDesktop): + case ui.PointerDeviceKind.mouse when (Utils.isDesktop): onTapDesktop(); break; default: - if (kDebugMode || Utils.isMobile) { + if (plPlayerController.enableTapDm && Utils.isMobile) { final ctr = plPlayerController.danmakuController; if (ctr != null) { - final item = ctr.findSingleDanmaku(event!.globalPosition); + final item = ctr.findSingleDanmaku(event!.localPosition); if (item == null) { - if (_suspendedDM != null) { + if (_suspendedDm.value != null) { _removeOverlay(); break; } - } else if (item != _suspendedDM) { + } else if (item != _suspendedDm.value?.item) { _showOverlay(item, event, ctr); break; } @@ -1892,9 +1902,102 @@ class _PLVideoPlayerState extends State ) : const SizedBox.shrink(); }), + + Obx(() { + if (_suspendedDm.value case final suspendedDm?) { + final offset = suspendedDm.offset; + final item = suspendedDm.item; + final extra = item.content.extra as VideoDanmaku; + return Positioned( + left: offset.dx, + top: offset.dy, + child: Column( + children: [ + const CustomPaint( + painter: _TrianglePainter(Colors.black54), + size: Size(12, 6), + ), + Container( + width: overlayWidth, + height: overlayHeight, + decoration: const BoxDecoration( + color: Colors.black54, + borderRadius: BorderRadius.all(Radius.circular(18)), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + _overlayItem( + Icon( + size: 20, + extra.isLike + ? Icons.thumb_up_off_alt_sharp + : Icons.thumb_up_off_alt_outlined, + color: Colors.white, + ), + onTap: () { + _removeOverlay(); + HeaderControl.likeDanmaku( + extra, + plPlayerController.cid!, + ); + }, + ), + _overlayItem( + const Icon( + size: 20, + Icons.copy, + color: Colors.white, + ), + onTap: () { + _removeOverlay(); + Utils.copyText(item.content.text); + }, + ), + if (item.content.selfSend) + _overlayItem( + const Icon( + size: 20, + Icons.delete, + color: Colors.white, + ), + onTap: () { + _removeOverlay(); + HeaderControl.deleteDanmaku( + extra.id, + plPlayerController.cid!, + ); + }, + ) + else + _overlayItem( + const Icon( + size: 20, + Icons.report_problem_outlined, + color: Colors.white, + ), + onTap: () { + _removeOverlay(); + HeaderControl.reportDanmaku( + extra, + context, + plPlayerController, + ); + }, + ), + ], + ), + ), + ], + ), + ); + } + return const SizedBox.shrink(); + }), ], ); - if (!kDebugMode && !Utils.isMobile) { + if (!Utils.isMobile) { return Listener( behavior: HitTestBehavior.translucent, onPointerDown: onPointerDown, @@ -2066,20 +2169,13 @@ class _PLVideoPlayerState extends State static const overlayWidth = 130.0; static const overlayHeight = 35.0; - DanmakuItem? _suspendedDM; - OverlayEntry? _overlayEntry; - - @override - void deactivate() { - _removeOverlay(); - super.deactivate(); - } + final Rx<({Offset offset, DanmakuItem item})?> _suspendedDm = + Rx<({Offset offset, DanmakuItem item})?>(null); void _removeOverlay() { - _suspendedDM?.suspend = false; - _suspendedDM = null; - _overlayEntry?.remove(); - _overlayEntry = null; + _suspendedDm + ..value?.item.suspend = false + ..value = null; } Widget _overlayItem(Widget child, {required VoidCallback onTap}) { @@ -2103,111 +2199,18 @@ class _PLVideoPlayerState extends State ) { _removeOverlay(); item.suspend = true; - _suspendedDM = item; final dy = item.content.type == DanmakuItemType.bottom ? ctr.viewHeight - item.yPosition - item.height : item.yPosition; - final extra = item.content.extra as VideoDanmaku; - final theme = Theme.of(context); - - Overlay.of(context).insert( - _overlayEntry = OverlayEntry( - builder: (context) { - return Positioned( - top: dy + item.height + 4, - left: clampDouble( - event.globalPosition.dx - overlayWidth / 2, - overlaySpacing, - ctr.viewWidth - overlayWidth - overlaySpacing, - ), - child: Column( - children: [ - CustomPaint( - painter: _TrianglePainter( - theme.colorScheme.onSurface.withValues(alpha: 0.8), - ), - size: const Size(12, 6), - ), - Container( - width: overlayWidth, - height: overlayHeight, - decoration: BoxDecoration( - color: theme.colorScheme.onSurface.withValues(alpha: 0.8), - borderRadius: const BorderRadius.all(Radius.circular(18)), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - _overlayItem( - Icon( - size: 20, - extra.isLike - ? Icons.thumb_up_off_alt_sharp - : Icons.thumb_up_off_alt_outlined, - color: theme.colorScheme.surface, - ), - onTap: () { - _removeOverlay(); - HeaderControl.likeDanmaku( - extra, - plPlayerController.cid!, - ); - }, - ), - _overlayItem( - Icon( - size: 20, - Icons.copy, - color: theme.colorScheme.surface, - ), - onTap: () { - _removeOverlay(); - Utils.copyText(item.content.text); - }, - ), - if (item.content.selfSend) - _overlayItem( - Icon( - size: 20, - Icons.delete, - color: theme.colorScheme.surface, - ), - onTap: () { - _removeOverlay(); - HeaderControl.deleteDanmaku( - extra.id, - plPlayerController.cid!, - ); - }, - ) - else - _overlayItem( - Icon( - size: 20, - Icons.report_problem_outlined, - color: theme.colorScheme.surface, - ), - onTap: () { - _removeOverlay(); - HeaderControl.reportDanmaku( - extra, - context, - plPlayerController, - ); - }, - ), - ], - ), - ), - ], - ), - ); - }, - ), + final top = dy + item.height; + final left = clampDouble( + event.localPosition.dx - overlayWidth / 2, + overlaySpacing, + ctr.viewWidth - overlayWidth - overlaySpacing, ); + _suspendedDm.value = (offset: Offset(left, top), item: item); } } diff --git a/lib/utils/storage_key.dart b/lib/utils/storage_key.dart index 574a5f466..483d0d149 100644 --- a/lib/utils/storage_key.dart +++ b/lib/utils/storage_key.dart @@ -141,7 +141,8 @@ abstract class SettingBoxKey { showFsLockBtn = 'showFsLockBtn', silentDownImg = 'silentDownImg', showMemberShop = 'showMemberShop', - enablePlayAll = 'enablePlayAll'; + enablePlayAll = 'enablePlayAll', + enableTapDm = 'enableTapDm'; static const String minimizeOnExit = 'minimizeOnExit', windowSize = 'windowSize', diff --git a/lib/utils/storage_pref.dart b/lib/utils/storage_pref.dart index c7ba98656..dbf9f1e29 100644 --- a/lib/utils/storage_pref.dart +++ b/lib/utils/storage_pref.dart @@ -858,4 +858,7 @@ abstract class Pref { static bool get enablePlayAll => _setting.get(SettingBoxKey.enablePlayAll, defaultValue: true); + + static bool get enableTapDm => + _setting.get(SettingBoxKey.enableTapDm, defaultValue: true); } diff --git a/pubspec.lock b/pubspec.lock index 06d37a5bc..ac8cee393 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -223,7 +223,7 @@ packages: description: path: "." ref: main - resolved-ref: "2a56c72b1a9a7e06f4ec2d03bfa2d6cb4d5cee12" + resolved-ref: "454790117e05e96782b05ee3d28d0283741b3cde" url: "https://github.com/bggRGjQaUbCoE/canvas_danmaku.git" source: git version: "0.2.6" @@ -1166,7 +1166,7 @@ packages: description: path: media_kit_video ref: "version_1.2.5" - resolved-ref: "5ae9c2de261d673536e3dd4d4548adee2470f980" + resolved-ref: cd4837c13db556ed4e33b13fdddbb77199f167d8 url: "https://github.com/bggRGjQaUbCoE/media-kit.git" source: git version: "1.2.5"