From 480bdffdaa4f0f2a4ecce02b8c08ced17ca40ba7 Mon Sep 17 00:00:00 2001 From: dom Date: Sat, 20 Jun 2026 13:31:28 +0800 Subject: [PATCH] opt scroll physics Signed-off-by: dom --- lib/common/skeleton/dynamic_card.dart | 10 ++++++++-- lib/common/skeleton/fav_pgc_item.dart | 9 +++++++-- lib/common/skeleton/media_bangumi.dart | 5 +++++ lib/common/skeleton/msg_feed_sys_msg_.dart | 11 +++++++++-- lib/common/skeleton/msg_feed_top.dart | 10 ++++++++-- lib/common/skeleton/space_opus.dart | 9 +++++++-- lib/common/skeleton/video_card_h.dart | 9 +++++++-- lib/common/skeleton/video_card_v.dart | 9 +++++++-- lib/common/skeleton/video_reply.dart | 9 +++++++-- lib/common/skeleton/whisper_item.dart | 11 +++++++++-- lib/common/widgets/flutter/refresh_indicator.dart | 2 +- lib/common/widgets/scroll_behavior.dart | 15 +++++++++++++++ lib/pages/blacklist/view.dart | 5 +---- lib/pages/common/common_controller.dart | 12 ++++++++++++ lib/pages/common/dyn/common_dyn_page.dart | 5 +---- lib/pages/dynamics_detail/controller.dart | 12 ++++-------- lib/pages/dynamics_tab/controller.dart | 14 ++++++-------- lib/pages/dynamics_tab/view.dart | 8 +++++--- lib/pages/fav/pgc/child_view.dart | 5 ++--- lib/pages/follow/child/child_view.dart | 5 +---- lib/pages/follow_type/view.dart | 5 ++--- lib/pages/live/view.dart | 5 ++--- lib/pages/live_area_detail/child/view.dart | 5 ++--- lib/pages/live_follow/view.dart | 5 ++--- lib/pages/live_search/child/view.dart | 10 ++++------ lib/pages/main_reply/controller.dart | 4 +++- lib/pages/main_reply/view.dart | 9 +++------ lib/pages/member_coin_arc/view.dart | 5 ++--- lib/pages/member_like_arc/view.dart | 5 ++--- lib/pages/member_opus/view.dart | 5 +---- lib/pages/member_shop/view.dart | 5 +---- lib/pages/member_video/controller.dart | 6 +++--- lib/pages/member_video_web/base/controller.dart | 11 +++-------- lib/pages/msg_feed_top/at_me/view.dart | 5 +---- lib/pages/msg_feed_top/like_detail/view.dart | 5 +---- lib/pages/msg_feed_top/like_me/view.dart | 5 +---- lib/pages/msg_feed_top/reply_me/view.dart | 5 +---- lib/pages/msg_feed_top/sys_msg/view.dart | 7 +------ lib/pages/pgc_review/child/controller.dart | 5 ++++- lib/pages/pgc_review/child/view.dart | 9 +++------ lib/pages/popular_series/controller.dart | 6 +++--- lib/pages/rank/zone/view.dart | 5 ++--- lib/pages/rcmd/view.dart | 5 ++--- lib/pages/search_panel/all/view.dart | 5 ++--- lib/pages/search_panel/live/view.dart | 5 ++--- lib/pages/search_panel/pgc/view.dart | 5 ++--- lib/pages/search_panel/user/view.dart | 5 ++--- lib/pages/video/member/view.dart | 5 ++--- lib/pages/video/note/view.dart | 6 +----- lib/pages/video/reply/controller.dart | 5 ++++- lib/pages/video/reply/view.dart | 8 +++----- lib/pages/video/reply_reply/controller.dart | 4 +++- lib/pages/video/reply_reply/view.dart | 9 +++------ lib/pages/video/view.dart | 3 +++ lib/pages/video/widgets/player_focus.dart | 6 ++++++ lib/pages/whisper/view.dart | 5 +---- lib/pages/whisper_secondary/view.dart | 5 +---- lib/utils/grid.dart | 5 ++--- lib/utils/waterfall.dart | 12 ++---------- 59 files changed, 210 insertions(+), 195 deletions(-) diff --git a/lib/common/skeleton/dynamic_card.dart b/lib/common/skeleton/dynamic_card.dart index 33796f101..bbfbf9290 100644 --- a/lib/common/skeleton/dynamic_card.dart +++ b/lib/common/skeleton/dynamic_card.dart @@ -1,8 +1,14 @@ import 'package:PiliPlus/utils/global_data.dart'; import 'package:flutter/material.dart'; -class DynamicCardSkeleton extends StatelessWidget { - const DynamicCardSkeleton({super.key}); +const _ = _DynamicCardSkeleton(); +const dynSkeleton_ = SliverList(delegate: dynDelegate); +const dynDelegate = SliverChildListDelegate.fixed( + [_, _, _, _, _, _, _, _, _, _], +); + +class _DynamicCardSkeleton extends StatelessWidget { + const _DynamicCardSkeleton(); @override Widget build(BuildContext context) { diff --git a/lib/common/skeleton/fav_pgc_item.dart b/lib/common/skeleton/fav_pgc_item.dart index d4077afd7..22cc80139 100644 --- a/lib/common/skeleton/fav_pgc_item.dart +++ b/lib/common/skeleton/fav_pgc_item.dart @@ -1,8 +1,13 @@ import 'package:PiliPlus/common/style.dart'; import 'package:flutter/material.dart'; -class FavPgcItemSkeleton extends StatelessWidget { - const FavPgcItemSkeleton({super.key}); +const _ = _FavPgcItemSkeleton(); +const favPgcDelegate = SliverChildListDelegate.fixed( + [_, _, _, _, _, _, _, _, _, _], +); + +class _FavPgcItemSkeleton extends StatelessWidget { + const _FavPgcItemSkeleton(); @override Widget build(BuildContext context) { diff --git a/lib/common/skeleton/media_bangumi.dart b/lib/common/skeleton/media_bangumi.dart index c2ec5888c..b9bba2727 100644 --- a/lib/common/skeleton/media_bangumi.dart +++ b/lib/common/skeleton/media_bangumi.dart @@ -1,6 +1,11 @@ import 'package:PiliPlus/common/style.dart'; import 'package:flutter/material.dart'; +const _ = MediaPgcSkeleton(); +const pgcDelegate = SliverChildListDelegate.fixed( + [_, _, _, _, _, _, _, _, _, _], +); + class MediaPgcSkeleton extends StatefulWidget { const MediaPgcSkeleton({super.key}); diff --git a/lib/common/skeleton/msg_feed_sys_msg_.dart b/lib/common/skeleton/msg_feed_sys_msg_.dart index 8df8f3963..8c6f165b4 100644 --- a/lib/common/skeleton/msg_feed_sys_msg_.dart +++ b/lib/common/skeleton/msg_feed_sys_msg_.dart @@ -1,7 +1,14 @@ import 'package:flutter/material.dart'; -class MsgFeedSysMsgSkeleton extends StatelessWidget { - const MsgFeedSysMsgSkeleton({super.key}); +const _ = _MsgFeedSysMsgSkeleton(); +const sysMsgSkeleton = SliverList( + delegate: SliverChildListDelegate.fixed( + [_, _, _, _, _, _, _, _, _, _], + ), +); + +class _MsgFeedSysMsgSkeleton extends StatelessWidget { + const _MsgFeedSysMsgSkeleton(); @override Widget build(BuildContext context) { diff --git a/lib/common/skeleton/msg_feed_top.dart b/lib/common/skeleton/msg_feed_top.dart index f4a272ffc..1c264689c 100644 --- a/lib/common/skeleton/msg_feed_top.dart +++ b/lib/common/skeleton/msg_feed_top.dart @@ -1,7 +1,13 @@ import 'package:flutter/material.dart'; -class MsgFeedTopSkeleton extends StatelessWidget { - const MsgFeedTopSkeleton({super.key}); +const _ = _MsgFeedTopSkeleton(); +const sysFeedSkeleton = SliverList(delegate: sysFeedDelegate); +const sysFeedDelegate = SliverChildListDelegate.fixed( + [_, _, _, _, _, _, _, _, _, _], +); + +class _MsgFeedTopSkeleton extends StatelessWidget { + const _MsgFeedTopSkeleton(); @override Widget build(BuildContext context) { diff --git a/lib/common/skeleton/space_opus.dart b/lib/common/skeleton/space_opus.dart index 97d614806..bcfd7a5b4 100644 --- a/lib/common/skeleton/space_opus.dart +++ b/lib/common/skeleton/space_opus.dart @@ -1,8 +1,13 @@ import 'package:PiliPlus/utils/utils.dart'; import 'package:flutter/material.dart'; -class SpaceOpusSkeleton extends StatelessWidget { - const SpaceOpusSkeleton({super.key}); +const _ = _SpaceOpusSkeleton(); +const opusDelegate = SliverChildListDelegate.fixed( + [_, _, _, _, _, _, _, _, _, _], +); + +class _SpaceOpusSkeleton extends StatelessWidget { + const _SpaceOpusSkeleton(); @override Widget build(BuildContext context) { diff --git a/lib/common/skeleton/video_card_h.dart b/lib/common/skeleton/video_card_h.dart index 6228979d4..b4b432d9e 100644 --- a/lib/common/skeleton/video_card_h.dart +++ b/lib/common/skeleton/video_card_h.dart @@ -1,8 +1,13 @@ import 'package:PiliPlus/common/style.dart'; import 'package:flutter/material.dart'; -class VideoCardHSkeleton extends StatelessWidget { - const VideoCardHSkeleton({super.key}); +const _ = _VideoCardHSkeleton(); +const videoHDelegate = SliverChildListDelegate.fixed( + [_, _, _, _, _, _, _, _, _, _], +); + +class _VideoCardHSkeleton extends StatelessWidget { + const _VideoCardHSkeleton(); @override Widget build(BuildContext context) { diff --git a/lib/common/skeleton/video_card_v.dart b/lib/common/skeleton/video_card_v.dart index ba50bb041..5af263867 100644 --- a/lib/common/skeleton/video_card_v.dart +++ b/lib/common/skeleton/video_card_v.dart @@ -1,8 +1,13 @@ import 'package:PiliPlus/common/style.dart'; import 'package:flutter/material.dart'; -class VideoCardVSkeleton extends StatelessWidget { - const VideoCardVSkeleton({super.key}); +const _ = _VideoCardVSkeleton(); +const videoVDelegate = SliverChildListDelegate.fixed( + [_, _, _, _, _, _, _, _, _, _], +); + +class _VideoCardVSkeleton extends StatelessWidget { + const _VideoCardVSkeleton(); @override Widget build(BuildContext context) { diff --git a/lib/common/skeleton/video_reply.dart b/lib/common/skeleton/video_reply.dart index 6774b0010..641ddae72 100644 --- a/lib/common/skeleton/video_reply.dart +++ b/lib/common/skeleton/video_reply.dart @@ -1,7 +1,12 @@ import 'package:flutter/material.dart'; -class VideoReplySkeleton extends StatelessWidget { - const VideoReplySkeleton({super.key}); +const _ = _VideoReplySkeleton(); +const replySkeleton = SliverList( + delegate: SliverChildListDelegate.fixed([_, _, _, _, _]), +); + +class _VideoReplySkeleton extends StatelessWidget { + const _VideoReplySkeleton(); @override Widget build(BuildContext context) { diff --git a/lib/common/skeleton/whisper_item.dart b/lib/common/skeleton/whisper_item.dart index f02fa89e4..322bba8db 100644 --- a/lib/common/skeleton/whisper_item.dart +++ b/lib/common/skeleton/whisper_item.dart @@ -1,7 +1,14 @@ import 'package:flutter/material.dart'; -class WhisperItemSkeleton extends StatelessWidget { - const WhisperItemSkeleton({super.key}); +const _ = _WhisperItemSkeleton(); +const whisperSkeleton = SliverList( + delegate: SliverChildListDelegate.fixed( + [_, _, _, _, _, _, _, _, _, _], + ), +); + +class _WhisperItemSkeleton extends StatelessWidget { + const _WhisperItemSkeleton(); @override Widget build(BuildContext context) { diff --git a/lib/common/widgets/flutter/refresh_indicator.dart b/lib/common/widgets/flutter/refresh_indicator.dart index ca158be89..2a6619f81 100644 --- a/lib/common/widgets/flutter/refresh_indicator.dart +++ b/lib/common/widgets/flutter/refresh_indicator.dart @@ -551,7 +551,7 @@ class RefreshIndicatorState extends State return ScrollConfiguration( behavior: RefreshScrollBehavior( scrollPhysics: RefreshScrollPhysics( - parent: const RangeMaintainingScrollPhysics(), + // parent: const RangeMaintainingScrollPhysics(), onDrag: _onDrag, ), ), diff --git a/lib/common/widgets/scroll_behavior.dart b/lib/common/widgets/scroll_behavior.dart index 03f6b43ff..8e5d5262d 100644 --- a/lib/common/widgets/scroll_behavior.dart +++ b/lib/common/widgets/scroll_behavior.dart @@ -3,6 +3,10 @@ import 'dart:io' show Platform; import 'package:flutter/gestures.dart' show PointerDeviceKind; import 'package:flutter/material.dart'; +const _clampingPhysics = ClampingScrollPhysics(); +const _bouncingPhysics = BouncingScrollPhysics(); +const _bouncingDesktopPhysics = BouncingScrollPhysics(decelerationRate: .fast); + class CustomScrollBehavior extends MaterialScrollBehavior { const CustomScrollBehavior(); @@ -29,6 +33,17 @@ class CustomScrollBehavior extends MaterialScrollBehavior { return child; } + @override + ScrollPhysics getScrollPhysics(BuildContext context) { + if (Platform.isIOS) { + return _bouncingPhysics; + } + if (Platform.isMacOS) { + return _bouncingDesktopPhysics; + } + return _clampingPhysics; + } + @override Set get dragDevices => desktopDragDevices; } diff --git a/lib/pages/blacklist/view.dart b/lib/pages/blacklist/view.dart index 32377ee61..6af756311 100644 --- a/lib/pages/blacklist/view.dart +++ b/lib/pages/blacklist/view.dart @@ -65,10 +65,7 @@ class _BlackListPageState extends State { Widget _buildBody(LoadingState?> loadingState) { late final style = TextStyle(color: Theme.of(context).colorScheme.outline); return switch (loadingState) { - Loading() => SliverList.builder( - itemCount: 12, - itemBuilder: (context, index) => const MsgFeedTopSkeleton(), - ), + Loading() => sysFeedSkeleton, Success(:final response) => response != null && response.isNotEmpty ? SliverList.builder( diff --git a/lib/pages/common/common_controller.dart b/lib/pages/common/common_controller.dart index eefc8912e..679696fcc 100644 --- a/lib/pages/common/common_controller.dart +++ b/lib/pages/common/common_controller.dart @@ -1,3 +1,4 @@ +import 'package:PiliPlus/common/widgets/scroll_physics.dart' show ReloadMixin; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/utils/extension/scroll_controller_ext.dart'; import 'package:flutter/widgets.dart' show ScrollController; @@ -50,3 +51,14 @@ abstract class CommonController extends GetxController super.onClose(); } } + +mixin CommonReloadMixin on CommonController implements ReloadMixin { + @override + late bool reload = false; + + @override + Future onReload() { + reload = true; + return super.onReload(); + } +} diff --git a/lib/pages/common/dyn/common_dyn_page.dart b/lib/pages/common/dyn/common_dyn_page.dart index 09e1dc384..7dcc5430c 100644 --- a/lib/pages/common/dyn/common_dyn_page.dart +++ b/lib/pages/common/dyn/common_dyn_page.dart @@ -121,10 +121,7 @@ mixin CommonDynPageMixin Widget replyList(LoadingState?> loadingState) { return switch (loadingState) { - Loading() => SliverList.builder( - itemCount: 12, - itemBuilder: (context, index) => const VideoReplySkeleton(), - ), + Loading() => replySkeleton, Success(:final response) => response != null && response.isNotEmpty ? SliverList.builder( diff --git a/lib/pages/dynamics_detail/controller.dart b/lib/pages/dynamics_detail/controller.dart index 63a2774c2..910f0a580 100644 --- a/lib/pages/dynamics_detail/controller.dart +++ b/lib/pages/dynamics_detail/controller.dart @@ -1,13 +1,15 @@ -import 'package:PiliPlus/common/widgets/scroll_physics.dart' show ReloadMixin; import 'package:PiliPlus/http/dynamics.dart'; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/reply.dart'; import 'package:PiliPlus/models/dynamics/result.dart'; +import 'package:PiliPlus/pages/common/common_controller.dart' + show CommonReloadMixin; import 'package:PiliPlus/pages/common/dyn/common_dyn_controller.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; -class DynamicDetailController extends CommonDynController with ReloadMixin { +class DynamicDetailController extends CommonDynController + with CommonReloadMixin { @override late int oid; @override @@ -70,10 +72,4 @@ class DynamicDetailController extends CommonDynController with ReloadMixin { }); } } - - @override - Future onReload() { - reload = true; - return super.onReload(); - } } diff --git a/lib/pages/dynamics_tab/controller.dart b/lib/pages/dynamics_tab/controller.dart index 999ecf69b..30631dfbd 100644 --- a/lib/pages/dynamics_tab/controller.dart +++ b/lib/pages/dynamics_tab/controller.dart @@ -1,11 +1,12 @@ import 'dart:async' show StreamSubscription; -import 'package:PiliPlus/common/widgets/scroll_physics.dart'; import 'package:PiliPlus/http/dynamics.dart'; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/msg.dart'; import 'package:PiliPlus/models/common/dynamic/dynamics_type.dart'; import 'package:PiliPlus/models/dynamics/result.dart'; +import 'package:PiliPlus/pages/common/common_controller.dart' + show CommonReloadMixin; import 'package:PiliPlus/pages/common/common_list_controller.dart'; import 'package:PiliPlus/pages/dynamics/controller.dart'; import 'package:PiliPlus/pages/main/controller.dart'; @@ -15,11 +16,13 @@ import 'package:get/get.dart'; class DynamicsTabController extends CommonListController - with AccountMixin, ReloadMixin { + with AccountMixin, CommonReloadMixin { DynamicsTabController({required this.dynamicsType}); final DynamicsTabType dynamicsType; String offset = ''; int? mid; + late int flag = 0; + late final MainController mainController = Get.find(); final dynamicsController = Get.find(); StreamSubscription? _listener; @@ -31,6 +34,7 @@ class DynamicsTabController if (dynamicsType == .up) { _listener = dynamicsController.mid.listen((mid) { if (mid != -1) { + flag++; this.mid = mid; onReload(); } @@ -74,12 +78,6 @@ class DynamicsTabController } } - @override - Future onReload() { - reload = true; - return super.onReload(); - } - void onBlock(int index) { if (dynamicsType != .up) { loadingState diff --git a/lib/pages/dynamics_tab/view.dart b/lib/pages/dynamics_tab/view.dart index 5b4173cfb..3b7230d64 100644 --- a/lib/pages/dynamics_tab/view.dart +++ b/lib/pages/dynamics_tab/view.dart @@ -52,9 +52,11 @@ class _DynamicsTabPageState extends State return controller.onRefresh(); }, child: CustomScrollView( - key: widget.dynamicsType == .all - ? null - : PageStorageKey(widget.dynamicsType), + key: switch (widget.dynamicsType) { + .all => null, + .up => PageStorageKey('${widget.dynamicsType}${controller.flag}'), + _ => PageStorageKey(widget.dynamicsType), + }, physics: ReloadScrollPhysics(controller: controller), controller: controller.scrollController, slivers: [ diff --git a/lib/pages/fav/pgc/child_view.dart b/lib/pages/fav/pgc/child_view.dart index 600576302..b4dffd25d 100644 --- a/lib/pages/fav/pgc/child_view.dart +++ b/lib/pages/fav/pgc/child_view.dart @@ -170,10 +170,9 @@ class _FavPgcChildPageState extends State Widget _buildBody(LoadingState?> loadingState) { return switch (loadingState) { - Loading() => SliverGrid.builder( + Loading() => SliverGrid( gridDelegate: gridDelegate, - itemBuilder: (context, index) => const FavPgcItemSkeleton(), - itemCount: 10, + delegate: favPgcDelegate, ), Success(:final response) => response != null && response.isNotEmpty diff --git a/lib/pages/follow/child/child_view.dart b/lib/pages/follow/child/child_view.dart index adbeda4ab..1a6145a9d 100644 --- a/lib/pages/follow/child/child_view.dart +++ b/lib/pages/follow/child/child_view.dart @@ -157,10 +157,7 @@ class _FollowChildPageState extends State Widget _buildBody(LoadingState?> loadingState) { return switch (loadingState) { - Loading() => SliverList.builder( - itemCount: 12, - itemBuilder: (context, index) => const MsgFeedTopSkeleton(), - ), + Loading() => sysFeedSkeleton, Success(:final response) => response != null && response.isNotEmpty ? SliverList.builder( diff --git a/lib/pages/follow_type/view.dart b/lib/pages/follow_type/view.dart index cb335d652..b01d96c1d 100644 --- a/lib/pages/follow_type/view.dart +++ b/lib/pages/follow_type/view.dart @@ -49,10 +49,9 @@ abstract class FollowTypePageState extends State { LoadingState?> loadingState, ) { return switch (loadingState) { - Loading() => SliverGrid.builder( + Loading() => SliverGrid( gridDelegate: gridDelegate, - itemBuilder: (context, index) => const MsgFeedTopSkeleton(), - itemCount: 16, + delegate: sysFeedDelegate, ), Success(:final response) => response != null && response.isNotEmpty diff --git a/lib/pages/live/view.dart b/lib/pages/live/view.dart index 5c81a212d..a14954ec5 100644 --- a/lib/pages/live/view.dart +++ b/lib/pages/live/view.dart @@ -171,10 +171,9 @@ class _LivePageState extends State Widget _buildBody(ThemeData theme, LoadingState loadingState) { return switch (loadingState) { - Loading() => SliverGrid.builder( + Loading() => SliverGrid( gridDelegate: gridDelegate, - itemBuilder: (context, index) => const VideoCardVSkeleton(), - itemCount: 10, + delegate: videoVDelegate, ), Success(:final response) => SliverMainAxisGroup( slivers: [ diff --git a/lib/pages/live_area_detail/child/view.dart b/lib/pages/live_area_detail/child/view.dart index b1bce3708..493f85c59 100644 --- a/lib/pages/live_area_detail/child/view.dart +++ b/lib/pages/live_area_detail/child/view.dart @@ -80,10 +80,9 @@ class _LiveAreaChildPageState extends State LoadingState?> loadingState, ) { return switch (loadingState) { - Loading() => SliverGrid.builder( + Loading() => SliverGrid( gridDelegate: gridDelegate, - itemBuilder: (context, index) => const VideoCardVSkeleton(), - itemCount: 10, + delegate: videoVDelegate, ), Success(:final response) => SliverMainAxisGroup( slivers: [ diff --git a/lib/pages/live_follow/view.dart b/lib/pages/live_follow/view.dart index a3e3abdcc..0bcbe03d0 100644 --- a/lib/pages/live_follow/view.dart +++ b/lib/pages/live_follow/view.dart @@ -62,10 +62,9 @@ class _LiveFollowPageState extends State { Widget _buildBody(LoadingState?> loadingState) { return switch (loadingState) { - Loading() => SliverGrid.builder( + Loading() => SliverGrid( gridDelegate: gridDelegate, - itemBuilder: (context, index) => const VideoCardVSkeleton(), - itemCount: 10, + delegate: videoVDelegate, ), Success(:final response) => response != null && response.isNotEmpty diff --git a/lib/pages/live_search/child/view.dart b/lib/pages/live_search/child/view.dart index e7905bdfd..a7665b382 100644 --- a/lib/pages/live_search/child/view.dart +++ b/lib/pages/live_search/child/view.dart @@ -60,15 +60,13 @@ class _LiveSearchChildPageState extends State Widget get _buildLoading { return switch (widget.searchType) { - .room => SliverGrid.builder( + .room => SliverGrid( gridDelegate: roomDelegate, - itemBuilder: (context, index) => const VideoCardVSkeleton(), - itemCount: 10, + delegate: videoVDelegate, ), - .user => SliverGrid.builder( + .user => SliverGrid( gridDelegate: userDelegate, - itemBuilder: (context, index) => const MsgFeedTopSkeleton(), - itemCount: 12, + delegate: sysFeedDelegate, ), }; } diff --git a/lib/pages/main_reply/controller.dart b/lib/pages/main_reply/controller.dart index a98658459..95e932cc1 100644 --- a/lib/pages/main_reply/controller.dart +++ b/lib/pages/main_reply/controller.dart @@ -2,10 +2,12 @@ import 'package:PiliPlus/grpc/bilibili/main/community/reply/v1.pb.dart' show MainListReply, ReplyInfo; import 'package:PiliPlus/grpc/reply.dart'; import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/pages/common/common_controller.dart'; import 'package:PiliPlus/pages/common/reply_controller.dart'; import 'package:get/get.dart'; -class MainReplyController extends ReplyController { +class MainReplyController extends ReplyController + with CommonReloadMixin { late final int oid; late final int replyType; diff --git a/lib/pages/main_reply/view.dart b/lib/pages/main_reply/view.dart index d5d305cdb..b3a6b9e08 100644 --- a/lib/pages/main_reply/view.dart +++ b/lib/pages/main_reply/view.dart @@ -3,6 +3,7 @@ import 'package:PiliPlus/common/style.dart'; import 'package:PiliPlus/common/widgets/flutter/refresh_indicator.dart'; import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart'; import 'package:PiliPlus/common/widgets/scaffold.dart'; +import 'package:PiliPlus/common/widgets/scroll_physics.dart'; import 'package:PiliPlus/common/widgets/sliver/sliver_floating_header.dart'; import 'package:PiliPlus/common/widgets/view_safe_area.dart'; import 'package:PiliPlus/grpc/bilibili/main/community/reply/v1.pb.dart' @@ -80,7 +81,7 @@ class _MainReplyPageState extends State right: padding.right, ), child: CustomScrollView( - physics: const AlwaysScrollableScrollPhysics(), + physics: ReloadScrollPhysics(controller: _controller), slivers: [ buildReplyHeader(colorScheme), Obx( @@ -131,11 +132,7 @@ class _MainReplyPageState extends State LoadingState?> loadingState, ) { return switch (loadingState) { - Loading() => SliverPrototypeExtentList.builder( - itemCount: 10, - itemBuilder: (_, _) => const VideoReplySkeleton(), - prototypeItem: const VideoReplySkeleton(), - ), + Loading() => replySkeleton, Success(:final response) => response != null && response.isNotEmpty ? SliverList.builder( diff --git a/lib/pages/member_coin_arc/view.dart b/lib/pages/member_coin_arc/view.dart index 93ea98669..7283859c8 100644 --- a/lib/pages/member_coin_arc/view.dart +++ b/lib/pages/member_coin_arc/view.dart @@ -77,10 +77,9 @@ class _MemberCoinArcPageState extends State { Widget _buildBody(LoadingState?> loadingState) { return switch (loadingState) { - Loading() => SliverGrid.builder( + Loading() => SliverGrid( gridDelegate: gridDelegate, - itemCount: 16, - itemBuilder: (context, index) => const VideoCardVSkeleton(), + delegate: videoVDelegate, ), Success(:final response) => response != null && response.isNotEmpty diff --git a/lib/pages/member_like_arc/view.dart b/lib/pages/member_like_arc/view.dart index ce67045eb..adb7f9c6a 100644 --- a/lib/pages/member_like_arc/view.dart +++ b/lib/pages/member_like_arc/view.dart @@ -79,10 +79,9 @@ class _MemberLikeArcPageState extends State { Widget _buildBody(LoadingState?> loadingState) { return switch (loadingState) { - Loading() => SliverGrid.builder( + Loading() => SliverGrid( gridDelegate: gridDelegate, - itemCount: 16, - itemBuilder: (context, index) => const VideoCardVSkeleton(), + delegate: videoVDelegate, ), Success(:final response) => response != null && response.isNotEmpty diff --git a/lib/pages/member_opus/view.dart b/lib/pages/member_opus/view.dart index 22e4152b5..f57591738 100644 --- a/lib/pages/member_opus/view.dart +++ b/lib/pages/member_opus/view.dart @@ -156,10 +156,7 @@ class _MemberOpusState extends State return switch (loadingState) { Loading() => SliverWaterfallFlow( gridDelegate: gridDelegate, - delegate: SliverChildBuilderDelegate( - (context, index) => const SpaceOpusSkeleton(), - childCount: 10, - ), + delegate: opusDelegate, ), Success(:final response) => response != null && response.isNotEmpty diff --git a/lib/pages/member_shop/view.dart b/lib/pages/member_shop/view.dart index 488600b5a..f4abfe4d7 100644 --- a/lib/pages/member_shop/view.dart +++ b/lib/pages/member_shop/view.dart @@ -77,10 +77,7 @@ class _MemberShopState extends State case Loading(): return SliverWaterfallFlow( gridDelegate: gridDelegate, - delegate: SliverChildBuilderDelegate( - (context, index) => const SpaceOpusSkeleton(), - childCount: 10, - ), + delegate: opusDelegate, ); case Success(:final response): if (response == null || response.isEmpty) { diff --git a/lib/pages/member_video/controller.dart b/lib/pages/member_video/controller.dart index e7d95fc06..b6dcdadd0 100644 --- a/lib/pages/member_video/controller.dart +++ b/lib/pages/member_video/controller.dart @@ -1,4 +1,3 @@ -import 'package:PiliPlus/common/widgets/scroll_physics.dart'; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/member.dart'; import 'package:PiliPlus/http/search.dart'; @@ -9,6 +8,8 @@ import 'package:PiliPlus/models/common/video/source_type.dart'; import 'package:PiliPlus/models_new/space/space_archive/data.dart'; import 'package:PiliPlus/models_new/space/space_archive/episodic_button.dart'; import 'package:PiliPlus/models_new/space/space_archive/item.dart'; +import 'package:PiliPlus/pages/common/common_controller.dart' + show CommonReloadMixin; import 'package:PiliPlus/pages/common/common_list_controller.dart'; import 'package:PiliPlus/utils/extension/dimension_ext.dart'; import 'package:PiliPlus/utils/extension/iterable_ext.dart'; @@ -18,7 +19,7 @@ import 'package:get/get.dart'; class MemberVideoCtr extends CommonListController - with ReloadMixin { + with CommonReloadMixin { MemberVideoCtr({ required this.type, required this.mid, @@ -226,7 +227,6 @@ class MemberVideoCtr @override Future onReload() { - reload = true; isLocating.value = false; return super.onReload(); } diff --git a/lib/pages/member_video_web/base/controller.dart b/lib/pages/member_video_web/base/controller.dart index 344b6e68f..e075d42b5 100644 --- a/lib/pages/member_video_web/base/controller.dart +++ b/lib/pages/member_video_web/base/controller.dart @@ -1,12 +1,13 @@ -import 'package:PiliPlus/common/widgets/scroll_physics.dart' show ReloadMixin; import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/pages/common/common_controller.dart' + show CommonReloadMixin; import 'package:PiliPlus/pages/common/common_list_controller.dart'; import 'package:get/get.dart'; const int ps = 30; abstract class BaseVideoWebCtr extends CommonListController - with ReloadMixin { + with CommonReloadMixin { final Object mid = Get.arguments['mid']; int? totalPage; @@ -41,10 +42,4 @@ abstract class BaseVideoWebCtr extends CommonListController loadingState.value = LoadingState.loading(); queryData(); } - - @override - Future onReload() { - reload = true; - return super.onReload(); - } } diff --git a/lib/pages/msg_feed_top/at_me/view.dart b/lib/pages/msg_feed_top/at_me/view.dart index b18ff7853..c97b11721 100644 --- a/lib/pages/msg_feed_top/at_me/view.dart +++ b/lib/pages/msg_feed_top/at_me/view.dart @@ -79,10 +79,7 @@ class _AtMePageState extends State { color: Colors.grey.withValues(alpha: 0.1), ); return switch (loadingState) { - Loading() => SliverList.builder( - itemCount: 12, - itemBuilder: (context, index) => const MsgFeedTopSkeleton(), - ), + Loading() => sysFeedSkeleton, Success(:final response) => response != null && response.isNotEmpty ? SliverList.separated( diff --git a/lib/pages/msg_feed_top/like_detail/view.dart b/lib/pages/msg_feed_top/like_detail/view.dart index 97d985442..f1ffcefa4 100644 --- a/lib/pages/msg_feed_top/like_detail/view.dart +++ b/lib/pages/msg_feed_top/like_detail/view.dart @@ -61,10 +61,7 @@ class _LikeDetailPageState extends State { color: Colors.grey.withValues(alpha: 0.1), ); return switch (loadingState) { - Loading() => SliverList.builder( - itemCount: 12, - itemBuilder: (context, index) => const MsgFeedTopSkeleton(), - ), + Loading() => sysFeedSkeleton, Success(:final response) => SliverMainAxisGroup( slivers: [ if (_controller.card != null) ...[ diff --git a/lib/pages/msg_feed_top/like_me/view.dart b/lib/pages/msg_feed_top/like_me/view.dart index b047a13f6..10b256218 100644 --- a/lib/pages/msg_feed_top/like_me/view.dart +++ b/lib/pages/msg_feed_top/like_me/view.dart @@ -82,10 +82,7 @@ class _LikeMePageState extends State { color: Colors.grey.withValues(alpha: 0.1), ); return switch (loadingState) { - Loading() => SliverList.builder( - itemCount: 12, - itemBuilder: (context, index) => const MsgFeedTopSkeleton(), - ), + Loading() => sysFeedSkeleton, Success(:final response) => Builder( builder: (context) { Pair, List> pair = response; diff --git a/lib/pages/msg_feed_top/reply_me/view.dart b/lib/pages/msg_feed_top/reply_me/view.dart index c351bc4bb..88bc93433 100644 --- a/lib/pages/msg_feed_top/reply_me/view.dart +++ b/lib/pages/msg_feed_top/reply_me/view.dart @@ -79,10 +79,7 @@ class _ReplyMePageState extends State { color: Colors.grey.withValues(alpha: 0.1), ); return switch (loadingState) { - Loading() => SliverList.builder( - itemCount: 12, - itemBuilder: (context, index) => const MsgFeedTopSkeleton(), - ), + Loading() => sysFeedSkeleton, Success(:final response) => response != null && response.isNotEmpty ? SliverList.separated( diff --git a/lib/pages/msg_feed_top/sys_msg/view.dart b/lib/pages/msg_feed_top/sys_msg/view.dart index 64fd00815..887e9fa98 100644 --- a/lib/pages/msg_feed_top/sys_msg/view.dart +++ b/lib/pages/msg_feed_top/sys_msg/view.dart @@ -66,12 +66,7 @@ class _SysMsgPageState extends State { color: Colors.grey.withValues(alpha: 0.1), ); return switch (loadingState) { - Loading() => ViewSliverSafeArea( - sliver: SliverList.builder( - itemCount: 12, - itemBuilder: (context, index) => const MsgFeedSysMsgSkeleton(), - ), - ), + Loading() => const ViewSliverSafeArea(sliver: sysMsgSkeleton), Success(:final response) => response != null && response.isNotEmpty ? SliverList.separated( diff --git a/lib/pages/pgc_review/child/controller.dart b/lib/pages/pgc_review/child/controller.dart index 91eec433b..155774ba4 100644 --- a/lib/pages/pgc_review/child/controller.dart +++ b/lib/pages/pgc_review/child/controller.dart @@ -3,12 +3,15 @@ import 'package:PiliPlus/http/pgc.dart'; import 'package:PiliPlus/models/common/pgc_review_type.dart'; import 'package:PiliPlus/models_new/pgc/pgc_review/data.dart'; import 'package:PiliPlus/models_new/pgc/pgc_review/list.dart'; +import 'package:PiliPlus/pages/common/common_controller.dart' + show CommonReloadMixin; import 'package:PiliPlus/pages/common/common_list_controller.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; class PgcReviewController - extends CommonListController { + extends CommonListController + with CommonReloadMixin { PgcReviewController({required this.type, required this.mediaId}); final PgcReviewType type; diff --git a/lib/pages/pgc_review/child/view.dart b/lib/pages/pgc_review/child/view.dart index 54e5b653c..98691ed6d 100644 --- a/lib/pages/pgc_review/child/view.dart +++ b/lib/pages/pgc_review/child/view.dart @@ -5,6 +5,7 @@ import 'package:PiliPlus/common/widgets/flutter/refresh_indicator.dart'; import 'package:PiliPlus/common/widgets/icon/bili_icons.dart'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart'; +import 'package:PiliPlus/common/widgets/scroll_physics.dart'; import 'package:PiliPlus/common/widgets/sliver/sliver_floating_header.dart'; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/models/common/pgc_review_type.dart'; @@ -66,7 +67,7 @@ class _PgcReviewChildPageState extends State onRefresh: _controller.onRefresh, child: CustomScrollView( controller: _controller.scrollController, - physics: const AlwaysScrollableScrollPhysics(), + physics: ReloadScrollPhysics(controller: _controller), slivers: [ _buildHeader(theme), SliverPadding( @@ -91,11 +92,7 @@ class _PgcReviewChildPageState extends State color: theme.colorScheme.outline.withValues(alpha: 0.1), ); return switch (loadingState) { - Loading() => SliverPrototypeExtentList.builder( - prototypeItem: const VideoReplySkeleton(), - itemBuilder: (_, _) => const VideoReplySkeleton(), - itemCount: 8, - ), + Loading() => replySkeleton, Success(:final response) => response != null && response.isNotEmpty ? SliverList.separated( diff --git a/lib/pages/popular_series/controller.dart b/lib/pages/popular_series/controller.dart index 1657fb66a..b43e86f36 100644 --- a/lib/pages/popular_series/controller.dart +++ b/lib/pages/popular_series/controller.dart @@ -1,17 +1,18 @@ -import 'package:PiliPlus/common/widgets/scroll_physics.dart' show ReloadMixin; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/video.dart'; import 'package:PiliPlus/models/model_hot_video_item.dart'; import 'package:PiliPlus/models_new/popular/popular_series_list/list.dart'; import 'package:PiliPlus/models_new/popular/popular_series_one/config.dart'; import 'package:PiliPlus/models_new/popular/popular_series_one/data.dart'; +import 'package:PiliPlus/pages/common/common_controller.dart' + show CommonReloadMixin; import 'package:PiliPlus/pages/common/common_list_controller.dart'; import 'package:PiliPlus/utils/extension/iterable_ext.dart'; import 'package:get/get.dart'; class PopularSeriesController extends CommonListController - with ReloadMixin { + with CommonReloadMixin { late int number; final config = Rxn(); @@ -55,7 +56,6 @@ class PopularSeriesController if (seriesList.isNullOrEmpty) { return _getSeriesList(); } - reload = true; return super.onReload(); } } diff --git a/lib/pages/rank/zone/view.dart b/lib/pages/rank/zone/view.dart index 4238babae..6f1e66540 100644 --- a/lib/pages/rank/zone/view.dart +++ b/lib/pages/rank/zone/view.dart @@ -28,10 +28,9 @@ class ZonePage extends StatelessWidget { Widget buildBody(LoadingState?> loadingState) { return switch (loadingState) { - Loading() => SliverGrid.builder( + Loading() => SliverGrid( gridDelegate: gridDelegate, - itemBuilder: (_, _) => const VideoCardHSkeleton(), - itemCount: 10, + delegate: videoHDelegate, ), Success(:final response) => response != null && response.isNotEmpty diff --git a/lib/pages/rcmd/view.dart b/lib/pages/rcmd/view.dart index 816e88dc7..2e57f4ba2 100644 --- a/lib/pages/rcmd/view.dart +++ b/lib/pages/rcmd/view.dart @@ -131,9 +131,8 @@ class _RcmdPageState extends State }; } - Widget get _buildSkeleton => SliverGrid.builder( + Widget get _buildSkeleton => SliverGrid( gridDelegate: gridDelegate, - itemBuilder: (context, index) => const VideoCardVSkeleton(), - itemCount: 10, + delegate: videoVDelegate, ); } diff --git a/lib/pages/search_panel/all/view.dart b/lib/pages/search_panel/all/view.dart index 4201773d3..7e793e046 100644 --- a/lib/pages/search_panel/all/view.dart +++ b/lib/pages/search_panel/all/view.dart @@ -101,9 +101,8 @@ class _SearchAllPanelState } @override - Widget get buildLoading => SliverGrid.builder( + Widget get buildLoading => SliverGrid( gridDelegate: Grid.videoCardHDelegate(), - itemBuilder: (context, index) => const VideoCardHSkeleton(), - itemCount: 10, + delegate: videoHDelegate, ); } diff --git a/lib/pages/search_panel/live/view.dart b/lib/pages/search_panel/live/view.dart index b846c7aed..d8e7e4a33 100644 --- a/lib/pages/search_panel/live/view.dart +++ b/lib/pages/search_panel/live/view.dart @@ -73,9 +73,8 @@ class _SearchLivePanelState } @override - Widget get buildLoading => SliverGrid.builder( + Widget get buildLoading => SliverGrid( gridDelegate: gridDelegate, - itemBuilder: (context, index) => const VideoCardVSkeleton(), - itemCount: 10, + delegate: videoVDelegate, ); } diff --git a/lib/pages/search_panel/pgc/view.dart b/lib/pages/search_panel/pgc/view.dart index bfa411cee..005896304 100644 --- a/lib/pages/search_panel/pgc/view.dart +++ b/lib/pages/search_panel/pgc/view.dart @@ -65,13 +65,12 @@ class _SearchPgcPanelState } @override - Widget get buildLoading => SliverGrid.builder( + Widget get buildLoading => SliverGrid( gridDelegate: SliverGridDelegateWithExtentAndRatio( mainAxisSpacing: 2, maxCrossAxisExtent: Grid.smallCardWidth * 2, childAspectRatio: Style.aspectRatio * 1.5, ), - itemBuilder: (context, index) => const MediaPgcSkeleton(), - itemCount: 10, + delegate: pgcDelegate, ); } diff --git a/lib/pages/search_panel/user/view.dart b/lib/pages/search_panel/user/view.dart index dc1008bec..c8d24f600 100644 --- a/lib/pages/search_panel/user/view.dart +++ b/lib/pages/search_panel/user/view.dart @@ -112,9 +112,8 @@ class _SearchUserPanelState } @override - Widget get buildLoading => SliverGrid.builder( + Widget get buildLoading => SliverGrid( gridDelegate: gridDelegate, - itemBuilder: (context, index) => const MsgFeedTopSkeleton(), - itemCount: 10, + delegate: sysFeedDelegate, ); } diff --git a/lib/pages/video/member/view.dart b/lib/pages/video/member/view.dart index 0c16fbacc..6a0c8a17c 100644 --- a/lib/pages/video/member/view.dart +++ b/lib/pages/video/member/view.dart @@ -173,9 +173,8 @@ class _HorizontalMemberPageState extends State { LoadingState?> loadingState, ) { return switch (loadingState) { - Loading() => SliverFixedExtentList.builder( - itemCount: 10, - itemBuilder: (_, _) => const VideoCardHSkeleton(), + Loading() => const SliverFixedExtentList( + delegate: videoHDelegate, itemExtent: 112, ), Success(:final response) => diff --git a/lib/pages/video/note/view.dart b/lib/pages/video/note/view.dart index 89c089196..cf9b38415 100644 --- a/lib/pages/video/note/view.dart +++ b/lib/pages/video/note/view.dart @@ -187,11 +187,7 @@ class _NoteListPageState extends State color: theme.colorScheme.outline.withValues(alpha: 0.1), ); return switch (loadingState) { - Loading() => SliverPrototypeExtentList.builder( - prototypeItem: const VideoReplySkeleton(), - itemBuilder: (_, _) => const VideoReplySkeleton(), - itemCount: 8, - ), + Loading() => replySkeleton, Success(:final response) => response != null && response.isNotEmpty ? SliverList.separated( diff --git a/lib/pages/video/reply/controller.dart b/lib/pages/video/reply/controller.dart index 215b6a1f3..b630f4bd9 100644 --- a/lib/pages/video/reply/controller.dart +++ b/lib/pages/video/reply/controller.dart @@ -3,11 +3,14 @@ import 'package:PiliPlus/grpc/bilibili/main/community/reply/v1.pb.dart' import 'package:PiliPlus/grpc/reply.dart'; import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/models/common/video/video_type.dart'; +import 'package:PiliPlus/pages/common/common_controller.dart' + show CommonReloadMixin; import 'package:PiliPlus/pages/common/reply_controller.dart'; import 'package:PiliPlus/pages/video/controller.dart'; import 'package:get/get.dart'; -class VideoReplyController extends ReplyController { +class VideoReplyController extends ReplyController + with CommonReloadMixin { VideoReplyController({ required this.aid, required this.videoType, diff --git a/lib/pages/video/reply/view.dart b/lib/pages/video/reply/view.dart index fc7ee0077..d517f0b60 100644 --- a/lib/pages/video/reply/view.dart +++ b/lib/pages/video/reply/view.dart @@ -2,6 +2,7 @@ import 'package:PiliPlus/common/skeleton/video_reply.dart'; import 'package:PiliPlus/common/style.dart'; import 'package:PiliPlus/common/widgets/flutter/refresh_indicator.dart'; import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart'; +import 'package:PiliPlus/common/widgets/scroll_physics.dart'; import 'package:PiliPlus/common/widgets/sliver/sliver_floating_header.dart'; import 'package:PiliPlus/grpc/bilibili/main/community/reply/v1.pb.dart' show ReplyInfo; @@ -86,7 +87,7 @@ class _VideoReplyPanelState extends State controller: widget.isNested ? null : _videoReplyController.scrollController, - physics: const AlwaysScrollableScrollPhysics(), + physics: ReloadScrollPhysics(controller: _videoReplyController), key: const PageStorageKey(_VideoReplyPanelState), slivers: [ SliverFloatingHeaderWidget( @@ -173,10 +174,7 @@ class _VideoReplyPanelState extends State LoadingState?> loadingState, ) { return switch (loadingState) { - Loading() => SliverList.builder( - itemBuilder: (context, index) => const VideoReplySkeleton(), - itemCount: 5, - ), + Loading() => replySkeleton, Success(:final response) => response != null && response.isNotEmpty ? SliverList.builder( diff --git a/lib/pages/video/reply_reply/controller.dart b/lib/pages/video/reply_reply/controller.dart index bf116cdcd..2e36e976a 100644 --- a/lib/pages/video/reply_reply/controller.dart +++ b/lib/pages/video/reply_reply/controller.dart @@ -2,6 +2,8 @@ import 'package:PiliPlus/grpc/bilibili/main/community/reply/v1.pb.dart' show ReplyInfo, DetailListReply, Mode; import 'package:PiliPlus/grpc/reply.dart'; import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/pages/common/common_controller.dart' + show CommonReloadMixin; import 'package:PiliPlus/pages/common/publish/publish_route.dart'; import 'package:PiliPlus/pages/common/reply_controller.dart'; import 'package:PiliPlus/pages/video/reply_new/view.dart'; @@ -14,7 +16,7 @@ import 'package:get/get.dart'; import 'package:super_sliver_list/super_sliver_list.dart'; class VideoReplyReplyController extends ReplyController - with GetSingleTickerProviderStateMixin { + with GetSingleTickerProviderStateMixin, CommonReloadMixin { VideoReplyReplyController({ required this.hasRoot, required this.id, diff --git a/lib/pages/video/reply_reply/view.dart b/lib/pages/video/reply_reply/view.dart index 1ed1bb315..2ef3fcdef 100644 --- a/lib/pages/video/reply_reply/view.dart +++ b/lib/pages/video/reply_reply/view.dart @@ -4,6 +4,7 @@ import 'package:PiliPlus/common/widgets/colored_box_transition.dart'; import 'package:PiliPlus/common/widgets/flutter/refresh_indicator.dart'; import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart'; import 'package:PiliPlus/common/widgets/scaffold.dart'; +import 'package:PiliPlus/common/widgets/scroll_physics.dart'; import 'package:PiliPlus/common/widgets/sliver/sliver_pinned_header.dart'; import 'package:PiliPlus/common/widgets/view_safe_area.dart'; import 'package:PiliPlus/grpc/bilibili/main/community/reply/v1.pb.dart' @@ -189,7 +190,7 @@ class _VideoReplyReplyPanelState extends State child: CustomScrollView( key: ValueKey(scrollController.hashCode), controller: scrollController, - physics: const AlwaysScrollableScrollPhysics(), + physics: ReloadScrollPhysics(controller: _controller), slivers: [ if (!isDialogue) ...[ if ((widget.firstFloor ?? _controller.firstFloor.value) @@ -284,11 +285,7 @@ class _VideoReplyReplyPanelState extends State ) { final jumpIndex = _controller.index.value; return switch (loadingState) { - Loading() => SliverPrototypeExtentList.builder( - prototypeItem: const VideoReplySkeleton(), - itemBuilder: (_, _) => const VideoReplySkeleton(), - itemCount: 8, - ), + Loading() => replySkeleton, Success(:final response!) => SuperSliverList.builder( listController: _controller.listController, itemBuilder: (context, index) { diff --git a/lib/pages/video/view.dart b/lib/pages/video/view.dart index 024e22094..b096a8e45 100644 --- a/lib/pages/video/view.dart +++ b/lib/pages/video/view.dart @@ -1046,6 +1046,9 @@ class _VideoDetailPageVState extends State return false; }, onSkipSegment: videoDetailController.onSkipSegment, + onDownload: videoDetailController.isFileSource + ? null + : () => videoDetailController.onDownload(context), child: child, ); } diff --git a/lib/pages/video/widgets/player_focus.dart b/lib/pages/video/widgets/player_focus.dart index 4d40f8751..7e5f14d14 100644 --- a/lib/pages/video/widgets/player_focus.dart +++ b/lib/pages/video/widgets/player_focus.dart @@ -24,6 +24,7 @@ class PlayerFocus extends StatelessWidget { this.canPlay, this.onSkipSegment, this.onRefresh, + this.onDownload, }); final Widget child; @@ -33,6 +34,7 @@ class PlayerFocus extends StatelessWidget { final ValueGetter? canPlay; final ValueGetter? onSkipSegment; final VoidCallback? onRefresh; + final VoidCallback? onDownload; static bool _shouldHandle(LogicalKeyboardKey logicalKey) { return logicalKey == LogicalKeyboardKey.tab || @@ -224,6 +226,10 @@ class PlayerFocus extends StatelessWidget { } return true; + case LogicalKeyboardKey.keyX: + onDownload?.call(); + return true; + case LogicalKeyboardKey.enter: if (onSkipSegment?.call() ?? false) { return true; diff --git a/lib/pages/whisper/view.dart b/lib/pages/whisper/view.dart index 3da55f341..d8cb65cd2 100644 --- a/lib/pages/whisper/view.dart +++ b/lib/pages/whisper/view.dart @@ -112,10 +112,7 @@ class _WhisperPageState extends State { color: Colors.grey.withValues(alpha: 0.1), ); return switch (loadingState) { - Loading() => SliverList.builder( - itemCount: 12, - itemBuilder: (context, index) => const WhisperItemSkeleton(), - ), + Loading() => whisperSkeleton, Success(:final response) => response != null && response.isNotEmpty ? SliverList.separated( diff --git a/lib/pages/whisper_secondary/view.dart b/lib/pages/whisper_secondary/view.dart index 559c0628d..bce563216 100644 --- a/lib/pages/whisper_secondary/view.dart +++ b/lib/pages/whisper_secondary/view.dart @@ -96,10 +96,7 @@ class _WhisperSecPageState extends State { color: Colors.grey.withValues(alpha: 0.1), ); return switch (loadingState) { - Loading() => SliverList.builder( - itemCount: 12, - itemBuilder: (context, index) => const WhisperItemSkeleton(), - ), + Loading() => whisperSkeleton, Success(:final response) => response != null && response.isNotEmpty ? SliverList.separated( diff --git a/lib/utils/grid.dart b/lib/utils/grid.dart index 80b461463..0545e5e30 100644 --- a/lib/utils/grid.dart +++ b/lib/utils/grid.dart @@ -8,10 +8,9 @@ import 'package:flutter/rendering.dart'; mixin GridMixin { late final gridDelegate = Grid.videoCardHDelegate(); - Widget get gridSkeleton => SliverGrid.builder( + Widget get gridSkeleton => SliverGrid( gridDelegate: gridDelegate, - itemBuilder: (_, _) => const VideoCardHSkeleton(), - itemCount: 10, + delegate: videoHDelegate, ); } diff --git a/lib/utils/waterfall.dart b/lib/utils/waterfall.dart index ad49462cf..ab3483c65 100644 --- a/lib/utils/waterfall.dart +++ b/lib/utils/waterfall.dart @@ -43,17 +43,9 @@ mixin DynMixin { Widget get dynSkeleton { if (GlobalData.dynamicsWaterfallFlow) { - return SliverGrid.builder( - gridDelegate: skeDelegate, - itemBuilder: (_, _) => const DynamicCardSkeleton(), - itemCount: 10, - ); + return SliverGrid(gridDelegate: skeDelegate, delegate: dynDelegate); } - return SliverPrototypeExtentList.builder( - prototypeItem: const DynamicCardSkeleton(), - itemBuilder: (_, _) => const DynamicCardSkeleton(), - itemCount: 10, - ); + return dynSkeleton_; } }