From 931fcb6f8fb4eadcccf9b7bde48f4c1d90f83ebd Mon Sep 17 00:00:00 2001 From: bggRGjQaUbCoE Date: Sun, 12 Oct 2025 17:05:52 +0800 Subject: [PATCH] opt fab Signed-off-by: bggRGjQaUbCoE --- lib/pages/article/view.dart | 10 ++-- lib/pages/dynamics_detail/view.dart | 9 ++-- lib/pages/dynamics_mention/view.dart | 4 +- lib/pages/fav_detail/controller.dart | 12 ++++- lib/pages/fav_detail/view.dart | 74 +++++++++++++++++--------- lib/pages/follow/child/child_view.dart | 4 +- lib/pages/later/base_controller.dart | 12 ++++- lib/pages/later/view.dart | 57 ++++++++++++-------- lib/pages/live_dm_block/view.dart | 4 +- lib/pages/member_opus/view.dart | 4 +- lib/pages/member_video/view.dart | 4 +- lib/pages/music/view.dart | 9 ++-- lib/pages/pgc_review/view.dart | 6 ++- lib/pages/video/post_panel/view.dart | 4 +- lib/pages/video/reply/view.dart | 4 +- lib/pages/webdav/view.dart | 5 +- lib/utils/storage_key.dart | 3 +- lib/utils/storage_pref.dart | 3 ++ 18 files changed, 150 insertions(+), 78 deletions(-) diff --git a/lib/pages/article/view.dart b/lib/pages/article/view.dart index 7f93e739e..c24329202 100644 --- a/lib/pages/article/view.dart +++ b/lib/pages/article/view.dart @@ -558,8 +558,8 @@ class _ArticlePageState extends CommonDynPageState { alignment: Alignment.bottomRight, child: Padding( padding: EdgeInsets.only( - right: 14, - bottom: padding.bottom + 14, + right: kFloatingActionButtonMargin, + bottom: padding.bottom + kFloatingActionButtonMargin, ), child: replyButton, ), @@ -602,8 +602,10 @@ class _ArticlePageState extends CommonDynPageState { Widget btn = Padding( padding: EdgeInsets.only( - right: 14, - bottom: 14 + (stats != null ? 0 : padding.bottom), + right: kFloatingActionButtonMargin, + bottom: + kFloatingActionButtonMargin + + (stats != null ? 0 : padding.bottom), ), child: replyButton, ); diff --git a/lib/pages/dynamics_detail/view.dart b/lib/pages/dynamics_detail/view.dart index 1f754520f..1acc7c4fb 100644 --- a/lib/pages/dynamics_detail/view.dart +++ b/lib/pages/dynamics_detail/view.dart @@ -198,8 +198,8 @@ class _DynamicDetailPageState extends CommonDynPageState { alignment: Alignment.bottomRight, child: Padding( padding: EdgeInsets.only( - right: 14, - bottom: padding.bottom + 14, + right: kFloatingActionButtonMargin, + bottom: padding.bottom + kFloatingActionButtonMargin, ), child: replyButton, ), @@ -243,7 +243,10 @@ class _DynamicDetailPageState extends CommonDynPageState { crossAxisAlignment: CrossAxisAlignment.end, children: [ Padding( - padding: const EdgeInsets.only(right: 14, bottom: 14), + padding: const EdgeInsets.only( + right: kFloatingActionButtonMargin, + bottom: kFloatingActionButtonMargin, + ), child: replyButton, ), Container( diff --git a/lib/pages/dynamics_mention/view.dart b/lib/pages/dynamics_mention/view.dart index 9232e5c37..064f6df23 100644 --- a/lib/pages/dynamics_mention/view.dart +++ b/lib/pages/dynamics_mention/view.dart @@ -196,10 +196,10 @@ class _DynMentionPanelState ), Obx(() { return Positioned( - right: 16, + right: kFloatingActionButtonMargin, bottom: padding + - 16 + + kFloatingActionButtonMargin + (_controller.showBtn.value ? viewInset : 0), child: AnimatedSlide( offset: _controller.showBtn.value diff --git a/lib/pages/fav_detail/controller.dart b/lib/pages/fav_detail/controller.dart index 37c0910f6..36d288047 100644 --- a/lib/pages/fav_detail/controller.dart +++ b/lib/pages/fav_detail/controller.dart @@ -13,6 +13,9 @@ import 'package:PiliPlus/pages/fav_sort/view.dart'; import 'package:PiliPlus/services/account_service.dart'; import 'package:PiliPlus/utils/extension.dart'; 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:flutter/services.dart' show ValueChanged; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; @@ -85,7 +88,14 @@ class FavDetailController AccountService accountService = Get.find(); - late final RxBool isPlayAll = true.obs; + late double dx = 0; + late final RxBool isPlayAll = Pref.enablePlayAll.obs; + + void setIsPlayAll(bool isPlayAll) { + if (this.isPlayAll.value == isPlayAll) return; + this.isPlayAll.value = isPlayAll; + GStorage.setting.put(SettingBoxKey.enablePlayAll, isPlayAll); + } @override void onInit() { diff --git a/lib/pages/fav_detail/view.dart b/lib/pages/fav_detail/view.dart index 4a10023b8..89d83a294 100644 --- a/lib/pages/fav_detail/view.dart +++ b/lib/pages/fav_detail/view.dart @@ -58,31 +58,42 @@ class _FavDetailPageState extends State with GridMixin { }, child: Scaffold( resizeToAvoidBottomInset: false, - floatingActionButton: Obx( - () => _favDetailController.folderInfo.value.mediaCount > 0 - ? AnimatedSlide( - offset: _favDetailController.isPlayAll.value - ? Offset.zero - : const Offset(0.75, 0), - duration: const Duration(milliseconds: 120), - child: GestureDetector( - onHorizontalDragUpdate: (details) => - _favDetailController.isPlayAll.value = - details.delta.dx < 0, - child: FloatingActionButton.extended( - onPressed: () { - if (_favDetailController.isPlayAll.value) { - _favDetailController.toViewPlayAll(); - } else { - _favDetailController.isPlayAll.value = true; - } - }, - label: const Text('播放全部'), - icon: const Icon(Icons.playlist_play), + floatingActionButtonLocation: const CustomFabLocation(), + floatingActionButton: Padding( + padding: const EdgeInsets.only( + right: kFloatingActionButtonMargin, + ), + child: Obx( + () => _favDetailController.folderInfo.value.mediaCount > 0 + ? AnimatedSlide( + offset: _favDetailController.isPlayAll.value + ? Offset.zero + : const Offset(0.75, 0), + duration: const Duration(milliseconds: 120), + child: GestureDetector( + onHorizontalDragDown: (details) => + _favDetailController.dx = + details.localPosition.dx, + onHorizontalDragStart: (details) => + _favDetailController.setIsPlayAll( + details.localPosition.dx < + _favDetailController.dx, + ), + child: FloatingActionButton.extended( + onPressed: () { + if (_favDetailController.isPlayAll.value) { + _favDetailController.toViewPlayAll(); + } else { + _favDetailController.setIsPlayAll(true); + } + }, + label: const Text('播放全部'), + icon: const Icon(Icons.playlist_play), + ), ), - ), - ) - : const SizedBox.shrink(), + ) + : const SizedBox.shrink(), + ), ), body: refreshIndicator( onRefresh: _favDetailController.onRefresh, @@ -509,3 +520,18 @@ class _FavDetailPageState extends State with GridMixin { }; } } + +class CustomFabLocation extends StandardFabLocation with FabFloatOffsetY { + const CustomFabLocation(); + + @override + double getOffsetX( + ScaffoldPrelayoutGeometry scaffoldGeometry, + double adjustment, + ) { + return scaffoldGeometry.scaffoldSize.width - + scaffoldGeometry.minInsets.right - + scaffoldGeometry.floatingActionButtonSize.width + + adjustment; + } +} diff --git a/lib/pages/follow/child/child_view.dart b/lib/pages/follow/child/child_view.dart index f2856389b..af54172dc 100644 --- a/lib/pages/follow/child/child_view.dart +++ b/lib/pages/follow/child/child_view.dart @@ -69,8 +69,8 @@ class _FollowChildPageState extends State children: [ child, Positioned( - right: 16 + padding.right, - bottom: 16 + padding.bottom, + right: kFloatingActionButtonMargin + padding.right, + bottom: kFloatingActionButtonMargin + padding.bottom, child: FloatingActionButton.extended( onPressed: () => _followController ..orderType.value = diff --git a/lib/pages/later/base_controller.dart b/lib/pages/later/base_controller.dart index 663e29088..e934cf047 100644 --- a/lib/pages/later/base_controller.dart +++ b/lib/pages/later/base_controller.dart @@ -1,4 +1,7 @@ import 'package:PiliPlus/models/common/later_view_type.dart'; +import 'package:PiliPlus/utils/storage.dart'; +import 'package:PiliPlus/utils/storage_key.dart'; +import 'package:PiliPlus/utils/storage_pref.dart'; import 'package:get/get.dart'; class LaterBaseController extends GetxController { @@ -9,5 +12,12 @@ class LaterBaseController extends GetxController { for (final item in LaterViewType.values) item: -1, }.obs; - late final RxBool isPlayAll = true.obs; + late double dx = 0; + late final RxBool isPlayAll = Pref.enablePlayAll.obs; + + void setIsPlayAll(bool isPlayAll) { + if (this.isPlayAll.value == isPlayAll) return; + this.isPlayAll.value = isPlayAll; + GStorage.setting.put(SettingBoxKey.enablePlayAll, isPlayAll); + } } diff --git a/lib/pages/later/view.dart b/lib/pages/later/view.dart index 160f70f7b..32870d83b 100644 --- a/lib/pages/later/view.dart +++ b/lib/pages/later/view.dart @@ -4,6 +4,7 @@ import 'package:PiliPlus/common/widgets/view_safe_area.dart'; import 'package:PiliPlus/models/common/later_view_type.dart'; import 'package:PiliPlus/models_new/later/data.dart'; import 'package:PiliPlus/models_new/later/list.dart'; +import 'package:PiliPlus/pages/fav_detail/view.dart'; import 'package:PiliPlus/pages/later/base_controller.dart'; import 'package:PiliPlus/pages/later/controller.dart'; import 'package:PiliPlus/utils/accounts.dart'; @@ -71,30 +72,40 @@ class _LaterPageState extends State child: Scaffold( resizeToAvoidBottomInset: false, appBar: _buildAppbar(enableMultiSelect), - floatingActionButton: Obx( - () => currCtr().loadingState.value.isSuccess - ? AnimatedSlide( - offset: _baseCtr.isPlayAll.value - ? Offset.zero - : const Offset(0.75, 0), - duration: const Duration(milliseconds: 120), - child: GestureDetector( - onHorizontalDragUpdate: (details) => - _baseCtr.isPlayAll.value = details.delta.dx < 0, - child: FloatingActionButton.extended( - onPressed: () { - if (_baseCtr.isPlayAll.value) { - currCtr().toViewPlayAll(); - } else { - _baseCtr.isPlayAll.value = true; - } - }, - label: const Text('播放全部'), - icon: const Icon(Icons.playlist_play), + floatingActionButtonLocation: const CustomFabLocation(), + floatingActionButton: Padding( + padding: const EdgeInsets.only( + right: kFloatingActionButtonMargin, + ), + child: Obx( + () => currCtr().loadingState.value.isSuccess + ? AnimatedSlide( + offset: _baseCtr.isPlayAll.value + ? Offset.zero + : const Offset(0.75, 0), + duration: const Duration(milliseconds: 120), + child: GestureDetector( + onHorizontalDragDown: (details) => + _baseCtr.dx = details.localPosition.dx, + onHorizontalDragStart: (details) => + _baseCtr.setIsPlayAll( + details.localPosition.dx < _baseCtr.dx, + ), + child: FloatingActionButton.extended( + onPressed: () { + if (_baseCtr.isPlayAll.value) { + currCtr().toViewPlayAll(); + } else { + _baseCtr.setIsPlayAll(true); + } + }, + label: const Text('播放全部'), + icon: const Icon(Icons.playlist_play), + ), ), - ), - ) - : const SizedBox.shrink(), + ) + : const SizedBox.shrink(), + ), ), body: ViewSafeArea( child: Column( diff --git a/lib/pages/live_dm_block/view.dart b/lib/pages/live_dm_block/view.dart index 10f4c10aa..31789eede 100644 --- a/lib/pages/live_dm_block/view.dart +++ b/lib/pages/live_dm_block/view.dart @@ -149,8 +149,8 @@ class _LiveDmBlockPageState extends State { ], ), Positioned( - right: 16, - bottom: 16 + padding.bottom, + right: kFloatingActionButtonMargin, + bottom: kFloatingActionButtonMargin + padding.bottom, child: FloatingActionButton( tooltip: '添加', onPressed: _addShieldKeyword, diff --git a/lib/pages/member_opus/view.dart b/lib/pages/member_opus/view.dart index db01c8b30..41d41a1b0 100644 --- a/lib/pages/member_opus/view.dart +++ b/lib/pages/member_opus/view.dart @@ -66,8 +66,8 @@ class _MemberOpusState extends State ), if (_controller.filter?.isNotEmpty == true) Positioned( - right: 16, - bottom: bottom + 16, + right: kFloatingActionButtonMargin, + bottom: bottom + kFloatingActionButtonMargin, child: FloatingActionButton.extended( onPressed: () => showDialog( context: context, diff --git a/lib/pages/member_video/view.dart b/lib/pages/member_video/view.dart index 337ca181a..e0169f210 100644 --- a/lib/pages/member_video/view.dart +++ b/lib/pages/member_video/view.dart @@ -119,8 +119,8 @@ class _MemberVideoState extends State Obx( () => !_controller.isLocating.value ? Positioned( - right: 15 + padding.right, - bottom: 15 + padding.bottom, + right: kFloatingActionButtonMargin + padding.right, + bottom: kFloatingActionButtonMargin + padding.bottom, child: FloatingActionButton.extended( onPressed: () { final fromViewAid = _controller.fromViewAid; diff --git a/lib/pages/music/view.dart b/lib/pages/music/view.dart index 691dc94e9..7f6d75cb1 100644 --- a/lib/pages/music/view.dart +++ b/lib/pages/music/view.dart @@ -241,7 +241,10 @@ class _MusicDetailPageState extends CommonDynPageState { crossAxisAlignment: CrossAxisAlignment.end, children: [ Padding( - padding: const EdgeInsets.only(right: 14, bottom: 14), + padding: const EdgeInsets.only( + right: kFloatingActionButtonMargin, + bottom: kFloatingActionButtonMargin, + ), child: replyButton, ), Container( @@ -335,8 +338,8 @@ class _MusicDetailPageState extends CommonDynPageState { alignment: Alignment.bottomRight, child: Padding( padding: EdgeInsets.only( - right: 14, - bottom: padding.bottom + 14, + right: kFloatingActionButtonMargin, + bottom: padding.bottom + kFloatingActionButtonMargin, ), child: replyButton, ), diff --git a/lib/pages/pgc_review/view.dart b/lib/pages/pgc_review/view.dart index e66ecb496..f323a7768 100644 --- a/lib/pages/pgc_review/view.dart +++ b/lib/pages/pgc_review/view.dart @@ -101,8 +101,10 @@ class _PgcReviewPageState extends State ], ), Positioned( - right: 16, - bottom: MediaQuery.viewPaddingOf(context).bottom + 16, + right: kFloatingActionButtonMargin, + bottom: + MediaQuery.viewPaddingOf(context).bottom + + kFloatingActionButtonMargin, child: FloatingActionButton( onPressed: () => showDialog( context: context, diff --git a/lib/pages/video/post_panel/view.dart b/lib/pages/video/post_panel/view.dart index 8271bf69c..35a407f15 100644 --- a/lib/pages/video/post_panel/view.dart +++ b/lib/pages/video/post_panel/view.dart @@ -276,8 +276,8 @@ class _PostPanelState extends State children: [ child, Positioned( - right: 16, - bottom: 16 + bottom, + right: kFloatingActionButtonMargin, + bottom: kFloatingActionButtonMargin + bottom, child: FloatingActionButton( tooltip: '提交', onPressed: () => showDialog( diff --git a/lib/pages/video/reply/view.dart b/lib/pages/video/reply/view.dart index 124ade9ac..58e13e128 100644 --- a/lib/pages/video/reply/view.dart +++ b/lib/pages/video/reply/view.dart @@ -143,8 +143,8 @@ class _VideoReplyPanelState extends State ], ), Positioned( - right: 14, - bottom: 14 + bottom, + right: kFloatingActionButtonMargin, + bottom: kFloatingActionButtonMargin + bottom, child: SlideTransition( position: _videoReplyController.anim, child: FloatingActionButton( diff --git a/lib/pages/webdav/view.dart b/lib/pages/webdav/view.dart index e06f7beea..c9d16360b 100644 --- a/lib/pages/webdav/view.dart +++ b/lib/pages/webdav/view.dart @@ -122,8 +122,9 @@ class _WebDavSettingPageState extends State { ], ), Positioned( - right: 16 + (showAppBar ? padding.right : 0), - bottom: 16 + padding.bottom, + right: + kFloatingActionButtonMargin + (showAppBar ? padding.right : 0), + bottom: kFloatingActionButtonMargin + padding.bottom, child: FloatingActionButton( child: const Icon(Icons.save), onPressed: () async { diff --git a/lib/utils/storage_key.dart b/lib/utils/storage_key.dart index 2991b681c..574a5f466 100644 --- a/lib/utils/storage_key.dart +++ b/lib/utils/storage_key.dart @@ -140,7 +140,8 @@ abstract class SettingBoxKey { showFsScreenshotBtn = 'showFsScreenshotBtn', showFsLockBtn = 'showFsLockBtn', silentDownImg = 'silentDownImg', - showMemberShop = 'showMemberShop'; + showMemberShop = 'showMemberShop', + enablePlayAll = 'enablePlayAll'; static const String minimizeOnExit = 'minimizeOnExit', windowSize = 'windowSize', diff --git a/lib/utils/storage_pref.dart b/lib/utils/storage_pref.dart index 199fb086e..c7ba98656 100644 --- a/lib/utils/storage_pref.dart +++ b/lib/utils/storage_pref.dart @@ -855,4 +855,7 @@ abstract class Pref { static PlayRepeat get audioPlayMode => PlayRepeat.values[_setting.get(SettingBoxKey.audioPlayMode) ?? PlayRepeat.listOrder.index]; + + static bool get enablePlayAll => + _setting.get(SettingBoxKey.enablePlayAll, defaultValue: true); }