import Foundation import GRDB import Martin enum MessageType: String, Codable, DatabaseValueConvertible { case chat case groupchat case error } enum MessageContentType: String, Codable, DatabaseValueConvertible { case text case typing case invite } struct Message: DBStorable, Equatable { static let databaseTableName = "messages" let id: String let type: MessageType let contentType: MessageContentType let from: String let to: String? let body: String? let subject: String? let thread: String? let oobUrl: String? let date: Date let pending: Bool let sentError: Bool static let attachment = hasOne(Attachment.self) var attachment: QueryInterfaceRequest { request(for: Message.attachment) } var attachmentId: String? } extension Message { // Universal mapping from Martin's Message to App Message static func map(_ martinMessage: Martin.Message) -> Message? { #if DEBUG print("---") print("Message received: \(martinMessage)") print("---") #endif // Check that the message type is supported let chatTypes: [StanzaType] = [.chat, .groupchat] guard let mType = martinMessage.type, chatTypes.contains(mType) else { #if DEBUG print("Unsupported message type: \(martinMessage.type?.rawValue ?? "nil")") #endif return nil } // Type let type = MessageType(rawValue: martinMessage.type?.rawValue ?? "") ?? .chat // Content type var contentType: MessageContentType = .text if martinMessage.hints.contains(.noStore) { contentType = .typing } // From/To let from = martinMessage.from?.bareJid.stringValue ?? "" let to = martinMessage.to?.bareJid.stringValue // Msg let msg = Message( id: martinMessage.id ?? UUID().uuidString, type: type, contentType: contentType, from: from, to: to, body: martinMessage.body, subject: martinMessage.subject, thread: martinMessage.thread, oobUrl: martinMessage.oob, date: Date(), pending: false, sentError: false ) return msg } }