diff --git a/lib/http/ua_type.dart b/lib/http/ua_type.dart index bf0ba9ba1..9af2f5a29 100644 --- a/lib/http/ua_type.dart +++ b/lib/http/ua_type.dart @@ -1,3 +1,5 @@ +import 'package:PiliPlus/utils/utils.dart'; + enum UaType { mob( 'Mozilla/5.0 (Linux; Android 10; SM-G975F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Mobile Safari/537.36', @@ -6,6 +8,8 @@ enum UaType { 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Safari/605.1.15', ); + static UaType get platformUA => Utils.isMobile ? mob : pc; + final String ua; const UaType(this.ua); } diff --git a/lib/pages/video/ai_conclusion/view.dart b/lib/pages/video/ai_conclusion/view.dart index 30266886f..e96806492 100644 --- a/lib/pages/video/ai_conclusion/view.dart +++ b/lib/pages/video/ai_conclusion/view.dart @@ -3,6 +3,7 @@ import 'package:PiliPlus/pages/common/slide/common_slide_page.dart'; import 'package:PiliPlus/pages/video/controller.dart'; import 'package:PiliPlus/pages/video/introduction/ugc/widgets/selectable_text.dart'; import 'package:PiliPlus/utils/duration_utils.dart'; +import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -53,16 +54,19 @@ class _AiDetailState extends State } late Key _key; + late bool _isNested; @override void didChangeDependencies() { super.didChangeDependencies(); - _key = ValueKey(PrimaryScrollController.of(context).hashCode); + final controller = PrimaryScrollController.of(context); + _isNested = controller is ExtendedNestedScrollController; + _key = ValueKey(controller.hashCode); } @override Widget buildList(ThemeData theme) { - return CustomScrollView( + final child = CustomScrollView( key: _key, physics: const AlwaysScrollableScrollPhysics(), slivers: [ @@ -158,5 +162,12 @@ class _AiDetailState extends State ), ], ); + if (_isNested) { + return ExtendedVisibilityDetector( + uniqueKey: const Key('ai-conclusion'), + child: child, + ); + } + return child; } } diff --git a/lib/pages/video/note/view.dart b/lib/pages/video/note/view.dart index 035bf49fa..67dda60c9 100644 --- a/lib/pages/video/note/view.dart +++ b/lib/pages/video/note/view.dart @@ -11,6 +11,7 @@ import 'package:PiliPlus/pages/video/note/controller.dart'; import 'package:PiliPlus/pages/webview/view.dart'; import 'package:PiliPlus/utils/accounts.dart'; import 'package:PiliPlus/utils/extension.dart'; +import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; @@ -89,81 +90,89 @@ class _NoteListPageState extends State } late Key _key; + late bool _isNested; @override void didChangeDependencies() { super.didChangeDependencies(); - _key = ValueKey(PrimaryScrollController.of(context).hashCode); + final controller = PrimaryScrollController.of(context); + _isNested = controller is ExtendedNestedScrollController; + _key = ValueKey(controller.hashCode); } @override Widget buildList(ThemeData theme) { - return refreshIndicator( + Widget child = refreshIndicator( onRefresh: _controller.onRefresh, - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Expanded( - child: CustomScrollView( - key: _key, - physics: const AlwaysScrollableScrollPhysics(), - slivers: [ - SliverPadding( - padding: const EdgeInsets.only(bottom: 100), - sliver: Obx( - () => _buildBody(theme, _controller.loadingState.value), - ), - ), - ], - ), - ), - Container( - padding: EdgeInsets.only( - left: 12, - right: 12, - top: 6, - bottom: MediaQuery.viewPaddingOf(context).bottom + 6, - ), - decoration: BoxDecoration( - color: theme.colorScheme.onInverseSurface, - border: Border( - top: BorderSide( - width: 0.5, - color: theme.colorScheme.outline.withValues(alpha: 0.1), - ), - ), - ), - child: Builder( - builder: (context) => FilledButton.tonal( - style: FilledButton.styleFrom( - tapTargetSize: MaterialTapTargetSize.shrinkWrap, - padding: EdgeInsets.zero, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(6)), - ), - ), - onPressed: () { - if (!Accounts.main.isLogin) { - SmartDialog.showToast('账号未登录'); - return; - } - Scaffold.of(context).showBottomSheet( - constraints: const BoxConstraints(), - (context) => WebviewPage( - oid: widget.oid, - title: widget.title, - url: - 'https://www.bilibili.com/h5/note-app?oid=${widget.oid}&pagefrom=ugcvideo&is_stein_gate=${widget.isStein ? 1 : 0}', - ), - ); - }, - child: const Text('开始记笔记'), - ), + child: CustomScrollView( + key: _key, + physics: const AlwaysScrollableScrollPhysics(), + slivers: [ + SliverPadding( + padding: const EdgeInsets.only(bottom: 100), + sliver: Obx( + () => _buildBody(theme, _controller.loadingState.value), ), ), ], ), ); + if (_isNested) { + child = ExtendedVisibilityDetector( + uniqueKey: const Key('note-list'), + child: child, + ); + } + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Expanded(child: child), + Container( + padding: EdgeInsets.only( + left: 12, + right: 12, + top: 6, + bottom: MediaQuery.viewPaddingOf(context).bottom + 6, + ), + decoration: BoxDecoration( + color: theme.colorScheme.onInverseSurface, + border: Border( + top: BorderSide( + width: 0.5, + color: theme.colorScheme.outline.withValues(alpha: 0.1), + ), + ), + ), + child: Builder( + builder: (context) => FilledButton.tonal( + style: FilledButton.styleFrom( + tapTargetSize: MaterialTapTargetSize.shrinkWrap, + padding: EdgeInsets.zero, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(6)), + ), + ), + onPressed: () { + if (!Accounts.main.isLogin) { + SmartDialog.showToast('账号未登录'); + return; + } + Scaffold.of(context).showBottomSheet( + constraints: const BoxConstraints(), + (context) => WebviewPage( + oid: widget.oid, + title: widget.title, + url: + 'https://www.bilibili.com/h5/note-app?oid=${widget.oid}&pagefrom=ugcvideo&is_stein_gate=${widget.isStein ? 1 : 0}', + ), + ); + }, + child: const Text('开始记笔记'), + ), + ), + ), + ], + ); } Widget _buildBody( diff --git a/lib/pages/video/post_panel/view.dart b/lib/pages/video/post_panel/view.dart index 9838f2a68..8271bf69c 100644 --- a/lib/pages/video/post_panel/view.dart +++ b/lib/pages/video/post_panel/view.dart @@ -17,6 +17,7 @@ import 'package:PiliPlus/utils/duration_utils.dart'; import 'package:PiliPlus/utils/extension.dart'; import 'package:PiliPlus/utils/storage_pref.dart'; import 'package:dio/dio.dart'; +import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart'; import 'package:flutter/foundation.dart' show kDebugMode; import 'package:flutter/material.dart'; import 'package:flutter/services.dart' show FilteringTextInputFormatter; @@ -239,11 +240,14 @@ class _PostPanelState extends State } late Key _key; + late bool _isNested; @override void didChangeDependencies() { super.didChangeDependencies(); - _key = ValueKey(PrimaryScrollController.of(context).hashCode); + final controller = PrimaryScrollController.of(context); + _isNested = controller is ExtendedNestedScrollController; + _key = ValueKey(controller.hashCode); } @override @@ -252,18 +256,25 @@ class _PostPanelState extends State return errorWidget(); } final bottom = MediaQuery.viewPaddingOf(context).bottom; + Widget child = ListView.builder( + key: _key, + physics: const AlwaysScrollableScrollPhysics(), + padding: EdgeInsets.only(bottom: 88 + bottom), + itemCount: list.length, + itemBuilder: (context, index) { + return _buildItem(theme, index, list[index]); + }, + ); + if (_isNested) { + child = ExtendedVisibilityDetector( + uniqueKey: const Key('post-panel'), + child: child, + ); + } return Stack( clipBehavior: Clip.none, children: [ - ListView.builder( - key: _key, - physics: const AlwaysScrollableScrollPhysics(), - padding: EdgeInsets.only(bottom: 88 + bottom), - itemCount: list.length, - itemBuilder: (context, index) { - return _buildItem(theme, index, list[index]); - }, - ), + child, Positioned( right: 16, bottom: 16 + bottom, diff --git a/lib/pages/video/reply_reply/view.dart b/lib/pages/video/reply_reply/view.dart index 03ef34977..19274a808 100644 --- a/lib/pages/video/reply_reply/view.dart +++ b/lib/pages/video/reply_reply/view.dart @@ -133,7 +133,7 @@ class _VideoReplyReplyPanelState extends State @override Widget buildList(ThemeData theme) { - return refreshIndicator( + final child = refreshIndicator( onRefresh: _controller.onRefresh, child: CustomScrollView( key: ValueKey(scrollController.hashCode), @@ -161,6 +161,13 @@ class _VideoReplyReplyPanelState extends State ], ), ); + if (widget.isNested) { + return ExtendedVisibilityDetector( + uniqueKey: Key(_tag), + child: child, + ); + } + return child; } Widget _header(ThemeData theme, ReplyInfo firstFloor) { diff --git a/lib/pages/video/view_point/view.dart b/lib/pages/video/view_point/view.dart index c2f29f0fb..a70017324 100644 --- a/lib/pages/video/view_point/view.dart +++ b/lib/pages/video/view_point/view.dart @@ -6,6 +6,7 @@ import 'package:PiliPlus/pages/common/slide/common_slide_page.dart'; import 'package:PiliPlus/pages/video/controller.dart'; import 'package:PiliPlus/plugin/pl_player/controller.dart'; import 'package:PiliPlus/utils/duration_utils.dart'; +import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -78,16 +79,19 @@ class _ViewPointsPageState extends State } late Key _key; + late bool _isNested; @override void didChangeDependencies() { super.didChangeDependencies(); - _key = ValueKey(PrimaryScrollController.of(context).hashCode); + final controller = PrimaryScrollController.of(context); + _isNested = controller is ExtendedNestedScrollController; + _key = ValueKey(controller.hashCode); } @override Widget buildList(ThemeData theme) { - return ListView.builder( + final child = ListView.builder( key: _key, physics: const AlwaysScrollableScrollPhysics(), padding: EdgeInsets.only( @@ -109,6 +113,13 @@ class _ViewPointsPageState extends State return _buildItem(theme, segment, isCurr); }, ); + if (_isNested) { + return ExtendedVisibilityDetector( + uniqueKey: const Key('viewpoints'), + child: child, + ); + } + return child; } Widget _buildItem(ThemeData theme, Segment segment, bool isCurr) { diff --git a/lib/pages/webview/view.dart b/lib/pages/webview/view.dart index bc09e6345..3df5aa778 100644 --- a/lib/pages/webview/view.dart +++ b/lib/pages/webview/view.dart @@ -30,8 +30,7 @@ class WebviewPage extends StatefulWidget { class _WebviewPageState extends State { late final String _url = widget.url ?? Get.parameters['url'] ?? ''; - late final UaType uaType = - widget.uaType ?? UaType.values.byName(Get.parameters['uaType'] ?? 'mob'); + late final UaType uaType; final RxString title = ''.obs; final RxDouble progress = 1.0.obs; bool _inApp = false; @@ -47,6 +46,10 @@ class _WebviewPageState extends State { @override void initState() { super.initState(); + late final uaType = Get.parameters['uaType']; + this.uaType = + widget.uaType ?? + (uaType != null ? UaType.values.byName(uaType) : UaType.platformUA); if (Get.arguments case Map map) { _inApp = map['inApp'] ?? false; _off = map['off'] ?? false; diff --git a/pubspec.lock b/pubspec.lock index e558f8748..b985aa276 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -505,7 +505,7 @@ packages: description: path: "." ref: mod - resolved-ref: "07dbeaa6f4352cd605e2292f073eca3538635ef3" + resolved-ref: "4bb4e827628b3b7ccc88a4b98ef76a036a5a51ac" url: "https://github.com/bggRGjQaUbCoE/extended_nested_scroll_view.git" source: git version: "6.2.1"