diff --git a/lib/ui/views/TIMUIKitGroupProfile/widgets/tim_uikit_group_name_card.dart b/lib/ui/views/TIMUIKitGroupProfile/widgets/tim_uikit_group_name_card.dart index a701560..0e8f0ca 100644 --- a/lib/ui/views/TIMUIKitGroupProfile/widgets/tim_uikit_group_name_card.dart +++ b/lib/ui/views/TIMUIKitGroupProfile/widgets/tim_uikit_group_name_card.dart @@ -22,6 +22,8 @@ class GroupProfileNameCard extends StatefulWidget { class GroupProfileNameCardState extends TIMUIKitState{ final TextEditingController controller = TextEditingController(); String? nameCard; + String? validationMessage; + bool isValid = true; @override Widget tuiBuild(BuildContext context, TUIKitBuildValue value) { @@ -34,6 +36,11 @@ class GroupProfileNameCardState extends TIMUIKitState{ } nameCard = model.getSelfNameCard(); controller.text = nameCard ?? ""; + + // 初始化验证状态 + if (nameCard != null && nameCard!.isNotEmpty) { + _validateNameCardRealTime(nameCard!); + } return Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), @@ -46,26 +53,7 @@ class GroupProfileNameCardState extends TIMUIKitState{ child: GestureDetector( onTap: () async { if (!isDesktopScreen) { - TextInputBottomSheet.showTextInputBottomSheet( - context: context, - title: TIM_t("修改我的群昵称"), - tips: TIM_t("仅限中文、字母、数字和下划线,2-20个字"), - onSubmitted: (String nameCard) async { - final text = nameCard.trim(); - // 验证输入格式 - if (_validateNameCard(text)) { - model.setNameCard(text); - } else { - // 显示错误提示 - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(TIM_t("仅限中文、字母、数字和下划线,2-20个字")), - backgroundColor: Colors.red, - ), - ); - } - }, - theme: theme); + _showNameCardInputBottomSheet(context, theme, model); } }, child: Column( @@ -103,8 +91,11 @@ class GroupProfileNameCardState extends TIMUIKitState{ ), if (isDesktopScreen) Text( - TIM_t("仅限中文、字母、数字和下划线,2-20个字"), - style: TextStyle(color: theme.weakTextColor, fontSize: 12), + validationMessage ?? TIM_t("仅限中文、字母、数字和下划线,2-16个字"), + style: TextStyle( + color: isValid ? theme.weakTextColor : Colors.red, + fontSize: 12 + ), ), if (isDesktopScreen) Container( @@ -114,6 +105,12 @@ class GroupProfileNameCardState extends TIMUIKitState{ minLines: 1, controller: controller, maxLines: 1, + onChanged: (text) { + final trimmedText = text.trim(); + setState(() { + _validateNameCardRealTime(trimmedText); + }); + }, onSubmitted: (text) { final trimmedText = text.trim(); // 验证输入格式 @@ -123,7 +120,7 @@ class GroupProfileNameCardState extends TIMUIKitState{ // 显示错误提示 ScaffoldMessenger.of(context).showSnackBar( SnackBar( - content: Text(TIM_t("仅限中文、字母、数字和下划线,2-20个字")), + content: Text(TIM_t("仅限中文、字母、数字和下划线,2-16个字")), backgroundColor: Colors.red, ), ); @@ -167,14 +164,14 @@ class GroupProfileNameCardState extends TIMUIKitState{ } /// 验证群昵称格式 - /// 仅限中文、字母、数字和下划线,2-20个字 + /// 仅限中文、字母、数字和下划线,2-16个字 bool _validateNameCard(String text) { if (text.isEmpty) { return false; } - // 检查长度:2-20个字符 - if (text.length < 2 || text.length > 20) { + // 检查长度:2-16个字符 + if (text.length < 2 || text.length > 16) { return false; } @@ -182,4 +179,251 @@ class GroupProfileNameCardState extends TIMUIKitState{ final RegExp regex = RegExp(r'^[\u4e00-\u9fa5a-zA-Z0-9_]+$'); return regex.hasMatch(text); } + + /// 实时验证群昵称格式并设置提示信息 + void _validateNameCardRealTime(String text) { + if (text.isEmpty) { + isValid = false; + validationMessage = TIM_t("昵称不能为空"); + return; + } + + if (text.length < 2) { + isValid = false; + validationMessage = TIM_t("昵称至少需要2个字符"); + return; + } + + if (text.length > 16) { + isValid = false; + validationMessage = TIM_t("昵称不能超过16个字符"); + return; + } + + // 检查字符类型:仅限中文、字母、数字和下划线 + final RegExp regex = RegExp(r'^[\u4e00-\u9fa5a-zA-Z0-9_]+$'); + if (!regex.hasMatch(text)) { + isValid = false; + validationMessage = TIM_t("仅限中文、字母、数字和下划线"); + return; + } + + // 验证通过 + isValid = true; + validationMessage = TIM_t("昵称格式正确"); + } + + /// 显示带有实时验证的群昵称输入底部弹窗 + void _showNameCardInputBottomSheet(BuildContext context, TUITheme theme, model) { + TextEditingController modalController = TextEditingController(); + modalController.text = nameCard ?? ""; + + showModalBottomSheet( + isScrollControlled: true, + context: context, + builder: (BuildContext context) { + return _NameCardInputWidget( + controller: modalController, + theme: theme, + model: model, + initialNameCard: nameCard, + ); + }, + ); + } } + +class _NameCardInputWidget extends StatefulWidget { + final TextEditingController controller; + final TUITheme theme; + final model; + final String? initialNameCard; + + const _NameCardInputWidget({ + required this.controller, + required this.theme, + required this.model, + this.initialNameCard, + }); + + @override + _NameCardInputWidgetState createState() => _NameCardInputWidgetState(); +} + +class _NameCardInputWidgetState extends State<_NameCardInputWidget> { + String? modalValidationMessage; + bool modalIsValid = true; + + @override + void initState() { + super.initState(); + // 初始化验证状态 + if (widget.initialNameCard != null && widget.initialNameCard!.isNotEmpty) { + _validateModalInput(widget.initialNameCard!); + } + } + + void _validateModalInput(String text) { + setState(() { + if (text.isEmpty) { + modalIsValid = false; + modalValidationMessage = TIM_t("昵称不能为空"); + } else if (text.length < 2) { + modalIsValid = false; + modalValidationMessage = TIM_t("昵称至少需要2个字符"); + } else if (text.length > 16) { + modalIsValid = false; + modalValidationMessage = TIM_t("昵称不能超过16个字符"); + } else { + final RegExp regex = RegExp(r'^[\u4e00-\u9fa5a-zA-Z0-9_]+$'); + if (!regex.hasMatch(text)) { + modalIsValid = false; + modalValidationMessage = TIM_t("仅限中文、字母、数字和下划线"); + } else { + modalIsValid = true; + modalValidationMessage = TIM_t("昵称格式正确"); + } + } + }); + } + + bool _validateNameCard(String text) { + if (text.isEmpty) { + return false; + } + + // 检查长度:2-16个字符 + if (text.length < 2 || text.length > 16) { + return false; + } + + // 检查字符类型:仅限中文、字母、数字和下划线 + final RegExp regex = RegExp(r'^[\u4e00-\u9fa5a-zA-Z0-9_]+$'); + return regex.hasMatch(text); + } + + @override + Widget build(BuildContext context) { + return SingleChildScrollView( + child: Container( + padding: EdgeInsets.only( + top: 16, + left: 16, + right: 16, + bottom: MediaQuery.of(context).viewInsets.bottom + 30, + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(bottom: 16), + child: Text( + TIM_t("修改我的群昵称"), + style: const TextStyle(fontWeight: FontWeight.w500, fontSize: 16), + ), + ), + Divider(height: 2, color: widget.theme.weakDividerColor), + TextField( + controller: widget.controller, + autofocus: true, + onChanged: (text) { + final trimmedText = text.trim(); + _validateModalInput(trimmedText); + }, + onSubmitted: (text) { + final trimmedText = text.trim(); + if (_validateNameCard(trimmedText)) { + widget.model.setNameCard(trimmedText); + Navigator.pop(context); + } else { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(TIM_t("仅限中文、字母、数字和下划线,2-16个字")), + backgroundColor: Colors.red, + ), + ); + } + }, + ), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + padding: const EdgeInsets.symmetric(vertical: 5), + height: 40, + child: Text( + modalValidationMessage ?? TIM_t("仅限中文、字母、数字和下划线,2-16个字"), + style: TextStyle( + color: modalIsValid ? Colors.grey : Colors.red, + fontSize: 12, + ), + ), + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Container( + margin: const EdgeInsets.only(right: 10), + child: ElevatedButton( + style: ButtonStyle( + backgroundColor: MaterialStateProperty.all(widget.theme.wideBackgroundColor), + shape: MaterialStateProperty.all( + RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)), + ), + ), + onPressed: () { + Navigator.pop(context); + }, + child: Text( + TIM_t("取消"), + style: TextStyle(color: widget.theme.darkTextColor), + ), + ), + ), + ), + Expanded( + child: ElevatedButton( + style: ButtonStyle( + shape: MaterialStateProperty.all( + RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)), + ), + ), + onPressed: () { + final text = widget.controller.text.trim(); + if (_validateNameCard(text)) { + widget.model.setNameCard(text); + Navigator.pop(context); + } else { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: Text(TIM_t("输入错误")), + content: Text(TIM_t("仅限中文、字母、数字和下划线,2-16个字")), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text(TIM_t("确定")), + ), + ], + ); + }, + ); + } + }, + child: Text(TIM_t("确定")), + ), + ), + ], + ), + ], + ), + ), + ); + } + }