From 0c207381f37aaea1ffa6569d1c8f63386dc5268b Mon Sep 17 00:00:00 2001 From: dom Date: Sat, 9 May 2026 22:22:03 +0800 Subject: [PATCH] prefetch fav video intro Signed-off-by: dom --- lib/pages/common/common_intro_controller.dart | 6 +- lib/pages/fav_detail/controller.dart | 23 +++- lib/pages/fav_search/controller.dart | 47 +++++--- .../video/introduction/ugc/controller.dart | 104 +++++++++++------- 4 files changed, 116 insertions(+), 64 deletions(-) diff --git a/lib/pages/common/common_intro_controller.dart b/lib/pages/common/common_intro_controller.dart index 8373459ce..2b092f0d5 100644 --- a/lib/pages/common/common_intro_controller.dart +++ b/lib/pages/common/common_intro_controller.dart @@ -80,10 +80,14 @@ abstract class CommonIntroController extends GetxController cid = RxInt(args['cid']); hasLater.value = args['sourceType'] == SourceType.watchLater; - queryVideoIntro(); + initQueryVideoIntro(args); startTimer(); } + void initQueryVideoIntro(Map args) { + queryVideoIntro(); + } + void startTimer() { if (isShowOnlineTotal) { queryOnlineTotal(); diff --git a/lib/pages/fav_detail/controller.dart b/lib/pages/fav_detail/controller.dart index 7485e9c6f..5519969de 100644 --- a/lib/pages/fav_detail/controller.dart +++ b/lib/pages/fav_detail/controller.dart @@ -1,11 +1,14 @@ import 'package:PiliPlus/common/widgets/dialog/dialog.dart'; import 'package:PiliPlus/http/fav.dart'; import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/http/video.dart'; import 'package:PiliPlus/models/common/fav_order_type.dart'; import 'package:PiliPlus/models/common/video/source_type.dart'; import 'package:PiliPlus/models_new/fav/fav_detail/data.dart'; import 'package:PiliPlus/models_new/fav/fav_detail/media.dart'; import 'package:PiliPlus/models_new/fav/fav_folder/list.dart'; +import 'package:PiliPlus/models_new/video/video_detail/data.dart'; +import 'package:PiliPlus/models_new/video/video_detail/page.dart'; import 'package:PiliPlus/pages/common/common_list_controller.dart'; import 'package:PiliPlus/pages/common/multi_select/base.dart'; import 'package:PiliPlus/pages/common/multi_select/multi_select_controller.dart'; @@ -16,6 +19,7 @@ import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/storage.dart'; import 'package:PiliPlus/utils/storage_key.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; +import 'package:collection/collection.dart'; import 'package:flutter/widgets.dart' show Text, ValueChanged; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; @@ -211,16 +215,25 @@ class FavDetailController } @override - void onViewFav(FavDetailItemModel item, int? index) { - final folder = folderInfo.value; - // TODO: dimension + Future onViewFav(FavDetailItemModel item, int? index) async { + final cid = item.ugc!.firstCid!; + Part? part; + VideoDetailData? videoIntro; + final res = await VideoHttp.videoIntro(bvid: item.bvid!); + if (res case Success(:final response)) { + videoIntro = response; + part = response.pages?.firstWhereOrNull((e) => e.cid == cid); + } + late final folder = folderInfo.value; PageUtils.toVideoPage( bvid: item.bvid, - cid: item.ugc!.firstCid!, + cid: cid, cover: item.cover, title: item.title, + dimension: part?.dimension, extraArguments: isPlayAll.value ? { + 'videoIntro': videoIntro, 'sourceType': SourceType.fav, 'mediaId': folder.id, 'oid': item.id, @@ -230,7 +243,7 @@ class FavDetailController if (index != null) 'isContinuePlaying': index != 0, 'isOwner': isOwner, } - : null, + : {'videoIntro': videoIntro}, ); } } diff --git a/lib/pages/fav_search/controller.dart b/lib/pages/fav_search/controller.dart index b57c601da..b4d213daa 100644 --- a/lib/pages/fav_search/controller.dart +++ b/lib/pages/fav_search/controller.dart @@ -1,13 +1,17 @@ import 'package:PiliPlus/http/fav.dart'; import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/http/video.dart'; import 'package:PiliPlus/models/common/fav_order_type.dart'; import 'package:PiliPlus/models/common/video/source_type.dart'; import 'package:PiliPlus/models_new/fav/fav_detail/data.dart'; import 'package:PiliPlus/models_new/fav/fav_detail/media.dart'; +import 'package:PiliPlus/models_new/video/video_detail/data.dart'; +import 'package:PiliPlus/models_new/video/video_detail/page.dart' show Part; import 'package:PiliPlus/pages/common/multi_select/base.dart'; import 'package:PiliPlus/pages/common/search/common_search_controller.dart'; import 'package:PiliPlus/pages/fav_detail/controller.dart'; import 'package:PiliPlus/utils/page_utils.dart'; +import 'package:collection/collection.dart'; import 'package:get/get.dart'; class FavSearchController @@ -57,20 +61,31 @@ class FavSearchController } @override - // TODO: dimension - void onViewFav(FavDetailItemModel item, int? index) => PageUtils.toVideoPage( - bvid: item.bvid, - cid: item.ugc!.firstCid!, - cover: item.cover, - title: item.title, - extraArguments: { - 'sourceType': SourceType.fav, - 'mediaId': mediaId, - 'oid': item.id, - 'favTitle': title, - 'count': count, - 'desc': true, - 'isContinuePlaying': true, - }, - ); + Future onViewFav(FavDetailItemModel item, int? index) async { + final cid = item.ugc!.firstCid!; + Part? part; + VideoDetailData? videoIntro; + final res = await VideoHttp.videoIntro(bvid: item.bvid!); + if (res case Success(:final response)) { + videoIntro = response; + part = response.pages?.firstWhereOrNull((e) => e.cid == cid); + } + PageUtils.toVideoPage( + bvid: item.bvid, + cid: item.ugc!.firstCid!, + cover: item.cover, + title: item.title, + dimension: part?.dimension, + extraArguments: { + 'videoIntro': videoIntro, + 'sourceType': SourceType.fav, + 'mediaId': mediaId, + 'oid': item.id, + 'favTitle': title, + 'count': count, + 'desc': true, + 'isContinuePlaying': true, + }, + ); + } } diff --git a/lib/pages/video/introduction/ugc/controller.dart b/lib/pages/video/introduction/ugc/controller.dart index eb1257e1a..265a4ae8a 100644 --- a/lib/pages/video/introduction/ugc/controller.dart +++ b/lib/pages/video/introduction/ugc/controller.dart @@ -15,6 +15,7 @@ import 'package:PiliPlus/models/common/video/source_type.dart'; import 'package:PiliPlus/models_new/member_card_info/data.dart'; import 'package:PiliPlus/models_new/relation/data.dart'; import 'package:PiliPlus/models_new/video/video_ai_conclusion/model_result.dart'; +import 'package:PiliPlus/models_new/video/video_detail/data.dart'; import 'package:PiliPlus/models_new/video/video_detail/dimension.dart'; import 'package:PiliPlus/models_new/video/video_detail/episode.dart'; import 'package:PiliPlus/models_new/video/video_detail/page.dart'; @@ -70,54 +71,28 @@ class UgcIntroController extends CommonIntroController with ReloadMixin { videoDetail.value.title = Get.arguments['title'] ?? ''; } + @override + void initQueryVideoIntro(Map args) { + if (args['videoIntro'] case final VideoDetailData videoIntro?) { + handleIntroRes(videoIntro); + queryVideoTags(); + if (isLogin) { + queryAllStatus(); + queryFollowStatus(); + } + } else { + queryVideoIntro(); + } + } + // 获取视频简介&分p @override Future queryVideoIntro() async { queryVideoTags(); + final res = await VideoHttp.videoIntro(bvid: bvid); if (res case Success(:final response)) { - if (response.redirectUrl != null && - videoDetailCtr.epId == null && - videoDetailCtr.seasonId == null) { - if (!isClosed) { - PageUtils.viewPgcFromUri(response.redirectUrl!, off: true); - } - return; - } - videoPlayerServiceHandler?.onVideoDetailChange( - response, - cid.value, - heroTag, - ); - if (videoDetail.value.ugcSeason?.id == response.ugcSeason?.id) { - // keep reversed season - response.ugcSeason = videoDetail.value.ugcSeason; - } - if (videoDetail.value.cid == response.cid) { - // keep reversed pages - response - ..pages = videoDetail.value.pages - ..isPageReversed = videoDetail.value.isPageReversed; - } - videoDetail.value = response; - try { - if (videoDetailCtr.cover.value.isEmpty || - (videoDetailCtr.videoUrl.isNullOrEmpty && - !videoDetailCtr.isQuerying)) { - videoDetailCtr.cover.value = response.pic ?? ''; - } - if (videoDetailCtr.showReply) { - try { - Get.find(tag: heroTag).count.value = - response.stat?.reply ?? 0; - } catch (_) {} - } - } catch (_) {} - final pages = videoDetail.value.pages; - if (pages != null && pages.isNotEmpty && cid.value == 0) { - cid.value = pages.first.cid!; - } - queryUserStat(response.staff); + handleIntroRes(response); } else { res.toast(); status.value = false; @@ -129,6 +104,51 @@ class UgcIntroController extends CommonIntroController with ReloadMixin { } } + void handleIntroRes(VideoDetailData response) { + if (response.redirectUrl != null && + videoDetailCtr.epId == null && + videoDetailCtr.seasonId == null) { + if (!isClosed) { + PageUtils.viewPgcFromUri(response.redirectUrl!, off: true); + } + return; + } + videoPlayerServiceHandler?.onVideoDetailChange( + response, + cid.value, + heroTag, + ); + if (videoDetail.value.ugcSeason?.id == response.ugcSeason?.id) { + // keep reversed season + response.ugcSeason = videoDetail.value.ugcSeason; + } + if (videoDetail.value.cid == response.cid) { + // keep reversed pages + response + ..pages = videoDetail.value.pages + ..isPageReversed = videoDetail.value.isPageReversed; + } + videoDetail.value = response; + try { + if (videoDetailCtr.cover.value.isEmpty || + (videoDetailCtr.videoUrl.isNullOrEmpty && + !videoDetailCtr.isQuerying)) { + videoDetailCtr.cover.value = response.pic ?? ''; + } + if (videoDetailCtr.showReply) { + try { + Get.find(tag: heroTag).count.value = + response.stat?.reply ?? 0; + } catch (_) {} + } + } catch (_) {} + final pages = videoDetail.value.pages; + if (pages != null && pages.isNotEmpty && cid.value == 0) { + cid.value = pages.first.cid!; + } + queryUserStat(response.staff); + } + // 获取up主粉丝数 Future queryUserStat(List? staff) async { if (staff != null && staff.isNotEmpty) {