// ignore_for_file: unrelated_type_equality_checks, avoid_print import 'dart:convert'; import 'package:flutter/cupertino.dart'; import 'package:tencent_im_base/tencent_im_base.dart'; import 'package:tencent_cloud_chat_uikit/ui/constants/history_message_constant.dart'; import 'package:tencent_cloud_chat_uikit/ui/constants/time.dart'; class MessageUtils { // 判断CallingData的方式和Trtc的方法一致 static isCallingData(String data) { try { Map customMap = jsonDecode(data); if (customMap.containsKey('businessID') && customMap['businessID'] == 1) { return true; } } catch (e) { print("isCallingData json parse error"); return false; } return false; } // 是否是群组TRTC信息 static isGroupCallingMessage(V2TimMessage message) { final isGroup = message.groupID != null; final isCustomMessage = message.elemType == MessageElemType.V2TIM_ELEM_TYPE_CUSTOM; if (isCustomMessage) { final customElemData = message.customElem?.data ?? ""; return isCallingData(customElemData) && isGroup; } return false; } static String _getGroupChangeType(V2TimGroupChangeInfo info) { int? type = info.type; var value = info.value; String s = TIM_t('群资料信息'); switch (type) { case GroupChangeInfoType.V2TIM_GROUP_INFO_CHANGE_TYPE_CUSTOM: s = TIM_t("自定义字段"); break; case GroupChangeInfoType.V2TIM_GROUP_INFO_CHANGE_TYPE_FACE_URL: s = TIM_t("群头像"); break; case GroupChangeInfoType.V2TIM_GROUP_INFO_CHANGE_TYPE_INTRODUCTION: s = TIM_t("群简介"); break; case GroupChangeInfoType.V2TIM_GROUP_INFO_CHANGE_TYPE_NAME: s = TIM_t("群名称"); break; case GroupChangeInfoType.V2TIM_GROUP_INFO_CHANGE_TYPE_NOTIFICATION: s = TIM_t("群公告"); break; case GroupChangeInfoType.V2TIM_GROUP_INFO_CHANGE_TYPE_OWNER: s = TIM_t("群主"); break; case GroupChangeInfoType.V2TIM_GROUP_INFO_CHANGE_TYPE_SHUT_UP_ALL: s = TIM_t("全员禁言状态"); break; case GroupChangeInfoType.V2TIM_GROUP_INFO_CHANGE_TYPE_RECEIVE_MESSAGE_OPT: s = TIM_t("消息接收方式"); break; case GroupChangeInfoType.V2TIM_GROUP_INFO_CHANGE_TYPE_GROUP_ADD_OPT: s = TIM_t("加群方式"); break; } final String option8 = s; if (value != null && value.isNotEmpty) { return TIM_t_para("{{option8}}为 ", "$option8为 ")(option8: option8) + ' $value'; } else { return option8; } } static String? _getOpUserNick(V2TimGroupMemberInfo opUser) { return opUser.friendRemark == null || opUser.friendRemark == '' ? opUser.nickName == null || opUser.nickName == '' ? opUser.userID : opUser.nickName : opUser.friendRemark; } static String? _getMemberNickName(V2TimGroupMemberInfo e) { final friendRemark = e.friendRemark; final nameCard = e.nameCard; final nickName = e.nickName; final userID = e.userID; if (friendRemark != null && friendRemark != "") { return friendRemark; } else if (nameCard != null && nameCard != "") { return nameCard; } else if (nickName != null && nickName != "") { return nickName; } else { return userID; } } static String groupTipsMessageAbstract(V2TimGroupTipsElem groupTipsElem) { String displayMessage; final operationType = groupTipsElem.type; final operationMember = groupTipsElem.opMember; final memberList = groupTipsElem.memberList; final opUserNickName = _getOpUserNick(operationMember); switch (operationType) { case GroupTipsElemType.V2TIM_GROUP_TIPS_TYPE_GROUP_INFO_CHANGE: final groupChangeInfoList = groupTipsElem.groupChangeInfoList; final String? option7 = opUserNickName ?? ""; var changedInfoString = groupChangeInfoList!.map((e) => _getGroupChangeType(e!)).join("、"); if (changedInfoString.isEmpty) { changedInfoString = TIM_t("群资料"); } displayMessage = TIM_t_para("{{option7}}修改", "$option7修改")(option7: option7) + changedInfoString; break; case GroupTipsElemType.V2TIM_GROUP_TIPS_TYPE_QUIT: final String? option6 = opUserNickName ?? ""; displayMessage = TIM_t_para("{{option6}}退出群聊", "$option6退出群聊")(option6: option6); break; case GroupTipsElemType.V2TIM_GROUP_TIPS_TYPE_INVITE: final option5 = memberList!.map((e) => _getMemberNickName(e!).toString()).join("、"); final inviteUser = _getOpUserNick(operationMember); displayMessage = '$inviteUser' + TIM_t_para("邀请{{option5}}加入群组", "邀请$option5加入群组")(option5: option5); break; case GroupTipsElemType.V2TIM_GROUP_TIPS_TYPE_KICKED: final option4 = memberList!.map((e) => _getMemberNickName(e!).toString()).join("、"); final kickUser = _getOpUserNick(operationMember); displayMessage = '$kickUser' + TIM_t_para("将{{option4}}踢出群组", "将$option4踢出群组")(option4: option4); break; case GroupTipsElemType.V2TIM_GROUP_TIPS_TYPE_JOIN: final option3 = memberList!.map((e) => _getMemberNickName(e!).toString()).join("、"); displayMessage = TIM_t_para("用户{{option3}}加入了群聊", "用户$option3加入了群聊")( option3: option3); break; case GroupTipsElemType.V2TIM_GROUP_TIPS_TYPE_MEMBER_INFO_CHANGE: displayMessage = groupTipsElem.memberList!.map((e) { final changedMember = groupTipsElem.memberChangeInfoList! .firstWhere((element) => element!.userID == e!.userID); final isMute = changedMember!.muteTime != 0; final option2 = _getMemberNickName(e!); final displayMessage = isMute ? TIM_t("禁言") : TIM_t("解除禁言"); return TIM_t_para("{{option2}} 被", "$option2 被")(option2: option2) + displayMessage; }).join("、"); break; case GroupTipsElemType.V2TIM_GROUP_TIPS_TYPE_SET_ADMIN: final adminMember = memberList!.map((e) => _getMemberNickName(e!).toString()).join("、"); final opMember = _getOpUserNick(operationMember); final option1 = adminMember; displayMessage = '$opMember' + TIM_t_para("将 {{option1}} 设置为管理员", "将 $option1 设置为管理员")( option1: option1); break; case GroupTipsElemType.V2TIM_GROUP_TIPS_TYPE_CANCEL_ADMIN: final adminMember = memberList!.map((e) => _getMemberNickName(e!).toString()).join("、"); final opMember = _getOpUserNick(operationMember); final option1 = adminMember; displayMessage = '$opMember' + TIM_t_para("将 {{option1}} 取消管理员", "将 $option1 取消管理员")( option1: option1); break; default: final String option2 = operationType.toString(); displayMessage = TIM_t_para("系统消息 {{option2}}", "系统消息 $option2")(option2: option2); break; } return displayMessage; } static String formatVideoTime(int time) { List times = []; if (time <= 0) return '0:01'; if (time >= TimeConst.DAY_SEC) return '1d+'; for (int idx = 0; idx < TimeConst.SEC_SERIES.length; idx++) { int sec = TimeConst.SEC_SERIES[idx]; if (time >= sec) { times.add((time / sec).floor()); time = time % sec; } else if (idx > 0) { times.add(0); } } times.add(time); String formatTime = times[0].toString(); for (int idx = 1; idx < times.length; idx++) { if (times[idx] < 10) { formatTime += ':0${times[idx].toString()}'; } else { formatTime += ':${times[idx].toString()}'; } } return formatTime; } static String handleCustomMessageString(V2TimMessage message) { final customElem = message.customElem; final callingMessage = CallingMessage.getCallMessage(customElem); if (callingMessage != null) { // 如果是结束消息 final isCallEnd = CallingMessage.isCallEndExist(callingMessage); String? option2 = ""; if (isCallEnd) { option2 = CallingMessage.getShowTime(callingMessage.callEnd!); } return isCallEnd ? (TIM_t_para("通话时间:{{option2}}", "通话时间:$option2")(option2: option2)) : (CallingMessage.getActionType(callingMessage.actionType!)); } else { return TIM_t("自定义消息"); } } static handleCustomMessage(V2TimMessage message, context) { // 这个函数应该返回String,目前已经切走用不上了,但是不敢删QAQ,就这么留着吧。 final customElem = message.customElem; final callingMessage = CallingMessage.getCallMessage(customElem); if (callingMessage != null) { // 如果是结束消息 final isCallEnd = CallingMessage.isCallEndExist(callingMessage); final isVoiceCall = callingMessage.callType == 1; String? option2 = ""; if (isCallEnd) { option2 = CallingMessage.getShowTime(callingMessage.callEnd!); } return Row( mainAxisSize: MainAxisSize.min, children: [ Padding( padding: const EdgeInsets.only(right: 4), child: Image.asset( isVoiceCall ? "images/voice_call.png" : "images/video_call.png", package: 'tencent_cloud_chat_uikit', height: 16, width: 16, ), ), isCallEnd ? Text(TIM_t_para("通话时间:{{option2}}", "通话时间:$option2")( option2: option2)) : Text( CallingMessage.getActionType(callingMessage.actionType!)), // if (isFromSelf) // Padding( // padding: const EdgeInsets.only(left: 4), // child: Image.asset( // isVoiceCall // ? "images/voice_call.png" // : "images/video_call_self.png", // package: 'tencent_cloud_chat_uikit', // height: 16, // width: 16, // ), // ), ], ); } else { return const Text("[自定义]"); } } static Widget wrapMessageTips(Widget child, TUITheme? theme) { return Container( margin: const EdgeInsets.symmetric(vertical: 10), child: child); } static String getAbstractMessage(V2TimMessage message) { final msgType = message.elemType; switch (msgType) { case MessageElemType.V2TIM_ELEM_TYPE_CUSTOM: return handleCustomMessageString(message); case MessageElemType.V2TIM_ELEM_TYPE_SOUND: return TIM_t("[语音]"); case MessageElemType.V2TIM_ELEM_TYPE_TEXT: return message.textElem!.text as String; case MessageElemType.V2TIM_ELEM_TYPE_FACE: return TIM_t("[表情]"); case MessageElemType.V2TIM_ELEM_TYPE_FILE: final String? option2 = message.fileElem!.fileName ?? ""; return TIM_t_para("[文件] {{option2}}", "[文件] $option2")( option2: option2); case MessageElemType.V2TIM_ELEM_TYPE_GROUP_TIPS: return MessageUtils.groupTipsMessageAbstract(message.groupTipsElem!); case MessageElemType.V2TIM_ELEM_TYPE_IMAGE: return TIM_t("[图片]"); case MessageElemType.V2TIM_ELEM_TYPE_VIDEO: return TIM_t("[视频]"); case MessageElemType.V2TIM_ELEM_TYPE_LOCATION: return TIM_t("[位置]"); case MessageElemType.V2TIM_ELEM_TYPE_MERGER: return TIM_t("[聊天记录]"); default: return TIM_t("未知消息"); } } static V2TimImage? getImageFromImgList( List? list, List order) { V2TimImage? img; try { for (String type in order) { img = list?.firstWhere( (e) => e?.type == HistoryMessageDartConstant.V2_TIM_IMAGE_TYPES[type], orElse: () => null); } } catch (e) { print('getImageFromImgList error ${e.toString()}'); } return img; } static String getDisplayName(V2TimMessage message) { final friendRemark = message.friendRemark ?? ""; final nameCard = message.nameCard ?? ""; final nickName = message.nickName ?? ""; final sender = message.sender ?? ""; final displayName = friendRemark.isNotEmpty ? friendRemark : nameCard.isNotEmpty ? nameCard : nickName.isNotEmpty ? nickName : sender; return displayName.toString(); } static Future?> handleMessageError( Future?> fun, BuildContext context) async { final res = await fun; return handleMessageErrorCode(res, context); } static V2TimValueCallback? handleMessageErrorCode( V2TimValueCallback? sendMsgRes, BuildContext context) { if (sendMsgRes == null) return null; return sendMsgRes; } }