feat: 历史记录多选删除
This commit is contained in:
@ -164,6 +164,9 @@ class Api {
|
|||||||
// 清空历史记录
|
// 清空历史记录
|
||||||
static const String clearHistory = '/x/v2/history/clear';
|
static const String clearHistory = '/x/v2/history/clear';
|
||||||
|
|
||||||
|
// 删除某条历史记录
|
||||||
|
static const String delHistory = '/x/v2/history/delete';
|
||||||
|
|
||||||
// 热搜
|
// 热搜
|
||||||
static const String hotSearchList =
|
static const String hotSearchList =
|
||||||
'https://s.search.bilibili.com/main/hotword';
|
'https://s.search.bilibili.com/main/hotword';
|
||||||
|
|||||||
@ -231,4 +231,21 @@ class UserHttp {
|
|||||||
return {'status': false, 'msg': res.data['message']};
|
return {'status': false, 'msg': res.data['message']};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 删除历史记录
|
||||||
|
static Future delHistory(kid) async {
|
||||||
|
var res = await Request().post(
|
||||||
|
Api.delHistory,
|
||||||
|
queryParameters: {
|
||||||
|
'kid': kid,
|
||||||
|
'jsonp': 'jsonp',
|
||||||
|
'csrf': await Request.getCsrf(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (res.data['code'] == 0) {
|
||||||
|
return {'status': true, 'msg': '已删除'};
|
||||||
|
} else {
|
||||||
|
return {'status': false, 'msg': res.data['message']};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -79,6 +79,7 @@ class HisListItem {
|
|||||||
this.kid,
|
this.kid,
|
||||||
this.tagName,
|
this.tagName,
|
||||||
this.liveStatus,
|
this.liveStatus,
|
||||||
|
this.checked,
|
||||||
});
|
});
|
||||||
|
|
||||||
String? title;
|
String? title;
|
||||||
@ -105,6 +106,7 @@ class HisListItem {
|
|||||||
int? kid;
|
int? kid;
|
||||||
String? tagName;
|
String? tagName;
|
||||||
int? liveStatus;
|
int? liveStatus;
|
||||||
|
bool? checked;
|
||||||
|
|
||||||
HisListItem.fromJson(Map<String, dynamic> json) {
|
HisListItem.fromJson(Map<String, dynamic> json) {
|
||||||
title = json['title'];
|
title = json['title'];
|
||||||
@ -131,6 +133,7 @@ class HisListItem {
|
|||||||
kid = json['kid'];
|
kid = json['kid'];
|
||||||
tagName = json['tag_name'];
|
tagName = json['tag_name'];
|
||||||
liveStatus = json['live_status'];
|
liveStatus = json['live_status'];
|
||||||
|
checked = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,11 +8,13 @@ import 'package:pilipala/utils/storage.dart';
|
|||||||
|
|
||||||
class HistoryController extends GetxController {
|
class HistoryController extends GetxController {
|
||||||
final ScrollController scrollController = ScrollController();
|
final ScrollController scrollController = ScrollController();
|
||||||
RxList<HisListItem> historyList = [HisListItem()].obs;
|
RxList<HisListItem> historyList = <HisListItem>[].obs;
|
||||||
RxBool isLoadingMore = false.obs;
|
RxBool isLoadingMore = false.obs;
|
||||||
RxBool pauseStatus = false.obs;
|
RxBool pauseStatus = false.obs;
|
||||||
Box localCache = GStrorage.localCache;
|
Box localCache = GStrorage.localCache;
|
||||||
RxBool isLoading = false.obs;
|
RxBool isLoading = false.obs;
|
||||||
|
RxBool enableMultiple = false.obs;
|
||||||
|
RxInt checkedCount = 0.obs;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
@ -56,7 +58,8 @@ class HistoryController extends GetxController {
|
|||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
title: const Text('提示'),
|
title: const Text('提示'),
|
||||||
content: Text(!pauseStatus.value ? '你要暂停历史记录功能吗?' : '要恢复历史记录功能吗?'),
|
content:
|
||||||
|
Text(!pauseStatus.value ? '啊叻?你要暂停历史记录功能吗?' : '啊叻?要恢复历史记录功能吗?'),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => SmartDialog.dismiss(),
|
onPressed: () => SmartDialog.dismiss(),
|
||||||
@ -97,7 +100,7 @@ class HistoryController extends GetxController {
|
|||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
title: const Text('提示'),
|
title: const Text('提示'),
|
||||||
content: const Text('你要清空历史记录功能吗?'),
|
content: const Text('啊叻?你要清空历史记录功能吗?'),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => SmartDialog.dismiss(),
|
onPressed: () => SmartDialog.dismiss(),
|
||||||
@ -120,4 +123,75 @@ class HistoryController extends GetxController {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 删除某条历史记录
|
||||||
|
Future delHistory(kid, business) async {
|
||||||
|
String resKid = 'archive_$kid';
|
||||||
|
if (business == 'live') {
|
||||||
|
resKid = 'live_$kid';
|
||||||
|
} else if (business.contains('article')) {
|
||||||
|
resKid = 'article_$kid';
|
||||||
|
}
|
||||||
|
|
||||||
|
var res = await UserHttp.delHistory(resKid);
|
||||||
|
if (res['status']) {
|
||||||
|
historyList.removeWhere((e) => e.kid == kid);
|
||||||
|
SmartDialog.showToast(res['msg']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除已看历史记录
|
||||||
|
Future onDelHistory() async {
|
||||||
|
/// TODO 优化
|
||||||
|
List<HisListItem> result =
|
||||||
|
historyList.where((e) => e.progress == -1).toList();
|
||||||
|
for (HisListItem i in result) {
|
||||||
|
String resKid = 'archive_${i.kid}';
|
||||||
|
await UserHttp.delHistory(resKid);
|
||||||
|
historyList.removeWhere((e) => e.kid == i.kid);
|
||||||
|
}
|
||||||
|
SmartDialog.showToast('操作完成');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除选中的记录
|
||||||
|
Future onDelCheckedHistory() async {
|
||||||
|
SmartDialog.show(
|
||||||
|
useSystem: true,
|
||||||
|
animationType: SmartAnimationType.centerFade_otherSlide,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: const Text('提示'),
|
||||||
|
content: const Text('确认删除所选历史记录吗?'),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => SmartDialog.dismiss(),
|
||||||
|
child: Text(
|
||||||
|
'取消',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.outline,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
/// TODO 优化
|
||||||
|
await SmartDialog.dismiss();
|
||||||
|
SmartDialog.showLoading(msg: '请求中');
|
||||||
|
List<HisListItem> result =
|
||||||
|
historyList.where((e) => e.checked!).toList();
|
||||||
|
for (HisListItem i in result) {
|
||||||
|
String resKid = 'archive_${i.kid}';
|
||||||
|
await UserHttp.delHistory(resKid);
|
||||||
|
historyList.removeWhere((e) => e.kid == i.kid);
|
||||||
|
}
|
||||||
|
checkedCount.value = 0;
|
||||||
|
SmartDialog.dismiss();
|
||||||
|
},
|
||||||
|
child: const Text('确认'),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,6 +39,20 @@ class _HistoryPageState extends State<HistoryPage> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 选中
|
||||||
|
onChoose(index) {
|
||||||
|
_historyController.historyList[index].checked =
|
||||||
|
!_historyController.historyList[index].checked!;
|
||||||
|
_historyController.checkedCount.value =
|
||||||
|
_historyController.historyList.where((item) => item.checked!).length;
|
||||||
|
_historyController.historyList.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新多选状态
|
||||||
|
onUpdateMultiple() {
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
scrollController.removeListener(() {});
|
scrollController.removeListener(() {});
|
||||||
@ -48,44 +62,115 @@ class _HistoryPageState extends State<HistoryPage> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBarWidget(
|
||||||
titleSpacing: 0,
|
visible: _historyController.enableMultiple.value,
|
||||||
centerTitle: false,
|
child1: AppBar(
|
||||||
title: Text(
|
titleSpacing: 0,
|
||||||
'观看记录',
|
centerTitle: false,
|
||||||
style: Theme.of(context).textTheme.titleMedium,
|
leading: IconButton(
|
||||||
),
|
onPressed: () => Get.back(),
|
||||||
actions: [
|
icon: const Icon(Icons.arrow_back_outlined),
|
||||||
PopupMenuButton<String>(
|
|
||||||
onSelected: (String type) {
|
|
||||||
// 处理菜单项选择的逻辑
|
|
||||||
switch (type) {
|
|
||||||
case 'pause':
|
|
||||||
_historyController.onPauseHistory();
|
|
||||||
break;
|
|
||||||
case 'clear':
|
|
||||||
_historyController.onClearHistory();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
},
|
|
||||||
itemBuilder: (BuildContext context) => <PopupMenuEntry<String>>[
|
|
||||||
PopupMenuItem<String>(
|
|
||||||
value: 'pause',
|
|
||||||
child: Obx(
|
|
||||||
() => Text(!_historyController.pauseStatus.value
|
|
||||||
? '暂停观看记录'
|
|
||||||
: '恢复观看记录'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const PopupMenuItem<String>(
|
|
||||||
value: 'clear',
|
|
||||||
child: Text('清空观看记录'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
const SizedBox(width: 6),
|
title: Text(
|
||||||
],
|
'观看记录',
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
// TextButton(
|
||||||
|
// onPressed: () {
|
||||||
|
// _historyController.enableMultiple.value = true;
|
||||||
|
// setState(() {});
|
||||||
|
// },
|
||||||
|
// child: const Text('多选'),
|
||||||
|
// ),
|
||||||
|
PopupMenuButton<String>(
|
||||||
|
onSelected: (String type) {
|
||||||
|
// 处理菜单项选择的逻辑
|
||||||
|
switch (type) {
|
||||||
|
case 'pause':
|
||||||
|
_historyController.onPauseHistory();
|
||||||
|
break;
|
||||||
|
case 'clear':
|
||||||
|
_historyController.onClearHistory();
|
||||||
|
break;
|
||||||
|
case 'del':
|
||||||
|
_historyController.onDelHistory();
|
||||||
|
break;
|
||||||
|
case 'multiple':
|
||||||
|
_historyController.enableMultiple.value = true;
|
||||||
|
setState(() {});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
},
|
||||||
|
itemBuilder: (BuildContext context) => <PopupMenuEntry<String>>[
|
||||||
|
PopupMenuItem<String>(
|
||||||
|
value: 'pause',
|
||||||
|
child: Obx(
|
||||||
|
() => Text(!_historyController.pauseStatus.value
|
||||||
|
? '暂停观看记录'
|
||||||
|
: '恢复观看记录'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const PopupMenuItem<String>(
|
||||||
|
value: 'clear',
|
||||||
|
child: Text('清空观看记录'),
|
||||||
|
),
|
||||||
|
const PopupMenuItem<String>(
|
||||||
|
value: 'del',
|
||||||
|
child: Text('删除已看记录'),
|
||||||
|
),
|
||||||
|
const PopupMenuItem<String>(
|
||||||
|
value: 'multiple',
|
||||||
|
child: Text('多选删除'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(width: 6),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child2: AppBar(
|
||||||
|
titleSpacing: 0,
|
||||||
|
centerTitle: false,
|
||||||
|
leading: IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
_historyController.enableMultiple.value = false;
|
||||||
|
for (var item in _historyController.historyList) {
|
||||||
|
item.checked = false;
|
||||||
|
}
|
||||||
|
_historyController.checkedCount.value = 0;
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.close_outlined),
|
||||||
|
),
|
||||||
|
title: Obx(
|
||||||
|
() => Text(
|
||||||
|
'已选择${_historyController.checkedCount.value}项',
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
for (var item in _historyController.historyList) {
|
||||||
|
item.checked = true;
|
||||||
|
}
|
||||||
|
_historyController.checkedCount.value =
|
||||||
|
_historyController.historyList.length;
|
||||||
|
_historyController.historyList.refresh();
|
||||||
|
},
|
||||||
|
child: const Text('全选'),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => _historyController.onDelCheckedHistory(),
|
||||||
|
child: Text(
|
||||||
|
'删除',
|
||||||
|
style: TextStyle(color: Theme.of(context).colorScheme.error),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 6),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
body: RefreshIndicator(
|
body: RefreshIndicator(
|
||||||
onRefresh: () async {
|
onRefresh: () async {
|
||||||
@ -112,6 +197,9 @@ class _HistoryPageState extends State<HistoryPage> {
|
|||||||
return HistoryItem(
|
return HistoryItem(
|
||||||
videoItem:
|
videoItem:
|
||||||
_historyController.historyList[index],
|
_historyController.historyList[index],
|
||||||
|
ctr: _historyController,
|
||||||
|
onChoose: () => onChoose(index),
|
||||||
|
onUpdateMultiple: () => onUpdateMultiple(),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
childCount:
|
childCount:
|
||||||
@ -147,6 +235,36 @@ class _HistoryPageState extends State<HistoryPage> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
// bottomNavigationBar: BottomAppBar(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AppBarWidget extends StatelessWidget implements PreferredSizeWidget {
|
||||||
|
const AppBarWidget({
|
||||||
|
required this.child1,
|
||||||
|
required this.child2,
|
||||||
|
required this.visible,
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: 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,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,12 +11,23 @@ import 'package:pilipala/models/bangumi/info.dart';
|
|||||||
import 'package:pilipala/models/common/business_type.dart';
|
import 'package:pilipala/models/common/business_type.dart';
|
||||||
import 'package:pilipala/models/common/search_type.dart';
|
import 'package:pilipala/models/common/search_type.dart';
|
||||||
import 'package:pilipala/models/live/item.dart';
|
import 'package:pilipala/models/live/item.dart';
|
||||||
|
import 'package:pilipala/pages/history/index.dart';
|
||||||
|
import 'package:pilipala/utils/feed_back.dart';
|
||||||
import 'package:pilipala/utils/id_utils.dart';
|
import 'package:pilipala/utils/id_utils.dart';
|
||||||
import 'package:pilipala/utils/utils.dart';
|
import 'package:pilipala/utils/utils.dart';
|
||||||
|
|
||||||
class HistoryItem extends StatelessWidget {
|
class HistoryItem extends StatelessWidget {
|
||||||
final dynamic videoItem;
|
final dynamic videoItem;
|
||||||
const HistoryItem({super.key, required this.videoItem});
|
final HistoryController? ctr;
|
||||||
|
final Function? onChoose;
|
||||||
|
final Function? onUpdateMultiple;
|
||||||
|
const HistoryItem({
|
||||||
|
super.key,
|
||||||
|
required this.videoItem,
|
||||||
|
this.ctr,
|
||||||
|
this.onChoose,
|
||||||
|
this.onUpdateMultiple,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -25,6 +36,11 @@ class HistoryItem extends StatelessWidget {
|
|||||||
String heroTag = Utils.makeHeroTag(aid);
|
String heroTag = Utils.makeHeroTag(aid);
|
||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
|
if (ctr!.enableMultiple.value) {
|
||||||
|
feedBack();
|
||||||
|
onChoose!();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (videoItem.history.business.contains('article')) {
|
if (videoItem.history.business.contains('article')) {
|
||||||
int cid = videoItem.history.cid ??
|
int cid = videoItem.history.cid ??
|
||||||
// videoItem.history.oid ??
|
// videoItem.history.oid ??
|
||||||
@ -115,6 +131,14 @@ class HistoryItem extends StatelessWidget {
|
|||||||
arguments: {'heroTag': heroTag, 'pic': videoItem.cover});
|
arguments: {'heroTag': heroTag, 'pic': videoItem.cover});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
onLongPress: () {
|
||||||
|
if (!ctr!.enableMultiple.value) {
|
||||||
|
feedBack();
|
||||||
|
ctr!.enableMultiple.value = true;
|
||||||
|
onChoose!();
|
||||||
|
onUpdateMultiple!();
|
||||||
|
}
|
||||||
|
},
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
@ -130,53 +154,105 @@ class HistoryItem extends StatelessWidget {
|
|||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
AspectRatio(
|
Stack(
|
||||||
aspectRatio: StyleString.aspectRatio,
|
children: [
|
||||||
child: LayoutBuilder(
|
AspectRatio(
|
||||||
builder: (context, boxConstraints) {
|
aspectRatio: StyleString.aspectRatio,
|
||||||
double maxWidth = boxConstraints.maxWidth;
|
child: LayoutBuilder(
|
||||||
double maxHeight = boxConstraints.maxHeight;
|
builder: (context, boxConstraints) {
|
||||||
return Stack(
|
double maxWidth = boxConstraints.maxWidth;
|
||||||
children: [
|
double maxHeight = boxConstraints.maxHeight;
|
||||||
Hero(
|
return Stack(
|
||||||
tag: heroTag,
|
children: [
|
||||||
child: NetworkImgLayer(
|
Hero(
|
||||||
src: (videoItem.cover != ''
|
tag: heroTag,
|
||||||
? videoItem.cover
|
child: NetworkImgLayer(
|
||||||
: videoItem.covers.first),
|
src: (videoItem.cover != ''
|
||||||
width: maxWidth,
|
? videoItem.cover
|
||||||
height: maxHeight,
|
: videoItem.covers.first),
|
||||||
|
width: maxWidth,
|
||||||
|
height: maxHeight,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (!BusinessType
|
||||||
|
.hiddenDurationType.hiddenDurationType
|
||||||
|
.contains(videoItem.history.business))
|
||||||
|
PBadge(
|
||||||
|
text: videoItem.progress == -1
|
||||||
|
? '已看完'
|
||||||
|
: '${Utils.timeFormat(videoItem.progress!)}/${Utils.timeFormat(videoItem.duration!)}',
|
||||||
|
right: 6.0,
|
||||||
|
bottom: 6.0,
|
||||||
|
type: 'gray',
|
||||||
|
),
|
||||||
|
// 右上角
|
||||||
|
if (BusinessType.showBadge.showBadge
|
||||||
|
.contains(
|
||||||
|
videoItem.history.business) ||
|
||||||
|
videoItem.history.business ==
|
||||||
|
BusinessType.live.type)
|
||||||
|
PBadge(
|
||||||
|
text: videoItem.badge,
|
||||||
|
top: 6.0,
|
||||||
|
right: 6.0,
|
||||||
|
bottom: null,
|
||||||
|
left: null,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Obx(
|
||||||
|
() => Positioned.fill(
|
||||||
|
child: AnimatedOpacity(
|
||||||
|
opacity: ctr!.enableMultiple.value ? 1 : 0,
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
color: Colors.black.withOpacity(0.6),
|
||||||
|
),
|
||||||
|
child: Center(
|
||||||
|
child: SizedBox(
|
||||||
|
width: 34,
|
||||||
|
height: 34,
|
||||||
|
child: IconButton(
|
||||||
|
style: ButtonStyle(
|
||||||
|
padding: MaterialStateProperty.all(
|
||||||
|
EdgeInsets.zero),
|
||||||
|
backgroundColor:
|
||||||
|
MaterialStateProperty.resolveWith(
|
||||||
|
(states) {
|
||||||
|
return Colors.white
|
||||||
|
.withOpacity(0.8);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
feedBack();
|
||||||
|
onChoose!();
|
||||||
|
},
|
||||||
|
icon: Icon(
|
||||||
|
Icons.done_all_outlined,
|
||||||
|
color: videoItem.checked
|
||||||
|
? Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.primary
|
||||||
|
: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.outline,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (!BusinessType
|
),
|
||||||
.hiddenDurationType.hiddenDurationType
|
),
|
||||||
.contains(videoItem.history.business))
|
),
|
||||||
PBadge(
|
],
|
||||||
text: videoItem.progress == -1
|
|
||||||
? '已看完'
|
|
||||||
: '${Utils.timeFormat(videoItem.progress!)}/${Utils.timeFormat(videoItem.duration!)}',
|
|
||||||
right: 6.0,
|
|
||||||
bottom: 6.0,
|
|
||||||
type: 'gray',
|
|
||||||
),
|
|
||||||
// 右上角
|
|
||||||
if (BusinessType.showBadge.showBadge
|
|
||||||
.contains(videoItem.history.business) ||
|
|
||||||
videoItem.history.business ==
|
|
||||||
BusinessType.live.type)
|
|
||||||
PBadge(
|
|
||||||
text: videoItem.badge,
|
|
||||||
top: 6.0,
|
|
||||||
right: 6.0,
|
|
||||||
bottom: null,
|
|
||||||
left: null,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
VideoContent(videoItem: videoItem)
|
VideoContent(videoItem: videoItem, ctr: ctr)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -191,7 +267,8 @@ class HistoryItem extends StatelessWidget {
|
|||||||
|
|
||||||
class VideoContent extends StatelessWidget {
|
class VideoContent extends StatelessWidget {
|
||||||
final dynamic videoItem;
|
final dynamic videoItem;
|
||||||
const VideoContent({super.key, required this.videoItem});
|
final HistoryController? ctr;
|
||||||
|
const VideoContent({super.key, required this.videoItem, this.ctr});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -244,26 +321,26 @@ class VideoContent extends StatelessWidget {
|
|||||||
Theme.of(context).textTheme.labelMedium!.fontSize,
|
Theme.of(context).textTheme.labelMedium!.fontSize,
|
||||||
color: Theme.of(context).colorScheme.outline),
|
color: Theme.of(context).colorScheme.outline),
|
||||||
),
|
),
|
||||||
if (videoItem.badge != '番剧' &&
|
SizedBox(
|
||||||
!videoItem.tagName.contains('动画') &&
|
width: 24,
|
||||||
videoItem.history.business != 'live' &&
|
height: 24,
|
||||||
!videoItem.history.business.contains('article'))
|
child: PopupMenuButton<String>(
|
||||||
SizedBox(
|
padding: EdgeInsets.zero,
|
||||||
width: 24,
|
tooltip: '功能菜单',
|
||||||
height: 24,
|
icon: Icon(
|
||||||
child: PopupMenuButton<String>(
|
Icons.more_vert_outlined,
|
||||||
padding: EdgeInsets.zero,
|
color: Theme.of(context).colorScheme.outline,
|
||||||
tooltip: '稍后再看',
|
size: 14,
|
||||||
icon: Icon(
|
),
|
||||||
Icons.more_vert_outlined,
|
position: PopupMenuPosition.under,
|
||||||
color: Theme.of(context).colorScheme.outline,
|
// constraints: const BoxConstraints(maxHeight: 35),
|
||||||
size: 14,
|
onSelected: (String type) {},
|
||||||
),
|
itemBuilder: (BuildContext context) =>
|
||||||
position: PopupMenuPosition.under,
|
<PopupMenuEntry<String>>[
|
||||||
// constraints: const BoxConstraints(maxHeight: 35),
|
if (videoItem.badge != '番剧' &&
|
||||||
onSelected: (String type) {},
|
!videoItem.tagName.contains('动画') &&
|
||||||
itemBuilder: (BuildContext context) =>
|
videoItem.history.business != 'live' &&
|
||||||
<PopupMenuEntry<String>>[
|
!videoItem.history.business.contains('article'))
|
||||||
PopupMenuItem<String>(
|
PopupMenuItem<String>(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
var res = await UserHttp.toViewLater(
|
var res = await UserHttp.toViewLater(
|
||||||
@ -280,9 +357,22 @@ class VideoContent extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
PopupMenuItem<String>(
|
||||||
),
|
onTap: () => ctr!.delHistory(
|
||||||
|
videoItem.kid, videoItem.history.business),
|
||||||
|
value: 'pause',
|
||||||
|
height: 35,
|
||||||
|
child: const Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.close_outlined, size: 16),
|
||||||
|
SizedBox(width: 6),
|
||||||
|
Text('删除记录', style: TextStyle(fontSize: 13))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in New Issue
Block a user