opt: post segments

Closes #531

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-03-26 12:03:21 +08:00
parent 812f351ddd
commit aa378d924b
4 changed files with 79 additions and 35 deletions

View File

@@ -8,7 +8,7 @@ class PostSegmentModel {
required this.category, required this.category,
required this.actionType, required this.actionType,
}); });
Pair<int, int> segment; Pair<double, double> segment;
SegmentType category; SegmentType category;
ActionType actionType; ActionType actionType;
} }

View File

@@ -745,12 +745,20 @@ class VideoDetailController extends GetxController
skipType = SkipType.showOnly; skipType = SkipType.showOnly;
} }
} }
int convert(value) {
return switch (value) {
int() => value,
double() => value.round(),
_ => -1,
};
}
return SegmentModel( return SegmentModel(
UUID: item['UUID'], UUID: item['UUID'],
segmentType: segmentType, segmentType: segmentType,
segment: Pair( segment: Pair(
first: _convert(item['segment'][0]), first: convert(item['segment'][0]),
second: _convert(item['segment'][1]), second: convert(item['segment'][1]),
), ),
skipType: skipType, skipType: skipType,
); );
@@ -772,14 +780,6 @@ class VideoDetailController extends GetxController
} }
} }
int _convert(value) {
return value is double
? value.round()
: value is int
? value
: -1;
}
void initSkip() { void initSkip() {
if (segmentList.isNotEmpty) { if (segmentList.isNotEmpty) {
positionSubscription = plPlayerController positionSubscription = plPlayerController
@@ -1319,7 +1319,7 @@ class VideoDetailController extends GetxController
PostSegmentModel( PostSegmentModel(
segment: Pair( segment: Pair(
first: 0, first: 0,
second: plPlayerController.positionSeconds.value, second: plPlayerController.position.value.inMilliseconds / 1000,
), ),
category: SegmentType.sponsor, category: SegmentType.sponsor,
actionType: ActionType.skip, actionType: ActionType.skip,

View File

@@ -42,6 +42,12 @@ class _PostPanelState extends CommonCollapseSlidePageState<PostPanel> {
PlPlayerController get plPlayerController => widget.plPlayerController; PlPlayerController get plPlayerController => widget.plPlayerController;
List<PostSegmentModel>? get list => videoDetailController.list; List<PostSegmentModel>? get list => videoDetailController.list;
late final double videoDuration =
plPlayerController.durationSeconds.value.inMilliseconds / 1000;
double get currentPos =>
plPlayerController.position.value.inMilliseconds / 1000;
@override @override
Widget get buildPage => Scaffold( Widget get buildPage => Scaffold(
resizeToAvoidBottomInset: false, resizeToAvoidBottomInset: false,
@@ -60,7 +66,7 @@ class _PostPanelState extends CommonCollapseSlidePageState<PostPanel> {
PostSegmentModel( PostSegmentModel(
segment: Pair( segment: Pair(
first: 0, first: 0,
second: plPlayerController.positionSeconds.value, second: currentPos,
), ),
category: SegmentType.sponsor, category: SegmentType.sponsor,
actionType: ActionType.skip, actionType: ActionType.skip,
@@ -299,6 +305,50 @@ class _PostPanelState extends CommonCollapseSlidePageState<PostPanel> {
}, },
), ),
), ),
Positioned(
top: 0,
left: 4,
child: iconButton(
context: context,
size: 26,
tooltip: '预览',
icon: Icons.preview_outlined,
onPressed: () async {
if (widget.plPlayerController
.videoPlayerController !=
null) {
int start = max(
0,
(list![index].segment.first * 1000).toInt() -
1,
);
await widget
.plPlayerController.videoPlayerController!
.seek(
Duration(milliseconds: start),
);
if (widget.plPlayerController
.videoPlayerController!.state.playing.not) {
await widget
.plPlayerController.videoPlayerController!
.play();
}
if (start != 0) {
await Future.delayed(
const Duration(seconds: 1));
}
widget.plPlayerController.videoPlayerController!
.seek(
Duration(
milliseconds:
(list![index].segment.second * 1000)
.toInt(),
),
);
}
},
),
),
], ],
), ),
), ),
@@ -338,8 +388,7 @@ class _PostPanelState extends CommonCollapseSlidePageState<PostPanel> {
'cid': videoDetailController.cid.value, 'cid': videoDetailController.cid.value,
'userID': GStorage.blockUserID, 'userID': GStorage.blockUserID,
'userAgent': Constants.userAgent, 'userAgent': Constants.userAgent,
'videoDuration': plPlayerController 'videoDuration': videoDuration,
.durationSeconds.value.inSeconds,
}, },
data: { data: {
'segments': list! 'segments': list!
@@ -400,7 +449,7 @@ class _PostPanelState extends CommonCollapseSlidePageState<PostPanel> {
void updateSegment({ void updateSegment({
required bool isFirst, required bool isFirst,
required int index, required int index,
required int value, required double value,
}) { }) {
if (isFirst) { if (isFirst) {
list![index].segment.first = value; list![index].segment.first = value;
@@ -434,7 +483,7 @@ class _PostPanelState extends CommonCollapseSlidePageState<PostPanel> {
updateSegment( updateSegment(
isFirst: isFirst, isFirst: isFirst,
index: index, index: index,
value: plPlayerController.positionSeconds.value, value: currentPos,
); );
}); });
}, },
@@ -450,9 +499,7 @@ class _PostPanelState extends CommonCollapseSlidePageState<PostPanel> {
updateSegment( updateSegment(
isFirst: isFirst, isFirst: isFirst,
index: index, index: index,
value: isFirst value: isFirst ? 0 : videoDuration,
? 0
: plPlayerController.durationSeconds.value.inSeconds,
); );
}); });
}, },
@@ -464,7 +511,7 @@ class _PostPanelState extends CommonCollapseSlidePageState<PostPanel> {
tooltip: '编辑', tooltip: '编辑',
icon: Icons.edit, icon: Icons.edit,
onPressed: () { onPressed: () {
showDialog( showDialog<String>(
context: context, context: context,
builder: (context) { builder: (context) {
String initV = value; String initV = value;
@@ -477,7 +524,7 @@ class _PostPanelState extends CommonCollapseSlidePageState<PostPanel> {
}, },
inputFormatters: [ inputFormatters: [
FilteringTextInputFormatter.allow( FilteringTextInputFormatter.allow(
RegExp(r'[\d:]+'), RegExp(r'[\d:.]+'),
), ),
], ],
), ),
@@ -500,19 +547,13 @@ class _PostPanelState extends CommonCollapseSlidePageState<PostPanel> {
).then((res) { ).then((res) {
if (res != null) { if (res != null) {
try { try {
List<int> split = (res as String) List<num> split =
.split(':') res.split(':').reversed.map((e) => num.parse(e)).toList();
.toList() double duration = 0;
.reversed
.toList()
.map((e) => int.parse(e))
.toList();
int duration = 0;
for (int i = 0; i < split.length; i++) { for (int i = 0; i < split.length; i++) {
duration += split[i] * pow(60, i).toInt(); duration += split[i] * pow(60, i);
} }
if (duration <= if (duration <= videoDuration) {
plPlayerController.durationSeconds.value.inSeconds) {
setState(() { setState(() {
updateSegment( updateSegment(
isFirst: isFirst, isFirst: isFirst,

View File

@@ -1423,10 +1423,13 @@ class Utils {
return v.toString() + random.nextInt(9999).toString(); return v.toString() + random.nextInt(9999).toString();
} }
static String formatDuration(int seconds) { static String formatDuration(num seconds) {
int hours = seconds ~/ 3600; int hours = seconds ~/ 3600;
int minutes = (seconds % 3600) ~/ 60; int minutes = (seconds % 3600) ~/ 60;
int remainingSeconds = seconds % 60; num remainingSeconds = seconds % 60;
if (remainingSeconds is double) {
remainingSeconds = remainingSeconds.toPrecision(3);
}
String minutesStr = minutes.toString().padLeft(2, '0'); String minutesStr = minutes.toString().padLeft(2, '0');
String secondsStr = remainingSeconds.toString().padLeft(2, '0'); String secondsStr = remainingSeconds.toString().padLeft(2, '0');