feat(im): 添加即时通讯SDK核心功能
- 实现IM API接口定义,包括消息、群组、好友、黑名单等功能 - 定义IM消息相关数据模型,包含聊天类型、消息类型、用户资料等 - 实现ImSDK单例类,提供登录、消息发送、群组管理、好友管理等核心功能 - 添加WebSocket连接管理,支持自动重连机制 - 实现历史消息查询、群组操作、用户资料管理等API调用 - 添加会话状态管理,支持置顶、静音、草稿等功能 - 集成文件上传结果,支持多媒体消息发送 - 实现连接状态监听和事件回调机制
这个提交包含在:
父节点
027937db1b
当前提交
5eb46f97c6
20
README.md
20
README.md
@ -20,7 +20,7 @@ XuqmGroup-iOSSDK/
|
|||||||
├── Push/
|
├── Push/
|
||||||
│ └── PushSDK.swift # APNs Token 注册
|
│ └── PushSDK.swift # APNs Token 注册
|
||||||
└── Update/
|
└── Update/
|
||||||
└── UpdateSDK.swift # 版本检查 / Bundle 下载
|
└── UpdateSDK.swift # 版本检查 / App 更新
|
||||||
```
|
```
|
||||||
|
|
||||||
## 集成
|
## 集成
|
||||||
@ -226,23 +226,7 @@ if result.needsUpdate, let info = result.info {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 检查 RN Bundle 更新
|
`UpdateSDK` 这里只负责 iOS App 版本更新。RN 热更新如果需要,走独立的 RN SDK / RN 更新模块,不并入统一发版能力。
|
||||||
|
|
||||||
```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 引擎加载
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@ -339,6 +339,56 @@ public final class ImSDK {
|
|||||||
return groups
|
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 {
|
public func createGroup(name: String, memberIds: [String], groupType: String = "WORK") async throws -> ImGroup {
|
||||||
let config = XuqmSDK.shared.requireConfig()
|
let config = XuqmSDK.shared.requireConfig()
|
||||||
return try await ApiClient.shared.request(
|
return try await ApiClient.shared.request(
|
||||||
|
|||||||
@ -46,6 +46,18 @@ public struct ImMessage: Codable, Sendable {
|
|||||||
public let createdAt: Int64
|
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 {
|
public protocol ImEventDelegate: AnyObject {
|
||||||
func imClientDidConnect()
|
func imClientDidConnect()
|
||||||
func imClientDidDisconnect(reason: String?)
|
func imClientDidDisconnect(reason: String?)
|
||||||
|
|||||||
@ -15,15 +15,6 @@ public struct AppUpdateInfo: Decodable, Sendable {
|
|||||||
public let appStoreUrl: String?
|
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
|
@MainActor
|
||||||
public final class UpdateSDK {
|
public final class UpdateSDK {
|
||||||
|
|
||||||
@ -50,17 +41,4 @@ public final class UpdateSDK {
|
|||||||
NSWorkspace.shared.open(storeURL)
|
NSWorkspace.shared.open(storeURL)
|
||||||
#endif
|
#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),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
正在加载...
在新工单中引用
屏蔽一个用户