diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index d8b7fe43..597030ed 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -54,6 +54,8 @@ class VideoDetailController extends GetxController RxBool autoPlay = true.obs; // 视频资源是否有效 RxBool isEffective = true.obs; + // 封面图的展示 + RxBool isShowCover = true.obs; @override void onInit() { @@ -74,7 +76,7 @@ class VideoDetailController extends GetxController heroTag = Get.arguments['heroTag']; } tabCtr = TabController(length: 2, vsync: this); - queryVideoUrl(); + // queryVideoUrl(); } showReplyReplyPanel() { @@ -119,9 +121,9 @@ class VideoDetailController extends GetxController playerInit(firstVideo, audioUrl, defaultST: position); } - playerInit(firstVideo, audioSource, + Future playerInit(firstVideo, audioSource, {Duration defaultST = Duration.zero, int duration = 0}) async { - plPlayerController.setDataSource( + await plPlayerController.setDataSource( DataSource( videoSource: firstVideo.baseUrl, audioSource: audioSource, @@ -149,7 +151,7 @@ class VideoDetailController extends GetxController } // 视频链接 - queryVideoUrl() async { + Future queryVideoUrl() async { var result = await VideoHttp.videoUrl(cid: cid, bvid: bvid); if (result['status']) { data = result['data']; @@ -168,7 +170,7 @@ class VideoDetailController extends GetxController if (firstAudio.id != null) { currentAudioQa = AudioQualityCode.fromCode(firstAudio.id!)!; } - playerInit( + await playerInit( firstVideo, audioUrl, defaultST: Duration(milliseconds: data.lastPlayTime!), diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index 3058282e..7325cfd0 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -35,12 +35,13 @@ class _VideoDetailPageState extends State late StreamController appbarStream; PlayerStatus playerStatus = PlayerStatus.playing; - bool isShowCover = true; + // bool isShowCover = true; double doubleOffset = 0; Box localCache = GStrorage.localCache; late double statusBarHeight; final videoHeight = Get.size.width * 9 / 16; + late Future _futureBuilderFuture; @override void initState() { @@ -51,12 +52,10 @@ class _VideoDetailPageState extends State videoDetailController.markHeartBeat(); playerStatus = status; if (status == PlayerStatus.playing) { - isShowCover = false; - setState(() {}); + videoDetailController.isShowCover.value = false; videoDetailController.loopHeartBeat(); } else { videoDetailController.timer!.cancel(); - // setState(() {}); // 播放完成停止 or 切换下一个 if (status == PlayerStatus.completed) { // 当只有1p或多p未打开自动播放时,播放完成还原进度条,展示控制栏 @@ -78,6 +77,7 @@ class _VideoDetailPageState extends State ); statusBarHeight = localCache.get('statusBarHeight'); + _futureBuilderFuture = videoDetailController.queryVideoUrl(); } void continuePlay() async { @@ -165,60 +165,98 @@ class _VideoDetailPageState extends State tag: videoDetailController.heroTag, child: Stack( children: [ - if (plPlayerController! - .videoPlayerController != - null) - PLVideoPlayer( - controller: plPlayerController!, - headerControl: HeaderControl( - controller: plPlayerController, - videoDetailCtr: videoDetailController, - ), - ), - Visibility( - visible: isShowCover, - child: Positioned( - top: 0, - left: 0, - right: 0, - child: NetworkImgLayer( - type: 'emote', - src: videoDetailController - .videoItem['pic'], - width: maxWidth, - height: maxHeight, + FutureBuilder( + future: _futureBuilderFuture, + builder: ((context, snapshot) { + if (snapshot.hasData && + snapshot.data['status']) { + return PLVideoPlayer( + controller: plPlayerController!, + headerControl: HeaderControl( + controller: plPlayerController, + videoDetailCtr: + videoDetailController, + ), + ); + } else { + return const SizedBox(); + } + }), + ), + Obx( + () => Visibility( + visible: videoDetailController + .isShowCover.value, + child: Positioned( + top: 0, + left: 0, + right: 0, + child: NetworkImgLayer( + type: 'emote', + src: videoDetailController + .videoItem['pic'], + width: maxWidth, + height: maxHeight, + ), ), ), ), /// 关闭自动播放时 手动播放 - Visibility( - visible: isShowCover && - videoDetailController - .isEffective.value && - !videoDetailController.autoPlay.value, - child: Positioned( - right: 12, - bottom: 6, - child: TextButton.icon( - style: ButtonStyle( - backgroundColor: - MaterialStateProperty.resolveWith( - (states) { - return Theme.of(context) - .colorScheme - .primaryContainer; - }), - ), - onPressed: () => - videoDetailController.handlePlay(), - icon: const Icon( - Icons.play_circle_outline, - size: 20, - ), - label: const Text('Play'), - ), - ), + Obx( + () => Visibility( + visible: videoDetailController + .isShowCover.value && + videoDetailController + .isEffective.value && + !videoDetailController + .autoPlay.value, + child: Stack( + children: [ + Positioned( + top: 0, + left: 0, + right: 0, + child: AppBar( + primary: false, + backgroundColor: + Colors.transparent, + actions: [ + /// TODO + IconButton( + tooltip: '稍后再看', + onPressed: () {}, + icon: const Icon(Icons + .history_outlined)) + ], + ), + ), + Positioned( + right: 12, + bottom: 6, + child: TextButton.icon( + style: ButtonStyle( + backgroundColor: + MaterialStateProperty + .resolveWith( + (states) { + return Theme.of(context) + .colorScheme + .primaryContainer; + }), + ), + onPressed: () => + videoDetailController + .handlePlay(), + icon: const Icon( + Icons.play_circle_outline, + size: 20, + ), + label: const Text('Play'), + ), + ), + ], + )), ), ], ),