|
|
|
@ -8,6 +8,9 @@ import '../../generated/assets.dart'; |
|
|
|
import '../../controller/discover/room_controller.dart'; |
|
|
|
import '../../controller/global.dart'; |
|
|
|
import '../../controller/message/chat_controller.dart'; |
|
|
|
import '../../controller/overlay_controller.dart'; |
|
|
|
import '../../rtc/rtc_manager.dart'; |
|
|
|
import '../../pages/discover/live_room_page.dart'; |
|
|
|
|
|
|
|
class RoomItem extends StatelessWidget { |
|
|
|
final EMMessage message; |
|
|
|
@ -32,11 +35,13 @@ class RoomItem extends StatelessWidget { |
|
|
|
final customBody = message.body as EMCustomMessageBody; |
|
|
|
// 检查是否是直播间邀请消息 |
|
|
|
if (customBody.event == 'live_room_invite') { |
|
|
|
return customBody.params; |
|
|
|
final params = customBody.params; |
|
|
|
print('📋 [RoomItem] 解析到的房间信息: $params'); |
|
|
|
return params; |
|
|
|
} |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
print('解析房间信息失败: $e'); |
|
|
|
print('❌ [RoomItem] 解析房间信息失败: $e'); |
|
|
|
} |
|
|
|
return null; |
|
|
|
} |
|
|
|
@ -56,21 +61,58 @@ class RoomItem extends StatelessWidget { |
|
|
|
/// 获取主持人头像 |
|
|
|
String _getAnchorAvatar() { |
|
|
|
final roomInfo = _parseRoomInfo(); |
|
|
|
return roomInfo?['anchorAvatar'] ?? ''; |
|
|
|
final avatar = roomInfo?['anchorAvatar'] ?? ''; |
|
|
|
// 清理头像URL(移除反引号) |
|
|
|
return avatar.trim().replaceAll('`', ''); |
|
|
|
} |
|
|
|
|
|
|
|
/// 获取封面图片(如果有的话,否则使用头像) |
|
|
|
String _getCoverImage() { |
|
|
|
final roomInfo = _parseRoomInfo(); |
|
|
|
// 优先使用封面图片,如果没有则使用头像 |
|
|
|
final coverImage = roomInfo?['anchorAvatar'] ?? ''; |
|
|
|
return coverImage.trim().replaceAll('`', ''); |
|
|
|
} |
|
|
|
|
|
|
|
/// 处理点击事件 |
|
|
|
void _handleTap() async{ |
|
|
|
void _handleTap() async { |
|
|
|
final channelId = _getChannelId(); |
|
|
|
if (channelId.isNotEmpty) { |
|
|
|
// 获取 RoomController 并加入频道 |
|
|
|
final roomController = Get.isRegistered<RoomController>() |
|
|
|
? Get.find<RoomController>() |
|
|
|
: Get.put(RoomController()); |
|
|
|
|
|
|
|
// 加入频道并跳转 |
|
|
|
await roomController.joinChannel(channelId); |
|
|
|
if (channelId.isEmpty) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// 获取当前直播间ID |
|
|
|
final currentChannelId = RTCManager.instance.currentChannelId; |
|
|
|
|
|
|
|
// 隐藏小窗口 |
|
|
|
if (Get.isRegistered<OverlayController>()) { |
|
|
|
final overlayController = Get.find<OverlayController>(); |
|
|
|
overlayController.hide(); |
|
|
|
} |
|
|
|
|
|
|
|
// 获取 RoomController |
|
|
|
final roomController = Get.isRegistered<RoomController>() |
|
|
|
? Get.find<RoomController>() |
|
|
|
: Get.put(RoomController()); |
|
|
|
|
|
|
|
// 如果频道ID一致,取消小窗口并进入直播间 |
|
|
|
if (currentChannelId != null && currentChannelId == channelId) { |
|
|
|
// 如果当前不在 LiveRoomPage,则导航到 LiveRoomPage |
|
|
|
final currentRoute = Get.currentRoute; |
|
|
|
if (currentRoute != '/LiveRoomPage' && !currentRoute.contains('LiveRoomPage')) { |
|
|
|
Get.to(() => const LiveRoomPage(id: 0)); |
|
|
|
} |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// 如果不一致,退出当前直播间并进入新的直播间 |
|
|
|
if (currentChannelId != null && currentChannelId.isNotEmpty) { |
|
|
|
// 退出当前直播间 |
|
|
|
await roomController.leaveChannel(); |
|
|
|
} |
|
|
|
|
|
|
|
// 加入新的直播间 |
|
|
|
await roomController.joinChannel(channelId); |
|
|
|
} |
|
|
|
|
|
|
|
@override |
|
|
|
@ -82,6 +124,7 @@ class RoomItem extends StatelessWidget { |
|
|
|
|
|
|
|
final anchorName = _getAnchorName(); |
|
|
|
final anchorAvatar = _getAnchorAvatar(); |
|
|
|
final coverImage = _getAnchorAvatar(); |
|
|
|
|
|
|
|
return Column( |
|
|
|
children: [ |
|
|
|
@ -134,11 +177,15 @@ class RoomItem extends StatelessWidget { |
|
|
|
width: 150.w, |
|
|
|
height: 150.w, |
|
|
|
color: Colors.grey[200], |
|
|
|
child: anchorAvatar.isNotEmpty |
|
|
|
child: coverImage.isNotEmpty |
|
|
|
? CachedNetworkImage( |
|
|
|
imageUrl: anchorAvatar, |
|
|
|
imageUrl: coverImage, |
|
|
|
width: 150.w, |
|
|
|
height: 150.w, |
|
|
|
fit: BoxFit.cover, |
|
|
|
placeholder: (context, url) => Container( |
|
|
|
width: 150.w, |
|
|
|
height: 150.w, |
|
|
|
color: Colors.grey[200], |
|
|
|
child: Center( |
|
|
|
child: CircularProgressIndicator( |
|
|
|
@ -147,15 +194,19 @@ class RoomItem extends StatelessWidget { |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
errorWidget: (context, url, error) => |
|
|
|
Container( |
|
|
|
color: Colors.grey[200], |
|
|
|
child: Icon( |
|
|
|
Icons.live_tv, |
|
|
|
size: 40.w, |
|
|
|
color: Colors.grey[400], |
|
|
|
), |
|
|
|
), |
|
|
|
errorWidget: (context, url, error) { |
|
|
|
print('❌ [RoomItem] 封面图片加载失败: $url, error: $error'); |
|
|
|
return Container( |
|
|
|
width: 150.w, |
|
|
|
height: 150.w, |
|
|
|
color: Colors.grey[200], |
|
|
|
child: Icon( |
|
|
|
Icons.live_tv, |
|
|
|
size: 40.w, |
|
|
|
color: Colors.grey[400], |
|
|
|
), |
|
|
|
); |
|
|
|
}, |
|
|
|
) |
|
|
|
: Container( |
|
|
|
color: Colors.grey[200], |
|
|
|
@ -189,7 +240,7 @@ class RoomItem extends StatelessWidget { |
|
|
|
), |
|
|
|
SizedBox(width: 4.w), |
|
|
|
Text( |
|
|
|
'直播中', |
|
|
|
'直播间', |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 11.sp, |
|
|
|
color: Colors.white, |
|
|
|
@ -214,36 +265,38 @@ class RoomItem extends StatelessWidget { |
|
|
|
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], |
|
|
|
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], |
|
|
|
errorWidget: (context, url, error) => |
|
|
|
Image.asset( |
|
|
|
Assets.imagesUserAvatar, |
|
|
|
width: 24.w, |
|
|
|
height: 24.w, |
|
|
|
fit: BoxFit.cover, |
|
|
|
), |
|
|
|
) |
|
|
|
: Image.asset( |
|
|
|
Assets.imagesUserAvatar, |
|
|
|
width: 24.w, |
|
|
|
height: 24.w, |
|
|
|
fit: BoxFit.cover, |
|
|
|
), |
|
|
|
) |
|
|
|
: Icon( |
|
|
|
Icons.person, |
|
|
|
size: 16.w, |
|
|
|
color: Colors.grey[600], |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
SizedBox(width: 5.w), |
|
|
|
|