diff --git a/lib/common/widgets/segment_progress_bar.dart b/lib/common/widgets/segment_progress_bar.dart index fcc1fcc04..9d83df627 100644 --- a/lib/common/widgets/segment_progress_bar.dart +++ b/lib/common/widgets/segment_progress_bar.dart @@ -4,8 +4,9 @@ class Segment { final double start; final double end; final Color color; + final String? title; - Segment(this.start, this.end, this.color); + Segment(this.start, this.end, this.color, [this.title]); } class SegmentProgressBar extends CustomPainter { @@ -21,10 +22,10 @@ class SegmentProgressBar extends CustomPainter { void paint(Canvas canvas, Size size) { final paint = Paint()..style = PaintingStyle.fill; - for (var segment in segmentColors) { - paint.color = segment.color; - final segmentStart = segment.start * size.width; - final segmentEnd = segment.end * size.width; + for (int i = 0; i < segmentColors.length; i++) { + paint.color = segmentColors[i].color; + final segmentStart = segmentColors[i].start * size.width; + final segmentEnd = segmentColors[i].end * size.width; final progressEnd = progress * size.width; if (progressEnd < segmentStart) { @@ -33,11 +34,35 @@ class SegmentProgressBar extends CustomPainter { final segmentWidth = (progressEnd < segmentEnd ? progressEnd : segmentEnd) - segmentStart; - if (segmentWidth > 0) { + if (segmentWidth >= 0) { canvas.drawRect( - Rect.fromLTWH(segmentStart, 0, segmentWidth, size.height), + Rect.fromLTWH( + segmentStart, + 0, + segmentWidth == 0 ? 2 : segmentWidth, + size.height, + ), paint, ); + if (segmentColors[i].title != null) { + TextPainter textPainter = TextPainter( + text: TextSpan( + text: segmentColors[i].title, + style: TextStyle(color: Colors.white, fontSize: 8), + ), + textDirection: TextDirection.ltr, + )..layout(); + + double? prevStart; + if (i != 0) { + prevStart = segmentColors[i - 1].start * size.width; + } + double textX = i == 0 + ? (segmentStart - textPainter.width) / 2 + : (segmentStart - prevStart! - textPainter.width) / 2 + prevStart; + double textY = size.height - textPainter.height - 1; + textPainter.paint(canvas, Offset(textX, textY)); + } } } } diff --git a/lib/http/video.dart b/lib/http/video.dart index 8f389328b..28097302e 100644 --- a/lib/http/video.dart +++ b/lib/http/video.dart @@ -861,11 +861,14 @@ class VideoHttp { static Future subtitlesJson( {String? aid, String? bvid, required int cid}) async { assert(aid != null || bvid != null); - var res = await Request().get(Api.subtitleUrl, data: { - if (aid != null) 'aid': aid, - if (bvid != null) 'bvid': bvid, - 'cid': cid, - }); + var res = await Request().get( + Api.subtitleUrl, + data: { + if (aid != null) 'aid': aid, + if (bvid != null) 'bvid': bvid, + 'cid': cid, + }, + ); if (res.data['code'] == 0) { dynamic data = res.data['data']; List subtitlesJson = data['subtitle']['subtitles']; @@ -887,6 +890,7 @@ class VideoHttp { return { 'status': true, 'data': subtitlesJson, + 'view_points': data['view_points'], }; } else { return {'status': false, 'data': [], 'msg': res.data['message']}; diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index aa53baa13..d8156343d 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -607,11 +607,7 @@ class VideoDetailController extends GetxController .clamp(0.0, 1.0); double end = (item.segment.second / ((data.timeLength ?? 0) / 1000)) .clamp(0.0, 1.0); - return Segment( - start, - (start == end && end != 0) ? (end + 0.01).clamp(0.0, 1.0) : end, - _getColor(item.segmentType), - ); + return Segment(start, end, _getColor(item.segmentType)); }).toList()); } catch (e) { debugPrint('failed to parse sponsorblock: $e'); diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index a0fcad758..91333c3b1 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -114,6 +114,7 @@ class PlPlayerController { Timer? _timerForGettingVolume; Timer? timerForTrackingMouse; + final RxList viewPointList = [].obs; final RxList segmentList = [].obs; // final Durations durations; @@ -430,6 +431,7 @@ class PlPlayerController { }) async { try { this.dataSource = dataSource; + viewPointList.clear(); this.segmentList.value = segmentList ?? []; _autoPlay = autoplay; _looping = looping; @@ -1357,17 +1359,27 @@ class PlPlayerController { // if (!res["status"]) { // SmartDialog.showToast('查询字幕错误,${res["msg"]}'); // } - if (res["data"].length == 0) { - return; + + if (res["data"] is List && res["data"].isNotEmpty) { + var result = await VideoHttp.vttSubtitles(res["data"]); + if (result != null) { + _vttSubtitles.value = result; + } + // if (_vttSubtitles.isEmpty) { + // SmartDialog.showToast('字幕均加载失败'); + // } } - var result = await VideoHttp.vttSubtitles(res["data"]); - if (result != null) { - _vttSubtitles.value = result; + if (res["view_points"] is List && res["view_points"].isNotEmpty) { + viewPointList.value = (res["view_points"] as List).map((item) { + double start = (item['to'] / durationSeconds.value).clamp(0.0, 1.0); + return Segment( + start, + start, + Colors.black, + item['content'], + ); + }).toList(); } - // if (_vttSubtitles.isEmpty) { - // SmartDialog.showToast('字幕均加载失败'); - // } - return; } // 设定字幕轨道 diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index fb06ba4a7..7be053964 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -1014,7 +1014,6 @@ class _PLVideoPlayerState extends State BottomControl( controller: widget.controller, buildBottomControl: buildBottomControl(), - segmentList: plPlayerController.segmentList, ), ), ), @@ -1115,6 +1114,14 @@ class _PLVideoPlayerState extends State segmentColors: plPlayerController.segmentList, ), ), + if (plPlayerController.viewPointList.isNotEmpty) + CustomPaint( + size: Size(double.infinity, 3.5), + painter: SegmentProgressBar( + progress: 1, + segmentColors: plPlayerController.viewPointList, + ), + ), ], ), // SlideTransition( diff --git a/lib/plugin/pl_player/widgets/bottom_control.dart b/lib/plugin/pl_player/widgets/bottom_control.dart index 0f14f2373..75e21327a 100644 --- a/lib/plugin/pl_player/widgets/bottom_control.dart +++ b/lib/plugin/pl_player/widgets/bottom_control.dart @@ -13,11 +13,9 @@ import '../../../common/widgets/audio_video_progress_bar.dart'; class BottomControl extends StatelessWidget implements PreferredSizeWidget { final PlPlayerController? controller; final List? buildBottomControl; - final List? segmentList; const BottomControl({ this.controller, this.buildBottomControl, - this.segmentList, super.key, }); @@ -98,12 +96,20 @@ class BottomControl extends StatelessWidget implements PreferredSizeWidget { TextDirection.ltr); }, ), - if (segmentList?.isNotEmpty == true) + if (controller?.segmentList.isNotEmpty == true) CustomPaint( size: Size(double.infinity, 3.5), painter: SegmentProgressBar( progress: 1, - segmentColors: segmentList!, + segmentColors: controller!.segmentList, + ), + ), + if (controller?.viewPointList.isNotEmpty == true) + CustomPaint( + size: Size(double.infinity, 3.5), + painter: SegmentProgressBar( + progress: 1, + segmentColors: controller!.viewPointList, ), ), ],