// // Models.swift // kordophone2 // // Created by James Magahern on 8/24/25. // import Foundation import XPC enum Display { struct Conversation: Identifiable { let id: String let name: String? let participants: [String] let messagePreview: String var displayName: String { if let name, name.count > 0 { return name } else { return participants.joined(separator: ", ") } } init(from c: Serialized.Conversation) { self.id = c.guid self.name = c.displayName self.participants = c.participants self.messagePreview = c.lastMessagePreview ?? "" } init(id: String = UUID().uuidString, name: String? = nil, participants: [String], messagePreview: String) { self.id = id self.name = name self.participants = participants self.messagePreview = messagePreview } } struct Message: Identifiable, Hashable { let id: String let sender: Sender let text: String var isFromMe: Bool { if case .me = sender { true } else { false } } init(from m: Serialized.Message) { self.id = m.guid self.text = m.text self.sender = if m.sender == "(Me)" { .me } else { .counterpart(m.sender) } } init(id: String = UUID().uuidString, sender: Sender = .me, text: String) { self.id = id self.sender = sender self.text = text } static func == (lhs: Message, rhs: Message) -> Bool { lhs.id == rhs.id } func hash(into hasher: inout Hasher) { hasher.combine(id) } enum Sender { case me case counterpart(String) } } } enum Serialized { struct Conversation: Decodable { let guid: String let displayName: String? let participants: [String] let lastMessagePreview: String? let unreadCount: Int let date: Date init?(xpc dict: xpc_object_t) { guard let g: String = dict["guid"] else { return nil } let dn: String? = dict["display_name"] let lmp: String? = dict["last_message_preview"] let names: [String] = dict["participants"] ?? [] let unread: Int = dict["unread_count"] ?? 0 let dt: Date = dict["date"] ?? Date(timeIntervalSince1970: 0) self.guid = g self.displayName = dn self.participants = names self.lastMessagePreview = lmp self.unreadCount = unread self.date = dt } } struct Message: Decodable { let guid: String let sender: String let text: String let date: Date init?(xpc dict: xpc_object_t) { guard let g: String = dict["id"] else { return nil } let s: String = dict["sender"] ?? "" let t: String = dict["text"] ?? "" let d: Date = dict["date"] ?? Date(timeIntervalSince1970: 0) self.guid = g self.sender = s self.text = t self.date = d } } }