mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
opt: reply item
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -110,7 +110,7 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 查看二级评论
|
// 查看二级评论
|
||||||
void replyReply(replyItem, id) {
|
void replyReply(replyItem, id, isTop) {
|
||||||
int oid = replyItem.oid.toInt();
|
int oid = replyItem.oid.toInt();
|
||||||
int rpid = replyItem.id.toInt()!;
|
int rpid = replyItem.id.toInt()!;
|
||||||
Get.to(
|
Get.to(
|
||||||
@@ -124,6 +124,7 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
|||||||
source: 'dynamic',
|
source: 'dynamic',
|
||||||
replyType: ReplyType.values[replyType],
|
replyType: ReplyType.values[replyType],
|
||||||
firstFloor: replyItem,
|
firstFloor: replyItem,
|
||||||
|
isTop: isTop,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ class _HtmlRenderPageState extends State<HtmlRenderPage>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void replyReply(replyItem, id) {
|
void replyReply(replyItem, id, isTop) {
|
||||||
int oid = replyItem.oid.toInt();
|
int oid = replyItem.oid.toInt();
|
||||||
int rpid = replyItem.id.toInt();
|
int rpid = replyItem.id.toInt();
|
||||||
Get.to(
|
Get.to(
|
||||||
@@ -125,6 +125,7 @@ class _HtmlRenderPageState extends State<HtmlRenderPage>
|
|||||||
source: 'dynamic',
|
source: 'dynamic',
|
||||||
replyType: ReplyType.values[type],
|
replyType: ReplyType.values[type],
|
||||||
firstFloor: replyItem,
|
firstFloor: replyItem,
|
||||||
|
isTop: isTop,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1321,18 +1321,13 @@ class VideoDetailController extends GetxController
|
|||||||
.primary,
|
.primary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(
|
Icon(
|
||||||
height: MediaQuery
|
Icons
|
||||||
.textScalerOf(
|
.keyboard_arrow_right,
|
||||||
context)
|
size: 22,
|
||||||
.scale(14),
|
color: Theme.of(context)
|
||||||
child: Icon(
|
.colorScheme
|
||||||
Icons
|
.primary,
|
||||||
.keyboard_arrow_right,
|
|
||||||
color: Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.primary,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -1387,19 +1382,14 @@ class VideoDetailController extends GetxController
|
|||||||
.primary,
|
.primary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(
|
Icon(
|
||||||
height: MediaQuery
|
Icons
|
||||||
.textScalerOf(
|
.keyboard_arrow_right,
|
||||||
context)
|
size: 22,
|
||||||
.scale(14),
|
color: Theme.of(context)
|
||||||
child: Icon(
|
.colorScheme
|
||||||
Icons
|
.primary,
|
||||||
.keyboard_arrow_right,
|
),
|
||||||
color: Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.primary,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -48,9 +48,7 @@ class ReplyItem extends StatelessWidget {
|
|||||||
// 点击整个评论区 评论详情/回复
|
// 点击整个评论区 评论详情/回复
|
||||||
onTap: () {
|
onTap: () {
|
||||||
feedBack();
|
feedBack();
|
||||||
if (replyReply != null) {
|
replyReply?.call(replyItem);
|
||||||
replyReply!(replyItem);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onLongPress: () {
|
onLongPress: () {
|
||||||
feedBack();
|
feedBack();
|
||||||
@@ -434,7 +432,7 @@ class ReplyItemRow extends StatelessWidget {
|
|||||||
for (int i = 0; i < replies!.length; i++) ...[
|
for (int i = 0; i < replies!.length; i++) ...[
|
||||||
InkWell(
|
InkWell(
|
||||||
// 一楼点击评论展开评论详情
|
// 一楼点击评论展开评论详情
|
||||||
onTap: () => replyReply!(replyItem),
|
onTap: () => replyReply?.call(replyItem),
|
||||||
onLongPress: () {
|
onLongPress: () {
|
||||||
feedBack();
|
feedBack();
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
@@ -534,7 +532,7 @@ class ReplyItemRow extends StatelessWidget {
|
|||||||
if (extraRow == 1)
|
if (extraRow == 1)
|
||||||
InkWell(
|
InkWell(
|
||||||
// 一楼点击【共xx条回复】展开评论详情
|
// 一楼点击【共xx条回复】展开评论详情
|
||||||
onTap: () => replyReply!(replyItem),
|
onTap: () => replyReply?.call(replyItem),
|
||||||
child: Container(
|
child: Container(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
padding: const EdgeInsets.fromLTRB(8, 5, 8, 8),
|
padding: const EdgeInsets.fromLTRB(8, 5, 8, 8),
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:hive/hive.dart';
|
|
||||||
import 'package:PiliPalaX/common/widgets/network_img_layer.dart';
|
import 'package:PiliPalaX/common/widgets/network_img_layer.dart';
|
||||||
import 'package:PiliPalaX/models/common/reply_type.dart';
|
import 'package:PiliPalaX/models/common/reply_type.dart';
|
||||||
import 'package:PiliPalaX/pages/video/detail/index.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 'package:PiliPalaX/utils/utils.dart';
|
||||||
import '../../../../../utils/app_scheme.dart';
|
import '../../../../../utils/app_scheme.dart';
|
||||||
|
|
||||||
Box setting = GStorage.setting;
|
|
||||||
|
|
||||||
class ReplyItemGrpc extends StatelessWidget {
|
class ReplyItemGrpc extends StatelessWidget {
|
||||||
const ReplyItemGrpc({
|
const ReplyItemGrpc({
|
||||||
super.key,
|
super.key,
|
||||||
@@ -59,9 +56,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
// 点击整个评论区 评论详情/回复
|
// 点击整个评论区 评论详情/回复
|
||||||
onTap: () {
|
onTap: () {
|
||||||
feedBack();
|
feedBack();
|
||||||
if (replyReply != null) {
|
replyReply?.call(replyItem, null, isTop);
|
||||||
replyReply!(replyItem, null);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onLongPress: () {
|
onLongPress: () {
|
||||||
feedBack();
|
feedBack();
|
||||||
@@ -318,20 +313,8 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
showReplyRow) ...[
|
showReplyRow) ...[
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 5, bottom: 12),
|
padding: const EdgeInsets.only(top: 5, bottom: 12),
|
||||||
child: ReplyItemRow(
|
child: replyItemRow(
|
||||||
upMid: upMid,
|
context: context,
|
||||||
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,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -430,35 +413,9 @@ class ReplyItemGrpc extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// ignore: must_be_immutable
|
Widget replyItemRow({required BuildContext context}) {
|
||||||
class ReplyItemRow extends StatelessWidget {
|
final bool extraRow = replyItem.replies.length < replyItem.count.toInt();
|
||||||
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<ReplyInfo> 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;
|
|
||||||
return Container(
|
return Container(
|
||||||
margin: const EdgeInsets.only(left: 42, right: 4, top: 0),
|
margin: const EdgeInsets.only(left: 42, right: 4, top: 0),
|
||||||
child: Material(
|
child: Material(
|
||||||
@@ -469,12 +426,12 @@ class ReplyItemRow extends StatelessWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
if (replies.isNotEmpty)
|
if (replyItem.replies.isNotEmpty)
|
||||||
for (int i = 0; i < replies.length; i++) ...[
|
for (int i = 0; i < replyItem.replies.length; i++) ...[
|
||||||
InkWell(
|
InkWell(
|
||||||
// 一楼点击评论展开评论详情
|
// 一楼点击评论展开评论详情
|
||||||
onTap: () =>
|
onTap: () => replyReply?.call(
|
||||||
replyReply?.call(replyItem, replies[i].id.toInt()),
|
replyItem, replyItem.replies[i].id.toInt(), isTop),
|
||||||
onLongPress: () {
|
onLongPress: () {
|
||||||
feedBack();
|
feedBack();
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
@@ -483,8 +440,10 @@ class ReplyItemRow extends StatelessWidget {
|
|||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return MorePanel(
|
return MorePanel(
|
||||||
item: replies[i],
|
item: replyItem.replies[i],
|
||||||
onDelete: onDelete,
|
onDelete: (rpid) {
|
||||||
|
onDelete?.call(rpid, replyItem.id.toInt());
|
||||||
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -493,13 +452,17 @@ class ReplyItemRow extends StatelessWidget {
|
|||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
padding: EdgeInsets.fromLTRB(
|
padding: EdgeInsets.fromLTRB(
|
||||||
8,
|
8,
|
||||||
i == 0 && (extraRow || replies.length > 1) ? 8 : 4,
|
i == 0 && (extraRow || replyItem.replies.length > 1)
|
||||||
|
? 8
|
||||||
|
: 4,
|
||||||
8,
|
8,
|
||||||
i == 0 && (extraRow || replies.length > 1) ? 4 : 6,
|
i == 0 && (extraRow || replyItem.replies.length > 1)
|
||||||
|
? 4
|
||||||
|
: 6,
|
||||||
),
|
),
|
||||||
child: Semantics(
|
child: Semantics(
|
||||||
label:
|
label:
|
||||||
'${replies[i].member.name} ${replies[i].content.message}',
|
'${replyItem.replies[i].member.name} ${replyItem.replies[i].content.message}',
|
||||||
excludeSemantics: true,
|
excludeSemantics: true,
|
||||||
child: Text.rich(
|
child: Text.rich(
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
@@ -517,7 +480,7 @@ class ReplyItemRow extends StatelessWidget {
|
|||||||
TextSpan(
|
TextSpan(
|
||||||
children: [
|
children: [
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: replies[i].member.name,
|
text: replyItem.replies[i].member.name,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Theme.of(context)
|
color: Theme.of(context)
|
||||||
.colorScheme
|
.colorScheme
|
||||||
@@ -527,17 +490,18 @@ class ReplyItemRow extends StatelessWidget {
|
|||||||
recognizer: TapGestureRecognizer()
|
recognizer: TapGestureRecognizer()
|
||||||
..onTap = () {
|
..onTap = () {
|
||||||
feedBack();
|
feedBack();
|
||||||
final String heroTag =
|
final String heroTag = Utils.makeHeroTag(
|
||||||
Utils.makeHeroTag(replies[i].member.mid);
|
replyItem.replies[i].member.mid);
|
||||||
Get.toNamed(
|
Get.toNamed(
|
||||||
'/member?mid=${replies[i].member.mid}',
|
'/member?mid=${replyItem.replies[i].member.mid}',
|
||||||
arguments: {
|
arguments: {
|
||||||
'face': replies[i].member.face,
|
'face':
|
||||||
|
replyItem.replies[i].member.face,
|
||||||
'heroTag': heroTag
|
'heroTag': heroTag
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
if (replies[i].mid == upMid) ...[
|
if (replyItem.replies[i].mid == upMid) ...[
|
||||||
const TextSpan(text: ' '),
|
const TextSpan(text: ' '),
|
||||||
const WidgetSpan(
|
const WidgetSpan(
|
||||||
alignment: PlaceholderAlignment.top,
|
alignment: PlaceholderAlignment.top,
|
||||||
@@ -551,15 +515,16 @@ class ReplyItemRow extends StatelessWidget {
|
|||||||
const TextSpan(text: ' '),
|
const TextSpan(text: ' '),
|
||||||
],
|
],
|
||||||
TextSpan(
|
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(
|
buildContent(
|
||||||
context,
|
context,
|
||||||
replies[i],
|
replyItem.replies[i],
|
||||||
replyReply,
|
replyReply,
|
||||||
replyItem,
|
replyItem,
|
||||||
null,
|
null,
|
||||||
@@ -576,7 +541,7 @@ class ReplyItemRow extends StatelessWidget {
|
|||||||
if (extraRow)
|
if (extraRow)
|
||||||
InkWell(
|
InkWell(
|
||||||
// 一楼点击【共xx条回复】展开评论详情
|
// 一楼点击【共xx条回复】展开评论详情
|
||||||
onTap: () => replyReply!(replyItem, null),
|
onTap: () => replyReply?.call(replyItem, null, isTop),
|
||||||
child: Container(
|
child: Container(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
padding: const EdgeInsets.fromLTRB(8, 5, 8, 8),
|
padding: const EdgeInsets.fromLTRB(8, 5, 8, 8),
|
||||||
@@ -587,7 +552,7 @@ class ReplyItemRow extends StatelessWidget {
|
|||||||
Theme.of(context).textTheme.labelMedium!.fontSize,
|
Theme.of(context).textTheme.labelMedium!.fontSize,
|
||||||
),
|
),
|
||||||
children: [
|
children: [
|
||||||
if (replyControl.upReply)
|
if (replyItem.replyControl.upReply)
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: 'UP主等人 ',
|
text: 'UP主等人 ',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
@@ -596,7 +561,7 @@ class ReplyItemRow extends StatelessWidget {
|
|||||||
.onSurface
|
.onSurface
|
||||||
.withOpacity(0.85))),
|
.withOpacity(0.85))),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: replyControl.subReplyEntryText,
|
text: replyItem.replyControl.subReplyEntryText,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Theme.of(context)
|
color: Theme.of(context)
|
||||||
.colorScheme
|
.colorScheme
|
||||||
@@ -703,6 +668,7 @@ InlineSpan buildContent(
|
|||||||
if (jumpUrlKeysList.isNotEmpty) {
|
if (jumpUrlKeysList.isNotEmpty) {
|
||||||
patternStr += '|${jumpUrlKeysList.map(RegExp.escape).join('|')}';
|
patternStr += '|${jumpUrlKeysList.map(RegExp.escape).join('|')}';
|
||||||
}
|
}
|
||||||
|
patternStr += r'|https://b23\.tv/[a-zA-Z0-9]{7}';
|
||||||
final RegExp pattern = RegExp(patternStr);
|
final RegExp pattern = RegExp(patternStr);
|
||||||
List<String> matchedStrs = [];
|
List<String> matchedStrs = [];
|
||||||
void addPlainTextSpan(str) {
|
void addPlainTextSpan(str) {
|
||||||
@@ -807,10 +773,24 @@ InlineSpan buildContent(
|
|||||||
: null,
|
: 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 {
|
} else {
|
||||||
String appUrlSchema = '';
|
String appUrlSchema = '';
|
||||||
final bool enableWordRe = setting.get(SettingBoxKey.enableWordRe,
|
final bool enableWordRe = GStorage.setting
|
||||||
defaultValue: false) as bool;
|
.get(SettingBoxKey.enableWordRe, defaultValue: false) as bool;
|
||||||
if (content.url[matchStr] != null && !matchedStrs.contains(matchStr)) {
|
if (content.url[matchStr] != null && !matchedStrs.contains(matchStr)) {
|
||||||
appUrlSchema = content.url[matchStr]!.appUrlSchema;
|
appUrlSchema = content.url[matchStr]!.appUrlSchema;
|
||||||
if (appUrlSchema.startsWith('bilibili://search') && !enableWordRe) {
|
if (appUrlSchema.startsWith('bilibili://search') && !enableWordRe) {
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ class VideoReplyReplyPanel extends StatefulWidget {
|
|||||||
this.source,
|
this.source,
|
||||||
this.replyType,
|
this.replyType,
|
||||||
this.isDialogue = false,
|
this.isDialogue = false,
|
||||||
|
this.isTop = false,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
// final dynamic rcount;
|
// final dynamic rcount;
|
||||||
@@ -38,6 +39,7 @@ class VideoReplyReplyPanel extends StatefulWidget {
|
|||||||
final String? source;
|
final String? source;
|
||||||
final ReplyType? replyType;
|
final ReplyType? replyType;
|
||||||
final bool isDialogue;
|
final bool isDialogue;
|
||||||
|
final bool isTop;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<VideoReplyReplyPanel> createState() => _VideoReplyReplyPanelState();
|
State<VideoReplyReplyPanel> createState() => _VideoReplyReplyPanelState();
|
||||||
@@ -164,6 +166,7 @@ class _VideoReplyReplyPanelState extends State<VideoReplyReplyPanel> {
|
|||||||
_onReply(firstFloor!, -1);
|
_onReply(firstFloor!, -1);
|
||||||
},
|
},
|
||||||
upMid: _videoReplyReplyController.upMid,
|
upMid: _videoReplyReplyController.upMid,
|
||||||
|
isTop: widget.isTop,
|
||||||
);
|
);
|
||||||
} else if (index == 1) {
|
} else if (index == 1) {
|
||||||
return Divider(
|
return Divider(
|
||||||
|
|||||||
@@ -1311,7 +1311,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
|||||||
);
|
);
|
||||||
|
|
||||||
// 展示二级回复
|
// 展示二级回复
|
||||||
void replyReply(replyItem, id) {
|
void replyReply(replyItem, id, isTop) {
|
||||||
videoDetailController.childKey.currentState?.showBottomSheet(
|
videoDetailController.childKey.currentState?.showBottomSheet(
|
||||||
(context) => VideoReplyReplyPanel(
|
(context) => VideoReplyReplyPanel(
|
||||||
id: id,
|
id: id,
|
||||||
@@ -1321,6 +1321,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
|||||||
firstFloor: replyItem,
|
firstFloor: replyItem,
|
||||||
replyType: ReplyType.video,
|
replyType: ReplyType.video,
|
||||||
source: 'videoDetail',
|
source: 'videoDetail',
|
||||||
|
isTop: isTop,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class Utils {
|
|||||||
static final Random random = Random();
|
static final Random random = Random();
|
||||||
|
|
||||||
static bool isStringNumeric(str) {
|
static bool isStringNumeric(str) {
|
||||||
RegExp numericRegex = RegExp(r'^\d+$');
|
RegExp numericRegex = RegExp(r'^[\d\.]+$');
|
||||||
return numericRegex.hasMatch(str.toString());
|
return numericRegex.hasMatch(str.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user