mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
opt: post segments
Closes #531 Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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');
|
||||||
|
|||||||
Reference in New Issue
Block a user