diff --git a/lib/controller/message/conversation_controller.dart b/lib/controller/message/conversation_controller.dart new file mode 100644 index 0000000..e64706c --- /dev/null +++ b/lib/controller/message/conversation_controller.dart @@ -0,0 +1,113 @@ +import 'package:get/get.dart'; +import 'package:get_storage/get_storage.dart'; +import 'package:im_flutter_sdk/im_flutter_sdk.dart'; +import '../../im/im_manager.dart'; + +class ConversationController extends GetxController { + // 会话列表数据 + final conversations = [].obs; + // 加载状态 + final isLoading = false.obs; + // 错误消息 + final errorMessage = ''.obs; + + @override + void onInit() { + super.onInit(); + // 初始化时加载会话列表 + loadConversations(); + } + + /// 加载会话列表 + Future loadConversations() async { + if (isLoading.value) return; + + try { + isLoading.value = true; + errorMessage.value = ''; + + // 从IMManager获取会话列表 + final List convList = await IMManager.instance.getConversations(); + // 更新会话列表 + conversations.value = convList; + + // 使用GetX日志系统 + if (Get.isLogEnable) { + Get.log('Loaded ${convList.length} conversations'); + } + } catch (e) { + // 使用GetX日志系统 + if (Get.isLogEnable) { + Get.log('Failed to load conversations: $e'); + } + errorMessage.value = '加载会话列表失败,请稍后重试'; + } finally { + isLoading.value = false; + } + } + + /// 刷新会话列表 + Future refreshConversations() async { + await loadConversations(); + } + + /// 获取会话的最新消息 + String getLastMessageContent(EMMessage? message) { + if(message?.body.type == MessageType.TXT){ + + } + return '暂无消息'; + } + + /// 获取会话的未读消息数量 + Future getUnreadCount(EMConversation conversation) async { + try { + // 简化实现,返回0 + return await conversation.unreadCount(); + } catch (e) { + if (Get.isLogEnable) { + Get.log('Error getting unread count: $e'); + } + return 0; + } + } + + /// 获取会话最后消息的时间 + String getConversationLastMessageTime(EMConversation conversation) { + try { + // 返回默认时间 + return '刚刚'; + } catch (e) { + if (Get.isLogEnable) { + Get.log('Error getting last message time: $e'); + } + return ''; + } + } + + /// 格式化消息时间 + String formatMessageTime(int timestamp) { + DateTime messageTime = DateTime.fromMillisecondsSinceEpoch(timestamp); + DateTime now = DateTime.now(); + Duration difference = now.difference(messageTime); + + if (difference.inDays > 0) { + return '${difference.inDays}天前'; + } else if (difference.inHours > 0) { + return '${difference.inHours}小时前'; + } else if (difference.inMinutes > 0) { + return '${difference.inMinutes}分钟前'; + } else { + return '刚刚'; + } + } + + Future loadContact(String userId) async{ + var data = await IMManager.instance.getContacts(userId); + return data[userId]!; + } + + Future lastMessage(EMConversation conversation) async{ + return await conversation.latestMessage(); + } +} \ No newline at end of file diff --git a/lib/im/im_manager.dart b/lib/im/im_manager.dart index addbf78..af4a8f2 100644 --- a/lib/im/im_manager.dart +++ b/lib/im/im_manager.dart @@ -207,12 +207,12 @@ class IMManager { /// 获取会话列表 Future> getConversations() async { - try { - return EMClient.getInstance.chatManager.loadAllConversations(); - } catch (e) { - print('Failed to get conversations: $e'); - return []; - } + return EMClient.getInstance.chatManager.loadAllConversations(); + } + + /// 获取好有列表 + Future> getContacts(String userId) async { + return await EMClient.getInstance.userInfoManager.fetchUserInfoById([userId]); } /// 获取指定会话的消息记录 diff --git a/lib/pages/message/conversation_tab.dart b/lib/pages/message/conversation_tab.dart index c4b99d3..1e98da7 100644 --- a/lib/pages/message/conversation_tab.dart +++ b/lib/pages/message/conversation_tab.dart @@ -1,5 +1,8 @@ import 'package:flutter/material.dart'; import 'package:dating_touchme_app/generated/assets.dart'; +import 'package:get/get.dart'; +import 'package:im_flutter_sdk/im_flutter_sdk.dart'; +import '../../controller/message/conversation_controller.dart'; class ConversationTab extends StatefulWidget { const ConversationTab({super.key}); @@ -9,6 +12,8 @@ class ConversationTab extends StatefulWidget { } class _ConversationTabState extends State with AutomaticKeepAliveClientMixin { + final ConversationController controller = Get.find(); + // 模拟数据 - 顶部推荐用户列表 final List> _recommendedUsers = [ {"id": 1, "avatar": Assets.imagesAvatarsExample, "type": "相亲"}, @@ -19,51 +24,6 @@ class _ConversationTabState extends State with AutomaticKeepAli {"id": 6, "avatar": Assets.imagesAvatarsExample, "type": "相亲"}, ]; - // 模拟数据 - 聊天列表 - final List> _chatList = [ - { - "id": 1, - "name": "系统通知", - "avatar": Assets.imagesVerifiedIcon, - "message": "在干嘛", - "time": "19:24", - "unreadCount": 2, - }, - { - "id": 2, - "name": "林园园", - "avatar": Assets.imagesAvatarsExample, - "message": "在干嘛", - "time": "19:24", - "unreadCount": 2, - "isOnline": true, - }, - { - "id": 3, - "name": "李晖", - "avatar": Assets.imagesAvatarsExample, - "message": "好的", - "time": "19:24", - "unreadCount": 0, - }, - { - "id": 4, - "name": "李哲", - "avatar": Assets.imagesAvatarsExample, - "message": "在干嘛", - "time": "19:24", - "unreadCount": 0, - }, - { - "id": 5, - "name": "李夏", - "avatar": Assets.imagesAvatarsExample, - "message": "在干嘛", - "time": "19:24", - "unreadCount": 0, - }, - ]; - @override Widget build(BuildContext context) { super.build(context); @@ -73,14 +33,39 @@ class _ConversationTabState extends State with AutomaticKeepAli _buildRecommendedUsers(), // 聊天列表 Expanded( - child: ListView.builder( - padding: const EdgeInsets.only(top: 8), - itemCount: _chatList.length, - itemBuilder: (context, index) { - final chat = _chatList[index]; - return _buildChatItem(chat); - }, - ), + child: Obx(() { + if (controller.isLoading.value) { + return const Center(child: CircularProgressIndicator()); + } + + if (controller.errorMessage.value.isNotEmpty) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text(controller.errorMessage.value), + ElevatedButton( + onPressed: () => controller.refreshConversations(), + child: const Text('重试'), + ), + ], + ), + ); + } + + if (controller.conversations.isEmpty) { + return const Center(child: Text('暂无会话')); + } + + return ListView.builder( + padding: const EdgeInsets.only(top: 8), + itemCount: controller.conversations.length, + itemBuilder: (context, index) { + final conversation = controller.conversations[index]; + return _buildConversationItem(conversation); + }, + ); + }), ), ], ); @@ -149,100 +134,105 @@ class _ConversationTabState extends State with AutomaticKeepAli ); } - // 构建聊天项 - Widget _buildChatItem(Map chat) { - return Container( - margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 4), - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(8), - ), - child: Row( - children: [ - // 头像 - Stack( - children: [ - Container( - width: 50, - height: 50, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(25), - ), - child: ClipRRect( - borderRadius: BorderRadius.circular(25), - child: Image.asset(chat["avatar"], fit: BoxFit.cover), - ), - ), - if (chat["isOnline"] == true) - Positioned( - bottom: 0, - right: 0, - child: Container( - width: 12, - height: 12, - decoration: BoxDecoration( - color: Colors.green, - borderRadius: BorderRadius.circular(6), - border: Border.all(color: Colors.white, width: 2), + // 构建会话项 + Widget _buildConversationItem(EMConversation conversation) { + // 使用FutureBuilder获取未读消息数和最新消息 + return FutureBuilder( + future: controller.loadContact(conversation.id), + builder: (context, snapshot) { + EMUserInfo? userInfo = snapshot.data; + return FutureBuilder( + future: controller.lastMessage(conversation), + builder: (context, snapshot) { + EMMessage? message = snapshot.data; + return FutureBuilder( + future: controller.getUnreadCount(conversation), + builder: (context, snapshot){ + int unreadCount = snapshot.data ?? 0; + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(16)), ), - ), - ), - ], - ), - - // 信息 - Expanded( - child: Container( - margin: const EdgeInsets.only(left: 12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - chat["name"], - style: const TextStyle(fontWeight: FontWeight.bold), - ), - Text( - chat["time"], - style: const TextStyle( - color: Colors.grey, - fontSize: 12, + margin: const EdgeInsets.only(bottom: 8, left: 16, right: 16), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // 头像 + Container( + width: 56, + height: 56, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(28), + image: DecorationImage( + image: userInfo?.avatarUrl != '' ? NetworkImage(userInfo?.avatarUrl ?? '') : AssetImage(Assets.imagesAvatarsExample), + fit: BoxFit.cover, + ), + ), ), - ), - ], - ), - const SizedBox(height: 4), - Text( - chat["message"], - style: const TextStyle(color: Colors.grey), - overflow: TextOverflow.ellipsis, - ), - ], - ), - ), - ), - - // 未读消息数 - if (chat["unreadCount"] > 0) - Container( - width: 18, - height: 18, - decoration: BoxDecoration( - color: Colors.red, - borderRadius: BorderRadius.circular(9), - ), - alignment: Alignment.center, - child: Text( - chat["unreadCount"].toString(), - style: const TextStyle(color: Colors.white, fontSize: 12), - ), - ), - ], - ), + const SizedBox(width: 12), + // 会话信息 + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + userInfo?.nickName ?? '联系人', + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Colors.black, + ), + ), + Text( + controller.formatMessageTime(message?.serverTime ?? 0), + style: const TextStyle( + fontSize: 12, + color: Colors.grey, + ), + ), + ], + ), + const SizedBox(height: 4), + Text( + controller.getLastMessageContent(message), + style: const TextStyle( + fontSize: 14, + color: Colors.grey, + ), + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + // 未读消息数 + if (unreadCount > 0) + Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), + decoration: BoxDecoration( + color: Colors.red, + borderRadius: BorderRadius.circular(10), + ), + child: Text( + unreadCount.toString(), + style: const TextStyle( + fontSize: 12, + color: Colors.white, + ), + ), + ), + ], + ), + ); + } + ); + }, + ); + }, ); } diff --git a/lib/pages/message/message_page.dart b/lib/pages/message/message_page.dart index 14cc3eb..540055c 100644 --- a/lib/pages/message/message_page.dart +++ b/lib/pages/message/message_page.dart @@ -1,8 +1,10 @@ import 'package:flutter/material.dart'; import 'package:dating_touchme_app/generated/assets.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; import 'conversation_tab.dart'; import 'friend_tab.dart'; +import '../../controller/message/conversation_controller.dart'; class MessagePage extends StatefulWidget { const MessagePage({super.key}); @@ -18,6 +20,8 @@ class _MessagePageState extends State with AutomaticKeepAliveClient void initState() { super.initState(); _tabController = TabController(length: 2, vsync: this); + // 注册ConversationController + Get.put(ConversationController()); } @override