From 8b3e5cce3556015b8246d4e6fcbd1794188d684b Mon Sep 17 00:00:00 2001 From: zhangxianbiao Date: Wed, 8 Jul 2026 10:25:04 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E9=A1=B5=E9=9D=A2=E8=AE=BE?= =?UTF-8?q?=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/modules/chat/message/sc_message_page.dart | 180 +++++++--------- .../msg/message_conversation_list_page.dart | 2 +- lib/ui_kit/widgets/room/room_msg_item.dart | 199 ++++++++++-------- 3 files changed, 194 insertions(+), 187 deletions(-) diff --git a/lib/modules/chat/message/sc_message_page.dart b/lib/modules/chat/message/sc_message_page.dart index ee22b03..f81fbe3 100644 --- a/lib/modules/chat/message/sc_message_page.dart +++ b/lib/modules/chat/message/sc_message_page.dart @@ -276,7 +276,7 @@ class _MessagePageState extends State { Widget _headMenu(RtmProvider provider) { return Container( margin: EdgeInsetsDirectional.symmetric( - horizontal: 25.w, + horizontal: 20.w, ).copyWith(top: 10.w), child: Column( spacing: 15.w, @@ -351,61 +351,40 @@ class _MessagePageState extends State { }, ), SCDebounceWidget( - child: Stack( + child: Row( children: [ - Row( - children: [ - SizedBox(height: 3.w), - Image.asset( - _strategy.getMessagePageSystemMessageIcon(), - 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, - ), - ], - ), - ], + SizedBox(height: 3.w), + Image.asset( + _strategy.getMessagePageSystemMessageIcon(), + width: 45.w, + height: 45.w, ), - PositionedDirectional( - bottom: 0, - end: 10.w, - child: Visibility( - visible: provider.systemUnReadCount > 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)), + SizedBox(width: 6.w), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + text( + SCAppLocalizations.of(context)!.system, + textColor: Colors.white, + fontSize: 14.sp, + fontWeight: FontWeight.bold, ), - child: Text( - "${provider.systemUnReadCount > 99 ? '99+' : provider.systemUnReadCount}", - style: TextStyle( - fontSize: 10.sp, - color: Color(0xffffffff), - fontWeight: FontWeight.w400, - decoration: TextDecoration.none, - ), + SizedBox(height: 3.w), + Row( + children: [ + Expanded( + child: text( + "[${SCAppLocalizations.of(context)!.newMessage}]", + fontSize: 12.sp, + textColor: Colors.white54, + ), + ), + SizedBox(width: 5.w), + _unreadBadge(provider.systemUnReadCount), + ], ), - ), + ], ), ), ], @@ -423,66 +402,42 @@ class _MessagePageState extends State { }, ), SCDebounceWidget( - child: Stack( + child: Row( children: [ - Container( - alignment: Alignment.center, - child: Row( + SizedBox(height: 3.w), + Image.asset( + _strategy.getMessagePageNotificationMessageIcon(), + width: 45.w, + height: 45.w, + ), + SizedBox(width: 6.w), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - SizedBox(height: 3.w), - Image.asset( - _strategy.getMessagePageNotificationMessageIcon(), - width: 45.w, - height: 45.w, + text( + SCAppLocalizations.of(context)!.notifcation, + textColor: Colors.white, + fontSize: 14.sp, + fontWeight: FontWeight.bold, ), - SizedBox(width: 5.w), - Column( - crossAxisAlignment: CrossAxisAlignment.start, + SizedBox(height: 3.w), + Row( children: [ - text( - SCAppLocalizations.of(context)!.notifcation, - textColor: Colors.white, - fontSize: 14.sp, - fontWeight: FontWeight.bold, - ), - SizedBox(height: 3.w), - text( - "[${SCAppLocalizations.of(context)!.newMessage}]", - fontSize: 12.sp, - textColor: Colors.white54, + Expanded( + child: 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: () { @@ -498,4 +453,25 @@ class _MessagePageState extends State { ), ); } + + 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, + ), + ), + ), + ); + } } diff --git a/lib/ui_kit/widgets/msg/message_conversation_list_page.dart b/lib/ui_kit/widgets/msg/message_conversation_list_page.dart index 52470d2..d6218fc 100644 --- a/lib/ui_kit/widgets/msg/message_conversation_list_page.dart +++ b/lib/ui_kit/widgets/msg/message_conversation_list_page.dart @@ -569,7 +569,7 @@ class _ConversationItemState extends State { child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ - head(url: _displayAvatar, width: 55.w), + head(url: _displayAvatar, width: 45.w), SizedBox(width: 6.w), Expanded( child: Column( diff --git a/lib/ui_kit/widgets/room/room_msg_item.dart b/lib/ui_kit/widgets/room/room_msg_item.dart index cba6035..b614110 100644 --- a/lib/ui_kit/widgets/room/room_msg_item.dart +++ b/lib/ui_kit/widgets/room/room_msg_item.dart @@ -157,30 +157,7 @@ class _MsgItemState extends State { margin: EdgeInsets.symmetric( horizontal: width(10), ).copyWith(bottom: 6.w), - child: Column( - 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"); - } - }, - ), - ), - ], - ), - ], - ), + child: _buildTextMessageItem(context), ), ); } else { @@ -212,10 +189,71 @@ class _MsgItemState extends State { } } - 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( + future: _loadRoomUserInfoSilently(userId), + builder: (ct, AsyncSnapshot 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 hasChatBubble = _resolveRoomChatBubbleImageUrl(chatBubble).isNotEmpty; - final bubbleStartMargin = 54.w; + final bubbleStartMargin = startMargin ?? 54.w; return LayoutBuilder( builder: (context, constraints) { final rowMaxWidth = @@ -1334,7 +1372,7 @@ class _MsgItemState extends State { }) { final hasUserId = (userId ?? "").trim().isNotEmpty; if (!hasUserId && fallbackBadges.isEmpty) { - return SizedBox(height: 16.w); + return const SizedBox.shrink(); } return SizedBox( width: double.infinity, @@ -1346,7 +1384,7 @@ class _MsgItemState extends State { longBadgeWidth: 51.w, spacing: 5.w, maxBadges: 8, - reserveSpace: true, + reserveSpace: false, ), ); } @@ -1830,14 +1868,7 @@ class _MsgItemState extends State { _buildUserInfoLine(BuildContext context) { final userId = widget.msg.user?.id; - if ((widget.msg.needUpDataUserInfo) ?? false) { - SCRoomUtils.roomUsersMap.remove(userId ?? ""); - if ((userId ?? "").isNotEmpty) { - _userInfoFutures.remove(userId); - _userInfoFailedAt.remove(userId); - } - widget.msg.needUpDataUserInfo = false; - } + _clearStaleUserInfoIfNeeded(userId); if (userId == null || userId.isEmpty) { return _buildPendingUserInfoLine(context); } @@ -1858,6 +1889,17 @@ class _MsgItemState extends State { : _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 _loadRoomUserInfoSilently(String userId) { final failedAt = _userInfoFailedAt[userId]; if (failedAt != null && @@ -1881,36 +1923,44 @@ class _MsgItemState extends State { }); } + 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) { return Row( children: [ - GestureDetector( - 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, - ), - ], - ), - ), + _buildMessageUserAvatar(context, widget.msg.user), SizedBox(width: 8.w), Expanded( - child: SizedBox( - height: 76.w, + child: ConstrainedBox( + constraints: BoxConstraints(minHeight: 48.w), child: Column( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildUserNameAndLevels(widget.msg.user), @@ -1935,33 +1985,14 @@ class _MsgItemState extends State { _buildNewUserInfoLine(BuildContext context, SocialChatUserProfile user) { return Row( children: [ - 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( - child: msgRoleTag(widget.msg.role ?? "", width: 14.w), - bottom: 2.w, - right: 2.w, - ), - ], - ), - ), + _buildMessageUserAvatar(context, user), SizedBox(width: 8.w), Expanded( - child: SizedBox( - height: 76.w, + child: ConstrainedBox( + constraints: BoxConstraints(minHeight: 48.w), child: Column( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildUserNameAndLevels(user),