mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-04-20 03:06:59 +08:00
feat: pgc skip
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -229,11 +229,13 @@ class VideoHttp {
|
||||
switch (videoType) {
|
||||
case VideoType.ugc:
|
||||
data = PlayUrlModel.fromJson(res.data['data']);
|
||||
|
||||
case VideoType.pugv:
|
||||
var result = res.data['data'];
|
||||
data = PlayUrlModel.fromJson(result)
|
||||
..lastPlayTime =
|
||||
result?['play_view_business_info']?['user_status']?['watch_progress']?['current_watch_progress'];
|
||||
|
||||
case VideoType.pgc:
|
||||
var result = res.data['result'];
|
||||
data = PlayUrlModel.fromJson(result['video_info'])
|
||||
|
||||
@@ -10,11 +10,10 @@ class SegmentModel {
|
||||
required this.segmentType,
|
||||
required this.segment,
|
||||
required this.skipType,
|
||||
this.hasSkipped = false,
|
||||
});
|
||||
String UUID;
|
||||
SegmentType segmentType;
|
||||
Pair<int, int> segment;
|
||||
SkipType skipType;
|
||||
bool hasSkipped;
|
||||
late bool hasSkipped = false;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'dart:math' show max, min;
|
||||
|
||||
import 'package:PiliPlus/models/common/video/audio_quality.dart';
|
||||
import 'package:PiliPlus/models/common/video/video_quality.dart';
|
||||
import 'package:PiliPlus/models_new/sponsor_block/segment_item.dart';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
|
||||
class PlayUrlModel {
|
||||
@@ -44,6 +45,7 @@ class PlayUrlModel {
|
||||
int? lastPlayCid;
|
||||
String? curLanguage;
|
||||
Language? language;
|
||||
List<SegmentItemModel>? clipInfoList;
|
||||
|
||||
PlayUrlModel.fromJson(Map<String, dynamic> json) {
|
||||
from = json['from'];
|
||||
@@ -72,6 +74,25 @@ class PlayUrlModel {
|
||||
language = json['language'] == null
|
||||
? null
|
||||
: Language.fromJson(json['language']);
|
||||
// debug
|
||||
// final clipInfoList = [
|
||||
// {
|
||||
// "start": 0,
|
||||
// "end": 150,
|
||||
// "clipType": "CLIP_TYPE_OP",
|
||||
// },
|
||||
// {
|
||||
// "start": timeLength! ~/ 1000 - 150,
|
||||
// "end": timeLength! ~/ 1000,
|
||||
// "clipType": "CLIP_TYPE_ED",
|
||||
// },
|
||||
// ];
|
||||
final List? clipInfoList = json['clip_info_list'];
|
||||
if (clipInfoList != null && clipInfoList.isNotEmpty) {
|
||||
this.clipInfoList = clipInfoList
|
||||
.map((e) => SegmentItemModel.fromPgcJson(e, timeLength))
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'package:PiliPlus/models/common/sponsor_block/segment_type.dart';
|
||||
|
||||
class SegmentItemModel {
|
||||
String? cid;
|
||||
String category;
|
||||
@@ -28,4 +30,21 @@ class SegmentItemModel {
|
||||
? null
|
||||
: (json["videoDuration"] as num) * 1000,
|
||||
);
|
||||
|
||||
factory SegmentItemModel.fromPgcJson(
|
||||
Map<String, dynamic> json,
|
||||
num? videoDuration,
|
||||
) => SegmentItemModel(
|
||||
category: switch (json['clipType']) {
|
||||
'CLIP_TYPE_OP' => SegmentType.intro.name,
|
||||
'CLIP_TYPE_ED' => SegmentType.outro.name,
|
||||
_ => SegmentType.sponsor.name,
|
||||
},
|
||||
segment: [
|
||||
((json['start'] as num) * 1000).round(),
|
||||
((json['end'] as num) * 1000).round(),
|
||||
],
|
||||
uuid: '',
|
||||
videoDuration: videoDuration,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import 'package:PiliPlus/models/common/dynamic/dynamics_type.dart';
|
||||
import 'package:PiliPlus/models/common/member/tab_type.dart';
|
||||
import 'package:PiliPlus/models/common/reply/reply_sort_type.dart';
|
||||
import 'package:PiliPlus/models/common/settings_type.dart';
|
||||
import 'package:PiliPlus/models/common/sponsor_block/skip_type.dart';
|
||||
import 'package:PiliPlus/models/common/super_resolution_type.dart';
|
||||
import 'package:PiliPlus/models/dynamics/result.dart';
|
||||
import 'package:PiliPlus/pages/common/slide/common_slide_page.dart';
|
||||
@@ -71,6 +72,54 @@ List<SettingsModel> get extraSettings => [
|
||||
],
|
||||
),
|
||||
),
|
||||
SettingsModel(
|
||||
settingsType: SettingsType.normal,
|
||||
leading: const Icon(MdiIcons.debugStepOver),
|
||||
title: '番剧片头/片尾跳过类型',
|
||||
getTrailing: () => Builder(
|
||||
builder: (context) {
|
||||
final pgcSkipType = Pref.pgcSkipType;
|
||||
final colorScheme = ColorScheme.of(context);
|
||||
final color = pgcSkipType == SkipType.disable
|
||||
? colorScheme.outline
|
||||
: colorScheme.secondary;
|
||||
return PopupMenuButton<SkipType>(
|
||||
initialValue: pgcSkipType,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
pgcSkipType.title,
|
||||
style: TextStyle(fontSize: 14, height: 1, color: color),
|
||||
strutStyle: const StrutStyle(
|
||||
leading: 0,
|
||||
height: 1,
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
Icon(
|
||||
MdiIcons.unfoldMoreHorizontal,
|
||||
size: MediaQuery.textScalerOf(context).scale(14),
|
||||
color: color,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
onSelected: (value) async {
|
||||
await GStorage.setting.put(SettingBoxKey.pgcSkipType, value.index);
|
||||
if (context.mounted) {
|
||||
(context as Element).markNeedsBuild();
|
||||
}
|
||||
},
|
||||
itemBuilder: (context) => SkipType.values
|
||||
.map((e) => PopupMenuItem(value: e, child: Text(e.title)))
|
||||
.toList(),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
SettingsModel(
|
||||
settingsType: SettingsType.sw1tch,
|
||||
title: '检查未读动态',
|
||||
@@ -185,6 +234,14 @@ List<SettingsModel> get extraSettings => [
|
||||
setKey: SettingBoxKey.horizontalMemberPage,
|
||||
defaultVal: false,
|
||||
),
|
||||
SettingsModel(
|
||||
settingsType: SettingsType.sw1tch,
|
||||
title: '横屏在侧栏打开图片预览',
|
||||
leading: const Icon(Icons.photo_outlined),
|
||||
setKey: SettingBoxKey.horizontalPreview,
|
||||
defaultVal: false,
|
||||
onChanged: (value) => CustomGridView.horizontalPreview = value,
|
||||
),
|
||||
SettingsModel(
|
||||
settingsType: SettingsType.normal,
|
||||
title: '评论折叠行数',
|
||||
@@ -331,14 +388,6 @@ List<SettingsModel> get extraSettings => [
|
||||
setKey: SettingBoxKey.continuePlayingPart,
|
||||
defaultVal: true,
|
||||
),
|
||||
SettingsModel(
|
||||
settingsType: SettingsType.sw1tch,
|
||||
title: '横屏在侧栏打开图片预览',
|
||||
leading: const Icon(Icons.photo_outlined),
|
||||
setKey: SettingBoxKey.horizontalPreview,
|
||||
defaultVal: false,
|
||||
onChanged: (value) => CustomGridView.horizontalPreview = value,
|
||||
),
|
||||
getBanwordModel(
|
||||
context: Get.context!,
|
||||
title: '评论关键词过滤',
|
||||
|
||||
@@ -142,6 +142,7 @@ class _AiDetailState extends State<AiConclusionPanel>
|
||||
tag: Get.arguments['heroTag'],
|
||||
).plPlayerController.seekTo(
|
||||
Duration(seconds: item.timestamp!),
|
||||
isSeek: false,
|
||||
);
|
||||
} catch (_) {}
|
||||
},
|
||||
|
||||
@@ -586,7 +586,7 @@ class VideoDetailController extends GetxController
|
||||
(item) => ListTile(
|
||||
onTap: () {
|
||||
Get.back();
|
||||
_showVoteDialog(context, item);
|
||||
if (isUgc) _showVoteDialog(context, item);
|
||||
},
|
||||
dense: true,
|
||||
title: Text.rich(
|
||||
@@ -635,7 +635,8 @@ class VideoDetailController extends GetxController
|
||||
Get.back();
|
||||
onSkip(
|
||||
item,
|
||||
item.skipType != SkipType.showOnly,
|
||||
isSkip: item.skipType != SkipType.showOnly,
|
||||
isSeek: false,
|
||||
);
|
||||
},
|
||||
style: IconButton.styleFrom(
|
||||
@@ -677,6 +678,7 @@ class VideoDetailController extends GetxController
|
||||
|
||||
Future<void> _querySponsorBlock() async {
|
||||
positionSubscription?.cancel();
|
||||
positionSubscription = null;
|
||||
videoLabel.value = '';
|
||||
segmentList.clear();
|
||||
segmentProgressList.clear();
|
||||
@@ -695,9 +697,10 @@ class VideoDetailController extends GetxController
|
||||
}
|
||||
}
|
||||
|
||||
void handleSBData(List<SegmentItemModel> list) {
|
||||
Future<void> handleSBData(List<SegmentItemModel> list) async {
|
||||
if (list.isNotEmpty) {
|
||||
try {
|
||||
Completer? completer;
|
||||
final duration = list.first.videoDuration ?? data.timeLength!;
|
||||
// segmentList
|
||||
segmentList.addAll(
|
||||
@@ -714,15 +717,20 @@ class VideoDetailController extends GetxController
|
||||
videoLabel.value +=
|
||||
'${videoLabel.value.isNotEmpty ? '/' : ''}${segmentType.title}';
|
||||
}
|
||||
var skipType = plPlayerController
|
||||
.blockSettings[segmentType.index]
|
||||
.second;
|
||||
if (skipType != SkipType.showOnly) {
|
||||
if (item.segment[1] == item.segment[0] ||
|
||||
item.segment[1] - item.segment[0] <
|
||||
plPlayerController.blockLimit) {
|
||||
skipType = SkipType.showOnly;
|
||||
SkipType skipType;
|
||||
if (isUgc) {
|
||||
skipType = plPlayerController
|
||||
.blockSettings[segmentType.index]
|
||||
.second;
|
||||
if (skipType != SkipType.showOnly) {
|
||||
if (item.segment[1] == item.segment[0] ||
|
||||
item.segment[1] - item.segment[0] <
|
||||
plPlayerController.blockLimit) {
|
||||
skipType = SkipType.showOnly;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
skipType = Pref.pgcSkipType;
|
||||
}
|
||||
|
||||
final segmentModel = SegmentModel(
|
||||
@@ -739,32 +747,44 @@ class VideoDetailController extends GetxController
|
||||
autoPlay.value &&
|
||||
plPlayerController.videoPlayerController != null) {
|
||||
final currPost =
|
||||
defaultST?.inMilliseconds ??
|
||||
plPlayerController.position.value.inMilliseconds;
|
||||
|
||||
if (currPost >= segmentModel.segment.first &&
|
||||
currPost < segmentModel.segment.second) {
|
||||
_lastPos = currPost;
|
||||
if (segmentModel.skipType == SkipType.alwaysSkip) {
|
||||
plPlayerController
|
||||
.videoPlayerController!
|
||||
.stream
|
||||
.buffer
|
||||
.first
|
||||
.whenComplete(() {
|
||||
onSkip(segmentModel);
|
||||
|
||||
switch (segmentModel.skipType) {
|
||||
case SkipType.alwaysSkip:
|
||||
case SkipType.skipOnce:
|
||||
segmentModel.hasSkipped = true;
|
||||
completer = Completer();
|
||||
final videoPlayerController =
|
||||
plPlayerController.videoPlayerController!;
|
||||
if (videoPlayerController.state.playing) {
|
||||
onSkip(
|
||||
segmentModel,
|
||||
).whenComplete(completer!.complete);
|
||||
} else {
|
||||
videoPlayerController.stream.playing.firstWhere((
|
||||
e,
|
||||
) {
|
||||
if (e) {
|
||||
onSkip(
|
||||
segmentModel,
|
||||
).whenComplete(completer!.complete);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
} else if (segmentModel.skipType == SkipType.skipOnce) {
|
||||
segmentModel.hasSkipped = true;
|
||||
plPlayerController
|
||||
.videoPlayerController!
|
||||
.stream
|
||||
.buffer
|
||||
.first
|
||||
.whenComplete(() {
|
||||
onSkip(segmentModel);
|
||||
});
|
||||
} else if (segmentModel.skipType ==
|
||||
SkipType.skipManually) {
|
||||
onAddItem(segmentModel);
|
||||
}
|
||||
|
||||
break;
|
||||
case SkipType.skipManually:
|
||||
onAddItem(segmentModel);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -785,6 +805,7 @@ class VideoDetailController extends GetxController
|
||||
|
||||
if (positionSubscription == null &&
|
||||
(autoPlay.value || plPlayerController.preInitPlayer)) {
|
||||
await completer?.future;
|
||||
initSkip();
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -815,14 +836,21 @@ class VideoDetailController extends GetxController
|
||||
// }
|
||||
if (msPos <= item.segment.first &&
|
||||
item.segment.first <= msPos + 1000) {
|
||||
if (item.skipType == SkipType.alwaysSkip) {
|
||||
onSkip(item);
|
||||
} else if (item.skipType == SkipType.skipOnce &&
|
||||
!item.hasSkipped) {
|
||||
item.hasSkipped = true;
|
||||
onSkip(item);
|
||||
} else if (item.skipType == SkipType.skipManually) {
|
||||
onAddItem(item);
|
||||
switch (item.skipType) {
|
||||
case SkipType.alwaysSkip:
|
||||
onSkip(item, isSeek: false);
|
||||
break;
|
||||
case SkipType.skipOnce:
|
||||
if (!item.hasSkipped) {
|
||||
item.hasSkipped = true;
|
||||
onSkip(item, isSeek: false);
|
||||
}
|
||||
break;
|
||||
case SkipType.skipManually:
|
||||
onAddItem(item);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -909,7 +937,7 @@ class VideoDetailController extends GetxController
|
||||
}
|
||||
onRemoveItem(listData.indexOf(item), item);
|
||||
} else if (item is SegmentModel) {
|
||||
onSkip(item);
|
||||
onSkip(item, isSeek: false);
|
||||
onRemoveItem(listData.indexOf(item), item);
|
||||
}
|
||||
},
|
||||
@@ -920,17 +948,21 @@ class VideoDetailController extends GetxController
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> onSkip(SegmentModel item, [bool isSkip = true]) async {
|
||||
Future<void> onSkip(
|
||||
SegmentModel item, {
|
||||
bool isSkip = true,
|
||||
bool isSeek = true,
|
||||
}) async {
|
||||
try {
|
||||
plPlayerController.danmakuController?.clear();
|
||||
await plPlayerController.videoPlayerController?.seek(
|
||||
await plPlayerController.seekTo(
|
||||
Duration(milliseconds: item.segment.second),
|
||||
isSeek: isSeek,
|
||||
);
|
||||
if (isSkip) {
|
||||
if (Pref.blockToast) {
|
||||
_showBlockToast('已跳过${item.segmentType.shortTitle}片段');
|
||||
}
|
||||
if (Pref.blockTrack) {
|
||||
if (isUgc && Pref.blockTrack) {
|
||||
Request().post(
|
||||
'$blockServer/api/viewedVideoSponsorTime',
|
||||
queryParameters: {'UUID': item.UUID},
|
||||
@@ -1031,9 +1063,10 @@ class VideoDetailController extends GetxController
|
||||
void updatePlayer() {
|
||||
autoPlay.value = true;
|
||||
playedTime = plPlayerController.position.value;
|
||||
plPlayerController.removeListeners();
|
||||
plPlayerController.isBuffering.value = false;
|
||||
plPlayerController.buffered.value = Duration.zero;
|
||||
plPlayerController
|
||||
..removeListeners()
|
||||
..isBuffering.value = false
|
||||
..buffered.value = Duration.zero;
|
||||
|
||||
final video = findVideoByQa(currentVideoQa.value.code);
|
||||
if (firstVideo.codecs != video.codecs) {
|
||||
@@ -1142,7 +1175,9 @@ class VideoDetailController extends GetxController
|
||||
return;
|
||||
}
|
||||
isQuerying = true;
|
||||
if (plPlayerController.enableSponsorBlock && !fromReset) {
|
||||
if (plPlayerController.enableSponsorBlock &&
|
||||
(isUgc || !plPlayerController.enablePgcSkip) &&
|
||||
!fromReset) {
|
||||
_querySponsorBlock();
|
||||
}
|
||||
if (plPlayerController.cacheVideoQa == null) {
|
||||
@@ -1174,6 +1209,26 @@ class VideoDetailController extends GetxController
|
||||
|
||||
volume = data.volume;
|
||||
|
||||
final progress = args['progress'];
|
||||
if (progress != null) {
|
||||
this.defaultST = Duration(milliseconds: progress);
|
||||
args['progress'] = null;
|
||||
} else {
|
||||
this.defaultST =
|
||||
defaultST ??
|
||||
(data.lastPlayTime == null
|
||||
? Duration.zero
|
||||
: Duration(milliseconds: data.lastPlayTime!));
|
||||
}
|
||||
|
||||
if (!isUgc && !fromReset && plPlayerController.enablePgcSkip) {
|
||||
if (data.clipInfoList case final clipInfoList?) {
|
||||
positionSubscription?.cancel();
|
||||
positionSubscription = null;
|
||||
handleSBData(clipInfoList);
|
||||
}
|
||||
}
|
||||
|
||||
if (data.acceptDesc?.contains('试看') == true) {
|
||||
SmartDialog.showToast(
|
||||
'该视频为专属视频,仅提供试看',
|
||||
@@ -1183,13 +1238,7 @@ class VideoDetailController extends GetxController
|
||||
if (data.dash == null && data.durl != null) {
|
||||
videoUrl = data.durl!.first.url!;
|
||||
audioUrl = '';
|
||||
final progress = args['progress'];
|
||||
if (progress != null) {
|
||||
this.defaultST = Duration(milliseconds: progress);
|
||||
args['progress'] = null;
|
||||
} else {
|
||||
this.defaultST = defaultST ?? Duration.zero;
|
||||
}
|
||||
|
||||
// 实际为FLV/MP4格式,但已被淘汰,这里仅做兜底处理
|
||||
firstVideo = VideoItem(
|
||||
id: data.quality!,
|
||||
@@ -1305,18 +1354,6 @@ class VideoDetailController extends GetxController
|
||||
firstAudio = AudioItem();
|
||||
audioUrl = '';
|
||||
}
|
||||
//
|
||||
final progress = args['progress'];
|
||||
if (progress != null) {
|
||||
this.defaultST = Duration(milliseconds: progress);
|
||||
args['progress'] = null;
|
||||
} else {
|
||||
this.defaultST =
|
||||
defaultST ??
|
||||
(data.lastPlayTime == null
|
||||
? Duration.zero
|
||||
: Duration(milliseconds: data.lastPlayTime!));
|
||||
}
|
||||
if (autoPlay.value || plPlayerController.preInitPlayer) {
|
||||
await playerInit();
|
||||
}
|
||||
@@ -1578,6 +1615,7 @@ class VideoDetailController extends GetxController
|
||||
|
||||
void onReset({bool isStein = false}) {
|
||||
playedTime = null;
|
||||
defaultST = null;
|
||||
videoUrl = null;
|
||||
audioUrl = null;
|
||||
|
||||
@@ -1609,6 +1647,7 @@ class VideoDetailController extends GetxController
|
||||
|
||||
// sponsor block
|
||||
if (plPlayerController.enableSponsorBlock) {
|
||||
_lastPos = null;
|
||||
positionSubscription?.cancel();
|
||||
positionSubscription = null;
|
||||
videoLabel.value = '';
|
||||
@@ -1699,7 +1738,7 @@ class VideoDetailController extends GetxController
|
||||
try {
|
||||
if (plPlayerController.enableSponsorBlock) {
|
||||
if (listData.lastOrNull case SegmentModel item) {
|
||||
onSkip(item);
|
||||
onSkip(item, isSeek: false);
|
||||
onRemoveItem(listData.indexOf(item), item);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -130,11 +130,10 @@ class _ViewPointsPageState extends State<ViewPointsPage>
|
||||
onTap: segment.from != null
|
||||
? () {
|
||||
Get.back();
|
||||
plPlayerController
|
||||
?..danmakuController?.clear()
|
||||
..videoPlayerController?.seek(
|
||||
Duration(seconds: segment.from!),
|
||||
);
|
||||
plPlayerController?.seekTo(
|
||||
Duration(seconds: segment.from!),
|
||||
isSeek: false,
|
||||
);
|
||||
}
|
||||
: null,
|
||||
child: Padding(
|
||||
|
||||
@@ -684,6 +684,7 @@ class HeaderControlState extends State<HeaderControl> {
|
||||
final int quality = item.quality!;
|
||||
final newQa = VideoQuality.fromCode(quality);
|
||||
videoDetailCtr
|
||||
..plPlayerController.cacheVideoQa = newQa.code
|
||||
..currentVideoQa.value = newQa
|
||||
..updatePlayer();
|
||||
|
||||
@@ -762,6 +763,7 @@ class HeaderControlState extends State<HeaderControl> {
|
||||
final int quality = i.id!;
|
||||
final newQa = AudioQuality.fromCode(quality);
|
||||
videoDetailCtr
|
||||
..plPlayerController.cacheAudioQa = newQa.code
|
||||
..currentAudioQa = newQa
|
||||
..updatePlayer();
|
||||
|
||||
|
||||
@@ -361,8 +361,10 @@ class PlPlayerController {
|
||||
late double subtitleStrokeWidth = Pref.subtitleStrokeWidth;
|
||||
late int subtitleFontWeight = Pref.subtitleFontWeight;
|
||||
|
||||
late final pgcSkipType = Pref.pgcSkipType;
|
||||
late final enablePgcSkip = Pref.pgcSkipType != SkipType.disable;
|
||||
// sponsor block
|
||||
late final bool enableSponsorBlock = Pref.enableSponsorBlock;
|
||||
late final bool enableSponsorBlock = Pref.enableSponsorBlock || enablePgcSkip;
|
||||
late final double blockLimit = Pref.blockLimit;
|
||||
late final blockSettings = Pref.blockSettings;
|
||||
late final List<Color> blockColor = Pref.blockColor;
|
||||
@@ -1253,14 +1255,12 @@ class PlPlayerController {
|
||||
|
||||
/// 暂停播放
|
||||
Future<void> pause({bool notify = true, bool isInterrupt = false}) async {
|
||||
if (videoPlayerController?.state.playing ?? false) {
|
||||
await _videoPlayerController?.playOrPause();
|
||||
playerStatus.status.value = PlayerStatus.paused;
|
||||
await _videoPlayerController?.pause();
|
||||
playerStatus.status.value = PlayerStatus.paused;
|
||||
|
||||
// 主动暂停时让出音频焦点
|
||||
if (!isInterrupt) {
|
||||
audioSessionHandler?.setActive(false);
|
||||
}
|
||||
// 主动暂停时让出音频焦点
|
||||
if (!isInterrupt) {
|
||||
audioSessionHandler?.setActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -682,6 +682,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
final int quality = item.quality!;
|
||||
final newQa = VideoQuality.fromCode(quality);
|
||||
videoDetailController
|
||||
..plPlayerController.cacheVideoQa = newQa.code
|
||||
..currentVideoQa.value = newQa
|
||||
..updatePlayer();
|
||||
|
||||
@@ -1756,7 +1757,8 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
|
||||
Obx(() {
|
||||
if (plPlayerController.dataStatus.loading ||
|
||||
plPlayerController.isBuffering.value) {
|
||||
(plPlayerController.isBuffering.value &&
|
||||
plPlayerController.playerStatus.playing)) {
|
||||
return Center(
|
||||
child: GestureDetector(
|
||||
onTap: plPlayerController.refreshPlayer,
|
||||
|
||||
@@ -26,7 +26,8 @@ abstract class SettingBoxKey {
|
||||
enableOnlineTotal = 'enableOnlineTotal',
|
||||
showSuperChat = 'showSuperChat',
|
||||
keyboardControl = 'keyboardControl',
|
||||
pauseOnMinimize = 'pauseOnMinimize';
|
||||
pauseOnMinimize = 'pauseOnMinimize',
|
||||
pgcSkipType = 'pgcSkipType';
|
||||
|
||||
static const String enableVerticalExpand = 'enableVerticalExpand',
|
||||
feedBackEnable = 'feedBackEnable',
|
||||
|
||||
@@ -847,4 +847,8 @@ abstract class Pref {
|
||||
|
||||
static double get desktopVolume =>
|
||||
_setting.get(SettingBoxKey.desktopVolume, defaultValue: 1.0);
|
||||
|
||||
static SkipType get pgcSkipType =>
|
||||
SkipType.values[_setting.get(SettingBoxKey.pgcSkipType) ??
|
||||
SkipType.skipOnce.index];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user