feat(group): 群消息提示中新增姓名高亮显示及点击跳转用户详情功能
This commit is contained in:
parent
e427047752
commit
d4ffbf2165
|
|
@ -30,6 +30,26 @@ import 'package:tencent_cloud_chat_uikit/ui/utils/common_utils.dart';
|
|||
import 'package:tencent_cloud_chat_uikit/ui/utils/logger.dart';
|
||||
import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
|
||||
|
||||
/// 群提示消息文本片段数据类
|
||||
class TipsTextSegment {
|
||||
final String text;
|
||||
final String? userID;
|
||||
final bool isClickable;
|
||||
|
||||
TipsTextSegment({
|
||||
required this.text,
|
||||
this.userID,
|
||||
required this.isClickable,
|
||||
});
|
||||
}
|
||||
|
||||
/// 群提示消息富文本数据类
|
||||
class GroupTipsRichTextData {
|
||||
final List<TipsTextSegment> segments;
|
||||
|
||||
GroupTipsRichTextData({required this.segments});
|
||||
}
|
||||
|
||||
class MessageUtils {
|
||||
// 判断CallingData的方式和Trtc的方法一致
|
||||
static isCallingData(String data) {
|
||||
|
|
@ -241,6 +261,251 @@ class MessageUtils {
|
|||
return displayMessage;
|
||||
}
|
||||
|
||||
/// 生成群提示消息的富文本数据,支持点击用户名跳转
|
||||
static Future<GroupTipsRichTextData> groupTipsMessageRichText(
|
||||
V2TimGroupTipsElem groupTipsElem, List<V2TimGroupMemberFullInfo?> groupMemberList) async {
|
||||
final operationType = groupTipsElem.type;
|
||||
final operationMember = groupTipsElem.opMember;
|
||||
final memberList = groupTipsElem.memberList;
|
||||
final opUserNickName = _getOpUserNick(operationMember);
|
||||
|
||||
// 获取当前登录用户ID
|
||||
final currentUserID = (await TencentImSDKPlugin.v2TIMManager.getLoginUser()).data;
|
||||
|
||||
List<TipsTextSegment> segments = [];
|
||||
|
||||
switch (operationType) {
|
||||
case GroupTipsElemType.V2TIM_GROUP_TIPS_TYPE_GROUP_INFO_CHANGE:
|
||||
final userName = opUserNickName ?? "";
|
||||
final userID = operationMember?.userID;
|
||||
final isCurrentUser = userID == currentUserID;
|
||||
final displayName = isCurrentUser ? "你" : userName;
|
||||
|
||||
if (userID != null && !isCurrentUser) {
|
||||
segments.add(TipsTextSegment(text: displayName, userID: userID, isClickable: true));
|
||||
} else {
|
||||
segments.add(TipsTextSegment(text: displayName, isClickable: false));
|
||||
}
|
||||
|
||||
final groupChangeInfoList = groupTipsElem.groupChangeInfoList ?? [];
|
||||
String changedInfoString = "";
|
||||
bool changedValue = false;
|
||||
for (V2TimGroupChangeInfo? element in groupChangeInfoList) {
|
||||
final newText = await _getGroupChangeType(element!, groupMemberList);
|
||||
changedInfoString += (changedInfoString.isEmpty ? "" : " / ") + newText;
|
||||
changedValue = element!.boolValue ?? false;
|
||||
}
|
||||
if (changedInfoString.isEmpty) {
|
||||
changedInfoString = TIM_t("群资料");
|
||||
}
|
||||
if (changedInfoString == TIM_t("全员禁言状态")) {
|
||||
changedInfoString = TIM_t("全员禁言");
|
||||
segments.add(TipsTextSegment(text: changedValue == false ? " 取消" + changedInfoString : " 开启" + changedInfoString, isClickable: false));
|
||||
} else {
|
||||
segments.add(TipsTextSegment(text: "修改" + changedInfoString, isClickable: false));
|
||||
}
|
||||
break;
|
||||
|
||||
case GroupTipsElemType.V2TIM_GROUP_TIPS_TYPE_QUIT:
|
||||
final userName = opUserNickName ?? "";
|
||||
final userID = operationMember?.userID;
|
||||
final isCurrentUser = userID == currentUserID;
|
||||
final displayName = isCurrentUser ? "你" : userName;
|
||||
|
||||
if (userID != null && !isCurrentUser) {
|
||||
segments.add(TipsTextSegment(text: displayName, userID: userID, isClickable: true));
|
||||
} else {
|
||||
segments.add(TipsTextSegment(text: displayName, isClickable: false));
|
||||
}
|
||||
segments.add(TipsTextSegment(text: "退出群聊", isClickable: false));
|
||||
break;
|
||||
|
||||
case GroupTipsElemType.V2TIM_GROUP_TIPS_TYPE_INVITE:
|
||||
final inviteUser = _getOpUserNick(operationMember);
|
||||
final opUserID = operationMember?.userID;
|
||||
final isOpCurrentUser = opUserID == currentUserID;
|
||||
final opDisplayName = isOpCurrentUser ? "你" : (inviteUser ?? "");
|
||||
|
||||
if (opUserID != null && !isOpCurrentUser) {
|
||||
segments.add(TipsTextSegment(text: opDisplayName, userID: opUserID, isClickable: true));
|
||||
} else {
|
||||
segments.add(TipsTextSegment(text: opDisplayName, isClickable: false));
|
||||
}
|
||||
segments.add(TipsTextSegment(text: "邀请", isClickable: false));
|
||||
|
||||
// 添加被邀请的用户
|
||||
for (int i = 0; i < memberList!.length; i++) {
|
||||
final member = memberList[i]!;
|
||||
final memberName = _getMemberNickName(member);
|
||||
final memberUserID = member.userID;
|
||||
final isMemberCurrentUser = memberUserID == currentUserID;
|
||||
final memberDisplayName = isMemberCurrentUser ? "你" : memberName!;
|
||||
|
||||
if (memberUserID != null && !isMemberCurrentUser) {
|
||||
segments.add(TipsTextSegment(text: memberDisplayName, userID: memberUserID, isClickable: true));
|
||||
} else {
|
||||
segments.add(TipsTextSegment(text: memberDisplayName, isClickable: false));
|
||||
}
|
||||
if (i < memberList.length - 1) {
|
||||
segments.add(TipsTextSegment(text: "、", isClickable: false));
|
||||
}
|
||||
}
|
||||
segments.add(TipsTextSegment(text: "加入群组", isClickable: false));
|
||||
break;
|
||||
|
||||
case GroupTipsElemType.V2TIM_GROUP_TIPS_TYPE_KICKED:
|
||||
final kickUser = _getOpUserNick(operationMember);
|
||||
final opUserID = operationMember?.userID;
|
||||
final isOpCurrentUser = opUserID == currentUserID;
|
||||
final opDisplayName = isOpCurrentUser ? "你" : (kickUser ?? "");
|
||||
|
||||
if (opUserID != null && !isOpCurrentUser) {
|
||||
segments.add(TipsTextSegment(text: opDisplayName, userID: opUserID, isClickable: true));
|
||||
} else {
|
||||
segments.add(TipsTextSegment(text: opDisplayName, isClickable: false));
|
||||
}
|
||||
segments.add(TipsTextSegment(text: "将", isClickable: false));
|
||||
|
||||
// 添加被踢的用户
|
||||
for (int i = 0; i < memberList!.length; i++) {
|
||||
final member = memberList[i]!;
|
||||
final memberName = _getMemberNickName(member);
|
||||
final memberUserID = member.userID;
|
||||
final isMemberCurrentUser = memberUserID == currentUserID;
|
||||
final memberDisplayName = isMemberCurrentUser ? "你" : memberName!;
|
||||
|
||||
if (memberUserID != null && !isMemberCurrentUser) {
|
||||
segments.add(TipsTextSegment(text: memberDisplayName, userID: memberUserID, isClickable: true));
|
||||
} else {
|
||||
segments.add(TipsTextSegment(text: memberDisplayName, isClickable: false));
|
||||
}
|
||||
if (i < memberList.length - 1) {
|
||||
segments.add(TipsTextSegment(text: "、", isClickable: false));
|
||||
}
|
||||
}
|
||||
segments.add(TipsTextSegment(text: "踢出群组", isClickable: false));
|
||||
break;
|
||||
|
||||
case GroupTipsElemType.V2TIM_GROUP_TIPS_TYPE_JOIN:
|
||||
segments.add(TipsTextSegment(text: "用户", isClickable: false));
|
||||
// 添加加入的用户
|
||||
for (int i = 0; i < memberList!.length; i++) {
|
||||
final member = memberList[i]!;
|
||||
final memberName = _getMemberNickName(member);
|
||||
final memberUserID = member.userID;
|
||||
final isMemberCurrentUser = memberUserID == currentUserID;
|
||||
final memberDisplayName = isMemberCurrentUser ? "你" : memberName!;
|
||||
|
||||
if (memberUserID != null && !isMemberCurrentUser) {
|
||||
segments.add(TipsTextSegment(text: memberDisplayName, userID: memberUserID, isClickable: true));
|
||||
} else {
|
||||
segments.add(TipsTextSegment(text: memberDisplayName, isClickable: false));
|
||||
}
|
||||
if (i < memberList.length - 1) {
|
||||
segments.add(TipsTextSegment(text: "、", isClickable: false));
|
||||
}
|
||||
}
|
||||
segments.add(TipsTextSegment(text: "加入了群聊", isClickable: false));
|
||||
break;
|
||||
|
||||
case GroupTipsElemType.V2TIM_GROUP_TIPS_TYPE_MEMBER_INFO_CHANGE:
|
||||
for (int i = 0; i < groupTipsElem.memberList!.length; i++) {
|
||||
final member = groupTipsElem.memberList![i]!;
|
||||
final changedMember =
|
||||
groupTipsElem.memberChangeInfoList!.firstWhere((element) => element!.userID == member.userID);
|
||||
final isMute = changedMember!.muteTime != 0;
|
||||
final memberName = _getMemberNickName(member);
|
||||
final memberUserID = member.userID;
|
||||
final isMemberCurrentUser = memberUserID == currentUserID;
|
||||
final memberDisplayName = isMemberCurrentUser ? "你" : memberName!;
|
||||
|
||||
if (memberUserID != null && !isMemberCurrentUser) {
|
||||
segments.add(TipsTextSegment(text: memberDisplayName, userID: memberUserID, isClickable: true));
|
||||
} else {
|
||||
segments.add(TipsTextSegment(text: memberDisplayName, isClickable: false));
|
||||
}
|
||||
segments.add(TipsTextSegment(text: " 被" + (isMute ? TIM_t("禁言") : TIM_t("解除禁言")), isClickable: false));
|
||||
if (i < groupTipsElem.memberList!.length - 1) {
|
||||
segments.add(TipsTextSegment(text: "、", isClickable: false));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GroupTipsElemType.V2TIM_GROUP_TIPS_TYPE_SET_ADMIN:
|
||||
final opMember = _getOpUserNick(operationMember);
|
||||
final opUserID = operationMember?.userID;
|
||||
final isOpCurrentUser = opUserID == currentUserID;
|
||||
final opDisplayName = isOpCurrentUser ? "你" : (opMember ?? "");
|
||||
|
||||
if (opUserID != null && !isOpCurrentUser) {
|
||||
segments.add(TipsTextSegment(text: opDisplayName, userID: opUserID, isClickable: true));
|
||||
} else {
|
||||
segments.add(TipsTextSegment(text: opDisplayName, isClickable: false));
|
||||
}
|
||||
segments.add(TipsTextSegment(text: "将 ", isClickable: false));
|
||||
|
||||
// 添加被设置为管理员的用户
|
||||
for (int i = 0; i < memberList!.length; i++) {
|
||||
final member = memberList[i]!;
|
||||
final memberName = _getMemberNickName(member);
|
||||
final memberUserID = member.userID;
|
||||
final isMemberCurrentUser = memberUserID == currentUserID;
|
||||
final memberDisplayName = isMemberCurrentUser ? "你" : memberName!;
|
||||
|
||||
if (memberUserID != null && !isMemberCurrentUser) {
|
||||
segments.add(TipsTextSegment(text: memberDisplayName, userID: memberUserID, isClickable: true));
|
||||
} else {
|
||||
segments.add(TipsTextSegment(text: memberDisplayName, isClickable: false));
|
||||
}
|
||||
if (i < memberList.length - 1) {
|
||||
segments.add(TipsTextSegment(text: "、", isClickable: false));
|
||||
}
|
||||
}
|
||||
segments.add(TipsTextSegment(text: " 设置为管理员", isClickable: false));
|
||||
break;
|
||||
|
||||
case GroupTipsElemType.V2TIM_GROUP_TIPS_TYPE_CANCEL_ADMIN:
|
||||
final opMember = _getOpUserNick(operationMember);
|
||||
final opUserID = operationMember?.userID;
|
||||
final isOpCurrentUser = opUserID == currentUserID;
|
||||
final opDisplayName = isOpCurrentUser ? "你" : (opMember ?? "");
|
||||
|
||||
if (opUserID != null && !isOpCurrentUser) {
|
||||
segments.add(TipsTextSegment(text: opDisplayName, userID: opUserID, isClickable: true));
|
||||
} else {
|
||||
segments.add(TipsTextSegment(text: opDisplayName, isClickable: false));
|
||||
}
|
||||
segments.add(TipsTextSegment(text: "将 ", isClickable: false));
|
||||
|
||||
// 添加被取消管理员的用户
|
||||
for (int i = 0; i < memberList!.length; i++) {
|
||||
final member = memberList[i]!;
|
||||
final memberName = _getMemberNickName(member);
|
||||
final memberUserID = member.userID;
|
||||
final isMemberCurrentUser = memberUserID == currentUserID;
|
||||
final memberDisplayName = isMemberCurrentUser ? "你" : memberName!;
|
||||
|
||||
if (memberUserID != null && !isMemberCurrentUser) {
|
||||
segments.add(TipsTextSegment(text: memberDisplayName, userID: memberUserID, isClickable: true));
|
||||
} else {
|
||||
segments.add(TipsTextSegment(text: memberDisplayName, isClickable: false));
|
||||
}
|
||||
if (i < memberList.length - 1) {
|
||||
segments.add(TipsTextSegment(text: "、", isClickable: false));
|
||||
}
|
||||
}
|
||||
segments.add(TipsTextSegment(text: " 取消管理员", isClickable: false));
|
||||
break;
|
||||
|
||||
default:
|
||||
final String option2 = operationType.toString();
|
||||
segments.add(TipsTextSegment(text: TIM_t_para("系统消息 {{option2}}", "系统消息 $option2")(option2: option2), isClickable: false));
|
||||
break;
|
||||
}
|
||||
|
||||
return GroupTipsRichTextData(segments: segments);
|
||||
}
|
||||
|
||||
static String formatVideoTime(int time) {
|
||||
List<int> times = [];
|
||||
if (time <= 0) return '0:01';
|
||||
|
|
|
|||
|
|
@ -283,6 +283,9 @@ class TIMUIKitHistoryMessageListItem extends StatefulWidget {
|
|||
/// If provided, the default message action functionality will appear in the right-click context menu instead.
|
||||
final Widget? Function(V2TimMessage message)? customMessageHoverBarOnDesktop;
|
||||
|
||||
/// Callback for tapping user names in group tips messages
|
||||
final Function(String userID, int conversationType)? onTapUserName;
|
||||
|
||||
const TIMUIKitHistoryMessageListItem(
|
||||
{Key? key,
|
||||
required this.message,
|
||||
|
|
@ -312,7 +315,8 @@ class TIMUIKitHistoryMessageListItem extends StatefulWidget {
|
|||
this.textFieldController,
|
||||
this.onSecondaryTapForOthersPortrait,
|
||||
this.groupMemberInfo,
|
||||
this.customMessageHoverBarOnDesktop})
|
||||
this.customMessageHoverBarOnDesktop,
|
||||
this.onTapUserName})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
|
|
@ -627,7 +631,9 @@ class _TIMUIKItHistoryMessageListItemState extends TIMUIKitState<TIMUIKitHistory
|
|||
return Container(
|
||||
padding: const EdgeInsets.only(bottom: 20),
|
||||
child: TIMUIKitGroupTipsElem(
|
||||
groupTipsElem: messageItem.groupTipsElem!, groupMemberList: model.groupMemberList ?? []));
|
||||
groupTipsElem: messageItem.groupTipsElem!,
|
||||
groupMemberList: model.groupMemberList ?? [],
|
||||
onTapUserName: widget.onTapUserName));
|
||||
}
|
||||
|
||||
Widget _selfRevokeEditMessageBuilder(theme, TUIChatSeparateViewModel model) {
|
||||
|
|
|
|||
|
|
@ -86,6 +86,9 @@ class TIMUIKitHistoryMessageListContainer extends StatefulWidget {
|
|||
/// If provided, the default message action functionality will appear in the right-click context menu instead.
|
||||
final Widget? Function(V2TimMessage message)? customMessageHoverBarOnDesktop;
|
||||
|
||||
/// Callback for tapping user names in group tips messages
|
||||
final Function(String userID, int conversationType)? onTapUserName;
|
||||
|
||||
const TIMUIKitHistoryMessageListContainer({
|
||||
Key? key,
|
||||
this.itemBuilder,
|
||||
|
|
@ -112,6 +115,7 @@ class TIMUIKitHistoryMessageListContainer extends StatefulWidget {
|
|||
this.onSecondaryTapAvatar,
|
||||
this.groupMemberInfo,
|
||||
this.customMessageHoverBarOnDesktop,
|
||||
this.onTapUserName,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
|
|
@ -188,7 +192,8 @@ class _TIMUIKitHistoryMessageListContainerState extends TIMUIKitState<TIMUIKitHi
|
|||
allowAtUserWhenReply: chatConfig.isAtWhenReply,
|
||||
allowAvatarTap: chatConfig.isAllowClickAvatar,
|
||||
allowLongPress: chatConfig.isAllowLongPressMessage,
|
||||
isUseMessageReaction: chatConfig.isUseMessageReaction);
|
||||
isUseMessageReaction: chatConfig.isUseMessageReaction,
|
||||
onTapUserName: widget.onTapUserName);
|
||||
},
|
||||
tongueItemBuilder: widget.tongueItemBuilder,
|
||||
initFindingMsg: widget.initFindingMsg,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_member_full_info.dart'
|
||||
if (dart.library.html) 'package:tencent_cloud_chat_sdk/web/compatible_models/v2_tim_group_member_full_info.dart';
|
||||
import 'package:tencent_cloud_chat_sdk/models/v2_tim_group_tips_elem.dart'
|
||||
|
|
@ -12,8 +13,14 @@ import 'package:tencent_cloud_chat_uikit/theme/tui_theme.dart';
|
|||
class TIMUIKitGroupTipsElem extends StatefulWidget {
|
||||
final V2TimGroupTipsElem groupTipsElem;
|
||||
final List<V2TimGroupMemberFullInfo?> groupMemberList;
|
||||
final Function(String userID, int conversationType)? onTapUserName;
|
||||
|
||||
const TIMUIKitGroupTipsElem({Key? key, required this.groupMemberList, required this.groupTipsElem}) : super(key: key);
|
||||
const TIMUIKitGroupTipsElem({
|
||||
Key? key,
|
||||
required this.groupMemberList,
|
||||
required this.groupTipsElem,
|
||||
this.onTapUserName,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<TIMUIKitGroupTipsElem> createState() => _TIMUIKitGroupTipsElemState();
|
||||
|
|
@ -21,6 +28,7 @@ class TIMUIKitGroupTipsElem extends StatefulWidget {
|
|||
|
||||
class _TIMUIKitGroupTipsElemState extends TIMUIKitState<TIMUIKitGroupTipsElem> {
|
||||
String groupTipsAbstractText = "";
|
||||
GroupTipsRichTextData? richTextData;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
|
@ -30,23 +38,63 @@ class _TIMUIKitGroupTipsElemState extends TIMUIKitState<TIMUIKitGroupTipsElem> {
|
|||
|
||||
void getText() async {
|
||||
final newText = await MessageUtils.groupTipsMessageAbstract(widget.groupTipsElem, widget.groupMemberList);
|
||||
final richData = await MessageUtils.groupTipsMessageRichText(widget.groupTipsElem, widget.groupMemberList);
|
||||
setState(() {
|
||||
groupTipsAbstractText = newText;
|
||||
richTextData = richData;
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildRichText(TUITheme theme) {
|
||||
if (richTextData == null || widget.onTapUserName == null) {
|
||||
// 如果没有富文本数据或回调函数,使用原来的简单文本
|
||||
return Text(
|
||||
groupTipsAbstractText,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 12, fontWeight: FontWeight.w400, color: hexToColor("888888")),
|
||||
);
|
||||
}
|
||||
|
||||
final List<TextSpan> spans = richTextData!.segments.map((segment) {
|
||||
if (segment.isClickable && segment.userID != null) {
|
||||
return TextSpan(
|
||||
text: segment.text,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: const Color(0xFF006CFF), // 蓝色
|
||||
),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
widget.onTapUserName!(segment.userID!, 1); // 1 表示群组对话
|
||||
},
|
||||
);
|
||||
} else {
|
||||
return TextSpan(
|
||||
text: segment.text,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: hexToColor("888888"),
|
||||
),
|
||||
);
|
||||
}
|
||||
}).toList();
|
||||
|
||||
return RichText(
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.center,
|
||||
text: TextSpan(children: spans),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget tuiBuild(BuildContext context, TUIKitBuildValue value) {
|
||||
final TUITheme theme = value.theme;
|
||||
|
||||
return MessageUtils.wrapMessageTips(
|
||||
Text(
|
||||
groupTipsAbstractText,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 12, fontWeight: FontWeight.w400, color: hexToColor("888888")),
|
||||
),
|
||||
theme);
|
||||
return MessageUtils.wrapMessageTips(_buildRichText(theme), theme);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -178,6 +178,9 @@ class TIMUIKitChat extends StatefulWidget {
|
|||
/// additional network requests to fetch the group member information internally.
|
||||
List<V2TimGroupMemberFullInfo?>? groupMemberList;
|
||||
|
||||
/// Callback for tapping user names in group tips messages
|
||||
final Function(String userID, int conversationType)? onTapUserName;
|
||||
|
||||
TIMUIKitChat(
|
||||
{Key? key,
|
||||
this.groupID,
|
||||
|
|
@ -216,7 +219,8 @@ class TIMUIKitChat extends StatefulWidget {
|
|||
this.customAppBar,
|
||||
this.inputTopBuilder,
|
||||
this.onSecondaryTapAvatar,
|
||||
this.customMessageHoverBarOnDesktop})
|
||||
this.customMessageHoverBarOnDesktop,
|
||||
this.onTapUserName})
|
||||
: super(key: key) {
|
||||
startTime = DateTime.now().millisecondsSinceEpoch;
|
||||
}
|
||||
|
|
@ -536,6 +540,7 @@ class _TUIChatState extends TIMUIKitState<TIMUIKitChat> {
|
|||
showNickName: widget.showNickName,
|
||||
messageItemBuilder: widget.messageItemBuilder,
|
||||
conversationID: _getConvID(),
|
||||
onTapUserName: widget.onTapUserName,
|
||||
),
|
||||
)),
|
||||
)),
|
||||
|
|
|
|||
Loading…
Reference in New Issue