feat: 新增长按删评论功能

This commit is contained in:
orz12
2024-04-22 20:08:27 +08:00
parent 6661967276
commit 65ce59984d
5 changed files with 106 additions and 40 deletions

View File

@@ -120,6 +120,10 @@ class Api {
// https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/comment/action.md
static const String replyAdd = '/x/v2/reply/add';
// 删除评论
// https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/comment/action.md
static const String replyDel = '/x/v2/reply/del';
// 用户(被)关注数、投稿数
// https://api.bilibili.com/x/relation/stat?vmid=697166795
static const String userStat = '/x/relation/stat';

View File

@@ -376,6 +376,25 @@ class VideoHttp {
}
}
static Future replyDel({
required int type,//replyType
required int oid,
required int rpid,
}) async {
var res = await Request().post(Api.replyDel, queryParameters: {
'type': type,//type.index
'oid': oid,
'rpid': rpid,
'csrf': await Request.getCsrf(),
});
log(res.toString());
if (res.data['code'] == 0) {
return {'status': true};
} else {
return {'status': false, 'msg': res.data['message']};
}
}
// 查询是否关注up
static Future hasFollow({required int mid}) async {
var res = await Request().get(Api.hasFollow, data: {'fid': mid});
@@ -584,14 +603,11 @@ class VideoHttp {
}
}
if (subtitlesVtt.isNotEmpty) {
subtitlesVtt.insert(0, {
'language': '',
'title': '关闭字幕',
'text': ""
});
subtitlesVtt.insert(0, {'language': '', 'title': '关闭字幕', 'text': ""});
}
return subtitlesVtt;
}
// 视频排行
static Future getRankVideoList(int rid) async {
try {

View File

@@ -23,18 +23,16 @@ class ReplyData {
page = ReplyPage.fromJson(json['page']);
config = ReplyConfig.fromJson(json['config']);
replies = json['replies'] != null
? json['replies']
? List<ReplyItemModel>.from(json['replies']
.map<ReplyItemModel>(
(item) => ReplyItemModel.fromJson(item, json['upper']['mid']))
.toList()
: [];
(item) => ReplyItemModel.fromJson(item, json['upper']['mid'])))
: <ReplyItemModel>[];
topReplies = json['top_replies'] != null
? json['top_replies']
? List<ReplyItemModel>.from(json['top_replies']
.map<ReplyItemModel>((item) => ReplyItemModel.fromJson(
item, json['upper']['mid'],
isTopStatus: true))
.toList()
: [];
isTopStatus: true)))
: <ReplyItemModel>[];
upper = ReplyUpper.fromJson(json['upper']);
}
}

View File

@@ -53,7 +53,7 @@ class ReplyItemModel {
int? action;
ReplyMember? member;
ReplyContent? content;
List? replies;
List<ReplyItemModel>? replies;
int? assist;
UpAction? upAction;
bool? invisible;
@@ -85,10 +85,9 @@ class ReplyItemModel {
member = ReplyMember.fromJson(json['member']);
content = ReplyContent.fromJson(json['content']);
replies = json['replies'] != null
? json['replies']
.map((item) => ReplyItemModel.fromJson(item, upperMid))
.toList()
: [];
? List<ReplyItemModel>.from(json['replies']
.map((item) => ReplyItemModel.fromJson(item, upperMid)))
: <ReplyItemModel>[];
assist = json['assist'];
upAction = UpAction.fromJson(json['up_action']);
invisible = json['invisible'];

View File

@@ -1,3 +1,4 @@
import 'package:PiliPalaX/http/video.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
@@ -54,7 +55,7 @@ class ReplyItem extends StatelessWidget {
useRootNavigator: true,
isScrollControlled: true,
builder: (context) {
return MorePanel(item: replyItem);
return MorePanel(item: replyItem!);
},
);
},
@@ -273,6 +274,7 @@ class ReplyItem extends StatelessWidget {
onPressed: () {
feedBack();
showModalBottomSheet(
isDismissible: false,
context: context,
isScrollControlled: true,
builder: (builder) {
@@ -347,7 +349,7 @@ class ReplyItemRow extends StatelessWidget {
this.replyItem,
this.replyReply,
});
final List? replies;
final List<ReplyItemModel>? replies;
ReplyControl? replyControl;
// int? f_rpid;
ReplyItemModel? replyItem;
@@ -392,9 +394,8 @@ class ReplyItemRow extends StatelessWidget {
i == 0 && (extraRow == 1 || replies!.length > 1) ? 4 : 6,
),
child: Semantics(
label: replies![i].member.uname +
' ' +
replies![i].content.message,
label:
'${replies![i].member!.uname} ${replies![i].content!.message}',
excludeSemantics: true,
child: Text.rich(
style: TextStyle(
@@ -412,7 +413,7 @@ class ReplyItemRow extends StatelessWidget {
TextSpan(
children: [
TextSpan(
text: replies![i].member.uname + ' ',
text: '${replies![i].member!.uname} ',
style: TextStyle(
color: Theme.of(context)
.colorScheme
@@ -423,16 +424,16 @@ class ReplyItemRow extends StatelessWidget {
..onTap = () {
feedBack();
final String heroTag = Utils.makeHeroTag(
replies![i].member.mid);
replies![i].member!.mid);
Get.toNamed(
'/member?mid=${replies![i].member.mid}',
'/member?mid=${replies![i].member!.mid}',
arguments: {
'face': replies![i].member.avatar,
'face': replies![i].member!.avatar,
'heroTag': heroTag
});
},
),
if (replies![i].isUp)
if (replies![i].isUp!)
const WidgetSpan(
alignment: PlaceholderAlignment.top,
child: PBadge(
@@ -971,11 +972,11 @@ InlineSpan buildContent(
}
class MorePanel extends StatelessWidget {
final dynamic item;
final ReplyItemModel item;
const MorePanel({super.key, required this.item});
Future<dynamic> menuActionHandler(String type) async {
String message = item.content.message ?? item.content;
String message = item.content?.message ?? '';
switch (type) {
case 'copyAll':
await Clipboard.setData(ClipboardData(text: message));
@@ -1000,9 +1001,46 @@ class MorePanel extends StatelessWidget {
// case 'report':
// SmartDialog.showToast('举报');
// break;
// case 'delete':
// SmartDialog.showToast('删除');
// break;
case 'delete':
//弹出确认提示:
bool? isDelete = await showDialog<bool>(
context: Get.context!,
builder: (context) {
return AlertDialog(
title: const Text('删除评论(测试)'),
content:
Text('确定尝试删除这条评论吗?\n\n$message\n\n注:只能删除自己的评论,或自己管理的评论区下的评论'),
actions: <Widget>[
TextButton(
onPressed: () {
Get.back(result: false);
},
child: const Text('取消'),
),
TextButton(
onPressed: () {
Get.back(result: true);
},
child: const Text('确定'),
),
],
);
},
);
if (isDelete == null || !isDelete) {
return;
}
SmartDialog.showLoading(msg: '删除中...');
var result = await VideoHttp.replyDel(
type: item.type!, oid: item.oid!, rpid: item.rpid!);
SmartDialog.dismiss();
if (result['status']) {
SmartDialog.showToast('删除成功,请刷新');
// Get.back();
} else {
SmartDialog.showToast('删除失败, ${result["msg"]}');
}
break;
default:
}
}
@@ -1011,7 +1049,12 @@ class MorePanel extends StatelessWidget {
Widget build(BuildContext context) {
Color errorColor = Theme.of(context).colorScheme.error;
return Container(
padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom),
padding: EdgeInsets.only(
bottom: MediaQueryData.fromView(
WidgetsBinding.instance.platformDispatcher.views.single)
.padding
.bottom +
20),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
@@ -1031,6 +1074,18 @@ class MorePanel extends StatelessWidget {
),
),
),
// 已登录用户才显示删除
if (GStrorage.userInfo.get('userInfoCache') != null)
ListTile(
onTap: () async => await menuActionHandler('delete'),
minLeadingWidth: 0,
leading: Icon(Icons.delete_outlined, color: errorColor, size: 19),
title: Text('删除',
style: Theme.of(context)
.textTheme
.titleSmall!
.copyWith(color: errorColor)),
),
ListTile(
onTap: () async => await menuActionHandler('copyAll'),
minLeadingWidth: 0,
@@ -1055,12 +1110,6 @@ class MorePanel extends StatelessWidget {
// leading: Icon(Icons.report_outlined, color: errorColor),
// title: Text('举报', style: TextStyle(color: errorColor)),
// ),
// ListTile(
// onTap: () async => await menuActionHandler('del'),
// minLeadingWidth: 0,
// leading: Icon(Icons.delete_outline, color: errorColor),
// title: Text('删除', style: TextStyle(color: errorColor)),
// ),
],
),
);