From 1f71dc9a67fc63102ca0346f240352948852a028 Mon Sep 17 00:00:00 2001 From: bggRGjQaUbCoE Date: Thu, 28 Nov 2024 15:24:28 +0800 Subject: [PATCH] opt: reply item Signed-off-by: bggRGjQaUbCoE --- lib/pages/dynamics/detail/view.dart | 3 +- lib/pages/html/view.dart | 3 +- lib/pages/video/detail/controller.dart | 40 +++--- .../detail/reply/widgets/reply_item.dart | 8 +- .../detail/reply/widgets/reply_item_grpc.dart | 122 ++++++++---------- lib/pages/video/detail/reply_reply/view.dart | 3 + lib/pages/video/detail/view.dart | 3 +- lib/utils/utils.dart | 2 +- 8 files changed, 79 insertions(+), 105 deletions(-) diff --git a/lib/pages/dynamics/detail/view.dart b/lib/pages/dynamics/detail/view.dart index a998e03d..7673fc3b 100644 --- a/lib/pages/dynamics/detail/view.dart +++ b/lib/pages/dynamics/detail/view.dart @@ -110,7 +110,7 @@ class _DynamicDetailPageState extends State } // 查看二级评论 - void replyReply(replyItem, id) { + void replyReply(replyItem, id, isTop) { int oid = replyItem.oid.toInt(); int rpid = replyItem.id.toInt()!; Get.to( @@ -124,6 +124,7 @@ class _DynamicDetailPageState extends State source: 'dynamic', replyType: ReplyType.values[replyType], firstFloor: replyItem, + isTop: isTop, ), ), ); diff --git a/lib/pages/html/view.dart b/lib/pages/html/view.dart index 0b00c15f..fc3cbfa4 100644 --- a/lib/pages/html/view.dart +++ b/lib/pages/html/view.dart @@ -109,7 +109,7 @@ class _HtmlRenderPageState extends State } } - void replyReply(replyItem, id) { + void replyReply(replyItem, id, isTop) { int oid = replyItem.oid.toInt(); int rpid = replyItem.id.toInt(); Get.to( @@ -125,6 +125,7 @@ class _HtmlRenderPageState extends State source: 'dynamic', replyType: ReplyType.values[type], firstFloor: replyItem, + isTop: isTop, ), ), ); diff --git a/lib/pages/video/detail/controller.dart b/lib/pages/video/detail/controller.dart index c1e07b5f..b5b39efe 100644 --- a/lib/pages/video/detail/controller.dart +++ b/lib/pages/video/detail/controller.dart @@ -1321,18 +1321,13 @@ class VideoDetailController extends GetxController .primary, ), ), - SizedBox( - height: MediaQuery - .textScalerOf( - context) - .scale(14), - child: Icon( - Icons - .keyboard_arrow_right, - color: Theme.of(context) - .colorScheme - .primary, - ), + Icon( + Icons + .keyboard_arrow_right, + size: 22, + color: Theme.of(context) + .colorScheme + .primary, ), ], ), @@ -1387,19 +1382,14 @@ class VideoDetailController extends GetxController .primary, ), ), - SizedBox( - height: MediaQuery - .textScalerOf( - context) - .scale(14), - child: Icon( - Icons - .keyboard_arrow_right, - color: Theme.of(context) - .colorScheme - .primary, - ), - ) + Icon( + Icons + .keyboard_arrow_right, + size: 22, + color: Theme.of(context) + .colorScheme + .primary, + ), ], ), ), diff --git a/lib/pages/video/detail/reply/widgets/reply_item.dart b/lib/pages/video/detail/reply/widgets/reply_item.dart index 2c676d11..96048094 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item.dart @@ -48,9 +48,7 @@ class ReplyItem extends StatelessWidget { // 点击整个评论区 评论详情/回复 onTap: () { feedBack(); - if (replyReply != null) { - replyReply!(replyItem); - } + replyReply?.call(replyItem); }, onLongPress: () { feedBack(); @@ -434,7 +432,7 @@ class ReplyItemRow extends StatelessWidget { for (int i = 0; i < replies!.length; i++) ...[ InkWell( // 一楼点击评论展开评论详情 - onTap: () => replyReply!(replyItem), + onTap: () => replyReply?.call(replyItem), onLongPress: () { feedBack(); showModalBottomSheet( @@ -534,7 +532,7 @@ class ReplyItemRow extends StatelessWidget { if (extraRow == 1) InkWell( // 一楼点击【共xx条回复】展开评论详情 - onTap: () => replyReply!(replyItem), + onTap: () => replyReply?.call(replyItem), child: Container( width: double.infinity, padding: const EdgeInsets.fromLTRB(8, 5, 8, 8), diff --git a/lib/pages/video/detail/reply/widgets/reply_item_grpc.dart b/lib/pages/video/detail/reply/widgets/reply_item_grpc.dart index 56625218..1f8f3940 100644 --- a/lib/pages/video/detail/reply/widgets/reply_item_grpc.dart +++ b/lib/pages/video/detail/reply/widgets/reply_item_grpc.dart @@ -10,7 +10,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; -import 'package:hive/hive.dart'; import 'package:PiliPalaX/common/widgets/network_img_layer.dart'; import 'package:PiliPalaX/models/common/reply_type.dart'; import 'package:PiliPalaX/pages/video/detail/index.dart'; @@ -20,8 +19,6 @@ import 'package:PiliPalaX/utils/url_utils.dart'; import 'package:PiliPalaX/utils/utils.dart'; import '../../../../../utils/app_scheme.dart'; -Box setting = GStorage.setting; - class ReplyItemGrpc extends StatelessWidget { const ReplyItemGrpc({ super.key, @@ -59,9 +56,7 @@ class ReplyItemGrpc extends StatelessWidget { // 点击整个评论区 评论详情/回复 onTap: () { feedBack(); - if (replyReply != null) { - replyReply!(replyItem, null); - } + replyReply?.call(replyItem, null, isTop); }, onLongPress: () { feedBack(); @@ -318,20 +313,8 @@ class ReplyItemGrpc extends StatelessWidget { showReplyRow) ...[ Padding( padding: const EdgeInsets.only(top: 5, bottom: 12), - child: ReplyItemRow( - upMid: upMid, - count: replyItem.count.toInt(), - replies: replyItem.replies, - replyControl: replyItem.replyControl, - // f_rpid: replyItem.rpid, - replyItem: replyItem, - replyReply: replyReply, - onDelete: (rpid) { - if (onDelete != null) { - onDelete!(rpid, replyItem.id.toInt()); - } - }, - getTag: getTag, + child: replyItemRow( + context: context, ), ), ], @@ -430,35 +413,9 @@ class ReplyItemGrpc extends StatelessWidget { ], ); } -} -// ignore: must_be_immutable -class ReplyItemRow extends StatelessWidget { - ReplyItemRow({ - super.key, - required this.count, - required this.replies, - required this.replyControl, - // this.f_rpid, - this.replyItem, - this.replyReply, - this.onDelete, - this.upMid, - this.getTag, - }); - final int count; - final List replies; - ReplyControl replyControl; - // int? f_rpid; - ReplyInfo? replyItem; - Function? replyReply; - final Function(dynamic rpid)? onDelete; - final dynamic upMid; - final Function? getTag; - - @override - Widget build(BuildContext context) { - final bool extraRow = replies.length < count; + Widget replyItemRow({required BuildContext context}) { + final bool extraRow = replyItem.replies.length < replyItem.count.toInt(); return Container( margin: const EdgeInsets.only(left: 42, right: 4, top: 0), child: Material( @@ -469,12 +426,12 @@ class ReplyItemRow extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (replies.isNotEmpty) - for (int i = 0; i < replies.length; i++) ...[ + if (replyItem.replies.isNotEmpty) + for (int i = 0; i < replyItem.replies.length; i++) ...[ InkWell( // 一楼点击评论展开评论详情 - onTap: () => - replyReply?.call(replyItem, replies[i].id.toInt()), + onTap: () => replyReply?.call( + replyItem, replyItem.replies[i].id.toInt(), isTop), onLongPress: () { feedBack(); showModalBottomSheet( @@ -483,8 +440,10 @@ class ReplyItemRow extends StatelessWidget { isScrollControlled: true, builder: (context) { return MorePanel( - item: replies[i], - onDelete: onDelete, + item: replyItem.replies[i], + onDelete: (rpid) { + onDelete?.call(rpid, replyItem.id.toInt()); + }, ); }, ); @@ -493,13 +452,17 @@ class ReplyItemRow extends StatelessWidget { width: double.infinity, padding: EdgeInsets.fromLTRB( 8, - i == 0 && (extraRow || replies.length > 1) ? 8 : 4, + i == 0 && (extraRow || replyItem.replies.length > 1) + ? 8 + : 4, 8, - i == 0 && (extraRow || replies.length > 1) ? 4 : 6, + i == 0 && (extraRow || replyItem.replies.length > 1) + ? 4 + : 6, ), child: Semantics( label: - '${replies[i].member.name} ${replies[i].content.message}', + '${replyItem.replies[i].member.name} ${replyItem.replies[i].content.message}', excludeSemantics: true, child: Text.rich( style: TextStyle( @@ -517,7 +480,7 @@ class ReplyItemRow extends StatelessWidget { TextSpan( children: [ TextSpan( - text: replies[i].member.name, + text: replyItem.replies[i].member.name, style: TextStyle( color: Theme.of(context) .colorScheme @@ -527,17 +490,18 @@ class ReplyItemRow extends StatelessWidget { recognizer: TapGestureRecognizer() ..onTap = () { feedBack(); - final String heroTag = - Utils.makeHeroTag(replies[i].member.mid); + final String heroTag = Utils.makeHeroTag( + replyItem.replies[i].member.mid); Get.toNamed( - '/member?mid=${replies[i].member.mid}', + '/member?mid=${replyItem.replies[i].member.mid}', arguments: { - 'face': replies[i].member.face, + 'face': + replyItem.replies[i].member.face, 'heroTag': heroTag }); }, ), - if (replies[i].mid == upMid) ...[ + if (replyItem.replies[i].mid == upMid) ...[ const TextSpan(text: ' '), const WidgetSpan( alignment: PlaceholderAlignment.top, @@ -551,15 +515,16 @@ class ReplyItemRow extends StatelessWidget { const TextSpan(text: ' '), ], TextSpan( - text: replies[i].root == replies[i].parent + text: replyItem.replies[i].root == + replyItem.replies[i].parent ? ': ' - : replies[i].mid == upMid + : replyItem.replies[i].mid == upMid ? '' : ' ', ), buildContent( context, - replies[i], + replyItem.replies[i], replyReply, replyItem, null, @@ -576,7 +541,7 @@ class ReplyItemRow extends StatelessWidget { if (extraRow) InkWell( // 一楼点击【共xx条回复】展开评论详情 - onTap: () => replyReply!(replyItem, null), + onTap: () => replyReply?.call(replyItem, null, isTop), child: Container( width: double.infinity, padding: const EdgeInsets.fromLTRB(8, 5, 8, 8), @@ -587,7 +552,7 @@ class ReplyItemRow extends StatelessWidget { Theme.of(context).textTheme.labelMedium!.fontSize, ), children: [ - if (replyControl.upReply) + if (replyItem.replyControl.upReply) TextSpan( text: 'UP主等人 ', style: TextStyle( @@ -596,7 +561,7 @@ class ReplyItemRow extends StatelessWidget { .onSurface .withOpacity(0.85))), TextSpan( - text: replyControl.subReplyEntryText, + text: replyItem.replyControl.subReplyEntryText, style: TextStyle( color: Theme.of(context) .colorScheme @@ -703,6 +668,7 @@ InlineSpan buildContent( if (jumpUrlKeysList.isNotEmpty) { patternStr += '|${jumpUrlKeysList.map(RegExp.escape).join('|')}'; } + patternStr += r'|https://b23\.tv/[a-zA-Z0-9]{7}'; final RegExp pattern = RegExp(patternStr); List matchedStrs = []; void addPlainTextSpan(str) { @@ -807,10 +773,24 @@ InlineSpan buildContent( : null, ), ); + } else if (matchStr.startsWith('https://b23.tv/')) { + spanChildren.add( + TextSpan( + text: ' $matchStr ', + style: TextStyle( + color: Theme.of(context).colorScheme.primary, + ), + recognizer: TapGestureRecognizer() + ..onTap = () => Get.toNamed( + '/webviewnew', + parameters: {'url': matchStr}, + ), + ), + ); } else { String appUrlSchema = ''; - final bool enableWordRe = setting.get(SettingBoxKey.enableWordRe, - defaultValue: false) as bool; + final bool enableWordRe = GStorage.setting + .get(SettingBoxKey.enableWordRe, defaultValue: false) as bool; if (content.url[matchStr] != null && !matchedStrs.contains(matchStr)) { appUrlSchema = content.url[matchStr]!.appUrlSchema; if (appUrlSchema.startsWith('bilibili://search') && !enableWordRe) { diff --git a/lib/pages/video/detail/reply_reply/view.dart b/lib/pages/video/detail/reply_reply/view.dart index 0d0f9943..b4adc900 100644 --- a/lib/pages/video/detail/reply_reply/view.dart +++ b/lib/pages/video/detail/reply_reply/view.dart @@ -27,6 +27,7 @@ class VideoReplyReplyPanel extends StatefulWidget { this.source, this.replyType, this.isDialogue = false, + this.isTop = false, super.key, }); // final dynamic rcount; @@ -38,6 +39,7 @@ class VideoReplyReplyPanel extends StatefulWidget { final String? source; final ReplyType? replyType; final bool isDialogue; + final bool isTop; @override State createState() => _VideoReplyReplyPanelState(); @@ -164,6 +166,7 @@ class _VideoReplyReplyPanelState extends State { _onReply(firstFloor!, -1); }, upMid: _videoReplyReplyController.upMid, + isTop: widget.isTop, ); } else if (index == 1) { return Divider( diff --git a/lib/pages/video/detail/view.dart b/lib/pages/video/detail/view.dart index 4b183795..7863a846 100644 --- a/lib/pages/video/detail/view.dart +++ b/lib/pages/video/detail/view.dart @@ -1311,7 +1311,7 @@ class _VideoDetailPageState extends State ); // 展示二级回复 - void replyReply(replyItem, id) { + void replyReply(replyItem, id, isTop) { videoDetailController.childKey.currentState?.showBottomSheet( (context) => VideoReplyReplyPanel( id: id, @@ -1321,6 +1321,7 @@ class _VideoDetailPageState extends State firstFloor: replyItem, replyType: ReplyType.video, source: 'videoDetail', + isTop: isTop, ), ); } diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index 197501ad..dfc6c4da 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -27,7 +27,7 @@ class Utils { static final Random random = Random(); static bool isStringNumeric(str) { - RegExp numericRegex = RegExp(r'^\d+$'); + RegExp numericRegex = RegExp(r'^[\d\.]+$'); return numericRegex.hasMatch(str.toString()); }