130 lines
3.5 KiB
Swift
130 lines
3.5 KiB
Swift
|
|
//
|
|||
|
|
// IMMessageModels.swift
|
|||
|
|
// Crush
|
|||
|
|
//
|
|||
|
|
// Created by Leon on 2025/8/22.
|
|||
|
|
//
|
|||
|
|
|
|||
|
|
import Foundation
|
|||
|
|
|
|||
|
|
enum CLCustomAttchType: String, Codable {
|
|||
|
|
case IMAGE
|
|||
|
|
case IM_SEND_GIFT
|
|||
|
|
case HEARTBEAT_LEVEL_UP
|
|||
|
|
case HEARTBEAT_LEVEL_DOWN
|
|||
|
|
case CALL
|
|||
|
|
// 余额不足 raw:{"type":"INSUFFICIENT_BALANCE","content":"余额不足"}
|
|||
|
|
case INSUFFICIENT_BALANCE
|
|||
|
|
/// 过滤此消息, 后端用来保持语音和文本之间的上下文使用
|
|||
|
|
case VOICE_CHAT_CONTENT
|
|||
|
|
|
|||
|
|
/// 一些自定义消息需要滑动显示完成
|
|||
|
|
var needInstantScrollDisplay: Bool{
|
|||
|
|
switch self {
|
|||
|
|
case .IMAGE, .IM_SEND_GIFT:
|
|||
|
|
return true
|
|||
|
|
default:
|
|||
|
|
return false
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
struct IMCustomAttachment: Codable{
|
|||
|
|
var type: CLCustomAttchType?
|
|||
|
|
/// 图片url
|
|||
|
|
var url: String? // 可能是模糊图片
|
|||
|
|
var width: FlexibleCGFloat?
|
|||
|
|
var height: FlexibleCGFloat?
|
|||
|
|
var albumId: Int? // 相册id
|
|||
|
|
var unlockPrice: Int? // AI图片解锁需要的价格。
|
|||
|
|
|
|||
|
|
// - 礼物专属
|
|||
|
|
var giftId: Int?
|
|||
|
|
var giftName: String?
|
|||
|
|
var giftNum: Int?
|
|||
|
|
var giftIcon: String?
|
|||
|
|
/**
|
|||
|
|
// HEARTBEAT_LEVEL_UP 和 HEARTBEAT_LEVEL_DOWN的title
|
|||
|
|
imContent
|
|||
|
|
*/
|
|||
|
|
var title : String?
|
|||
|
|
var icon: String?
|
|||
|
|
|
|||
|
|
// - Call
|
|||
|
|
var callType: CallType?
|
|||
|
|
var duration: Int?
|
|||
|
|
|
|||
|
|
// - 心动等级升降
|
|||
|
|
var heartbeatLevel: HeartbeatLevel?
|
|||
|
|
var heartbeatLevelNum: Int?
|
|||
|
|
var heartbeatVal: CGFloat?
|
|||
|
|
var heartbeatLevelName: String?
|
|||
|
|
|
|||
|
|
func getDisplayString() -> String{
|
|||
|
|
var displayString = ""
|
|||
|
|
// guard let theType = type else{
|
|||
|
|
// return displayString
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
switch type {
|
|||
|
|
case .IMAGE:
|
|||
|
|
displayString = "[Image]"
|
|||
|
|
case .IM_SEND_GIFT:
|
|||
|
|
displayString = "[Gift]"
|
|||
|
|
case .CALL:
|
|||
|
|
displayString = dealCallAttachment()
|
|||
|
|
default:
|
|||
|
|
displayString = " "
|
|||
|
|
#if DEBUG
|
|||
|
|
// 最后一条消息,可能是自定义消息,且不含内容,比如coin不足。
|
|||
|
|
displayString = "[测试环境显示]Check 类型⚠️ is \(String(describing: type))"
|
|||
|
|
#endif
|
|||
|
|
}
|
|||
|
|
return displayString
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// MARK: - Helper
|
|||
|
|
extension IMCustomAttachment{
|
|||
|
|
// ⚠️不清晰,需要换!
|
|||
|
|
static func getCustomInfo(model: SessionBaseModel) -> IMCustomAttachment? {
|
|||
|
|
guard let raw = model.v2msg?.attachment?.raw else{
|
|||
|
|
dlog("☁️❌ getCustom error")
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
return CodableHelper.decode(IMCustomAttachment.self, from: raw)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private func dealCallAttachment() -> String {
|
|||
|
|
guard let theCallType = callType else { return "" }
|
|||
|
|
if theCallType == .CALL_CANCEL {
|
|||
|
|
return "Call Canceled"
|
|||
|
|
} else {
|
|||
|
|
let durationInMinistamp = duration ?? 0
|
|||
|
|
return formatDuration(durationInMinistamp)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fileprivate func formatDuration(_ duration: Int) -> String {
|
|||
|
|
// 毫秒 → 秒(向上取整)
|
|||
|
|
let totalSeconds = Int(ceil(Double(duration) / 1000.0))
|
|||
|
|
|
|||
|
|
let hours = totalSeconds / 3600
|
|||
|
|
let minutes = (totalSeconds / 60) % 60
|
|||
|
|
let seconds = totalSeconds % 60
|
|||
|
|
|
|||
|
|
if hours > 0 {
|
|||
|
|
return String(format: "%@ %02d:%02d:%02d", "Call Duration", hours, minutes, seconds)
|
|||
|
|
} else {
|
|||
|
|
return String(format: "%@ %02d:%02d", "Call Duration", minutes, seconds)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
enum CallType: String, Codable{
|
|||
|
|
case CALL_CANCEL
|
|||
|
|
case CALL_END
|
|||
|
|
}
|