|
|
|
@ -1,15 +1,24 @@ |
|
|
|
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; |
|
|
|
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'; |
|
|
|
import '../../model/home/marriage_data.dart'; |
|
|
|
import '../../pages/home/report_page.dart'; |
|
|
|
import '../../pages/home/user_information_page.dart'; |
|
|
|
import '../message/conversation_controller.dart'; |
|
|
|
|
|
|
|
class ChatSettingsController extends GetxController { |
|
|
|
final String userId; |
|
|
|
final MarriageData? userData; |
|
|
|
final _storage = GetStorage(); |
|
|
|
|
|
|
|
// 用户信息 |
|
|
|
final Rx<EMUserInfo?> userInfo = Rx<EMUserInfo?>(null); |
|
|
|
|
|
|
|
// 用户miId(用于跳转到用户主页) |
|
|
|
String? miId; |
|
|
|
|
|
|
|
// 是否拉黑 |
|
|
|
final RxBool isBlacklisted = RxBool(false); |
|
|
|
@ -20,36 +29,297 @@ class ChatSettingsController extends GetxController { |
|
|
|
// 备注名 |
|
|
|
final RxString remark = RxString(''); |
|
|
|
|
|
|
|
ChatSettingsController({required this.userId}); |
|
|
|
ChatSettingsController({ |
|
|
|
required this.userId, |
|
|
|
this.userData, |
|
|
|
}); |
|
|
|
|
|
|
|
@override |
|
|
|
void onInit() { |
|
|
|
super.onInit(); |
|
|
|
// 初始化时获取用户信息 |
|
|
|
fetchUserInfo(); |
|
|
|
// 检查黑名单状态 |
|
|
|
checkBlacklistStatus(); |
|
|
|
// 检查关注状态 |
|
|
|
checkFollowStatus(); |
|
|
|
|
|
|
|
try { |
|
|
|
// 验证 userId |
|
|
|
if (userId.isEmpty) { |
|
|
|
print('❌ [ChatSettings] userId 为空'); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// 如果传入了用户信息,优先使用(同步操作,安全) |
|
|
|
if (userData != null) { |
|
|
|
try { |
|
|
|
miId = userData!.miId; |
|
|
|
} catch (e) { |
|
|
|
print('❌ [ChatSettings] 设置 miId 失败: $e'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 加载备注名(同步,立即执行,安全) |
|
|
|
try { |
|
|
|
loadRemark(); |
|
|
|
} catch (e) { |
|
|
|
print('❌ [ChatSettings] 加载备注名失败: $e'); |
|
|
|
} |
|
|
|
|
|
|
|
// 延迟执行异步操作,避免阻塞 UI |
|
|
|
Future.microtask(() { |
|
|
|
try { |
|
|
|
// 如果传入了用户信息,同步到缓存 |
|
|
|
if (userData != null) { |
|
|
|
_syncUserDataToCache(); |
|
|
|
} |
|
|
|
// 初始化时获取用户信息(异步,不阻塞) |
|
|
|
fetchUserInfo(); |
|
|
|
// 检查黑名单状态(异步,不阻塞) |
|
|
|
checkBlacklistStatus(); |
|
|
|
// 检查关注状态(异步,不阻塞) |
|
|
|
checkFollowStatus(); |
|
|
|
} catch (e, stackTrace) { |
|
|
|
print('❌ [ChatSettings] 异步初始化失败: $e'); |
|
|
|
print('堆栈跟踪: $stackTrace'); |
|
|
|
} |
|
|
|
}); |
|
|
|
} catch (e, stackTrace) { |
|
|
|
print('❌ [ChatSettings] onInit 失败: $e'); |
|
|
|
print('堆栈跟踪: $stackTrace'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// 将传入的用户信息同步到 ConversationController 缓存 |
|
|
|
void _syncUserDataToCache() { |
|
|
|
try { |
|
|
|
if (userData == null) return; |
|
|
|
|
|
|
|
if (Get.isRegistered<ConversationController>()) { |
|
|
|
try { |
|
|
|
final conversationController = Get.find<ConversationController>(); |
|
|
|
final extendedInfo = ExtendedUserInfo( |
|
|
|
userId: userId, |
|
|
|
nickName: userData!.nickName, |
|
|
|
avatarUrl: userData!.profilePhoto.trim().replaceAll('`', ''), |
|
|
|
); |
|
|
|
conversationController.cacheUserInfo(userId, extendedInfo); |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('✅ [ChatSettings] 已同步用户信息到缓存: nickName=${userData!.nickName}'); |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('⚠️ [ChatSettings] 获取 ConversationController 失败: $e'); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('⚠️ [ChatSettings] 同步用户信息到缓存失败: $e'); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// 获取用户信息 |
|
|
|
Future<void> fetchUserInfo() async { |
|
|
|
try { |
|
|
|
final EMUserInfo? info = await IMManager.instance.getUserInfo(userId); |
|
|
|
if (info != null) { |
|
|
|
userInfo.value = info; |
|
|
|
// 0. 如果传入了用户信息,优先使用(已在 onInit 中处理) |
|
|
|
if (userData != null) { |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('获取用户信息成功: ${info.nickName}'); |
|
|
|
Get.log('✅ [ChatSettings] 使用传入的用户信息: nickName=${userData!.nickName}, miId=${userData!.miId}'); |
|
|
|
} |
|
|
|
} else { |
|
|
|
// 仍然尝试从IM获取,以便更新 userInfo.value |
|
|
|
} |
|
|
|
|
|
|
|
// 1. 优先从ConversationController的缓存中获取用户信息 |
|
|
|
if (Get.isRegistered<ConversationController>()) { |
|
|
|
try { |
|
|
|
final conversationController = Get.find<ConversationController>(); |
|
|
|
final cachedUserInfo = conversationController.getCachedUserInfo(userId); |
|
|
|
if (cachedUserInfo != null && (cachedUserInfo.nickName != null || cachedUserInfo.avatarUrl != null)) { |
|
|
|
// 使用缓存中的用户信息创建 EMUserInfo |
|
|
|
// 注意:EMUserInfo 可能没有公开构造函数,所以我们先尝试从IM获取 |
|
|
|
// 如果IM没有,我们使用缓存的信息来显示 |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('✅ [ChatSettings] 从缓存获取到用户信息: userId=$userId, nickName=${cachedUserInfo.nickName}'); |
|
|
|
} |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('⚠️ [ChatSettings] 获取 ConversationController 失败: $e'); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 2. 尝试从IM获取用户信息 |
|
|
|
EMUserInfo? info; |
|
|
|
try { |
|
|
|
info = await IMManager.instance.getUserInfo(userId); |
|
|
|
if (info != null && (info.nickName?.isNotEmpty ?? false)) { |
|
|
|
userInfo.value = info; |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('✅ [ChatSettings] 从IM获取到用户信息: ${info.nickName}'); |
|
|
|
} |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('未找到用户信息: $userId'); |
|
|
|
Get.log('⚠️ [ChatSettings] 从IM获取用户信息失败: $e'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 3. 如果IM没有用户信息,尝试从会话历史消息中提取 |
|
|
|
if (userInfo.value == null || (userInfo.value?.nickName?.isEmpty ?? true)) { |
|
|
|
await _fetchUserInfoFromConversation(); |
|
|
|
} |
|
|
|
|
|
|
|
// 4. 尝试从会话历史消息中获取miId |
|
|
|
await _tryGetMiIdFromConversation(); |
|
|
|
} catch (e) { |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('❌ [ChatSettings] 获取用户信息失败: $e'); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// 从会话历史消息中提取用户信息 |
|
|
|
Future<void> _fetchUserInfoFromConversation() async { |
|
|
|
try { |
|
|
|
final conversation = await EMClient.getInstance.chatManager.getConversation( |
|
|
|
userId, |
|
|
|
type: EMConversationType.Chat, |
|
|
|
createIfNeed: false, |
|
|
|
); |
|
|
|
|
|
|
|
if (conversation == null) { |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('⚠️ [ChatSettings] 会话不存在: $userId'); |
|
|
|
} |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
final messages = await conversation.loadMessages(loadCount: 20); |
|
|
|
|
|
|
|
for (var message in messages) { |
|
|
|
try { |
|
|
|
final attributes = message.attributes; |
|
|
|
if (attributes == null || attributes.isEmpty) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
String? nickName; |
|
|
|
String? avatarUrl; |
|
|
|
|
|
|
|
if (message.direction == MessageDirection.RECEIVE) { |
|
|
|
// 接收到的消息:从扩展字段中提取发送者信息(sender_ 前缀) |
|
|
|
final fromUserId = message.from; |
|
|
|
if (fromUserId != null && fromUserId == userId) { |
|
|
|
nickName = attributes['sender_nickName'] as String? ?? attributes['nickName'] as String?; |
|
|
|
avatarUrl = attributes['sender_avatarUrl'] as String? ?? attributes['avatarUrl'] as String?; |
|
|
|
} |
|
|
|
} else if (message.direction == MessageDirection.SEND) { |
|
|
|
// 发送的消息:从扩展字段中提取接收者信息(receiver_ 前缀) |
|
|
|
final toUserId = message.to; |
|
|
|
if (toUserId != null && toUserId == userId) { |
|
|
|
nickName = attributes['receiver_nickName'] as String?; |
|
|
|
avatarUrl = attributes['receiver_avatarUrl'] as String?; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (nickName != null || avatarUrl != null) { |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('✅ [ChatSettings] 从消息扩展字段提取到用户信息: nickName=$nickName, avatarUrl=$avatarUrl'); |
|
|
|
} |
|
|
|
|
|
|
|
// 将提取到的用户信息保存到 ConversationController 的缓存中 |
|
|
|
if (Get.isRegistered<ConversationController>()) { |
|
|
|
try { |
|
|
|
final conversationController = Get.find<ConversationController>(); |
|
|
|
final extendedInfo = ExtendedUserInfo( |
|
|
|
userId: userId, |
|
|
|
nickName: nickName, |
|
|
|
avatarUrl: avatarUrl, |
|
|
|
); |
|
|
|
conversationController.cacheUserInfo(userId, extendedInfo); |
|
|
|
} catch (e) { |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('⚠️ [ChatSettings] 获取 ConversationController 失败: $e'); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 如果IM没有返回用户信息,尝试再次从IM获取(可能信息已更新) |
|
|
|
if (userInfo.value == null || (userInfo.value?.nickName?.isEmpty ?? true)) { |
|
|
|
try { |
|
|
|
final imInfo = await IMManager.instance.getUserInfo(userId); |
|
|
|
if (imInfo != null) { |
|
|
|
userInfo.value = imInfo; |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
// 忽略错误,使用缓存的信息 |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 再次尝试从缓存获取 |
|
|
|
if (Get.isRegistered<ConversationController>()) { |
|
|
|
try { |
|
|
|
final conversationController = Get.find<ConversationController>(); |
|
|
|
final cachedUserInfo = conversationController.getCachedUserInfo(userId); |
|
|
|
if (cachedUserInfo != null && userInfo.value == null) { |
|
|
|
// 如果IM没有返回用户信息,但缓存中有,尝试再次从IM获取 |
|
|
|
// 或者直接使用缓存的信息(通过 getDisplayName 方法) |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('✅ [ChatSettings] 使用缓存中的用户信息: nickName=${cachedUserInfo.nickName}'); |
|
|
|
} |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('⚠️ [ChatSettings] 获取 ConversationController 失败: $e'); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('❌ [ChatSettings] 从会话提取用户信息失败: $e'); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// 尝试从会话历史消息中获取miId |
|
|
|
Future<void> _tryGetMiIdFromConversation() async { |
|
|
|
try { |
|
|
|
final conversation = await EMClient.getInstance.chatManager.getConversation( |
|
|
|
userId, |
|
|
|
type: EMConversationType.Chat, |
|
|
|
createIfNeed: false, |
|
|
|
); |
|
|
|
if (conversation != null) { |
|
|
|
final messages = await conversation.loadMessages(loadCount: 20); |
|
|
|
for (var message in messages) { |
|
|
|
try { |
|
|
|
final attributes = message.attributes; |
|
|
|
if (attributes != null && attributes.isNotEmpty) { |
|
|
|
// 尝试从消息扩展字段中获取miId |
|
|
|
final msgMiId = attributes['sender_miId'] as String? ?? |
|
|
|
attributes['receiver_miId'] as String? ?? |
|
|
|
attributes['miId'] as String?; |
|
|
|
if (msgMiId != null && msgMiId.isNotEmpty) { |
|
|
|
miId = msgMiId; |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('从消息扩展字段获取到miId: $miId'); |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('获取用户信息失败: $e'); |
|
|
|
Get.log('从会话获取miId失败: $e'); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -127,10 +397,19 @@ class ChatSettingsController extends GetxController { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// 加载备注名 |
|
|
|
void loadRemark() { |
|
|
|
final savedRemark = _storage.read<String>('remark_$userId'); |
|
|
|
if (savedRemark != null) { |
|
|
|
remark.value = savedRemark; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// 设置备注名 |
|
|
|
Future<void> setRemark(String newRemark) async { |
|
|
|
try { |
|
|
|
// TODO: 调用实际的设置备注名API |
|
|
|
// 保存到本地存储 |
|
|
|
await _storage.write('remark_$userId', newRemark); |
|
|
|
remark.value = newRemark; |
|
|
|
SmartDialog.showToast('备注名设置成功'); |
|
|
|
update(); |
|
|
|
@ -141,11 +420,137 @@ class ChatSettingsController extends GetxController { |
|
|
|
SmartDialog.showToast('设置失败,请重试'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// 获取显示名称(优先显示备注名,其次显示昵称) |
|
|
|
String getDisplayName() { |
|
|
|
try { |
|
|
|
if (remark.value.isNotEmpty) { |
|
|
|
return remark.value; |
|
|
|
} |
|
|
|
|
|
|
|
// 优先使用传入的用户信息 |
|
|
|
if (userData != null && userData!.nickName.isNotEmpty) { |
|
|
|
return userData!.nickName; |
|
|
|
} |
|
|
|
|
|
|
|
// 其次使用 IM 返回的用户信息 |
|
|
|
if (userInfo.value != null && userInfo.value!.nickName != null && userInfo.value!.nickName!.isNotEmpty) { |
|
|
|
return userInfo.value!.nickName!; |
|
|
|
} |
|
|
|
|
|
|
|
// 如果 IM 没有,尝试从 ConversationController 缓存中获取 |
|
|
|
if (Get.isRegistered<ConversationController>()) { |
|
|
|
try { |
|
|
|
final conversationController = Get.find<ConversationController>(); |
|
|
|
final cachedUserInfo = conversationController.getCachedUserInfo(userId); |
|
|
|
if (cachedUserInfo != null && cachedUserInfo.nickName != null && cachedUserInfo.nickName!.isNotEmpty) { |
|
|
|
return cachedUserInfo.nickName!; |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
// 忽略错误,使用默认值 |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return userId.isNotEmpty ? userId : '未知用户'; |
|
|
|
} catch (e) { |
|
|
|
print('❌ [ChatSettings] getDisplayName 失败: $e'); |
|
|
|
return userId.isNotEmpty ? userId : '未知用户'; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// 获取用户头像URL |
|
|
|
String? getAvatarUrl() { |
|
|
|
try { |
|
|
|
// 优先使用传入的用户信息 |
|
|
|
if (userData != null && userData!.profilePhoto.isNotEmpty) { |
|
|
|
return userData!.profilePhoto.trim().replaceAll('`', ''); |
|
|
|
} |
|
|
|
|
|
|
|
// 其次使用 IM 返回的用户信息 |
|
|
|
if (userInfo.value != null && userInfo.value!.avatarUrl != null && userInfo.value!.avatarUrl!.isNotEmpty) { |
|
|
|
return userInfo.value!.avatarUrl!; |
|
|
|
} |
|
|
|
|
|
|
|
// 如果 IM 没有,尝试从 ConversationController 缓存中获取 |
|
|
|
if (Get.isRegistered<ConversationController>()) { |
|
|
|
try { |
|
|
|
final conversationController = Get.find<ConversationController>(); |
|
|
|
final cachedUserInfo = conversationController.getCachedUserInfo(userId); |
|
|
|
if (cachedUserInfo != null && cachedUserInfo.avatarUrl != null && cachedUserInfo.avatarUrl!.isNotEmpty) { |
|
|
|
return cachedUserInfo.avatarUrl!; |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
// 忽略错误,返回 null |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return null; |
|
|
|
} catch (e) { |
|
|
|
print('❌ [ChatSettings] getAvatarUrl 失败: $e'); |
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// 举报用户 |
|
|
|
void reportUser() { |
|
|
|
// 跳转到举报页面 |
|
|
|
Get.to(() => ReportPage()); |
|
|
|
} |
|
|
|
|
|
|
|
/// 跳转到用户主页 |
|
|
|
Future<void> navigateToUserProfile() async { |
|
|
|
try { |
|
|
|
String? targetMiId; |
|
|
|
String targetUserId = userId; |
|
|
|
|
|
|
|
// 优先使用传入的用户信息中的 miId |
|
|
|
if (userData != null && userData!.miId.isNotEmpty) { |
|
|
|
targetMiId = userData!.miId; |
|
|
|
targetUserId = userData!.userId.isNotEmpty ? userData!.userId : userId; |
|
|
|
} else if (miId != null && miId!.isNotEmpty) { |
|
|
|
// 如果已经有miId,直接使用 |
|
|
|
targetMiId = miId; |
|
|
|
} else { |
|
|
|
// 如果没有miId,尝试从会话中获取 |
|
|
|
await _tryGetMiIdFromConversation(); |
|
|
|
if (miId != null && miId!.isNotEmpty) { |
|
|
|
targetMiId = miId; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 验证参数 |
|
|
|
if (targetMiId == null || targetMiId.isEmpty) { |
|
|
|
SmartDialog.showToast('无法获取用户信息,请稍后重试'); |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('❌ [ChatSettings] 无法跳转到用户主页:miId为空'); |
|
|
|
} |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (targetUserId.isEmpty) { |
|
|
|
SmartDialog.showToast('用户ID无效'); |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('❌ [ChatSettings] 无法跳转到用户主页:userId为空'); |
|
|
|
} |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('✅ [ChatSettings] 跳转到用户主页:miId=$targetMiId, userId=$targetUserId'); |
|
|
|
} |
|
|
|
|
|
|
|
// 跳转到用户主页 |
|
|
|
await Get.to(() => UserInformationPage( |
|
|
|
miId: targetMiId!, |
|
|
|
userId: targetUserId, |
|
|
|
)); |
|
|
|
} catch (e, stackTrace) { |
|
|
|
if (Get.isLogEnable) { |
|
|
|
Get.log('❌ [ChatSettings] 跳转到用户主页失败: $e'); |
|
|
|
Get.log('堆栈跟踪: $stackTrace'); |
|
|
|
} |
|
|
|
SmartDialog.showToast('跳转失败,请稍后重试'); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|