# iOS IM 接入

基于 `XuqmSDK` 中的 IM 子模块实现即时通讯功能。

---

## 初始化与登录

### 初始化

```swift
import XuqmSDK

XuqmSDK.shared.initialize(config: config)
```

### 登录（UserSig 模式）

```swift
import XuqmSDK

try await XuqmSDK.shared.login(userId: "user_001", userSig: "your_user_sig_jwt")
```


---

## 消息收发

### 设置事件代理

```swift
import XuqmSDK

ImSDK.shared.setDelegate(self)

extension ViewController: ImEventDelegate {
    func imClientDidConnect() { print("IM connected") }
    func imClientDidReceiveMessage(_ msg: ImMessage) { /* 处理单聊消息 */ }
    func imClientDidReceiveGroupMessage(_ msg: ImMessage) { /* 处理群消息 */ }
    func imClientDidReadMessage(_ msg: ImMessage) { /* 对方已读回执 */ }
    func imClientDidReceiveRevokedMessage(_ msg: ImMessage) { /* 消息被撤回 */ }
    func imClientDidDisconnect(reason: String?) { /* 断线 */ }
    func imClientDidError(_ error: String) { /* 错误 */ }
}
```

### 发送文本消息

```swift
let msg = ImSDK.shared.sendTextMessage(
    toId: "user_002",
    chatType: .single,
    content: "Hello!"
)
```

### 发送多媒体消息

```swift
// 图片
let msg = ImSDK.shared.sendImageMessage(
    toId: "user_002",
    chatType: .single,
    url: "https://cdn.example.com/img.jpg",
    width: 800,
    height: 600
)

// 视频
let msg = ImSDK.shared.sendVideoMessage(
    toId: "user_002",
    chatType: .single,
    url: "https://cdn.example.com/video.mp4",
    duration: 15,
    size: 5_000_000
)

// 语音
let msg = ImSDK.shared.sendAudioMessage(
    toId: "user_002",
    chatType: .single,
    url: "https://cdn.example.com/audio.mp3",
    duration: 5,
    size: 100_000
)

// 文件
let msg = ImSDK.shared.sendFileMessage(
    toId: "user_002",
    chatType: .single,
    url: "https://cdn.example.com/file.pdf",
    name: "document.pdf",
    size: 2_000_000
)

// 位置
let msg = ImSDK.shared.sendLocationMessage(
    toId: "user_002",
    chatType: .single,
    lat: 31.2304,
    lng: 121.4737,
    title: "上海",
    address: "上海市黄浦区"
)
```

### 撤回与编辑

```swift
try await ImSDK.shared.revokeMessage(messageId: msg.id)
try await ImSDK.shared.editMessage(messageId: msg.id, content: "新内容")
```

### 获取历史消息

```swift
let history = try await ImSDK.shared.fetchHistory(toId: "user_002", page: 0, size: 20)
let groupHistory = try await ImSDK.shared.fetchGroupHistory(groupId: "group_xxx", page: 0, size: 20)
```

---

## 群聊

### 创建群组

```swift
let group = try await ImSDK.shared.createGroup(
    name: "项目讨论",
    memberIds: ["user_001", "user_002"],
    groupType: "WORK"
)
```

### 订阅群消息

```swift
ImSDK.shared.subscribeGroup(group.id)
```

### 发送群消息

```swift
ImSDK.shared.sendTextMessage(toId: group.id, chatType: .group, content: "大家好")
```

### 群管理

```swift
// 添加/移除成员
try await ImSDK.shared.addGroupMember(groupId: group.id, userId: "user_003")
try await ImSDK.shared.removeGroupMember(groupId: group.id, targetUserId: "user_003")

// 设置角色
try await ImSDK.shared.setGroupRole(groupId: group.id, userId: "user_003", role: "ADMIN")

// 禁言
try await ImSDK.shared.muteGroupMember(groupId: group.id, userId: "user_003", minutes: 60)

// 转让群主
try await ImSDK.shared.transferGroupOwner(groupId: group.id, newOwnerId: "user_002")

// 退出/解散
try await ImSDK.shared.leaveGroup(groupId: group.id)
try await ImSDK.shared.dismissGroup(groupId: group.id)
```

---

## 好友管理

```swift
let friends = try await ImSDK.shared.listFriends()
try await ImSDK.shared.addFriend(friendId: "user_002")
try await ImSDK.shared.removeFriend(friendId: "user_002")

// 好友请求
try await ImSDK.shared.sendFriendRequest(toUserId: "user_002", remark: "你好")
let requests = try await ImSDK.shared.listFriendRequests(direction: "incoming")
try await ImSDK.shared.acceptFriendRequest(requestId: "request_id")
try await ImSDK.shared.rejectFriendRequest(requestId: "request_id")

// 黑名单
let blacklist = try await ImSDK.shared.listBlacklist()
try await ImSDK.shared.addToBlacklist(blockedUserId: "user_002")
try await ImSDK.shared.removeFromBlacklist(blockedUserId: "user_002")
```

---

## 会话列表

```swift
let conversations = try await ImSDK.shared.listConversations()

try await ImSDK.shared.setConversationPinned(targetId: "user_002", chatType: .single, pinned: true)
try await ImSDK.shared.setConversationMuted(targetId: "user_002", chatType: .single, muted: true)
try await ImSDK.shared.markRead(targetId: "user_002", chatType: .single)
try await ImSDK.shared.setDraft(targetId: "user_002", chatType: .single, draft: "未完成")
try await ImSDK.shared.deleteConversation(targetId: "user_002", chatType: .single)
```

---

## 离线消息同步

```swift
let count = try await ImSDK.shared.offlineMessageCount()
let offlineMessages = try await ImSDK.shared.syncOfflineMessages()
```

---

## 连接状态监听

```swift
let state = ImSDK.shared.connectionState
// .disconnected / .connecting / .connected

ImSDK.shared.addConnectionStateListener { state in
    switch state {
    case .connected: print("IM 已连接")
    case .connecting: print("IM 连接中...")
    case .disconnected: print("IM 已断开")
    }
}
```

---

## 消息类型

| MsgType | 说明 | content 结构 |
|---------|------|-------------|
| `.text` | 纯文本 | `String` |
| `.image` | 图片 | `{url, width, height, thumbnailUrl?}` |
| `.video` | 视频 | `{url, duration, thumbnailUrl, size}` |
| `.audio` | 语音 | `{url, duration, size}` |
| `.file` | 文件 | `{url, name, size, mimeType}` |
| `.location` | 位置 | `{lat, lng, address, title}` |
| `.custom` | 自定义 | 任意 JSON |
| `.notify` | 系统通知 | `{title, content}` |
| `.richText` | 富文本 | `{html}` |
| `.callAudio` | 语音通话信令 | `{action}` |
| `.callVideo` | 视频通话信令 | `{action}` |
| `.forward` | 转发 | `{originalSender, originalContent}` |
| `.quote` | 引用 | `{quotedMsgId, quotedContent, text}` |
| `.merge` | 合并转发 | `{title, msgList}` |
| `.revoked` | 撤回 | 系统内部填充 |
