Compare commits
2 Commits
02b4fafb3e
...
7baa3b48ca
| Author | SHA1 | Date | |
|---|---|---|---|
| 7baa3b48ca | |||
| 8b3e5cce35 |
@ -276,7 +276,7 @@ class _MessagePageState extends State<SCMessagePage> {
|
|||||||
Widget _headMenu(RtmProvider provider) {
|
Widget _headMenu(RtmProvider provider) {
|
||||||
return Container(
|
return Container(
|
||||||
margin: EdgeInsetsDirectional.symmetric(
|
margin: EdgeInsetsDirectional.symmetric(
|
||||||
horizontal: 25.w,
|
horizontal: 20.w,
|
||||||
).copyWith(top: 10.w),
|
).copyWith(top: 10.w),
|
||||||
child: Column(
|
child: Column(
|
||||||
spacing: 15.w,
|
spacing: 15.w,
|
||||||
@ -351,61 +351,40 @@ class _MessagePageState extends State<SCMessagePage> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
SCDebounceWidget(
|
SCDebounceWidget(
|
||||||
child: Stack(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Row(
|
SizedBox(height: 3.w),
|
||||||
children: [
|
Image.asset(
|
||||||
SizedBox(height: 3.w),
|
_strategy.getMessagePageSystemMessageIcon(),
|
||||||
Image.asset(
|
width: 45.w,
|
||||||
_strategy.getMessagePageSystemMessageIcon(),
|
height: 45.w,
|
||||||
width: 45.w,
|
|
||||||
height: 45.w,
|
|
||||||
),
|
|
||||||
SizedBox(width: 5.w),
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
text(
|
|
||||||
SCAppLocalizations.of(context)!.system,
|
|
||||||
textColor: Colors.white,
|
|
||||||
fontSize: 14.sp,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
SizedBox(height: 3.w),
|
|
||||||
text(
|
|
||||||
"[${SCAppLocalizations.of(context)!.newMessage}]",
|
|
||||||
fontSize: 12.sp,
|
|
||||||
textColor: Colors.white54,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
PositionedDirectional(
|
SizedBox(width: 6.w),
|
||||||
bottom: 0,
|
Expanded(
|
||||||
end: 10.w,
|
child: Column(
|
||||||
child: Visibility(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
visible: provider.systemUnReadCount > 0,
|
children: [
|
||||||
child: Container(
|
text(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 6.w),
|
SCAppLocalizations.of(context)!.system,
|
||||||
alignment: Alignment.center,
|
textColor: Colors.white,
|
||||||
height: 16.w,
|
fontSize: 14.sp,
|
||||||
decoration: BoxDecoration(
|
fontWeight: FontWeight.bold,
|
||||||
//gradient: LinearGradient(colors: [Color(0xffA447FF), Color(0xff623CE9)]),
|
|
||||||
color: Colors.red,
|
|
||||||
shape: BoxShape.circle,
|
|
||||||
//borderRadius: BorderRadius.all(Radius.circular(7.w)),
|
|
||||||
),
|
),
|
||||||
child: Text(
|
SizedBox(height: 3.w),
|
||||||
"${provider.systemUnReadCount > 99 ? '99+' : provider.systemUnReadCount}",
|
Row(
|
||||||
style: TextStyle(
|
children: [
|
||||||
fontSize: 10.sp,
|
Expanded(
|
||||||
color: Color(0xffffffff),
|
child: text(
|
||||||
fontWeight: FontWeight.w400,
|
"[${SCAppLocalizations.of(context)!.newMessage}]",
|
||||||
decoration: TextDecoration.none,
|
fontSize: 12.sp,
|
||||||
),
|
textColor: Colors.white54,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 5.w),
|
||||||
|
_unreadBadge(provider.systemUnReadCount),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -423,66 +402,42 @@ class _MessagePageState extends State<SCMessagePage> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
SCDebounceWidget(
|
SCDebounceWidget(
|
||||||
child: Stack(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
SizedBox(height: 3.w),
|
||||||
alignment: Alignment.center,
|
Image.asset(
|
||||||
child: Row(
|
_strategy.getMessagePageNotificationMessageIcon(),
|
||||||
|
width: 45.w,
|
||||||
|
height: 45.w,
|
||||||
|
),
|
||||||
|
SizedBox(width: 6.w),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
SizedBox(height: 3.w),
|
text(
|
||||||
Image.asset(
|
SCAppLocalizations.of(context)!.notifcation,
|
||||||
_strategy.getMessagePageNotificationMessageIcon(),
|
textColor: Colors.white,
|
||||||
width: 45.w,
|
fontSize: 14.sp,
|
||||||
height: 45.w,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
SizedBox(width: 5.w),
|
SizedBox(height: 3.w),
|
||||||
Column(
|
Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
children: [
|
||||||
text(
|
Expanded(
|
||||||
SCAppLocalizations.of(context)!.notifcation,
|
child: text(
|
||||||
textColor: Colors.white,
|
"[${SCAppLocalizations.of(context)!.newMessage}]",
|
||||||
fontSize: 14.sp,
|
fontSize: 12.sp,
|
||||||
fontWeight: FontWeight.bold,
|
textColor: Colors.white54,
|
||||||
),
|
),
|
||||||
SizedBox(height: 3.w),
|
|
||||||
text(
|
|
||||||
"[${SCAppLocalizations.of(context)!.newMessage}]",
|
|
||||||
fontSize: 12.sp,
|
|
||||||
textColor: Colors.white54,
|
|
||||||
),
|
),
|
||||||
|
SizedBox(width: 5.w),
|
||||||
|
_unreadBadge(provider.notifcationUnReadCount),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
PositionedDirectional(
|
|
||||||
bottom: 0,
|
|
||||||
end: 10.w,
|
|
||||||
child: Visibility(
|
|
||||||
visible: provider.notifcationUnReadCount > 0,
|
|
||||||
child: Container(
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 6.w),
|
|
||||||
alignment: Alignment.center,
|
|
||||||
height: 16.w,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
//gradient: LinearGradient(colors: [Color(0xffA447FF), Color(0xff623CE9)]),
|
|
||||||
color: Colors.red,
|
|
||||||
shape: BoxShape.circle,
|
|
||||||
//borderRadius: BorderRadius.all(Radius.circular(7.w)),
|
|
||||||
),
|
|
||||||
child: Text(
|
|
||||||
"${provider.notifcationUnReadCount > 99 ? '99+' : provider.notifcationUnReadCount}",
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 10.sp,
|
|
||||||
color: Color(0xffffffff),
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
decoration: TextDecoration.none,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
@ -498,4 +453,25 @@ class _MessagePageState extends State<SCMessagePage> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _unreadBadge(int unreadCount) {
|
||||||
|
return Visibility(
|
||||||
|
visible: unreadCount > 0,
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 6.w),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
height: 16.w,
|
||||||
|
decoration: BoxDecoration(color: Colors.red, shape: BoxShape.circle),
|
||||||
|
child: Text(
|
||||||
|
"${unreadCount > 99 ? '99+' : unreadCount}",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 10.sp,
|
||||||
|
color: Color(0xffffffff),
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
decoration: TextDecoration.none,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -569,7 +569,7 @@ class _ConversationItemState extends State<ConversationItem> {
|
|||||||
child: Row(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
head(url: _displayAvatar, width: 55.w),
|
head(url: _displayAvatar, width: 45.w),
|
||||||
SizedBox(width: 6.w),
|
SizedBox(width: 6.w),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Column(
|
child: Column(
|
||||||
|
|||||||
@ -157,30 +157,7 @@ class _MsgItemState extends State<MsgItem> {
|
|||||||
margin: EdgeInsets.symmetric(
|
margin: EdgeInsets.symmetric(
|
||||||
horizontal: width(10),
|
horizontal: width(10),
|
||||||
).copyWith(bottom: 6.w),
|
).copyWith(bottom: 6.w),
|
||||||
child: Column(
|
child: _buildTextMessageItem(context),
|
||||||
children: [
|
|
||||||
_buildUserInfoLine(context),
|
|
||||||
SizedBox(height: 6.w),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Flexible(
|
|
||||||
// 使用Flexible替代Expanded
|
|
||||||
child: GestureDetector(
|
|
||||||
child: _buildTextMessageBubble(),
|
|
||||||
onLongPress: () {
|
|
||||||
if (!(widget.msg.msg ?? "").startsWith(AtText.flag)) {
|
|
||||||
Clipboard.setData(
|
|
||||||
ClipboardData(text: widget.msg.msg ?? ''),
|
|
||||||
);
|
|
||||||
SCTts.show("Copied");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@ -212,10 +189,71 @@ class _MsgItemState extends State<MsgItem> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildTextMessageBubble() {
|
Widget _buildTextMessageItem(BuildContext context) {
|
||||||
|
final userId = widget.msg.user?.id;
|
||||||
|
_clearStaleUserInfoIfNeeded(userId);
|
||||||
|
if (userId == null || userId.isEmpty) {
|
||||||
|
return _buildTextMessageItemWithUser(context, widget.msg.user);
|
||||||
|
}
|
||||||
|
final cachedUser = SCRoomUtils.roomUsersMap[userId];
|
||||||
|
if (cachedUser != null) {
|
||||||
|
return _buildTextMessageItemWithUser(context, cachedUser);
|
||||||
|
}
|
||||||
|
return FutureBuilder<SocialChatUserProfile?>(
|
||||||
|
future: _loadRoomUserInfoSilently(userId),
|
||||||
|
builder: (ct, AsyncSnapshot<SocialChatUserProfile?> snapshot) {
|
||||||
|
if (snapshot.connectionState == ConnectionState.done &&
|
||||||
|
snapshot.hasData) {
|
||||||
|
final user = snapshot.data!;
|
||||||
|
SCRoomUtils.roomUsersMap[user.id ?? ""] = user;
|
||||||
|
return _buildTextMessageItemWithUser(context, user);
|
||||||
|
}
|
||||||
|
return _buildTextMessageItemWithUser(context, widget.msg.user);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildTextMessageItemWithUser(
|
||||||
|
BuildContext context,
|
||||||
|
SocialChatUserProfile? user,
|
||||||
|
) {
|
||||||
|
final badges = _activeWearBadges(user);
|
||||||
|
return Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
_buildMessageUserAvatar(context, user),
|
||||||
|
SizedBox(width: 8.w),
|
||||||
|
Flexible(
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
_buildUserNameAndLevels(user),
|
||||||
|
_buildLongMedals(userId: user?.id, fallbackBadges: badges),
|
||||||
|
_buildMedals(userId: user?.id, fallbackBadges: badges),
|
||||||
|
SizedBox(height: 2.w),
|
||||||
|
GestureDetector(
|
||||||
|
child: _buildTextMessageBubble(startMargin: 0),
|
||||||
|
onLongPress: () {
|
||||||
|
if (!(widget.msg.msg ?? "").startsWith(AtText.flag)) {
|
||||||
|
Clipboard.setData(
|
||||||
|
ClipboardData(text: widget.msg.msg ?? ''),
|
||||||
|
);
|
||||||
|
SCTts.show("Copied");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildTextMessageBubble({double? startMargin}) {
|
||||||
final chatBubble = widget.msg.user?.getChatBox();
|
final chatBubble = widget.msg.user?.getChatBox();
|
||||||
final hasChatBubble = _resolveRoomChatBubbleImageUrl(chatBubble).isNotEmpty;
|
final hasChatBubble = _resolveRoomChatBubbleImageUrl(chatBubble).isNotEmpty;
|
||||||
final bubbleStartMargin = 54.w;
|
final bubbleStartMargin = startMargin ?? 54.w;
|
||||||
return LayoutBuilder(
|
return LayoutBuilder(
|
||||||
builder: (context, constraints) {
|
builder: (context, constraints) {
|
||||||
final rowMaxWidth =
|
final rowMaxWidth =
|
||||||
@ -1334,7 +1372,7 @@ class _MsgItemState extends State<MsgItem> {
|
|||||||
}) {
|
}) {
|
||||||
final hasUserId = (userId ?? "").trim().isNotEmpty;
|
final hasUserId = (userId ?? "").trim().isNotEmpty;
|
||||||
if (!hasUserId && fallbackBadges.isEmpty) {
|
if (!hasUserId && fallbackBadges.isEmpty) {
|
||||||
return SizedBox(height: 16.w);
|
return const SizedBox.shrink();
|
||||||
}
|
}
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
@ -1346,7 +1384,7 @@ class _MsgItemState extends State<MsgItem> {
|
|||||||
longBadgeWidth: 51.w,
|
longBadgeWidth: 51.w,
|
||||||
spacing: 5.w,
|
spacing: 5.w,
|
||||||
maxBadges: 8,
|
maxBadges: 8,
|
||||||
reserveSpace: true,
|
reserveSpace: false,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1837,14 +1875,7 @@ class _MsgItemState extends State<MsgItem> {
|
|||||||
|
|
||||||
_buildUserInfoLine(BuildContext context) {
|
_buildUserInfoLine(BuildContext context) {
|
||||||
final userId = widget.msg.user?.id;
|
final userId = widget.msg.user?.id;
|
||||||
if ((widget.msg.needUpDataUserInfo) ?? false) {
|
_clearStaleUserInfoIfNeeded(userId);
|
||||||
SCRoomUtils.roomUsersMap.remove(userId ?? "");
|
|
||||||
if ((userId ?? "").isNotEmpty) {
|
|
||||||
_userInfoFutures.remove(userId);
|
|
||||||
_userInfoFailedAt.remove(userId);
|
|
||||||
}
|
|
||||||
widget.msg.needUpDataUserInfo = false;
|
|
||||||
}
|
|
||||||
if (userId == null || userId.isEmpty) {
|
if (userId == null || userId.isEmpty) {
|
||||||
return _buildPendingUserInfoLine(context);
|
return _buildPendingUserInfoLine(context);
|
||||||
}
|
}
|
||||||
@ -1865,6 +1896,17 @@ class _MsgItemState extends State<MsgItem> {
|
|||||||
: _buildNewUserInfoLine(context, SCRoomUtils.roomUsersMap[userId]!);
|
: _buildNewUserInfoLine(context, SCRoomUtils.roomUsersMap[userId]!);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _clearStaleUserInfoIfNeeded(String? userId) {
|
||||||
|
if ((widget.msg.needUpDataUserInfo) ?? false) {
|
||||||
|
SCRoomUtils.roomUsersMap.remove(userId ?? "");
|
||||||
|
if ((userId ?? "").isNotEmpty) {
|
||||||
|
_userInfoFutures.remove(userId);
|
||||||
|
_userInfoFailedAt.remove(userId);
|
||||||
|
}
|
||||||
|
widget.msg.needUpDataUserInfo = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<SocialChatUserProfile?> _loadRoomUserInfoSilently(String userId) {
|
Future<SocialChatUserProfile?> _loadRoomUserInfoSilently(String userId) {
|
||||||
final failedAt = _userInfoFailedAt[userId];
|
final failedAt = _userInfoFailedAt[userId];
|
||||||
if (failedAt != null &&
|
if (failedAt != null &&
|
||||||
@ -1888,36 +1930,44 @@ class _MsgItemState extends State<MsgItem> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildMessageUserAvatar(
|
||||||
|
BuildContext context,
|
||||||
|
SocialChatUserProfile? user,
|
||||||
|
) {
|
||||||
|
return GestureDetector(
|
||||||
|
behavior: HitTestBehavior.opaque,
|
||||||
|
onTap: () {
|
||||||
|
widget.onClick(user);
|
||||||
|
},
|
||||||
|
child: Stack(
|
||||||
|
alignment: AlignmentDirectional.bottomEnd,
|
||||||
|
children: [
|
||||||
|
head(
|
||||||
|
url: user?.userAvatar ?? "",
|
||||||
|
width: 48.w,
|
||||||
|
// headdress: msg.user?.getHeaddress()?.sourceUrl,
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
bottom: 2.w,
|
||||||
|
right: 2.w,
|
||||||
|
child: msgRoleTag(widget.msg.role ?? "", width: 14.w),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget _buildPendingUserInfoLine(BuildContext context) {
|
Widget _buildPendingUserInfoLine(BuildContext context) {
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
GestureDetector(
|
_buildMessageUserAvatar(context, widget.msg.user),
|
||||||
behavior: HitTestBehavior.opaque,
|
|
||||||
onTap: () {
|
|
||||||
widget.onClick(widget.msg.user);
|
|
||||||
},
|
|
||||||
child: Stack(
|
|
||||||
alignment: AlignmentDirectional.bottomEnd,
|
|
||||||
children: [
|
|
||||||
head(
|
|
||||||
url: widget.msg.user?.userAvatar ?? "",
|
|
||||||
width: 48.w,
|
|
||||||
// headdress: msg.user?.getHeaddress()?.sourceUrl,
|
|
||||||
),
|
|
||||||
Positioned(
|
|
||||||
child: msgRoleTag(widget.msg.role ?? "", width: 14.w),
|
|
||||||
bottom: 2.w,
|
|
||||||
right: 2.w,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(width: 8.w),
|
SizedBox(width: 8.w),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: SizedBox(
|
child: ConstrainedBox(
|
||||||
height: 76.w,
|
constraints: BoxConstraints(minHeight: 48.w),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
_buildUserNameAndLevels(widget.msg.user),
|
_buildUserNameAndLevels(widget.msg.user),
|
||||||
@ -1942,33 +1992,14 @@ class _MsgItemState extends State<MsgItem> {
|
|||||||
_buildNewUserInfoLine(BuildContext context, SocialChatUserProfile user) {
|
_buildNewUserInfoLine(BuildContext context, SocialChatUserProfile user) {
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
GestureDetector(
|
_buildMessageUserAvatar(context, user),
|
||||||
behavior: HitTestBehavior.opaque,
|
|
||||||
onTap: () {
|
|
||||||
widget.onClick(user);
|
|
||||||
},
|
|
||||||
child: Stack(
|
|
||||||
alignment: AlignmentDirectional.bottomEnd,
|
|
||||||
children: [
|
|
||||||
head(
|
|
||||||
url: user.userAvatar ?? "",
|
|
||||||
width: 48.w,
|
|
||||||
// headdress: msg.user?.getHeaddress()?.sourceUrl,
|
|
||||||
),
|
|
||||||
Positioned(
|
|
||||||
child: msgRoleTag(widget.msg.role ?? "", width: 14.w),
|
|
||||||
bottom: 2.w,
|
|
||||||
right: 2.w,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(width: 8.w),
|
SizedBox(width: 8.w),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: SizedBox(
|
child: ConstrainedBox(
|
||||||
height: 76.w,
|
constraints: BoxConstraints(minHeight: 48.w),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
_buildUserNameAndLevels(user),
|
_buildUserNameAndLevels(user),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user