mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-26 12:07:11 +08:00
show fullscreen qa btn
Closes #1081 Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
enum AudioQuality {
|
||||
k64(30216, '64K'),
|
||||
k132(30232, '132K'),
|
||||
k192(30280, '192K'),
|
||||
hiRes(30251, 'Hi-Res无损'),
|
||||
dolby(30250, '杜比全景声'),
|
||||
hiRes(30251, 'Hi-Res无损');
|
||||
k192(30280, '192K'),
|
||||
k132(30232, '132K'),
|
||||
k64(30216, '64K');
|
||||
|
||||
final int code;
|
||||
final String desc;
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
enum VideoQuality {
|
||||
speed240(6, '240P 极速'),
|
||||
fluent360(16, '360P 流畅'),
|
||||
clear480(32, '480P 清晰'),
|
||||
high720(64, '720P 高清'),
|
||||
high72060(74, '720P60 高帧率'),
|
||||
high1080(80, '1080P 高清'),
|
||||
high1080plus(112, '1080P+ 高码率'),
|
||||
high108060(116, '1080P60 高帧率'),
|
||||
super4K(120, '4K 超清'),
|
||||
hdr(125, 'HDR 真彩色'),
|
||||
dolbyVision(126, '杜比视界'),
|
||||
super8k(127, '8K 超高清');
|
||||
super8k(127, '8K 超高清', '8K'),
|
||||
dolbyVision(126, '杜比视界', '杜比'),
|
||||
hdr(125, 'HDR 真彩色', 'HDR'),
|
||||
super4K(120, '4K 超清', '4K'),
|
||||
high108060(116, '1080P60 高帧率', '1080P60'),
|
||||
high1080plus(112, '1080P+ 高码率', '1080P+'),
|
||||
high1080(80, '1080P 高清', '1080P'),
|
||||
high72060(74, '720P60 高帧率', '720P60'),
|
||||
high720(64, '720P 高清', '720P'),
|
||||
clear480(32, '480P 清晰', '480P'),
|
||||
fluent360(16, '360P 流畅', '360P'),
|
||||
speed240(6, '240P 极速', '240P');
|
||||
|
||||
final int code;
|
||||
final String desc;
|
||||
final String shortDesc;
|
||||
|
||||
const VideoQuality(this.code, this.desc);
|
||||
const VideoQuality(this.code, this.desc, this.shortDesc);
|
||||
|
||||
static final _codeMap = {for (var i in values) i.code: i};
|
||||
|
||||
|
||||
@@ -107,9 +107,7 @@ List<SettingsModel> get videoSettings => [
|
||||
return SelectDialog<int>(
|
||||
title: '默认画质',
|
||||
value: Pref.defaultVideoQa,
|
||||
values: VideoQuality.values.reversed
|
||||
.map((e) => (e.code, e.desc))
|
||||
.toList(),
|
||||
values: VideoQuality.values.map((e) => (e.code, e.desc)).toList(),
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -132,9 +130,7 @@ List<SettingsModel> get videoSettings => [
|
||||
return SelectDialog<int>(
|
||||
title: '蜂窝网络画质',
|
||||
value: Pref.defaultVideoQaCellular,
|
||||
values: VideoQuality.values.reversed
|
||||
.map((e) => (e.code, e.desc))
|
||||
.toList(),
|
||||
values: VideoQuality.values.map((e) => (e.code, e.desc)).toList(),
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -160,9 +156,7 @@ List<SettingsModel> get videoSettings => [
|
||||
return SelectDialog<int>(
|
||||
title: '默认音质',
|
||||
value: Pref.defaultAudioQa,
|
||||
values: AudioQuality.values.reversed
|
||||
.map((e) => (e.code, e.desc))
|
||||
.toList(),
|
||||
values: AudioQuality.values.map((e) => (e.code, e.desc)).toList(),
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -185,9 +179,7 @@ List<SettingsModel> get videoSettings => [
|
||||
return SelectDialog<int>(
|
||||
title: '蜂窝网络音质',
|
||||
value: Pref.defaultAudioQaCellular,
|
||||
values: AudioQuality.values.reversed
|
||||
.map((e) => (e.code, e.desc))
|
||||
.toList(),
|
||||
values: AudioQuality.values.map((e) => (e.code, e.desc)).toList(),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -98,7 +98,7 @@ class VideoDetailController extends GetxController
|
||||
final Rx<LoadingState> videoState = LoadingState.loading().obs;
|
||||
|
||||
/// 播放器配置 画质 音质 解码格式
|
||||
late VideoQuality currentVideoQa;
|
||||
late Rx<VideoQuality> currentVideoQa;
|
||||
AudioQuality? currentAudioQa;
|
||||
late VideoDecodeFormatType currentDecodeFormats;
|
||||
// 是否开始自动播放 存在多p的情况下,第二p需要为true
|
||||
@@ -1004,7 +1004,7 @@ class VideoDetailController extends GetxController
|
||||
|
||||
/// 根据currentVideoQa和currentDecodeFormats 重新设置videoUrl
|
||||
List<VideoItem> videoList = data.dash!.video!
|
||||
.where((i) => i.id == currentVideoQa.code)
|
||||
.where((i) => i.id == currentVideoQa.value.code)
|
||||
.toList();
|
||||
|
||||
final List<String> supportDecodeFormats = videoList
|
||||
@@ -1036,7 +1036,7 @@ class VideoDetailController extends GetxController
|
||||
orElse: () => videoList.first,
|
||||
);
|
||||
} else {
|
||||
if (currentVideoQa == VideoQuality.dolbyVision) {
|
||||
if (currentVideoQa.value == VideoQuality.dolbyVision) {
|
||||
currentDecodeFormats = VideoDecodeFormatTypeExt.fromString(
|
||||
videoList.first.codecs!,
|
||||
)!;
|
||||
@@ -1203,7 +1203,7 @@ class VideoDetailController extends GetxController
|
||||
);
|
||||
setVideoHeight();
|
||||
currentDecodeFormats = VideoDecodeFormatTypeExt.fromString('avc1')!;
|
||||
currentVideoQa = VideoQuality.fromCode(data.quality!);
|
||||
currentVideoQa = Rx(VideoQuality.fromCode(data.quality!));
|
||||
if (autoPlay.value || plPlayerController.preInitPlayer) {
|
||||
await playerInit();
|
||||
}
|
||||
@@ -1236,7 +1236,7 @@ class VideoDetailController extends GetxController
|
||||
numbers,
|
||||
);
|
||||
}
|
||||
currentVideoQa = VideoQuality.fromCode(resVideoQa);
|
||||
currentVideoQa = Rx(VideoQuality.fromCode(resVideoQa));
|
||||
|
||||
/// 取出符合当前画质的videoList
|
||||
final List<VideoItem> videosList = allVideosList
|
||||
|
||||
@@ -740,17 +740,9 @@ class ReplyItemGrpc extends StatelessWidget {
|
||||
final ctr = Get.find<VideoDetailController>(
|
||||
tag: getTag?.call() ?? Get.arguments['heroTag'],
|
||||
);
|
||||
int duration = ctr.data.timeLength!;
|
||||
List<int> split = matchStr
|
||||
.split(':')
|
||||
.reversed
|
||||
.map((item) => int.parse(item))
|
||||
.toList();
|
||||
int seek = 0;
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
seek += split[i] * pow(60, i).toInt();
|
||||
}
|
||||
isValid = seek * 1000 <= duration;
|
||||
isValid =
|
||||
ctr.data.timeLength! * 1000 <=
|
||||
DurationUtil.parseDuration(matchStr);
|
||||
} catch (e) {
|
||||
if (kDebugMode) debugPrint('failed to validate: $e');
|
||||
}
|
||||
|
||||
@@ -361,7 +361,7 @@ class HeaderControlState extends TripleState<HeaderControl> {
|
||||
leading: const Icon(Icons.play_circle_outline, size: 20),
|
||||
title: const Text('选择画质', style: titleStyle),
|
||||
subtitle: Text(
|
||||
'当前画质 ${videoDetailCtr.currentVideoQa.desc}',
|
||||
'当前画质 ${videoDetailCtr.currentVideoQa.value.desc}',
|
||||
style: subTitleStyle,
|
||||
),
|
||||
),
|
||||
@@ -604,7 +604,7 @@ class HeaderControlState extends TripleState<HeaderControl> {
|
||||
return;
|
||||
}
|
||||
final List<FormatItem> videoFormat = videoInfo.supportFormats!;
|
||||
final VideoQuality currentVideoQa = videoDetailCtr.currentVideoQa;
|
||||
final VideoQuality currentVideoQa = videoDetailCtr.currentVideoQa.value;
|
||||
|
||||
/// 总质量分类
|
||||
final int totalQaSam = videoFormat.length;
|
||||
@@ -663,10 +663,13 @@ class HeaderControlState extends TripleState<HeaderControl> {
|
||||
}
|
||||
Get.back();
|
||||
final int quality = item.quality!;
|
||||
final newQa = VideoQuality.fromCode(quality);
|
||||
videoDetailCtr
|
||||
..currentVideoQa = VideoQuality.fromCode(quality)
|
||||
..currentVideoQa.value = newQa
|
||||
..updatePlayer();
|
||||
|
||||
SmartDialog.showToast("画质已变为:${newQa.desc}");
|
||||
|
||||
// update
|
||||
if (!plPlayerController.tempPlayerConf) {
|
||||
final res = await Connectivity().checkConnectivity();
|
||||
@@ -682,9 +685,6 @@ class HeaderControlState extends TripleState<HeaderControl> {
|
||||
);
|
||||
}
|
||||
}
|
||||
SmartDialog.showToast(
|
||||
"画质已变为:${VideoQuality.fromCode(quality).desc}",
|
||||
);
|
||||
},
|
||||
// 可能包含会员解锁画质
|
||||
enabled: index >= totalQaSam - userfulQaSam,
|
||||
@@ -740,10 +740,13 @@ class HeaderControlState extends TripleState<HeaderControl> {
|
||||
}
|
||||
Get.back();
|
||||
final int quality = i.id!;
|
||||
final newQa = AudioQuality.fromCode(quality);
|
||||
videoDetailCtr
|
||||
..currentAudioQa = AudioQuality.fromCode(quality)
|
||||
..currentAudioQa = newQa
|
||||
..updatePlayer();
|
||||
|
||||
SmartDialog.showToast("音质已变为:${newQa.desc}");
|
||||
|
||||
// update
|
||||
if (!plPlayerController.tempPlayerConf) {
|
||||
final res = await Connectivity().checkConnectivity();
|
||||
@@ -759,9 +762,6 @@ class HeaderControlState extends TripleState<HeaderControl> {
|
||||
);
|
||||
}
|
||||
}
|
||||
SmartDialog.showToast(
|
||||
"音质已变为:${AudioQuality.fromCode(quality).desc}",
|
||||
);
|
||||
},
|
||||
contentPadding: const EdgeInsets.only(left: 20, right: 20),
|
||||
title: Text(i.quality),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
enum BottomControlType {
|
||||
pre,
|
||||
playOrPause,
|
||||
pre,
|
||||
next,
|
||||
time,
|
||||
episode,
|
||||
@@ -11,4 +11,5 @@ enum BottomControlType {
|
||||
viewPoints,
|
||||
superResolution,
|
||||
dmChart,
|
||||
qa,
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ import 'package:PiliPlus/common/widgets/progress_bar/segment_progress_bar.dart';
|
||||
import 'package:PiliPlus/common/widgets/view_safe_area.dart';
|
||||
import 'package:PiliPlus/http/init.dart';
|
||||
import 'package:PiliPlus/models/common/super_resolution_type.dart';
|
||||
import 'package:PiliPlus/models/common/video/video_quality.dart';
|
||||
import 'package:PiliPlus/models/video/play/url.dart';
|
||||
import 'package:PiliPlus/models_new/video/video_detail/episode.dart';
|
||||
import 'package:PiliPlus/models_new/video/video_detail/section.dart';
|
||||
import 'package:PiliPlus/models_new/video/video_shot/data.dart';
|
||||
@@ -31,6 +33,9 @@ import 'package:PiliPlus/plugin/pl_player/widgets/forward_seek.dart';
|
||||
import 'package:PiliPlus/plugin/pl_player/widgets/play_pause_btn.dart';
|
||||
import 'package:PiliPlus/utils/duration_util.dart';
|
||||
import 'package:PiliPlus/utils/id_utils.dart';
|
||||
import 'package:PiliPlus/utils/storage.dart';
|
||||
import 'package:PiliPlus/utils/storage_key.dart';
|
||||
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:easy_debounce/easy_throttle.dart';
|
||||
import 'package:fl_chart/fl_chart.dart';
|
||||
@@ -400,7 +405,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
.toList();
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Text(
|
||||
plPlayerController.superResolutionType.value.title,
|
||||
style: const TextStyle(color: Colors.white, fontSize: 13),
|
||||
@@ -508,7 +513,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
.toList();
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Text(
|
||||
plPlayerController.videoFit.value.desc,
|
||||
style: const TextStyle(color: Colors.white, fontSize: 13),
|
||||
@@ -595,7 +600,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
.toList();
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Text(
|
||||
"${plPlayerController.playbackSpeed}X",
|
||||
style: const TextStyle(color: Colors.white, fontSize: 13),
|
||||
@@ -605,6 +610,88 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
),
|
||||
),
|
||||
|
||||
BottomControlType.qa => Obx(
|
||||
() {
|
||||
final videoDetailCtr = widget.videoDetailController!;
|
||||
final VideoQuality currentVideoQa =
|
||||
videoDetailCtr.currentVideoQa.value;
|
||||
final PlayUrlModel videoInfo = videoDetailCtr.data;
|
||||
final List<FormatItem> videoFormat = videoInfo.supportFormats!;
|
||||
final int totalQaSam = videoFormat.length;
|
||||
int userfulQaSam = 0;
|
||||
final List<VideoItem> video = videoInfo.dash!.video!;
|
||||
final Set<int> idSet = {};
|
||||
for (final VideoItem item in video) {
|
||||
final int id = item.id!;
|
||||
if (!idSet.contains(id)) {
|
||||
idSet.add(id);
|
||||
userfulQaSam++;
|
||||
}
|
||||
}
|
||||
return PopupMenuButton<int>(
|
||||
requestFocus: false,
|
||||
initialValue: currentVideoQa.code,
|
||||
color: Colors.black.withValues(alpha: 0.8),
|
||||
itemBuilder: (context) {
|
||||
return List.generate(
|
||||
totalQaSam,
|
||||
(index) {
|
||||
final item = videoFormat[index];
|
||||
final enabled = index >= totalQaSam - userfulQaSam;
|
||||
return PopupMenuItem<int>(
|
||||
enabled: enabled,
|
||||
height: 35,
|
||||
padding: const EdgeInsets.only(left: 20),
|
||||
value: item.quality,
|
||||
onTap: () async {
|
||||
if (currentVideoQa.code == item.quality) {
|
||||
return;
|
||||
}
|
||||
final int quality = item.quality!;
|
||||
final newQa = VideoQuality.fromCode(quality);
|
||||
videoDetailCtr
|
||||
..currentVideoQa.value = newQa
|
||||
..updatePlayer();
|
||||
|
||||
SmartDialog.showToast("画质已变为:${newQa.desc}");
|
||||
|
||||
// update
|
||||
if (!plPlayerController.tempPlayerConf) {
|
||||
final res = await Connectivity().checkConnectivity();
|
||||
if (res.contains(ConnectivityResult.wifi)) {
|
||||
GStorage.setting.put(
|
||||
SettingBoxKey.defaultVideoQa,
|
||||
quality,
|
||||
);
|
||||
} else {
|
||||
GStorage.setting.put(
|
||||
SettingBoxKey.defaultVideoQaCellular,
|
||||
quality,
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
item.newDesc ?? '',
|
||||
style: enabled
|
||||
? const TextStyle(color: Colors.white, fontSize: 13)
|
||||
: null,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Text(
|
||||
currentVideoQa.shortDesc,
|
||||
style: const TextStyle(color: Colors.white, fontSize: 13),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
/// 全屏
|
||||
BottomControlType.fullscreen => ComBtn(
|
||||
width: widgetWidth,
|
||||
@@ -644,6 +731,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
if (isFullScreen) BottomControlType.fit,
|
||||
BottomControlType.subtitle,
|
||||
BottomControlType.speed,
|
||||
if (isFullScreen) BottomControlType.qa,
|
||||
BottomControlType.fullscreen,
|
||||
];
|
||||
|
||||
|
||||
@@ -372,9 +372,9 @@ class PageUtils {
|
||||
EnableManual(
|
||||
aspectRatio: aspectRatio.fitsInAndroidRequirements
|
||||
? aspectRatio
|
||||
: width > height
|
||||
? const Rational.landscape()
|
||||
: const Rational.vertical(),
|
||||
: height > width
|
||||
? const Rational.vertical()
|
||||
: const Rational.landscape(),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
|
||||
@@ -198,7 +198,7 @@ class Pref {
|
||||
|
||||
static int get defaultVideoQa => _setting.get(
|
||||
SettingBoxKey.defaultVideoQa,
|
||||
defaultValue: VideoQuality.values.last.code,
|
||||
defaultValue: VideoQuality.super8k.code,
|
||||
);
|
||||
|
||||
static int get defaultVideoQaCellular => _setting.get(
|
||||
@@ -208,7 +208,7 @@ class Pref {
|
||||
|
||||
static int get defaultAudioQa => _setting.get(
|
||||
SettingBoxKey.defaultAudioQa,
|
||||
defaultValue: AudioQuality.values.last.code,
|
||||
defaultValue: AudioQuality.hiRes.code,
|
||||
);
|
||||
|
||||
static int get defaultAudioQaCellular => _setting.get(
|
||||
|
||||
Reference in New Issue
Block a user