jsdw_ios/QuickLocation/Section/Group/GroupChat/GroupChatVC.swift

178 lines
5.7 KiB
Swift

//
// GroupChatVC.swift
// QuickLocation
//
// Created by on 2026/6/4.
//
import UIKit
import RxSwift
import RxCocoa
import OpenIMSDK
final class GroupChatVC: BaseViewController {
override var isNavigationBarHidden: Bool { true }
fileprivate var rootView: GroupChatView!
private let groupId: String
private var msgListener: MessageListenerProxy?
// MARK: - Init
init(groupId: String) {
self.groupId = groupId
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func loadView() {
rootView = GroupChatView(frame: UIScreen.main.bounds)
view = rootView
}
override func viewDidLoad() {
super.viewDidLoad()
reactiveAction()
loadGroupInfo()
loadMessages()
setupMessageListener()
}
// MARK: - Message Listener
private func setupMessageListener() {
msgListener = MessageListenerProxy { [weak self] msg in
guard let self = self, msg.groupID == self.groupId else { return }
let chatMsg = self.convertMessage(msg)
DispatchQueue.main.async {
self.rootView.messages.append(chatMsg)
self.rootView.tableView.reloadData()
self.rootView.tableView.scrollToRow(
at: IndexPath(row: self.rootView.messages.count - 1, section: 0),
at: .bottom, animated: true
)
}
}
OIMManager.callbacker.addAdvancedMsgListener(listener: msgListener!)
}
// MARK: - Load Messages
private func loadMessages() {
let param = OIMGetAdvancedHistoryMessageListParam()
param.conversationID = "sg_\(groupId)"
param.count = 30
OIMManager.manager.getAdvancedHistoryMessageList(
param,
onSuccess: { [weak self] result in
guard let self = self,
let list = result?.messageList else { return }
let msgs = list.compactMap { self.convertMessage($0) }.reversed()
DispatchQueue.main.async {
self.rootView.messages = Array(msgs)
}
},
onFailure: { code, msg in
print("loadMessages failed: \(code) \(msg ?? "")")
})
}
private func convertMessage(_ msg: OIMMessageInfo) -> ChatMessage {
let isSelf = msg.isSelf()
let content = msg.textElem?.content ?? "[非文本消息]"
let ts = TimeInterval(msg.sendTime) / 1000.0
let lastTs = rootView.messages.last?.timestamp
let showTime = lastTs == nil || (ts - lastTs!) > 300
return ChatMessage(
id: msg.clientMsgID ?? UUID().uuidString,
isSelf: isSelf,
senderName: msg.senderNickname ?? "",
content: content,
timestamp: ts,
showTime: showTime
)
}
// MARK: - Group Info
private func loadGroupInfo() {
OIMManager.manager.getSpecifiedGroupsInfo([groupId]) { [weak self] groups in
guard let self = self,
let group = groups?.first else { return }
self.rootView.groupNameLabel.text = group.groupName ?? ""
if let faceURL = group.faceURL, !faceURL.isEmpty {
self.rootView.groupAvatarView.dl.setImage(with: faceURL)
}
} onFailure: { code, msg in
print("getGroupInfo failed: \(code) \(msg ?? "")")
}
}
// MARK: - Actions
private func reactiveAction() {
rootView.backBtn.rx.tap
.subscribe(onNext: { _ in
AppRouter.shared.popOrDismiss()
})
.disposed(by: disposeBag)
rootView.sendBtn.rx.tap
.subscribe(onNext: { [weak self] _ in
self?.sendMessage()
})
.disposed(by: disposeBag)
rootView.textField.rx.controlEvent(.editingDidEndOnExit)
.subscribe(onNext: { [weak self] _ in
self?.sendMessage()
})
.disposed(by: disposeBag)
}
private func sendMessage() {
guard let text = rootView.textField.text?.trimmingCharacters(in: .whitespacesAndNewlines),
!text.isEmpty else { return }
rootView.textField.text = ""
let msg = OIMMessageInfo.createTextMessage(text)
OIMManager.manager.sendMessage(msg,
recvID: "",
groupID: groupId,
offlinePushInfo: nil,
onSuccess: { [weak self] _ in
guard let self = self else { return }
let chatMsg = self.convertMessage(msg)
DispatchQueue.main.async {
self.rootView.messages.append(chatMsg)
self.rootView.tableView.reloadData()
self.rootView.tableView.scrollToRow(
at: IndexPath(row: self.rootView.messages.count - 1, section: 0),
at: .bottom, animated: true
)
}
},
onProgress: nil as OIMNumberCallback?,
onFailure: { code, errMsg in
print("send failed: \(code) \(errMsg ?? "")")
})
}
}
// MARK: - MessageListenerProxy
private class MessageListenerProxy: NSObject, OIMAdvancedMsgListener {
private let handler: (OIMMessageInfo) -> Void
init(handler: @escaping (OIMMessageInfo) -> Void) {
self.handler = handler
}
func onRecvNewMessage(_ msg: OIMMessageInfo) {
handler(msg)
}
}