IMConversationListViewController.swift 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. //
  2. // IMConversationListViewController.swift
  3. // O2Platform
  4. //
  5. // Created by FancyLou on 2020/6/4.
  6. // Copyright © 2020 zoneland. All rights reserved.
  7. //
  8. import UIKit
  9. import CocoaLumberjack
  10. class IMConversationListViewController: UIViewController {
  11. fileprivate lazy var tableview: UITableView = {
  12. var tableview = UITableView(frame: CGRect(x: 0, y: 0, width: self.view.width, height: self.view.height - TAB_BAR_HEIGHT))
  13. tableview.delegate = self
  14. tableview.dataSource = self
  15. tableview.backgroundColor = UIColor(netHex: 0xe8edf3)
  16. tableview.register(UINib(nibName: "IMConversationItemCell", bundle: nil), forCellReuseIdentifier: "IMConversationItemCell")
  17. tableview.separatorStyle = .none
  18. return tableview
  19. }()
  20. fileprivate lazy var emptyView: UIView = {
  21. let view = UIView(frame: CGRect(x: 0, y: 36, width: self.view.width, height: self.view.height - 36))
  22. view.isHidden = true
  23. view.backgroundColor = .white
  24. let tips = UILabel()
  25. tips.text = "暂无会话"
  26. tips.textColor = UIColor(netHex: 0x666666)
  27. tips.sizeToFit()
  28. tips.center = CGPoint(x: view.centerX, y: view.height / 2 - 60)
  29. view.addSubview(tips)
  30. return view
  31. }()
  32. private lazy var viewModel: IMViewModel = {
  33. return IMViewModel()
  34. }()
  35. private var conversationList: [IMConversationInfo] = []
  36. private var instantMsgList: [InstantMessage] = []
  37. private var imConfig = IMConfig()
  38. override func viewDidLoad() {
  39. super.viewDidLoad()
  40. self.navigationItem.rightBarButtonItems = [UIBarButtonItem(image: UIImage(named: "add"), style: .plain, target: self, action: #selector(addConversation))]
  41. view.addSubview(tableview)
  42. view.addSubview(emptyView)
  43. NotificationCenter.default.addObserver(self, selector: #selector(receiveMessageFromWs(notice:)), name: OONotification.websocket.notificationName, object: nil)
  44. imConfig.enableClearMsg = false
  45. viewModel.loadImConfig().then { imConfig in
  46. self.imConfig = imConfig
  47. }
  48. }
  49. override func viewWillAppear(_ animated: Bool) {
  50. getInstantMsgList()
  51. }
  52. func getInstantMsgList() {
  53. self.showLoading()
  54. viewModel.getInstantMsgList().then { (list) in
  55. self.instantMsgList = list
  56. self.getConversationList()
  57. }
  58. }
  59. func getConversationList() {
  60. viewModel.myConversationList().then { (list) in
  61. self.conversationList = list
  62. var n = 0
  63. if !self.conversationList.isEmpty {
  64. for item in self.conversationList {
  65. if let number = item.unreadNumber {
  66. n += number
  67. }
  68. }
  69. }
  70. DispatchQueue.main.async {
  71. self.hideLoading()
  72. if self.conversationList.count > 0 || self.instantMsgList.count > 0 {
  73. self.emptyView.isHidden = true
  74. } else {
  75. self.emptyView.isHidden = false
  76. }
  77. self.tableview.reloadData()
  78. self.refreshRedPoint(number: n)
  79. }
  80. }.catch { (err) in
  81. DDLogError(err.localizedDescription)
  82. DispatchQueue.main.async {
  83. self.hideLoading()
  84. if self.conversationList.count > 0 || self.instantMsgList.count > 0 {
  85. self.emptyView.isHidden = false
  86. }
  87. }
  88. }
  89. }
  90. //接收websocket消息
  91. @objc private func receiveMessageFromWs(notice: Notification) {
  92. DDLogDebug("接收到websocket im 消息")
  93. if let message = notice.object as? IMMessageInfo {
  94. if self.conversationList.contains(where: { (info) -> Bool in
  95. return info.id == message.conversationId
  96. }) {
  97. DDLogDebug("有对应的会话 刷新列表")
  98. var newList: [IMConversationInfo] = []
  99. self.conversationList.forEach { (info) in
  100. if message.conversationId != nil && info.id == message.conversationId {
  101. info.lastMessage = message
  102. info.unreadNumber = (info.unreadNumber ?? 0) + 1
  103. }
  104. newList.append(info)
  105. }
  106. self.conversationList = newList
  107. DispatchQueue.main.async {
  108. self.tableview.reloadData()
  109. }
  110. } else {
  111. DDLogDebug("没有对应的会话 重新获取会话列表")
  112. self.getInstantMsgList()
  113. }
  114. } else {
  115. DDLogError("不正确的消息类型。。。")
  116. }
  117. }
  118. private func refreshRedPoint(number: Int) {
  119. if number > 0 && number < 100 {
  120. self.navigationController?.tabBarItem.badgeValue = "\(number)"
  121. } else if number >= 100 {
  122. self.navigationController?.tabBarItem.badgeValue = "99.."
  123. }else {
  124. self.navigationController?.tabBarItem.badgeValue = nil
  125. }
  126. }
  127. @objc private func addConversation() {
  128. self.showSheetAction(title: nil, message: nil, actions: [
  129. UIAlertAction(title: "创建单聊", style: .default, handler: { (action) in
  130. self.createSingleConversation()
  131. }),
  132. UIAlertAction(title: "创建群聊", style: .default, handler: { (action) in
  133. self.createGroupConversation()
  134. })
  135. ])
  136. }
  137. private func createSingleConversation() {
  138. self.showContactPicker(modes: [.person], callback: { (result) in
  139. if let users = result.users, users.count > 0 {
  140. self.viewModel.createConversation(type: o2_im_conversation_type_single, users: [users[0].distinguishedName!]).then { (con) in
  141. self.createConversationSuccess(conv: con)
  142. }.catch { (err) in
  143. self.showError(title: "创建单聊失败, \(err.localizedDescription)")
  144. }
  145. }
  146. }, multiple: false)
  147. }
  148. private func createGroupConversation() {
  149. self.showContactPicker(modes: [.person], callback: { (result) in
  150. if let users = result.users, users.count > 0 {
  151. let array = users.map { (item) -> String in
  152. item.distinguishedName!
  153. }
  154. self.viewModel.createConversation(type: o2_im_conversation_type_group, users: array).then { (conv) in
  155. self.createConversationSuccess(conv: conv)
  156. }.catch { (err) in
  157. self.showError(title: "创建群聊失败, \(err.localizedDescription)")
  158. }
  159. }
  160. })
  161. }
  162. //创建会话成功 打开聊天界面
  163. private func createConversationSuccess(conv: IMConversationInfo) {
  164. if !self.conversationList.contains(where: { (info) -> Bool in
  165. return info.id == conv.id
  166. }) {
  167. self.conversationList.append(conv)
  168. DispatchQueue.main.async {
  169. self.tableview.reloadData()
  170. }
  171. }
  172. let chatView = IMChatViewController()
  173. chatView.conversation = conv
  174. self.navigationController?.pushViewController(chatView, animated: true)
  175. }
  176. }
  177. // MARK: - tableview delegate
  178. extension IMConversationListViewController: UITableViewDelegate, UITableViewDataSource {
  179. func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  180. if self.instantMsgList.count > 0 {
  181. return self.conversationList.count + 1
  182. }
  183. return self.conversationList.count
  184. }
  185. func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  186. if let cell = tableView.dequeueReusableCell(withIdentifier: "IMConversationItemCell", for: indexPath) as? IMConversationItemCell {
  187. if self.instantMsgList.count > 0 {
  188. if indexPath.row == 0 {
  189. cell.setInstantContent(item: self.instantMsgList.last!)
  190. }else {
  191. cell.bindConversation(conversation: self.conversationList[indexPath.row - 1])
  192. }
  193. }else {
  194. cell.bindConversation(conversation: self.conversationList[indexPath.row])
  195. }
  196. return cell
  197. }
  198. return UITableViewCell()
  199. }
  200. func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
  201. return 84
  202. }
  203. /// Cell 圆角背景计算
  204. func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
  205. //圆率
  206. let cornerRadius:CGFloat = 10.0
  207. //大小
  208. let bounds:CGRect = cell.bounds
  209. //绘制曲线
  210. // var bezierPath: UIBezierPath? = nil
  211. //一个为一组时,四个角都为圆角
  212. let bezierPath: UIBezierPath? = UIBezierPath(roundedRect: bounds, byRoundingCorners: .allCorners, cornerRadii: CGSize(width: cornerRadius, height: cornerRadius))
  213. //cell的背景色透明
  214. cell.backgroundColor = .clear
  215. //新建一个图层
  216. let layer = CAShapeLayer()
  217. //图层边框路径
  218. layer.path = bezierPath?.cgPath
  219. //图层填充色,也就是cell的底色
  220. layer.fillColor = UIColor.white.cgColor
  221. //图层边框线条颜色
  222. /*
  223. 如果self.tableView.style = UITableViewStyleGrouped时,每一组的首尾都会有一根分割线,目前我还没找到去掉每组首尾分割线,保留cell分割线的办法。
  224. 所以这里取巧,用带颜色的图层边框替代分割线。
  225. 这里为了美观,最好设为和tableView的底色一致。
  226. 设为透明,好像不起作用。
  227. */
  228. layer.strokeColor = UIColor.white.cgColor
  229. //将图层添加到cell的图层中,并插到最底层
  230. cell.layer.insertSublayer(layer, at: 0)
  231. }
  232. func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
  233. DDLogDebug("点击了 row \(indexPath.row)")
  234. if self.instantMsgList.count > 0 {
  235. if indexPath.row == 0 {
  236. let instantView = IMInstantMessageViewController()
  237. instantView.instantMsgList = self.instantMsgList
  238. self.navigationController?.pushViewController(instantView, animated: true)
  239. }else {
  240. gotoChatView(row: indexPath.row-1)
  241. }
  242. }else {
  243. gotoChatView(row: indexPath.row)
  244. }
  245. }
  246. private func gotoChatView(row: Int) {
  247. let chatView = IMChatViewController()
  248. chatView.conversation = self.conversationList[row]
  249. self.navigationController?.pushViewController(chatView, animated: true)
  250. }
  251. }