mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-16 07:06:14 +08:00
opt: multiSelect (#935)
This commit is contained in:
committed by
GitHub
parent
d246462535
commit
7b51f15753
91
lib/common/widgets/appbar/appbar.dart
Normal file
91
lib/common/widgets/appbar/appbar.dart
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
import 'package:PiliPlus/pages/common/multi_select_controller.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
|
class AppBarWidget extends StatelessWidget implements PreferredSizeWidget {
|
||||||
|
const AppBarWidget({
|
||||||
|
required this.child1,
|
||||||
|
required this.child2,
|
||||||
|
required this.visible,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
final PreferredSizeWidget child1;
|
||||||
|
final PreferredSizeWidget child2;
|
||||||
|
final bool visible;
|
||||||
|
@override
|
||||||
|
Size get preferredSize => child1.preferredSize;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AnimatedSwitcher(
|
||||||
|
duration: const Duration(milliseconds: 500),
|
||||||
|
transitionBuilder: (Widget child, Animation<double> animation) {
|
||||||
|
return ScaleTransition(
|
||||||
|
scale: animation,
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: !visible
|
||||||
|
? KeyedSubtree.wrap(child1, 0)
|
||||||
|
: KeyedSubtree.wrap(child2, 1),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MultiSelectAppBarWidget extends StatelessWidget
|
||||||
|
implements PreferredSizeWidget {
|
||||||
|
final MultiSelectMixin ctr;
|
||||||
|
final bool? visible;
|
||||||
|
final AppBar child;
|
||||||
|
final List<Widget>? children;
|
||||||
|
|
||||||
|
const MultiSelectAppBarWidget({
|
||||||
|
super.key,
|
||||||
|
required this.ctr,
|
||||||
|
this.visible,
|
||||||
|
this.children,
|
||||||
|
required this.child,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AppBarWidget(
|
||||||
|
visible: visible ?? ctr.enableMultiSelect.value,
|
||||||
|
child1: child,
|
||||||
|
child2: AppBar(
|
||||||
|
bottom: child.bottom,
|
||||||
|
leading: IconButton(
|
||||||
|
tooltip: '取消',
|
||||||
|
onPressed: ctr.handleSelect,
|
||||||
|
icon: const Icon(Icons.close_outlined),
|
||||||
|
),
|
||||||
|
title: Obx(() => Text('已选: ${ctr.checkedCount}')),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
visualDensity: VisualDensity.compact,
|
||||||
|
),
|
||||||
|
onPressed: () => ctr.handleSelect(true),
|
||||||
|
child: const Text('全选'),
|
||||||
|
),
|
||||||
|
...?children,
|
||||||
|
TextButton(
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
visualDensity: VisualDensity.compact,
|
||||||
|
),
|
||||||
|
onPressed: ctr.onConfirm,
|
||||||
|
child: Text(
|
||||||
|
'移除',
|
||||||
|
style: TextStyle(color: Get.theme.colorScheme.error),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 6),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Size get preferredSize => child.preferredSize;
|
||||||
|
}
|
||||||
@@ -312,7 +312,7 @@ class FavHttp {
|
|||||||
|
|
||||||
static Future delNote({
|
static Future delNote({
|
||||||
required bool isPublish,
|
required bool isPublish,
|
||||||
required List noteIds,
|
required Iterable noteIds,
|
||||||
}) async {
|
}) async {
|
||||||
final res = await Request().post(
|
final res = await Request().post(
|
||||||
isPublish ? Api.delPublishNote : Api.delNote,
|
isPublish ? Api.delPublishNote : Api.delNote,
|
||||||
@@ -637,13 +637,13 @@ class FavHttp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future copyOrMoveFav({
|
static Future<LoadingState> copyOrMoveFav({
|
||||||
required bool isCopy,
|
required bool isCopy,
|
||||||
required bool isFav,
|
required bool isFav,
|
||||||
required dynamic srcMediaId,
|
required dynamic srcMediaId,
|
||||||
required dynamic tarMediaId,
|
required dynamic tarMediaId,
|
||||||
dynamic mid,
|
dynamic mid,
|
||||||
required List resources,
|
required Iterable resources,
|
||||||
}) async {
|
}) async {
|
||||||
var res = await Request().post(
|
var res = await Request().post(
|
||||||
isFav
|
isFav
|
||||||
@@ -664,21 +664,21 @@ class FavHttp {
|
|||||||
options: Options(contentType: Headers.formUrlEncodedContentType),
|
options: Options(contentType: Headers.formUrlEncodedContentType),
|
||||||
);
|
);
|
||||||
if (res.data['code'] == 0) {
|
if (res.data['code'] == 0) {
|
||||||
return {'status': true};
|
return const Success(null);
|
||||||
} else {
|
} else {
|
||||||
return {'status': false, 'msg': res.data['message']};
|
return Error(res.data['message']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future allFavFolders(mid) async {
|
static Future<LoadingState<FavFolderData>> allFavFolders(Object mid) async {
|
||||||
var res = await Request().get(
|
var res = await Request().get(
|
||||||
Api.favFolder,
|
Api.favFolder,
|
||||||
queryParameters: {'up_mid': mid},
|
queryParameters: {'up_mid': mid},
|
||||||
);
|
);
|
||||||
if (res.data['code'] == 0) {
|
if (res.data['code'] == 0) {
|
||||||
return {'status': true, 'data': FavFolderData.fromJson(res.data['data'])};
|
return Success(FavFolderData.fromJson(res.data['data']));
|
||||||
} else {
|
} else {
|
||||||
return {'status': false, 'msg': res.data['message']};
|
return Error(res.data['message']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ class UserHttp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 移除已观看
|
// 移除已观看
|
||||||
static Future toViewDel({required List<int?> aids}) async {
|
static Future toViewDel({required Iterable<int> aids}) async {
|
||||||
final Map<String, dynamic> params = {
|
final Map<String, dynamic> params = {
|
||||||
'csrf': Accounts.main.csrf,
|
'csrf': Accounts.main.csrf,
|
||||||
'resources': aids.join(','),
|
'resources': aids.join(','),
|
||||||
@@ -204,7 +204,7 @@ class UserHttp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 删除历史记录
|
// 删除历史记录
|
||||||
static Future delHistory(List<String> kidList) async {
|
static Future delHistory(Iterable<String> kidList) async {
|
||||||
var res = await Request().post(
|
var res = await Request().post(
|
||||||
Api.delHistory,
|
Api.delHistory,
|
||||||
data: {
|
data: {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:PiliPlus/http/loading_state.dart';
|
||||||
import 'package:PiliPlus/pages/common/common_list_controller.dart';
|
import 'package:PiliPlus/pages/common/common_list_controller.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
@@ -5,35 +6,60 @@ mixin MultiSelectData {
|
|||||||
bool? checked;
|
bool? checked;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class MultiSelectController<R, T extends MultiSelectData>
|
mixin MultiSelectMixin<T> {
|
||||||
extends CommonListController<R, T> {
|
|
||||||
late final RxBool enableMultiSelect = false.obs;
|
late final RxBool enableMultiSelect = false.obs;
|
||||||
late final RxInt checkedCount = 0.obs;
|
|
||||||
late final allSelected = false.obs;
|
late final allSelected = false.obs;
|
||||||
|
|
||||||
|
int get checkedCount;
|
||||||
|
|
||||||
|
void onSelect(T item, [bool disableSelect = true]);
|
||||||
|
void handleSelect([bool checked = false, bool disableSelect = true]);
|
||||||
|
void onConfirm();
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class MultiSelectController<R, T extends MultiSelectData>
|
||||||
|
extends CommonListController<R, T>
|
||||||
|
with MultiSelectMixin<T>, CommonMultiSelectMixin, DeleteItemMixin {}
|
||||||
|
|
||||||
|
mixin CommonMultiSelectMixin<T extends MultiSelectData> on MultiSelectMixin<T> {
|
||||||
|
Rx<LoadingState<List<T>?>> get loadingState;
|
||||||
|
late final RxInt rxCount = 0.obs;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get checkedCount => rxCount.value;
|
||||||
|
|
||||||
|
Iterable<T> get allChecked =>
|
||||||
|
loadingState.value.data!.where((v) => v.checked == true);
|
||||||
|
|
||||||
|
@override
|
||||||
void onSelect(T item, [bool disableSelect = true]) {
|
void onSelect(T item, [bool disableSelect = true]) {
|
||||||
List<T> list = loadingState.value.data!;
|
List<T> list = loadingState.value.data!;
|
||||||
item.checked = !(item.checked ?? false);
|
item.checked = !(item.checked ?? false);
|
||||||
checkedCount.value = list.where((item) => item.checked == true).length;
|
if (item.checked!) {
|
||||||
|
rxCount.value++;
|
||||||
|
} else {
|
||||||
|
rxCount.value--;
|
||||||
|
}
|
||||||
loadingState.refresh();
|
loadingState.refresh();
|
||||||
if (disableSelect) {
|
if (disableSelect) {
|
||||||
if (checkedCount.value == 0) {
|
if (checkedCount == 0) {
|
||||||
enableMultiSelect.value = false;
|
enableMultiSelect.value = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
allSelected.value = checkedCount.value == list.length;
|
allSelected.value = checkedCount == list.length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
void handleSelect([bool checked = false, bool disableSelect = true]) {
|
void handleSelect([bool checked = false, bool disableSelect = true]) {
|
||||||
if (loadingState.value.isSuccess) {
|
if (loadingState.value.isSuccess) {
|
||||||
List<T>? list = loadingState.value.data;
|
final list = loadingState.value.data;
|
||||||
if (list?.isNotEmpty == true) {
|
if (list?.isNotEmpty == true) {
|
||||||
for (T item in list!) {
|
for (var item in list!) {
|
||||||
item.checked = checked;
|
item.checked = checked;
|
||||||
}
|
}
|
||||||
loadingState.refresh();
|
loadingState.refresh();
|
||||||
checkedCount.value = checked ? list.length : 0;
|
rxCount.value = checked ? list.length : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (disableSelect && !checked) {
|
if (disableSelect && !checked) {
|
||||||
@@ -41,3 +67,75 @@ abstract class MultiSelectController<R, T extends MultiSelectData>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mixin DeleteItemMixin<R, T extends MultiSelectData>
|
||||||
|
on CommonListController<R, T>, CommonMultiSelectMixin<T> {
|
||||||
|
Future<void> afterDelete(Set<T> result) async {
|
||||||
|
// TODO: result require hash
|
||||||
|
final remainList = loadingState.value.data!;
|
||||||
|
if (result.length == 1) {
|
||||||
|
remainList.remove(result.single);
|
||||||
|
} else {
|
||||||
|
remainList.removeWhere(result.contains);
|
||||||
|
}
|
||||||
|
if (remainList.isNotEmpty) {
|
||||||
|
loadingState.refresh();
|
||||||
|
} else if (!isEnd) {
|
||||||
|
onReload();
|
||||||
|
}
|
||||||
|
if (enableMultiSelect.value) {
|
||||||
|
rxCount.value = 0;
|
||||||
|
enableMultiSelect.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// abstract class SetMultiSelectController<R, T, I>
|
||||||
|
// extends CommonListController<R, T>
|
||||||
|
// with MultiSelectMixin<T>, SetCommonMultiSelectMixin<T, I> {}
|
||||||
|
|
||||||
|
// mixin SetCommonMultiSelectMixin<T, R> on MultiSelectMixin<T> {
|
||||||
|
// Rx<LoadingState<List<T>?>> get loadingState;
|
||||||
|
// RxSet<R> get selected;
|
||||||
|
|
||||||
|
// @override
|
||||||
|
// int get checkedCount => selected.length;
|
||||||
|
|
||||||
|
// R getId(T item);
|
||||||
|
|
||||||
|
// @override
|
||||||
|
// void onSelect(T item, [bool disableSelect = true]) {
|
||||||
|
// final id = getId(item);
|
||||||
|
// if (selected.contains(id)) {
|
||||||
|
// selected.remove(id);
|
||||||
|
// } else {
|
||||||
|
// selected.add(id);
|
||||||
|
// }
|
||||||
|
// loadingState.refresh();
|
||||||
|
// if (disableSelect) {
|
||||||
|
// if (checkedCount == 0) {
|
||||||
|
// enableMultiSelect.value = false;
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// allSelected.value = checkedCount == loadingState.value.data!.length;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @override
|
||||||
|
// void handleSelect([bool checked = false, bool disableSelect = true]) {
|
||||||
|
// if (loadingState.value.isSuccess) {
|
||||||
|
// final list = loadingState.value.data;
|
||||||
|
// if (list?.isNotEmpty == true) {
|
||||||
|
// if (checked) {
|
||||||
|
// selected.addAll(list!.map(getId));
|
||||||
|
// } else {
|
||||||
|
// selected.clear();
|
||||||
|
// }
|
||||||
|
// loadingState.refresh();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if (disableSelect && !checked) {
|
||||||
|
// enableMultiSelect.value = false;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ class _CreateVotePageState extends State<CreateVotePage> {
|
|||||||
..add(
|
..add(
|
||||||
_buildInput(
|
_buildInput(
|
||||||
theme,
|
theme,
|
||||||
key: ValueKey(e.hashCode),
|
key: ObjectKey(e),
|
||||||
showDel: showDel,
|
showDel: showDel,
|
||||||
onDel: () {
|
onDel: () {
|
||||||
FocusManager.instance.primaryFocus?.unfocus();
|
FocusManager.instance.primaryFocus?.unfocus();
|
||||||
|
|||||||
@@ -115,11 +115,11 @@ class _FavNoteChildPageState extends State<FavNoteChildPage>
|
|||||||
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (_favNoteController.checkedCount.value != 0) {
|
if (_favNoteController.checkedCount != 0) {
|
||||||
showConfirmDialog(
|
showConfirmDialog(
|
||||||
context: context,
|
context: context,
|
||||||
title: '确定删除已选中的笔记吗?',
|
title: '确定删除已选中的笔记吗?',
|
||||||
onConfirm: _favNoteController.onRemove,
|
onConfirm: _favNoteController.onConfirm,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -34,24 +34,15 @@ class FavNoteController
|
|||||||
: FavHttp.noteList(page: page);
|
: FavHttp.noteList(page: page);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> onRemove() async {
|
@override
|
||||||
List<FavNoteItemModel> dataList = loadingState.value.data!;
|
Future<void> onConfirm() async {
|
||||||
Set<FavNoteItemModel> removeList = dataList
|
Set<FavNoteItemModel> removeList = allChecked.toSet();
|
||||||
.where((item) => item.checked == true)
|
|
||||||
.toSet();
|
|
||||||
final res = await FavHttp.delNote(
|
final res = await FavHttp.delNote(
|
||||||
isPublish: isPublish,
|
isPublish: isPublish,
|
||||||
noteIds: removeList
|
noteIds: removeList.map((item) => isPublish ? item.cvid : item.noteId),
|
||||||
.map((item) => isPublish ? item.cvid : item.noteId)
|
|
||||||
.toList(),
|
|
||||||
);
|
);
|
||||||
if (res['status']) {
|
if (res['status']) {
|
||||||
List<FavNoteItemModel> remainList = dataList
|
afterDelete(removeList);
|
||||||
.toSet()
|
|
||||||
.difference(removeList)
|
|
||||||
.toList();
|
|
||||||
loadingState.value = Success(remainList);
|
|
||||||
enableMultiSelect.value = false;
|
|
||||||
SmartDialog.showToast('删除成功');
|
SmartDialog.showToast('删除成功');
|
||||||
} else {
|
} else {
|
||||||
SmartDialog.showToast(res['msg']);
|
SmartDialog.showToast(res['msg']);
|
||||||
@@ -59,7 +50,7 @@ class FavNoteController
|
|||||||
}
|
}
|
||||||
|
|
||||||
void onDisable() {
|
void onDisable() {
|
||||||
if (checkedCount.value != 0) {
|
if (checkedCount != 0) {
|
||||||
handleSelect();
|
handleSelect();
|
||||||
}
|
}
|
||||||
enableMultiSelect.value = false;
|
enableMultiSelect.value = false;
|
||||||
|
|||||||
@@ -128,8 +128,7 @@ class _FavPgcChildPageState extends State<FavPgcChildPage>
|
|||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
behavior: HitTestBehavior.opaque,
|
behavior: HitTestBehavior.opaque,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (_favPgcController.checkedCount.value !=
|
if (_favPgcController.checkedCount != 0) {
|
||||||
0) {
|
|
||||||
_favPgcController.onUpdateList(
|
_favPgcController.onUpdateList(
|
||||||
item.followStatus,
|
item.followStatus,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ class FavPgcController
|
|||||||
);
|
);
|
||||||
|
|
||||||
void onDisable() {
|
void onDisable() {
|
||||||
if (checkedCount.value != 0) {
|
if (checkedCount != 0) {
|
||||||
handleSelect();
|
handleSelect();
|
||||||
}
|
}
|
||||||
enableMultiSelect.value = false;
|
enableMultiSelect.value = false;
|
||||||
@@ -65,22 +65,19 @@ class FavPgcController
|
|||||||
SmartDialog.showToast(result['msg']);
|
SmartDialog.showToast(result['msg']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onConfirm() {
|
||||||
|
assert(false, 'call onUpdateList');
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> onUpdateList(int followStatus) async {
|
Future<void> onUpdateList(int followStatus) async {
|
||||||
List<FavPgcItemModel> dataList = loadingState.value.data!;
|
final updateList = allChecked.toSet();
|
||||||
Set<FavPgcItemModel> updateList = dataList
|
|
||||||
.where((item) => item.checked == true)
|
|
||||||
.toSet();
|
|
||||||
final res = await VideoHttp.pgcUpdate(
|
final res = await VideoHttp.pgcUpdate(
|
||||||
seasonId: updateList.map((item) => item.seasonId).toList(),
|
seasonId: updateList.map((item) => item.seasonId).toList(),
|
||||||
status: followStatus,
|
status: followStatus,
|
||||||
);
|
);
|
||||||
if (res['status']) {
|
if (res['status']) {
|
||||||
List<FavPgcItemModel> remainList = dataList
|
afterDelete(updateList);
|
||||||
.toSet()
|
|
||||||
.difference(updateList)
|
|
||||||
.toList();
|
|
||||||
loadingState.value = Success(remainList);
|
|
||||||
enableMultiSelect.value = false;
|
|
||||||
try {
|
try {
|
||||||
final ctr = Get.find<FavPgcController>(tag: '$type$followStatus');
|
final ctr = Get.find<FavPgcController>(tag: '$type$followStatus');
|
||||||
if (ctr.loadingState.value.isSuccess) {
|
if (ctr.loadingState.value.isSuccess) {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class FavPgcItem extends StatelessWidget {
|
|||||||
});
|
});
|
||||||
|
|
||||||
final FavPgcItemModel item;
|
final FavPgcItemModel item;
|
||||||
final MultiSelectController ctr;
|
final MultiSelectMixin ctr;
|
||||||
final VoidCallback onSelect;
|
final VoidCallback onSelect;
|
||||||
final VoidCallback onUpdateStatus;
|
final VoidCallback onUpdateStatus;
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:PiliPlus/common/widgets/dialog/dialog.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';
|
||||||
@@ -11,7 +12,6 @@ import 'package:PiliPlus/services/account_service.dart';
|
|||||||
import 'package:PiliPlus/utils/extension.dart';
|
import 'package:PiliPlus/utils/extension.dart';
|
||||||
import 'package:PiliPlus/utils/page_utils.dart';
|
import 'package:PiliPlus/utils/page_utils.dart';
|
||||||
import 'package:PiliPlus/utils/utils.dart';
|
import 'package:PiliPlus/utils/utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
@@ -90,61 +90,28 @@ class FavDetailController
|
|||||||
order: order.value,
|
order: order.value,
|
||||||
);
|
);
|
||||||
|
|
||||||
void onDelChecked(BuildContext context) {
|
@override
|
||||||
showDialog(
|
void onConfirm() {
|
||||||
context: context,
|
showConfirmDialog(
|
||||||
builder: (context) {
|
context: Get.context!,
|
||||||
return AlertDialog(
|
content: '确认删除所选收藏吗?',
|
||||||
title: const Text('提示'),
|
title: '提示',
|
||||||
content: const Text('确认删除所选收藏吗?'),
|
onConfirm: () async {
|
||||||
actions: [
|
final checked = allChecked.toSet();
|
||||||
TextButton(
|
|
||||||
onPressed: Get.back,
|
|
||||||
child: Text(
|
|
||||||
'取消',
|
|
||||||
style: TextStyle(
|
|
||||||
color: Theme.of(context).colorScheme.outline,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () async {
|
|
||||||
Get.back();
|
|
||||||
List<FavDetailItemModel> list = loadingState.value.data!
|
|
||||||
.where((e) => e.checked == true)
|
|
||||||
.toList();
|
|
||||||
var result = await FavHttp.favVideo(
|
var result = await FavHttp.favVideo(
|
||||||
resources: list
|
resources: checked.map((item) => '${item.id}:${item.type}').join(','),
|
||||||
.map((item) => '${item.id}:${item.type}')
|
|
||||||
.join(','),
|
|
||||||
delIds: mediaId.toString(),
|
delIds: mediaId.toString(),
|
||||||
);
|
);
|
||||||
if (result['status']) {
|
if (result['status']) {
|
||||||
List<FavDetailItemModel> dataList = loadingState.value.data!;
|
afterDelete(checked);
|
||||||
List<FavDetailItemModel> remainList = dataList
|
|
||||||
.toSet()
|
|
||||||
.difference(list.toSet())
|
|
||||||
.toList();
|
|
||||||
folderInfo
|
folderInfo
|
||||||
..value.mediaCount -= list.length
|
..value.mediaCount -= checked.length
|
||||||
..refresh();
|
..refresh();
|
||||||
if (remainList.isNotEmpty) {
|
|
||||||
loadingState.value = Success(remainList);
|
|
||||||
} else {
|
|
||||||
onReload();
|
|
||||||
}
|
|
||||||
SmartDialog.showToast('取消收藏');
|
SmartDialog.showToast('取消收藏');
|
||||||
checkedCount.value = 0;
|
|
||||||
enableMultiSelect.value = false;
|
|
||||||
} else {
|
} else {
|
||||||
SmartDialog.showToast(result['msg']);
|
SmartDialog.showToast(result['msg']);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: const Text('确认'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
|||||||
Obx(
|
Obx(
|
||||||
() {
|
() {
|
||||||
return Text(
|
return Text(
|
||||||
'已选: ${_favDetailController.checkedCount.value}',
|
'已选: ${_favDetailController.checkedCount}',
|
||||||
style: const TextStyle(fontSize: 15),
|
style: const TextStyle(fontSize: 15),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -327,7 +327,7 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
|||||||
style: TextButton.styleFrom(
|
style: TextButton.styleFrom(
|
||||||
visualDensity: VisualDensity.compact,
|
visualDensity: VisualDensity.compact,
|
||||||
),
|
),
|
||||||
onPressed: () => _favDetailController.onDelChecked(context),
|
onPressed: _favDetailController.onConfirm,
|
||||||
child: Text(
|
child: Text(
|
||||||
'删除',
|
'删除',
|
||||||
style: TextStyle(color: theme.colorScheme.error),
|
style: TextStyle(color: theme.colorScheme.error),
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:PiliPlus/common/widgets/dialog/dialog.dart';
|
||||||
import 'package:PiliPlus/http/loading_state.dart';
|
import 'package:PiliPlus/http/loading_state.dart';
|
||||||
import 'package:PiliPlus/http/user.dart';
|
import 'package:PiliPlus/http/user.dart';
|
||||||
import 'package:PiliPlus/models_new/history/data.dart';
|
import 'package:PiliPlus/models_new/history/data.dart';
|
||||||
@@ -26,6 +27,12 @@ class HistoryController
|
|||||||
int? max;
|
int? max;
|
||||||
int? viewAt;
|
int? viewAt;
|
||||||
|
|
||||||
|
@override
|
||||||
|
RxInt get rxCount => baseCtr.checkedCount;
|
||||||
|
|
||||||
|
@override
|
||||||
|
RxBool get enableMultiSelect => baseCtr.enableMultiSelect;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
super.onInit();
|
super.onInit();
|
||||||
@@ -40,36 +47,6 @@ class HistoryController
|
|||||||
return super.onRefresh();
|
return super.onRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
void onSelect(HistoryItemModel item, [bool disableSelect = true]) {
|
|
||||||
List<HistoryItemModel> list = loadingState.value.data!;
|
|
||||||
item.checked = !(item.checked ?? false);
|
|
||||||
baseCtr.checkedCount.value = list
|
|
||||||
.where((item) => item.checked == true)
|
|
||||||
.length;
|
|
||||||
loadingState.refresh();
|
|
||||||
if (baseCtr.checkedCount.value == 0) {
|
|
||||||
baseCtr.enableMultiSelect.value = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void handleSelect([bool checked = false, bool disableSelect = true]) {
|
|
||||||
if (loadingState.value.isSuccess) {
|
|
||||||
List<HistoryItemModel>? list = loadingState.value.data;
|
|
||||||
if (list?.isNotEmpty == true) {
|
|
||||||
for (HistoryItemModel item in list!) {
|
|
||||||
item.checked = checked;
|
|
||||||
}
|
|
||||||
baseCtr.checkedCount.value = checked ? list.length : 0;
|
|
||||||
loadingState.refresh();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!checked) {
|
|
||||||
baseCtr.enableMultiSelect.value = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<HistoryItemModel>? getDataList(HistoryData response) {
|
List<HistoryItemModel>? getDataList(HistoryData response) {
|
||||||
return response.list;
|
return response.list;
|
||||||
@@ -108,82 +85,43 @@ class HistoryController
|
|||||||
|
|
||||||
// 删除某条历史记录
|
// 删除某条历史记录
|
||||||
void delHistory(HistoryItemModel item) {
|
void delHistory(HistoryItemModel item) {
|
||||||
_onDelete([item]);
|
_onDelete({item});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除已看历史记录
|
// 删除已看历史记录
|
||||||
void onDelHistory() {
|
void onDelHistory() {
|
||||||
if (loadingState.value.isSuccess) {
|
if (loadingState.value.isSuccess) {
|
||||||
List<HistoryItemModel> list = loadingState.value.data!
|
final set = loadingState.value.data!
|
||||||
.where((e) => e.progress == -1)
|
.where((e) => e.progress == -1)
|
||||||
.toList();
|
.toSet();
|
||||||
if (list.isNotEmpty) {
|
if (set.isNotEmpty) {
|
||||||
_onDelete(list);
|
_onDelete(set);
|
||||||
} else {
|
} else {
|
||||||
SmartDialog.showToast('无已看记录');
|
SmartDialog.showToast('无已看记录');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onDelete(List<HistoryItemModel> result) async {
|
Future<void> _onDelete(Set<HistoryItemModel> result) async {
|
||||||
SmartDialog.showLoading(msg: '请求中');
|
SmartDialog.showLoading(msg: '请求中');
|
||||||
List<String> kidList = result.map((item) {
|
final response = await UserHttp.delHistory(
|
||||||
return '${item.history.business}_${item.kid}';
|
result.map((item) => '${item.history.business}_${item.kid}'),
|
||||||
}).toList();
|
);
|
||||||
var response = await UserHttp.delHistory(kidList);
|
|
||||||
if (response['status']) {
|
if (response['status']) {
|
||||||
List<HistoryItemModel> remainList = loadingState.value.data!
|
afterDelete(result);
|
||||||
.toSet()
|
|
||||||
.difference(result.toSet())
|
|
||||||
.toList();
|
|
||||||
if (remainList.isNotEmpty) {
|
|
||||||
loadingState.value = Success(remainList);
|
|
||||||
} else {
|
|
||||||
onReload();
|
|
||||||
}
|
|
||||||
if (baseCtr.enableMultiSelect.value) {
|
|
||||||
baseCtr.checkedCount.value = 0;
|
|
||||||
baseCtr.enableMultiSelect.value = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
SmartDialog.dismiss();
|
SmartDialog.dismiss();
|
||||||
SmartDialog.showToast(response['msg']);
|
SmartDialog.showToast(response['msg']);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除选中的记录
|
// 删除选中的记录
|
||||||
void onDelCheckedHistory(BuildContext context) {
|
@override
|
||||||
showDialog(
|
void onConfirm() {
|
||||||
context: context,
|
showConfirmDialog(
|
||||||
builder: (context) {
|
context: Get.context!,
|
||||||
return AlertDialog(
|
content: '确认删除所选历史记录吗?',
|
||||||
title: const Text('提示'),
|
title: '提示',
|
||||||
content: const Text('确认删除所选历史记录吗?'),
|
onConfirm: () => _onDelete(allChecked.toSet()),
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: Get.back,
|
|
||||||
child: Text(
|
|
||||||
'取消',
|
|
||||||
style: TextStyle(
|
|
||||||
color: Theme.of(context).colorScheme.outline,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () {
|
|
||||||
Get.back();
|
|
||||||
if (loadingState.value.isSuccess) {
|
|
||||||
_onDelete(
|
|
||||||
loadingState.value.data!
|
|
||||||
.where((e) => e.checked == true)
|
|
||||||
.toList(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: const Text('确认'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:PiliPlus/common/constants.dart';
|
import 'package:PiliPlus/common/constants.dart';
|
||||||
import 'package:PiliPlus/common/skeleton/video_card_h.dart';
|
import 'package:PiliPlus/common/skeleton/video_card_h.dart';
|
||||||
|
import 'package:PiliPlus/common/widgets/appbar/appbar.dart';
|
||||||
import 'package:PiliPlus/common/widgets/keep_alive_wrapper.dart';
|
import 'package:PiliPlus/common/widgets/keep_alive_wrapper.dart';
|
||||||
import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart';
|
import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart';
|
||||||
import 'package:PiliPlus/common/widgets/refresh_indicator.dart';
|
import 'package:PiliPlus/common/widgets/refresh_indicator.dart';
|
||||||
@@ -65,9 +66,10 @@ class _HistoryPageState extends State<HistoryPage>
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
appBar: AppBarWidget(
|
appBar: MultiSelectAppBarWidget(
|
||||||
visible: enableMultiSelect,
|
visible: enableMultiSelect,
|
||||||
child1: AppBar(
|
ctr: currCtr(),
|
||||||
|
child: AppBar(
|
||||||
title: const Text('观看记录'),
|
title: const Text('观看记录'),
|
||||||
bottom: _buildPauseTip,
|
bottom: _buildPauseTip,
|
||||||
actions: [
|
actions: [
|
||||||
@@ -153,36 +155,6 @@ class _HistoryPageState extends State<HistoryPage>
|
|||||||
const SizedBox(width: 6),
|
const SizedBox(width: 6),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
child2: AppBar(
|
|
||||||
bottom: _buildPauseTip,
|
|
||||||
leading: IconButton(
|
|
||||||
tooltip: '取消',
|
|
||||||
onPressed: currCtr().handleSelect,
|
|
||||||
icon: const Icon(Icons.close_outlined),
|
|
||||||
),
|
|
||||||
title: Obx(
|
|
||||||
() => Text(
|
|
||||||
'已选: ${_historyController.baseCtr.checkedCount.value}',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: () => currCtr().handleSelect(true),
|
|
||||||
child: const Text('全选'),
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () =>
|
|
||||||
currCtr().onDelCheckedHistory(context),
|
|
||||||
child: Text(
|
|
||||||
'删除',
|
|
||||||
style: TextStyle(
|
|
||||||
color: Theme.of(context).colorScheme.error,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 6),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
body: Obx(
|
body: Obx(
|
||||||
() => _historyController.tabs.isNotEmpty
|
() => _historyController.tabs.isNotEmpty
|
||||||
@@ -288,8 +260,7 @@ class _HistoryPageState extends State<HistoryPage>
|
|||||||
final item = response[index];
|
final item = response[index];
|
||||||
return HistoryItem(
|
return HistoryItem(
|
||||||
item: item,
|
item: item,
|
||||||
ctr: _historyController.baseCtr,
|
ctr: _historyController,
|
||||||
onChoose: () => _historyController.onSelect(item),
|
|
||||||
onDelete: (kid, business) =>
|
onDelete: (kid, business) =>
|
||||||
_historyController.delHistory(item),
|
_historyController.delHistory(item),
|
||||||
);
|
);
|
||||||
@@ -359,32 +330,3 @@ class _HistoryPageState extends State<HistoryPage>
|
|||||||
@override
|
@override
|
||||||
bool get wantKeepAlive => widget.type != null;
|
bool get wantKeepAlive => widget.type != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
class AppBarWidget extends StatelessWidget implements PreferredSizeWidget {
|
|
||||||
const AppBarWidget({
|
|
||||||
required this.child1,
|
|
||||||
required this.child2,
|
|
||||||
required this.visible,
|
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
final PreferredSizeWidget child1;
|
|
||||||
final PreferredSizeWidget child2;
|
|
||||||
final bool visible;
|
|
||||||
@override
|
|
||||||
Size get preferredSize => child1.preferredSize;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return AnimatedSwitcher(
|
|
||||||
duration: const Duration(milliseconds: 500),
|
|
||||||
transitionBuilder: (Widget child, Animation<double> animation) {
|
|
||||||
return ScaleTransition(
|
|
||||||
scale: animation,
|
|
||||||
child: child,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: !visible ? child1 : child2,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import 'package:PiliPlus/common/constants.dart';
|
import 'package:PiliPlus/common/constants.dart';
|
||||||
import 'package:PiliPlus/common/widgets/badge.dart';
|
import 'package:PiliPlus/common/widgets/badge.dart';
|
||||||
import 'package:PiliPlus/common/widgets/image/image_save.dart';
|
|
||||||
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
|
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
|
||||||
import 'package:PiliPlus/common/widgets/progress_bar/video_progress_indicator.dart';
|
import 'package:PiliPlus/common/widgets/progress_bar/video_progress_indicator.dart';
|
||||||
import 'package:PiliPlus/http/search.dart';
|
import 'package:PiliPlus/http/search.dart';
|
||||||
@@ -9,7 +8,6 @@ import 'package:PiliPlus/models/common/badge_type.dart';
|
|||||||
import 'package:PiliPlus/models/common/history_business_type.dart';
|
import 'package:PiliPlus/models/common/history_business_type.dart';
|
||||||
import 'package:PiliPlus/models_new/history/list.dart';
|
import 'package:PiliPlus/models_new/history/list.dart';
|
||||||
import 'package:PiliPlus/pages/common/multi_select_controller.dart';
|
import 'package:PiliPlus/pages/common/multi_select_controller.dart';
|
||||||
import 'package:PiliPlus/pages/history/base_controller.dart';
|
|
||||||
import 'package:PiliPlus/utils/date_util.dart';
|
import 'package:PiliPlus/utils/date_util.dart';
|
||||||
import 'package:PiliPlus/utils/duration_util.dart';
|
import 'package:PiliPlus/utils/duration_util.dart';
|
||||||
import 'package:PiliPlus/utils/feed_back.dart';
|
import 'package:PiliPlus/utils/feed_back.dart';
|
||||||
@@ -23,15 +21,13 @@ import 'package:material_design_icons_flutter/material_design_icons_flutter.dart
|
|||||||
|
|
||||||
class HistoryItem extends StatelessWidget {
|
class HistoryItem extends StatelessWidget {
|
||||||
final HistoryItemModel item;
|
final HistoryItemModel item;
|
||||||
final dynamic ctr;
|
final MultiSelectMixin ctr;
|
||||||
final Function? onChoose;
|
final void Function(int kid, String business) onDelete;
|
||||||
final Function(dynamic kid, dynamic business) onDelete;
|
|
||||||
|
|
||||||
const HistoryItem({
|
const HistoryItem({
|
||||||
super.key,
|
super.key,
|
||||||
required this.item,
|
required this.item,
|
||||||
this.ctr,
|
required this.ctr,
|
||||||
this.onChoose,
|
|
||||||
required this.onDelete,
|
required this.onDelete,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -45,12 +41,10 @@ class HistoryItem extends StatelessWidget {
|
|||||||
type: MaterialType.transparency,
|
type: MaterialType.transparency,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
if (ctr is MultiSelectController || ctr is HistoryBaseController) {
|
|
||||||
if (ctr.enableMultiSelect.value) {
|
if (ctr.enableMultiSelect.value) {
|
||||||
onChoose?.call();
|
ctr.onSelect(item);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (item.history.business?.contains('article') == true) {
|
if (item.history.business?.contains('article') == true) {
|
||||||
PageUtils.toDupNamed(
|
PageUtils.toDupNamed(
|
||||||
'/articlePage',
|
'/articlePage',
|
||||||
@@ -97,18 +91,16 @@ class HistoryItem extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLongPress: () {
|
onLongPress: () {
|
||||||
if (ctr is MultiSelectController || ctr is HistoryBaseController) {
|
|
||||||
if (!ctr.enableMultiSelect.value) {
|
if (!ctr.enableMultiSelect.value) {
|
||||||
ctr.enableMultiSelect.value = true;
|
ctr.enableMultiSelect.value = true;
|
||||||
onChoose?.call();
|
ctr.onSelect(item);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
// imageSaveDialog(
|
||||||
imageSaveDialog(
|
// title: item.title,
|
||||||
title: item.title,
|
// cover: item.cover,
|
||||||
cover: item.cover,
|
// bvid: bvid,
|
||||||
bvid: bvid,
|
// );
|
||||||
);
|
|
||||||
},
|
},
|
||||||
child: Stack(
|
child: Stack(
|
||||||
clipBehavior: Clip.none,
|
clipBehavior: Clip.none,
|
||||||
@@ -205,7 +197,7 @@ class HistoryItem extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
feedBack();
|
feedBack();
|
||||||
onChoose?.call();
|
ctr.onSelect(item);
|
||||||
},
|
},
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
Icons.done_all_outlined,
|
Icons.done_all_outlined,
|
||||||
@@ -287,7 +279,7 @@ class HistoryItem extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
PopupMenuItem<String>(
|
PopupMenuItem<String>(
|
||||||
onTap: () =>
|
onTap: () =>
|
||||||
onDelete(item.kid, item.history.business),
|
onDelete(item.kid!, item.history.business!),
|
||||||
height: 35,
|
height: 35,
|
||||||
child: const Row(
|
child: const Row(
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@@ -1,12 +1,19 @@
|
|||||||
|
import 'package:PiliPlus/common/widgets/dialog/dialog.dart';
|
||||||
import 'package:PiliPlus/http/loading_state.dart';
|
import 'package:PiliPlus/http/loading_state.dart';
|
||||||
import 'package:PiliPlus/http/user.dart';
|
import 'package:PiliPlus/http/user.dart';
|
||||||
import 'package:PiliPlus/models_new/history/data.dart';
|
import 'package:PiliPlus/models_new/history/data.dart';
|
||||||
import 'package:PiliPlus/models_new/history/list.dart';
|
import 'package:PiliPlus/models_new/history/list.dart';
|
||||||
import 'package:PiliPlus/pages/common/common_search_controller.dart';
|
import 'package:PiliPlus/pages/common/common_search_controller.dart';
|
||||||
|
import 'package:PiliPlus/pages/common/multi_select_controller.dart';
|
||||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
class HistorySearchController
|
class HistorySearchController
|
||||||
extends CommonSearchController<HistoryData, HistoryItemModel> {
|
extends CommonSearchController<HistoryData, HistoryItemModel>
|
||||||
|
with
|
||||||
|
MultiSelectMixin<HistoryItemModel>,
|
||||||
|
CommonMultiSelectMixin,
|
||||||
|
DeleteItemMixin {
|
||||||
@override
|
@override
|
||||||
Future<LoadingState<HistoryData>> customGetData() => UserHttp.searchHistory(
|
Future<LoadingState<HistoryData>> customGetData() => UserHttp.searchHistory(
|
||||||
pn: page,
|
pn: page,
|
||||||
@@ -18,12 +25,14 @@ class HistorySearchController
|
|||||||
return response.list;
|
return response.list;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> onDelHistory(int index, kid, business) async {
|
Future<void> onDelHistory(int index, kid, String business) async {
|
||||||
String resKid = 'archive_$kid';
|
final String resKid;
|
||||||
if (business == 'live') {
|
if (business == 'live') {
|
||||||
resKid = 'live_$kid';
|
resKid = 'live_$kid';
|
||||||
} else if (business.contains('article')) {
|
} else if (business.contains('article')) {
|
||||||
resKid = 'article_$kid';
|
resKid = 'article_$kid';
|
||||||
|
} else {
|
||||||
|
resKid = 'archive_$kid';
|
||||||
}
|
}
|
||||||
|
|
||||||
var res = await UserHttp.delHistory([resKid]);
|
var res = await UserHttp.delHistory([resKid]);
|
||||||
@@ -34,4 +43,26 @@ class HistorySearchController
|
|||||||
}
|
}
|
||||||
SmartDialog.showToast(res['msg']);
|
SmartDialog.showToast(res['msg']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onConfirm() {
|
||||||
|
showConfirmDialog(
|
||||||
|
context: Get.context!,
|
||||||
|
content: '确认删除所选历史记录吗?',
|
||||||
|
title: '提示',
|
||||||
|
onConfirm: () async {
|
||||||
|
SmartDialog.showLoading(msg: '请求中');
|
||||||
|
final result = allChecked.toSet();
|
||||||
|
final kidList = result.map(
|
||||||
|
(item) => '${item.history.business!}_${item.kid!}',
|
||||||
|
);
|
||||||
|
var response = await UserHttp.delHistory(kidList);
|
||||||
|
if (response['status']) {
|
||||||
|
afterDelete(result);
|
||||||
|
}
|
||||||
|
SmartDialog.dismiss();
|
||||||
|
SmartDialog.showToast(response['msg']);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:PiliPlus/common/widgets/appbar/appbar.dart';
|
||||||
import 'package:PiliPlus/models_new/history/data.dart';
|
import 'package:PiliPlus/models_new/history/data.dart';
|
||||||
import 'package:PiliPlus/models_new/history/list.dart';
|
import 'package:PiliPlus/models_new/history/list.dart';
|
||||||
import 'package:PiliPlus/pages/common/common_search_page.dart';
|
import 'package:PiliPlus/pages/common/common_search_page.dart';
|
||||||
@@ -28,6 +29,31 @@ class _HistorySearchPageState
|
|||||||
tag: Utils.generateRandomString(8),
|
tag: Utils.generateRandomString(8),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
// TODO: refa
|
||||||
|
return Obx(() {
|
||||||
|
final parent = super.build(context) as Scaffold;
|
||||||
|
final enableMultiSelect = controller.enableMultiSelect.value;
|
||||||
|
return PopScope(
|
||||||
|
canPop: !enableMultiSelect,
|
||||||
|
onPopInvokedWithResult: (didPop, result) {
|
||||||
|
if (enableMultiSelect) {
|
||||||
|
controller.handleSelect();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Scaffold(
|
||||||
|
resizeToAvoidBottomInset: parent.resizeToAvoidBottomInset,
|
||||||
|
appBar: MultiSelectAppBarWidget(
|
||||||
|
ctr: controller,
|
||||||
|
child: parent.appBar as AppBar,
|
||||||
|
),
|
||||||
|
body: parent.body,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildList(List<HistoryItemModel> list) {
|
Widget buildList(List<HistoryItemModel> list) {
|
||||||
return SliverGrid(
|
return SliverGrid(
|
||||||
@@ -42,10 +68,8 @@ class _HistorySearchPageState
|
|||||||
return HistoryItem(
|
return HistoryItem(
|
||||||
item: item,
|
item: item,
|
||||||
ctr: controller,
|
ctr: controller,
|
||||||
onChoose: null,
|
onDelete: (kid, business) =>
|
||||||
onDelete: (kid, business) {
|
controller.onDelHistory(index, kid, business),
|
||||||
controller.onDelHistory(index, kid, business);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -27,6 +27,12 @@ class LaterController extends MultiSelectController<LaterData, LaterItemModel> {
|
|||||||
|
|
||||||
final LaterBaseController baseCtr = Get.put(LaterBaseController());
|
final LaterBaseController baseCtr = Get.put(LaterBaseController());
|
||||||
|
|
||||||
|
@override
|
||||||
|
RxBool get enableMultiSelect => baseCtr.enableMultiSelect;
|
||||||
|
|
||||||
|
@override
|
||||||
|
RxInt get rxCount => baseCtr.checkedCount;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<LoadingState<LaterData>> customGetData() => UserHttp.seeYouLater(
|
Future<LoadingState<LaterData>> customGetData() => UserHttp.seeYouLater(
|
||||||
page: page,
|
page: page,
|
||||||
@@ -34,36 +40,6 @@ class LaterController extends MultiSelectController<LaterData, LaterItemModel> {
|
|||||||
asc: asc.value,
|
asc: asc.value,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
|
||||||
void onSelect(LaterItemModel item, [bool disableSelect = true]) {
|
|
||||||
List<LaterItemModel> list = loadingState.value.data!;
|
|
||||||
item.checked = !(item.checked ?? false);
|
|
||||||
baseCtr.checkedCount.value = list
|
|
||||||
.where((item) => item.checked == true)
|
|
||||||
.length;
|
|
||||||
loadingState.refresh();
|
|
||||||
if (baseCtr.checkedCount.value == 0) {
|
|
||||||
baseCtr.enableMultiSelect.value = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void handleSelect([bool checked = false, bool disableSelect = true]) {
|
|
||||||
if (loadingState.value.isSuccess) {
|
|
||||||
List<LaterItemModel>? list = loadingState.value.data;
|
|
||||||
if (list?.isNotEmpty == true) {
|
|
||||||
for (LaterItemModel item in list!) {
|
|
||||||
item.checked = checked;
|
|
||||||
}
|
|
||||||
baseCtr.checkedCount.value = checked ? list.length : 0;
|
|
||||||
loadingState.refresh();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!checked) {
|
|
||||||
baseCtr.enableMultiSelect.value = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
super.onInit();
|
super.onInit();
|
||||||
@@ -102,7 +78,7 @@ class LaterController extends MultiSelectController<LaterData, LaterItemModel> {
|
|||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
Get.back();
|
Get.back();
|
||||||
var res = await UserHttp.toViewDel(aids: [aid]);
|
final res = await UserHttp.toViewDel(aids: {aid!});
|
||||||
if (res['status']) {
|
if (res['status']) {
|
||||||
baseCtr.counts[laterViewType] =
|
baseCtr.counts[laterViewType] =
|
||||||
baseCtr.counts[laterViewType]! - 1;
|
baseCtr.counts[laterViewType]! - 1;
|
||||||
@@ -148,51 +124,24 @@ class LaterController extends MultiSelectController<LaterData, LaterItemModel> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onDelChecked(BuildContext context) {
|
@override
|
||||||
showDialog(
|
void onConfirm() {
|
||||||
context: context,
|
showConfirmDialog(
|
||||||
builder: (context) {
|
context: Get.context!,
|
||||||
return AlertDialog(
|
content: '确认删除所选稍后再看吗?',
|
||||||
title: const Text('提示'),
|
title: '提示',
|
||||||
content: const Text('确认删除所选稍后再看吗?'),
|
onConfirm: () => _onDelete(allChecked.toSet()),
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: Get.back,
|
|
||||||
child: Text(
|
|
||||||
'取消',
|
|
||||||
style: TextStyle(
|
|
||||||
color: Theme.of(context).colorScheme.outline,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () {
|
|
||||||
Get.back();
|
|
||||||
_onDelete(
|
|
||||||
loadingState.value.data!
|
|
||||||
.where((e) => e.checked == true)
|
|
||||||
.toList(),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: const Text('确认'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onDelete(List<LaterItemModel> result) async {
|
Future<void> _onDelete(Set<LaterItemModel> result) async {
|
||||||
SmartDialog.showLoading(msg: '请求中');
|
SmartDialog.showLoading(msg: '请求中');
|
||||||
List<int?> aids = result.map((item) => item.aid).toList();
|
final res = await UserHttp.toViewDel(aids: result.map((item) => item.aid!));
|
||||||
var res = await UserHttp.toViewDel(aids: aids);
|
|
||||||
if (res['status']) {
|
if (res['status']) {
|
||||||
Set<LaterItemModel> remainList = loadingState.value.data!
|
afterDelete(result);
|
||||||
.toSet()
|
|
||||||
.difference(result.toSet());
|
|
||||||
baseCtr.counts[laterViewType] =
|
baseCtr.counts[laterViewType] =
|
||||||
baseCtr.counts[laterViewType]! - aids.length;
|
baseCtr.counts[laterViewType]! - result.length;
|
||||||
loadingState.value = Success(remainList.toList());
|
|
||||||
if (baseCtr.enableMultiSelect.value) {
|
if (baseCtr.enableMultiSelect.value) {
|
||||||
baseCtr.checkedCount.value = 0;
|
baseCtr.checkedCount.value = 0;
|
||||||
baseCtr.enableMultiSelect.value = false;
|
baseCtr.enableMultiSelect.value = false;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
|
import 'package:PiliPlus/common/widgets/appbar/appbar.dart';
|
||||||
import 'package:PiliPlus/common/widgets/scroll_physics.dart';
|
import 'package:PiliPlus/common/widgets/scroll_physics.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/data.dart';
|
||||||
import 'package:PiliPlus/models_new/later/list.dart';
|
import 'package:PiliPlus/models_new/later/list.dart';
|
||||||
import 'package:PiliPlus/pages/history/view.dart' show AppBarWidget;
|
|
||||||
import 'package:PiliPlus/pages/later/base_controller.dart';
|
import 'package:PiliPlus/pages/later/base_controller.dart';
|
||||||
import 'package:PiliPlus/pages/later/controller.dart';
|
import 'package:PiliPlus/pages/later/controller.dart';
|
||||||
import 'package:PiliPlus/utils/accounts.dart';
|
import 'package:PiliPlus/utils/accounts.dart';
|
||||||
@@ -128,9 +128,54 @@ class _LaterPageState extends State<LaterPage>
|
|||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
Color color = theme.colorScheme.secondary;
|
Color color = theme.colorScheme.secondary;
|
||||||
|
|
||||||
return AppBarWidget(
|
return MultiSelectAppBarWidget(
|
||||||
visible: enableMultiSelect,
|
visible: enableMultiSelect,
|
||||||
child1: AppBar(
|
ctr: currCtr(),
|
||||||
|
children: [
|
||||||
|
TextButton(
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
visualDensity: VisualDensity.compact,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
final ctr = currCtr();
|
||||||
|
RequestUtils.onCopyOrMove<LaterData, LaterItemModel>(
|
||||||
|
context: context,
|
||||||
|
isCopy: true,
|
||||||
|
ctr: ctr,
|
||||||
|
mediaId: null,
|
||||||
|
mid: ctr.accountService.mid,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
'复制',
|
||||||
|
style: TextStyle(
|
||||||
|
color: theme.colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
visualDensity: VisualDensity.compact,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
final ctr = currCtr();
|
||||||
|
RequestUtils.onCopyOrMove<LaterData, LaterItemModel>(
|
||||||
|
context: context,
|
||||||
|
isCopy: false,
|
||||||
|
ctr: ctr,
|
||||||
|
mediaId: null,
|
||||||
|
mid: ctr.accountService.mid,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
'移动',
|
||||||
|
style: TextStyle(
|
||||||
|
color: theme.colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
child: AppBar(
|
||||||
title: const Text('稍后再看'),
|
title: const Text('稍后再看'),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
@@ -251,76 +296,6 @@ class _LaterPageState extends State<LaterPage>
|
|||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
child2: AppBar(
|
|
||||||
leading: IconButton(
|
|
||||||
tooltip: '取消',
|
|
||||||
onPressed: currCtr().handleSelect,
|
|
||||||
icon: const Icon(Icons.close_outlined),
|
|
||||||
),
|
|
||||||
title: Obx(() => Text('已选: ${_baseCtr.checkedCount.value}')),
|
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
style: TextButton.styleFrom(
|
|
||||||
visualDensity: VisualDensity.compact,
|
|
||||||
),
|
|
||||||
onPressed: () => currCtr().handleSelect(true),
|
|
||||||
child: const Text('全选'),
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
style: TextButton.styleFrom(
|
|
||||||
visualDensity: VisualDensity.compact,
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
final ctr = currCtr();
|
|
||||||
RequestUtils.onCopyOrMove<LaterData, LaterItemModel>(
|
|
||||||
context: context,
|
|
||||||
isCopy: true,
|
|
||||||
ctr: ctr,
|
|
||||||
mediaId: null,
|
|
||||||
mid: ctr.accountService.mid,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
'复制',
|
|
||||||
style: TextStyle(
|
|
||||||
color: theme.colorScheme.onSurfaceVariant,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
style: TextButton.styleFrom(
|
|
||||||
visualDensity: VisualDensity.compact,
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
final ctr = currCtr();
|
|
||||||
RequestUtils.onCopyOrMove<LaterData, LaterItemModel>(
|
|
||||||
context: context,
|
|
||||||
isCopy: false,
|
|
||||||
ctr: ctr,
|
|
||||||
mediaId: null,
|
|
||||||
mid: ctr.accountService.mid,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
'移动',
|
|
||||||
style: TextStyle(
|
|
||||||
color: theme.colorScheme.onSurfaceVariant,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
style: TextButton.styleFrom(
|
|
||||||
visualDensity: VisualDensity.compact,
|
|
||||||
),
|
|
||||||
onPressed: () => currCtr().onDelChecked(context),
|
|
||||||
child: Text(
|
|
||||||
'移除',
|
|
||||||
style: TextStyle(color: theme.colorScheme.error),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 6),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class LaterSearchController
|
|||||||
return response.list;
|
return response.list;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> toViewDel(BuildContext context, int index, aid) async {
|
Future<void> toViewDel(BuildContext context, int index, int aid) async {
|
||||||
var res = await UserHttp.toViewDel(aids: [aid]);
|
var res = await UserHttp.toViewDel(aids: [aid]);
|
||||||
if (res['status']) {
|
if (res['status']) {
|
||||||
loadingState.value.data!.removeAt(index);
|
loadingState.value.data!.removeAt(index);
|
||||||
@@ -31,4 +31,25 @@ class LaterSearchController
|
|||||||
}
|
}
|
||||||
SmartDialog.showToast(res['msg']);
|
SmartDialog.showToast(res['msg']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @override
|
||||||
|
// void onConfirm() {
|
||||||
|
// showConfirmDialog(
|
||||||
|
// context: Get.context!,
|
||||||
|
// content: '确认删除所选稍后再看吗?',
|
||||||
|
// title: '提示',
|
||||||
|
// onConfirm: () async {
|
||||||
|
// final result = allChecked.toSet();
|
||||||
|
// SmartDialog.showLoading(msg: '请求中');
|
||||||
|
// var res = await UserHttp.toViewDel(
|
||||||
|
// aids: result.map((item) => item.aid!),
|
||||||
|
// );
|
||||||
|
// if (res['status']) {
|
||||||
|
// afterDelete(result);
|
||||||
|
// }
|
||||||
|
// SmartDialog.dismiss();
|
||||||
|
// SmartDialog.showToast(res['msg']);
|
||||||
|
// },
|
||||||
|
// );
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,31 @@ class _LaterSearchPageState
|
|||||||
tag: Utils.generateRandomString(8),
|
tag: Utils.generateRandomString(8),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// @override
|
||||||
|
// Widget build(BuildContext context) {
|
||||||
|
// // TODO: refa
|
||||||
|
// return Obx(() {
|
||||||
|
// final parent = super.build(context) as Scaffold;
|
||||||
|
// final enableMultiSelect = controller.enableMultiSelect.value;
|
||||||
|
// return PopScope(
|
||||||
|
// canPop: !enableMultiSelect,
|
||||||
|
// onPopInvokedWithResult: (didPop, result) {
|
||||||
|
// if (enableMultiSelect) {
|
||||||
|
// controller.handleSelect();
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// child: Scaffold(
|
||||||
|
// resizeToAvoidBottomInset: parent.resizeToAvoidBottomInset,
|
||||||
|
// appBar: MultiSelectAppBarWidget(
|
||||||
|
// ctr: controller,
|
||||||
|
// child: parent.appBar as AppBar,
|
||||||
|
// ),
|
||||||
|
// body: parent.body,
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildList(List<LaterItemModel> list) {
|
Widget buildList(List<LaterItemModel> list) {
|
||||||
return SliverGrid(
|
return SliverGrid(
|
||||||
@@ -73,7 +98,7 @@ class _LaterSearchPageState
|
|||||||
onConfirm: () => controller.toViewDel(
|
onConfirm: () => controller.toViewDel(
|
||||||
context,
|
context,
|
||||||
index,
|
index,
|
||||||
item.aid,
|
item.aid!,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
icon: Icons.clear,
|
icon: Icons.clear,
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import 'package:PiliPlus/models/common/reply/reply_sort_type.dart';
|
|||||||
import 'package:PiliPlus/models/common/settings_type.dart';
|
import 'package:PiliPlus/models/common/settings_type.dart';
|
||||||
import 'package:PiliPlus/models/common/super_resolution_type.dart';
|
import 'package:PiliPlus/models/common/super_resolution_type.dart';
|
||||||
import 'package:PiliPlus/models/dynamics/result.dart';
|
import 'package:PiliPlus/models/dynamics/result.dart';
|
||||||
import 'package:PiliPlus/models_new/fav/fav_folder/data.dart';
|
|
||||||
import 'package:PiliPlus/pages/common/common_slide_page.dart';
|
import 'package:PiliPlus/pages/common/common_slide_page.dart';
|
||||||
import 'package:PiliPlus/pages/home/controller.dart';
|
import 'package:PiliPlus/pages/home/controller.dart';
|
||||||
import 'package:PiliPlus/pages/hot/controller.dart';
|
import 'package:PiliPlus/pages/hot/controller.dart';
|
||||||
@@ -786,9 +785,8 @@ List<SettingsModel> get extraSettings => [
|
|||||||
onTap: () async {
|
onTap: () async {
|
||||||
if (Accounts.main.isLogin) {
|
if (Accounts.main.isLogin) {
|
||||||
final res = await FavHttp.allFavFolders(Accounts.main.mid);
|
final res = await FavHttp.allFavFolders(Accounts.main.mid);
|
||||||
if (res['status']) {
|
if (res.isSuccess) {
|
||||||
final FavFolderData data = res['data'];
|
final list = res.data.list;
|
||||||
final list = data.list;
|
|
||||||
if (list.isNullOrEmpty) {
|
if (list.isNullOrEmpty) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -821,7 +819,7 @@ List<SettingsModel> get extraSettings => [
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
SmartDialog.showToast('${res['msg']}');
|
res.toast();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ 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_folder/list.dart';
|
|
||||||
import 'package:PiliPlus/pages/common/multi_select_controller.dart';
|
import 'package:PiliPlus/pages/common/multi_select_controller.dart';
|
||||||
import 'package:PiliPlus/pages/dynamics_tab/controller.dart';
|
import 'package:PiliPlus/pages/dynamics_tab/controller.dart';
|
||||||
import 'package:PiliPlus/pages/group_panel/view.dart';
|
import 'package:PiliPlus/pages/group_panel/view.dart';
|
||||||
@@ -376,11 +375,9 @@ class RequestUtils {
|
|||||||
required dynamic mid,
|
required dynamic mid,
|
||||||
}) {
|
}) {
|
||||||
FavHttp.allFavFolders(mid).then((res) {
|
FavHttp.allFavFolders(mid).then((res) {
|
||||||
if (context.mounted &&
|
if (context.mounted && res.dataOrNull?.list?.isNotEmpty == true) {
|
||||||
res['status'] &&
|
final list = res.data.list!;
|
||||||
(res['data'].list as List?)?.isNotEmpty == true) {
|
int? checkedId;
|
||||||
List<FavFolderInfo> list = res['data'].list;
|
|
||||||
dynamic checkedId;
|
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
@@ -392,7 +389,7 @@ class RequestUtils {
|
|||||||
builder: (context) => Column(
|
builder: (context) => Column(
|
||||||
children: List.generate(list.length, (index) {
|
children: List.generate(list.length, (index) {
|
||||||
final item = list[index];
|
final item = list[index];
|
||||||
return RadioWidget(
|
return RadioWidget<int>(
|
||||||
padding: const EdgeInsets.only(left: 14),
|
padding: const EdgeInsets.only(left: 14),
|
||||||
title: item.title,
|
title: item.title,
|
||||||
groupValue: checkedId,
|
groupValue: checkedId,
|
||||||
@@ -421,9 +418,7 @@ class RequestUtils {
|
|||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (checkedId != null) {
|
if (checkedId != null) {
|
||||||
List resources = ctr.loadingState.value.data!
|
Set resources = ctr.allChecked.toSet();
|
||||||
.where((e) => e.checked == true)
|
|
||||||
.toList();
|
|
||||||
SmartDialog.showLoading();
|
SmartDialog.showLoading();
|
||||||
FavHttp.copyOrMoveFav(
|
FavHttp.copyOrMoveFav(
|
||||||
isCopy: isCopy,
|
isCopy: isCopy,
|
||||||
@@ -439,22 +434,20 @@ class RequestUtils {
|
|||||||
.toList(),
|
.toList(),
|
||||||
mid: isCopy ? mid : null,
|
mid: isCopy ? mid : null,
|
||||||
).then((res) {
|
).then((res) {
|
||||||
if (res['status']) {
|
if (res.isSuccess) {
|
||||||
ctr.handleSelect(false);
|
ctr.handleSelect(false);
|
||||||
if (!isCopy) {
|
if (!isCopy) {
|
||||||
List<T> dataList = ctr.loadingState.value.data!;
|
ctr.loadingState.value.data!.removeWhere(
|
||||||
List<T> remainList = dataList
|
resources.contains,
|
||||||
.toSet()
|
);
|
||||||
.difference(resources.toSet())
|
ctr.loadingState.refresh();
|
||||||
.toList();
|
|
||||||
ctr.loadingState.value = Success(remainList);
|
|
||||||
}
|
}
|
||||||
SmartDialog.dismiss();
|
SmartDialog.dismiss();
|
||||||
SmartDialog.showToast('${isCopy ? '复制' : '移动'}成功');
|
SmartDialog.showToast('${isCopy ? '复制' : '移动'}成功');
|
||||||
Get.back();
|
Get.back();
|
||||||
} else {
|
} else {
|
||||||
SmartDialog.dismiss();
|
SmartDialog.dismiss();
|
||||||
SmartDialog.showToast('${res['msg']}');
|
res.toast();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -466,7 +459,7 @@ class RequestUtils {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
SmartDialog.showToast('${res['msg']}');
|
res.toast();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user