opt: 首页推荐卡片

This commit is contained in:
guozhigq
2024-04-24 23:56:07 +08:00
parent e699df52e3
commit 72a8c33a66

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:pilipala/utils/feed_back.dart';
import '../../models/model_rec_video_item.dart';
import 'overlay_pop.dart';
import 'stat/danmu.dart';
@ -20,15 +21,11 @@ import 'network_img_layer.dart';
class VideoCardV extends StatelessWidget {
final dynamic videoItem;
final int crossAxisCount;
// final Function()? longPress;
// final Function()? longPressEnd;
const VideoCardV({
Key? key,
required this.videoItem,
required this.crossAxisCount,
// this.longPress,
// this.longPressEnd,
}) : super(key: key);
bool isStringNumeric(String str) {
@ -128,11 +125,7 @@ class VideoCardV extends StatelessWidget {
@override
Widget build(BuildContext context) {
String heroTag = Utils.makeHeroTag(videoItem.id);
return Card(
elevation: 0,
clipBehavior: Clip.hardEdge,
margin: EdgeInsets.zero,
child: InkWell(
return InkWell(
onTap: () async => onPushDetail(heroTag),
onLongPress: () {
SmartDialog.show(
@ -142,6 +135,7 @@ class VideoCardV extends StatelessWidget {
),
);
},
borderRadius: BorderRadius.circular(16),
child: Column(
children: [
AspectRatio(
@ -182,7 +176,6 @@ class VideoCardV extends StatelessWidget {
VideoContent(videoItem: videoItem, crossAxisCount: crossAxisCount)
],
),
),
);
}
}
@ -252,11 +245,28 @@ class VideoContent extends StatelessWidget {
const Spacer(),
],
if (videoItem.goto == 'av')
VideoPopupMenu(
size: 24,
iconSize: 14,
videoItem: videoItem,
SizedBox(
width: 24,
height: 24,
child: IconButton(
onPressed: () {
feedBack();
showModalBottomSheet(
context: context,
useRootNavigator: true,
isScrollControlled: true,
builder: (context) {
return MorePanel(videoItem: videoItem);
},
);
},
icon: Icon(
Icons.more_vert_outlined,
color: Theme.of(context).colorScheme.outline,
size: 14,
),
),
)
],
),
],
@ -279,15 +289,9 @@ class VideoStat extends StatelessWidget {
Widget build(BuildContext context) {
return Row(
children: [
StatView(
theme: 'gray',
view: videoItem.stat.view,
),
StatView(theme: 'gray', view: videoItem.stat.view),
const SizedBox(width: 8),
StatDanMu(
theme: 'gray',
danmu: videoItem.stat.danmu,
),
StatDanMu(theme: 'gray', danmu: videoItem.stat.danmu),
if (videoItem is RecVideoItemModel) ...<Widget>[
crossAxisCount > 1 ? const Spacer() : const SizedBox(width: 8),
RichText(
@ -306,68 +310,39 @@ class VideoStat extends StatelessWidget {
}
}
class VideoPopupMenu extends StatelessWidget {
final double? size;
final double? iconSize;
class MorePanel extends StatelessWidget {
final dynamic videoItem;
const MorePanel({super.key, required this.videoItem});
const VideoPopupMenu({
Key? key,
required this.size,
required this.iconSize,
required this.videoItem,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return SizedBox(
width: size,
height: size,
child: PopupMenuButton<String>(
padding: EdgeInsets.zero,
icon: Icon(
Icons.more_vert_outlined,
color: Theme.of(context).colorScheme.outline,
size: iconSize,
),
position: PopupMenuPosition.under,
onSelected: (String type) {},
itemBuilder: (BuildContext context) => <PopupMenuEntry<String>>[
PopupMenuItem<String>(
onTap: () async {
var res =
await UserHttp.toViewLater(bvid: videoItem.bvid as String);
Future<dynamic> menuActionHandler(String type) async {
switch (type) {
case 'block':
blockUser();
break;
case 'watchLater':
var res = await UserHttp.toViewLater(bvid: videoItem.bvid as String);
SmartDialog.showToast(res['msg']);
},
value: 'pause',
height: 40,
child: const Row(
children: [
Icon(Icons.watch_later_outlined, size: 16),
SizedBox(width: 6),
Text('稍后再看', style: TextStyle(fontSize: 13))
],
),
),
const PopupMenuDivider(),
PopupMenuItem<String>(
onTap: () async {
Get.back();
break;
default:
}
}
void blockUser() async {
SmartDialog.show(
useSystem: true,
animationType: SmartAnimationType.centerFade_otherSlide,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('提示'),
content: Text(
'确定拉黑:${videoItem.owner.name}(${videoItem.owner.mid})?'
content: Text('确定拉黑:${videoItem.owner.name}(${videoItem.owner.mid})?'
'\n\n被拉黑的Up可以在隐私设置-黑名单管理中解除'),
actions: [
TextButton(
onPressed: () => SmartDialog.dismiss(),
child: Text(
'点错了',
style: TextStyle(
color: Theme.of(context).colorScheme.outline),
style: TextStyle(color: Theme.of(context).colorScheme.outline),
),
),
TextButton(
@ -386,18 +361,47 @@ class VideoPopupMenu extends StatelessWidget {
);
},
);
},
value: 'pause',
height: 40,
child: Row(
}
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.block, size: 16),
const SizedBox(width: 6),
Text('拉黑:${videoItem.owner.name}',
style: const TextStyle(fontSize: 13))
],
InkWell(
onTap: () => Get.back(),
child: Container(
height: 35,
padding: const EdgeInsets.only(bottom: 2),
child: Center(
child: Container(
width: 32,
height: 3,
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.outline,
borderRadius: const BorderRadius.all(Radius.circular(3))),
),
),
),
),
ListTile(
onTap: () async => await menuActionHandler('block'),
minLeadingWidth: 0,
leading: const Icon(Icons.block, size: 19),
title: Text(
'拉黑up主 「${videoItem.owner.name}',
style: Theme.of(context).textTheme.titleSmall,
),
),
ListTile(
onTap: () async => await menuActionHandler('watchLater'),
minLeadingWidth: 0,
leading: const Icon(Icons.watch_later_outlined, size: 19),
title:
Text('添加至稍后再看', style: Theme.of(context).textTheme.titleSmall),
),
],
),
);