feat(im): 添加即时通讯SDK核心功能
- 实现IM API接口定义,包括消息、群组、好友、黑名单等功能 - 定义IM消息相关数据模型,包含聊天类型、消息类型、用户资料等 - 实现ImSDK单例类,提供登录、消息发送、群组管理、好友管理等核心功能 - 添加WebSocket连接管理,支持自动重连机制 - 实现历史消息查询、群组操作、用户资料管理等API调用 - 添加会话状态管理,支持置顶、静音、草稿等功能 - 集成文件上传结果,支持多媒体消息发送 - 实现连接状态监听和事件回调机制
这个提交包含在:
父节点
027937db1b
当前提交
5eb46f97c6
20
README.md
20
README.md
@ -20,7 +20,7 @@ XuqmGroup-iOSSDK/
|
||||
├── Push/
|
||||
│ └── PushSDK.swift # APNs Token 注册
|
||||
└── Update/
|
||||
└── UpdateSDK.swift # 版本检查 / Bundle 下载
|
||||
└── UpdateSDK.swift # 版本检查 / App 更新
|
||||
```
|
||||
|
||||
## 集成
|
||||
@ -226,23 +226,7 @@ if result.needsUpdate, let info = result.info {
|
||||
}
|
||||
```
|
||||
|
||||
### 检查 RN Bundle 更新
|
||||
|
||||
```swift
|
||||
let rnResult = try await UpdateSDK.checkRnUpdate(
|
||||
appId: "ak_xxx",
|
||||
moduleId: "main",
|
||||
currentVersion: "1.0.0"
|
||||
)
|
||||
|
||||
if rnResult.needsUpdate, let info = rnResult.info {
|
||||
let filePath = try await UpdateSDK.downloadBundle(
|
||||
from: info.downloadUrl,
|
||||
filename: "main.ios.bundle"
|
||||
)
|
||||
// 校验 MD5,通知 RN 引擎加载
|
||||
}
|
||||
```
|
||||
`UpdateSDK` 这里只负责 iOS App 版本更新。RN 热更新如果需要,走独立的 RN SDK / RN 更新模块,不并入统一发版能力。
|
||||
|
||||
---
|
||||
|
||||
|
||||
@ -339,6 +339,56 @@ public final class ImSDK {
|
||||
return groups
|
||||
}
|
||||
|
||||
public func searchUsers(keyword: String, size: Int = 20) async throws -> [UserProfile] {
|
||||
let config = XuqmSDK.shared.requireConfig()
|
||||
return try await ApiClient.shared.request(
|
||||
path: "/api/im/admin/users/search",
|
||||
queryItems: [
|
||||
URLQueryItem(name: "appId", value: config.appId),
|
||||
URLQueryItem(name: "keyword", value: keyword),
|
||||
URLQueryItem(name: "size", value: String(size)),
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
public func searchGroups(keyword: String, size: Int = 20) async throws -> [ImGroup] {
|
||||
let config = XuqmSDK.shared.requireConfig()
|
||||
return try await ApiClient.shared.request(
|
||||
path: "/api/im/admin/groups/search",
|
||||
queryItems: [
|
||||
URLQueryItem(name: "appId", value: config.appId),
|
||||
URLQueryItem(name: "keyword", value: keyword),
|
||||
URLQueryItem(name: "size", value: String(size)),
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
public func searchMessages(
|
||||
keyword: String? = nil,
|
||||
chatType: String? = nil,
|
||||
msgType: String? = nil,
|
||||
startTime: Date? = nil,
|
||||
endTime: Date? = nil,
|
||||
page: Int = 0,
|
||||
size: Int = 20
|
||||
) async throws -> PageResult<ImMessage> {
|
||||
let config = XuqmSDK.shared.requireConfig()
|
||||
var items: [URLQueryItem] = [
|
||||
URLQueryItem(name: "appId", value: config.appId),
|
||||
URLQueryItem(name: "page", value: String(page)),
|
||||
URLQueryItem(name: "size", value: String(size)),
|
||||
]
|
||||
if let keyword, !keyword.isEmpty { items.append(URLQueryItem(name: "keyword", value: keyword)) }
|
||||
if let chatType, !chatType.isEmpty { items.append(URLQueryItem(name: "chatType", value: chatType)) }
|
||||
if let msgType, !msgType.isEmpty { items.append(URLQueryItem(name: "msgType", value: msgType)) }
|
||||
if let startTime { items.append(URLQueryItem(name: "startTime", value: isoLocalDateTime(startTime))) }
|
||||
if let endTime { items.append(URLQueryItem(name: "endTime", value: isoLocalDateTime(endTime))) }
|
||||
return try await ApiClient.shared.request(
|
||||
path: "/api/im/admin/messages/search",
|
||||
queryItems: items
|
||||
)
|
||||
}
|
||||
|
||||
public func createGroup(name: String, memberIds: [String], groupType: String = "WORK") async throws -> ImGroup {
|
||||
let config = XuqmSDK.shared.requireConfig()
|
||||
return try await ApiClient.shared.request(
|
||||
|
||||
@ -46,6 +46,18 @@ public struct ImMessage: Codable, Sendable {
|
||||
public let createdAt: Int64
|
||||
}
|
||||
|
||||
public struct PageResult<T: Decodable & Sendable>: Decodable, Sendable {
|
||||
public let content: [T]
|
||||
public let totalElements: Int64
|
||||
public let totalPages: Int
|
||||
public let size: Int
|
||||
public let number: Int
|
||||
public let numberOfElements: Int
|
||||
public let first: Bool
|
||||
public let last: Bool
|
||||
public let empty: Bool
|
||||
}
|
||||
|
||||
public protocol ImEventDelegate: AnyObject {
|
||||
func imClientDidConnect()
|
||||
func imClientDidDisconnect(reason: String?)
|
||||
|
||||
@ -15,15 +15,6 @@ public struct AppUpdateInfo: Decodable, Sendable {
|
||||
public let appStoreUrl: String?
|
||||
}
|
||||
|
||||
public struct RnUpdateInfo: Decodable, Sendable {
|
||||
public let needsUpdate: Bool
|
||||
public let latestVersion: String
|
||||
public let downloadUrl: String
|
||||
public let md5: String
|
||||
public let minCommonVersion: String
|
||||
public let note: String
|
||||
}
|
||||
|
||||
@MainActor
|
||||
public final class UpdateSDK {
|
||||
|
||||
@ -50,17 +41,4 @@ public final class UpdateSDK {
|
||||
NSWorkspace.shared.open(storeURL)
|
||||
#endif
|
||||
}
|
||||
|
||||
public func checkRnUpdate(moduleId: String, currentVersion: String) async throws -> RnUpdateInfo {
|
||||
let config = XuqmSDK.shared.requireConfig()
|
||||
return try await ApiClient.shared.request(
|
||||
path: "/api/v1/rn/update/check",
|
||||
queryItems: [
|
||||
URLQueryItem(name: "appId", value: config.appId),
|
||||
URLQueryItem(name: "moduleId", value: moduleId),
|
||||
URLQueryItem(name: "platform", value: "IOS"),
|
||||
URLQueryItem(name: "currentVersion", value: currentVersion),
|
||||
]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
正在加载...
在新工单中引用
屏蔽一个用户