146 行
4.1 KiB
Swift
146 行
4.1 KiB
Swift
|
|
import Foundation
|
||
|
|
import XuqmSDK
|
||
|
|
|
||
|
|
@MainActor
|
||
|
|
final class ChatViewModel: ObservableObject {
|
||
|
|
@Published var messages: [ImMessage] = []
|
||
|
|
@Published var inputText: String = ""
|
||
|
|
@Published var isLoading: Bool = false
|
||
|
|
@Published var errorMessage: String?
|
||
|
|
@Published var connectionStatus: String = "连接中"
|
||
|
|
|
||
|
|
private var targetId: String = ""
|
||
|
|
private var chatType: ChatType = .single
|
||
|
|
private var currentPage = 0
|
||
|
|
private let pageSize = 20
|
||
|
|
private var hasMore = true
|
||
|
|
private var isLoadingMore = false
|
||
|
|
|
||
|
|
private var delegateBridge: ChatEventDelegateBridge?
|
||
|
|
|
||
|
|
func setup(targetId: String, chatType: ChatType) {
|
||
|
|
self.targetId = targetId
|
||
|
|
self.chatType = chatType
|
||
|
|
self.messages = []
|
||
|
|
self.currentPage = 0
|
||
|
|
self.hasMore = true
|
||
|
|
self.isLoadingMore = false
|
||
|
|
self.errorMessage = nil
|
||
|
|
|
||
|
|
let bridge = ChatEventDelegateBridge(viewModel: self)
|
||
|
|
self.delegateBridge = bridge
|
||
|
|
ImSDK.shared.setDelegate(bridge)
|
||
|
|
|
||
|
|
loadHistory()
|
||
|
|
}
|
||
|
|
|
||
|
|
func loadHistory() {
|
||
|
|
guard !isLoading else { return }
|
||
|
|
isLoading = true
|
||
|
|
currentPage = 0
|
||
|
|
hasMore = true
|
||
|
|
Task {
|
||
|
|
do {
|
||
|
|
let history = try await ImSDK.shared.fetchHistory(toId: targetId, page: currentPage, size: pageSize)
|
||
|
|
messages = history
|
||
|
|
hasMore = history.count >= pageSize
|
||
|
|
isLoading = false
|
||
|
|
} catch {
|
||
|
|
errorMessage = error.localizedDescription
|
||
|
|
isLoading = false
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func loadMoreHistory() {
|
||
|
|
guard hasMore, !isLoadingMore, !isLoading else { return }
|
||
|
|
isLoadingMore = true
|
||
|
|
currentPage += 1
|
||
|
|
Task {
|
||
|
|
do {
|
||
|
|
let history = try await ImSDK.shared.fetchHistory(toId: targetId, page: currentPage, size: pageSize)
|
||
|
|
messages.append(contentsOf: history)
|
||
|
|
hasMore = history.count >= pageSize
|
||
|
|
isLoadingMore = false
|
||
|
|
} catch {
|
||
|
|
isLoadingMore = false
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func sendText() {
|
||
|
|
let text = inputText.trimmingCharacters(in: .whitespacesAndNewlines)
|
||
|
|
guard !text.isEmpty else { return }
|
||
|
|
let message = ImSDK.shared.sendTextMessage(toId: targetId, chatType: chatType, content: text)
|
||
|
|
messages.insert(message, at: 0)
|
||
|
|
inputText = ""
|
||
|
|
}
|
||
|
|
|
||
|
|
func markRead() {
|
||
|
|
Task {
|
||
|
|
try? await ImSDK.shared.markRead(targetId: targetId, chatType: chatType)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// MARK: - Delegate callbacks (called on MainActor via bridge)
|
||
|
|
|
||
|
|
func didReceiveMessage(_ message: ImMessage) {
|
||
|
|
guard message.fromId == targetId || message.toId == targetId else { return }
|
||
|
|
if !messages.contains(where: { $0.id == message.id }) {
|
||
|
|
messages.insert(message, at: 0)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func didConnect() {
|
||
|
|
connectionStatus = "已连接"
|
||
|
|
}
|
||
|
|
|
||
|
|
func didDisconnect(reason: String?) {
|
||
|
|
connectionStatus = reason ?? "已断开"
|
||
|
|
}
|
||
|
|
|
||
|
|
func didError(_ error: String) {
|
||
|
|
connectionStatus = "错误: \(error)"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// MARK: - ImEventDelegate Bridge
|
||
|
|
|
||
|
|
private final class ChatEventDelegateBridge: NSObject, ImEventDelegate {
|
||
|
|
weak var viewModel: ChatViewModel?
|
||
|
|
|
||
|
|
init(viewModel: ChatViewModel) {
|
||
|
|
self.viewModel = viewModel
|
||
|
|
}
|
||
|
|
|
||
|
|
func imClientDidConnect() {
|
||
|
|
Task { @MainActor [weak viewModel] in
|
||
|
|
viewModel?.didConnect()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func imClientDidDisconnect(reason: String?) {
|
||
|
|
Task { @MainActor [weak viewModel] in
|
||
|
|
viewModel?.didDisconnect(reason: reason)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func imClientDidReceiveMessage(_ message: ImMessage) {
|
||
|
|
Task { @MainActor [weak viewModel] in
|
||
|
|
viewModel?.didReceiveMessage(message)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func imClientDidReceiveGroupMessage(_ message: ImMessage) {
|
||
|
|
Task { @MainActor [weak viewModel] in
|
||
|
|
viewModel?.didReceiveMessage(message)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func imClientDidError(_ error: String) {
|
||
|
|
Task { @MainActor [weak viewModel] in
|
||
|
|
viewModel?.didError(error)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|