opt del later view

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-08-05 18:42:02 +08:00
parent 104d295389
commit b954c6f893
6 changed files with 139 additions and 149 deletions

View File

@@ -34,6 +34,7 @@ class FavVideoCardH extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final isOwner = !isSort && ctr!.isOwner; final isOwner = !isSort && ctr!.isOwner;
late final enableMultiSelect = ctr?.enableMultiSelect.value ?? false; late final enableMultiSelect = ctr?.enableMultiSelect.value ?? false;
final theme = Theme.of(context);
return Material( return Material(
type: MaterialType.transparency, type: MaterialType.transparency,
child: InkWell( child: InkWell(
@@ -62,8 +63,9 @@ class FavVideoCardH extends StatelessWidget {
? null ? null
: isOwner && !enableMultiSelect : isOwner && !enableMultiSelect
? () { ? () {
ctr!.enableMultiSelect.value = true; ctr!
ctr!.onSelect(item); ..enableMultiSelect.value = true
..onSelect(item);
} }
: () => imageSaveDialog( : () => imageSaveDialog(
title: item.title, title: item.title,
@@ -108,7 +110,7 @@ class FavVideoCardH extends StatelessWidget {
if (!isSort) if (!isSort)
Positioned.fill( Positioned.fill(
child: selectMask( child: selectMask(
Theme.of(context), theme,
item.checked == true, item.checked == true,
), ),
), ),
@@ -118,7 +120,7 @@ class FavVideoCardH extends StatelessWidget {
), ),
), ),
const SizedBox(width: 10), const SizedBox(width: 10),
content(context, isOwner), content(context, theme, isOwner),
], ],
), ),
), ),
@@ -126,8 +128,7 @@ class FavVideoCardH extends StatelessWidget {
); );
} }
Widget content(BuildContext context, bool isOwner) { Widget content(BuildContext context, ThemeData theme, isOwner) {
final theme = Theme.of(context);
return Expanded( return Expanded(
child: Stack( child: Stack(
clipBehavior: Clip.none, clipBehavior: Clip.none,

View File

@@ -75,10 +75,9 @@ class _LaterViewChildPageState extends State<LaterViewChildPage>
_laterController.onLoadMore(); _laterController.onLoadMore();
} }
var videoItem = response[index]; var videoItem = response[index];
final enableMultiSelect =
_laterController.baseCtr.enableMultiSelect.value;
return VideoCardHLater( return VideoCardHLater(
videoItem: videoItem, videoItem: videoItem,
ctr: _laterController,
onViewLater: (cid) { onViewLater: (cid) {
PageUtils.toVideoPage( PageUtils.toVideoPage(
bvid: videoItem.bvid, bvid: videoItem.bvid,
@@ -98,20 +97,15 @@ class _LaterViewChildPageState extends State<LaterViewChildPage>
}, },
); );
}, },
onTap: !enableMultiSelect
? null
: () => _laterController.onSelect(videoItem),
onLongPress: enableMultiSelect
? null
: () {
_laterController.baseCtr.enableMultiSelect.value =
true;
_laterController.onSelect(videoItem);
},
onRemove: () => _laterController.toViewDel( onRemove: () => _laterController.toViewDel(
context, context,
index, index,
videoItem.aid, videoItem.aid,
onSuccess: () {
final counts = _laterController.baseCtr.counts;
counts[widget.laterViewType] =
counts[widget.laterViewType]! - 1;
},
), ),
); );
}, },

View File

@@ -5,6 +5,9 @@ import 'package:PiliPlus/models/common/later_view_type.dart';
import 'package:PiliPlus/models/common/video/source_type.dart'; import 'package:PiliPlus/models/common/video/source_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/common/common_list_controller.dart'
show CommonListController;
import 'package:PiliPlus/pages/common/multi_select/base.dart';
import 'package:PiliPlus/pages/common/multi_select/multi_select_controller.dart'; import 'package:PiliPlus/pages/common/multi_select/multi_select_controller.dart';
import 'package:PiliPlus/pages/later/base_controller.dart'; import 'package:PiliPlus/pages/later/base_controller.dart';
import 'package:PiliPlus/services/account_service.dart'; import 'package:PiliPlus/services/account_service.dart';
@@ -14,7 +17,54 @@ 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';
class LaterController extends MultiSelectController<LaterData, LaterItemModel> { mixin BaseLaterController
on
CommonListController<LaterData, LaterItemModel>,
CommonMultiSelectMixin<LaterItemModel> {
// single
void toViewDel(
BuildContext context,
int index,
int? aid, {
VoidCallback? onSuccess,
}) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('提示'),
content: const Text('即将移除该视频,确定是否移除'),
actions: [
TextButton(
onPressed: Get.back,
child: Text(
'取消',
style: TextStyle(color: Theme.of(context).colorScheme.outline),
),
),
TextButton(
onPressed: () async {
Get.back();
final res = await UserHttp.toViewDel(aids: aid.toString());
if (res['status']) {
loadingState
..value.data!.removeAt(index)
..refresh();
onSuccess?.call();
}
SmartDialog.showToast(res['msg']);
},
child: const Text('确认移除'),
),
],
);
},
);
}
}
class LaterController extends MultiSelectController<LaterData, LaterItemModel>
with BaseLaterController {
LaterController(this.laterViewType); LaterController(this.laterViewType);
final LaterViewType laterViewType; final LaterViewType laterViewType;
@@ -56,43 +106,6 @@ class LaterController extends MultiSelectController<LaterData, LaterItemModel> {
} }
} }
// single
void toViewDel(BuildContext context, int index, int? aid) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('提示'),
content: const Text('即将移除该视频,确定是否移除'),
actions: [
TextButton(
onPressed: Get.back,
child: Text(
'取消',
style: TextStyle(color: Theme.of(context).colorScheme.outline),
),
),
TextButton(
onPressed: () async {
Get.back();
final res = await UserHttp.toViewDel(aids: aid.toString());
if (res['status']) {
baseCtr.counts[laterViewType] =
baseCtr.counts[laterViewType]! - 1;
loadingState
..value.data!.removeAt(index)
..refresh();
}
SmartDialog.showToast(res['msg']);
},
child: const Text('确认移除'),
),
],
);
},
);
}
// 一键清空 // 一键清空
void toViewClear(BuildContext context, [int? cleanType]) { void toViewClear(BuildContext context, [int? cleanType]) {
String content = switch (cleanType) { String content = switch (cleanType) {

View File

@@ -1,7 +1,6 @@
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/button/icon_button.dart'; import 'package:PiliPlus/common/widgets/button/icon_button.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/common/widgets/select_mask.dart'; import 'package:PiliPlus/common/widgets/select_mask.dart';
@@ -11,6 +10,7 @@ import 'package:PiliPlus/models/common/badge_type.dart';
import 'package:PiliPlus/models/common/stat_type.dart'; import 'package:PiliPlus/models/common/stat_type.dart';
import 'package:PiliPlus/models/search/result.dart'; import 'package:PiliPlus/models/search/result.dart';
import 'package:PiliPlus/models_new/later/list.dart'; import 'package:PiliPlus/models_new/later/list.dart';
import 'package:PiliPlus/pages/later/controller.dart';
import 'package:PiliPlus/utils/duration_util.dart'; import 'package:PiliPlus/utils/duration_util.dart';
import 'package:PiliPlus/utils/page_utils.dart'; import 'package:PiliPlus/utils/page_utils.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -20,17 +20,15 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
class VideoCardHLater extends StatelessWidget { class VideoCardHLater extends StatelessWidget {
const VideoCardHLater({ const VideoCardHLater({
super.key, super.key,
required this.ctr,
required this.videoItem, required this.videoItem,
this.onTap,
this.onLongPress,
this.onViewLater, this.onViewLater,
this.onRemove, required this.onRemove,
}); });
final BaseLaterController ctr;
final LaterItemModel videoItem; final LaterItemModel videoItem;
final VoidCallback? onTap;
final VoidCallback? onLongPress;
final ValueChanged<int>? onViewLater; final ValueChanged<int>? onViewLater;
final VoidCallback? onRemove; final VoidCallback onRemove;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -41,45 +39,45 @@ class VideoCardHLater extends StatelessWidget {
type = typeOrNull!; type = typeOrNull!;
} }
} }
final theme = Theme.of(context);
final enableMultiSelect = ctr.enableMultiSelect.value;
return Material( return Material(
type: MaterialType.transparency, type: MaterialType.transparency,
child: InkWell( child: InkWell(
onLongPress: onLongPress: enableMultiSelect
onLongPress ?? ? null
() => imageSaveDialog( : () => ctr
title: videoItem.title, ..enableMultiSelect.value = true
cover: videoItem.pic, ..onSelect(videoItem),
bvid: videoItem.bvid, onTap: enableMultiSelect
), ? () => ctr.onSelect(videoItem)
onTap: : () async {
onTap ?? if (type == 'ketang') {
() async { PageUtils.viewPugv(seasonId: videoItem.aid);
if (type == 'ketang') { return;
PageUtils.viewPugv(seasonId: videoItem.aid);
return;
}
if (videoItem.isPgc == true) {
if (videoItem.bangumi?.epId != null) {
PageUtils.viewPgc(epId: videoItem.bangumi!.epId);
} else if (videoItem.redirectUrl?.isNotEmpty == true) {
PageUtils.viewPgcFromUri(videoItem.redirectUrl!);
} }
return; if (videoItem.isPgc == true) {
} if (videoItem.bangumi?.epId != null) {
try { PageUtils.viewPgc(epId: videoItem.bangumi!.epId);
final int? cid = } else if (videoItem.redirectUrl?.isNotEmpty == true) {
videoItem.cid ?? PageUtils.viewPgcFromUri(videoItem.redirectUrl!);
await SearchHttp.ab2c( }
aid: videoItem.aid, return;
bvid: videoItem.bvid,
);
if (cid != null) {
onViewLater!(cid);
} }
} catch (err) { try {
SmartDialog.showToast(err.toString()); final int? cid =
} videoItem.cid ??
}, await SearchHttp.ab2c(
aid: videoItem.aid,
bvid: videoItem.bvid,
);
if (cid != null) {
onViewLater!(cid);
}
} catch (err) {
SmartDialog.showToast(err.toString());
}
},
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
horizontal: StyleString.safeSpace, horizontal: StyleString.safeSpace,
@@ -158,7 +156,7 @@ class VideoCardHLater extends StatelessWidget {
), ),
Positioned.fill( Positioned.fill(
child: selectMask( child: selectMask(
Theme.of(context), theme,
videoItem.checked == true, videoItem.checked == true,
), ),
), ),
@@ -168,7 +166,7 @@ class VideoCardHLater extends StatelessWidget {
), ),
), ),
const SizedBox(width: 10), const SizedBox(width: 10),
content(context), content(context, theme),
], ],
), ),
), ),
@@ -176,13 +174,36 @@ class VideoCardHLater extends StatelessWidget {
); );
} }
Widget content(BuildContext context) { Widget content(BuildContext context, ThemeData theme) {
final theme = Theme.of(context); final isPgc = videoItem.isPgc == true && videoItem.bangumi != null;
Widget bottom = Row(
spacing: 8,
children: [
StatWidget(
type: StatType.play,
value: videoItem.stat?.view,
),
if (!isPgc)
StatWidget(
type: StatType.danmaku,
value: videoItem.stat?.danmaku,
),
const Spacer(),
iconButton(
tooltip: '移除',
context: context,
onPressed: onRemove,
icon: Icons.clear,
iconColor: theme.colorScheme.outline,
bgColor: Colors.transparent,
),
],
);
return Expanded( return Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
if (videoItem.isPgc == true && videoItem.bangumi != null) ...[ if (isPgc) ...[
Text( Text(
videoItem.bangumi!.season!.title!, videoItem.bangumi!.season!.title!,
style: TextStyle( style: TextStyle(
@@ -205,10 +226,7 @@ class VideoCardHLater extends StatelessWidget {
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
const Spacer(), const Spacer(),
StatWidget( bottom,
type: StatType.play,
value: videoItem.stat?.view,
),
] else ...[ ] else ...[
Expanded( Expanded(
child: Text( child: Text(
@@ -233,30 +251,7 @@ class VideoCardHLater extends StatelessWidget {
), ),
), ),
const SizedBox(height: 3), const SizedBox(height: 3),
Row( bottom,
spacing: 8,
children: [
StatWidget(
type: StatType.play,
value: videoItem.stat?.view,
),
StatWidget(
type: StatType.danmaku,
value: videoItem.stat?.danmaku,
),
if (onRemove != null) ...[
const Spacer(),
iconButton(
tooltip: '移除',
context: context,
onPressed: onRemove,
icon: Icons.clear,
iconColor: theme.colorScheme.outline,
bgColor: Colors.transparent,
),
],
],
),
], ],
], ],
), ),

View File

@@ -5,13 +5,16 @@ 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/common/multi_select/base.dart'; import 'package:PiliPlus/pages/common/multi_select/base.dart';
import 'package:PiliPlus/pages/common/search/common_search_controller.dart'; import 'package:PiliPlus/pages/common/search/common_search_controller.dart';
import 'package:flutter/material.dart'; import 'package:PiliPlus/pages/later/controller.dart' show BaseLaterController;
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';
class LaterSearchController class LaterSearchController
extends CommonSearchController<LaterData, LaterItemModel> extends CommonSearchController<LaterData, LaterItemModel>
with CommonMultiSelectMixin<LaterItemModel>, DeleteItemMixin { with
CommonMultiSelectMixin<LaterItemModel>,
DeleteItemMixin,
BaseLaterController {
dynamic mid = Get.arguments['mid']; dynamic mid = Get.arguments['mid'];
dynamic count = Get.arguments['count']; dynamic count = Get.arguments['count'];
@@ -26,15 +29,6 @@ class LaterSearchController
return response.list; return response.list;
} }
Future<void> toViewDel(BuildContext context, int index, int aid) async {
var res = await UserHttp.toViewDel(aids: aid.toString());
if (res['status']) {
loadingState.value.data!.removeAt(index);
loadingState.refresh();
}
SmartDialog.showToast(res['msg']);
}
@override @override
void onRemove() { void onRemove() {
showConfirmDialog( showConfirmDialog(

View File

@@ -37,9 +37,9 @@ class _LaterSearchPageState
controller.onLoadMore(); controller.onLoadMore();
} }
final item = list[index]; final item = list[index];
final enableMultiSelect = controller.enableMultiSelect.value;
return VideoCardHLater( return VideoCardHLater(
videoItem: item, videoItem: item,
ctr: controller,
onViewLater: (cid) { onViewLater: (cid) {
PageUtils.toVideoPage( PageUtils.toVideoPage(
bvid: item.bvid, bvid: item.bvid,
@@ -62,13 +62,6 @@ class _LaterSearchPageState
index, index,
item.aid!, item.aid!,
), ),
onTap: !enableMultiSelect ? null : () => controller.onSelect(item),
onLongPress: enableMultiSelect
? null
: () {
controller.enableMultiSelect.value = true;
controller.onSelect(item);
},
); );
}), }),
); );