diff --git a/lib/http/reply.dart b/lib/http/reply.dart index 398176c0..7e37442d 100644 --- a/lib/http/reply.dart +++ b/lib/http/reply.dart @@ -70,7 +70,7 @@ class ReplyHttp { static Future replyReplyList({ required int oid, - required String root, + required int root, required int pageNum, required int type, int sort = 1, diff --git a/lib/pages/blacklist/index.dart b/lib/pages/blacklist/index.dart index a46d94be..b306a051 100644 --- a/lib/pages/blacklist/index.dart +++ b/lib/pages/blacklist/index.dart @@ -111,11 +111,16 @@ class BlackListController extends CommonController { @override bool customHandleResponse(Success response) { total.value = response.response.total; - isEnd = response.response.list.isEmpty; + if (response.response.list.isEmpty) { + isEnd = true; + } if (currentPage != 1 && loadingState.value is Success) { response.response.list ?.insertAll(0, (loadingState.value as Success).response); } + if (response.response.list.length >= total.value) { + isEnd = true; + } loadingState.value = LoadingState.success(response.response.list); return true; } diff --git a/lib/pages/common/reply_controller.dart b/lib/pages/common/reply_controller.dart index 68c9082f..01c9d59e 100644 --- a/lib/pages/common/reply_controller.dart +++ b/lib/pages/common/reply_controller.dart @@ -1,8 +1,11 @@ import 'package:PiliPalaX/grpc/app/main/community/reply/v1/reply.pb.dart'; import 'package:PiliPalaX/http/loading_state.dart'; import 'package:PiliPalaX/models/common/reply_type.dart'; +import 'package:PiliPalaX/models/video/reply/data.dart'; import 'package:PiliPalaX/pages/common/common_controller.dart'; import 'package:PiliPalaX/pages/video/detail/reply_new/reply_page.dart'; +import 'package:PiliPalaX/utils/extension.dart'; +import 'package:PiliPalaX/utils/global_data.dart'; import 'package:PiliPalaX/utils/utils.dart'; import 'package:easy_debounce/easy_throttle.dart'; import 'package:flutter/material.dart'; @@ -14,11 +17,9 @@ import 'package:PiliPalaX/utils/storage.dart'; import 'package:get/get_navigation/src/dialog/dialog_route.dart'; abstract class ReplyController extends CommonController { - String nextOffset = ""; + String nextOffset = ''; bool isLoadingMore = false; RxInt count = (-1).obs; - // 当前回复的回复 - ReplyItemModel? currentReplyItem; ReplySortType sortType = ReplySortType.time; RxString sortTypeTitle = ReplySortType.time.titles.obs; @@ -26,10 +27,10 @@ abstract class ReplyController extends CommonController { late final savedReplies = {}; - bool isLogin = GStorage.userInfo.get('userInfoCache') != null; + late bool isLogin = GStorage.userInfo.get('userInfoCache') != null; CursorReply? cursor; - Mode mode = Mode.MAIN_LIST_HOT; + late Mode mode = Mode.MAIN_LIST_HOT; bool hasUpTop = false; @override @@ -55,23 +56,53 @@ abstract class ReplyController extends CommonController { @override bool customHandleResponse(Success response) { - MainListReply replies = response.response; - if (cursor == null) { - count.value = replies.subjectControl.count.toInt(); - hasUpTop = replies.hasUpTop(); - if (replies.hasUpTop()) { - replies.replies.insert(0, replies.upTop); + if (GlobalData().grpcReply) { + MainListReply replies = response.response; + if (cursor == null) { + count.value = replies.subjectControl.count.toInt(); + hasUpTop = replies.hasUpTop(); + if (replies.hasUpTop()) { + replies.replies.insert(0, replies.upTop); + } } + cursor = replies.cursor; + if (currentPage != 1 && loadingState.value is Success) { + replies.replies + .insertAll(0, (loadingState.value as Success).response.replies); + } + isEnd = replies.replies.isEmpty || + replies.cursor.isEnd || + replies.replies.length >= count.value; + loadingState.value = LoadingState.success(replies); + } else { + List replies = response.response.replies; + if (isLogin.not) { + nextOffset = response.response.cursor.paginationReply.nextOffset ?? ''; + } + count.value = isLogin.not + ? response.response.cursor.allCount + : response.response.page.count ?? 0; + if (replies.isEmpty) { + isEnd = true; + } + if (currentPage == 1) { + if (response.response.upper.top != null) { + final bool flag = response.response.topReplies.any( + (ReplyItemModel reply) => + reply.rpid == response.response.upper.top.rpid) as bool; + if (!flag) { + replies.insert(0, response.response.upper.top); + } + } + replies.insertAll(0, response.response.topReplies); + } else if (loadingState.value is Success) { + replies.insertAll(0, (loadingState.value as Success).response.replies); + } + if (replies.length >= count.value) { + isEnd = true; + } + loadingState.value = LoadingState.success(response.response); } - cursor = replies.cursor; - if (currentPage != 1 && loadingState.value is Success) { - replies.replies - .insertAll(0, (loadingState.value as Success).response.replies); - } - isEnd = replies.replies.isEmpty || - replies.cursor.isEnd || - replies.replies.length >= count.value; - loadingState.value = LoadingState.success(replies); return true; } @@ -92,7 +123,7 @@ abstract class ReplyController extends CommonController { } sortTypeTitle.value = sortType.titles; sortTypeLabel.value = sortType.labels; - nextOffset = ""; + nextOffset = ''; loadingState.value = LoadingState.loading(); onRefresh(); }); @@ -105,24 +136,40 @@ abstract class ReplyController extends CommonController { int index = 0, ReplyType? replyType, }) { - dynamic key = oid ?? replyItem.oid + replyItem.id; + dynamic key = oid ?? + replyItem.oid + + (GlobalData().grpcReply ? replyItem.id : replyItem.rpid); Navigator.of(context) .push( GetDialogRoute( pageBuilder: (buildContext, animation, secondaryAnimation) { - return ReplyPage( - oid: oid ?? replyItem.oid.toInt(), - root: oid != null ? 0 : replyItem.id.toInt(), - parent: oid != null ? 0 : replyItem.id.toInt(), - replyType: replyItem != null - ? ReplyType.values[replyItem.type.toInt()] - : replyType, - replyItem: replyItem, - savedReply: savedReplies[key], - onSaveReply: (reply) { - savedReplies[key] = reply; - }, - ); + return GlobalData().grpcReply + ? ReplyPage( + oid: oid ?? replyItem.oid.toInt(), + root: oid != null ? 0 : replyItem.id.toInt(), + parent: oid != null ? 0 : replyItem.id.toInt(), + replyType: replyItem != null + ? ReplyType.values[replyItem.type.toInt()] + : replyType, + replyItem: replyItem, + savedReply: savedReplies[key], + onSaveReply: (reply) { + savedReplies[key] = reply; + }, + ) + : ReplyPage( + oid: oid ?? replyItem.oid, + root: oid != null ? 0 : replyItem.rpid, + parent: oid != null ? 0 : replyItem.rpid, + replyType: replyItem != null + ? ReplyType.values[replyItem.type.toInt()] + : replyType, + replyItem: replyItem, + savedReply: savedReplies[key], + onSaveReply: (reply) { + savedReplies[key] = reply; + }, + ); }, transitionDuration: const Duration(milliseconds: 500), transitionBuilder: (context, animation, secondaryAnimation, child) { @@ -144,37 +191,72 @@ abstract class ReplyController extends CommonController { (res) { if (res != null) { savedReplies[key] = null; - ReplyInfo replyInfo = Utils.replyCast(res); - MainListReply response = - (loadingState.value as Success?)?.response ?? MainListReply(); - if (oid != null) { - response.replies.insert(hasUpTop ? 1 : 0, replyInfo); + if (GlobalData().grpcReply) { + ReplyInfo replyInfo = Utils.replyCast(res); + MainListReply response = + (loadingState.value as Success?)?.response ?? MainListReply(); + if (oid != null) { + response.replies.insert(hasUpTop ? 1 : 0, replyInfo); + } else { + response.replies[index].replies.add(replyInfo); + } + count.value += 1; + loadingState.value = LoadingState.success(response); } else { - response.replies[index].replies.add(replyInfo); + ReplyData response = + (loadingState.value as Success?)?.response ?? ReplyData(); + response.replies ??= []; + if (oid != null) { + response.replies + ?.insert(hasUpTop ? 1 : 0, ReplyItemModel.fromJson(res, '')); + } else { + response.replies?[index].replies ??= []; + response.replies?[index].replies + ?.add(ReplyItemModel.fromJson(res, '')); + } + count.value += 1; + loadingState.value = LoadingState.success(response); } - count.value += 1; - loadingState.value = LoadingState.success(response); } }, ); } onMDelete(rpid, frpid) { - MainListReply response = (loadingState.value as Success).response; - if (frpid == null) { - response.replies.removeWhere((item) { - return item.id.toInt() == rpid; - }); + if (GlobalData().grpcReply) { + MainListReply response = (loadingState.value as Success).response; + if (frpid == null) { + response.replies.removeWhere((item) { + return item.id.toInt() == rpid; + }); + } else { + response.replies.map((item) { + if (item.id == frpid) { + return item + ..replies.removeWhere((reply) => reply.id.toInt() == rpid); + } else { + return item; + } + }).toList(); + } + count.value -= 1; + loadingState.value = LoadingState.success(response); } else { - response.replies.map((item) { - if (item.id == frpid) { - return item..replies.removeWhere((reply) => reply.id.toInt() == rpid); - } else { - return item; - } - }).toList(); + ReplyData response = (loadingState.value as Success).response; + response.replies = frpid == null + ? response.replies?.where((item) => item.rpid != rpid).toList() + : response.replies?.map((item) { + if (item.rpid == frpid) { + return item + ..replies = item.replies + ?.where((reply) => reply.rpid != rpid) + .toList(); + } else { + return item; + } + }).toList(); + count.value -= 1; + loadingState.value = LoadingState.success(response); } - count.value -= 1; - loadingState.value = LoadingState.success(response); } } diff --git a/lib/pages/dynamics/detail/controller.dart b/lib/pages/dynamics/detail/controller.dart index 8e75e107..3d48e869 100644 --- a/lib/pages/dynamics/detail/controller.dart +++ b/lib/pages/dynamics/detail/controller.dart @@ -1,6 +1,7 @@ import 'package:PiliPalaX/grpc/app/main/community/reply/v1/reply.pb.dart'; import 'package:PiliPalaX/http/loading_state.dart'; import 'package:PiliPalaX/pages/common/reply_controller.dart'; +import 'package:PiliPalaX/utils/global_data.dart'; import 'package:get/get.dart'; import 'package:PiliPalaX/http/html.dart'; import 'package:PiliPalaX/http/reply.dart'; @@ -34,23 +35,22 @@ class DynamicDetailController extends ReplyController { queryData(); } - // @override - // Future customGetData() => ReplyHttp.replyList( - // isLogin: isLogin, - // oid: oid!, - // nextOffset: nextOffset, - // type: type!, - // sort: sortType.index, - // page: currentPage, - // ); - @override - Future customGetData() => ReplyHttp.replyListGrpc( - type: type ?? 1, - oid: oid!, - cursor: CursorReq( - next: cursor?.next ?? $fixnum.Int64(0), - mode: mode, - ), - ); + Future customGetData() => GlobalData().grpcReply + ? ReplyHttp.replyListGrpc( + type: type ?? 1, + oid: oid!, + cursor: CursorReq( + next: cursor?.next ?? $fixnum.Int64(0), + mode: mode, + ), + ) + : ReplyHttp.replyList( + isLogin: isLogin, + oid: oid!, + nextOffset: nextOffset, + type: type!, + sort: sortType.index, + page: currentPage, + ); } diff --git a/lib/pages/dynamics/detail/view.dart b/lib/pages/dynamics/detail/view.dart index 0e853486..9c64c107 100644 --- a/lib/pages/dynamics/detail/view.dart +++ b/lib/pages/dynamics/detail/view.dart @@ -3,9 +3,12 @@ import 'dart:math'; import 'package:PiliPalaX/common/widgets/refresh_indicator.dart'; import 'package:PiliPalaX/http/loading_state.dart'; +import 'package:PiliPalaX/pages/video/detail/reply/widgets/reply_item.dart'; import 'package:PiliPalaX/pages/video/detail/reply/widgets/reply_item_grpc.dart'; import 'package:PiliPalaX/utils/extension.dart'; +import 'package:PiliPalaX/utils/global_data.dart'; import 'package:PiliPalaX/utils/utils.dart'; +import 'package:easy_debounce/easy_throttle.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:get/get.dart'; @@ -110,23 +113,25 @@ class _DynamicDetailPageState extends State // 查看二级评论 void replyReply(replyItem, id, isTop) { - int oid = replyItem.oid.toInt(); - int rpid = replyItem.id.toInt()!; - Get.to( - () => Scaffold( - resizeToAvoidBottomInset: false, - appBar: AppBar(title: Text('评论详情')), - body: VideoReplyReplyPanel( - id: id, - oid: oid, - rpid: rpid, - source: 'dynamic', - replyType: ReplyType.values[replyType], - firstFloor: replyItem, - isTop: isTop, + EasyThrottle.throttle('replyReply', const Duration(milliseconds: 500), () { + int oid = replyItem.oid.toInt(); + int rpid = GlobalData().grpcReply ? replyItem.id.toInt() : replyItem.rpid; + Get.to( + () => Scaffold( + resizeToAvoidBottomInset: false, + appBar: AppBar(title: Text('评论详情')), + body: VideoReplyReplyPanel( + id: id, + oid: oid, + rpid: rpid, + source: 'dynamic', + replyType: ReplyType.values[replyType], + firstFloor: replyItem, + isTop: isTop ?? false, + ), ), - ), - ); + ); + }); } // 滑动事件监听 @@ -386,23 +391,40 @@ class _DynamicDetailPageState extends State ), ); } else { - return ReplyItemGrpc( - replyItem: loadingState.response.replies[index], - showReplyRow: true, - replyLevel: '1', - replyReply: replyReply, - replyType: ReplyType.values[replyType], - onReply: () { - _dynamicDetailController.onReply( - context, - replyItem: loadingState.response.replies[index], - index: index, - ); - }, - onDelete: _dynamicDetailController.onMDelete, - isTop: _dynamicDetailController.hasUpTop && index == 0, - upMid: loadingState.response.subjectControl.upMid, - ); + return GlobalData().grpcReply + ? ReplyItemGrpc( + replyItem: loadingState.response.replies[index], + showReplyRow: true, + replyLevel: '1', + replyReply: replyReply, + replyType: ReplyType.values[replyType], + onReply: () { + _dynamicDetailController.onReply( + context, + replyItem: loadingState.response.replies[index], + index: index, + ); + }, + onDelete: _dynamicDetailController.onMDelete, + isTop: + _dynamicDetailController.hasUpTop && index == 0, + upMid: loadingState.response.subjectControl.upMid, + ) + : ReplyItem( + replyItem: loadingState.response.replies[index], + showReplyRow: true, + replyLevel: '1', + replyReply: replyReply, + replyType: ReplyType.values[replyType], + onReply: () { + _dynamicDetailController.onReply( + context, + replyItem: loadingState.response.replies[index], + index: index, + ); + }, + onDelete: _dynamicDetailController.onMDelete, + ); } }, childCount: loadingState.response.replies.length + 1, diff --git a/lib/pages/fav/controller.dart b/lib/pages/fav/controller.dart index 136f35e8..f36f5daa 100644 --- a/lib/pages/fav/controller.dart +++ b/lib/pages/fav/controller.dart @@ -1,6 +1,5 @@ import 'package:PiliPalaX/http/loading_state.dart'; import 'package:PiliPalaX/pages/common/common_controller.dart'; -import 'package:PiliPalaX/utils/extension.dart'; import 'package:hive/hive.dart'; import 'package:PiliPalaX/http/user.dart'; import 'package:PiliPalaX/models/user/info.dart'; @@ -10,7 +9,6 @@ class FavController extends CommonController { Box userInfoCache = GStorage.userInfo; late final UserInfoData? userInfo = userInfoCache.get('userInfoCache'); int pageSize = 10; - bool hasMore = true; @override void onInit() { @@ -24,16 +22,14 @@ class FavController extends CommonController { loadingState.value = LoadingState.error('账号未登录'); return Future.value(); } - if (isRefresh.not && hasMore.not) { - return Future.value(); - } return super.queryData(isRefresh); } @override bool customHandleResponse(Success response) { - hasMore = response.response.hasMore; - isEnd = response.response.list.isEmpty; + if (!response.response.hasMore || response.response.list.isEmpty) { + isEnd = true; + } if (currentPage != 1 && loadingState.value is Success) { response.response.list .insertAll(0, (loadingState.value as Success).response); diff --git a/lib/pages/fav_detail/controller.dart b/lib/pages/fav_detail/controller.dart index 30b0dcbe..175f49f8 100644 --- a/lib/pages/fav_detail/controller.dart +++ b/lib/pages/fav_detail/controller.dart @@ -35,16 +35,19 @@ class FavDetailController extends MultiSelectController { isOwner.value = response.response.info.mid == GStorage.userInfo.get('userInfoCache')?.mid; } + if (response.response.medias.isEmpty) { + isEnd = true; + } if (currentPage != 1 && loadingState.value is Success) { response.response.medias?.insertAll( 0, List.from((loadingState.value as Success).response), ); } - loadingState.value = LoadingState.success(response.response.medias); if (response.response.medias.length >= response.response.info.mediaCount) { isEnd = true; } + loadingState.value = LoadingState.success(response.response.medias); return true; } diff --git a/lib/pages/fav_search/controller.dart b/lib/pages/fav_search/controller.dart index e946bba2..e3266266 100644 --- a/lib/pages/fav_search/controller.dart +++ b/lib/pages/fav_search/controller.dart @@ -56,10 +56,10 @@ class FavSearchController extends CommonController { : (currentPage == 1 ? response.response.list : currentList + response.response.list); - loadingState.value = LoadingState.success(dataList); isEnd = searchType == SearchType.fav ? !response.response.hasMore : response.response.list.isEmpty; + loadingState.value = LoadingState.success(dataList); return true; } diff --git a/lib/pages/html/controller.dart b/lib/pages/html/controller.dart index 3d695c27..7305c1cf 100644 --- a/lib/pages/html/controller.dart +++ b/lib/pages/html/controller.dart @@ -1,6 +1,7 @@ import 'package:PiliPalaX/grpc/app/main/community/reply/v1/reply.pb.dart'; import 'package:PiliPalaX/http/loading_state.dart'; import 'package:PiliPalaX/pages/common/reply_controller.dart'; +import 'package:PiliPalaX/utils/global_data.dart'; import 'package:get/get.dart'; import 'package:PiliPalaX/http/html.dart'; import 'package:PiliPalaX/http/reply.dart'; @@ -44,23 +45,22 @@ class HtmlRenderController extends ReplyController { } } - // @override - // Future customGetData() => ReplyHttp.replyList( - // isLogin: isLogin, - // oid: oid.value, - // nextOffset: nextOffset, - // type: type, - // sort: sortType.index, - // page: currentPage, - // ); - @override - Future customGetData() => ReplyHttp.replyListGrpc( - type: type, - oid: oid.value, - cursor: CursorReq( - next: cursor?.next ?? $fixnum.Int64(0), - mode: mode, - ), - ); + Future customGetData() => GlobalData().grpcReply + ? ReplyHttp.replyListGrpc( + type: type, + oid: oid.value, + cursor: CursorReq( + next: cursor?.next ?? $fixnum.Int64(0), + mode: mode, + ), + ) + : ReplyHttp.replyList( + isLogin: isLogin, + oid: oid.value, + nextOffset: nextOffset, + type: type, + sort: sortType.index, + page: currentPage, + ); } diff --git a/lib/pages/html/view.dart b/lib/pages/html/view.dart index a5f4c960..91be6678 100644 --- a/lib/pages/html/view.dart +++ b/lib/pages/html/view.dart @@ -3,8 +3,11 @@ import 'dart:math'; import 'package:PiliPalaX/common/widgets/article_content.dart'; import 'package:PiliPalaX/common/widgets/http_error.dart'; import 'package:PiliPalaX/http/loading_state.dart'; +import 'package:PiliPalaX/pages/video/detail/reply/widgets/reply_item.dart'; import 'package:PiliPalaX/pages/video/detail/reply/widgets/reply_item_grpc.dart'; import 'package:PiliPalaX/utils/extension.dart'; +import 'package:PiliPalaX/utils/global_data.dart'; +import 'package:easy_debounce/easy_throttle.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; @@ -101,25 +104,27 @@ class _HtmlRenderPageState extends State } void replyReply(replyItem, id, isTop) { - int oid = replyItem.oid.toInt(); - int rpid = replyItem.id.toInt(); - Get.to( - () => Scaffold( - resizeToAvoidBottomInset: false, - appBar: AppBar( - title: Text('评论详情'), + EasyThrottle.throttle('replyReply', const Duration(milliseconds: 500), () { + int oid = replyItem.oid.toInt(); + int rpid = GlobalData().grpcReply ? replyItem.id.toInt() : replyItem.rpid; + Get.to( + () => Scaffold( + resizeToAvoidBottomInset: false, + appBar: AppBar( + title: Text('评论详情'), + ), + body: VideoReplyReplyPanel( + id: id, + oid: oid, + rpid: rpid, + source: 'dynamic', + replyType: ReplyType.values[type], + firstFloor: replyItem, + isTop: isTop ?? false, + ), ), - body: VideoReplyReplyPanel( - id: id, - oid: oid, - rpid: rpid, - source: 'dynamic', - replyType: ReplyType.values[type], - firstFloor: replyItem, - isTop: isTop, - ), - ), - ); + ); + }); } @override @@ -345,23 +350,39 @@ class _HtmlRenderPageState extends State ), ); } else { - return ReplyItemGrpc( - replyItem: loadingState.response.replies[index], - showReplyRow: true, - replyLevel: '1', - replyReply: replyReply, - replyType: ReplyType.values[type], - onReply: () { - _htmlRenderCtr.onReply( - context, - replyItem: loadingState.response.replies[index], - index: index, - ); - }, - onDelete: _htmlRenderCtr.onMDelete, - isTop: _htmlRenderCtr.hasUpTop && index == 0, - upMid: loadingState.response.subjectControl.upMid, - ); + return GlobalData().grpcReply + ? ReplyItemGrpc( + replyItem: loadingState.response.replies[index], + showReplyRow: true, + replyLevel: '1', + replyReply: replyReply, + replyType: ReplyType.values[type], + onReply: () { + _htmlRenderCtr.onReply( + context, + replyItem: loadingState.response.replies[index], + index: index, + ); + }, + onDelete: _htmlRenderCtr.onMDelete, + isTop: _htmlRenderCtr.hasUpTop && index == 0, + upMid: loadingState.response.subjectControl.upMid, + ) + : ReplyItem( + replyItem: loadingState.response.replies[index], + showReplyRow: true, + replyLevel: '1', + replyReply: replyReply, + replyType: ReplyType.values[type], + onReply: () { + _htmlRenderCtr.onReply( + context, + replyItem: loadingState.response.replies[index], + index: index, + ); + }, + onDelete: _htmlRenderCtr.onMDelete, + ); } }, ) diff --git a/lib/pages/later/controller.dart b/lib/pages/later/controller.dart index 5efc0615..3cfb89f1 100644 --- a/lib/pages/later/controller.dart +++ b/lib/pages/later/controller.dart @@ -17,8 +17,9 @@ class LaterController extends MultiSelectController { @override bool customHandleResponse(Success response) { - if (currentPage == 1) { - count.value = response.response['count']; + count.value = response.response['count']; + if (response.response['list'].isEmpty) { + isEnd = true; } if (currentPage != 1 && loadingState.value is Success) { response.response['list'].insertAll( diff --git a/lib/pages/member/new/content/member_contribute/content/article/member_article_ctr.dart b/lib/pages/member/new/content/member_contribute/content/article/member_article_ctr.dart index ff0f902b..a5d796b2 100644 --- a/lib/pages/member/new/content/member_contribute/content/article/member_article_ctr.dart +++ b/lib/pages/member/new/content/member_contribute/content/article/member_article_ctr.dart @@ -2,6 +2,7 @@ import 'package:PiliPalaX/http/loading_state.dart'; import 'package:PiliPalaX/http/member.dart'; import 'package:PiliPalaX/models/space_article/data.dart'; import 'package:PiliPalaX/pages/common/common_controller.dart'; +import 'package:PiliPalaX/utils/extension.dart'; class MemberArticleCtr extends CommonController { MemberArticleCtr({ @@ -21,12 +22,17 @@ class MemberArticleCtr extends CommonController { @override bool customHandleResponse(Success response) { Data data = response.response; + if (data.item.isNullOrEmpty) { + isEnd = true; + } if (currentPage == 1) { count = data.count ?? -1; } else if (loadingState.value is Success) { data.item?.insertAll(0, (loadingState.value as Success).response); } - isEnd = (data.item?.length ?? -1) >= count; + if ((data.item?.length ?? -1) >= count) { + isEnd = true; + } loadingState.value = LoadingState.success(data.item); return true; } diff --git a/lib/pages/member/new/content/member_contribute/content/bangumi/member_bangumi_ctr.dart b/lib/pages/member/new/content/member_contribute/content/bangumi/member_bangumi_ctr.dart index 79925291..a46d0209 100644 --- a/lib/pages/member/new/content/member_contribute/content/bangumi/member_bangumi_ctr.dart +++ b/lib/pages/member/new/content/member_contribute/content/bangumi/member_bangumi_ctr.dart @@ -5,6 +5,7 @@ import 'package:PiliPalaX/pages/common/common_controller.dart'; import 'package:PiliPalaX/pages/member/new/content/member_contribute/member_contribute.dart' show ContributeType; import 'package:PiliPalaX/pages/member/new/controller.dart'; +import 'package:PiliPalaX/utils/extension.dart'; import 'package:get/get.dart'; class MemberBangumiCtr extends CommonController { @@ -31,10 +32,15 @@ class MemberBangumiCtr extends CommonController { @override bool customHandleResponse(Success response) { Data data = response.response; + if (data.item.isNullOrEmpty) { + isEnd = true; + } if (currentPage != 1 && loadingState.value is Success) { data.item?.insertAll(0, (loadingState.value as Success).response); } - isEnd = data.item!.length >= count; + if (data.item!.length >= count) { + isEnd = true; + } loadingState.value = LoadingState.success(data.item); return true; } diff --git a/lib/pages/setting/extra_setting.dart b/lib/pages/setting/extra_setting.dart index 601baefb..e886af72 100644 --- a/lib/pages/setting/extra_setting.dart +++ b/lib/pages/setting/extra_setting.dart @@ -1,6 +1,7 @@ import 'package:PiliPalaX/pages/main/controller.dart'; import 'package:PiliPalaX/pages/member/new/controller.dart' show MemberTabType, MemberTabTypeExt; +import 'package:PiliPalaX/utils/global_data.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; @@ -152,7 +153,7 @@ class _ExtraSettingState extends State { leading: Icon(Icons.notifications_none), setKey: SettingBoxKey.checkDynamic, defaultVal: true, - callFn: (value) { + onChanged: (value) { Get.find().checkDynamic = value; }, onTap: () { @@ -201,6 +202,16 @@ class _ExtraSettingState extends State { ); }, ), + SetSwitchItem( + title: '使用gRPC加载评论', + subTitle: '如无法加载评论,可关闭\n非gRPC楼中楼无法定位评论、按热度/时间排序、查看对话', + leading: Icon(Icons.reply), + setKey: SettingBoxKey.grpcReply, + defaultVal: true, + onChanged: (value) { + GlobalData().grpcReply = value; + }, + ), Obx( () => ListTile( enableFeedback: true, @@ -238,7 +249,7 @@ class _ExtraSettingState extends State { leading: const Icon(Icons.whatshot_outlined), setKey: SettingBoxKey.enableSearchWord, defaultVal: true, - callFn: (val) { + onChanged: (val) { Get.find().defaultSearch.value = ''; }, ), diff --git a/lib/pages/setting/pages/play_speed_set.dart b/lib/pages/setting/pages/play_speed_set.dart index 405f0a02..5511c3ed 100644 --- a/lib/pages/setting/pages/play_speed_set.dart +++ b/lib/pages/setting/pages/play_speed_set.dart @@ -225,7 +225,7 @@ class _PlaySpeedPageState extends State { subTitle: '根据默认倍速长按时自动双倍', setKey: SettingBoxKey.enableAutoLongPressSpeed, defaultVal: enableAutoLongPressSpeed, - callFn: (val) { + onChanged: (val) { Map newItem = sheetMenu[1]; val ? newItem['show'] = false : newItem['show'] = true; setState(() { diff --git a/lib/pages/setting/play_setting.dart b/lib/pages/setting/play_setting.dart index 23e8bda5..493d9cc0 100644 --- a/lib/pages/setting/play_setting.dart +++ b/lib/pages/setting/play_setting.dart @@ -159,7 +159,7 @@ class _PlaySettingState extends State { leading: const Icon(Icons.picture_in_picture_outlined), setKey: SettingBoxKey.autoPiP, defaultVal: false, - callFn: (val) { + onChanged: (val) { if (val && !setting.get(SettingBoxKey.enableBackgroundPlay, defaultValue: true)) { diff --git a/lib/pages/setting/recommend_setting.dart b/lib/pages/setting/recommend_setting.dart index 763d1942..04cbfecc 100644 --- a/lib/pages/setting/recommend_setting.dart +++ b/lib/pages/setting/recommend_setting.dart @@ -231,7 +231,7 @@ class _RecommendSettingState extends State { leading: const Icon(Icons.favorite_border_outlined), setKey: SettingBoxKey.exemptFilterForFollowed, defaultVal: true, - callFn: (_) => {RecommendFilter.update}, + onChanged: (_) => {RecommendFilter.update}, ), // ListTile( // dense: false, @@ -267,7 +267,7 @@ class _RecommendSettingState extends State { leading: const Icon(Icons.explore_outlined), setKey: SettingBoxKey.applyFilterToRelatedVideos, defaultVal: true, - callFn: (_) => {RecommendFilter.update}, + onChanged: (_) => {RecommendFilter.update}, ), ListTile( dense: true, diff --git a/lib/pages/setting/style_setting.dart b/lib/pages/setting/style_setting.dart index c0b4519b..30bcda50 100644 --- a/lib/pages/setting/style_setting.dart +++ b/lib/pages/setting/style_setting.dart @@ -64,7 +64,7 @@ class _StyleSettingState extends State { leading: const Icon(Icons.phonelink_outlined), setKey: SettingBoxKey.horizontalScreen, defaultVal: false, - callFn: (value) { + onChanged: (value) { if (value) { autoScreen(); // SmartDialog.showToast('已开启横屏适配'); diff --git a/lib/pages/setting/widgets/switch_item.dart b/lib/pages/setting/widgets/switch_item.dart index 2fb7c7fb..d7b6ae6c 100644 --- a/lib/pages/setting/widgets/switch_item.dart +++ b/lib/pages/setting/widgets/switch_item.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; -import 'package:hive/hive.dart'; import 'package:PiliPalaX/utils/storage.dart'; class SetSwitchItem extends StatefulWidget { @@ -8,7 +7,7 @@ class SetSwitchItem extends StatefulWidget { final String? subTitle; final String? setKey; final bool? defaultVal; - final Function? callFn; + final ValueChanged? onChanged; final bool? needReboot; final Widget? leading; final GestureTapCallback? onTap; @@ -18,7 +17,7 @@ class SetSwitchItem extends StatefulWidget { this.subTitle, this.setKey, this.defaultVal, - this.callFn, + this.onChanged, this.needReboot, this.leading, this.onTap, @@ -30,24 +29,23 @@ class SetSwitchItem extends StatefulWidget { } class _SetSwitchItemState extends State { - // ignore: non_constant_identifier_names - Box Setting = GStorage.setting; late bool val; @override void initState() { super.initState(); - val = Setting.get(widget.setKey, defaultValue: widget.defaultVal ?? false); + val = GStorage.setting + .get(widget.setKey, defaultValue: widget.defaultVal ?? false); } void switchChange(value) async { val = value ?? !val; - await Setting.put(widget.setKey, val); + await GStorage.setting.put(widget.setKey, val); // if (widget.setKey == SettingBoxKey.autoUpdate && value == true) { // Utils.checkUpdate(); // } - if (widget.callFn != null) { - widget.callFn!.call(val); + if (widget.onChanged != null) { + widget.onChanged!.call(val); } if (widget.needReboot != null && widget.needReboot!) { SmartDialog.showToast('重启生效'); @@ -87,7 +85,7 @@ class _SetSwitchItemState extends State { return null; // All other states will use the default thumbIcon. }), value: val, - onChanged: (val) => switchChange(val), + onChanged: switchChange, ), ), ); diff --git a/lib/pages/video/detail/reply/controller.dart b/lib/pages/video/detail/reply/controller.dart index 6fdfd72d..ca79728d 100644 --- a/lib/pages/video/detail/reply/controller.dart +++ b/lib/pages/video/detail/reply/controller.dart @@ -1,7 +1,9 @@ import 'package:PiliPalaX/grpc/app/main/community/reply/v1/reply.pb.dart'; import 'package:PiliPalaX/http/loading_state.dart'; +import 'package:PiliPalaX/models/common/reply_type.dart'; import 'package:PiliPalaX/pages/common/reply_controller.dart'; import 'package:PiliPalaX/http/reply.dart'; +import 'package:PiliPalaX/utils/global_data.dart'; import 'package:fixnum/fixnum.dart' as $fixnum; class VideoReplyController extends ReplyController { @@ -18,11 +20,20 @@ class VideoReplyController extends ReplyController { String? rpid; @override - Future customGetData() => ReplyHttp.replyListGrpc( - oid: aid!, - cursor: CursorReq( - next: cursor?.next ?? $fixnum.Int64(0), - mode: mode, - ), - ); + Future customGetData() => GlobalData().grpcReply + ? ReplyHttp.replyListGrpc( + oid: aid!, + cursor: CursorReq( + next: cursor?.next ?? $fixnum.Int64(0), + mode: mode, + ), + ) + : ReplyHttp.replyList( + isLogin: isLogin, + oid: aid!, + nextOffset: nextOffset, + type: ReplyType.video.index, + sort: sortType.index, + page: currentPage, + ); } diff --git a/lib/pages/video/detail/reply/view.dart b/lib/pages/video/detail/reply/view.dart index a12d77a4..dec63411 100644 --- a/lib/pages/video/detail/reply/view.dart +++ b/lib/pages/video/detail/reply/view.dart @@ -1,8 +1,10 @@ import 'package:PiliPalaX/common/widgets/refresh_indicator.dart'; import 'package:PiliPalaX/common/widgets/http_error.dart'; import 'package:PiliPalaX/http/loading_state.dart'; +import 'package:PiliPalaX/pages/video/detail/reply/widgets/reply_item.dart'; import 'package:PiliPalaX/pages/video/detail/reply/widgets/reply_item_grpc.dart'; import 'package:PiliPalaX/utils/extension.dart'; +import 'package:PiliPalaX/utils/global_data.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:get/get.dart'; @@ -228,24 +230,43 @@ class _VideoReplyPanelState extends State ), ); } else { - return ReplyItemGrpc( - replyItem: loadingState.response.replies[index], - showReplyRow: true, - replyLevel: replyLevel, - replyReply: widget.replyReply, - replyType: ReplyType.video, - onReply: () { - _videoReplyController.onReply( - context, - replyItem: loadingState.response.replies[index], - index: index, - ); - }, - onDelete: _videoReplyController.onMDelete, - isTop: _videoReplyController.hasUpTop && index == 0, - upMid: loadingState.response.subjectControl.upMid, - getTag: () => heroTag, - ); + return GlobalData().grpcReply + ? ReplyItemGrpc( + replyItem: loadingState.response.replies[index], + showReplyRow: true, + replyLevel: replyLevel, + replyReply: widget.replyReply, + replyType: ReplyType.video, + onReply: () { + _videoReplyController.onReply( + context, + replyItem: loadingState.response.replies[index], + index: index, + ); + }, + onDelete: _videoReplyController.onMDelete, + isTop: _videoReplyController.hasUpTop && index == 0, + upMid: loadingState.response.subjectControl.upMid, + getTag: () => heroTag, + ) + : ReplyItem( + replyItem: loadingState.response.replies[index], + showReplyRow: true, + replyLevel: replyLevel, + replyReply: widget.replyReply, + replyType: ReplyType.video, + onReply: () { + _videoReplyController.onReply( + context, + replyItem: loadingState.response.replies[index], + index: index, + ); + }, + onDelete: _videoReplyController.onMDelete, + // isTop: _videoReplyController.hasUpTop && index == 0, + // upMid: loadingState.response.subjectControl.upMid, + // getTag: () => heroTag, + ); } }, childCount: loadingState.response.replies.length + 1, @@ -256,7 +277,8 @@ class _VideoReplyPanelState extends State callback: _videoReplyController.onReload, ), Error() => HttpError( - errMsg: loadingState.errMsg, + errMsg: + '如无法加载评论:\n1.关闭代理\n2.设置中关闭使用gRPC加载评论\n\n${loadingState.errMsg}', callback: _videoReplyController.onReload, ), LoadingState() => throw UnimplementedError(), diff --git a/lib/pages/video/detail/reply/widgets/reply_item.dart b/lib/pages/video/detail/reply/widgets/reply_item.dart index 4afa8a6e..58444d75 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item.dart @@ -48,7 +48,7 @@ class ReplyItem extends StatelessWidget { // 点击整个评论区 评论详情/回复 onTap: () { feedBack(); - replyReply?.call(replyItem); + replyReply?.call(replyItem, null, null); }, onLongPress: () { feedBack(); @@ -425,7 +425,7 @@ class ReplyItemRow extends StatelessWidget { for (int i = 0; i < replies!.length; i++) ...[ InkWell( // 一楼点击评论展开评论详情 - onTap: () => replyReply?.call(replyItem), + onTap: () => replyReply?.call(replyItem, null, null), onLongPress: () { feedBack(); showModalBottomSheet( @@ -525,7 +525,7 @@ class ReplyItemRow extends StatelessWidget { if (extraRow == 1) InkWell( // 一楼点击【共xx条回复】展开评论详情 - onTap: () => replyReply?.call(replyItem), + onTap: () => replyReply?.call(replyItem, null, null), child: Container( width: double.infinity, padding: const EdgeInsets.fromLTRB(8, 5, 8, 8), diff --git a/lib/pages/video/detail/reply_new/reply_page.dart b/lib/pages/video/detail/reply_new/reply_page.dart index b74f55f1..eef7874b 100644 --- a/lib/pages/video/detail/reply_new/reply_page.dart +++ b/lib/pages/video/detail/reply_new/reply_page.dart @@ -2,9 +2,8 @@ import 'dart:async'; import 'dart:io'; import 'dart:math'; -import 'package:PiliPalaX/grpc/app/main/community/reply/v1/reply.pb.dart' - as reply; import 'package:PiliPalaX/http/msg.dart'; +import 'package:PiliPalaX/utils/global_data.dart'; import 'package:chat_bottom_container/chat_bottom_container.dart'; import 'package:easy_debounce/easy_throttle.dart'; import 'package:flutter/material.dart'; @@ -26,7 +25,7 @@ class ReplyPage extends StatefulWidget { final int? root; final int? parent; final ReplyType? replyType; - final reply.ReplyInfo? replyItem; + final dynamic replyItem; final String? savedReply; final Function(String reply)? onSaveReply; @@ -507,8 +506,8 @@ class _ReplyPageState extends State oid: widget.oid!, root: widget.root!, parent: widget.parent!, - message: widget.replyItem != null && widget.replyItem!.root != 0 - ? ' 回复 @${widget.replyItem!.member.name} : $message' + message: widget.replyItem != null && widget.replyItem.root != 0 + ? ' 回复 @${GlobalData().grpcReply ? widget.replyItem.member.name : widget.replyItem.member.uname} : $message' : message, pictures: pictures, ); diff --git a/lib/pages/video/detail/reply_reply/controller.dart b/lib/pages/video/detail/reply_reply/controller.dart index db3b0db2..a8bbbb1b 100644 --- a/lib/pages/video/detail/reply_reply/controller.dart +++ b/lib/pages/video/detail/reply_reply/controller.dart @@ -1,7 +1,9 @@ import 'package:PiliPalaX/grpc/app/main/community/reply/v1/reply.pb.dart'; import 'package:PiliPalaX/grpc/grpc_repo.dart'; import 'package:PiliPalaX/http/loading_state.dart'; +import 'package:PiliPalaX/models/video/reply/item.dart'; import 'package:PiliPalaX/pages/common/common_controller.dart'; +import 'package:PiliPalaX/utils/global_data.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:PiliPalaX/http/reply.dart'; @@ -29,8 +31,6 @@ class VideoReplyReplyController extends CommonController // rpid 请求楼中楼回复 int? rpid; ReplyType replyType; // = ReplyType.video; - // 当前回复的回复 - ReplyInfo? currentReplyItem; CursorReply? cursor; Rx mode = Mode.MAIN_LIST_TIME.obs; @@ -41,7 +41,7 @@ class VideoReplyReplyController extends CommonController AnimationController? controller; Animation? colorAnimation; - ReplyInfo? firstFloor; + dynamic firstFloor; @override void onInit() { @@ -49,34 +49,6 @@ class VideoReplyReplyController extends CommonController queryData(); } - // @override - // bool customHandleResponse(Success response) { - // if (response.response.root != null) root = response.response.root; - // List replies = response.response.replies; - // if (replies.isNotEmpty) { - // noMore.value = '加载中...'; - // if (replies.length == response.response.page.count) { - // noMore.value = '没有更多了'; - // } - // } else { - // // 未登录状态replies可能返回null - // noMore.value = currentPage == 1 ? '还没有评论' : '没有更多了'; - // } - // if (currentPage != 1) { - // List list = loadingState.value is Success - // ? (loadingState.value as Success).response - // : []; - // // 每次回复之后,翻页请求有且只有相同的一条回复数据 - // if (replies.length == 1 && replies.last.rpid == list.last.rpid) { - // return true; - // } else { - // replies.insertAll(0, list); - // } - // } - // loadingState.value = LoadingState.success(replies); - // return true; - // } - @override Future queryData([bool isRefresh = true]) async { if (!isDialogue && @@ -95,14 +67,6 @@ class VideoReplyReplyController extends CommonController return super.queryData(isRefresh); } - // @override - // Future customGetData() => ReplyHttp.replyReplyList( - // oid: aid!, - // root: rpid!, - // pageNum: currentPage, - // type: replyType.index, - // ); - @override Future onRefresh() { cursor = null; @@ -111,61 +75,89 @@ class VideoReplyReplyController extends CommonController @override bool customHandleResponse(Success response) { - dynamic replies = response.response; - if (replies is DetailListReply && cursor == null) { - count.value = replies.root.count.toInt(); - if (id != null) { - index = replies.root.replies - .map((item) => item.id.toInt()) - .toList() - .indexOf(id!); - if (index != -1) { - controller = AnimationController( - duration: const Duration(milliseconds: 300), - vsync: this, - ); - colorAnimation = ColorTween( - begin: Theme.of(Get.context!).colorScheme.onInverseSurface, - end: Theme.of(Get.context!).colorScheme.surface, - ).animate(controller!); - WidgetsBinding.instance.addPostFrameCallback((_) async { - itemScrollCtr.jumpTo( - index: hasRoot ? index! + 3 : index! + 1, - alignment: 0.25, + if (GlobalData().grpcReply) { + dynamic replies = response.response; + if (replies is DetailListReply && cursor == null) { + count.value = replies.root.count.toInt(); + if (id != null) { + index = replies.root.replies + .map((item) => item.id.toInt()) + .toList() + .indexOf(id!); + if (index != -1) { + controller = AnimationController( + duration: const Duration(milliseconds: 300), + vsync: this, ); - await Future.delayed(const Duration(milliseconds: 800)); - await controller?.forward(); - index = null; - }); + colorAnimation = ColorTween( + begin: Theme.of(Get.context!).colorScheme.onInverseSurface, + end: Theme.of(Get.context!).colorScheme.surface, + ).animate(controller!); + WidgetsBinding.instance.addPostFrameCallback((_) async { + itemScrollCtr.jumpTo( + index: hasRoot ? index! + 3 : index! + 1, + alignment: 0.25, + ); + await Future.delayed(const Duration(milliseconds: 800)); + await controller?.forward(); + index = null; + }); + } + id = null; } - id = null; } - } - upMid ??= replies.subjectControl.upMid.toInt(); - cursor = replies.cursor; - if (currentPage != 1) { - List list = loadingState.value is Success - ? (loadingState.value as Success).response - : []; + upMid ??= replies.subjectControl.upMid.toInt(); + cursor = replies.cursor; if (isDialogue) { - replies.replies.insertAll(0, list); + if (replies.replies.isEmpty) { + isEnd = true; + } } else { - replies.root.replies.insertAll(0, list); + if (replies.root.replies.isEmpty) { + isEnd = true; + } + } + if (currentPage != 1) { + List list = loadingState.value is Success + ? (loadingState.value as Success).response + : []; + if (isDialogue) { + replies.replies.insertAll(0, list); + } else { + replies.root.replies.insertAll(0, list); + } + } + if (isDialogue) { + if (replies.cursor.isEnd || replies.replies.length >= count.value) { + isEnd = true; + } + } else { + if (replies.cursor.isEnd || + replies.root.replies.length >= count.value) { + isEnd = true; + } + } + if (isDialogue) { + loadingState.value = LoadingState.success(replies.replies); + } else { + loadingState.value = LoadingState.success(replies.root.replies); } - } - if (isDialogue) { - isEnd = replies.replies.isEmpty || - replies.cursor.isEnd || - replies.replies.length >= count.value; } else { - isEnd = replies.root.replies.isEmpty || - replies.cursor.isEnd || - replies.root.replies.length >= count.value; - } - if (isDialogue) { - loadingState.value = LoadingState.success(replies.replies); - } else { - loadingState.value = LoadingState.success(replies.root.replies); + if (response.response.root != null) { + firstFloor = response.response.root; + } + List replies = response.response.replies; + count.value = response.response.page.count; + if (replies.isEmpty) { + isEnd = true; + } + if (currentPage != 1 && loadingState.value is Success) { + replies.insertAll(0, (loadingState.value as Success).response); + } + if (replies.length >= response.response.page.count) { + isEnd = true; + } + loadingState.value = LoadingState.success(replies); } return true; } @@ -182,16 +174,23 @@ class VideoReplyReplyController extends CommonController mode: mode.value, ), ) - : ReplyHttp.replyReplyListGrpc( - type: replyType.index, - oid: oid!, - root: rpid!, - rpid: id ?? 0, - cursor: CursorReq( - next: cursor?.next, - mode: mode.value, - ), - ); + : GlobalData().grpcReply + ? ReplyHttp.replyReplyListGrpc( + type: replyType.index, + oid: oid!, + root: rpid!, + rpid: id ?? 0, + cursor: CursorReq( + next: cursor?.next, + mode: mode.value, + ), + ) + : ReplyHttp.replyReplyList( + oid: oid!, + root: rpid!, + pageNum: currentPage, + type: replyType.index, + ); queryBySort() { mode.value = mode.value == Mode.MAIN_LIST_HOT diff --git a/lib/pages/video/detail/reply_reply/view.dart b/lib/pages/video/detail/reply_reply/view.dart index f4cdf517..edf7b860 100644 --- a/lib/pages/video/detail/reply_reply/view.dart +++ b/lib/pages/video/detail/reply_reply/view.dart @@ -1,9 +1,12 @@ import 'package:PiliPalaX/common/widgets/refresh_indicator.dart'; import 'package:PiliPalaX/grpc/app/main/community/reply/v1/reply.pb.dart'; import 'package:PiliPalaX/http/loading_state.dart'; +import 'package:PiliPalaX/models/video/reply/item.dart'; +import 'package:PiliPalaX/pages/video/detail/reply/widgets/reply_item.dart'; import 'package:PiliPalaX/pages/video/detail/reply/widgets/reply_item_grpc.dart'; import 'package:PiliPalaX/pages/video/detail/reply_new/reply_page.dart'; import 'package:PiliPalaX/utils/extension.dart'; +import 'package:PiliPalaX/utils/global_data.dart'; import 'package:PiliPalaX/utils/utils.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -17,7 +20,6 @@ import 'controller.dart'; class VideoReplyReplyPanel extends StatefulWidget { const VideoReplyReplyPanel({ - // this.rcount, this.id, this.oid, this.rpid, @@ -29,12 +31,11 @@ class VideoReplyReplyPanel extends StatefulWidget { this.isTop = false, super.key, }); - // final dynamic rcount; final int? id; final int? oid; final int? rpid; final int? dialog; - final ReplyInfo? firstFloor; + final dynamic firstFloor; final String? source; final ReplyType? replyType; final bool isDialogue; @@ -50,7 +51,7 @@ class _VideoReplyReplyPanelState extends State { late final itemPositionsListener = ItemPositionsListener.create(); late final _key = GlobalKey(); - ReplyInfo? get firstFloor => + dynamic get firstFloor => widget.firstFloor ?? _videoReplyReplyController.firstFloor; @override @@ -155,18 +156,29 @@ class _VideoReplyReplyPanelState extends State { index); } else if (firstFloor != null) { if (index == 0) { - return ReplyItemGrpc( - replyItem: firstFloor!, - replyLevel: '2', - showReplyRow: false, - replyType: widget.replyType, - needDivider: false, - onReply: () { - _onReply(firstFloor!, -1); - }, - upMid: _videoReplyReplyController.upMid, - isTop: widget.isTop, - ); + return GlobalData().grpcReply + ? ReplyItemGrpc( + replyItem: firstFloor, + replyLevel: '2', + showReplyRow: false, + replyType: widget.replyType, + needDivider: false, + onReply: () { + _onReply(firstFloor, -1); + }, + upMid: _videoReplyReplyController.upMid, + isTop: widget.isTop, + ) + : ReplyItem( + replyItem: firstFloor, + replyLevel: '2', + showReplyRow: false, + replyType: widget.replyType, + needDivider: false, + onReply: () { + _onReply(firstFloor, -1); + }, + ); } else if (index == 1) { return Divider( height: 20, @@ -223,30 +235,32 @@ class _VideoReplyReplyPanelState extends State { ) : const SizedBox.shrink(), ), - SizedBox( - height: 35, - child: TextButton.icon( - onPressed: () => _videoReplyReplyController.queryBySort(), - icon: const Icon(Icons.sort, size: 16), - label: Obx( - () => Text( - _videoReplyReplyController.mode.value == Mode.MAIN_LIST_HOT - ? '按热度' - : '按时间', - style: const TextStyle(fontSize: 13), + if (GlobalData().grpcReply) + SizedBox( + height: 35, + child: TextButton.icon( + onPressed: () => _videoReplyReplyController.queryBySort(), + icon: const Icon(Icons.sort, size: 16), + label: Obx( + () => Text( + _videoReplyReplyController.mode.value == + Mode.MAIN_LIST_HOT + ? '按热度' + : '按时间', + style: const TextStyle(fontSize: 13), + ), ), ), - ), - ) + ) ], ), ); - void _onReply(ReplyInfo? item, int index) { + void _onReply(dynamic item, int index) { dynamic oid = item?.oid.toInt(); - dynamic root = item?.id.toInt(); - dynamic parent = item?.id.toInt(); - dynamic key = oid + root + parent; + dynamic root = GlobalData().grpcReply ? item?.id.toInt() : item?.rpid; + dynamic key = oid + root; + Navigator.of(context) .push( GetDialogRoute( @@ -254,7 +268,7 @@ class _VideoReplyReplyPanelState extends State { return ReplyPage( oid: oid, root: root, - parent: parent, + parent: root, replyType: widget.replyType, replyItem: item, savedReply: _savedReplies[key], @@ -282,14 +296,26 @@ class _VideoReplyReplyPanelState extends State { .then((res) { if (res != null) { _savedReplies[key] = null; - ReplyInfo replyInfo = Utils.replyCast(res); - List list = (_videoReplyReplyController.loadingState.value as Success?) - ?.response ?? - []; - list.insert(index + 1, replyInfo); - _videoReplyReplyController.count.value += 1; - _videoReplyReplyController.loadingState.value = - LoadingState.success(list); + if (GlobalData().grpcReply) { + ReplyInfo replyInfo = Utils.replyCast(res); + List list = + (_videoReplyReplyController.loadingState.value as Success?) + ?.response ?? + []; + list.insert(index + 1, replyInfo); + _videoReplyReplyController.count.value += 1; + _videoReplyReplyController.loadingState.value = + LoadingState.success(list); + } else { + List list = + (_videoReplyReplyController.loadingState.value as Success?) + ?.response ?? + []; + list.insert(index + 1, ReplyItemModel.fromJson(res, '')); + _videoReplyReplyController.count.value += 1; + _videoReplyReplyController.loadingState.value = + LoadingState.success(list); + } } }); } @@ -361,36 +387,56 @@ class _VideoReplyReplyPanelState extends State { } Widget _replyItem(replyItem, index) { - return ReplyItemGrpc( - replyItem: replyItem, - replyLevel: widget.isDialogue ? '3' : '2', - showReplyRow: false, - replyType: widget.replyType, - onReply: () { - _onReply(replyItem, index); - }, - onDelete: (rpid, frpid) { - List list = - (_videoReplyReplyController.loadingState.value as Success).response; - list = list.where((item) => item.id != rpid).toList(); - _videoReplyReplyController.count.value -= 1; - _videoReplyReplyController.loadingState.value = - LoadingState.success(list); - }, - upMid: _videoReplyReplyController.upMid, - showDialogue: () { - _key.currentState?.showBottomSheet( - (context) => VideoReplyReplyPanel( - oid: replyItem.oid.toInt(), - rpid: replyItem.root.toInt(), - dialog: replyItem.dialog.toInt(), + return GlobalData().grpcReply + ? ReplyItemGrpc( + replyItem: replyItem, + replyLevel: widget.isDialogue ? '3' : '2', + showReplyRow: false, replyType: widget.replyType, - source: 'videoDetail', - isDialogue: true, - ), - ); - }, - ); + onReply: () { + _onReply(replyItem, index); + }, + onDelete: (rpid, frpid) { + List list = + (_videoReplyReplyController.loadingState.value as Success) + .response; + list = list.where((item) => item.id != rpid).toList(); + _videoReplyReplyController.count.value -= 1; + _videoReplyReplyController.loadingState.value = + LoadingState.success(list); + }, + upMid: _videoReplyReplyController.upMid, + showDialogue: () { + _key.currentState?.showBottomSheet( + (context) => VideoReplyReplyPanel( + oid: replyItem.oid.toInt(), + rpid: replyItem.root.toInt(), + dialog: replyItem.dialog.toInt(), + replyType: widget.replyType, + source: 'videoDetail', + isDialogue: true, + ), + ); + }, + ) + : ReplyItem( + replyItem: replyItem, + replyLevel: '2', + showReplyRow: false, + replyType: widget.replyType, + onReply: () { + _onReply(replyItem, index); + }, + onDelete: (rpid, frpid) { + List list = + (_videoReplyReplyController.loadingState.value as Success) + .response; + list.removeWhere((item) => item.rpid == rpid); + _videoReplyReplyController.count.value -= 1; + _videoReplyReplyController.loadingState.value = + LoadingState.success(list); + }, + ); } int _itemCount(LoadingState loadingState) { diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index 1f6afb8b..75585e7f 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -14,6 +14,7 @@ import 'package:PiliPalaX/pages/video/detail/introduction/widgets/intro_detail.d import 'package:PiliPalaX/pages/video/detail/reply_reply/view.dart'; import 'package:PiliPalaX/pages/video/detail/widgets/ai_detail.dart'; import 'package:PiliPalaX/utils/extension.dart'; +import 'package:PiliPalaX/utils/global_data.dart'; import 'package:PiliPalaX/utils/id_utils.dart'; import 'package:auto_orientation/auto_orientation.dart'; import 'package:easy_debounce/easy_throttle.dart'; @@ -1314,16 +1315,17 @@ class _VideoDetailPageState extends State // 展示二级回复 void replyReply(replyItem, id, isTop) { EasyThrottle.throttle('replyReply', const Duration(milliseconds: 500), () { + int oid = replyItem.oid.toInt(); + int rpid = GlobalData().grpcReply ? replyItem.id.toInt() : replyItem.rpid; videoDetailController.childKey.currentState?.showBottomSheet( (context) => VideoReplyReplyPanel( id: id, - // rcount: replyItem.rcount, - oid: replyItem.oid.toInt(), - rpid: replyItem.id.toInt(), + oid: oid, + rpid: rpid, firstFloor: replyItem, replyType: ReplyType.video, source: 'videoDetail', - isTop: isTop, + isTop: isTop ?? false, ), ); }); diff --git a/lib/utils/global_data.dart b/lib/utils/global_data.dart index b0661c82..270beb26 100644 --- a/lib/utils/global_data.dart +++ b/lib/utils/global_data.dart @@ -3,6 +3,8 @@ class GlobalData { int themeMode = 2; + bool grpcReply = true; + // 私有构造函数 GlobalData._(); diff --git a/lib/utils/storage.dart b/lib/utils/storage.dart index be2f5b5d..c9117de9 100644 --- a/lib/utils/storage.dart +++ b/lib/utils/storage.dart @@ -99,6 +99,9 @@ class GStorage { static double get danmakuFontScaleFS => setting.get(SettingBoxKey.danmakuFontScaleFS, defaultValue: 1.2); + static bool get grpcReply => + setting.get(SettingBoxKey.grpcReply, defaultValue: true); + static MemberTabType get memberTab => MemberTabType .values[setting.get(SettingBoxKey.memberTab, defaultValue: 0)]; @@ -157,6 +160,7 @@ class GStorage { SettingBoxKey.themeMode, defaultValue: ThemeType.system.code, ); + GlobalData().grpcReply = grpcReply; } static Future exportAllSettings() async { @@ -274,7 +278,8 @@ class SettingBoxKey { previewQuality = 'previewQuality', checkDynamic = 'checkDynamic', dynamicPeriod = 'dynamicPeriod', - schemeVariant = 'schemeVariaznt', + schemeVariant = 'schemeVariant', + grpcReply = 'grpcReply', // Sponsor Block enableSponsorBlock = 'enableSponsorBlock',