feat: add copy/move support to fav/later search results (#1822)

* feat: add copy/move support to fav/later search results

* update

Signed-off-by: dom <githubaccount56556@proton.me>

---------

Co-authored-by: dom <githubaccount56556@proton.me>
This commit is contained in:
систем
2026-02-03 10:21:01 +08:00
committed by GitHub
parent 7260a387f9
commit 18e0b93ca7
5 changed files with 126 additions and 78 deletions

View File

@@ -6,7 +6,6 @@ import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart';
import 'package:PiliPlus/http/fav.dart'; import 'package:PiliPlus/http/fav.dart';
import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/models/common/fav_order_type.dart'; import 'package:PiliPlus/models/common/fav_order_type.dart';
import 'package:PiliPlus/models_new/fav/fav_detail/data.dart';
import 'package:PiliPlus/models_new/fav/fav_detail/media.dart'; import 'package:PiliPlus/models_new/fav/fav_detail/media.dart';
import 'package:PiliPlus/models_new/fav/fav_folder/list.dart'; import 'package:PiliPlus/models_new/fav/fav_folder/list.dart';
import 'package:PiliPlus/pages/dynamics_repost/view.dart'; import 'package:PiliPlus/pages/dynamics_repost/view.dart';
@@ -305,56 +304,39 @@ class _FavDetailPageState extends State<FavDetailPage> with GridMixin {
]; ];
} }
List<Widget> _selectActions(ThemeData theme) => [ List<Widget> _selectActions(ThemeData theme) {
final btnStyle = TextButton.styleFrom(visualDensity: .compact);
final textStyle = TextStyle(color: theme.colorScheme.onSurfaceVariant);
return [
TextButton( TextButton(
style: TextButton.styleFrom( style: btnStyle,
visualDensity: VisualDensity.compact,
),
onPressed: () => _favDetailController.handleSelect(checked: true), onPressed: () => _favDetailController.handleSelect(checked: true),
child: const Text('全选'), child: const Text('全选'),
), ),
TextButton( TextButton(
style: TextButton.styleFrom( style: btnStyle,
visualDensity: VisualDensity.compact, onPressed: () => RequestUtils.onCopyOrMove<FavDetailItemModel>(
),
onPressed: () =>
RequestUtils.onCopyOrMove<FavDetailData, FavDetailItemModel>(
context: context, context: context,
isCopy: true, isCopy: true,
ctr: _favDetailController, ctr: _favDetailController,
mediaId: _favDetailController.mediaId, mediaId: _favDetailController.mediaId,
mid: _favDetailController.account.mid, mid: _favDetailController.account.mid,
), ),
child: Text( child: Text('复制', style: textStyle),
'复制',
style: TextStyle(
color: theme.colorScheme.onSurfaceVariant,
),
),
), ),
TextButton( TextButton(
style: TextButton.styleFrom( style: btnStyle,
visualDensity: VisualDensity.compact, onPressed: () => RequestUtils.onCopyOrMove<FavDetailItemModel>(
),
onPressed: () =>
RequestUtils.onCopyOrMove<FavDetailData, FavDetailItemModel>(
context: context, context: context,
isCopy: false, isCopy: false,
ctr: _favDetailController, ctr: _favDetailController,
mediaId: _favDetailController.mediaId, mediaId: _favDetailController.mediaId,
mid: _favDetailController.account.mid, mid: _favDetailController.account.mid,
), ),
child: Text( child: Text('移动', style: textStyle),
'移动',
style: TextStyle(
color: theme.colorScheme.onSurfaceVariant,
),
),
), ),
TextButton( TextButton(
style: TextButton.styleFrom( style: btnStyle,
visualDensity: VisualDensity.compact,
),
onPressed: _favDetailController.onRemove, onPressed: _favDetailController.onRemove,
child: Text( child: Text(
'删除', '删除',
@@ -363,6 +345,7 @@ class _FavDetailPageState extends State<FavDetailPage> with GridMixin {
), ),
const SizedBox(width: 10), const SizedBox(width: 10),
]; ];
}
Widget _flexibleSpace(ThemeData theme) { Widget _flexibleSpace(ThemeData theme) {
final style = TextStyle( final style = TextStyle(

View File

@@ -4,7 +4,9 @@ import 'package:PiliPlus/models_new/fav/fav_detail/media.dart';
import 'package:PiliPlus/pages/common/search/common_search_page.dart'; import 'package:PiliPlus/pages/common/search/common_search_page.dart';
import 'package:PiliPlus/pages/fav_detail/widget/fav_video_card.dart'; import 'package:PiliPlus/pages/fav_detail/widget/fav_video_card.dart';
import 'package:PiliPlus/pages/fav_search/controller.dart'; import 'package:PiliPlus/pages/fav_search/controller.dart';
import 'package:PiliPlus/utils/accounts.dart';
import 'package:PiliPlus/utils/grid.dart'; import 'package:PiliPlus/utils/grid.dart';
import 'package:PiliPlus/utils/request_utils.dart';
import 'package:PiliPlus/utils/utils.dart'; import 'package:PiliPlus/utils/utils.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
@@ -29,6 +31,38 @@ class _FavSearchPageState
tag: Utils.generateRandomString(8), tag: Utils.generateRandomString(8),
); );
@override
List<Widget>? get multiSelectActions {
final btnStyle = TextButton.styleFrom(visualDensity: .compact);
final textStyle = TextStyle(
color: ColorScheme.of(context).onSurfaceVariant,
);
return [
TextButton(
style: btnStyle,
onPressed: () => RequestUtils.onCopyOrMove<FavDetailItemModel>(
context: context,
isCopy: true,
ctr: controller,
mediaId: controller.mediaId,
mid: Accounts.main.mid,
),
child: Text('复制', style: textStyle),
),
TextButton(
style: btnStyle,
onPressed: () => RequestUtils.onCopyOrMove<FavDetailItemModel>(
context: context,
isCopy: false,
ctr: controller,
mediaId: controller.mediaId,
mid: Accounts.main.mid,
),
child: Text('移动', style: textStyle),
),
];
}
@override @override
List<Widget>? get extraActions => [ List<Widget>? get extraActions => [
Obx( Obx(

View File

@@ -4,7 +4,6 @@ import 'package:PiliPlus/common/widgets/gesture/horizontal_drag_gesture_recogniz
import 'package:PiliPlus/common/widgets/scroll_physics.dart'; import 'package:PiliPlus/common/widgets/scroll_physics.dart';
import 'package:PiliPlus/common/widgets/view_safe_area.dart'; import 'package:PiliPlus/common/widgets/view_safe_area.dart';
import 'package:PiliPlus/models/common/later_view_type.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/models_new/later/list.dart';
import 'package:PiliPlus/pages/fav_detail/view.dart'; import 'package:PiliPlus/pages/fav_detail/view.dart';
import 'package:PiliPlus/pages/later/base_controller.dart'; import 'package:PiliPlus/pages/later/base_controller.dart';
@@ -154,16 +153,17 @@ class _LaterPageState extends State<LaterPage>
PreferredSizeWidget _buildAppbar(bool enableMultiSelect) { PreferredSizeWidget _buildAppbar(bool enableMultiSelect) {
final theme = Theme.of(context); final theme = Theme.of(context);
Color color = theme.colorScheme.secondary; Color color = theme.colorScheme.secondary;
final btnStyle = TextButton.styleFrom(visualDensity: .compact);
final textStyle = TextStyle(color: theme.colorScheme.onSurfaceVariant);
return MultiSelectAppBarWidget( return MultiSelectAppBarWidget(
visible: enableMultiSelect, visible: enableMultiSelect,
ctr: currCtr(), ctr: currCtr(),
actions: [ actions: [
TextButton( TextButton(
style: TextButton.styleFrom(visualDensity: .compact), style: btnStyle,
onPressed: () { onPressed: () {
final ctr = currCtr(); final ctr = currCtr();
RequestUtils.onCopyOrMove<LaterData, LaterItemModel>( RequestUtils.onCopyOrMove<LaterItemModel>(
context: context, context: context,
isCopy: true, isCopy: true,
ctr: ctr, ctr: ctr,
@@ -171,16 +171,13 @@ class _LaterPageState extends State<LaterPage>
mid: ctr.mid, mid: ctr.mid,
); );
}, },
child: Text( child: Text('复制', style: textStyle),
'复制',
style: TextStyle(color: theme.colorScheme.onSurfaceVariant),
),
), ),
TextButton( TextButton(
style: TextButton.styleFrom(visualDensity: .compact), style: btnStyle,
onPressed: () { onPressed: () {
final ctr = currCtr(); final ctr = currCtr();
RequestUtils.onCopyOrMove<LaterData, LaterItemModel>( RequestUtils.onCopyOrMove<LaterItemModel>(
context: context, context: context,
isCopy: false, isCopy: false,
ctr: ctr, ctr: ctr,
@@ -188,10 +185,7 @@ class _LaterPageState extends State<LaterPage>
mid: ctr.mid, mid: ctr.mid,
); );
}, },
child: Text( child: Text('移动', style: textStyle),
'移动',
style: TextStyle(color: theme.colorScheme.onSurfaceVariant),
),
), ),
], ],
child: AppBar( child: AppBar(

View File

@@ -6,6 +6,7 @@ import 'package:PiliPlus/pages/later/widgets/video_card_h_later.dart';
import 'package:PiliPlus/pages/later_search/controller.dart'; import 'package:PiliPlus/pages/later_search/controller.dart';
import 'package:PiliPlus/utils/grid.dart'; import 'package:PiliPlus/utils/grid.dart';
import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart';
import 'package:PiliPlus/utils/request_utils.dart';
import 'package:PiliPlus/utils/utils.dart'; import 'package:PiliPlus/utils/utils.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
@@ -25,6 +26,38 @@ class _LaterSearchPageState
tag: Utils.generateRandomString(8), tag: Utils.generateRandomString(8),
); );
@override
List<Widget>? get multiSelectActions {
final btnStyle = TextButton.styleFrom(visualDensity: .compact);
final textStyle = TextStyle(
color: ColorScheme.of(context).onSurfaceVariant,
);
return [
TextButton(
style: btnStyle,
onPressed: () => RequestUtils.onCopyOrMove<LaterItemModel>(
context: context,
isCopy: true,
ctr: controller,
mediaId: null,
mid: controller.mid,
),
child: Text('复制', style: textStyle),
),
TextButton(
style: btnStyle,
onPressed: () => RequestUtils.onCopyOrMove<LaterItemModel>(
context: context,
isCopy: false,
ctr: controller,
mediaId: null,
mid: controller.mid,
),
child: Text('移动', style: textStyle),
),
];
}
late final gridDelegate = Grid.videoCardHDelegate(context, minHeight: 110); late final gridDelegate = Grid.videoCardHDelegate(context, minHeight: 110);
@override @override

View File

@@ -16,11 +16,13 @@ import 'package:PiliPlus/http/validate.dart';
import 'package:PiliPlus/http/video.dart'; import 'package:PiliPlus/http/video.dart';
import 'package:PiliPlus/models/dynamics/result.dart'; import 'package:PiliPlus/models/dynamics/result.dart';
import 'package:PiliPlus/models/login/model.dart'; import 'package:PiliPlus/models/login/model.dart';
import 'package:PiliPlus/models_new/fav/fav_detail/media.dart';
import 'package:PiliPlus/models_new/later/list.dart';
import 'package:PiliPlus/pages/common/multi_select/base.dart'; import 'package:PiliPlus/pages/common/multi_select/base.dart';
import 'package:PiliPlus/pages/common/multi_select/multi_select_controller.dart';
import 'package:PiliPlus/pages/dynamics_tab/controller.dart'; import 'package:PiliPlus/pages/dynamics_tab/controller.dart';
import 'package:PiliPlus/pages/fav_detail/controller.dart'
show BaseFavController;
import 'package:PiliPlus/pages/group_panel/view.dart'; import 'package:PiliPlus/pages/group_panel/view.dart';
import 'package:PiliPlus/pages/later/controller.dart';
import 'package:PiliPlus/pages/login/geetest/geetest_webview_dialog.dart'; import 'package:PiliPlus/pages/login/geetest/geetest_webview_dialog.dart';
import 'package:PiliPlus/utils/accounts.dart'; import 'package:PiliPlus/utils/accounts.dart';
import 'package:PiliPlus/utils/extension/context_ext.dart'; import 'package:PiliPlus/utils/extension/context_ext.dart';
@@ -387,10 +389,10 @@ abstract final class RequestUtils {
} }
} }
static void onCopyOrMove<R, T extends MultiSelectData>({ static void onCopyOrMove<T extends MultiSelectData>({
required BuildContext context, required BuildContext context,
required bool isCopy, required bool isCopy,
required MultiSelectController<R, T> ctr, required CommonMultiSelectMixin<T> ctr,
required dynamic mediaId, required dynamic mediaId,
required dynamic mid, required dynamic mid,
}) { }) {
@@ -437,18 +439,20 @@ abstract final class RequestUtils {
TextButton( TextButton(
onPressed: () { onPressed: () {
if (checkedId != null) { if (checkedId != null) {
Set removeList = ctr.allChecked.toSet(); final removeList = ctr.allChecked.toSet();
SmartDialog.showLoading(); SmartDialog.showLoading();
FavHttp.copyOrMoveFav( FavHttp.copyOrMoveFav(
isCopy: isCopy, isCopy: isCopy,
isFav: ctr is! LaterController, isFav: ctr is BaseFavController,
srcMediaId: mediaId, srcMediaId: mediaId,
tarMediaId: checkedId, tarMediaId: checkedId,
resources: removeList resources: removeList
.map( .map(
(item) => ctr is LaterController (e) => switch (e) {
? item.aid LaterItemModel _ => e.aid,
: '${item.id}:${item.type}', FavDetailItemModel _ => '${e.id}:${e.type}',
_ => throw UnsupportedError(e.toString()),
},
) )
.join(','), .join(','),
mid: isCopy ? mid : null, mid: isCopy ? mid : null,