diff --git a/lib/common/widgets/video_card_v.dart b/lib/common/widgets/video_card_v.dart index dc876136..9e0182f0 100644 --- a/lib/common/widgets/video_card_v.dart +++ b/lib/common/widgets/video_card_v.dart @@ -1,3 +1,4 @@ +import 'package:PiliPalaX/http/search.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; @@ -78,7 +79,11 @@ class VideoCardV extends StatelessWidget { break; case 'av': String bvid = videoItem.bvid ?? IdUtils.av2bv(videoItem.aid); - Get.toNamed('/video?bvid=$bvid&cid=${videoItem.cid}', arguments: { + int cid = videoItem.cid; + if (cid == -1) { + cid = await SearchHttp.ab2c(aid: videoItem.aid, bvid: bvid); + } + Get.toNamed('/video?bvid=$bvid&cid=$cid', arguments: { // 'videoItem': videoItem, 'pic': videoItem.pic, 'heroTag': heroTag, diff --git a/lib/models/home/rcmd/result.dart b/lib/models/home/rcmd/result.dart index a5eb7ee9..df51a49b 100644 --- a/lib/models/home/rcmd/result.dart +++ b/lib/models/home/rcmd/result.dart @@ -55,7 +55,7 @@ class RecVideoItemAppModel { id = json['player_args'] != null ? json['player_args']['aid'] : int.parse(json['param'] ?? '-1'); - aid = json['player_args'] != null ? json['player_args']['aid'] : -1; + aid = id; bvid = json['bvid'] ?? (json['player_args'] != null ? IdUtils.av2bv(json['player_args']['aid']) diff --git a/lib/pages/common/reply_controller.dart b/lib/pages/common/reply_controller.dart index 656aa86e..32c89b38 100644 --- a/lib/pages/common/reply_controller.dart +++ b/lib/pages/common/reply_controller.dart @@ -92,12 +92,16 @@ abstract class ReplyController extends CommonController { if (response.response.upper.top != null) { final bool flag = response.response.topReplies.any( (ReplyItemModel reply) => - reply.rpid == response.response.upper.top.rpid) as bool; - if (!flag) { + reply.rpid != response.response.upper.top.rpid) as bool; + if (flag) { replies.insert(0, response.response.upper.top); + hasUpTop = true; } } - replies.insertAll(0, response.response.topReplies); + if (response.response.topReplies != null) { + replies.insertAll(0, response.response.topReplies); + hasUpTop = true; + } } else if (loadingState.value is Success) { replies.insertAll(0, (loadingState.value as Success).response.replies); } diff --git a/lib/pages/danmaku/view.dart b/lib/pages/danmaku/view.dart index 30826165..d4af115b 100644 --- a/lib/pages/danmaku/view.dart +++ b/lib/pages/danmaku/view.dart @@ -25,7 +25,7 @@ class PlDanmaku extends StatefulWidget { State createState() => _PlDanmakuState(); } -class _PlDanmakuState extends State with WidgetsBindingObserver { +class _PlDanmakuState extends State { late PlPlayerController playerController; late PlDanmakuController _plDanmakuController; DanmakuController? _controller; @@ -41,23 +41,11 @@ class _PlDanmakuState extends State with WidgetsBindingObserver { // late double strokeWidth; // late int fontWeight; int latestAddedPosition = -1; - bool showDanmaku = true; bool? _isFullScreen; - @override - void didChangeAppLifecycleState(AppLifecycleState state) { - if (state == AppLifecycleState.resumed) { - showDanmaku = true; - } else if (state == AppLifecycleState.paused) { - showDanmaku = false; - _controller?.clear(); - } - } - @override void initState() { super.initState(); - WidgetsBinding.instance.addObserver(this); enableShowDanmaku = setting.get(SettingBoxKey.enableShowDanmaku, defaultValue: true); _plDanmakuController = PlDanmakuController( @@ -129,7 +117,7 @@ class _PlDanmakuState extends State with WidgetsBindingObserver { List? currentDanmakuList = _plDanmakuController.getCurrentDanmaku(currentPosition); - if (showDanmaku && + if (playerController.showDanmaku && playerController.playerStatus.status.value == PlayerStatus.playing && currentDanmakuList != null && _controller != null) { @@ -150,7 +138,6 @@ class _PlDanmakuState extends State with WidgetsBindingObserver { @override void dispose() { - WidgetsBinding.instance.removeObserver(this); playerController.removePositionListener(videoPositionListen); playerController.removeStatusLister(playerListener); _plDanmakuController.dispose(); diff --git a/lib/pages/setting/sponsor_block_page.dart b/lib/pages/setting/sponsor_block_page.dart index 99d87785..0ab54802 100644 --- a/lib/pages/setting/sponsor_block_page.dart +++ b/lib/pages/setting/sponsor_block_page.dart @@ -22,7 +22,7 @@ class SponsorBlockPage extends StatefulWidget { } class _SponsorBlockPageState extends State { - final _url = 'https://github.com/hanydd/BilibiliSponsorBlock'; + static const _url = 'https://github.com/hanydd/BilibiliSponsorBlock'; final _textController = TextEditingController(); late double _blockLimit; late List> _blockSettings; @@ -78,7 +78,7 @@ class _SponsorBlockPageState extends State { setState(() { _serverStatus = res.statusCode == 200 && res.data is String && - (double.tryParse(res.data) ?? int.tryParse(res.data)) != null; + Utils.isStringNumeric(res.data); }); }); } diff --git a/lib/pages/video/detail/introduction/controller.dart b/lib/pages/video/detail/introduction/controller.dart index 93790339..ce53ca09 100644 --- a/lib/pages/video/detail/introduction/controller.dart +++ b/lib/pages/video/detail/introduction/controller.dart @@ -74,7 +74,6 @@ class VideoIntroController extends GetxController bool isShowOnlineTotal = false; RxString total = '1'.obs; Timer? timer; - bool isPaused = false; String heroTag = ''; late ModelResult modelResult; Rx> queryVideoIntroData = @@ -574,11 +573,8 @@ class VideoIntroController extends GetxController void startTimer() { if (isShowOnlineTotal) { queryOnlineTotal(); - const duration = Duration(seconds: 10); // 设置定时器间隔为10秒 - timer ??= Timer.periodic(duration, (Timer timer) { - if (!isPaused) { - queryOnlineTotal(); // 定时器回调函数,发起请求 - } + timer ??= Timer.periodic(const Duration(seconds: 10), (Timer timer) { + queryOnlineTotal(); }); } } @@ -606,9 +602,7 @@ class VideoIntroController extends GetxController @override void onClose() { - if (timer != null) { - timer!.cancel(); // 销毁页面时取消定时器 - } + canelTimer(); super.onClose(); } diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index 75585e7f..8076b556 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -54,7 +54,7 @@ class VideoDetailPage extends StatefulWidget { } class _VideoDetailPageState extends State - with TickerProviderStateMixin, RouteAware { + with TickerProviderStateMixin, RouteAware, WidgetsBindingObserver { late VideoDetailController videoDetailController; late VideoReplyController _videoReplyController; PlPlayerController? plPlayerController; @@ -170,6 +170,7 @@ class _VideoDetailPageState extends State // : context.width * 9 / 16), // end: 0, // ).animate(_animationController); + WidgetsBinding.instance.addObserver(this); } // 获取视频资源,初始化播放器 @@ -183,6 +184,17 @@ class _VideoDetailPageState extends State } } + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + if (state == AppLifecycleState.resumed) { + videoIntroController.startTimer(); + videoDetailController.plPlayerController.showDanmaku = true; + } else if (state == AppLifecycleState.paused) { + videoIntroController.canelTimer(); + videoDetailController.plPlayerController.showDanmaku = false; + } + } + void playCallBack() { plPlayerController?.play(); } @@ -241,7 +253,8 @@ class _VideoDetailPageState extends State Future handlePlay() async { if (videoDetailController.videoUrl == null || videoDetailController.audioUrl == null) { - SmartDialog.showToast('not initialized'); + // SmartDialog.showToast('not initialized'); + debugPrint('not initialized'); return; } plPlayerController = videoDetailController.plPlayerController; @@ -275,6 +288,7 @@ class _VideoDetailPageState extends State @override void dispose() { + WidgetsBinding.instance.removeObserver(this); if (!Get.previousRoute.startsWith('/video')) { ScreenBrightness().resetApplicationScreenBrightness(); PlPlayerController.setPlayCallBack(null); @@ -325,7 +339,6 @@ class _VideoDetailPageState extends State } if (plPlayerController != null) { videoDetailController.defaultST = plPlayerController!.position.value; - videoIntroController.isPaused = true; plPlayerController!.removeStatusLister(playerListener); plPlayerController!.pause(); } @@ -369,7 +382,6 @@ class _VideoDetailPageState extends State // } /// 未开启自动播放时,未播放跳转下一页返回/播放后跳转下一页返回 - videoIntroController.isPaused = false; // if (autoplay) { // // await Future.delayed(const Duration(milliseconds: 300)); // debugPrint(plPlayerController); diff --git a/lib/plugin/pl_player/controller.dart b/lib/plugin/pl_player/controller.dart index 28baedc9..91df8e75 100644 --- a/lib/plugin/pl_player/controller.dart +++ b/lib/plugin/pl_player/controller.dart @@ -243,6 +243,7 @@ class PlPlayerController { ValueNotifier([]); // 关联弹幕控制器 DanmakuController? danmakuController; + bool showDanmaku = true; // 弹幕相关配置 late List blockTypes; late double showArea; @@ -1243,7 +1244,10 @@ class PlPlayerController { // 记录播放记录 Future makeHeartBeat(int progress, {type = 'playing'}) async { - if (!_enableHeart || MineController.anonymity) { + if (!_enableHeart || + MineController.anonymity || + progress == 0 || + playerStatus.status.value == PlayerStatus.paused) { return false; } if (videoType.value == 'live') { @@ -1252,6 +1256,7 @@ class PlPlayerController { bool isComplete = playerStatus.status.value == PlayerStatus.completed || type == 'completed'; // 播放状态变化时,更新 + if (type == 'status' || type == 'completed') { await VideoHttp.heartBeat( bvid: _bvid, @@ -1261,7 +1266,7 @@ class PlPlayerController { return; } // 正常播放时,间隔5秒更新一次 - if (progress - _heartDuration >= 5) { + else if (progress - _heartDuration >= 5) { _heartDuration = progress; await VideoHttp.heartBeat( bvid: _bvid, @@ -1335,9 +1340,9 @@ class PlPlayerController { Future refreshSubtitles() async { _vttSubtitles.clear(); Map res = await VideoHttp.subtitlesJson(bvid: _bvid, cid: _cid); - if (!res["status"]) { - SmartDialog.showToast('查询字幕错误,${res["msg"]}'); - } + // if (!res["status"]) { + // SmartDialog.showToast('查询字幕错误,${res["msg"]}'); + // } if (res["data"].length == 0) { return; }