mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-05-29 20:48:40 +00:00
feat: 新增长按删评论功能
This commit is contained in:
@@ -120,6 +120,10 @@ class Api {
|
|||||||
// https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/comment/action.md
|
// https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/comment/action.md
|
||||||
static const String replyAdd = '/x/v2/reply/add';
|
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
|
// https://api.bilibili.com/x/relation/stat?vmid=697166795
|
||||||
static const String userStat = '/x/relation/stat';
|
static const String userStat = '/x/relation/stat';
|
||||||
|
|||||||
@@ -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
|
// 查询是否关注up
|
||||||
static Future hasFollow({required int mid}) async {
|
static Future hasFollow({required int mid}) async {
|
||||||
var res = await Request().get(Api.hasFollow, data: {'fid': mid});
|
var res = await Request().get(Api.hasFollow, data: {'fid': mid});
|
||||||
@@ -584,14 +603,11 @@ class VideoHttp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (subtitlesVtt.isNotEmpty) {
|
if (subtitlesVtt.isNotEmpty) {
|
||||||
subtitlesVtt.insert(0, {
|
subtitlesVtt.insert(0, {'language': '', 'title': '关闭字幕', 'text': ""});
|
||||||
'language': '',
|
|
||||||
'title': '关闭字幕',
|
|
||||||
'text': ""
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return subtitlesVtt;
|
return subtitlesVtt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 视频排行
|
// 视频排行
|
||||||
static Future getRankVideoList(int rid) async {
|
static Future getRankVideoList(int rid) async {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -23,18 +23,16 @@ class ReplyData {
|
|||||||
page = ReplyPage.fromJson(json['page']);
|
page = ReplyPage.fromJson(json['page']);
|
||||||
config = ReplyConfig.fromJson(json['config']);
|
config = ReplyConfig.fromJson(json['config']);
|
||||||
replies = json['replies'] != null
|
replies = json['replies'] != null
|
||||||
? json['replies']
|
? List<ReplyItemModel>.from(json['replies']
|
||||||
.map<ReplyItemModel>(
|
.map<ReplyItemModel>(
|
||||||
(item) => ReplyItemModel.fromJson(item, json['upper']['mid']))
|
(item) => ReplyItemModel.fromJson(item, json['upper']['mid'])))
|
||||||
.toList()
|
: <ReplyItemModel>[];
|
||||||
: [];
|
|
||||||
topReplies = json['top_replies'] != null
|
topReplies = json['top_replies'] != null
|
||||||
? json['top_replies']
|
? List<ReplyItemModel>.from(json['top_replies']
|
||||||
.map<ReplyItemModel>((item) => ReplyItemModel.fromJson(
|
.map<ReplyItemModel>((item) => ReplyItemModel.fromJson(
|
||||||
item, json['upper']['mid'],
|
item, json['upper']['mid'],
|
||||||
isTopStatus: true))
|
isTopStatus: true)))
|
||||||
.toList()
|
: <ReplyItemModel>[];
|
||||||
: [];
|
|
||||||
upper = ReplyUpper.fromJson(json['upper']);
|
upper = ReplyUpper.fromJson(json['upper']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ class ReplyItemModel {
|
|||||||
int? action;
|
int? action;
|
||||||
ReplyMember? member;
|
ReplyMember? member;
|
||||||
ReplyContent? content;
|
ReplyContent? content;
|
||||||
List? replies;
|
List<ReplyItemModel>? replies;
|
||||||
int? assist;
|
int? assist;
|
||||||
UpAction? upAction;
|
UpAction? upAction;
|
||||||
bool? invisible;
|
bool? invisible;
|
||||||
@@ -85,10 +85,9 @@ class ReplyItemModel {
|
|||||||
member = ReplyMember.fromJson(json['member']);
|
member = ReplyMember.fromJson(json['member']);
|
||||||
content = ReplyContent.fromJson(json['content']);
|
content = ReplyContent.fromJson(json['content']);
|
||||||
replies = json['replies'] != null
|
replies = json['replies'] != null
|
||||||
? json['replies']
|
? List<ReplyItemModel>.from(json['replies']
|
||||||
.map((item) => ReplyItemModel.fromJson(item, upperMid))
|
.map((item) => ReplyItemModel.fromJson(item, upperMid)))
|
||||||
.toList()
|
: <ReplyItemModel>[];
|
||||||
: [];
|
|
||||||
assist = json['assist'];
|
assist = json['assist'];
|
||||||
upAction = UpAction.fromJson(json['up_action']);
|
upAction = UpAction.fromJson(json['up_action']);
|
||||||
invisible = json['invisible'];
|
invisible = json['invisible'];
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:PiliPalaX/http/video.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
@@ -54,7 +55,7 @@ class ReplyItem extends StatelessWidget {
|
|||||||
useRootNavigator: true,
|
useRootNavigator: true,
|
||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return MorePanel(item: replyItem);
|
return MorePanel(item: replyItem!);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -273,6 +274,7 @@ class ReplyItem extends StatelessWidget {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
feedBack();
|
feedBack();
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
|
isDismissible: false,
|
||||||
context: context,
|
context: context,
|
||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
builder: (builder) {
|
builder: (builder) {
|
||||||
@@ -347,7 +349,7 @@ class ReplyItemRow extends StatelessWidget {
|
|||||||
this.replyItem,
|
this.replyItem,
|
||||||
this.replyReply,
|
this.replyReply,
|
||||||
});
|
});
|
||||||
final List? replies;
|
final List<ReplyItemModel>? replies;
|
||||||
ReplyControl? replyControl;
|
ReplyControl? replyControl;
|
||||||
// int? f_rpid;
|
// int? f_rpid;
|
||||||
ReplyItemModel? replyItem;
|
ReplyItemModel? replyItem;
|
||||||
@@ -392,9 +394,8 @@ class ReplyItemRow extends StatelessWidget {
|
|||||||
i == 0 && (extraRow == 1 || replies!.length > 1) ? 4 : 6,
|
i == 0 && (extraRow == 1 || replies!.length > 1) ? 4 : 6,
|
||||||
),
|
),
|
||||||
child: Semantics(
|
child: Semantics(
|
||||||
label: replies![i].member.uname +
|
label:
|
||||||
' ' +
|
'${replies![i].member!.uname} ${replies![i].content!.message}',
|
||||||
replies![i].content.message,
|
|
||||||
excludeSemantics: true,
|
excludeSemantics: true,
|
||||||
child: Text.rich(
|
child: Text.rich(
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
@@ -412,7 +413,7 @@ class ReplyItemRow extends StatelessWidget {
|
|||||||
TextSpan(
|
TextSpan(
|
||||||
children: [
|
children: [
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: replies![i].member.uname + ' ',
|
text: '${replies![i].member!.uname} ',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Theme.of(context)
|
color: Theme.of(context)
|
||||||
.colorScheme
|
.colorScheme
|
||||||
@@ -423,16 +424,16 @@ class ReplyItemRow extends StatelessWidget {
|
|||||||
..onTap = () {
|
..onTap = () {
|
||||||
feedBack();
|
feedBack();
|
||||||
final String heroTag = Utils.makeHeroTag(
|
final String heroTag = Utils.makeHeroTag(
|
||||||
replies![i].member.mid);
|
replies![i].member!.mid);
|
||||||
Get.toNamed(
|
Get.toNamed(
|
||||||
'/member?mid=${replies![i].member.mid}',
|
'/member?mid=${replies![i].member!.mid}',
|
||||||
arguments: {
|
arguments: {
|
||||||
'face': replies![i].member.avatar,
|
'face': replies![i].member!.avatar,
|
||||||
'heroTag': heroTag
|
'heroTag': heroTag
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
if (replies![i].isUp)
|
if (replies![i].isUp!)
|
||||||
const WidgetSpan(
|
const WidgetSpan(
|
||||||
alignment: PlaceholderAlignment.top,
|
alignment: PlaceholderAlignment.top,
|
||||||
child: PBadge(
|
child: PBadge(
|
||||||
@@ -971,11 +972,11 @@ InlineSpan buildContent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
class MorePanel extends StatelessWidget {
|
class MorePanel extends StatelessWidget {
|
||||||
final dynamic item;
|
final ReplyItemModel item;
|
||||||
const MorePanel({super.key, required this.item});
|
const MorePanel({super.key, required this.item});
|
||||||
|
|
||||||
Future<dynamic> menuActionHandler(String type) async {
|
Future<dynamic> menuActionHandler(String type) async {
|
||||||
String message = item.content.message ?? item.content;
|
String message = item.content?.message ?? '';
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'copyAll':
|
case 'copyAll':
|
||||||
await Clipboard.setData(ClipboardData(text: message));
|
await Clipboard.setData(ClipboardData(text: message));
|
||||||
@@ -1000,9 +1001,46 @@ class MorePanel extends StatelessWidget {
|
|||||||
// case 'report':
|
// case 'report':
|
||||||
// SmartDialog.showToast('举报');
|
// SmartDialog.showToast('举报');
|
||||||
// break;
|
// break;
|
||||||
// case 'delete':
|
case 'delete':
|
||||||
// SmartDialog.showToast('删除');
|
//弹出确认提示:
|
||||||
// break;
|
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:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1011,7 +1049,12 @@ class MorePanel extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Color errorColor = Theme.of(context).colorScheme.error;
|
Color errorColor = Theme.of(context).colorScheme.error;
|
||||||
return Container(
|
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(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
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(
|
ListTile(
|
||||||
onTap: () async => await menuActionHandler('copyAll'),
|
onTap: () async => await menuActionHandler('copyAll'),
|
||||||
minLeadingWidth: 0,
|
minLeadingWidth: 0,
|
||||||
@@ -1055,12 +1110,6 @@ class MorePanel extends StatelessWidget {
|
|||||||
// leading: Icon(Icons.report_outlined, color: errorColor),
|
// leading: Icon(Icons.report_outlined, color: errorColor),
|
||||||
// title: Text('举报', style: TextStyle(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)),
|
|
||||||
// ),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user