// // V2TIMMessage+Extension.swift // Lanu // // Created by OneeChan on 2025/12/14. // import Foundation extension V2TIMMessage { var displayString: String? { let hasRisk = hasRiskContent let isRevoked = status == .MSG_STATUS_LOCAL_REVOKED if hasRisk, !isRevoked { return TIMLocalizedText.shared.commonText("TUIKitMessageDisplayRiskContent") } if isRevoked { return revokeDisplayString } return displayStringForMessageElement } private var revokeDisplayString: String? { var revoker = sender if let revokerInfo { revoker = revokerInfo.userID } var content = TIMLocalizedText.shared.commonText("TUIKitMessageTipsNormalRecallMessage") if revoker == sender { if isSelf { content = TIMLocalizedText.shared.commonText("TUIKitMessageTipsYouRecallMessage") } else { if userID?.isEmpty == false { content = TIMLocalizedText.shared.commonText("TUIKitMessageTipsOthersRecallMessage") } else if groupID?.isEmpty == false { content = String(format: TIMLocalizedText.shared.commonText("TUIKitMessageTipsRecallMessageFormat"), showName) } else { } } } else { var userName = showName if let revokerInfo { userName = revokerInfo.nickName ?? "" } content = String(format: TIMLocalizedText.shared.commonText("TUIKitMessageTipsRecallMessageFormat"), userName) } return content } private var displayStringForMessageElement: String? { switch elemType { case .ELEM_TYPE_TEXT: textElem?.text?.getEmojiDescContent case .ELEM_TYPE_IMAGE: TIMLocalizedText.shared.commonText("TUIkitMessageTypeImage") case .ELEM_TYPE_SOUND: TIMLocalizedText.shared.commonText("TUIKitMessageTypeVoice") case .ELEM_TYPE_VIDEO: TIMLocalizedText.shared.commonText("TUIkitMessageTypeVideo") case .ELEM_TYPE_FILE: TIMLocalizedText.shared.commonText("TUIkitMessageTypeFile") case .ELEM_TYPE_FACE: TIMLocalizedText.shared.commonText("TUIKitMessageTypeAnimateEmoji") case .ELEM_TYPE_MERGER: String(format: "[%@]", TIMLocalizedText.shared.commonText("TUIKitRelayChatHistory")) case .ELEM_TYPE_GROUP_TIPS: groupTipsDisplayString case .ELEM_TYPE_CUSTOM: TIMLocalizedText.shared.commonText("TUIKitMessageTipsUnsupportCustomMessage") default: TIMLocalizedText.shared.commonText("TUIKitMessageTipsUnsupportCustomMessage") } } private var groupTipsDisplayString: String? { guard let tips = groupTipsElem else { return nil } let opUser = groupOpMemberShowName(info: tips.opMember) let userList = groupUserNameList var str = "" switch tips.type { case .GROUP_TIPS_TYPE_JOIN: if !opUser.isEmpty { if userList.isEmpty || (userList.count == 1 && opUser == userList.first) { str = String(format: TIMLocalizedText.shared.commonText("TUIKitMessageTipsJoinGroupFormat"), opUser) } else { let users = userList.joined(separator: "、") str = String(format: TIMLocalizedText.shared.commonText("TUIKitMessageTipsInviteJoinGroupFormat"), opUser, users) } } case .GROUP_TIPS_TYPE_INVITE: if !userList.isEmpty { let users = userList.joined(separator: "、") str = String(format: TIMLocalizedText.shared.commonText("TUIKitMessageTipsInviteJoinGroupFormat"), opUser, users) } case .GROUP_TIPS_TYPE_QUIT: if !opUser.isEmpty { str = String(format: TIMLocalizedText.shared.commonText("TUIKitMessageTipsLeaveGroupFormat"), opUser) } case .GROUP_TIPS_TYPE_KICKED: if !userList.isEmpty { let users = userList.joined(separator: "、") str = String(format: TIMLocalizedText.shared.commonText("TUIKitMessageTipsKickoffGroupFormat"), opUser, users) } case .GROUP_TIPS_TYPE_SET_ADMIN: if !userList.isEmpty { let users = userList.joined(separator: "、") str = String(format: TIMLocalizedText.shared.commonText("TUIKitMessageTipsSettAdminFormat"), users) } case .GROUP_TIPS_TYPE_CANCEL_ADMIN: if !userList.isEmpty { let users = userList.joined(separator: "、") str = String(format: TIMLocalizedText.shared.commonText("TUIKitMessageTipsCancelAdminFormat"), users) } case .GROUP_TIPS_TYPE_GROUP_INFO_CHANGE: str = opGroupInfoChangedFormatStr(opUser: opUser, userList: userList, tips: tips) case .GROUP_TIPS_TYPE_MEMBER_INFO_CHANGE: tips.memberChangeInfoList.forEach { info in let userId = info.userID let muteTime = info.muteTime let showName = if let user = tips.memberList.first(where: { $0.userID == userId }) { groupOpMemberShowName(info: user) } else { "" } str = String(format: "%@ %@", userId?.isMyUid == true ? TIMLocalizedText.shared.commonText("You") : showName, muteTime == 0 ? TIMLocalizedText.shared.commonText("TUIKitMessageTipsUnmute") : TIMLocalizedText.shared.commonText("TUIKitMessageTipsMute")) } case .GROUP_TIPS_TYPE_PINNED_MESSAGE_ADDED: if !opUser.isEmpty { str = String(format: TIMLocalizedText.shared.commonText("TUIKitMessageTipsGroupPinMessage"), opUser) } case .GROUP_TIPS_TYPE_PINNED_MESSAGE_DELETED: if !opUser.isEmpty { str = String(format: TIMLocalizedText.shared.commonText("TUIKitMessageTipsGroupUnPinMessage"), opUser) } default: break } return str } private var showName: String { if let nameCard, !nameCard.isEmpty { nameCard } else if let friendRemark, !friendRemark.isEmpty { friendRemark } else if let nickName, !nickName.isEmpty { nickName } else { sender ?? "" } } private func groupOpMemberShowName(info: V2TIMGroupMemberInfo) -> String { if let nameCard = info.nameCard, !nameCard.isEmpty { nameCard } else if let nickName = info.nickName, !nickName.isEmpty { nickName } else { info.userID ?? "" } } private var groupUserNameList: [String] { groupTipsElem?.memberList.compactMap { groupOpMemberShowName(info: $0) } ?? [] } private func opGroupInfoChangedFormatStr(opUser: String, userList: [String], tips: V2TIMGroupTipsElem) -> String { var str = String(format: "%@", opUser) for info in tips.groupChangeInfoList { switch info.type { case .GROUP_INFO_CHANGE_TYPE_NAME: str = String(format: TIMLocalizedText.shared.commonText("TUIkitMessageTipsEditGroupNameFormat"), str, info.value ?? "") case .GROUP_INFO_CHANGE_TYPE_INTRODUCTION: str = String(format: TIMLocalizedText.shared.commonText("TUIKitMessageTipsEditGroupIntroFormat"), str, info.value ?? "") case .GROUP_INFO_CHANGE_TYPE_NOTIFICATION: if let value = info.value, !value.isEmpty { str = String(format: TIMLocalizedText.shared.commonText("TUIKitMessageTipsEditGroupAnnounceFormat"), str, value) } else { str = String(format: TIMLocalizedText.shared.commonText("TUIKitMessageTipsDeleteGroupAnnounceFormat"), str) } case .GROUP_INFO_CHANGE_TYPE_FACE: str = String(format: TIMLocalizedText.shared.commonText("TUIKitMessageTipsEditGroupAvatarFormat"), str) case .GROUP_INFO_CHANGE_TYPE_OWNER: if !userList.isEmpty { str = String(format: TIMLocalizedText.shared.commonText("TUIKitMessageTipsEditGroupOwnerFormat"), str, userList.first!) } else { str = String(format: TIMLocalizedText.shared.commonText("TUIKitMessageTipsEditGroupOwnerFormat"), str, info.value ?? "") } case .GROUP_INFO_CHANGE_TYPE_SHUT_UP_ALL: if info.boolValue { str = String(format: TIMLocalizedText.shared.commonText("TUIKitSetShutupAllFormat"), opUser) } else { str = String(format: TIMLocalizedText.shared.commonText("TUIKitCancelShutupAllFormat"), opUser) } case .GROUP_INFO_CHANGE_TYPE_GROUP_ADD_OPT: let addOpt = info.intValue var addOptDesc = "unknown" if addOpt == V2TIMGroupAddOpt.GROUP_ADD_FORBID.rawValue { addOptDesc = TIMLocalizedText.shared.commonText("TUIKitGroupProfileJoinDisable") } else if addOpt == V2TIMGroupAddOpt.GROUP_ADD_AUTH.rawValue { addOptDesc = TIMLocalizedText.shared.commonText("TUIKitGroupProfileAdminApprove") } else if addOpt == V2TIMGroupAddOpt.GROUP_ADD_ANY.rawValue { addOptDesc = TIMLocalizedText.shared.commonText("TUIKitGroupProfileAutoApproval") } str = String(format: TIMLocalizedText.shared.commonText("TUIKitMessageTipsEditGroupAddOptFormat"), str, addOptDesc) case .GROUP_INFO_CHANGE_TYPE_GROUP_APPROVE_OPT: let addOpt = info.intValue var addOptDesc = "unknown" if addOpt == V2TIMGroupAddOpt.GROUP_ADD_FORBID.rawValue { addOptDesc = TIMLocalizedText.shared.commonText("TUIKitGroupProfileInviteDisable") } else if addOpt == V2TIMGroupAddOpt.GROUP_ADD_AUTH.rawValue { addOptDesc = TIMLocalizedText.shared.commonText("TUIKitGroupProfileAdminApprove") } else if addOpt == V2TIMGroupAddOpt.GROUP_ADD_ANY.rawValue { addOptDesc = TIMLocalizedText.shared.commonText("TUIKitGroupProfileAutoApproval") } str = String(format: TIMLocalizedText.shared.commonText("TUIKitMessageTipsEditGroupInviteOptFormat"), str, addOptDesc) default: break } } return str } }