opt: query sponsor block

Closes #633

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-04-07 21:52:39 +08:00
parent 4de180c23a
commit 6f2d697748

View File

@@ -41,6 +41,7 @@ import 'package:PiliPlus/utils/utils.dart';
import 'package:PiliPlus/utils/video_utils.dart'; import 'package:PiliPlus/utils/video_utils.dart';
import 'package:get/get_navigation/src/dialog/dialog_route.dart'; import 'package:get/get_navigation/src/dialog/dialog_route.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'package:media_kit/media_kit.dart'; import 'package:media_kit/media_kit.dart';
import '../../../utils/id_utils.dart'; import '../../../utils/id_utils.dart';
@@ -633,34 +634,29 @@ class VideoDetailController extends GetxController
item.skipType.title, item.skipType.title,
style: TextStyle(fontSize: 13), style: TextStyle(fontSize: 13),
), ),
if (item.skipType == SkipType.showOnly && if (item.segment.second != 0)
item.segment.second != 0)
SizedBox( SizedBox(
width: 36, width: 36,
height: 36, height: 36,
child: IconButton( child: IconButton(
tooltip: '跳转至此片段', tooltip: item.skipType == SkipType.showOnly
? '跳至此片段'
: '跳过此片段',
onPressed: () async { onPressed: () async {
Get.back(); Get.back();
try { onSkip(
plPlayerController.danmakuController?.clear(); item,
await plPlayerController.videoPlayerController item.skipType != SkipType.showOnly,
?.seek(Duration( );
seconds: item.segment.first));
if (GStorage.blockToast) {
_showBlockToast(
'已跳至${item.segmentType.shortTitle}');
}
} catch (e) {
_showBlockToast('跳转失败: $e');
}
}, },
style: IconButton.styleFrom( style: IconButton.styleFrom(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
tapTargetSize: MaterialTapTargetSize.shrinkWrap, tapTargetSize: MaterialTapTargetSize.shrinkWrap,
), ),
icon: Icon( icon: Icon(
Icons.my_location, item.skipType == SkipType.showOnly
? Icons.my_location
: MdiIcons.debugStepOver,
size: 18, size: 18,
color: Theme.of(context) color: Theme.of(context)
.colorScheme .colorScheme
@@ -695,15 +691,17 @@ class VideoDetailController extends GetxController
videoLabel.value = ''; videoLabel.value = '';
segmentList.clear(); segmentList.clear();
segmentProgressList = null; segmentProgressList = null;
dynamic result = await Request().get( final result = await Request().get(
'${GStorage.blockServer}/api/skipSegments', '${GStorage.blockServer}/api/skipSegments',
queryParameters: { queryParameters: {
'videoID': bvid, 'videoID': bvid,
'cid': cid.value, 'cid': cid.value,
}, },
); );
if (result.statusCode == 200) {
handleSBData(result); handleSBData(result);
} }
}
void handleSBData(result) { void handleSBData(result) {
if (result.data is List && result.data.isNotEmpty) { if (result.data is List && result.data.isNotEmpty) {
@@ -736,6 +734,7 @@ class VideoDetailController extends GetxController
skipType = SkipType.showOnly; skipType = SkipType.showOnly;
} }
} }
int convert(value) { int convert(value) {
return switch (value) { return switch (value) {
int() => value, int() => value,
@@ -744,7 +743,7 @@ class VideoDetailController extends GetxController
}; };
} }
return SegmentModel( final segmentModel = SegmentModel(
UUID: item['UUID'], UUID: item['UUID'],
segmentType: segmentType, segmentType: segmentType,
segment: Pair( segment: Pair(
@@ -753,18 +752,51 @@ class VideoDetailController extends GetxController
), ),
skipType: skipType, skipType: skipType,
); );
if (item['segment'][0] == 0 &&
item['segment'][1] > 0 &&
!isShowCover.value) {
if (plPlayerController.videoPlayerController != null &&
plPlayerController
.videoPlayerController!.state.position.inSeconds <
item['segment'][1]) {
if (segmentModel.skipType == SkipType.alwaysSkip) {
_lastPos = 0;
plPlayerController.videoPlayerController!.stream.buffer.first
.then((_) {
onSkip(segmentModel);
});
} else if (segmentModel.skipType == SkipType.skipOnce) {
_lastPos = 0;
segmentModel.hasSkipped = true;
plPlayerController.videoPlayerController!.stream.buffer.first
.then((_) {
onSkip(segmentModel);
});
} else if (segmentModel.skipType == SkipType.skipManually) {
onAddItem(segmentModel);
}
}
}
return segmentModel;
}, },
).toList()); ).toList());
// _segmentProgressList // _segmentProgressList
segmentProgressList ??= <Segment>[]; segmentProgressList ??= <Segment>[];
segmentProgressList!.addAll(segmentList.map((item) { segmentProgressList!.addAll(segmentList.map((item) {
double start = (item.segment.first / ((data.timeLength ?? 0) / 1000)) double start =
.clamp(0.0, 1.0); (item.segment.first / (data.timeLength! / 1000)).clamp(0.0, 1.0);
double end = (item.segment.second / ((data.timeLength ?? 0) / 1000)) double end =
.clamp(0.0, 1.0); (item.segment.second / (data.timeLength! / 1000)).clamp(0.0, 1.0);
return Segment(start, end, _getColor(item.segmentType)); return Segment(start, end, _getColor(item.segmentType));
}).toList()); }).toList());
if (positionSubscription == null && autoPlay.value) {
initSkip();
plPlayerController.segmentList.value = segmentProgressList!;
}
} catch (e) { } catch (e) {
debugPrint('failed to parse sponsorblock: $e'); debugPrint('failed to parse sponsorblock: $e');
} }
@@ -773,9 +805,10 @@ class VideoDetailController extends GetxController
void initSkip() { void initSkip() {
if (segmentList.isNotEmpty) { if (segmentList.isNotEmpty) {
positionSubscription?.cancel();
positionSubscription = plPlayerController positionSubscription = plPlayerController
.videoPlayerController?.stream.position .videoPlayerController?.stream.position
.listen((position) async { .listen((position) {
if (isShowCover.value) { if (isShowCover.value) {
return; return;
} }
@@ -804,6 +837,7 @@ class VideoDetailController extends GetxController
} }
void onAddItem(item) { void onAddItem(item) {
if (listData.contains(item)) return;
listData.insert(0, item); listData.insert(0, item);
listKey.currentState?.insertItem(0); listKey.currentState?.insertItem(0);
skipTimer ??= Timer.periodic(const Duration(seconds: 4), (_) { skipTimer ??= Timer.periodic(const Duration(seconds: 4), (_) {
@@ -890,11 +924,12 @@ class VideoDetailController extends GetxController
); );
} }
void onSkip(SegmentModel item) async { void onSkip(SegmentModel item, [bool isSkip = true]) async {
try { try {
plPlayerController.danmakuController?.clear(); plPlayerController.danmakuController?.clear();
await plPlayerController.videoPlayerController await plPlayerController.videoPlayerController
?.seek(Duration(seconds: item.segment.second)); ?.seek(Duration(seconds: item.segment.second));
if (isSkip) {
if (GStorage.blockToast) { if (GStorage.blockToast) {
_showBlockToast('已跳过${item.segmentType.shortTitle}片段'); _showBlockToast('已跳过${item.segmentType.shortTitle}片段');
} }
@@ -904,9 +939,16 @@ class VideoDetailController extends GetxController
queryParameters: {'UUID': item.UUID}, queryParameters: {'UUID': item.UUID},
); );
} }
} else {
_showBlockToast('已跳至${item.segmentType.shortTitle}');
}
} catch (e) { } catch (e) {
debugPrint('failed to skip: $e'); debugPrint('failed to skip: $e');
if (isSkip) {
_showBlockToast('${item.segmentType.shortTitle}片段跳过失败'); _showBlockToast('${item.segmentType.shortTitle}片段跳过失败');
} else {
_showBlockToast('跳转失败');
}
} }
} }
@@ -1134,7 +1176,7 @@ class VideoDetailController extends GetxController
data = result['data']; data = result['data'];
if (enableSponsorBlock) { if (enableSponsorBlock) {
await _querySponsorBlock(); _querySponsorBlock();
} }
if (data.acceptDesc!.isNotEmpty && data.acceptDesc!.contains('试看')) { if (data.acceptDesc!.isNotEmpty && data.acceptDesc!.contains('试看')) {
@@ -1457,9 +1499,10 @@ class VideoDetailController extends GetxController
if (GStorage.showViewPoints && if (GStorage.showViewPoints &&
res["view_points"] is List && res["view_points"] is List &&
res["view_points"].isNotEmpty) { res["view_points"].isNotEmpty) {
try {
viewPointList = (res["view_points"] as List).map((item) { viewPointList = (res["view_points"] as List).map((item) {
double start = double start =
(item['to'] / ((data.timeLength ?? 0) / 1000)).clamp(0.0, 1.0); (item['to'] / (data.timeLength! / 1000)).clamp(0.0, 1.0);
return Segment( return Segment(
start, start,
start, start,
@@ -1474,6 +1517,7 @@ class VideoDetailController extends GetxController
plPlayerController.viewPointList.value = viewPointList; plPlayerController.viewPointList.value = viewPointList;
plPlayerController.showVP.value = showVP = true; plPlayerController.showVP.value = showVP = true;
} }
} catch (_) {}
} }
if (res["subtitles"] is List && res["subtitles"].isNotEmpty) { if (res["subtitles"] is List && res["subtitles"].isNotEmpty) {
@@ -1563,6 +1607,7 @@ class VideoDetailController extends GetxController
// sponsor block // sponsor block
if (enableSponsorBlock) { if (enableSponsorBlock) {
positionSubscription?.cancel(); positionSubscription?.cancel();
positionSubscription = null;
videoLabel.value = ''; videoLabel.value = '';
segmentList.clear(); segmentList.clear();
segmentProgressList = null; segmentProgressList = null;