diff --git a/lib/pages/video/detail/introduction/view.dart b/lib/pages/video/detail/introduction/view.dart index 1e9e83b8..4603e8d9 100644 --- a/lib/pages/video/detail/introduction/view.dart +++ b/lib/pages/video/detail/introduction/view.dart @@ -165,6 +165,9 @@ class _VideoInfoState extends State with TickerProviderStateMixin { Icons.shield_outlined, size: MediaQuery.textScalerOf(context).scale(16), + color: Theme.of(context) + .colorScheme + .onSecondaryContainer, ), Icon( Icons.play_arrow_rounded, diff --git a/lib/pages/video/detail/introduction/widgets/menu_row.dart b/lib/pages/video/detail/introduction/widgets/menu_row.dart index ad52daf9..de5a662b 100644 --- a/lib/pages/video/detail/introduction/widgets/menu_row.dart +++ b/lib/pages/video/detail/introduction/widgets/menu_row.dart @@ -99,20 +99,24 @@ class MenuRow extends StatelessWidget { class ActionRowLineItem extends StatelessWidget { const ActionRowLineItem({ super.key, - this.selectStatus, + required this.selectStatus, this.onTap, this.text, this.loadingStatus = false, + this.iconData, + this.icon, }); - final bool? selectStatus; + final bool selectStatus; final Function? onTap; final bool? loadingStatus; final String? text; + final IconData? iconData; + final Widget? icon; @override Widget build(BuildContext context) { return Material( - color: selectStatus! + color: selectStatus ? Theme.of(context).colorScheme.secondaryContainer : Colors.transparent, borderRadius: const BorderRadius.all(Radius.circular(30)), @@ -127,7 +131,7 @@ class ActionRowLineItem extends StatelessWidget { decoration: BoxDecoration( borderRadius: const BorderRadius.all(Radius.circular(30)), border: Border.all( - color: selectStatus! + color: selectStatus ? Colors.transparent : Theme.of(context).colorScheme.secondaryContainer, ), @@ -135,6 +139,16 @@ class ActionRowLineItem extends StatelessWidget { child: Row( mainAxisSize: MainAxisSize.min, children: [ + if (iconData != null) + Icon( + iconData, + size: 13, + color: selectStatus + ? Theme.of(context).colorScheme.onSecondaryContainer + : Theme.of(context).colorScheme.outline, + ) + else if (icon != null) + icon!, AnimatedOpacity( opacity: loadingStatus! ? 0 : 1, duration: const Duration(milliseconds: 200), @@ -142,7 +156,7 @@ class ActionRowLineItem extends StatelessWidget { text!, style: TextStyle( fontSize: 13, - color: selectStatus! + color: selectStatus ? Theme.of(context).colorScheme.onSecondaryContainer : Theme.of(context).colorScheme.outline), ), diff --git a/lib/pages/video/detail/widgets/header_control.dart b/lib/pages/video/detail/widgets/header_control.dart index 995babe5..079e845e 100644 --- a/lib/pages/video/detail/widgets/header_control.dart +++ b/lib/pages/video/detail/widgets/header_control.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:io'; import 'dart:math'; +import 'package:PiliPalaX/common/widgets/self_sized_horizontal_list.dart'; import 'package:PiliPalaX/pages/setting/widgets/switch_item.dart'; import 'package:PiliPalaX/utils/extension.dart'; import 'package:PiliPalaX/utils/id_utils.dart'; @@ -230,24 +231,71 @@ class _HeaderControlState extends State { } }, ), - ListTile( - dense: true, - onTap: () { - Get.back(); - Player? player = - widget.controller.videoPlayerController; - if (player == null) { - SmartDialog.showToast('播放器未初始化'); - return; - } - var pp = player.platform as NativePlayer; - pp.setProperty("video", "no"); + SelfSizedHorizontalList( + itemCount: 4, + gapSize: 10, + padding: const EdgeInsets.symmetric(horizontal: 16), + childBuilder: (index) { + return switch (index) { + 0 => Obx( + () => ActionRowLineItem( + iconData: Icons.flip, + onTap: () { + widget.controller.flipX.value = + !widget.controller.flipX.value; + }, + text: " 左右翻转 ", + selectStatus: widget.controller.flipX.value, + ), + ), + 1 => Obx( + () => ActionRowLineItem( + icon: Transform.rotate( + angle: pi / 2, + child: Icon( + Icons.flip, + size: 13, + color: widget.controller.flipY.value + ? Theme.of(context) + .colorScheme + .onSecondaryContainer + : Theme.of(context) + .colorScheme + .outline, + ), + ), + onTap: () { + widget.controller.flipY.value = + !widget.controller.flipY.value; + }, + text: " 上下翻转 ", + selectStatus: widget.controller.flipY.value, + ), + ), + 2 => Obx( + () => ActionRowLineItem( + iconData: Icons.headphones, + onTap: widget.controller.setOnlyPlayAudio, + text: " 听视频 ", + selectStatus: + widget.controller.onlyPlayAudio.value, + ), + ), + 3 => Obx( + () => ActionRowLineItem( + iconData: Icons.play_circle_outline, + onTap: widget + .controller.setContinuePlayInBackground, + text: " 后台播放 ", + selectStatus: widget.controller + .continuePlayInBackground.value, + ), + ), + int() => throw UnimplementedError(), + }; }, - leading: - const Icon(Icons.headphones_outlined, size: 20), - title: const Text('听视频(需返回首页才能终止该状态)', - style: titleStyle), ), + ListTile( dense: true, onTap: () => {Get.back(), showSetVideoQa()}, diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index a8896c36..e38b11bc 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -81,7 +81,13 @@ class PlPlayerController { late StreamSubscription _dataListenerForEnterFullscreen; /// 后台播放 - final Rx _continuePlayInBackground = false.obs; + late final Rx _continuePlayInBackground = false.obs; + + late final Rx _onlyPlayAudio = false.obs; + + late final Rx _flipX = false.obs; + + late final Rx _flipY = false.obs; /// final Rx _isSliderMoving = false.obs; @@ -212,6 +218,14 @@ class PlPlayerController { /// 后台播放 Rx get continuePlayInBackground => _continuePlayInBackground; + /// 听视频 + Rx get onlyPlayAudio => _onlyPlayAudio; + + /// 镜像 + Rx get flipX => _flipX; + + Rx get flipY => _flipY; + /// 是否长按倍速 Rx get doubleSpeedStatus => _doubleSpeedStatus; @@ -1429,4 +1443,16 @@ class PlPlayerController { _instance?._playerCount.value -= 1; } } + + void setContinuePlayInBackground() { + _continuePlayInBackground.value = !_continuePlayInBackground.value; + setting.put(SettingBoxKey.continuePlayInBackground, + _continuePlayInBackground.value); + } + + void setOnlyPlayAudio() { + _onlyPlayAudio.value = !_onlyPlayAudio.value; + videoPlayerController?.setVideoTrack( + _onlyPlayAudio.value ? VideoTrack.no() : VideoTrack.auto()); + } } diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index e7288b94..69599c9b 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -712,17 +712,21 @@ class _PLVideoPlayerState extends State _initialFocalPoint = Offset.zero; _gestureType = null; }, - child: Video( - key: plPlayerController.key, - controller: videoController, - controls: NoVideoControls, - pauseUponEnteringBackgroundMode: - !plPlayerController.continuePlayInBackground.value, - resumeUponEnteringForegroundMode: true, - // 字幕尺寸调节 - subtitleViewConfiguration: - plPlayerController.subtitleViewConfiguration, - fit: plPlayerController.videoFit.value, + child: Transform.flip( + flipX: plPlayerController.flipX.value, + flipY: plPlayerController.flipY.value, + child: Video( + key: plPlayerController.key, + controller: videoController, + controls: NoVideoControls, + pauseUponEnteringBackgroundMode: + !plPlayerController.continuePlayInBackground.value, + resumeUponEnteringForegroundMode: true, + // 字幕尺寸调节 + subtitleViewConfiguration: + plPlayerController.subtitleViewConfiguration, + fit: plPlayerController.videoFit.value, + ), ), ), ),