diff --git a/Pachyderm/Model/Attachment.swift b/Pachyderm/Model/Attachment.swift
index 32bcee8543..7a9fbbb28e 100644
--- a/Pachyderm/Model/Attachment.swift
+++ b/Pachyderm/Model/Attachment.swift
@@ -8,7 +8,7 @@
import Foundation
-public class Attachment: Decodable {
+public class Attachment: Codable {
public let id: String
public let kind: Kind
public let url: URL
@@ -58,7 +58,7 @@ public class Attachment: Decodable {
}
extension Attachment {
- public enum Kind: String, Decodable {
+ public enum Kind: String, Codable {
case image
case video
case gifv
@@ -68,7 +68,7 @@ extension Attachment {
}
extension Attachment {
- public class Metadata: Decodable {
+ public class Metadata: Codable {
public let length: String?
public let duration: Float?
public let audioEncoding: String?
@@ -99,7 +99,7 @@ extension Attachment {
}
}
- public class ImageMetadata: Decodable {
+ public class ImageMetadata: Codable {
public let width: Int?
public let height: Int?
public let size: String?
diff --git a/Pachyderm/Model/Emoji.swift b/Pachyderm/Model/Emoji.swift
index bec0ea9dfc..a0a6d50fce 100644
--- a/Pachyderm/Model/Emoji.swift
+++ b/Pachyderm/Model/Emoji.swift
@@ -8,7 +8,7 @@
import Foundation
-public class Emoji: Decodable {
+public class Emoji: Codable {
public let shortcode: String
public let url: URL
public let staticURL: URL
diff --git a/Pachyderm/Model/Mention.swift b/Pachyderm/Model/Mention.swift
index ea086f34d4..2e60f4c622 100644
--- a/Pachyderm/Model/Mention.swift
+++ b/Pachyderm/Model/Mention.swift
@@ -8,7 +8,7 @@
import Foundation
-public class Mention: Decodable {
+public class Mention: Codable {
public let url: URL
public let username: String
public let acct: String
diff --git a/Tusker.xcodeproj/project.pbxproj b/Tusker.xcodeproj/project.pbxproj
index b23acb7803..4f42aa7c9a 100644
--- a/Tusker.xcodeproj/project.pbxproj
+++ b/Tusker.xcodeproj/project.pbxproj
@@ -25,6 +25,7 @@
D60D2B8223844C71001B87A3 /* BaseStatusTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D60D2B8123844C71001B87A3 /* BaseStatusTableViewCell.swift */; };
D60E2F272442372B005F8713 /* StatusMO.swift in Sources */ = {isa = PBXBuildFile; fileRef = D60E2F232442372B005F8713 /* StatusMO.swift */; };
D60E2F292442372B005F8713 /* AccountMO.swift in Sources */ = {isa = PBXBuildFile; fileRef = D60E2F252442372B005F8713 /* AccountMO.swift */; };
+ D60E2F2C24423EAD005F8713 /* LazilyDecoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = D60E2F2B24423EAD005F8713 /* LazilyDecoding.swift */; };
D60E2F2E244248BF005F8713 /* MastodonCachePersistentStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = D60E2F2D244248BF005F8713 /* MastodonCachePersistentStore.swift */; };
D61099B42144B0CC00432DC2 /* Pachyderm.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D61099AB2144B0CC00432DC2 /* Pachyderm.framework */; };
D61099BB2144B0CC00432DC2 /* PachydermTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61099BA2144B0CC00432DC2 /* PachydermTests.swift */; };
@@ -1236,6 +1237,7 @@
D6028B9A2150811100F223B9 /* MastodonCache.swift */,
D6C693EE216192C2007D6A6D /* TuskerNavigationDelegate.swift */,
D6DFC69F242C4CCC00ACC392 /* WeakArray.swift */,
+ D60E2F2B24423EAD005F8713 /* LazilyDecoding.swift */,
D6F1F84E2193B9BE00F5FE67 /* Caching */,
D6757A7A2157E00100721E32 /* XCallbackURL */,
D62D241E217AA46B005076CC /* Shortcuts */,
@@ -1664,6 +1666,7 @@
D62D2422217AA7E1005076CC /* UserActivityManager.swift in Sources */,
D60D2B8223844C71001B87A3 /* BaseStatusTableViewCell.swift in Sources */,
D60E2F272442372B005F8713 /* StatusMO.swift in Sources */,
+ D60E2F2C24423EAD005F8713 /* LazilyDecoding.swift in Sources */,
D62D2424217ABF3F005076CC /* NSUserActivity+Extensions.swift in Sources */,
D646C958213B367000269FB5 /* LargeImageShrinkAnimationController.swift in Sources */,
D6A3BC852321F6C100FD64D5 /* AccountListTableViewController.swift in Sources */,
diff --git a/Tusker/CoreData/AccountMO.swift b/Tusker/CoreData/AccountMO.swift
index b46da8f931..74409cf8da 100644
--- a/Tusker/CoreData/AccountMO.swift
+++ b/Tusker/CoreData/AccountMO.swift
@@ -9,6 +9,7 @@
import Foundation
import CoreData
+import Pachyderm
@objc(AccountMO)
public class AccountMO: NSManagedObject {
@@ -22,8 +23,8 @@ public class AccountMO: NSManagedObject {
@NSManaged public var bot: Bool
@NSManaged public var createdAt: Date?
@NSManaged public var displayName: String?
- @NSManaged public var emojis: Data?
- @NSManaged public var fields: Data?
+ @NSManaged public var emojisData: Data?
+ @NSManaged public var fieldsData: Data?
@NSManaged public var followersCount: Int64
@NSManaged public var followingCount: Int64
@NSManaged public var header: URL?
@@ -36,4 +37,10 @@ public class AccountMO: NSManagedObject {
@NSManaged public var username: String?
@NSManaged public var movedTo: AccountMO?
+ @LazilyDecoding(arrayFrom: \AccountMO.emojisData)
+ var emojis: [Emoji]
+
+ @LazilyDecoding(arrayFrom: \AccountMO.fieldsData)
+ var fields: [Account.Field]
+
}
diff --git a/Tusker/CoreData/StatusMO.swift b/Tusker/CoreData/StatusMO.swift
index aacde0d51c..34251ab568 100644
--- a/Tusker/CoreData/StatusMO.swift
+++ b/Tusker/CoreData/StatusMO.swift
@@ -9,6 +9,7 @@
import Foundation
import CoreData
+import Pachyderm
@objc(StatusMO)
public final class StatusMO: NSManagedObject {
@@ -41,4 +42,16 @@ public final class StatusMO: NSManagedObject {
@NSManaged public var inReplyToAccount: AccountMO?
@NSManaged public var reblog: StatusMO?
+ @LazilyDecoding(arrayFrom: \StatusMO.attachmentsData)
+ var attachments: [Attachment]
+
+ @LazilyDecoding(arrayFrom: \StatusMO.emojisData)
+ var emoji: [Emoji]
+
+ @LazilyDecoding(arrayFrom: \StatusMO.hashtagsData)
+ var hashtags: [Hashtag]
+
+ @LazilyDecoding(arrayFrom: \StatusMO.mentionsData)
+ var mentions: [Mention]
+
}
diff --git a/Tusker/CoreData/Tusker.xcdatamodeld/Tusker.xcdatamodel/contents b/Tusker/CoreData/Tusker.xcdatamodeld/Tusker.xcdatamodel/contents
index 9bd9aa123f..a4de90e0f3 100644
--- a/Tusker/CoreData/Tusker.xcdatamodeld/Tusker.xcdatamodel/contents
+++ b/Tusker/CoreData/Tusker.xcdatamodeld/Tusker.xcdatamodel/contents
@@ -6,8 +6,8 @@
-
-
+
+
diff --git a/Tusker/LazilyDecoding.swift b/Tusker/LazilyDecoding.swift
new file mode 100644
index 0000000000..2930df5823
--- /dev/null
+++ b/Tusker/LazilyDecoding.swift
@@ -0,0 +1,63 @@
+//
+// LazyDecoding.swift
+// Tusker
+//
+// Created by Shadowfacts on 4/11/20.
+// Copyright © 2020 Shadowfacts. All rights reserved.
+//
+
+import Foundation
+
+private let decoder = PropertyListDecoder()
+private let encoder = PropertyListEncoder()
+
+@propertyWrapper
+struct LazilyDecoding {
+
+ private let keyPath: ReferenceWritableKeyPath
+ private let fallback: Value
+ private var value: Value?
+
+ init(from keyPath: ReferenceWritableKeyPath, fallback: Value) {
+ self.keyPath = keyPath
+ self.fallback = fallback
+ }
+
+ var wrappedValue: Value {
+ get { fatalError("called LazilyDecoding wrappedValue getter") }
+ set { fatalError("called LazilyDecoding wrappedValue setter") }
+ }
+
+ static subscript(_enclosingInstance instance: Enclosing, wrapped wrappedKeyPath: ReferenceWritableKeyPath, storage storageKeyPath: ReferenceWritableKeyPath) -> Value {
+ get {
+ var wrapper = instance[keyPath: storageKeyPath]
+ if let value = wrapper.value {
+ return value
+ } else {
+ guard let data = instance[keyPath: wrapper.keyPath] else { return wrapper.fallback }
+ do {
+ let value = try decoder.decode(Value.self, from: data)
+ wrapper.value = value
+ instance[keyPath: storageKeyPath] = wrapper
+ return value
+ } catch {
+ return wrapper.fallback
+ }
+ }
+ }
+ set {
+ var wrapper = instance[keyPath: storageKeyPath]
+ wrapper.value = newValue
+ instance[keyPath: storageKeyPath] = wrapper
+ let newData = try? encoder.encode(newValue)
+ instance[keyPath: wrapper.keyPath] = newData
+ }
+ }
+
+}
+
+extension LazilyDecoding {
+ init(arrayFrom keyPath: ReferenceWritableKeyPath) {
+ self.init(from: keyPath, fallback: [] as! Value)
+ }
+}