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 { }