refactor(group): 优化群昵称修改流程的用户体验
This commit is contained in:
parent
d4ffbf2165
commit
498bdb7f5d
|
|
@ -22,6 +22,8 @@ class GroupProfileNameCard extends StatefulWidget {
|
|||
class GroupProfileNameCardState extends TIMUIKitState<GroupProfileNameCard>{
|
||||
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<GroupProfileNameCard>{
|
|||
}
|
||||
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<GroupProfileNameCard>{
|
|||
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<GroupProfileNameCard>{
|
|||
),
|
||||
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<GroupProfileNameCard>{
|
|||
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<GroupProfileNameCard>{
|
|||
// 显示错误提示
|
||||
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<GroupProfileNameCard>{
|
|||
}
|
||||
|
||||
/// 验证群昵称格式
|
||||
/// 仅限中文、字母、数字和下划线,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<GroupProfileNameCard>{
|
|||
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("确定")),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue