mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-06-02 00:58:19 +08:00
opt: query sponsor block
Closes #633 Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user