383 lines
13 KiB
Swift
383 lines
13 KiB
Swift
//
|
|
// PigeonModel.swift
|
|
// QuickLocation
|
|
//
|
|
|
|
import ObjectMapper
|
|
import UIKit
|
|
|
|
struct PigeonLocalTemplate: Equatable {
|
|
let id: String
|
|
let title: String
|
|
let mediaType: String
|
|
let coverAssetName: String
|
|
let contentAssetName: String
|
|
|
|
static let imageTemplates: [PigeonLocalTemplate] = [
|
|
PigeonLocalTemplate(
|
|
id: "come_play",
|
|
title: "出来玩",
|
|
mediaType: "image",
|
|
coverAssetName: "PigeonMessage/template_come_play_cover",
|
|
contentAssetName: "PigeonMessage/template_come_play"
|
|
),
|
|
PigeonLocalTemplate(
|
|
id: "miss_you",
|
|
title: "想你了",
|
|
mediaType: "image",
|
|
coverAssetName: "PigeonMessage/template_miss_you_cover",
|
|
contentAssetName: "PigeonMessage/template_miss_you"
|
|
),
|
|
PigeonLocalTemplate(
|
|
id: "buy_for_me",
|
|
title: "给我买",
|
|
mediaType: "image",
|
|
coverAssetName: "PigeonMessage/template_buy_for_me_cover",
|
|
contentAssetName: "PigeonMessage/template_buy_for_me"
|
|
),
|
|
PigeonLocalTemplate(
|
|
id: "dislike_you",
|
|
title: "讨厌你",
|
|
mediaType: "image",
|
|
coverAssetName: "PigeonMessage/template_dislike_you_cover",
|
|
contentAssetName: "PigeonMessage/template_dislike_you"
|
|
),
|
|
PigeonLocalTemplate(
|
|
id: "who_upset_me",
|
|
title: "谁惹我",
|
|
mediaType: "image",
|
|
coverAssetName: "PigeonMessage/template_who_upset_me_cover",
|
|
contentAssetName: "PigeonMessage/template_who_upset_me"
|
|
),
|
|
PigeonLocalTemplate(
|
|
id: "apology",
|
|
title: "道歉",
|
|
mediaType: "image",
|
|
coverAssetName: "PigeonMessage/template_apology_cover",
|
|
contentAssetName: "PigeonMessage/template_apology"
|
|
),
|
|
PigeonLocalTemplate(
|
|
id: "arriving_soon",
|
|
title: "马上到",
|
|
mediaType: "image",
|
|
coverAssetName: "PigeonMessage/template_arriving_soon_cover",
|
|
contentAssetName: "PigeonMessage/template_arriving_soon"
|
|
),
|
|
PigeonLocalTemplate(
|
|
id: "proud",
|
|
title: "骄傲",
|
|
mediaType: "image",
|
|
coverAssetName: "PigeonMessage/template_proud_cover",
|
|
contentAssetName: "PigeonMessage/template_proud"
|
|
)
|
|
]
|
|
|
|
var coverImage: UIImage? {
|
|
UIImage(named: coverAssetName)
|
|
}
|
|
|
|
var contentImage: UIImage? {
|
|
UIImage(named: contentAssetName)
|
|
}
|
|
|
|
static func resolve(templateId: String) -> PigeonLocalTemplate? {
|
|
imageTemplates.first { $0.id == templateId }
|
|
}
|
|
}
|
|
|
|
struct PigeonVoiceTemplate: Equatable {
|
|
let id: String
|
|
let title: String
|
|
let duration: TimeInterval
|
|
let audioAssetName: String
|
|
|
|
static let templates: [PigeonVoiceTemplate] = [
|
|
PigeonVoiceTemplate(id: "sorry_im_right", title: "错不起,我对了", duration: 1.881),
|
|
PigeonVoiceTemplate(id: "wake_up_sleepyhead", title: "小懒虫,起床啦", duration: 2.821),
|
|
PigeonVoiceTemplate(id: "dont_you_need_to_work", title: "你们不用打工吗 一天......", duration: 4.049),
|
|
PigeonVoiceTemplate(id: "ignoring_me", title: "不理我 是吧", duration: 3.527),
|
|
PigeonVoiceTemplate(id: "who_can_save_me", title: "谁来救救我", duration: 1.228),
|
|
PigeonVoiceTemplate(id: "baby_dont_be_angry", title: "宝宝,别生气了", duration: 3.056),
|
|
PigeonVoiceTemplate(id: "okay", title: "好的", duration: 2.377),
|
|
PigeonVoiceTemplate(id: "thank_you", title: "谢谢你", duration: 0.836),
|
|
PigeonVoiceTemplate(id: "good_night_kiss", title: "我先睡了 晚安 么么哒", duration: 2.299),
|
|
PigeonVoiceTemplate(id: "sleep_if_you_want", title: "如果你想睡觉就晚安", duration: 5.956),
|
|
PigeonVoiceTemplate(id: "getting_bold", title: "我看你胆子真是肥嘟嘟", duration: 2.534),
|
|
PigeonVoiceTemplate(id: "mosquito_violin", title: "再不理我我就派蚊子去你耳边拉小提琴", duration: 5.721),
|
|
PigeonVoiceTemplate(id: "am_i_talkative", title: "我多嘴问一句我多嘴吗", duration: 6.949),
|
|
PigeonVoiceTemplate(id: "is_my_mic_loud", title: "我的麦很炸吗", duration: 3.396),
|
|
PigeonVoiceTemplate(id: "love_you", title: "爱你哟", duration: 1.019),
|
|
PigeonVoiceTemplate(id: "what_can_you_do", title: "说白了 你有啥实力啊", duration: 3.056),
|
|
PigeonVoiceTemplate(id: "save_me", title: "救我救我", duration: 1.489),
|
|
PigeonVoiceTemplate(id: "dare_to_compete", title: "敢不敢和我比划比划", duration: 1.646),
|
|
PigeonVoiceTemplate(id: "teasing_you_daily", title: "其实每天骚扰你就是我最大的乐趣", duration: 3.448)
|
|
]
|
|
|
|
private init(id: String, title: String, duration: TimeInterval) {
|
|
self.id = id
|
|
self.title = title
|
|
self.duration = duration
|
|
audioAssetName = "PigeonMessage/voice_\(id)"
|
|
}
|
|
|
|
var audioData: Data? {
|
|
NSDataAsset(name: audioAssetName)?.data
|
|
}
|
|
|
|
static func resolve(templateId: String) -> PigeonVoiceTemplate? {
|
|
templates.first { $0.id == templateId }
|
|
}
|
|
}
|
|
|
|
struct PigeonTemplateExtra: Mappable {
|
|
var image_template_id: String = ""
|
|
var voice_template_id: String = ""
|
|
|
|
init?(map: Map) {}
|
|
|
|
static func decode(_ value: Any?) -> PigeonTemplateExtra? {
|
|
if let extra = value as? PigeonTemplateExtra {
|
|
return extra
|
|
}
|
|
if let json = value as? [String: Any] {
|
|
return PigeonTemplateExtra(JSON: json)
|
|
}
|
|
|
|
let data: Data?
|
|
if let value = value as? String {
|
|
data = value.data(using: .utf8)
|
|
} else {
|
|
data = value as? Data
|
|
}
|
|
guard let data,
|
|
let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else {
|
|
return nil
|
|
}
|
|
return PigeonTemplateExtra(JSON: json)
|
|
}
|
|
|
|
mutating func mapping(map: Map) {
|
|
image_template_id <- map["image_template_id"]
|
|
voice_template_id <- map["voice_template_id"]
|
|
|
|
var legacyMediaType = ""
|
|
var legacyTemplateID = ""
|
|
legacyMediaType <- map["media_type"]
|
|
legacyTemplateID <- map["template_id"]
|
|
let legacyID = legacyTemplateID.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
guard !legacyID.isEmpty else { return }
|
|
|
|
switch legacyMediaType.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() {
|
|
case "voice":
|
|
if voice_template_id.isEmpty { voice_template_id = legacyID }
|
|
case "image":
|
|
if image_template_id.isEmpty { image_template_id = legacyID }
|
|
default:
|
|
if image_template_id.isEmpty,
|
|
PigeonLocalTemplate.resolve(templateId: legacyID) != nil {
|
|
image_template_id = legacyID
|
|
} else if voice_template_id.isEmpty,
|
|
PigeonVoiceTemplate.resolve(templateId: legacyID) != nil {
|
|
voice_template_id = legacyID
|
|
}
|
|
}
|
|
}
|
|
|
|
var normalizedImageTemplateID: String {
|
|
image_template_id.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
}
|
|
|
|
var normalizedVoiceTemplateID: String {
|
|
voice_template_id.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
}
|
|
|
|
var sendParameters: [String: Any]? {
|
|
var parameters: [String: Any] = [:]
|
|
if !normalizedImageTemplateID.isEmpty {
|
|
parameters["image_template_id"] = normalizedImageTemplateID
|
|
}
|
|
if !normalizedVoiceTemplateID.isEmpty {
|
|
parameters["voice_template_id"] = normalizedVoiceTemplateID
|
|
}
|
|
return parameters.isEmpty ? nil : parameters
|
|
}
|
|
}
|
|
|
|
private let kPigeonTemplateExtraTransform = TransformOf<PigeonTemplateExtra, Any>(fromJSON: { value in
|
|
PigeonTemplateExtra.decode(value)
|
|
}, toJSON: { value in
|
|
value?.sendParameters
|
|
})
|
|
|
|
struct PigeonSentResponse: BaseModelProtocol {
|
|
var code: String?
|
|
var message: String?
|
|
var list: [PigeonSentMessage] = []
|
|
|
|
init?(map: Map) {}
|
|
|
|
mutating func mapping(map: Map) {
|
|
code <- (map["code"], kIntTransformStr)
|
|
message <- map["message"]
|
|
list <- map["data"]
|
|
}
|
|
}
|
|
|
|
struct PigeonSentMessage: Mappable {
|
|
var message_uuid: String = ""
|
|
var group_key: String = ""
|
|
var from_user: PigeonSentUser?
|
|
var to_user: [PigeonSentUser] = []
|
|
var msg_type: Int = 0
|
|
var msg: String = ""
|
|
var text_msg: String = ""
|
|
var bg_img: String = ""
|
|
var extra: PigeonTemplateExtra?
|
|
var expire_time: Int64 = 0
|
|
var send_time: Int64 = 0
|
|
|
|
init?(map: Map) {}
|
|
|
|
mutating func mapping(map: Map) {
|
|
message_uuid <- map["message_uuid"]
|
|
group_key <- map["group_key"]
|
|
from_user <- map["from_user"]
|
|
to_user <- map["to_user"]
|
|
msg_type <- map["msg_type"]
|
|
msg <- map["msg"]
|
|
text_msg <- map["text_msg"]
|
|
bg_img <- map["bg_img"]
|
|
extra <- (map["extra"], kPigeonTemplateExtraTransform)
|
|
expire_time <- map["expire_time"]
|
|
send_time <- map["send_time"]
|
|
}
|
|
|
|
var isVoice: Bool { msg_type == 2 }
|
|
|
|
var localTemplate: PigeonLocalTemplate? {
|
|
let templateId = extra?.normalizedImageTemplateID ?? ""
|
|
return PigeonLocalTemplate.resolve(templateId: templateId)
|
|
}
|
|
|
|
var localTemplateImage: UIImage? {
|
|
localTemplate?.contentImage
|
|
}
|
|
|
|
var localVoiceTemplate: PigeonVoiceTemplate? {
|
|
let templateId = extra?.normalizedVoiceTemplateID ?? ""
|
|
return PigeonVoiceTemplate.resolve(templateId: templateId)
|
|
}
|
|
|
|
var localVoiceData: Data? {
|
|
localVoiceTemplate?.audioData
|
|
}
|
|
|
|
var captionText: String {
|
|
if isVoice { return "" }
|
|
let fromMsg = msg.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
if !fromMsg.isEmpty, !fromMsg.lowercased().hasPrefix("http") {
|
|
return fromMsg
|
|
}
|
|
return text_msg
|
|
}
|
|
|
|
var backgroundURL: URL? {
|
|
let background = bg_img.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
let legacyImage = isVoice ? "" : msg.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
let raw = background.lowercased().hasPrefix("http") ? background : legacyImage
|
|
guard raw.lowercased().hasPrefix("http"), let url = URL(string: raw) else {
|
|
return nil
|
|
}
|
|
return url
|
|
}
|
|
|
|
var audioURL: URL? {
|
|
guard isVoice else { return nil }
|
|
let raw = msg.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
guard raw.lowercased().hasPrefix("http"), let url = URL(string: raw) else {
|
|
return nil
|
|
}
|
|
return url
|
|
}
|
|
|
|
var mediaURL: URL? {
|
|
isVoice ? audioURL : backgroundURL
|
|
}
|
|
|
|
func toHistoryItem() -> PigeonHistoryItem {
|
|
PigeonHistoryItem(
|
|
id: message_uuid.isEmpty ? UUID().uuidString : message_uuid,
|
|
dateText: Self.dateText(from: send_time),
|
|
timeText: Self.timeText(from: send_time),
|
|
kind: isVoice ? .voice : .image,
|
|
caption: captionText,
|
|
image: localTemplateImage,
|
|
mediaURL: mediaURL,
|
|
localAudioData: localVoiceData,
|
|
senderAvatar: from_user?.avatarImage,
|
|
receiverAvatars: to_user.map(\.avatarImage),
|
|
duration: localVoiceTemplate?.duration ?? 0
|
|
)
|
|
}
|
|
|
|
private static func date(from timestamp: Int64) -> Date {
|
|
Date(timeIntervalSince1970: TimeInterval(timestamp))
|
|
}
|
|
|
|
private static func dateText(from timestamp: Int64) -> String {
|
|
let date = date(from: timestamp)
|
|
let calendar = Calendar.current
|
|
let month = calendar.component(.month, from: date)
|
|
let day = calendar.component(.day, from: date)
|
|
let weekdays = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"]
|
|
let weekday = weekdays[calendar.component(.weekday, from: date) - 1]
|
|
return "\(month).\(day) \(weekday)"
|
|
}
|
|
|
|
private static func timeText(from timestamp: Int64) -> String {
|
|
let date = date(from: timestamp)
|
|
let calendar = Calendar.current
|
|
let hour = calendar.component(.hour, from: date)
|
|
let minute = calendar.component(.minute, from: date)
|
|
let period = hour < 12 ? "上午" : "下午"
|
|
let hour12 = hour % 12 == 0 ? 12 : hour % 12
|
|
return String(format: "%@ %d:%02d", period, hour12, minute)
|
|
}
|
|
}
|
|
|
|
struct PigeonSentUser: Mappable {
|
|
var user_id: String = ""
|
|
var nick_name: String = ""
|
|
var remark: String = ""
|
|
var head_pic: String = ""
|
|
var extra = MemberExtra()
|
|
|
|
init?(map: Map) {}
|
|
|
|
mutating func mapping(map: Map) {
|
|
user_id <- map["user_id"]
|
|
nick_name <- map["nick_name"]
|
|
remark <- map["remark"]
|
|
head_pic <- map["head_pic"]
|
|
extra <- (map["extra"], kMemberExtraTransform)
|
|
if extra.relation_idx.isEmpty {
|
|
extra.relation_idx <- (map["relation_idx"], kMemberRelationIndexTransform)
|
|
}
|
|
}
|
|
|
|
var displayName: String {
|
|
let remarkName = remark.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
if !remarkName.isEmpty { return remarkName }
|
|
return nick_name
|
|
}
|
|
|
|
var avatarImage: UIImage {
|
|
let iconName = head_pic.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
guard !iconName.isEmpty,
|
|
let image = UIImage(named: "UserIcon/\(iconName)") else {
|
|
return UIImage(named: "UserIcon/1") ?? UIImage()
|
|
}
|
|
return image
|
|
}
|
|
}
|