- 添加 expiresAt 和 refreshUserSig 参数支持自动续签 - 修改 PushSDK 初始化方式,自动完成设备注册和厂商初始化 - 调整过期续签策略,从提前 15 分钟改为提前 5 分钟触发 - 重构 RN SDK 文档结构,简化安装和使用方式 - 更新统一登录流程,支持 profile 信息传递 - 添加 IM 数据库自动隔离功能 - 修复 Android 群消息聚合问题 - 补充自动化测试验证和错误处理机制
112 行
3.2 KiB
Swift
112 行
3.2 KiB
Swift
import Foundation
|
|
import XuqmSDK
|
|
|
|
enum AppRoute: Hashable {
|
|
case chat(targetId: String, targetName: String)
|
|
}
|
|
|
|
struct DemoUser: Identifiable {
|
|
let id: String
|
|
let userId: String
|
|
let nickname: String
|
|
let avatar: String?
|
|
}
|
|
|
|
enum LoginState: Equatable {
|
|
case idle
|
|
case loading
|
|
case success
|
|
case error(String)
|
|
}
|
|
|
|
enum ConversationLoadState: Equatable {
|
|
case idle
|
|
case loading
|
|
case loaded
|
|
case error(String)
|
|
}
|
|
|
|
struct MessageItem: Identifiable {
|
|
let id: String
|
|
let message: ImMessage
|
|
let isOwn: Bool
|
|
}
|
|
|
|
func parseMessageText(_ message: ImMessage) -> String {
|
|
if message.msgType == .text {
|
|
if let data = message.content.data(using: .utf8),
|
|
let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
|
|
let text = json["text"] as? String {
|
|
return text
|
|
}
|
|
return message.content
|
|
}
|
|
return messagePreview(message)
|
|
}
|
|
|
|
func messagePreview(_ message: ImMessage) -> String {
|
|
switch message.msgType {
|
|
case .image: return "[图片]"
|
|
case .video: return "[视频]"
|
|
case .audio: return "[语音]"
|
|
case .file: return "[文件]"
|
|
case .location: return "[位置]"
|
|
case .custom: return "[自定义]"
|
|
case .richText: return "[富文本]"
|
|
case .forward: return "[转发]"
|
|
case .quote: return "[引用]"
|
|
case .merge: return "[合并转发]"
|
|
case .callAudio: return "[语音通话]"
|
|
case .callVideo: return "[视频通话]"
|
|
case .revoked: return "[消息已撤回]"
|
|
case .notify: return message.content
|
|
case .text: return message.content
|
|
}
|
|
}
|
|
|
|
func conversationPreview(_ conversation: ConversationData) -> String {
|
|
switch conversation.lastMsgType?.uppercased() {
|
|
case "TEXT": return conversation.lastMsgContent ?? ""
|
|
case "IMAGE": return "[图片]"
|
|
case "VIDEO": return "[视频]"
|
|
case "AUDIO": return "[语音]"
|
|
case "FILE": return "[文件]"
|
|
case "LOCATION": return "[位置]"
|
|
case "CUSTOM": return "[自定义]"
|
|
case "RICH_TEXT": return "[富文本]"
|
|
case "FORWARD": return "[转发]"
|
|
case "QUOTE": return "[引用]"
|
|
case "MERGE": return "[合并转发]"
|
|
case "CALL_AUDIO": return "[语音通话]"
|
|
case "CALL_VIDEO": return "[视频通话]"
|
|
case "REVOKED": return "[消息已撤回]"
|
|
case "NOTIFY": return conversation.lastMsgContent ?? "[通知]"
|
|
default: return conversation.lastMsgContent ?? ""
|
|
}
|
|
}
|
|
|
|
func statusLabel(_ status: MsgStatus) -> String {
|
|
switch status {
|
|
case .sending: return "发送中"
|
|
case .sent: return "已发送"
|
|
case .delivered: return "已送达"
|
|
case .read: return "已读"
|
|
case .failed: return "发送失败"
|
|
case .revoked: return "已撤回"
|
|
}
|
|
}
|
|
|
|
func formatConversationTime(_ timestamp: Int64) -> String {
|
|
let date = Date(timeIntervalSince1970: Double(timestamp) / 1000)
|
|
let formatter = DateFormatter()
|
|
formatter.locale = Locale(identifier: "zh_CN")
|
|
if Calendar.current.isDateInToday(date) {
|
|
formatter.dateFormat = "HH:mm"
|
|
} else if Calendar.current.isDateInYesterday(date) {
|
|
return "昨天"
|
|
} else {
|
|
formatter.dateFormat = "MM-dd"
|
|
}
|
|
return formatter.string(from: date)
|
|
}
|