178 lines
5.7 KiB
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)
|
|
}
|
|
}
|