Compare commits

...

2 Commits

Author SHA1 Message Date
7baa3b48ca Merge remote-tracking branch 'origin/main' 2026-07-08 10:26:57 +08:00
8b3e5cce35 更新页面设计 2026-07-08 10:25:04 +08:00
3 changed files with 194 additions and 187 deletions

View File

@ -276,7 +276,7 @@ class _MessagePageState extends State<SCMessagePage> {
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<SCMessagePage> {
},
),
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<SCMessagePage> {
},
),
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<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,
),
),
),
);
}
}

View File

@ -569,7 +569,7 @@ class _ConversationItemState extends State<ConversationItem> {
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
head(url: _displayAvatar, width: 55.w),
head(url: _displayAvatar, width: 45.w),
SizedBox(width: 6.w),
Expanded(
child: Column(

View File

@ -157,30 +157,7 @@ class _MsgItemState extends State<MsgItem> {
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<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 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<MsgItem> {
}) {
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<MsgItem> {
longBadgeWidth: 51.w,
spacing: 5.w,
maxBadges: 8,
reserveSpace: true,
reserveSpace: false,
),
);
}
@ -1837,14 +1875,7 @@ class _MsgItemState extends State<MsgItem> {
_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);
}
@ -1865,6 +1896,17 @@ class _MsgItemState extends State<MsgItem> {
: _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) {
final failedAt = _userInfoFailedAt[userId];
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) {
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),
@ -1942,33 +1992,14 @@ class _MsgItemState extends State<MsgItem> {
_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),