From 38543ed8f22851b1641197b7fb313907b766801a Mon Sep 17 00:00:00 2001 From: orz12 Date: Thu, 4 Apr 2024 11:04:48 +0800 Subject: [PATCH] =?UTF-8?q?mod:=20=E5=90=8E=E5=8F=B0=E6=92=AD=E6=94=BE?= =?UTF-8?q?=E5=B1=9E=E6=80=A7=E7=A7=BB=E5=8A=A8=EF=BC=9Bpip=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=E5=BC=80=E5=90=AF=E5=90=8E=E5=8F=B0=E6=92=AD=E6=94=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/setting/play_setting.dart | 19 ++++-- .../video/detail/widgets/header_control.dart | 67 +++++++++++++++++++ lib/plugin/pl_player/controller.dart | 23 +++++-- lib/plugin/pl_player/view.dart | 7 +- 4 files changed, 101 insertions(+), 15 deletions(-) diff --git a/lib/pages/setting/play_setting.dart b/lib/pages/setting/play_setting.dart index af7fe7e8..e9cc19d9 100644 --- a/lib/pages/setting/play_setting.dart +++ b/lib/pages/setting/play_setting.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:hive/hive.dart'; import 'package:PiliPalaX/pages/setting/widgets/select_dialog.dart'; @@ -137,12 +138,18 @@ class _PlaySettingState extends State { defaultVal: false, ), if (Platform.isAndroid) - const SetSwitchItem( - title: '后台画中画', - subTitle: '进入后台时以小窗形式(PiP)播放', - setKey: SettingBoxKey.autoPiP, - defaultVal: false, - ), + SetSwitchItem( + title: '后台画中画', + subTitle: '进入后台时以小窗形式(PiP)播放,建议同时开启【后台播放】,避免没有暂停按钮', + setKey: SettingBoxKey.autoPiP, + defaultVal: false, + callFn: (val) { + if (val && + !setting.get(SettingBoxKey.enableBackgroundPlay, + defaultValue: false)) { + SmartDialog.showToast('建议开启后台播放'); + } + }), if (Platform.isAndroid) const SetSwitchItem( title: '画中画不加载弹幕', diff --git a/lib/pages/video/detail/widgets/header_control.dart b/lib/pages/video/detail/widgets/header_control.dart index e221d0af..493d26ae 100644 --- a/lib/pages/video/detail/widgets/header_control.dart +++ b/lib/pages/video/detail/widgets/header_control.dart @@ -20,6 +20,7 @@ import 'package:PiliPalaX/utils/storage.dart'; import 'package:PiliPalaX/http/danmaku.dart'; import 'package:PiliPalaX/services/shutdown_timer_service.dart'; import '../../../../models/video_detail_res.dart'; +import '../../../../services/service_locator.dart'; import '../introduction/index.dart'; import 'package:marquee/marquee.dart'; @@ -1244,6 +1245,72 @@ class _HeaderControlState extends State { await widget.floating!.isPipAvailable; widget.controller!.hiddenControls(false); if (canUsePiP) { + bool enableBackgroundPlay = setting.get( + SettingBoxKey.enableBackgroundPlay, + defaultValue: false); + if (!enableBackgroundPlay) { + // SmartDialog.showToast('建议开启【后台播放】功能\n避免画中画没有暂停按钮'); + // await Future.delayed(const Duration(seconds: 2), () { + // }); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Column(children: [ + const Row( + children: [ + Icon( + Icons.check, + color: Colors.green, + ), + SizedBox(width: 10), + Text('画中画', + style: + TextStyle(fontSize: 15, height: 1.5)) + ], + ), + const SizedBox(height: 10), + const Text( + '建议开启【后台播放】功能\n' + '避免画中画没有暂停按钮', + style: + TextStyle(fontSize: 12.5, height: 1.5)), + Row(children: [ + TextButton( + style: ButtonStyle( + foregroundColor: + MaterialStateProperty.resolveWith( + (states) { + return Theme.of(context) + .snackBarTheme + .actionTextColor; + }), + ), + onPressed: () async { + _.setBackgroundPlay(true); + SmartDialog.showToast("请重新载入本页面刷新"); + // Get.back(); + }, + child: const Text('启用后台播放(推荐)')), + const SizedBox(width: 10), + TextButton( + style: ButtonStyle( + foregroundColor: + MaterialStateProperty.resolveWith( + (states) { + return Theme.of(context) + .snackBarTheme + .actionTextColor; + }), + ), + onPressed: () {}, + child: const Text('不启用')) + ]) + ]), + duration: const Duration(seconds: 2), + showCloseIcon: true, + ), + ); + await Future.delayed(const Duration(seconds: 3), () {}); + } final Rational aspectRatio = Rational( widget.videoDetailCtr!.data.dash!.video!.first.width!, widget.videoDetailCtr!.data.dash!.video!.first.height!, diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index 8cced838..c1e8f959 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -85,6 +85,8 @@ class PlPlayerController { final Rx _videoFitDesc = Rx(videoFitType.first['desc']); late StreamSubscription _dataListenerForVideoFit; late StreamSubscription _dataListenerForEnterFullscreen; + /// 后台播放 + final Rx _backgroundPlay = false.obs; /// // ignore: prefer_final_fields @@ -153,7 +155,7 @@ class PlPlayerController { Stream get onMuteChanged => _mute.stream; // 视频字幕 - RxList> get vttSubtitles => _vttSubtitles; + RxList> get vttSubtitles => _vttSubtitles; RxInt get vttSubtitlesIndex => _vttSubtitlesIndex; /// [videoPlayerController] instance of Player @@ -202,6 +204,9 @@ class PlPlayerController { Rx get videoFit => _videoFit; Rx get videoFitDEsc => _videoFitDesc; + /// 后台播放 + Rx get backgroundPlay => _backgroundPlay; + /// 是否长按倍速 Rx get doubleSpeedStatus => _doubleSpeedStatus; @@ -296,6 +301,9 @@ class PlPlayerController { videoStorage.get(VideoBoxKey.playSpeedDefault, defaultValue: 1.0); enableAutoLongPressSpeed = setting .get(SettingBoxKey.enableAutoLongPressSpeed, defaultValue: false); + // 后台播放 + _backgroundPlay.value = + setting.get(SettingBoxKey.enableBackgroundPlay, defaultValue: false); if (!enableAutoLongPressSpeed) { _longPressSpeed.value = videoStorage .get(VideoBoxKey.longPressSpeedDefault, defaultValue: 3.0); @@ -387,7 +395,7 @@ class PlPlayerController { await _initializePlayer(seekTo: seekTo, duration: _duration.value); if (videoType.value != 'live' && _cid != 0) { refreshSubtitles().then((value) { - if (_vttSubtitles.isNotEmpty){ + if (_vttSubtitles.isNotEmpty) { String preference = setting.get(SettingBoxKey.subtitlePreference, defaultValue: SubtitlePreference.values.first.code); if (preference == 'on') { @@ -551,8 +559,8 @@ class PlPlayerController { } Future autoEnterFullscreen() async { - bool autoEnterFullscreen = - GStrorage.setting.get(SettingBoxKey.enableAutoEnter, defaultValue: false); + bool autoEnterFullscreen = GStrorage.setting + .get(SettingBoxKey.enableAutoEnter, defaultValue: false); if (autoEnterFullscreen) { Future.delayed(const Duration(milliseconds: 500), () { if (dataStatus.status.value != DataStatus.loaded) { @@ -961,6 +969,13 @@ class PlPlayerController { _videoFitDesc.value = videoFitType[fitValue]['desc']; } + /// 设置后台播放 + Future setBackgroundPlay(bool val) async { + _backgroundPlay.value = val; + setting.put(SettingBoxKey.enableBackgroundPlay, val); + videoPlayerServiceHandler.revalidateSetting(); + } + /// 读取亮度 // Future getVideoBrightness() async { // double brightnessValue = diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index 00ae76ed..9960e6c6 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -75,7 +75,6 @@ class _PLVideoPlayerState extends State late int defaultBtmProgressBehavior; late bool enableQuickDouble; late bool fullScreenGestureReverse; - late bool enableBackgroundPlay; // 用于记录上一次全屏切换手势触发时间,避免误触 DateTime? lastFullScreenToggleTime; @@ -136,8 +135,6 @@ class _PLVideoPlayerState extends State setting.get(SettingBoxKey.enableQuickDouble, defaultValue: true); fullScreenGestureReverse = setting .get(SettingBoxKey.fullScreenGestureReverse, defaultValue: false); - enableBackgroundPlay = - setting.get(SettingBoxKey.enableBackgroundPlay, defaultValue: false); Future.microtask(() async { try { FlutterVolumeController.updateShowSystemUI(true); @@ -223,10 +220,10 @@ class _PLVideoPlayerState extends State children: [ Obx( () => Video( - key: ValueKey(_.videoFit.value), + key: ValueKey('${_.videoFit.value}${_.backgroundPlay.value}'), controller: videoController, controls: NoVideoControls, - pauseUponEnteringBackgroundMode: !enableBackgroundPlay, + pauseUponEnteringBackgroundMode: !_.backgroundPlay.value, resumeUponEnteringForegroundMode: true, subtitleViewConfiguration: const SubtitleViewConfiguration( style: subTitleStyle,