import Foundation struct SettingsFavoritePost: Codable, Identifiable, Hashable { let id: UUID let postId: String let tags: [String] let createdAt: Date let provider: BooruProvider var folder: UUID? var lastVisit: Date var visitedCount: Int let thumbnailUrl: String? let previewUrl: String? let fileUrl: String? let fileType: BooruPostFileType let rating: BooruRating let width: Int let height: Int let fileSize: Int? init( post: BooruPost, provider: BooruProvider, folder: UUID? = nil, id: UUID = UUID() ) { self.createdAt = Date() self.lastVisit = Date() self.id = id self.postId = post.id self.tags = post.tags self.provider = provider self.folder = folder self.visitedCount = 0 self.thumbnailUrl = post.previewURL.absoluteString self.previewUrl = post.previewURL.absoluteString self.fileUrl = post.fileURL.absoluteString self.fileType = .preview self.rating = post.rating self.width = post.width self.height = post.height self.fileSize = nil } enum CodingKeys: String, CodingKey { // swiftlint:disable:next explicit_enum_raw_value case id, postId, tags, createdAt, provider, folder, lastVisit, visitedCount, thumbnailUrl, // swiftlint:disable:next explicit_enum_raw_value previewUrl, fileUrl, fileType, rating, width, height, fileSize } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) self.id = try container.decodeIfPresent(UUID.self, forKey: .id) ?? UUID() self.postId = try container.decode(String.self, forKey: .postId) self.tags = try container.decodeIfPresent([String].self, forKey: .tags) ?? [] self.createdAt = try container.decodeIfPresent(Date.self, forKey: .createdAt) ?? Date() self.provider = try container.decodeIfPresent(BooruProvider.self, forKey: .provider) ?? .safebooru self.folder = try container.decodeIfPresent(UUID.self, forKey: .folder) self.lastVisit = try container.decodeIfPresent(Date.self, forKey: .lastVisit) ?? Date() self.visitedCount = try container.decodeIfPresent(Int.self, forKey: .visitedCount) ?? 0 self.thumbnailUrl = try container.decodeIfPresent(String.self, forKey: .thumbnailUrl) self.previewUrl = try container.decodeIfPresent(String.self, forKey: .previewUrl) self.fileUrl = try container.decodeIfPresent(String.self, forKey: .fileUrl) self.fileType = try container.decodeIfPresent(BooruPostFileType.self, forKey: .fileType) ?? .preview self.rating = try container.decodeIfPresent(BooruRating.self, forKey: .rating) ?? .questionable self.width = try container.decodeIfPresent(Int.self, forKey: .width) ?? 0 self.height = try container.decodeIfPresent(Int.self, forKey: .height) ?? 0 self.fileSize = try container.decodeIfPresent(Int.self, forKey: .fileSize) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(id, forKey: .id) try container.encode(postId, forKey: .postId) try container.encode(tags, forKey: .tags) try container.encode(createdAt, forKey: .createdAt) try container.encode(provider, forKey: .provider) try container.encodeIfPresent(folder, forKey: .folder) try container.encode(lastVisit, forKey: .lastVisit) try container.encode(visitedCount, forKey: .visitedCount) try container.encodeIfPresent(thumbnailUrl, forKey: .thumbnailUrl) try container.encodeIfPresent(previewUrl, forKey: .previewUrl) try container.encodeIfPresent(fileUrl, forKey: .fileUrl) try container.encode(fileType.rawValue, forKey: .fileType) try container.encode(rating, forKey: .rating) try container.encode(width, forKey: .width) try container.encode(height, forKey: .height) try container.encodeIfPresent(fileSize, forKey: .fileSize) } }