diff --git a/lib/common/widgets/video_popup_menu.dart b/lib/common/widgets/video_popup_menu.dart index 69f6ae0ce..f395d1769 100644 --- a/lib/common/widgets/video_popup_menu.dart +++ b/lib/common/widgets/video_popup_menu.dart @@ -194,6 +194,9 @@ class VideoCustomActions { SmartDialog.showToast( res['status'] ? "点踩成功" : res['msg'], ); + if (res['status']) { + onRemove?.call(); + } }, style: FilledButton.styleFrom( visualDensity: VisualDensity( diff --git a/lib/pages/rcmd/controller.dart b/lib/pages/rcmd/controller.dart index 8e1bcece4..2d889b40c 100644 --- a/lib/pages/rcmd/controller.dart +++ b/lib/pages/rcmd/controller.dart @@ -4,14 +4,16 @@ import 'package:PiliPlus/pages/common/common_controller.dart'; import 'package:PiliPlus/utils/storage.dart'; class RcmdController extends CommonController { - late bool enableSaveLastData; + late bool enableSaveLastData = GStorage.setting + .get(SettingBoxKey.enableSaveLastData, defaultValue: false); late String defaultRcmdType = 'app'; + int? lastRefreshAt; + late bool savedRcmdTip = GStorage.savedRcmdTip; + @override void onInit() { super.onInit(); - enableSaveLastData = GStorage.setting - .get(SettingBoxKey.enableSaveLastData, defaultValue: false); defaultRcmdType = GStorage.setting .get(SettingBoxKey.defaultRcmdType, defaultValue: 'app'); @@ -34,12 +36,13 @@ class RcmdController extends CommonController { @override List? handleListResponse(List currentList, List dataList) { - return currentPage == 0 && - enableSaveLastData && - currentList.isNotEmpty && - currentList.length < 500 - ? dataList + currentList - : null; + bool shouldSaveLast = enableSaveLastData && currentPage == 0; + if (shouldSaveLast) { + int length = currentList.length; + shouldSaveLast = shouldSaveLast && length > 0 && length < 500; + } + lastRefreshAt = shouldSaveLast && savedRcmdTip ? dataList.length : null; + return shouldSaveLast ? dataList + currentList : null; } @override diff --git a/lib/pages/rcmd/view.dart b/lib/pages/rcmd/view.dart index 14e6eb008..5c8755469 100644 --- a/lib/pages/rcmd/view.dart +++ b/lib/pages/rcmd/view.dart @@ -124,21 +124,73 @@ class _RcmdPageState extends State index == loadingState.response.length - 1) { _controller.onLoadMore(); } - return loadingState is Success - ? widget.tabType == TabType.rcmd - ? VideoCardV( - videoItem: loadingState.response[index], - onRemove: () { - _controller.loadingState.value = LoadingState.success( - (loadingState.response as List)..removeAt(index)); - }, - ) - : LiveCardV( - liveItem: loadingState.response[index], - ) - : const VideoCardVSkeleton(); + if (widget.tabType == TabType.rcmd) { + if (loadingState is Success) { + RcmdController ctr = _controller as RcmdController; + if (ctr.savedRcmdTip) { + if (ctr.lastRefreshAt == index) { + return GestureDetector( + onTap: () { + _controller.animateToTop(); + _controller.onRefresh(); + }, + child: Card( + child: Container( + alignment: Alignment.center, + padding: const EdgeInsets.symmetric(horizontal: 10), + child: Text( + '上次看到这里\n点击刷新', + textAlign: TextAlign.center, + style: TextStyle( + color: + Theme.of(context).colorScheme.onSurfaceVariant, + ), + ), + ), + ), + ); + } + int actualIndex = ctr.lastRefreshAt == null + ? index + : index > ctr.lastRefreshAt! + ? index - 1 + : index; + return VideoCardV( + videoItem: loadingState.response[actualIndex], + onRemove: () { + if (ctr.lastRefreshAt != null && + actualIndex < ctr.lastRefreshAt!) { + ctr.lastRefreshAt = ctr.lastRefreshAt! - 1; + } + _controller.loadingState.value = LoadingState.success( + (loadingState.response as List)..removeAt(actualIndex)); + }, + ); + } else { + return VideoCardV( + videoItem: loadingState.response[index], + onRemove: () { + _controller.loadingState.value = LoadingState.success( + (loadingState.response as List)..removeAt(index)); + }, + ); + } + } + return const VideoCardVSkeleton(); + } else { + return loadingState is Success + ? LiveCardV( + liveItem: loadingState.response[index], + ) + : const VideoCardVSkeleton(); + } }, - childCount: loadingState is Success ? loadingState.response.length : 10, + childCount: loadingState is Success + ? widget.tabType == TabType.rcmd && + (_controller as RcmdController).lastRefreshAt != null + ? loadingState.response.length + 1 + : loadingState.response.length + : 10, ), ); } diff --git a/lib/pages/setting/widgets/model.dart b/lib/pages/setting/widgets/model.dart index ec55ac1fc..6918c178a 100644 --- a/lib/pages/setting/widgets/model.dart +++ b/lib/pages/setting/widgets/model.dart @@ -16,6 +16,7 @@ import 'package:PiliPlus/pages/home/controller.dart'; import 'package:PiliPlus/pages/main/controller.dart'; import 'package:PiliPlus/pages/member/new/controller.dart'; import 'package:PiliPlus/pages/mine/controller.dart'; +import 'package:PiliPlus/pages/rcmd/controller.dart'; import 'package:PiliPlus/pages/setting/pages/color_select.dart'; import 'package:PiliPlus/pages/setting/widgets/multi_select_dialog.dart'; import 'package:PiliPlus/pages/setting/widgets/normal_item.dart'; @@ -1113,12 +1114,33 @@ List get recommendSettings => [ ), SettingsModel( settingsType: SettingsType.sw1tch, - title: '首页推荐刷新', + title: '保留首页推荐刷新', subtitle: '下拉刷新时保留上次内容', leading: Icon(Icons.refresh), setKey: SettingBoxKey.enableSaveLastData, defaultVal: false, - needReboot: true, + onChanged: (value) { + try { + Get.find().enableSaveLastData = value; + } catch (e) { + debugPrint('$e'); + } + }, + ), + SettingsModel( + settingsType: SettingsType.sw1tch, + title: '显示上次看到位置提示', + subtitle: '保留上次推荐时,在上次刷新位置显示提示', + leading: Icon(Icons.tips_and_updates_outlined), + setKey: SettingBoxKey.savedRcmdTip, + defaultVal: true, + onChanged: (value) { + try { + Get.find().savedRcmdTip = value; + } catch (e) { + debugPrint('$e'); + } + }, ), SettingsModel(settingsType: SettingsType.divider), SettingsModel( diff --git a/lib/utils/storage.dart b/lib/utils/storage.dart index 2280ebd47..f638fcd88 100644 --- a/lib/utils/storage.dart +++ b/lib/utils/storage.dart @@ -318,6 +318,9 @@ class GStorage { static bool get horizontalPreview => GStorage.setting .get(SettingBoxKey.horizontalPreview, defaultValue: false); + static bool get savedRcmdTip => + GStorage.setting.get(SettingBoxKey.savedRcmdTip, defaultValue: true); + static List get dynamicDetailRatio => List.from(setting .get(SettingBoxKey.dynamicDetailRatio, defaultValue: [60.0, 40.0])); @@ -530,6 +533,7 @@ class SettingBoxKey { horizontalPreview = 'horizontalPreview', banWordForReply = 'banWordForReply', banWordForZone = 'banWordForZone', + savedRcmdTip = 'savedRcmdTip', // Sponsor Block enableSponsorBlock = 'enableSponsorBlock',