diff --git a/lib/pages/video/reply/view.dart b/lib/pages/video/reply/view.dart index f62813433..b2b5b677c 100644 --- a/lib/pages/video/reply/view.dart +++ b/lib/pages/video/reply/view.dart @@ -10,6 +10,7 @@ import 'package:PiliPlus/pages/video/reply/widgets/reply_item_grpc.dart'; import 'package:PiliPlus/pages/video/reply_reply/view.dart'; import 'package:PiliPlus/utils/feed_back.dart'; import 'package:easy_debounce/easy_throttle.dart'; +import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:get/get.dart'; @@ -92,7 +93,7 @@ class _VideoReplyPanelState extends State Widget build(BuildContext context) { super.build(context); final theme = Theme.of(context); - return refreshIndicator( + final child = refreshIndicator( onRefresh: _videoReplyController.onRefresh, child: Stack( clipBehavior: Clip.none, @@ -182,6 +183,13 @@ class _VideoReplyPanelState extends State ], ), ); + if (widget.isNested) { + return ExtendedVisibilityDetector( + uniqueKey: const Key('reply-list'), + child: child, + ); + } + return child; } Widget _buildBody( diff --git a/lib/pages/video/view.dart b/lib/pages/video/view.dart index 8034e4ee3..28c9e48a7 100644 --- a/lib/pages/video/view.dart +++ b/lib/pages/video/view.dart @@ -946,7 +946,11 @@ class _VideoDetailPageVState extends State child: videoTabBarView( controller: videoDetailController.tabCtr, children: [ - videoIntro(isHorizontal: false, needCtr: false), + videoIntro( + isHorizontal: false, + needCtr: false, + isNested: true, + ), if (videoDetailController.showReply) videoReplyPanel(isNested: true), if (_shouldShowSeasonPanel) seasonPanel, @@ -1815,65 +1819,77 @@ class _VideoDetailPageVState extends State bool? isHorizontal, bool needRelated = true, bool needCtr = true, + bool isNested = false, }) { final bottom = MediaQuery.viewPaddingOf(context).bottom; Widget introPanel() => KeepAliveWrapper( - builder: (context) => CustomScrollView( - controller: needCtr ? introScrollController : null, - physics: !needCtr - ? const AlwaysScrollableScrollPhysics( - parent: ClampingScrollPhysics(), - ) - : null, - slivers: [ - if (videoDetailController.isUgc) ...[ - UgcIntroPanel( - key: videoIntroKey, - heroTag: heroTag, - showAiBottomSheet: showAiBottomSheet, - showEpisodes: showEpisodes, - onShowMemberPage: onShowMemberPage, - isPortrait: isPortrait, - isHorizontal: isHorizontal ?? width! > height! * 1.25, - ), - if (needRelated && - videoDetailController.plPlayerController.showRelatedVideo) ...[ - SliverToBoxAdapter( - child: Padding( - padding: const EdgeInsets.only(top: StyleString.safeSpace), - child: Divider( - height: 1, - indent: 12, - endIndent: 12, - color: themeData.colorScheme.outline.withValues( - alpha: 0.08, + builder: (context) { + final child = CustomScrollView( + controller: needCtr ? introScrollController : null, + physics: !needCtr + ? const AlwaysScrollableScrollPhysics( + parent: ClampingScrollPhysics(), + ) + : null, + slivers: [ + if (videoDetailController.isUgc) ...[ + UgcIntroPanel( + key: videoIntroKey, + heroTag: heroTag, + showAiBottomSheet: showAiBottomSheet, + showEpisodes: showEpisodes, + onShowMemberPage: onShowMemberPage, + isPortrait: isPortrait, + isHorizontal: isHorizontal ?? width! > height! * 1.25, + ), + if (needRelated && + videoDetailController + .plPlayerController + .showRelatedVideo) ...[ + SliverToBoxAdapter( + child: Padding( + padding: const EdgeInsets.only(top: StyleString.safeSpace), + child: Divider( + height: 1, + indent: 12, + endIndent: 12, + color: themeData.colorScheme.outline.withValues( + alpha: 0.08, + ), ), ), ), + RelatedVideoPanel(key: videoRelatedKey, heroTag: heroTag), + ], + ] else + PgcIntroPage( + key: videoIntroKey, + heroTag: heroTag, + cid: videoDetailController.cid.value, + showEpisodes: showEpisodes, + showIntroDetail: showIntroDetail, + maxWidth: width ?? maxWidth, + isLandscape: !isPortrait, + ), + SliverToBoxAdapter( + child: SizedBox( + height: + (videoDetailController.isPlayAll && !isPortrait + ? 80 + : StyleString.safeSpace) + + bottom, ), - RelatedVideoPanel(key: videoRelatedKey, heroTag: heroTag), - ], - ] else - PgcIntroPage( - key: videoIntroKey, - heroTag: heroTag, - cid: videoDetailController.cid.value, - showEpisodes: showEpisodes, - showIntroDetail: showIntroDetail, - maxWidth: width ?? maxWidth, - isLandscape: !isPortrait, ), - SliverToBoxAdapter( - child: SizedBox( - height: - (videoDetailController.isPlayAll && !isPortrait - ? 80 - : StyleString.safeSpace) + - bottom, - ), - ), - ], - ), + ], + ); + if (isNested) { + return ExtendedVisibilityDetector( + uniqueKey: const Key('intro-panel'), + child: child, + ); + } + return child; + }, ); if (videoDetailController.isPlayAll) { return Stack(