diff --git a/MastodonSDK/Sources/CoreDataStack/CoreData.xcdatamodeld/.xccurrentversion b/MastodonSDK/Sources/CoreDataStack/CoreData.xcdatamodeld/.xccurrentversion index 1d5ea989f..2145ac780 100644 --- a/MastodonSDK/Sources/CoreDataStack/CoreData.xcdatamodeld/.xccurrentversion +++ b/MastodonSDK/Sources/CoreDataStack/CoreData.xcdatamodeld/.xccurrentversion @@ -3,6 +3,6 @@ _XCCurrentVersionName - CoreData 4.xcdatamodel + CoreData 5.xcdatamodel diff --git a/MastodonSDK/Sources/CoreDataStack/CoreData.xcdatamodeld/CoreData 5.xcdatamodel/contents b/MastodonSDK/Sources/CoreDataStack/CoreData.xcdatamodeld/CoreData 5.xcdatamodel/contents new file mode 100644 index 000000000..5a0ef6a6a --- /dev/null +++ b/MastodonSDK/Sources/CoreDataStack/CoreData.xcdatamodeld/CoreData 5.xcdatamodel/contents @@ -0,0 +1,271 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MastodonSDK/Sources/CoreDataStack/Entity/Mastodon/Card.swift b/MastodonSDK/Sources/CoreDataStack/Entity/Mastodon/Card.swift new file mode 100644 index 000000000..12f6d636e --- /dev/null +++ b/MastodonSDK/Sources/CoreDataStack/Entity/Mastodon/Card.swift @@ -0,0 +1,162 @@ +// +// Card.swift +// CoreDataStack +// +// Created by Kyle Bashour on 11/23/22. +// + +import Foundation +import CoreData + +public final class Card: NSManagedObject { + // sourcery: autoGenerateProperty + @NSManaged public private(set) var url: String + // sourcery: autoGenerateProperty + @NSManaged public private(set) var title: String + // sourcery: autoGenerateProperty + @NSManaged public private(set) var desc: String + + @NSManaged public private(set) var typeRaw: String + // sourcery: autoGenerateProperty + public var type: MastodonCardType { + get { MastodonCardType(rawValue: typeRaw) } + set { typeRaw = newValue.rawValue } + } + + // sourcery: autoGenerateProperty + @NSManaged public private(set) var authorName: String? + // sourcery: autoGenerateProperty + @NSManaged public private(set) var authorURL: String? + // sourcery: autoGenerateProperty + @NSManaged public private(set) var providerName: String? + // sourcery: autoGenerateProperty + @NSManaged public private(set) var providerURL: String? + // sourcery: autoGenerateProperty + @NSManaged public private(set) var width: Int64 + // sourcery: autoGenerateProperty + @NSManaged public private(set) var height: Int64 + // sourcery: autoGenerateProperty + @NSManaged public private(set) var image: String? + // sourcery: autoGenerateProperty + @NSManaged public private(set) var embedURL: String? + // sourcery: autoGenerateProperty + @NSManaged public private(set) var blurhash: String? + + // one-to-one relationship + @NSManaged public private(set) var status: Status +} + +extension Card { + + @discardableResult + public static func insert( + into context: NSManagedObjectContext, + property: Property + ) -> Card { + let object: Card = context.insertObject() + + object.configure(property: property) + + return object + } + +} + +extension Card: Managed { + public static var defaultSortDescriptors: [NSSortDescriptor] { + return [] + } +} + +// MARK: - AutoGenerateProperty +extension Card: AutoGenerateProperty { + // sourcery:inline:Card.AutoGenerateProperty + + // Generated using Sourcery + // DO NOT EDIT + public struct Property { + public let url: String + public let title: String + public let desc: String + public let type: MastodonCardType + public let authorName: String? + public let authorURL: String? + public let providerName: String? + public let providerURL: String? + public let width: Int64 + public let height: Int64 + public let image: String? + public let embedURL: String? + public let blurhash: String? + + public init( + url: String, + title: String, + desc: String, + type: MastodonCardType, + authorName: String?, + authorURL: String?, + providerName: String?, + providerURL: String?, + width: Int64, + height: Int64, + image: String?, + embedURL: String?, + blurhash: String? + ) { + self.url = url + self.title = title + self.desc = desc + self.type = type + self.authorName = authorName + self.authorURL = authorURL + self.providerName = providerName + self.providerURL = providerURL + self.width = width + self.height = height + self.image = image + self.embedURL = embedURL + self.blurhash = blurhash + } + } + + public func configure(property: Property) { + self.url = property.url + self.title = property.title + self.desc = property.desc + self.type = property.type + self.authorName = property.authorName + self.authorURL = property.authorURL + self.providerName = property.providerName + self.providerURL = property.providerURL + self.width = property.width + self.height = property.height + self.image = property.image + self.embedURL = property.embedURL + self.blurhash = property.blurhash + } + + public func update(property: Property) { + } + + // sourcery:end +} + +// MARK: - AutoGenerateRelationship +extension Card: AutoGenerateRelationship { + // sourcery:inline:Card.AutoGenerateRelationship + + // Generated using Sourcery + // DO NOT EDIT + public struct Relationship { + + public init( + ) { + } + } + + public func configure(relationship: Relationship) { + } + + // sourcery:end +} diff --git a/MastodonSDK/Sources/CoreDataStack/Entity/Mastodon/Status.swift b/MastodonSDK/Sources/CoreDataStack/Entity/Mastodon/Status.swift index 0c7291913..1bc641f5f 100644 --- a/MastodonSDK/Sources/CoreDataStack/Entity/Mastodon/Status.swift +++ b/MastodonSDK/Sources/CoreDataStack/Entity/Mastodon/Status.swift @@ -84,7 +84,9 @@ public final class Status: NSManagedObject { @NSManaged public private(set) var pinnedBy: MastodonUser? // sourcery: autoGenerateRelationship @NSManaged public private(set) var poll: Poll? - + // sourcery: autoGenerateRelationship + @NSManaged public private(set) var card: Card? + // one-to-many relationship @NSManaged public private(set) var feeds: Set @@ -379,15 +381,18 @@ extension Status: AutoGenerateRelationship { public let author: MastodonUser public let reblog: Status? public let poll: Poll? + public let card: Card? public init( author: MastodonUser, reblog: Status?, - poll: Poll? + poll: Poll?, + card: Card? ) { self.author = author self.reblog = reblog self.poll = poll + self.card = card } } @@ -395,6 +400,7 @@ extension Status: AutoGenerateRelationship { self.author = relationship.author self.reblog = relationship.reblog self.poll = relationship.poll + self.card = relationship.card } // sourcery:end } diff --git a/MastodonSDK/Sources/CoreDataStack/Entity/Transient/MastodonCardType.swift b/MastodonSDK/Sources/CoreDataStack/Entity/Transient/MastodonCardType.swift new file mode 100644 index 000000000..59401cf4a --- /dev/null +++ b/MastodonSDK/Sources/CoreDataStack/Entity/Transient/MastodonCardType.swift @@ -0,0 +1,34 @@ +// +// MastodonCardType.swift +// CoreDataStack +// +// Created by Kyle Bashour on 11/23/22. +// + +import Foundation + +public enum MastodonCardType: RawRepresentable, Equatable { + case link + case photo + case video + + case _other(String) + + public init(rawValue: String) { + switch rawValue { + case "link": self = .link + case "photo": self = .photo + case "video": self = .video + default: self = ._other(rawValue) + } + } + + public var rawValue: String { + switch self { + case .link: return "link" + case .photo: return "photo" + case .video: return "video" + case ._other(let value): return value + } + } +} diff --git a/MastodonSDK/Sources/MastodonCore/Persistence/Persistence+Card.swift b/MastodonSDK/Sources/MastodonCore/Persistence/Persistence+Card.swift new file mode 100644 index 000000000..8c3b4c312 --- /dev/null +++ b/MastodonSDK/Sources/MastodonCore/Persistence/Persistence+Card.swift @@ -0,0 +1,94 @@ +// +// Persistence+Card.swift +// +// +// Created by MainasuK on 2021-12-9. +// + +import CoreData +import CoreDataStack +import Foundation +import MastodonSDK +import os.log + +extension Persistence.Card { + + public struct PersistContext { + public let domain: String + public let entity: Mastodon.Entity.Card + public let me: MastodonUser? + public let log = Logger(subsystem: "Card", category: "Persistence") + public init( + domain: String, + entity: Mastodon.Entity.Card, + me: MastodonUser? + ) { + self.domain = domain + self.entity = entity + self.me = me + } + } + + public struct PersistResult { + public let card: Card + public let isNewInsertion: Bool + + public init( + card: Card, + isNewInsertion: Bool + ) { + self.card = card + self.isNewInsertion = isNewInsertion + } + + #if DEBUG + public let logger = Logger(subsystem: "Persistence.MastodonCard.PersistResult", category: "Persist") + public func log() { + let pollInsertionFlag = isNewInsertion ? "+" : "-" + logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public): [\(pollInsertionFlag)](\(card.title)):") + } + #endif + } + + public static func create( + in managedObjectContext: NSManagedObjectContext, + context: PersistContext + ) -> PersistResult { + var type: MastodonCardType { + switch context.entity.type { + case .link: return .link + case .photo: return .photo + case .video: return .video + case .rich: return ._other(context.entity.type.rawValue) + case ._other(let rawValue): return ._other(rawValue) + } + } + + let property = Card.Property( + url: context.entity.url, + title: context.entity.title, + desc: context.entity.description, + type: type, + authorName: context.entity.authorName, + authorURL: context.entity.authorURL, + providerName: context.entity.providerName, + providerURL: context.entity.providerURL, + width: Int64(context.entity.width ?? 0), + height: Int64(context.entity.height ?? 0), + image: context.entity.image, + embedURL: context.entity.embedURL, + blurhash: context.entity.blurhash + ) + + let card = Card.insert( + into: managedObjectContext, + property: property + ) + + return PersistResult( + card: card, + isNewInsertion: true + ) + } + +} diff --git a/MastodonSDK/Sources/MastodonCore/Persistence/Persistence+Status.swift b/MastodonSDK/Sources/MastodonCore/Persistence/Persistence+Status.swift index a15e974e4..97ab32e30 100644 --- a/MastodonSDK/Sources/MastodonCore/Persistence/Persistence+Status.swift +++ b/MastodonSDK/Sources/MastodonCore/Persistence/Persistence+Status.swift @@ -107,7 +107,20 @@ extension Persistence.Status { ) return result.poll }() - + + let card: Card? = { + guard let entity = context.entity.card else { return nil } + let result = Persistence.Card.create( + in: managedObjectContext, + context: Persistence.Card.PersistContext( + domain: context.domain, + entity: entity, + me: context.me + ) + ) + return result.card + }() + let authorResult = Persistence.MastodonUser.createOrMerge( in: managedObjectContext, context: Persistence.MastodonUser.PersistContext( @@ -122,7 +135,8 @@ extension Persistence.Status { let relationship = Status.Relationship( author: author, reblog: reblog, - poll: poll + poll: poll, + card: card ) let status = create( in: managedObjectContext, diff --git a/MastodonSDK/Sources/MastodonCore/Persistence/Persistence.swift b/MastodonSDK/Sources/MastodonCore/Persistence/Persistence.swift index 350b603cc..3a36dec41 100644 --- a/MastodonSDK/Sources/MastodonCore/Persistence/Persistence.swift +++ b/MastodonSDK/Sources/MastodonCore/Persistence/Persistence.swift @@ -15,6 +15,7 @@ extension Persistence { public enum MastodonUser { } public enum Status { } public enum Poll { } + public enum Card { } public enum PollOption { } public enum Tag { } public enum SearchHistory { }