diff --git a/lib/pages/video/controller.dart b/lib/pages/video/controller.dart index c343da3b..5f6ce953 100644 --- a/lib/pages/video/controller.dart +++ b/lib/pages/video/controller.dart @@ -430,10 +430,9 @@ class VideoDetailController extends GetxController bool get showVideoSheet => !horizontalScreen && !isPortrait; int? _lastPos; - List postList = []; - RxList segmentList = [].obs; - List viewPointList = []; - List? segmentProgressList; + late final List postList = []; + late final List segmentList = []; + late final RxList segmentProgressList = [].obs; Color _getColor(SegmentType segment) => plPlayerController.blockColor[segment.index]; @@ -678,7 +677,7 @@ class VideoDetailController extends GetxController positionSubscription?.cancel(); videoLabel.value = ''; segmentList.clear(); - segmentProgressList = null; + segmentProgressList.clear(); final result = await Request().get( '$blockServer/api/skipSegments', queryParameters: { @@ -774,7 +773,7 @@ class VideoDetailController extends GetxController ); // _segmentProgressList - (segmentProgressList ??= []).addAll( + segmentProgressList.addAll( segmentList.map((e) { double start = (e.segment.first / duration).clamp(0.0, 1.0); double end = (e.segment.second / duration).clamp(0.0, 1.0); @@ -785,7 +784,6 @@ class VideoDetailController extends GetxController if (positionSubscription == null && (autoPlay.value || plPlayerController.preInitPlayer)) { initSkip(); - plPlayerController.segmentList.value = segmentProgressList!; } } catch (e) { if (kDebugMode) debugPrint('failed to parse sponsorblock: $e'); @@ -1072,10 +1070,6 @@ class VideoDetailController extends GetxController 'referer': HttpString.baseUrl, }, ), - segmentList: segmentProgressList, - viewPointList: viewPointList, - showVP: showVP, - dmTrend: dmTrend, seekTo: seekToTime ?? defaultST ?? playedTime, duration: duration ?? @@ -1101,13 +1095,15 @@ class VideoDetailController extends GetxController height: firstVideo.height, ); - initSkip(); - - if (vttSubtitlesIndex.value == -1) { - _getSubtitle(); + if (plPlayerController.enableSponsorBlock) { + initSkip(); } - if (plPlayerController.showDmChart && dmTrend == null) { + if (vttSubtitlesIndex.value == -1) { + _queryPlayInfo(); + } + + if (plPlayerController.showDmChart && dmTrend.value == null) { _getDmTrend(); } @@ -1365,13 +1361,8 @@ class VideoDetailController extends GetxController RxList subtitles = RxList(); late final Map _vttSubtitles = {}; late final RxInt vttSubtitlesIndex = (-1).obs; - late bool showVP = true; - - void _getSubtitle() { - _vttSubtitles.clear(); - viewPointList.clear(); - _queryPlayInfo(); - } + late final RxBool showVP = true.obs; + late final RxList viewPointList = [].obs; // 设定字幕轨道 Future setSubtitle(int index) async { @@ -1439,6 +1430,10 @@ class VideoDetailController extends GetxController late bool continuePlayingPart = Pref.continuePlayingPart; Future _queryPlayInfo() async { + _vttSubtitles.clear(); + if (plPlayerController.showViewPoints) { + viewPointList.clear(); + } var res = await VideoHttp.playInfo(bvid: bvid, cid: cid.value); if (res['status']) { PlayInfoData playInfo = res['data']; @@ -1475,9 +1470,10 @@ class VideoDetailController extends GetxController } catch (_) {} } - if (playInfo.viewPoints?.isNotEmpty == true && Pref.showViewPoints) { + if (plPlayerController.showViewPoints && + playInfo.viewPoints?.isNotEmpty == true) { try { - viewPointList = playInfo.viewPoints!.map((item) { + viewPointList.value = playInfo.viewPoints!.map((item) { double start = (item.to! / (data.timeLength! / 1000)).clamp( 0.0, 1.0, @@ -1492,10 +1488,6 @@ class VideoDetailController extends GetxController item.to, ); }).toList(); - if (plPlayerController.viewPointList.isEmpty) { - plPlayerController.viewPointList.value = viewPointList; - plPlayerController.showVP.value = showVP = true; - } } catch (_) {} } @@ -1576,8 +1568,12 @@ class VideoDetailController extends GetxController scrollRatio.refresh(); } + // dm trend + if (plPlayerController.showDmChart) { + dmTrend.value = null; + } + // danmaku - dmTrend = null; savedDanmaku = null; // subtitle @@ -1586,7 +1582,9 @@ class VideoDetailController extends GetxController _vttSubtitles.clear(); // view point - viewPointList.clear(); + if (plPlayerController.showViewPoints) { + viewPointList.clear(); + } // sponsor block if (plPlayerController.enableSponsorBlock) { @@ -1594,7 +1592,7 @@ class VideoDetailController extends GetxController positionSubscription = null; videoLabel.value = ''; segmentList.clear(); - segmentProgressList = null; + segmentProgressList.clear(); } // interactive video @@ -1605,10 +1603,12 @@ class VideoDetailController extends GetxController showSteinEdgeInfo.value = false; } - List? dmTrend; + late final Rx>?> dmTrend = + Rx>?>(null); + late final RxBool showDmTreandChart = true.obs; Future _getDmTrend() async { - dmTrend = null; + dmTrend.value = LoadingState>.loading(); try { var res = await Request().get( 'https://bvc.bilivideo.com/pbp/data', @@ -1617,16 +1617,15 @@ class VideoDetailController extends GetxController 'cid': cid.value, }, ); - PbpData data = PbpData.fromJson(res.data); int stepSec = data.stepSec ?? 0; if (stepSec != 0 && data.events?.eDefault?.isNotEmpty == true) { - dmTrend = data.events?.eDefault; - if (plPlayerController.dmTrend.isEmpty) { - plPlayerController.dmTrend.value = dmTrend!; - } + dmTrend.value = Success(data.events!.eDefault!); + return; } + dmTrend.value = const Error(null); } catch (e) { + dmTrend.value = const Error(null); if (kDebugMode) debugPrint('_getDmTrend: $e'); } } diff --git a/lib/pages/video/post_panel/view.dart b/lib/pages/video/post_panel/view.dart index c36c3ac0..9838f2a6 100644 --- a/lib/pages/video/post_panel/view.dart +++ b/lib/pages/video/post_panel/view.dart @@ -4,7 +4,6 @@ import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/widgets/button/icon_button.dart'; import 'package:PiliPlus/common/widgets/loading_widget/loading_widget.dart'; import 'package:PiliPlus/common/widgets/pair.dart'; -import 'package:PiliPlus/common/widgets/progress_bar/segment_progress_bar.dart'; import 'package:PiliPlus/http/init.dart'; import 'package:PiliPlus/models/common/sponsor_block/action_type.dart'; import 'package:PiliPlus/models/common/sponsor_block/post_segment_model.dart'; @@ -338,8 +337,6 @@ class _PostPanelState extends State list.map((e) => SegmentItemModel.fromJson(e)).toList(), ); } - plPlayerController.segmentList.value = - videoDetailController.segmentProgressList ?? []; if (videoDetailController.positionSubscription == null) { videoDetailController.initSkip(); } diff --git a/lib/pages/video/view.dart b/lib/pages/video/view.dart index bca9895a..d1a50609 100644 --- a/lib/pages/video/view.dart +++ b/lib/pages/video/view.dart @@ -396,9 +396,7 @@ class _VideoDetailPageVState extends State ..playerStatus = plPlayerController?.playerStatus.status.value ..brightness = plPlayerController?.brightness.value; if (plPlayerController != null) { - videoDetailController - ..makeHeartBeat() - ..showVP = plPlayerController!.showVP.value; + videoDetailController.makeHeartBeat(); plPlayerController! ..removeStatusLister(playerListener) ..removePositionListener(positionListener) diff --git a/lib/pages/video/view_point/view.dart b/lib/pages/video/view_point/view.dart index db12d3cf..2aa8381e 100644 --- a/lib/pages/video/view_point/view.dart +++ b/lib/pages/video/view_point/view.dart @@ -59,10 +59,9 @@ class _ViewPointsPageState extends State } return null; }), - value: videoDetailController.plPlayerController.showVP.value, - onChanged: (value) { - videoDetailController.plPlayerController.showVP.value = value; - }, + value: videoDetailController.showVP.value, + onChanged: (value) => + videoDetailController.showVP.value = value, ), ), ), diff --git a/lib/pages/video/widgets/header_control.dart b/lib/pages/video/widgets/header_control.dart index 7903808e..aa7c6da0 100644 --- a/lib/pages/video/widgets/header_control.dart +++ b/lib/pages/video/widgets/header_control.dart @@ -2054,7 +2054,7 @@ class HeaderControlState extends TripleState { ), ), Obx( - () => videoDetailCtr.segmentList.isNotEmpty + () => videoDetailCtr.segmentProgressList.isNotEmpty ? SizedBox( width: 42, height: 34, diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index 272ff7c0..cd01f30c 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -5,7 +5,6 @@ import 'dart:math' show max; import 'dart:ui' as ui; import 'package:PiliPlus/common/constants.dart'; -import 'package:PiliPlus/common/widgets/progress_bar/segment_progress_bar.dart'; import 'package:PiliPlus/http/init.dart'; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/ua_type.dart'; @@ -144,10 +143,6 @@ class PlPlayerController { Timer? _timerForSeek; Timer? _timerForShowingVolume; - final RxList viewPointList = [].obs; - final RxBool showVP = true.obs; - final RxList segmentList = [].obs; - Box setting = GStorage.setting; // final Durations durations; @@ -333,6 +328,7 @@ class PlPlayerController { late final reverseFromFirst = Pref.reverseFromFirst; late final horizontalPreview = Pref.horizontalPreview; late final showDmChart = Pref.showDmChart; + late final showViewPoints = Pref.showViewPoints; late final showFsScreenshotBtn = Pref.showFsScreenshotBtn; late final showFsLockBtn = Pref.showFsLockBtn; late final keyboardControl = Pref.keyboardControl; @@ -531,10 +527,6 @@ class PlPlayerController { Future setDataSource( DataSource dataSource, { bool isLive = false, - List? segmentList, - List? viewPointList, - bool? showVP, - List? dmTrend, bool autoplay = true, // 默认不循环 PlaylistMode looping = PlaylistMode.none, @@ -563,10 +555,6 @@ class PlPlayerController { this.width = width; this.height = height; this.dataSource = dataSource; - this.segmentList.value = segmentList ?? []; - this.viewPointList.value = viewPointList ?? []; - this.showVP.value = showVP ?? true; - this.dmTrend.value = dmTrend ?? []; _autoPlay = autoplay; _looping = looping; // 初始化视频倍速 @@ -1720,7 +1708,4 @@ class PlPlayerController { if (kDebugMode) debugPrint('getVideoShot: $e'); } } - - late final RxList dmTrend = [].obs; - late final RxBool showDmTreandChart = true.obs; } diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index b2032479..b137b1e0 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -107,6 +107,8 @@ class _PLVideoPlayerState extends State late AnimationController animationController; late VideoController videoController; late final CommonIntroController introController = widget.introController!; + late final VideoDetailController videoDetailController = + widget.videoDetailController!; final GlobalKey _playerKey = GlobalKey(); final GlobalKey key = GlobalKey(); @@ -229,12 +231,15 @@ class _PLVideoPlayerState extends State } // 动态构建底部控制条 - Widget buildBottomControl(bool isLandscape) { + Widget buildBottomControl( + VideoDetailController videoDetailController, + bool isLandscape, + ) { final videoDetail = introController.videoDetail.value; final isSeason = videoDetail.ugcSeason != null; final isPart = videoDetail.pages != null && videoDetail.pages!.length > 1; - final isPgc = !widget.videoDetailController!.isUgc; - final isPlayAll = widget.videoDetailController?.isPlayAll == true; + final isPgc = !videoDetailController.isUgc; + final isPlayAll = videoDetailController.isPlayAll; final anySeason = isSeason || isPart || isPgc || isPlayAll; final isFullScreen = this.isFullScreen; final double widgetWidth = isLandscape && isFullScreen ? 42 : 35; @@ -318,36 +323,40 @@ class _PLVideoPlayerState extends State /// 高能进度条 BottomControlType.dmChart => Obx( - () => plPlayerController.dmTrend.isEmpty - ? const SizedBox.shrink() - : ComBtn( - width: widgetWidth, - height: 30, - icon: plPlayerController.showDmTreandChart.value - ? const Icon( - Icons.show_chart, - size: 22, - color: Colors.white, - ) - : const Stack( - clipBehavior: Clip.none, - alignment: Alignment.center, - children: [ - Icon( - Icons.show_chart, - size: 22, - color: Colors.white, - ), - Icon( - Icons.hide_source, - size: 22, - color: Colors.white, - ), - ], - ), - onTap: () => plPlayerController.showDmTreandChart.value = - !plPlayerController.showDmTreandChart.value, - ), + () { + final list = videoDetailController.dmTrend.value?.dataOrNull; + if (list != null && list.isNotEmpty) { + return ComBtn( + width: widgetWidth, + height: 30, + icon: videoDetailController.showDmTreandChart.value + ? const Icon( + Icons.show_chart, + size: 22, + color: Colors.white, + ) + : const Stack( + clipBehavior: Clip.none, + alignment: Alignment.center, + children: [ + Icon( + Icons.show_chart, + size: 22, + color: Colors.white, + ), + Icon( + Icons.hide_source, + size: 22, + color: Colors.white, + ), + ], + ), + onTap: () => videoDetailController.showDmTreandChart.value = + !videoDetailController.showDmTreandChart.value, + ); + } + return const SizedBox.shrink(); + }, ), /// 超分辨率 @@ -385,7 +394,7 @@ class _PLVideoPlayerState extends State /// 分段信息 BottomControlType.viewPoints => Obx( - () => plPlayerController.viewPointList.isEmpty + () => videoDetailController.viewPointList.isEmpty ? const SizedBox.shrink() : ComBtn( width: widgetWidth, @@ -402,8 +411,8 @@ class _PLVideoPlayerState extends State onTap: widget.showViewPoints, onLongPress: () { Feedback.forLongPress(context); - plPlayerController.showVP.value = - !plPlayerController.showVP.value; + videoDetailController.showVP.value = + !videoDetailController.showVP.value; }, ), ), @@ -453,7 +462,7 @@ class _PLVideoPlayerState extends State bvid, IdUtils.bv2av(bvid), isSeason && isPart - ? widget.videoDetailController?.seasonCid ?? currentCid + ? videoDetailController.seasonCid ?? currentCid : currentCid, ); }, @@ -494,32 +503,32 @@ class _PLVideoPlayerState extends State /// 字幕 BottomControlType.subtitle => Obx( - () => widget.videoDetailController?.subtitles.isEmpty == true + () => videoDetailController.subtitles.isEmpty == true ? const SizedBox.shrink() : PopupMenuButton( tooltip: '选择字幕', requestFocus: false, - initialValue: widget - .videoDetailController! - .vttSubtitlesIndex - .value - .clamp(0, widget.videoDetailController!.subtitles.length), + initialValue: videoDetailController.vttSubtitlesIndex.value + .clamp( + 0, + videoDetailController.subtitles.length, + ), color: Colors.black.withValues(alpha: 0.8), itemBuilder: (context) { return [ PopupMenuItem( value: 0, - onTap: () => widget.videoDetailController!.setSubtitle(0), + onTap: () => videoDetailController.setSubtitle(0), child: const Text( "关闭字幕", style: TextStyle(color: Colors.white), ), ), - ...widget.videoDetailController!.subtitles.indexed.map((e) { + ...videoDetailController.subtitles.indexed.map((e) { return PopupMenuItem( value: e.$1 + 1, onTap: () => - widget.videoDetailController!.setSubtitle(e.$1 + 1), + videoDetailController.setSubtitle(e.$1 + 1), child: Text( "${e.$2.lanDoc}", style: const TextStyle(color: Colors.white), @@ -531,8 +540,7 @@ class _PLVideoPlayerState extends State child: SizedBox( width: widgetWidth, height: 30, - child: - widget.videoDetailController!.vttSubtitlesIndex.value == 0 + child: videoDetailController.vttSubtitlesIndex.value == 0 ? const Icon( Icons.closed_caption_off_outlined, size: 22, @@ -584,10 +592,9 @@ class _PLVideoPlayerState extends State BottomControlType.qa => Obx( () { - final videoDetailCtr = widget.videoDetailController!; final VideoQuality currentVideoQa = - videoDetailCtr.currentVideoQa.value; - final PlayUrlModel videoInfo = videoDetailCtr.data; + videoDetailController.currentVideoQa.value; + final PlayUrlModel videoInfo = videoDetailController.data; if (videoInfo.dash == null) { return const SizedBox.shrink(); } @@ -625,7 +632,7 @@ class _PLVideoPlayerState extends State } final int quality = item.quality!; final newQa = VideoQuality.fromCode(quality); - videoDetailCtr + videoDetailController ..currentVideoQa.value = newQa ..updatePlayer(); @@ -697,9 +704,9 @@ class _PLVideoPlayerState extends State ]; List userSpecifyItemRight = [ - BottomControlType.dmChart, + if (plPlayerController.showDmChart) BottomControlType.dmChart, if (plPlayerController.isAnim) BottomControlType.superResolution, - BottomControlType.viewPoints, + if (plPlayerController.showViewPoints) BottomControlType.viewPoints, if (anySeason) BottomControlType.episode, if (isFullScreen) BottomControlType.fit, BottomControlType.subtitle, @@ -1264,8 +1271,11 @@ class _PLVideoPlayerState extends State maxWidth: maxWidth, isFullScreen: isFullScreen, controller: plPlayerController, - buildBottomControl: () => - buildBottomControl(maxWidth > maxHeight), + videoDetailController: videoDetailController, + buildBottomControl: () => buildBottomControl( + videoDetailController, + maxWidth > maxHeight, + ), ), ), ], @@ -1394,7 +1404,8 @@ class _PLVideoPlayerState extends State ); }), ), - if (plPlayerController.segmentList.isNotEmpty) + if (plPlayerController.enableSponsorBlock && + videoDetailController.segmentProgressList.isNotEmpty) Positioned( left: 0, right: 0, @@ -1405,14 +1416,16 @@ class _PLVideoPlayerState extends State key: const Key('segmentList'), size: const Size(double.infinity, 3.5), painter: SegmentProgressBar( - segmentColors: plPlayerController.segmentList, + segmentColors: + videoDetailController.segmentProgressList, ), ), ), ), ), - if (plPlayerController.viewPointList.isNotEmpty && - plPlayerController.showVP.value) ...[ + if (plPlayerController.showViewPoints && + videoDetailController.viewPointList.isNotEmpty && + videoDetailController.showVP.value) ...[ Positioned( left: 0, right: 0, @@ -1423,7 +1436,8 @@ class _PLVideoPlayerState extends State key: const Key('viewPointList'), size: const Size(double.infinity, 3.5), painter: SegmentProgressBar( - segmentColors: plPlayerController.viewPointList, + segmentColors: + videoDetailController.viewPointList, ), ), ), @@ -1431,14 +1445,17 @@ class _PLVideoPlayerState extends State ), if (isMobile) buildViewPointWidget( + videoDetailController, plPlayerController, 4.25, maxWidth, ), ], - if (plPlayerController.dmTrend.isNotEmpty && - plPlayerController.showDmTreandChart.value) - buildDmChart(theme, plPlayerController), + if (plPlayerController.showDmChart && + videoDetailController.showDmTreandChart.value) + if (videoDetailController.dmTrend.value?.dataOrNull + case final list?) + buildDmChart(theme, list, videoDetailController), ], ); }, @@ -1719,10 +1736,11 @@ class _PLVideoPlayerState extends State ); Future screenshotWebp() async { - final videoCtr = widget.videoDetailController!; - final videoInfo = videoCtr.data; + final videoInfo = videoDetailController.data; final ids = videoInfo.dash!.video!.map((i) => i.id!).toSet(); - final video = videoCtr.findVideoByQa(ids.reduce((p, n) => p < n ? p : n)); + final video = videoDetailController.findVideoByQa( + ids.reduce((p, n) => p < n ? p : n), + ); VideoQuality qa = video.quality; String? url = video.baseUrl; @@ -1760,7 +1778,7 @@ class _PLVideoPlayerState extends State title: '选择画质', initialValue: qa.code, onSelected: (value) { - final video = videoCtr.findVideoByQa(value); + final video = videoDetailController.findVideoByQa(value); url = video.baseUrl; qa = video.quality; return false; @@ -1859,7 +1877,8 @@ class _PLVideoPlayerState extends State Widget buildDmChart( ThemeData theme, - PlPlayerController plPlayerController, [ + List dmTrend, + VideoDetailController videoDetailController, [ double offset = 0, ]) { final color = theme.colorScheme.primary; @@ -1868,8 +1887,8 @@ Widget buildDmChart( height: 12, margin: EdgeInsets.only( bottom: - plPlayerController.viewPointList.isNotEmpty && - plPlayerController.showVP.value + videoDetailController.viewPointList.isNotEmpty && + videoDetailController.showVP.value ? 20.25 + offset : 4.25 + offset, ), @@ -1880,18 +1899,16 @@ Widget buildDmChart( gridData: const FlGridData(show: false), borderData: FlBorderData(show: false), minX: 0, - maxX: (plPlayerController.dmTrend.length - 1).toDouble(), + maxX: (dmTrend.length - 1).toDouble(), minY: 0, - maxY: plPlayerController.dmTrend - .reduce((a, b) => a > b ? a : b) - .toDouble(), + maxY: dmTrend.reduce((a, b) => a > b ? a : b).toDouble(), lineBarsData: [ LineChartBarData( spots: List.generate( - plPlayerController.dmTrend.length, + dmTrend.length, (index) => FlSpot( index.toDouble(), - plPlayerController.dmTrend[index], + dmTrend[index], ), ), isCurved: true, @@ -2172,6 +2189,7 @@ class _CroppedImagePainter extends CustomPainter { } Widget buildViewPointWidget( + VideoDetailController videoDetailController, PlPlayerController plPlayerController, double offset, double maxWidth, @@ -2184,7 +2202,7 @@ Widget buildViewPointWidget( onPointerDown: (event) { try { double seg = event.localPosition.dx / maxWidth; - Segment item = plPlayerController.viewPointList + Segment item = videoDetailController.viewPointList .where((item) => item.start >= seg) .reduce((a, b) => a.start < b.start ? a : b); if (item.from != null) { diff --git a/lib/plugin/pl_player/widgets/bottom_control.dart b/lib/plugin/pl_player/widgets/bottom_control.dart index 8e408974..ce0ffc89 100644 --- a/lib/plugin/pl_player/widgets/bottom_control.dart +++ b/lib/plugin/pl_player/widgets/bottom_control.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:PiliPlus/common/widgets/progress_bar/audio_video_progress_bar.dart'; import 'package:PiliPlus/common/widgets/progress_bar/segment_progress_bar.dart'; +import 'package:PiliPlus/pages/video/controller.dart'; import 'package:PiliPlus/plugin/pl_player/controller.dart'; import 'package:PiliPlus/plugin/pl_player/view.dart'; import 'package:PiliPlus/utils/feed_back.dart'; @@ -17,12 +18,14 @@ class BottomControl extends StatelessWidget { required this.isFullScreen, required this.controller, required this.buildBottomControl, + required this.videoDetailController, }); final double maxWidth; final bool isFullScreen; final PlPlayerController controller; final Widget Function() buildBottomControl; + final VideoDetailController videoDetailController; @override Widget build(BuildContext context) { @@ -107,7 +110,8 @@ class BottomControl extends StatelessWidget { }, ); }), - if (controller.segmentList.isNotEmpty) + if (controller.enableSponsorBlock && + videoDetailController.segmentProgressList.isNotEmpty) Positioned( left: 0, right: 0, @@ -118,14 +122,16 @@ class BottomControl extends StatelessWidget { key: const Key('segmentList'), size: const Size(double.infinity, 3.5), painter: SegmentProgressBar( - segmentColors: controller.segmentList, + segmentColors: + videoDetailController.segmentProgressList, ), ), ), ), ), - if (controller.viewPointList.isNotEmpty && - controller.showVP.value) ...[ + if (controller.showViewPoints && + videoDetailController.viewPointList.isNotEmpty && + videoDetailController.showVP.value) ...[ Positioned( left: 0, right: 0, @@ -136,18 +142,26 @@ class BottomControl extends StatelessWidget { key: const Key('viewPointList'), size: const Size(double.infinity, 3.5), painter: SegmentProgressBar( - segmentColors: controller.viewPointList, + segmentColors: + videoDetailController.viewPointList, ), ), ), ), ), if (!Utils.isMobile) - buildViewPointWidget(controller, 8.75, maxWidth - 40), + buildViewPointWidget( + videoDetailController, + controller, + 8.75, + maxWidth - 40, + ), ], - if (controller.dmTrend.isNotEmpty && - controller.showDmTreandChart.value) - buildDmChart(theme, controller, 4.5), + if (controller.showDmChart && + videoDetailController.showDmTreandChart.value) + if (videoDetailController.dmTrend.value?.dataOrNull + case final list?) + buildDmChart(theme, list, videoDetailController, 4.5), ], ), ),