Browse Source

feat(im): 优化消息处理与界面展示

- 修改 ExtendedUserInfo 构造函数,移除 userId 默认空字符串赋值
- 新增对自定义消息类型的解析,支持识别直播房间邀请消息
- 移除 sendCustomMessage 方法参数末尾多余逗号
- 在获取会话列表后增加日志输出,便于调试用户信息获取
- 简化 joinChannel 方法异常处理逻辑,提升代码可读性
- 更新 RoomItem 组件点击事件为异步方法,确保频道加入完成后再跳转页面
- 调整消息气泡布局和尺寸限制,优化显示效果
- 将底部信息栏改为绝对定位,并调整头像和昵称样式以适配新布局
ios
Jolie 4 months ago
parent
commit
a0e66a2675
5 changed files with 89 additions and 89 deletions
  1. 26
      lib/controller/discover/room_controller.dart
  2. 9
      lib/controller/message/conversation_controller.dart
  3. 2
      lib/im/im_manager.dart
  4. 3
      lib/widget/live/live_room_guest_list_dialog.dart
  5. 138
      lib/widget/message/room_item.dart

26
lib/controller/discover/room_controller.dart

@ -149,21 +149,17 @@ class RoomController extends GetxController with WidgetsBindingObserver {
}
Future<void> joinChannel(String channelName) async {
try {
final response = await _networkService.rtcApi.getSwRtcToken(channelName);
final base = response.data;
if (base.isSuccess && base.data != null) {
rtcChannel.value = base.data;
currentRole = CurrentRole.normalUser;
await _joinRtcChannel(
base.data!.token,
channelName,
base.data!.uid,
ClientRoleType.clientRoleAudience,
);
}
} catch (e) {
SmartDialog.showToast('加入频道异常:$e');
final response = await _networkService.rtcApi.getSwRtcToken(channelName);
final base = response.data;
if (base.isSuccess && base.data != null) {
rtcChannel.value = base.data;
currentRole = CurrentRole.normalUser;
await _joinRtcChannel(
base.data!.token,
channelName,
base.data!.uid,
ClientRoleType.clientRoleAudience,
);
}
}

9
lib/controller/message/conversation_controller.dart

@ -18,7 +18,7 @@ class ExtendedUserInfo {
// EMUserInfo
factory ExtendedUserInfo.fromEMUserInfo(EMUserInfo emUserInfo) {
return ExtendedUserInfo(
userId: emUserInfo.userId ?? '',
userId: emUserInfo.userId,
nickName: emUserInfo.nickName,
avatarUrl: emUserInfo.avatarUrl,
);
@ -262,6 +262,13 @@ class ConversationController extends GetxController {
return '[文件]';
}else if(message?.body.type == MessageType.LOCATION){
return '[位置]';
}else if(message?.body.type == MessageType.CUSTOM){
final body = message?.body as EMCustomMessageBody;
//
if(body.event == 'live_room_invite'){
return '[分享房间]';
}
return '[自定义消息]';
}
return '暂无消息';
}

2
lib/im/im_manager.dart

@ -430,7 +430,7 @@ class IMManager {
}
///
Future<EMMessage?> sendCustomMessage(String targetId, String event, Map<String, String>? data,) async {
Future<EMMessage?> sendCustomMessage(String targetId, String event, Map<String, String>? data) async {
final customMsg = EMMessage.createCustomSendMessage(
targetId: targetId,
// `event`

3
lib/widget/live/live_room_guest_list_dialog.dart

@ -41,7 +41,6 @@ class _LiveRoomGuestListDialogState extends State<LiveRoomGuestListDialog> {
try {
//
final conversations = await IMManager.instance.getConversations();
if (conversations.isEmpty) {
setState(() {
_guestList = [];
@ -62,7 +61,7 @@ class _LiveRoomGuestListDialogState extends State<LiveRoomGuestListDialog> {
//
final contactsMap = await IMManager.instance.getContacts(userId);
final emUserInfo = contactsMap[userId];
Get.log('获取会话列表: ${emUserInfo?.gender}');
//
final response = await networkService.userApi.getBaseUserInfo(userId);

138
lib/widget/message/room_item.dart

@ -59,7 +59,7 @@ class RoomItem extends StatelessWidget {
}
///
void _handleTap() {
void _handleTap() async{
final channelId = _getChannelId();
if (channelId.isNotEmpty) {
// RoomController
@ -68,11 +68,7 @@ class RoomItem extends StatelessWidget {
: Get.put(RoomController());
//
roomController.joinChannel(channelId).then((_) {
Get.to(() => const LiveRoomPage(id: 0));
}).catchError((e) {
print('❌ 加入直播间失败: $e');
});
await roomController.joinChannel(channelId);
}
}
@ -95,7 +91,7 @@ class RoomItem extends StatelessWidget {
child: Row(
mainAxisAlignment:
isSentByMe ? MainAxisAlignment.end : MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (!isSentByMe) _buildAvatar(),
if (!isSentByMe) SizedBox(width: 8.w),
@ -113,8 +109,7 @@ class RoomItem extends StatelessWidget {
GestureDetector(
onTap: _handleTap,
child: Container(
constraints: BoxConstraints(maxWidth: 250.w),
margin: EdgeInsets.only(top: 10.h),
constraints: BoxConstraints(maxWidth: 150.w, maxHeight: 150.w),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12.w),
@ -135,8 +130,8 @@ class RoomItem extends StatelessWidget {
Stack(
children: [
Container(
width: 250.w,
height: 250.w,
width: 150.w,
height: 150.w,
color: Colors.grey[200],
child: anchorAvatar.isNotEmpty
? CachedNetworkImage(
@ -204,70 +199,73 @@ class RoomItem extends StatelessWidget {
),
),
),
],
),
//
Container(
padding: EdgeInsets.all(12.w),
child: Row(
children: [
//
ClipRRect(
borderRadius: BorderRadius.circular(12.w),
child: Container(
width: 24.w,
height: 24.w,
color: Colors.grey[300],
child: anchorAvatar.isNotEmpty
? CachedNetworkImage(
imageUrl: anchorAvatar,
width: 24.w,
height: 24.w,
fit: BoxFit.cover,
placeholder: (context, url) =>
Container(
color: Colors.grey[300],
child: Center(
child: SizedBox(
width: 12.w,
height: 12.w,
child: CircularProgressIndicator(
strokeWidth: 2,
color: Colors.grey[600],
Positioned(
left: 8.w,
bottom: 8.w,
child: Row(
children: [
//
ClipRRect(
borderRadius: BorderRadius.circular(12.w),
child: Container(
width: 24.w,
height: 24.w,
color: Colors.grey[300],
child: anchorAvatar.isNotEmpty
? CachedNetworkImage(
imageUrl: anchorAvatar,
width: 24.w,
height: 24.w,
fit: BoxFit.cover,
placeholder: (context, url) =>
Container(
color: Colors.grey[300],
child: Center(
child: SizedBox(
width: 12.w,
height: 12.w,
child: CircularProgressIndicator(
strokeWidth: 2,
color: Colors.grey[600],
),
),
),
),
),
errorWidget: (context, url, error) =>
Icon(
Icons.person,
size: 16.w,
color: Colors.grey[600],
),
)
: Icon(
Icons.person,
size: 16.w,
color: Colors.grey[600],
),
),
),
SizedBox(width: 8.w),
//
Expanded(
child: Text(
anchorName,
style: TextStyle(
fontSize: 13.sp,
color: Colors.black87,
fontWeight: FontWeight.w500,
errorWidget: (context, url, error) =>
Icon(
Icons.person,
size: 16.w,
color: Colors.grey[600],
),
)
: Icon(
Icons.person,
size: 16.w,
color: Colors.grey[600],
),
),
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
SizedBox(width: 5.w),
//
Container(
constraints: BoxConstraints(
maxWidth: 100.w,
),
child: Text(
anchorName,
style: TextStyle(
fontSize: 11.sp,
color: Colors.white,
fontWeight: FontWeight.w500,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
],
),
],
),
)
],
),
],
),

Loading…
Cancel
Save