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) } } }