IMChatMessageSendViewCell.swift 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. //
  2. // IMChatMessageSendViewCell.swift
  3. // O2Platform
  4. //
  5. // Created by FancyLou on 2020/6/10.
  6. // Copyright © 2020 zoneland. All rights reserved.
  7. //
  8. import UIKit
  9. import CocoaLumberjack
  10. class IMChatMessageSendViewCell: UITableViewCell {
  11. @IBOutlet weak var timeLabel: UILabel!
  12. @IBOutlet weak var avatarImageView: UIImageView!
  13. @IBOutlet weak var nameLabel: UILabel!
  14. @IBOutlet weak var messageBackgroundView: UIView!
  15. @IBOutlet weak var messageBgWidth: NSLayoutConstraint!
  16. @IBOutlet weak var messageBgHeight: NSLayoutConstraint!
  17. //音频消息 主体view
  18. private lazy var audioView: IMAudioView = {
  19. let view = Bundle.main.loadNibNamed("IMAudioView", owner: self, options: nil)?.first as! IMAudioView
  20. view.frame = CGRect(x: 0, y: 0, width: IMAudioView.IMAudioView_width, height: IMAudioView.IMAudioView_height)
  21. return view
  22. }()
  23. //位置消息 主体view
  24. private lazy var locationView: IMLocationView = {
  25. let view = Bundle.main.loadNibNamed("IMLocationView", owner: self, options: nil)?.first as! IMLocationView
  26. view.frame = CGRect(x: 0, y: 0, width: IMLocationView.IMLocationViewWidth, height: IMLocationView.IMLocationViewHeight)
  27. return view
  28. }()
  29. var delegate: IMChatMessageDelegate?
  30. override func awakeFromNib() {
  31. super.awakeFromNib()
  32. }
  33. override func setSelected(_ selected: Bool, animated: Bool) {
  34. super.setSelected(selected, animated: animated)
  35. }
  36. func setContent(item: IMMessageInfo) {
  37. //time
  38. if let time = item.createTime {
  39. let date = time.toDate(formatter: "yyyy-MM-dd HH:mm:ss")
  40. self.timeLabel.text = date.friendlyTime()
  41. }
  42. //name avatart
  43. if let person = item.createPerson {
  44. let urlstr = AppDelegate.o2Collect.generateURLWithAppContextKey(ContactContext.contactsContextKeyV2, query: ContactContext.personIconByNameQueryV2, parameter: ["##name##":person as AnyObject], generateTime: false)
  45. if let u = URL(string: urlstr!) {
  46. self.avatarImageView.hnk_setImageFromURL(u)
  47. }else {
  48. self.avatarImageView.image = UIImage(named: "icon_men")
  49. }
  50. //姓名
  51. self.nameLabel.text = person.split("@").first ?? ""
  52. }else {
  53. self.avatarImageView.image = UIImage(named: "icon_men")
  54. self.nameLabel.text = ""
  55. }
  56. self.messageBackgroundView.removeSubviews()
  57. if let jsonBody = item.body, let body = parseJson(msg: jsonBody) {
  58. if o2_im_msg_type_emoji == body.type {
  59. emojiMsgRender(emoji: body.body!)
  60. }else if o2_im_msg_type_image == body.type {
  61. imageMsgRender(info: body)
  62. }else if o2_im_msg_type_audio == body.type {
  63. audioMsgRender(info: body)
  64. } else if o2_im_msg_type_location == body.type {
  65. locationMsgRender(info: body)
  66. } else {
  67. textMsgRender(msg: body.body!)
  68. }
  69. }
  70. }
  71. //位置消息
  72. private func locationMsgRender(info: IMMessageBodyInfo) {
  73. self.messageBgWidth.constant = IMLocationView.IMLocationViewWidth + 20
  74. self.messageBgHeight.constant = IMLocationView.IMLocationViewHeight + 20
  75. self.locationView.translatesAutoresizingMaskIntoConstraints = false
  76. self.messageBackgroundView.addSubview(self.locationView)
  77. self.locationView.setLocationAddress(address: info.address ?? "")
  78. //点击打开地址
  79. self.locationView.addTapGesture { (tap) in
  80. //open map view//open map view
  81. self.delegate?.openLocatinMap(info: info)
  82. }
  83. self.constraintWithContent(contentView: self.locationView)
  84. }
  85. //音频消息
  86. private func audioMsgRender(info: IMMessageBodyInfo) {
  87. self.messageBgWidth.constant = IMAudioView.IMAudioView_width + 20
  88. self.messageBgHeight.constant = IMAudioView.IMAudioView_height + 20
  89. self.audioView.translatesAutoresizingMaskIntoConstraints = false
  90. self.messageBackgroundView.addSubview(self.audioView)
  91. self.audioView.setDuration(duration: info.audioDuration ?? "0")
  92. self.audioView.addTapGesture { (tap) in
  93. self.playAudio(info: info)
  94. }
  95. self.constraintWithContent(contentView: self.audioView)
  96. }
  97. private func playAudio(info: IMMessageBodyInfo) {
  98. if let fileId = info.fileId {
  99. var ext = info.fileExtension ?? "mp3"
  100. if ext.isEmpty {
  101. ext = "mp3"
  102. }
  103. O2IMFileManager.shared.getFileLocalUrl(fileId: fileId, fileExtension: ext)
  104. .then { (url) in
  105. do {
  106. let data = try Data(contentsOf: url)
  107. AudioPlayerManager.shared.managerAudioWithData(data, toplay: true)
  108. } catch {
  109. DDLogError(error.localizedDescription)
  110. }
  111. }.catch { (e) in
  112. DDLogError(e.localizedDescription)
  113. }
  114. } else if let filePath = info.fileTempPath {
  115. do {
  116. let data = try Data(contentsOf: URL(fileURLWithPath: filePath))
  117. AudioPlayerManager.shared.managerAudioWithData(data, toplay: true)
  118. } catch {
  119. DDLogError(error.localizedDescription)
  120. }
  121. }
  122. }
  123. private func constraintWithContent(contentView: UIView) {
  124. let top = NSLayoutConstraint(item: contentView, attribute: .top, relatedBy: .equal, toItem: contentView.superview!, attribute: .top, multiplier: 1, constant: 10)
  125. let bottom = NSLayoutConstraint(item: contentView.superview!, attribute: .bottom, relatedBy: .equal, toItem: contentView, attribute: .bottom, multiplier: 1, constant: 10)
  126. let left = NSLayoutConstraint(item: contentView, attribute: .leading, relatedBy: .equal, toItem: contentView.superview!, attribute: .leading, multiplier: 1, constant: 10)
  127. let right = NSLayoutConstraint(item: contentView.superview!, attribute: .trailing, relatedBy: .equal, toItem: contentView, attribute: .trailing, multiplier: 1, constant: 10)
  128. NSLayoutConstraint.activate([top, bottom, left, right])
  129. }
  130. //图片消息
  131. private func imageMsgRender(info: IMMessageBodyInfo) {
  132. let width: CGFloat = 144
  133. let height: CGFloat = 192
  134. self.messageBgWidth.constant = width + 20
  135. self.messageBgHeight.constant = height + 20
  136. //图片
  137. let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: width, height: height))
  138. if let fileId = info.fileId {
  139. DDLogDebug("fileId :\(fileId)")
  140. let urlStr = AppDelegate.o2Collect.generateURLWithAppContextKey(
  141. CommunicateContext.communicateContextKey,
  142. query: CommunicateContext.imDownloadImageWithSizeQuery,
  143. parameter: ["##id##": fileId as AnyObject,
  144. "##width##": "144" as AnyObject,
  145. "##height##": "192" as AnyObject], generateTime: false)
  146. if let url = URL(string: urlStr!) {
  147. imageView.hnk_setImageFromURL(url)
  148. } else {
  149. imageView.image = UIImage(named: "chat_image")
  150. }
  151. } else if let filePath = info.fileTempPath {
  152. DDLogDebug("filePath :\(filePath)")
  153. imageView.hnk_setImageFromFile(filePath)
  154. } else {
  155. imageView.image = UIImage(named: "chat_image")
  156. }
  157. imageView.translatesAutoresizingMaskIntoConstraints = false
  158. self.messageBackgroundView.addSubview(imageView)
  159. imageView.addTapGesture { (tap) in
  160. self.delegate?.clickImageMessage(info: info)
  161. }
  162. self.constraintWithContent(contentView: imageView)
  163. }
  164. private func emojiMsgRender(emoji: String) {
  165. let emojiSize = 36
  166. let width = CGFloat(emojiSize + 20)
  167. let height = CGFloat(emojiSize + 20)
  168. self.messageBgWidth.constant = width
  169. self.messageBgHeight.constant = height
  170. //背景图片
  171. let bgImg = UIImageView(frame: CGRect(x: 0, y: 0, width: width, height: height))
  172. let insets = UIEdgeInsets(top: 28, left: 5, bottom: 5, right: 10); // 上、左、下、右
  173. var bubble = UIImage(named: "chat_bubble_outgoing")
  174. bubble = bubble?.resizableImage(withCapInsets: insets, resizingMode: .stretch)
  175. bgImg.image = bubble
  176. self.messageBackgroundView.addSubview(bgImg)
  177. //表情图
  178. let emojiImage = UIImageView(frame: CGRect(x: 0, y: 0, width: emojiSize, height: emojiSize))
  179. let bundle = Bundle().o2EmojiBundle(anyClass: IMChatMessageSendViewCell.self)
  180. let path = o2ImEmojiPath(emojiBody: emoji)
  181. emojiImage.image = UIImage(named: path, in: bundle, compatibleWith: nil)
  182. emojiImage.translatesAutoresizingMaskIntoConstraints = false
  183. self.messageBackgroundView.addSubview(emojiImage)
  184. self.constraintWithContent(contentView: emojiImage)
  185. }
  186. private func textMsgRender(msg: String) {
  187. let size = msg.getSizeWithMaxWidth(fontSize: 16, maxWidth: messageWidth)
  188. self.messageBgWidth.constant = size.width + 28
  189. self.messageBgHeight.constant = size.height + 28
  190. //背景图片
  191. let bgImg = UIImageView(frame: CGRect(x: 0, y: 0, width: size.width + 28, height: size.height + 28))
  192. let insets = UIEdgeInsets(top: 28, left: 5, bottom: 5, right: 10); // 上、左、下、右
  193. var bubble = UIImage(named: "chat_bubble_outgoing")
  194. bubble = bubble?.resizableImage(withCapInsets: insets, resizingMode: .stretch)
  195. bgImg.image = bubble
  196. self.messageBackgroundView.addSubview(bgImg)
  197. //文字
  198. let label = generateMessagelabel(str: msg, size: size)
  199. label.translatesAutoresizingMaskIntoConstraints = false
  200. self.messageBackgroundView.addSubview(label)
  201. self.constraintWithContent(contentView: label)
  202. // let top = NSLayoutConstraint(item: label, attribute: .top, relatedBy: .equal, toItem: label.superview!, attribute: .top, multiplier: 1, constant: 10)
  203. // let left = NSLayoutConstraint(item: label, attribute: .leading, relatedBy: .equal, toItem: label.superview!, attribute: .leading, multiplier: 1, constant: 10)
  204. // let right = NSLayoutConstraint(item: label.superview!, attribute: .trailing, relatedBy: .equal, toItem: label, attribute: .trailing, multiplier: 1, constant: 10)
  205. // NSLayoutConstraint.activate([top, left, right])
  206. }
  207. private func generateMessagelabel(str: String, size: CGSize) -> UILabel {
  208. let label = UILabel(frame: CGRect(x: 0, y: 0, width: size.width + 8, height: size.height + 8))
  209. label.text = str
  210. label.font = UIFont.systemFont(ofSize: 16)
  211. label.numberOfLines = 0
  212. label.lineBreakMode = .byCharWrapping
  213. label.preferredMaxLayoutWidth = size.width
  214. return label
  215. }
  216. // private func calTextSize(str: String) -> CGSize {
  217. // let size = CGSize(width: 176, height: CGFloat(MAXFLOAT))
  218. // return str.boundingRect(with: size, options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 16)], context: nil).size
  219. // }
  220. //解析json为消息对象
  221. private func parseJson(msg: String) -> IMMessageBodyInfo? {
  222. return IMMessageBodyInfo.deserialize(from: msg)
  223. }
  224. }