From c899ea95e13b2812569d8a197773dd276e4ffc26 Mon Sep 17 00:00:00 2001 From: My-Responsitories <107370289+My-Responsitories@users.noreply.github.com> Date: Sun, 11 May 2025 16:38:15 +0800 Subject: [PATCH] opt: reply type (#850) --- lib/http/reply.dart | 2 +- lib/pages/common/reply_controller.dart | 34 +++---- .../video/reply/widgets/reply_item_grpc.dart | 19 ++-- lib/pages/video/reply_reply/controller.dart | 6 +- lib/pages/video/reply_reply/view.dart | 96 +++++++++---------- 5 files changed, 77 insertions(+), 80 deletions(-) diff --git a/lib/http/reply.dart b/lib/http/reply.dart index ee49978e..a5d97854 100644 --- a/lib/http/reply.dart +++ b/lib/http/reply.dart @@ -138,7 +138,7 @@ class ReplyHttp { } @Deprecated('Use replyReplyListGrpc instead') - static Future replyReplyList({ + static Future> replyReplyList({ required bool isLogin, required int oid, required int root, diff --git a/lib/pages/common/reply_controller.dart b/lib/pages/common/reply_controller.dart index 4e5cf901..14a5441d 100644 --- a/lib/pages/common/reply_controller.dart +++ b/lib/pages/common/reply_controller.dart @@ -33,7 +33,7 @@ abstract class ReplyController extends CommonListController { late final bool isLogin = Accounts.main.isLogin; - dynamic upMid; + Int64? upMid; Int64? cursorNext; FeedPaginationReply? paginationReply; late Rx mode = Mode.MAIN_LIST_HOT.obs; @@ -256,8 +256,8 @@ abstract class ReplyController extends CommonListController { // ref https://github.com/freedom-introvert/biliSendCommAntifraud Future checkReply({ required BuildContext context, - required dynamic oid, - required dynamic rpid, + required int oid, + required int? rpid, required int replyType, required int replyId, required String message, @@ -346,7 +346,7 @@ abstract class ReplyController extends CommonListController { // not found if (context.mounted.not) return; // cookie check - dynamic res1 = await ReplyHttp.replyReplyList( + final res1 = await ReplyHttp.replyReplyList( isLogin: isLogin, oid: oid, root: rpid ?? replyId, @@ -363,11 +363,11 @@ abstract class ReplyController extends CommonListController { '无法找到你的评论。\n\n你的评论:$message', ); } - } else if (res1 is Success) { + } else { // found if (context.mounted.not) return; // no cookie check - dynamic res2 = await ReplyHttp.replyReplyList( + final res2 = await ReplyHttp.replyReplyList( isLogin: false, oid: oid, root: rpid ?? replyId, @@ -387,7 +387,7 @@ abstract class ReplyController extends CommonListController { : '评论不可见(${res2.errMsg}): $message', ); } - } else if (res2 is Success) { + } else { // found if (context.mounted) { showReplyCheckResult(isManual @@ -404,12 +404,12 @@ https://api.bilibili.com/x/v2/reply/reply?oid=$oid&pn=1&ps=20&root=${rpid ?? rep } } } else { - for (int i = 1; true; i++) { + for (int i = 1;; i++) { if (context.mounted.not) return; - dynamic res3 = await ReplyHttp.replyReplyList( + final res3 = await ReplyHttp.replyReplyList( isLogin: false, oid: oid, - root: rpid ?? replyId, + root: rpid, pageNum: i, type: replyType, filterBanWord: false, @@ -418,8 +418,8 @@ https://api.bilibili.com/x/v2/reply/reply?oid=$oid&pn=1&ps=20&root=${rpid ?? rep ); if (res3 is Error) { break; - } else if (res3 is Success) { - ReplyReplyData data = res3.response; + } else { + final data = res3.data; if (data.replies.isNullOrEmpty) { break; } @@ -439,12 +439,12 @@ https://api.bilibili.com/x/v2/reply/reply?oid=$oid&pn=1&ps=20&root=${rpid ?? rep } } - for (int i = 1; true; i++) { + for (int i = 1;; i++) { if (context.mounted.not) return; - dynamic res4 = await ReplyHttp.replyReplyList( + final res4 = await ReplyHttp.replyReplyList( isLogin: true, oid: oid, - root: rpid ?? replyId, + root: rpid, pageNum: i, type: replyType, filterBanWord: false, @@ -453,8 +453,8 @@ https://api.bilibili.com/x/v2/reply/reply?oid=$oid&pn=1&ps=20&root=${rpid ?? rep ); if (res4 is Error) { break; - } else if (res4 is Success) { - ReplyReplyData data = res4.response; + } else { + final data = res4.data; if (data.replies.isNullOrEmpty) { break; } diff --git a/lib/pages/video/reply/widgets/reply_item_grpc.dart b/lib/pages/video/reply/widgets/reply_item_grpc.dart index 88a85d2c..f0ec2213 100644 --- a/lib/pages/video/reply/widgets/reply_item_grpc.dart +++ b/lib/pages/video/reply/widgets/reply_item_grpc.dart @@ -25,6 +25,7 @@ import 'package:PiliPlus/utils/url_utils.dart'; import 'package:PiliPlus/utils/utils.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:dio/dio.dart'; +import 'package:fixnum/fixnum.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; @@ -54,7 +55,7 @@ class ReplyItemGrpc extends StatelessWidget { final bool needDivider; final VoidCallback? onReply; final ValueChanged? onDelete; - final dynamic upMid; + final Int64? upMid; final VoidCallback? showDialogue; final Function? getTag; final VoidCallback? onViewImage; @@ -667,7 +668,7 @@ class ReplyItemGrpc extends StatelessWidget { content.atNameToMid.containsKey(matchStr.substring(1))) { // 处理@用户 final String userName = matchStr.substring(1); - final int userId = content.atNameToMid[userName]!.toInt(); + final userId = content.atNameToMid[userName]!.toString(); spanChildren.add( TextSpan( text: matchStr, @@ -966,8 +967,8 @@ class ReplyItemGrpc extends StatelessWidget { required onDelete, required bool isSubReply, }) { - int ownerMid = Accounts.main.mid; - Future menuActionHandler(String type) async { + final ownerMid = Int64(Accounts.main.mid); + Future menuActionHandler(String type) async { late String message = item.content.message; switch (type) { case 'report': @@ -1100,7 +1101,7 @@ class ReplyItemGrpc extends StatelessWidget { } final theme = Theme.of(context); - Color errorColor = theme.colorScheme.error; + final errorColor = theme.colorScheme.error; final style = theme.textTheme.titleSmall; return Padding( @@ -1129,21 +1130,21 @@ class ReplyItemGrpc extends StatelessWidget { ), ), ), - if (ownerMid == upMid.toInt() || ownerMid == item.member.mid.toInt()) + if (ownerMid == upMid || ownerMid == item.member.mid) ListTile( onTap: () => menuActionHandler('delete'), minLeadingWidth: 0, leading: Icon(Icons.delete_outlined, color: errorColor, size: 19), title: Text('删除', style: style!.copyWith(color: errorColor)), ), - if (ownerMid != 0) + if (ownerMid != Int64.ZERO) ListTile( onTap: () => menuActionHandler('report'), minLeadingWidth: 0, leading: Icon(Icons.error_outline, color: errorColor, size: 19), title: Text('举报', style: style!.copyWith(color: errorColor)), ), - if (replyLevel == '1' && isSubReply.not && ownerMid == upMid.toInt()) + if (replyLevel == '1' && isSubReply.not && ownerMid == upMid) ListTile( onTap: () => menuActionHandler('top'), minLeadingWidth: 0, @@ -1171,7 +1172,7 @@ class ReplyItemGrpc extends StatelessWidget { leading: const Icon(Icons.save_alt, size: 19), title: Text('保存评论', style: style), ), - if (item.mid.toInt() == ownerMid) + if (item.mid == ownerMid) ListTile( onTap: () => menuActionHandler('checkReply'), minLeadingWidth: 0, diff --git a/lib/pages/video/reply_reply/controller.dart b/lib/pages/video/reply_reply/controller.dart index a0aaca9a..a96cd806 100644 --- a/lib/pages/video/reply_reply/controller.dart +++ b/lib/pages/video/reply_reply/controller.dart @@ -32,7 +32,7 @@ class VideoReplyReplyController extends ReplyController int rpid; ReplyType replyType; // = ReplyType.video; - dynamic firstFloor; + ReplyInfo? firstFloor; int? index; AnimationController? controller; @@ -65,9 +65,9 @@ class VideoReplyReplyController extends ReplyController bool customHandleResponse(bool isRefresh, Success response) { final data = response.response; - upMid ??= data.subjectControl.upMid.toInt(); + upMid ??= data.subjectControl.upMid; paginationReply = data.paginationReply; - isEnd = data.cursor?.isEnd ?? false; + isEnd = data.cursor.isEnd; // reply2Reply // isDialogue.not if (data is DetailListReply) { diff --git a/lib/pages/video/reply_reply/view.dart b/lib/pages/video/reply_reply/view.dart index a0dae947..d3c42f68 100644 --- a/lib/pages/video/reply_reply/view.dart +++ b/lib/pages/video/reply_reply/view.dart @@ -37,7 +37,7 @@ class VideoReplyReplyPanel extends CommonSlidePage { final int oid; final int rpid; final int? dialog; - final dynamic firstFloor; + final ReplyInfo? firstFloor; final String? source; final ReplyType replyType; final bool isDialogue; @@ -53,14 +53,14 @@ class _VideoReplyReplyPanelState extends CommonSlidePageState with TickerProviderStateMixin { late VideoReplyReplyController _videoReplyReplyController; - late final _savedReplies = {}; + late final _savedReplies = {}; late final itemPositionsListener = ItemPositionsListener.create(); late final _key = GlobalKey(); late final _listKey = GlobalKey(); late final _tag = Utils.makeHeroTag('${widget.rpid}${widget.dialog}${widget.isDialogue}'); - dynamic get firstFloor => + ReplyInfo? get firstFloor => widget.firstFloor ?? _videoReplyReplyController.firstFloor; bool get _horizontalPreview => @@ -179,11 +179,11 @@ class _VideoReplyReplyPanelState } else if (firstFloor != null) { if (index == 0) { return ReplyItemGrpc( - replyItem: firstFloor, + replyItem: firstFloor!, replyLevel: '2', needDivider: false, onReply: () { - _onReply(firstFloor, -1); + _onReply(firstFloor!, -1); }, upMid: _videoReplyReplyController.upMid, onViewImage: widget.onViewImage, @@ -287,41 +287,40 @@ class _VideoReplyReplyPanelState ), ); - Function(dynamic imgList, dynamic index)? get _getImageCallback => - _horizontalPreview - ? (imgList, index) { - final ctr = AnimationController( - vsync: this, - duration: const Duration(milliseconds: 200), - )..forward(); - PageUtils.onHorizontalPreview( - _key, - AnimationController( - vsync: this, - duration: Duration.zero, - ), - ctr, - imgList, - index, - (value) async { - if (value == false) { - await ctr.reverse(); - } - try { - ctr.dispose(); - } catch (_) {} - if (value == false) { - Get.back(); - } - }, - ); - } - : null; + Function(List, int)? get _getImageCallback => _horizontalPreview + ? (imgList, index) { + final ctr = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 200), + )..forward(); + PageUtils.onHorizontalPreview( + _key, + AnimationController( + vsync: this, + duration: Duration.zero, + ), + ctr, + imgList, + index, + (value) async { + if (value == false) { + await ctr.reverse(); + } + try { + ctr.dispose(); + } catch (_) {} + if (value == false) { + Get.back(); + } + }, + ); + } + : null; - void _onReply(dynamic item, int index) { - dynamic oid = item?.oid.toInt(); - dynamic root = item?.id.toInt(); - dynamic key = oid + root; + void _onReply(ReplyInfo item, int index) { + final oid = item.oid.toInt(); + final root = item.id.toInt(); + final key = oid + root; Navigator.of(context) .push( @@ -357,7 +356,7 @@ class _VideoReplyReplyPanelState ) .then((res) { if (res != null) { - _savedReplies[key] = null; + _savedReplies.remove(key); ReplyInfo replyInfo = RequestUtils.replyCast(res); _videoReplyReplyController.loadingState.value.dataOrNull ?.insert(index + 1, replyInfo); @@ -385,7 +384,8 @@ class _VideoReplyReplyPanelState }); } - Widget _buildBody(ThemeData theme, LoadingState loadingState, int index) { + Widget _buildBody( + ThemeData theme, LoadingState?> loadingState, int index) { return switch (loadingState) { Loading() => IgnorePointer( child: CustomScrollView( @@ -402,7 +402,7 @@ class _VideoReplyReplyPanelState ), ), Success(:var response) => () { - if (index == response.length) { + if (index == response!.length) { _videoReplyReplyController.onLoadMore(); return Container( alignment: Alignment.center, @@ -445,7 +445,7 @@ class _VideoReplyReplyPanelState }; } - Widget _replyItem(replyItem, index) { + Widget _replyItem(ReplyInfo replyItem, int index) { return ReplyItemGrpc( replyItem: replyItem, replyLevel: widget.isDialogue ? '3' : '2', @@ -484,18 +484,14 @@ class _VideoReplyReplyPanelState ); } - int _itemCount(LoadingState loadingState) { + int _itemCount(LoadingState?> loadingState) { if (widget.isDialogue) { - return (loadingState is Success ? loadingState.response.length : 0) + 1; + return (loadingState.dataOrNull?.length ?? 0) + 1; } int itemCount = 0; if (firstFloor != null) { itemCount = 2; } - if (loadingState is Success) { - return loadingState.response.length + itemCount + 2; - } else { - return itemCount + 2; - } + return (loadingState.dataOrNull?.length ?? 0) + itemCount + 2; } }