IMChatMessageSendViewCell.swift 10 KB

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