mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-05-31 16:18:22 +08:00
@@ -1,6 +1,8 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:PiliPlus/common/constants.dart';
|
import 'package:PiliPlus/common/constants.dart';
|
||||||
|
import 'package:PiliPlus/grpc/bilibili/main/community/reply/v1.pb.dart'
|
||||||
|
show ReplyInfo;
|
||||||
import 'package:PiliPlus/http/api.dart';
|
import 'package:PiliPlus/http/api.dart';
|
||||||
import 'package:PiliPlus/http/browser_ua.dart';
|
import 'package:PiliPlus/http/browser_ua.dart';
|
||||||
import 'package:PiliPlus/http/init.dart';
|
import 'package:PiliPlus/http/init.dart';
|
||||||
@@ -32,7 +34,10 @@ import 'package:PiliPlus/utils/extension/string_ext.dart';
|
|||||||
import 'package:PiliPlus/utils/global_data.dart';
|
import 'package:PiliPlus/utils/global_data.dart';
|
||||||
import 'package:PiliPlus/utils/id_utils.dart';
|
import 'package:PiliPlus/utils/id_utils.dart';
|
||||||
import 'package:PiliPlus/utils/recommend_filter.dart';
|
import 'package:PiliPlus/utils/recommend_filter.dart';
|
||||||
|
import 'package:PiliPlus/utils/request_utils.dart';
|
||||||
|
import 'package:PiliPlus/utils/storage.dart';
|
||||||
import 'package:PiliPlus/utils/storage_pref.dart';
|
import 'package:PiliPlus/utils/storage_pref.dart';
|
||||||
|
import 'package:PiliPlus/utils/utils.dart';
|
||||||
import 'package:PiliPlus/utils/wbi_sign.dart';
|
import 'package:PiliPlus/utils/wbi_sign.dart';
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:flutter/foundation.dart' show compute;
|
import 'package:flutter/foundation.dart' show compute;
|
||||||
@@ -524,7 +529,7 @@ abstract final class VideoHttp {
|
|||||||
// parent num 父评论rpid 非必要 二级评论同根评论id 大于二级评论为要回复的评论id
|
// parent num 父评论rpid 非必要 二级评论同根评论id 大于二级评论为要回复的评论id
|
||||||
// message str 发送评论内容 必要 最大1000字符
|
// message str 发送评论内容 必要 最大1000字符
|
||||||
// plat num 发送平台标识 非必要 1:web端 2:安卓客户端 3:ios客户端 4:wp客户端
|
// plat num 发送平台标识 非必要 1:web端 2:安卓客户端 3:ios客户端 4:wp客户端
|
||||||
static Future<LoadingState<Map>> replyAdd({
|
static Future<LoadingState<ReplyInfo?>> replyAdd({
|
||||||
required int type,
|
required int type,
|
||||||
required int oid,
|
required int oid,
|
||||||
required String message,
|
required String message,
|
||||||
@@ -552,7 +557,19 @@ abstract final class VideoHttp {
|
|||||||
options: Options(contentType: Headers.formUrlEncodedContentType),
|
options: Options(contentType: Headers.formUrlEncodedContentType),
|
||||||
);
|
);
|
||||||
if (res.data['code'] == 0) {
|
if (res.data['code'] == 0) {
|
||||||
return Success(res.data['data']);
|
try {
|
||||||
|
final replyInfo = RequestUtils.replyCast(res.data['data']['reply']);
|
||||||
|
GStorage.reply.put(
|
||||||
|
replyInfo.id.toString(),
|
||||||
|
(replyInfo.toProto3Json() as Map)
|
||||||
|
..remove('memberV2')
|
||||||
|
..remove('trackInfo'),
|
||||||
|
);
|
||||||
|
return Success(replyInfo);
|
||||||
|
} catch (e, s) {
|
||||||
|
Utils.reportError(e, s);
|
||||||
|
return const Success(null);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return Error(res.data['message']);
|
return Error(res.data['message']);
|
||||||
}
|
}
|
||||||
@@ -574,6 +591,7 @@ abstract final class VideoHttp {
|
|||||||
options: Options(contentType: Headers.formUrlEncodedContentType),
|
options: Options(contentType: Headers.formUrlEncodedContentType),
|
||||||
);
|
);
|
||||||
if (res.data['code'] == 0) {
|
if (res.data['code'] == 0) {
|
||||||
|
GStorage.reply.delete(rpid.toString());
|
||||||
return const Success(null);
|
return const Success(null);
|
||||||
} else {
|
} else {
|
||||||
return const Error('请退出账号后重新登录');
|
return const Error('请退出账号后重新登录');
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import 'package:PiliPlus/pages/common/publish/publish_route.dart';
|
|||||||
import 'package:PiliPlus/pages/video/reply_new/view.dart';
|
import 'package:PiliPlus/pages/video/reply_new/view.dart';
|
||||||
import 'package:PiliPlus/utils/feed_back.dart';
|
import 'package:PiliPlus/utils/feed_back.dart';
|
||||||
import 'package:PiliPlus/utils/reply_utils.dart';
|
import 'package:PiliPlus/utils/reply_utils.dart';
|
||||||
import 'package:PiliPlus/utils/request_utils.dart';
|
|
||||||
import 'package:PiliPlus/utils/storage_pref.dart';
|
import 'package:PiliPlus/utils/storage_pref.dart';
|
||||||
import 'package:fixnum/fixnum.dart';
|
import 'package:fixnum/fixnum.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -174,10 +173,9 @@ abstract class ReplyController<R> extends CommonListController<R, ReplyInfo> {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
.then(
|
.then(
|
||||||
(res) {
|
(replyInfo) {
|
||||||
if (res != null) {
|
if (replyInfo is ReplyInfo) {
|
||||||
savedReplies.remove(key);
|
savedReplies.remove(key);
|
||||||
ReplyInfo replyInfo = RequestUtils.replyCast(res);
|
|
||||||
if (loadingState.value case Success(:final response)) {
|
if (loadingState.value case Success(:final response)) {
|
||||||
if (response == null) {
|
if (response == null) {
|
||||||
loadingState.value = Success([replyInfo]);
|
loadingState.value = Success([replyInfo]);
|
||||||
|
|||||||
@@ -160,6 +160,14 @@ class _MediaPageState extends CommonPageState<MinePage>
|
|||||||
),
|
),
|
||||||
msgBadge(_mainController),
|
msgBadge(_mainController),
|
||||||
],
|
],
|
||||||
|
IconButton(
|
||||||
|
iconSize: iconSize,
|
||||||
|
padding: padding,
|
||||||
|
style: style,
|
||||||
|
tooltip: '评论记录',
|
||||||
|
onPressed: () => Get.toNamed('/myReply'),
|
||||||
|
icon: const Icon(Icons.message_outlined),
|
||||||
|
),
|
||||||
Obx(
|
Obx(
|
||||||
() {
|
() {
|
||||||
final anonymity = MineController.anonymity.value;
|
final anonymity = MineController.anonymity.value;
|
||||||
|
|||||||
122
lib/pages/my_reply/view.dart
Normal file
122
lib/pages/my_reply/view.dart
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
import 'package:PiliPlus/common/widgets/dialog/dialog.dart';
|
||||||
|
import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart';
|
||||||
|
import 'package:PiliPlus/common/widgets/view_sliver_safe_area.dart';
|
||||||
|
import 'package:PiliPlus/grpc/bilibili/main/community/reply/v1.pb.dart';
|
||||||
|
import 'package:PiliPlus/pages/video/reply/widgets/reply_item_grpc.dart';
|
||||||
|
import 'package:PiliPlus/utils/app_scheme.dart';
|
||||||
|
import 'package:PiliPlus/utils/page_utils.dart';
|
||||||
|
import 'package:PiliPlus/utils/reply_utils.dart';
|
||||||
|
import 'package:PiliPlus/utils/storage.dart';
|
||||||
|
import 'package:PiliPlus/utils/storage_pref.dart';
|
||||||
|
import 'package:PiliPlus/utils/waterfall.dart';
|
||||||
|
import 'package:flutter/foundation.dart' show kDebugMode;
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:waterfall_flow/waterfall_flow.dart';
|
||||||
|
|
||||||
|
class MyReply extends StatefulWidget {
|
||||||
|
const MyReply({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<MyReply> createState() => _MyReplyState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MyReplyState extends State<MyReply> with DynMixin {
|
||||||
|
late final List<ReplyInfo> _replies;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_replies =
|
||||||
|
GStorage.reply.values
|
||||||
|
.map((e) => ReplyInfo.create()..mergeFromProto3Json(e))
|
||||||
|
.toList()
|
||||||
|
..sort((a, b) => b.ctime.compareTo(a.ctime));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text('我的评论'),
|
||||||
|
actions: kDebugMode
|
||||||
|
? [
|
||||||
|
IconButton(
|
||||||
|
tooltip: 'Clear',
|
||||||
|
onPressed: () => showConfirmDialog(
|
||||||
|
context: context,
|
||||||
|
title: 'Clear Local Storage?',
|
||||||
|
onConfirm: () {
|
||||||
|
GStorage.reply.clear();
|
||||||
|
_replies.clear();
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
icon: const Icon(Icons.clear_all),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 6),
|
||||||
|
]
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
body: CustomScrollView(
|
||||||
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
|
slivers: [
|
||||||
|
_replies.isNotEmpty
|
||||||
|
? ViewSliverSafeArea(
|
||||||
|
sliver: SliverWaterfallFlow(
|
||||||
|
gridDelegate: dynGridDelegate,
|
||||||
|
delegate: SliverChildBuilderDelegate(
|
||||||
|
childCount: _replies.length,
|
||||||
|
(context, index) => ReplyItemGrpc(
|
||||||
|
replyLevel: 0,
|
||||||
|
needDivider: false,
|
||||||
|
replyItem: _replies[index],
|
||||||
|
replyReply: _replyReply,
|
||||||
|
onDelete: (_, _) => _onDelete(index),
|
||||||
|
onCheckReply: _onCheckReply,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: const HttpError(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _replyReply(ReplyInfo replyInfo, int? rpid) {
|
||||||
|
switch (replyInfo.type.toInt()) {
|
||||||
|
case 1:
|
||||||
|
PiliScheme.videoPush(
|
||||||
|
replyInfo.oid.toInt(),
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
case 12:
|
||||||
|
PageUtils.toDupNamed(
|
||||||
|
'/articlePage',
|
||||||
|
parameters: {
|
||||||
|
'id': replyInfo.oid.toString(),
|
||||||
|
'type': 'read',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
case _:
|
||||||
|
PageUtils.pushDynFromId(
|
||||||
|
rid: replyInfo.oid.toString(),
|
||||||
|
type: replyInfo.type,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onDelete(int index) {
|
||||||
|
_replies.removeAt(index);
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onCheckReply(ReplyInfo replyInfo) {
|
||||||
|
ReplyUtils.onCheckReply(
|
||||||
|
replyInfo: replyInfo,
|
||||||
|
biliSendCommAntifraud: Pref.biliSendCommAntifraud,
|
||||||
|
sourceId: null,
|
||||||
|
isManual: true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -29,6 +29,7 @@ import 'package:PiliPlus/utils/feed_back.dart';
|
|||||||
import 'package:PiliPlus/utils/image_utils.dart';
|
import 'package:PiliPlus/utils/image_utils.dart';
|
||||||
import 'package:PiliPlus/utils/page_utils.dart';
|
import 'package:PiliPlus/utils/page_utils.dart';
|
||||||
import 'package:PiliPlus/utils/platform_utils.dart';
|
import 'package:PiliPlus/utils/platform_utils.dart';
|
||||||
|
import 'package:PiliPlus/utils/storage.dart';
|
||||||
import 'package:PiliPlus/utils/storage_pref.dart';
|
import 'package:PiliPlus/utils/storage_pref.dart';
|
||||||
import 'package:PiliPlus/utils/url_utils.dart';
|
import 'package:PiliPlus/utils/url_utils.dart';
|
||||||
import 'package:PiliPlus/utils/utils.dart';
|
import 'package:PiliPlus/utils/utils.dart';
|
||||||
@@ -865,6 +866,35 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (kDebugMode) ...[
|
||||||
|
ListTile(
|
||||||
|
onTap: () {
|
||||||
|
Get.back();
|
||||||
|
GStorage.reply.put(
|
||||||
|
item.id.toString(),
|
||||||
|
(item.toProto3Json() as Map)
|
||||||
|
..remove('replies')
|
||||||
|
..remove('memberV2')
|
||||||
|
..remove('trackInfo'),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
title: Text(
|
||||||
|
'save to local',
|
||||||
|
style: style!.copyWith(color: theme.colorScheme.primary),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
onTap: () {
|
||||||
|
Get.back();
|
||||||
|
onDelete();
|
||||||
|
GStorage.reply.delete(item.id.toString());
|
||||||
|
},
|
||||||
|
title: Text(
|
||||||
|
'remove from local',
|
||||||
|
style: style.copyWith(color: theme.colorScheme.primary),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
if (ownerMid == upMid || ownerMid == item.member.mid)
|
if (ownerMid == upMid || ownerMid == item.member.mid)
|
||||||
ListTile(
|
ListTile(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
|
|||||||
@@ -429,8 +429,8 @@ class _ReplyPageState extends CommonRichTextPubPageState<ReplyPage> {
|
|||||||
);
|
);
|
||||||
if (res case Success(:final response)) {
|
if (res case Success(:final response)) {
|
||||||
hasPub = true;
|
hasPub = true;
|
||||||
SmartDialog.showToast(response['success_toast']);
|
SmartDialog.showToast('发送成功');
|
||||||
Get.back(result: response['reply']);
|
Get.back(result: response);
|
||||||
} else {
|
} else {
|
||||||
res.toast();
|
res.toast();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import 'package:PiliPlus/pages/common/publish/publish_route.dart';
|
|||||||
import 'package:PiliPlus/pages/common/reply_controller.dart';
|
import 'package:PiliPlus/pages/common/reply_controller.dart';
|
||||||
import 'package:PiliPlus/pages/video/reply_new/view.dart';
|
import 'package:PiliPlus/pages/video/reply_new/view.dart';
|
||||||
import 'package:PiliPlus/utils/id_utils.dart';
|
import 'package:PiliPlus/utils/id_utils.dart';
|
||||||
import 'package:PiliPlus/utils/request_utils.dart';
|
|
||||||
import 'package:PiliPlus/utils/storage_pref.dart';
|
import 'package:PiliPlus/utils/storage_pref.dart';
|
||||||
import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart';
|
import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart';
|
||||||
import 'package:fixnum/fixnum.dart';
|
import 'package:fixnum/fixnum.dart';
|
||||||
@@ -195,10 +194,9 @@ class VideoReplyReplyController extends ReplyController
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.then((res) {
|
.then((replyInfo) {
|
||||||
if (res != null) {
|
if (replyInfo is ReplyInfo) {
|
||||||
savedReplies.remove(key);
|
savedReplies.remove(key);
|
||||||
ReplyInfo replyInfo = RequestUtils.replyCast(res);
|
|
||||||
|
|
||||||
count.value += 1;
|
count.value += 1;
|
||||||
loadingState
|
loadingState
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ import 'package:PiliPlus/pages/msg_feed_top/like_me/view.dart';
|
|||||||
import 'package:PiliPlus/pages/msg_feed_top/reply_me/view.dart';
|
import 'package:PiliPlus/pages/msg_feed_top/reply_me/view.dart';
|
||||||
import 'package:PiliPlus/pages/msg_feed_top/sys_msg/view.dart';
|
import 'package:PiliPlus/pages/msg_feed_top/sys_msg/view.dart';
|
||||||
import 'package:PiliPlus/pages/music/view.dart';
|
import 'package:PiliPlus/pages/music/view.dart';
|
||||||
|
import 'package:PiliPlus/pages/my_reply/view.dart';
|
||||||
import 'package:PiliPlus/pages/popular_precious/view.dart';
|
import 'package:PiliPlus/pages/popular_precious/view.dart';
|
||||||
import 'package:PiliPlus/pages/popular_series/view.dart';
|
import 'package:PiliPlus/pages/popular_series/view.dart';
|
||||||
import 'package:PiliPlus/pages/search/view.dart';
|
import 'package:PiliPlus/pages/search/view.dart';
|
||||||
@@ -190,5 +191,6 @@ class Routes {
|
|||||||
GetPage(name: '/sameFollowing', page: () => const FollowSamePage()),
|
GetPage(name: '/sameFollowing', page: () => const FollowSamePage()),
|
||||||
GetPage(name: '/download', page: () => const DownloadPage()),
|
GetPage(name: '/download', page: () => const DownloadPage()),
|
||||||
GetPage(name: '/dlna', page: () => const DLNAPage()),
|
GetPage(name: '/dlna', page: () => const DLNAPage()),
|
||||||
|
GetPage(name: '/myReply', page: () => const MyReply()),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ abstract final class PageUtils {
|
|||||||
String? id,
|
String? id,
|
||||||
Object? rid,
|
Object? rid,
|
||||||
bool off = false,
|
bool off = false,
|
||||||
|
Object? type,
|
||||||
}) async {
|
}) async {
|
||||||
assert(id != null || rid != null);
|
assert(id != null || rid != null);
|
||||||
SmartDialog.showLoading();
|
SmartDialog.showLoading();
|
||||||
@@ -139,7 +140,7 @@ abstract final class PageUtils {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
res.toast();
|
SmartDialog.showToast('${type != null ? 'type: $type ' : ''}$res');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ abstract final class GStorage {
|
|||||||
static late final Box<dynamic> setting;
|
static late final Box<dynamic> setting;
|
||||||
static late final Box<dynamic> video;
|
static late final Box<dynamic> video;
|
||||||
static late final Box<int> watchProgress;
|
static late final Box<int> watchProgress;
|
||||||
|
static late final Box<Map> reply;
|
||||||
|
|
||||||
static Future<void> init() async {
|
static Future<void> init() async {
|
||||||
await Hive.initFlutter(path.join(appSupportDirPath, 'hive'));
|
await Hive.initFlutter(path.join(appSupportDirPath, 'hive'));
|
||||||
@@ -58,6 +59,12 @@ abstract final class GStorage {
|
|||||||
return deletedEntries > 4;
|
return deletedEntries > 4;
|
||||||
},
|
},
|
||||||
).then((res) => watchProgress = res),
|
).then((res) => watchProgress = res),
|
||||||
|
Hive.openBox<Map>(
|
||||||
|
'reply',
|
||||||
|
compactionStrategy: (entries, deletedEntries) {
|
||||||
|
return deletedEntries > 10;
|
||||||
|
},
|
||||||
|
).then((res) => reply = res),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,6 +107,7 @@ abstract final class GStorage {
|
|||||||
video.compact(),
|
video.compact(),
|
||||||
Accounts.account.compact(),
|
Accounts.account.compact(),
|
||||||
watchProgress.compact(),
|
watchProgress.compact(),
|
||||||
|
reply.compact(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,6 +120,7 @@ abstract final class GStorage {
|
|||||||
video.close(),
|
video.close(),
|
||||||
Accounts.account.close(),
|
Accounts.account.close(),
|
||||||
watchProgress.close(),
|
watchProgress.close(),
|
||||||
|
reply.close(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user