From 437e4b042a3a56fe4dfaa022daf8754ceb2a3ab9 Mon Sep 17 00:00:00 2001 From: XuqmGroup Date: Tue, 28 Apr 2026 22:32:21 +0800 Subject: [PATCH] =?UTF-8?q?feat(chat):=20=E6=B7=BB=E5=8A=A0=E8=81=8A?= =?UTF-8?q?=E5=A4=A9=E7=95=8C=E9=9D=A2=E8=A7=86=E5=9B=BE=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E5=92=8C=E8=81=94=E7=B3=BB=E4=BA=BA=E7=AE=A1=E7=90=86=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 实现 ChatViewModel 处理消息收发、历史记录加载和状态管理 - 添加消息搜索、草稿保存、引用回复等功能 - 实现多媒体附件发送包括图片、视频、音频和文件 - 添加群组提及用户功能和消息撤回机制 - 实现联系人管理功能包括好友搜索、添加、删除和黑名单管理 - 添加好友请求处理和实时消息监听 - 实现会话列表管理包含未读消息统计和实时更新 - 集成 IM SDK 的连接状态管理和事件监听 - 添加消息状态跟踪和超时处理机制 - 实现数据缓存机制优化用户体验 --- Sources/XuqmSDK/IM/ImClient.swift | 5 +++ Sources/XuqmSDK/IM/ImSDK.swift | 62 +++++++++++++++++++++++++++++++ Sources/XuqmSDK/IM/ImTypes.swift | 10 +++++ 3 files changed, 77 insertions(+) diff --git a/Sources/XuqmSDK/IM/ImClient.swift b/Sources/XuqmSDK/IM/ImClient.swift index 126c525..68e43fc 100644 --- a/Sources/XuqmSDK/IM/ImClient.swift +++ b/Sources/XuqmSDK/IM/ImClient.swift @@ -84,6 +84,7 @@ public final class ImClient: NSObject, URLSessionWebSocketDelegate, @unchecked S status: .sending, mentionedUserIds: mentionedUserIds?.isEmpty == false ? mentionedUserIds : nil, groupReadCount: nil, + revoked: false, createdAt: now ) guard let activeAppId else { @@ -199,6 +200,9 @@ public final class ImClient: NSObject, URLSessionWebSocketDelegate, @unchecked S let msg = try? JSONDecoder().decode(ImMessage.self, from: messageData) else { continue } + if (msg.revoked ?? false) || msg.status == .revoked || msg.msgType == .revoked { + delegate?.imClientDidReceiveRevokedMessage(msg) + } if msg.chatType == .group { delegate?.imClientDidReceiveGroupMessage(msg) } else { @@ -298,6 +302,7 @@ private extension ImMessage { status: .failed, mentionedUserIds: mentionedUserIds, groupReadCount: groupReadCount, + revoked: false, createdAt: createdAt ) } diff --git a/Sources/XuqmSDK/IM/ImSDK.swift b/Sources/XuqmSDK/IM/ImSDK.swift index f5a242c..b8c68e9 100644 --- a/Sources/XuqmSDK/IM/ImSDK.swift +++ b/Sources/XuqmSDK/IM/ImSDK.swift @@ -248,6 +248,16 @@ public final class ImSDK { client?.revoke(messageId: messageId) } + public func editMessage(messageId: String, content: String) async throws -> ImMessage { + let config = XuqmSDK.shared.requireConfig() + return try await ApiClient.shared.request( + path: "/api/im/messages/\(messageId)", + method: "PUT", + queryItems: [URLQueryItem(name: "appId", value: config.appId)], + body: EditMessageRequest(content: content) + ) + } + public func subscribeGroup(_ groupId: String) { client?.subscribeGroup(groupId) } @@ -274,6 +284,7 @@ public final class ImSDK { status: .failed, mentionedUserIds: mentionedUserIds, groupReadCount: nil, + revoked: false, createdAt: Int64(Date().timeIntervalSince1970 * 1000) ) } @@ -319,6 +330,57 @@ public final class ImSDK { ) } + public func locateHistoryPage( + toId: String, + messageId: String, + pageSize: Int = 20, + maxPages: Int = 20 + ) async throws -> [ImMessage]? { + try await locatePage( + messageId: messageId, + maxPages: maxPages, + pageSize: pageSize, + loadPage: { page in + try await self.fetchHistory(toId: toId, page: page, size: pageSize) + } + ) + } + + public func locateGroupHistoryPage( + groupId: String, + messageId: String, + pageSize: Int = 20, + maxPages: Int = 20 + ) async throws -> [ImMessage]? { + try await locatePage( + messageId: messageId, + maxPages: maxPages, + pageSize: pageSize, + loadPage: { page in + try await self.fetchGroupHistory(groupId: groupId, page: page, size: pageSize) + } + ) + } + + private func locatePage( + messageId: String, + maxPages: Int, + pageSize: Int, + loadPage: @escaping (Int) async throws -> [ImMessage] + ) async throws -> [ImMessage]? { + let pageCount = max(maxPages, 1) + for page in 0.. [ImGroup] { let config = XuqmSDK.shared.requireConfig() let groups: [ImGroup] = try await ApiClient.shared.request( diff --git a/Sources/XuqmSDK/IM/ImTypes.swift b/Sources/XuqmSDK/IM/ImTypes.swift index 2e436a7..dc5ddcd 100644 --- a/Sources/XuqmSDK/IM/ImTypes.swift +++ b/Sources/XuqmSDK/IM/ImTypes.swift @@ -43,6 +43,7 @@ public struct ImMessage: Codable, Sendable { public let status: MsgStatus public let mentionedUserIds: String? public let groupReadCount: Int? + public let revoked: Bool? public let createdAt: Int64 } @@ -63,9 +64,14 @@ public protocol ImEventDelegate: AnyObject { func imClientDidDisconnect(reason: String?) func imClientDidReceiveMessage(_ message: ImMessage) func imClientDidReceiveGroupMessage(_ message: ImMessage) + func imClientDidReceiveRevokedMessage(_ message: ImMessage) func imClientDidError(_ error: String) } +public extension ImEventDelegate { + func imClientDidReceiveRevokedMessage(_ message: ImMessage) {} +} + public struct ImGroup: Codable, Sendable { public let id: String public let appId: String @@ -139,6 +145,10 @@ public struct ImSendMessageRequest: Encodable, Sendable { public let mentionedUserIds: String? } +public struct EditMessageRequest: Encodable, Sendable { + public let content: String +} + public struct ImLoginResponse: Decodable, Sendable { public let token: String }