mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
feat: comment antifraud (#193)
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -4,13 +4,11 @@ import 'package:PiliPlus/grpc/app/main/community/reply/v1/reply.pb.dart';
|
|||||||
import 'package:PiliPlus/grpc/grpc_repo.dart';
|
import 'package:PiliPlus/grpc/grpc_repo.dart';
|
||||||
import 'package:PiliPlus/http/loading_state.dart';
|
import 'package:PiliPlus/http/loading_state.dart';
|
||||||
import 'package:PiliPlus/utils/extension.dart';
|
import 'package:PiliPlus/utils/extension.dart';
|
||||||
import 'package:PiliPlus/utils/storage.dart';
|
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
|
|
||||||
import '../models/video/reply/data.dart';
|
import '../models/video/reply/data.dart';
|
||||||
import '../models/video/reply/emote.dart';
|
import '../models/video/reply/emote.dart';
|
||||||
import 'api.dart';
|
import 'api.dart';
|
||||||
import 'constants.dart';
|
|
||||||
import 'init.dart';
|
import 'init.dart';
|
||||||
|
|
||||||
class ReplyHttp {
|
class ReplyHttp {
|
||||||
@@ -29,7 +27,7 @@ class ReplyHttp {
|
|||||||
: null;
|
: null;
|
||||||
var res = !isLogin
|
var res = !isLogin
|
||||||
? await Request().get(
|
? await Request().get(
|
||||||
'${HttpString.apiBaseUrl}${Api.replyList}/main',
|
'${Api.replyList}/main',
|
||||||
queryParameters: {
|
queryParameters: {
|
||||||
'oid': oid,
|
'oid': oid,
|
||||||
'type': type,
|
'type': type,
|
||||||
@@ -40,7 +38,7 @@ class ReplyHttp {
|
|||||||
options: options,
|
options: options,
|
||||||
)
|
)
|
||||||
: await Request().get(
|
: await Request().get(
|
||||||
'${HttpString.apiBaseUrl}${Api.replyList}',
|
Api.replyList,
|
||||||
queryParameters: {
|
queryParameters: {
|
||||||
'oid': oid,
|
'oid': oid,
|
||||||
'type': type,
|
'type': type,
|
||||||
@@ -134,26 +132,27 @@ class ReplyHttp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Future<LoadingState> replyReplyList({
|
static Future<LoadingState> replyReplyList({
|
||||||
|
required bool isLogin,
|
||||||
required int oid,
|
required int oid,
|
||||||
required int root,
|
required int root,
|
||||||
required int pageNum,
|
required int pageNum,
|
||||||
required int type,
|
required int type,
|
||||||
int sort = 1,
|
|
||||||
required String banWordForReply,
|
required String banWordForReply,
|
||||||
|
bool? isCheck,
|
||||||
}) async {
|
}) async {
|
||||||
Options? options = GStorage.userInfo.get('userInfoCache') == null
|
Options? options = isLogin.not
|
||||||
? Options(
|
? Options(
|
||||||
headers: {HttpHeaders.cookieHeader: "buvid3= ; b_nut= ; sid= "})
|
headers: {HttpHeaders.cookieHeader: "buvid3= ; b_nut= ; sid= "})
|
||||||
: null;
|
: null;
|
||||||
var res = await Request().get(
|
var res = await Request().get(
|
||||||
'${HttpString.apiBaseUrl}${Api.replyReplyList}',
|
Api.replyReplyList,
|
||||||
queryParameters: {
|
queryParameters: {
|
||||||
'oid': oid,
|
'oid': oid,
|
||||||
'root': root,
|
'root': root,
|
||||||
'pn': pageNum,
|
'pn': pageNum,
|
||||||
'type': type,
|
'type': type,
|
||||||
'sort': 1,
|
'sort': 1,
|
||||||
'csrf': await Request.getCsrf(),
|
if (isLogin) 'csrf': await Request.getCsrf(),
|
||||||
},
|
},
|
||||||
options: options,
|
options: options,
|
||||||
);
|
);
|
||||||
@@ -168,7 +167,11 @@ class ReplyHttp {
|
|||||||
}
|
}
|
||||||
return LoadingState.success(replyData);
|
return LoadingState.success(replyData);
|
||||||
} else {
|
} else {
|
||||||
return LoadingState.error(res.data['message']);
|
return LoadingState.error(
|
||||||
|
isCheck == true
|
||||||
|
? '${res.data['code']}${res.data['message']}'
|
||||||
|
: res.data['message'],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:PiliPlus/grpc/app/main/community/reply/v1/reply.pb.dart';
|
import 'package:PiliPlus/grpc/app/main/community/reply/v1/reply.pb.dart';
|
||||||
import 'package:PiliPlus/http/loading_state.dart';
|
import 'package:PiliPlus/http/loading_state.dart';
|
||||||
|
import 'package:PiliPlus/http/reply.dart';
|
||||||
import 'package:PiliPlus/models/common/reply_type.dart';
|
import 'package:PiliPlus/models/common/reply_type.dart';
|
||||||
import 'package:PiliPlus/models/video/reply/data.dart';
|
import 'package:PiliPlus/models/video/reply/data.dart';
|
||||||
import 'package:PiliPlus/pages/common/common_controller.dart';
|
import 'package:PiliPlus/pages/common/common_controller.dart';
|
||||||
@@ -9,12 +10,14 @@ import 'package:PiliPlus/utils/global_data.dart';
|
|||||||
import 'package:PiliPlus/utils/utils.dart';
|
import 'package:PiliPlus/utils/utils.dart';
|
||||||
import 'package:easy_debounce/easy_throttle.dart';
|
import 'package:easy_debounce/easy_throttle.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:PiliPlus/models/common/reply_sort_type.dart';
|
import 'package:PiliPlus/models/common/reply_sort_type.dart';
|
||||||
import 'package:PiliPlus/models/video/reply/item.dart';
|
import 'package:PiliPlus/models/video/reply/item.dart';
|
||||||
import 'package:PiliPlus/utils/feed_back.dart';
|
import 'package:PiliPlus/utils/feed_back.dart';
|
||||||
import 'package:PiliPlus/utils/storage.dart';
|
import 'package:PiliPlus/utils/storage.dart';
|
||||||
import 'package:get/get_navigation/src/dialog/dialog_route.dart';
|
import 'package:get/get_navigation/src/dialog/dialog_route.dart';
|
||||||
|
import 'package:fixnum/fixnum.dart' as $fixnum;
|
||||||
|
|
||||||
abstract class ReplyController extends CommonController {
|
abstract class ReplyController extends CommonController {
|
||||||
String nextOffset = '';
|
String nextOffset = '';
|
||||||
@@ -27,10 +30,11 @@ abstract class ReplyController extends CommonController {
|
|||||||
late final bool isLogin = GStorage.userInfo.get('userInfoCache') != null;
|
late final bool isLogin = GStorage.userInfo.get('userInfoCache') != null;
|
||||||
|
|
||||||
CursorReply? cursor;
|
CursorReply? cursor;
|
||||||
late Mode mode = Mode.MAIN_LIST_HOT;
|
late Rx<Mode> mode = Mode.MAIN_LIST_HOT.obs;
|
||||||
late bool hasUpTop = false;
|
late bool hasUpTop = false;
|
||||||
|
|
||||||
late final banWordForReply = GStorage.banWordForReply;
|
late final banWordForReply = GStorage.banWordForReply;
|
||||||
|
late final enableCommAntifraud = GStorage.enableCommAntifraud;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
@@ -43,7 +47,7 @@ abstract class ReplyController extends CommonController {
|
|||||||
}
|
}
|
||||||
sortType.value = ReplySortType.values[defaultReplySortIndex];
|
sortType.value = ReplySortType.values[defaultReplySortIndex];
|
||||||
if (sortType.value == ReplySortType.time) {
|
if (sortType.value == ReplySortType.time) {
|
||||||
mode = Mode.MAIN_LIST_TIME;
|
mode.value = Mode.MAIN_LIST_TIME;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +99,7 @@ abstract class ReplyController extends CommonController {
|
|||||||
hasUpTop = true;
|
hasUpTop = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (response.response.topReplies != null) {
|
if ((response.response.topReplies as List?)?.isNotEmpty == true) {
|
||||||
replies.insertAll(0, response.response.topReplies);
|
replies.insertAll(0, response.response.topReplies);
|
||||||
hasUpTop = true;
|
hasUpTop = true;
|
||||||
}
|
}
|
||||||
@@ -117,11 +121,11 @@ abstract class ReplyController extends CommonController {
|
|||||||
switch (sortType.value) {
|
switch (sortType.value) {
|
||||||
case ReplySortType.time:
|
case ReplySortType.time:
|
||||||
sortType.value = ReplySortType.like;
|
sortType.value = ReplySortType.like;
|
||||||
mode = Mode.MAIN_LIST_HOT;
|
mode.value = Mode.MAIN_LIST_HOT;
|
||||||
break;
|
break;
|
||||||
case ReplySortType.like:
|
case ReplySortType.like:
|
||||||
sortType.value = ReplySortType.time;
|
sortType.value = ReplySortType.time;
|
||||||
mode = Mode.MAIN_LIST_TIME;
|
mode.value = Mode.MAIN_LIST_TIME;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
nextOffset = '';
|
nextOffset = '';
|
||||||
@@ -204,21 +208,44 @@ abstract class ReplyController extends CommonController {
|
|||||||
}
|
}
|
||||||
count.value += 1;
|
count.value += 1;
|
||||||
loadingState.value = LoadingState.success(response);
|
loadingState.value = LoadingState.success(response);
|
||||||
|
if (enableCommAntifraud && context.mounted) {
|
||||||
|
checkReply(
|
||||||
|
context,
|
||||||
|
oid ?? replyItem.oid.toInt(),
|
||||||
|
replyItem?.id.toInt(),
|
||||||
|
replyItem?.type.toInt() ??
|
||||||
|
replyType?.index ??
|
||||||
|
ReplyType.video.index,
|
||||||
|
replyInfo.id.toInt(),
|
||||||
|
replyInfo.content.message,
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ReplyData response = loadingState.value is Success
|
ReplyData response = loadingState.value is Success
|
||||||
? (loadingState.value as Success).response
|
? (loadingState.value as Success).response
|
||||||
: ReplyData();
|
: ReplyData();
|
||||||
response.replies ??= <ReplyItemModel>[];
|
response.replies ??= <ReplyItemModel>[];
|
||||||
|
ReplyItemModel replyInfo = ReplyItemModel.fromJson(res, '');
|
||||||
if (oid != null) {
|
if (oid != null) {
|
||||||
response.replies
|
response.replies?.insert(hasUpTop ? 1 : 0, replyInfo);
|
||||||
?.insert(hasUpTop ? 1 : 0, ReplyItemModel.fromJson(res, ''));
|
|
||||||
} else {
|
} else {
|
||||||
response.replies?[index].replies ??= <ReplyItemModel>[];
|
response.replies?[index].replies ??= <ReplyItemModel>[];
|
||||||
response.replies?[index].replies
|
response.replies?[index].replies?.add(replyInfo);
|
||||||
?.add(ReplyItemModel.fromJson(res, ''));
|
|
||||||
}
|
}
|
||||||
count.value += 1;
|
count.value += 1;
|
||||||
loadingState.value = LoadingState.success(response);
|
loadingState.value = LoadingState.success(response);
|
||||||
|
if (enableCommAntifraud && context.mounted) {
|
||||||
|
checkReply(
|
||||||
|
context,
|
||||||
|
oid ?? replyItem.oid,
|
||||||
|
replyItem?.rpid,
|
||||||
|
replyItem?.type.toInt() ??
|
||||||
|
replyType?.index ??
|
||||||
|
ReplyType.video.index,
|
||||||
|
replyInfo.rpid ?? 0,
|
||||||
|
replyInfo.content?.message ?? '',
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -262,4 +289,192 @@ abstract class ReplyController extends CommonController {
|
|||||||
loadingState.value = LoadingState.success(response);
|
loadingState.value = LoadingState.success(response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ref https://github.com/freedom-introvert/biliSendCommAntifraud
|
||||||
|
void checkReply(
|
||||||
|
BuildContext context,
|
||||||
|
dynamic oid,
|
||||||
|
dynamic rpid,
|
||||||
|
int replyType,
|
||||||
|
int replyId,
|
||||||
|
String message,
|
||||||
|
) async {
|
||||||
|
void showReplyCheckResult(BuildContext context, String message) {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => AlertDialog(
|
||||||
|
title: Text('评论检查结果'),
|
||||||
|
content: SelectableText(message),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await Future.delayed(const Duration(seconds: 5));
|
||||||
|
if (context.mounted.not) return;
|
||||||
|
// root reply
|
||||||
|
if (rpid == null) {
|
||||||
|
// no cookie check
|
||||||
|
dynamic res = await ReplyHttp.replyList(
|
||||||
|
isLogin: false,
|
||||||
|
oid: oid,
|
||||||
|
nextOffset: '',
|
||||||
|
type: replyType,
|
||||||
|
sort: ReplySortType.time.index,
|
||||||
|
page: 1,
|
||||||
|
banWordForReply: '',
|
||||||
|
);
|
||||||
|
if (context.mounted.not) return;
|
||||||
|
if (res is Error) {
|
||||||
|
SmartDialog.showToast('获取评论主列表时发生错误:${res.errMsg}');
|
||||||
|
return;
|
||||||
|
} else if (res is Success) {
|
||||||
|
ReplyData replies = res.response;
|
||||||
|
int index =
|
||||||
|
replies.replies?.indexWhere((item) => item.rpid == replyId) ?? -1;
|
||||||
|
if (index != -1) {
|
||||||
|
// found
|
||||||
|
if (context.mounted) {
|
||||||
|
showReplyCheckResult(
|
||||||
|
context,
|
||||||
|
'无账号状态下找到了你的评论,评论正常!\n\n你的评论:$message',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// not found
|
||||||
|
if (context.mounted.not) return;
|
||||||
|
// cookie check
|
||||||
|
dynamic res1 = await ReplyHttp.replyReplyList(
|
||||||
|
isLogin: isLogin,
|
||||||
|
oid: oid,
|
||||||
|
root: rpid,
|
||||||
|
pageNum: 1,
|
||||||
|
type: replyType,
|
||||||
|
banWordForReply: '',
|
||||||
|
);
|
||||||
|
if (context.mounted.not) return;
|
||||||
|
if (res1 is Error) {
|
||||||
|
// not found
|
||||||
|
if (context.mounted) {
|
||||||
|
showReplyCheckResult(
|
||||||
|
context,
|
||||||
|
'无法找到你的评论。\n\n你的评论:$message',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (res1 is Success) {
|
||||||
|
// found
|
||||||
|
if (context.mounted.not) return;
|
||||||
|
// no cookie check
|
||||||
|
dynamic res2 = await ReplyHttp.replyReplyList(
|
||||||
|
isLogin: false,
|
||||||
|
oid: oid,
|
||||||
|
root: rpid,
|
||||||
|
pageNum: 1,
|
||||||
|
type: replyType,
|
||||||
|
banWordForReply: '',
|
||||||
|
isCheck: true,
|
||||||
|
);
|
||||||
|
if (context.mounted.not) return;
|
||||||
|
if (res2 is Error) {
|
||||||
|
// not found
|
||||||
|
if (context.mounted) {
|
||||||
|
showReplyCheckResult(
|
||||||
|
context,
|
||||||
|
res2.errMsg.startsWith('12022')
|
||||||
|
? '你的评论被shadow ban(仅自己可见)!\n\n你的评论: $message'
|
||||||
|
: '评论不可见(${res2.errMsg}): $message',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (res2 is Success) {
|
||||||
|
// found
|
||||||
|
if (context.mounted) {
|
||||||
|
showReplyCheckResult(context, '''
|
||||||
|
你评论状态有点可疑,虽然无账号翻找评论区获取不到你的评论,但是无账号可通过
|
||||||
|
https://api.bilibili.com/x/v2/reply/reply?oid=$oid&pn=1&ps=20&root=$rpid&type=$replyType
|
||||||
|
获取你的评论,疑似评论区被戒严或者这是你的视频。
|
||||||
|
|
||||||
|
你的评论:$message''');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 1; true; i++) {
|
||||||
|
if (context.mounted.not) return;
|
||||||
|
dynamic res3 = await ReplyHttp.replyReplyList(
|
||||||
|
isLogin: false,
|
||||||
|
oid: oid,
|
||||||
|
root: rpid,
|
||||||
|
pageNum: i,
|
||||||
|
type: replyType,
|
||||||
|
banWordForReply: '',
|
||||||
|
isCheck: true,
|
||||||
|
);
|
||||||
|
if (res3 is Error) {
|
||||||
|
break;
|
||||||
|
} else if (res3 is Success) {
|
||||||
|
ReplyReplyData data = res3.response;
|
||||||
|
if (data.replies.isNullOrEmpty) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int index =
|
||||||
|
data.replies?.indexWhere((item) => item.rpid == replyId) ?? -1;
|
||||||
|
if (index == -1) {
|
||||||
|
// not found
|
||||||
|
} else {
|
||||||
|
// found
|
||||||
|
if (context.mounted) {
|
||||||
|
showReplyCheckResult(
|
||||||
|
context,
|
||||||
|
'无账号状态下找到了你的评论,评论正常!\n\n你的评论:$message',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; true; i++) {
|
||||||
|
if (context.mounted.not) return;
|
||||||
|
dynamic res4 = await ReplyHttp.replyReplyList(
|
||||||
|
isLogin: true,
|
||||||
|
oid: oid,
|
||||||
|
root: rpid,
|
||||||
|
pageNum: i,
|
||||||
|
type: replyType,
|
||||||
|
banWordForReply: '',
|
||||||
|
isCheck: true,
|
||||||
|
);
|
||||||
|
if (res4 is Error) {
|
||||||
|
break;
|
||||||
|
} else if (res4 is Success) {
|
||||||
|
ReplyReplyData data = res4.response;
|
||||||
|
if (data.replies.isNullOrEmpty) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int index =
|
||||||
|
data.replies?.indexWhere((item) => item.rpid == replyId) ?? -1;
|
||||||
|
if (index == -1) {
|
||||||
|
// not found
|
||||||
|
} else {
|
||||||
|
// found
|
||||||
|
if (context.mounted) {
|
||||||
|
showReplyCheckResult(
|
||||||
|
context,
|
||||||
|
'你的评论被shadow ban(仅自己可见)!\n\n你的评论: $message',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.mounted) {
|
||||||
|
showReplyCheckResult(
|
||||||
|
context,
|
||||||
|
'评论不可见: $message',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class DynamicDetailController extends ReplyController {
|
|||||||
oid: oid!,
|
oid: oid!,
|
||||||
cursor: CursorReq(
|
cursor: CursorReq(
|
||||||
next: cursor?.next ?? $fixnum.Int64(0),
|
next: cursor?.next ?? $fixnum.Int64(0),
|
||||||
mode: mode,
|
mode: mode.value,
|
||||||
),
|
),
|
||||||
banWordForReply: banWordForReply,
|
banWordForReply: banWordForReply,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ class HtmlRenderController extends ReplyController {
|
|||||||
oid: oid.value,
|
oid: oid.value,
|
||||||
cursor: CursorReq(
|
cursor: CursorReq(
|
||||||
next: cursor?.next ?? $fixnum.Int64(0),
|
next: cursor?.next ?? $fixnum.Int64(0),
|
||||||
mode: mode,
|
mode: mode.value,
|
||||||
),
|
),
|
||||||
banWordForReply: banWordForReply,
|
banWordForReply: banWordForReply,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1937,6 +1937,24 @@ List<SettingsModel> get extraSettings => [
|
|||||||
setKey: SettingBoxKey.showDmChart,
|
setKey: SettingBoxKey.showDmChart,
|
||||||
defaultVal: false,
|
defaultVal: false,
|
||||||
),
|
),
|
||||||
|
SettingsModel(
|
||||||
|
settingsType: SettingsType.sw1tch,
|
||||||
|
title: '发评反诈',
|
||||||
|
subtitle: '发送评论后检查评论是否可见',
|
||||||
|
leading: Stack(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.shield),
|
||||||
|
Icon(
|
||||||
|
Icons.reply,
|
||||||
|
size: 16,
|
||||||
|
color: Theme.of(Get.context!).colorScheme.surface,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
setKey: SettingBoxKey.enableCommAntifraud,
|
||||||
|
defaultVal: false,
|
||||||
|
),
|
||||||
SettingsModel(
|
SettingsModel(
|
||||||
settingsType: SettingsType.sw1tch,
|
settingsType: SettingsType.sw1tch,
|
||||||
enableFeedback: true,
|
enableFeedback: true,
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class VideoReplyController extends ReplyController {
|
|||||||
oid: aid!,
|
oid: aid!,
|
||||||
cursor: CursorReq(
|
cursor: CursorReq(
|
||||||
next: cursor?.next ?? $fixnum.Int64(0),
|
next: cursor?.next ?? $fixnum.Int64(0),
|
||||||
mode: mode,
|
mode: mode.value,
|
||||||
),
|
),
|
||||||
banWordForReply: banWordForReply,
|
banWordForReply: banWordForReply,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import 'package:PiliPlus/grpc/app/main/community/reply/v1/reply.pb.dart';
|
import 'package:PiliPlus/grpc/app/main/community/reply/v1/reply.pb.dart';
|
||||||
import 'package:PiliPlus/http/loading_state.dart';
|
import 'package:PiliPlus/http/loading_state.dart';
|
||||||
import 'package:PiliPlus/models/video/reply/item.dart';
|
import 'package:PiliPlus/models/video/reply/item.dart';
|
||||||
import 'package:PiliPlus/pages/common/common_controller.dart';
|
import 'package:PiliPlus/pages/common/reply_controller.dart';
|
||||||
import 'package:PiliPlus/utils/global_data.dart';
|
import 'package:PiliPlus/utils/global_data.dart';
|
||||||
import 'package:PiliPlus/utils/storage.dart';
|
import 'package:PiliPlus/utils/storage.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -10,7 +10,7 @@ import 'package:PiliPlus/http/reply.dart';
|
|||||||
import 'package:PiliPlus/models/common/reply_type.dart';
|
import 'package:PiliPlus/models/common/reply_type.dart';
|
||||||
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
|
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
|
||||||
|
|
||||||
class VideoReplyReplyController extends CommonController
|
class VideoReplyReplyController extends ReplyController
|
||||||
with GetTickerProviderStateMixin {
|
with GetTickerProviderStateMixin {
|
||||||
VideoReplyReplyController({
|
VideoReplyReplyController({
|
||||||
required this.hasRoot,
|
required this.hasRoot,
|
||||||
@@ -32,9 +32,6 @@ class VideoReplyReplyController extends CommonController
|
|||||||
int? rpid;
|
int? rpid;
|
||||||
ReplyType replyType; // = ReplyType.video;
|
ReplyType replyType; // = ReplyType.video;
|
||||||
|
|
||||||
CursorReply? cursor;
|
|
||||||
Rx<Mode> mode = Mode.MAIN_LIST_TIME.obs;
|
|
||||||
RxInt count = (-1).obs;
|
|
||||||
int? upMid;
|
int? upMid;
|
||||||
|
|
||||||
dynamic firstFloor;
|
dynamic firstFloor;
|
||||||
@@ -45,8 +42,6 @@ class VideoReplyReplyController extends CommonController
|
|||||||
|
|
||||||
late final horizontalPreview = GStorage.horizontalPreview;
|
late final horizontalPreview = GStorage.horizontalPreview;
|
||||||
|
|
||||||
late final banWordForReply = GStorage.banWordForReply;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
super.onInit();
|
super.onInit();
|
||||||
@@ -203,6 +198,7 @@ class VideoReplyReplyController extends CommonController
|
|||||||
banWordForReply: banWordForReply,
|
banWordForReply: banWordForReply,
|
||||||
)
|
)
|
||||||
: ReplyHttp.replyReplyList(
|
: ReplyHttp.replyReplyList(
|
||||||
|
isLogin: isLogin,
|
||||||
oid: oid!,
|
oid: oid!,
|
||||||
root: rpid!,
|
root: rpid!,
|
||||||
pageNum: currentPage,
|
pageNum: currentPage,
|
||||||
@@ -210,6 +206,7 @@ class VideoReplyReplyController extends CommonController
|
|||||||
banWordForReply: banWordForReply,
|
banWordForReply: banWordForReply,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
queryBySort() {
|
queryBySort() {
|
||||||
mode.value = mode.value == Mode.MAIN_LIST_HOT
|
mode.value = mode.value == Mode.MAIN_LIST_HOT
|
||||||
? Mode.MAIN_LIST_TIME
|
? Mode.MAIN_LIST_TIME
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class VideoReplyReplyPanel extends StatefulWidget {
|
|||||||
this.dialog,
|
this.dialog,
|
||||||
this.firstFloor,
|
this.firstFloor,
|
||||||
this.source,
|
this.source,
|
||||||
this.replyType,
|
required this.replyType,
|
||||||
this.isDialogue = false,
|
this.isDialogue = false,
|
||||||
this.isTop = false,
|
this.isTop = false,
|
||||||
this.onViewImage,
|
this.onViewImage,
|
||||||
@@ -39,7 +39,7 @@ class VideoReplyReplyPanel extends StatefulWidget {
|
|||||||
final int? dialog;
|
final int? dialog;
|
||||||
final dynamic firstFloor;
|
final dynamic firstFloor;
|
||||||
final String? source;
|
final String? source;
|
||||||
final ReplyType? replyType;
|
final ReplyType replyType;
|
||||||
final bool isDialogue;
|
final bool isDialogue;
|
||||||
final bool isTop;
|
final bool isTop;
|
||||||
final VoidCallback? onViewImage;
|
final VoidCallback? onViewImage;
|
||||||
@@ -73,7 +73,7 @@ class _VideoReplyReplyPanelState extends State<VideoReplyReplyPanel>
|
|||||||
oid: widget.oid,
|
oid: widget.oid,
|
||||||
rpid: widget.rpid,
|
rpid: widget.rpid,
|
||||||
dialog: widget.dialog,
|
dialog: widget.dialog,
|
||||||
replyType: widget.replyType!,
|
replyType: widget.replyType,
|
||||||
isDialogue: widget.isDialogue,
|
isDialogue: widget.isDialogue,
|
||||||
),
|
),
|
||||||
tag: '${widget.rpid}${widget.dialog}${widget.isDialogue}',
|
tag: '${widget.rpid}${widget.dialog}${widget.isDialogue}',
|
||||||
@@ -352,15 +352,36 @@ class _VideoReplyReplyPanelState extends State<VideoReplyReplyPanel>
|
|||||||
_videoReplyReplyController.count.value += 1;
|
_videoReplyReplyController.count.value += 1;
|
||||||
_videoReplyReplyController.loadingState.value =
|
_videoReplyReplyController.loadingState.value =
|
||||||
LoadingState.success(list);
|
LoadingState.success(list);
|
||||||
|
if (_videoReplyReplyController.enableCommAntifraud && mounted) {
|
||||||
|
_videoReplyReplyController.checkReply(
|
||||||
|
context,
|
||||||
|
oid,
|
||||||
|
root,
|
||||||
|
widget.replyType.index,
|
||||||
|
replyInfo.id.toInt(),
|
||||||
|
replyInfo.content.message,
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
List list = _videoReplyReplyController.loadingState.value is Success
|
List list = _videoReplyReplyController.loadingState.value is Success
|
||||||
? (_videoReplyReplyController.loadingState.value as Success)
|
? (_videoReplyReplyController.loadingState.value as Success)
|
||||||
.response
|
.response
|
||||||
: <ReplyItemModel>[];
|
: <ReplyItemModel>[];
|
||||||
list.insert(index + 1, ReplyItemModel.fromJson(res, ''));
|
ReplyItemModel replyInfo = ReplyItemModel.fromJson(res, '');
|
||||||
|
list.insert(index + 1, replyInfo);
|
||||||
_videoReplyReplyController.count.value += 1;
|
_videoReplyReplyController.count.value += 1;
|
||||||
_videoReplyReplyController.loadingState.value =
|
_videoReplyReplyController.loadingState.value =
|
||||||
LoadingState.success(list);
|
LoadingState.success(list);
|
||||||
|
if (_videoReplyReplyController.enableCommAntifraud && mounted) {
|
||||||
|
_videoReplyReplyController.checkReply(
|
||||||
|
context,
|
||||||
|
oid,
|
||||||
|
root,
|
||||||
|
widget.replyType.index,
|
||||||
|
replyInfo.rpid ?? 0,
|
||||||
|
replyInfo.content?.message ?? '',
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ import '../pages/setting/style_setting.dart';
|
|||||||
import '../pages/subscription/index.dart';
|
import '../pages/subscription/index.dart';
|
||||||
import '../pages/subscription_detail/index.dart';
|
import '../pages/subscription_detail/index.dart';
|
||||||
import '../pages/video/detail/index.dart';
|
import '../pages/video/detail/index.dart';
|
||||||
import '../pages/video/detail/reply_reply/index.dart';
|
|
||||||
import '../pages/whisper/index.dart';
|
import '../pages/whisper/index.dart';
|
||||||
import '../pages/whisper_detail/index.dart';
|
import '../pages/whisper_detail/index.dart';
|
||||||
|
|
||||||
@@ -99,8 +98,8 @@ class Routes {
|
|||||||
CustomGetPage(name: '/member', page: () => const MemberPageNew()),
|
CustomGetPage(name: '/member', page: () => const MemberPageNew()),
|
||||||
CustomGetPage(name: '/memberSearch', page: () => const MemberSearchPage()),
|
CustomGetPage(name: '/memberSearch', page: () => const MemberSearchPage()),
|
||||||
// 二级回复
|
// 二级回复
|
||||||
CustomGetPage(
|
// CustomGetPage(
|
||||||
name: '/replyReply', page: () => const VideoReplyReplyPanel()),
|
// name: '/replyReply', page: () => const VideoReplyReplyPanel()),
|
||||||
// 推荐流设置
|
// 推荐流设置
|
||||||
CustomGetPage(
|
CustomGetPage(
|
||||||
name: '/recommendSetting', page: () => const RecommendSetting()),
|
name: '/recommendSetting', page: () => const RecommendSetting()),
|
||||||
|
|||||||
@@ -361,6 +361,9 @@ class GStorage {
|
|||||||
static bool get showDmChart =>
|
static bool get showDmChart =>
|
||||||
GStorage.setting.get(SettingBoxKey.showDmChart, defaultValue: false);
|
GStorage.setting.get(SettingBoxKey.showDmChart, defaultValue: false);
|
||||||
|
|
||||||
|
static bool get enableCommAntifraud => GStorage.setting
|
||||||
|
.get(SettingBoxKey.enableCommAntifraud, defaultValue: false);
|
||||||
|
|
||||||
static List<double> get dynamicDetailRatio => List<double>.from(setting
|
static List<double> get dynamicDetailRatio => List<double>.from(setting
|
||||||
.get(SettingBoxKey.dynamicDetailRatio, defaultValue: [60.0, 40.0]));
|
.get(SettingBoxKey.dynamicDetailRatio, defaultValue: [60.0, 40.0]));
|
||||||
|
|
||||||
@@ -591,6 +594,7 @@ class SettingBoxKey {
|
|||||||
enableLivePhoto = 'enableLivePhoto',
|
enableLivePhoto = 'enableLivePhoto',
|
||||||
showSeekPreview = 'showSeekPreview',
|
showSeekPreview = 'showSeekPreview',
|
||||||
showDmChart = 'showDmChart',
|
showDmChart = 'showDmChart',
|
||||||
|
enableCommAntifraud = 'enableCommAntifraud',
|
||||||
|
|
||||||
// Sponsor Block
|
// Sponsor Block
|
||||||
enableSponsorBlock = 'enableSponsorBlock',
|
enableSponsorBlock = 'enableSponsorBlock',
|
||||||
|
|||||||
Reference in New Issue
Block a user