import Foundation import SwiftData @Model final class HistoryItem { let startDate: Date let message: HistoryMessage let route: TransmissionType let finishDate: Date init(message: Message, startDate: Date, route: TransmissionType, finishDate: Date) { self.startDate = startDate self.message = .init( messageType: message.messageType, clientChallenge: Int(message.clientChallenge), serverChallenge: Int(message.serverChallenge), result: message.result) self.finishDate = finishDate self.route = route } var roundTripTime: TimeInterval { finishDate.timeIntervalSince(startDate) } var response: MessageResult { message.result } } struct HistoryMessage { /// The type of message being sent. let messageType: MessageType /** * The random nonce created by the remote * * This nonce is a random number created by the remote, different for each unlock request. * It is set for all message types. */ let clientChallenge: Int /** * A random number to sign by the remote * * This nonce is set by the server after receiving an initial message. * It is set for the message types `challenge`, `request`, and `response`. */ let serverChallenge: Int /** * The response status for the previous message. * * It is set only for messages from the server, e.g. the `challenge` and `response` message types. * Must be set to `MessageAccepted` for other messages. */ let result: MessageResult } extension HistoryMessage: Encodable { func encode(to encoder: Encoder) throws { var container = encoder.unkeyedContainer() try container.encode(messageType) try container.encode(clientChallenge) try container.encode(serverChallenge) try container.encode(result) } } extension HistoryMessage: Decodable { init(from decoder: Decoder) throws { var container = try decoder.unkeyedContainer() self.messageType = try container.decode(MessageType.self) self.clientChallenge = try container.decode(Int.self) self.serverChallenge = try container.decode(Int.self) self.result = try container.decode(MessageResult.self) } } extension HistoryItem: Identifiable { var id: Double { startDate.timeIntervalSince1970 } } extension HistoryItem: Comparable { static func < (lhs: HistoryItem, rhs: HistoryItem) -> Bool { lhs.startDate < rhs.startDate } } extension HistoryItem { static var mock: HistoryItem { let message = Message(messageType: .request, clientChallenge: 123, serverChallenge: 234, result: .unlocked) return .init( message: message, startDate: Date.now.addingTimeInterval(-5), route: .throughServer, finishDate: Date.now) } }