diff --git a/CoreDataStack/CoreData.xcdatamodeld/CoreData.xcdatamodel/contents b/CoreDataStack/CoreData.xcdatamodeld/CoreData.xcdatamodel/contents index 5cd582bf1..ce454981b 100644 --- a/CoreDataStack/CoreData.xcdatamodeld/CoreData.xcdatamodel/contents +++ b/CoreDataStack/CoreData.xcdatamodeld/CoreData.xcdatamodel/contents @@ -1,5 +1,11 @@ - + + + + + + + @@ -95,6 +101,7 @@ + diff --git a/CoreDataStack/Entity/Application.swift b/CoreDataStack/Entity/Application.swift new file mode 100644 index 000000000..cfbf48f7e --- /dev/null +++ b/CoreDataStack/Entity/Application.swift @@ -0,0 +1,61 @@ +// +// Application.swift +// CoreDataStack +// +// Created by sxiaojian on 2021/2/3. +// + +import CoreData +import Foundation + +public final class Application: NSManagedObject { + public typealias ID = UUID + @NSManaged public private(set) var identifier: ID + @NSManaged public private(set) var createAt: Date + + @NSManaged public private(set) var name: String + @NSManaged public private(set) var website: String? + @NSManaged public private(set) var vapidKey: String? + + // one-to-many relationship + @NSManaged public private(set) var toots: Set +} + +public extension Application { + override func awakeFromInsert() { + super.awakeFromInsert() + identifier = UUID() + } + + @discardableResult + static func insert( + into context: NSManagedObjectContext, + property: Property + ) -> Application { + let app: Application = context.insertObject() + app.name = property.name + app.website = property.website + app.vapidKey = property.vapidKey + return app + } +} + +public extension Application { + struct Property { + public let name: String + public let website: String? + public let vapidKey: String? + + public init(name: String, website: String?, vapidKey: String?) { + self.name = name + self.website = website + self.vapidKey = vapidKey + } + } +} + +extension Application: Managed { + public static var defaultSortDescriptors: [NSSortDescriptor] { + return [NSSortDescriptor(keyPath: \Application.createAt, ascending: false)] + } +} diff --git a/CoreDataStack/Entity/Toot.swift b/CoreDataStack/Entity/Toot.swift index a0908d9de..65971ffe9 100644 --- a/CoreDataStack/Entity/Toot.swift +++ b/CoreDataStack/Entity/Toot.swift @@ -21,6 +21,7 @@ public final class Toot: NSManagedObject { @NSManaged public private(set) var visibility: String? @NSManaged public private(set) var sensitive: Bool @NSManaged public private(set) var spoilerText: String? + @NSManaged public private(set) var application: Application? // Informational @NSManaged public private(set) var reblogsCount: NSNumber @@ -88,6 +89,9 @@ public extension Toot { toot.sensitive = property.sensitive toot.spoilerText = property.spoilerText + if let application = property.application { + toot.mutableSetValue(forKey: #keyPath(Toot.application)).add(application) + } if let mentions = property.mentions { toot.mutableSetValue(forKey: #keyPath(Toot.mentions)).addObjects(from: mentions) } @@ -123,11 +127,9 @@ public extension Toot { if let bookmarkedBy = property.bookmarkedBy { toot.mutableSetValue(forKey: #keyPath(Toot.bookmarkedBy)).add(bookmarkedBy) } - - // TODO: not implement yet - // if let pinnedBy = property.pinnedBy { - // toot.mutableSetValue(forKey: #keyPath(Toot.pinnedBy)) - // } + if let pinnedBy = property.pinnedBy { + toot.mutableSetValue(forKey: #keyPath(Toot.pinnedBy)).add(pinnedBy) + } toot.updatedAt = property.updatedAt toot.deletedAt = property.deletedAt @@ -150,6 +152,7 @@ public extension Toot { visibility: String?, sensitive: Bool, spoilerText: String?, + application: Application?, mentions: [Mention]?, emojis: [Emoji]?, tags: [Tag]?, @@ -181,6 +184,7 @@ public extension Toot { self.visibility = visibility self.sensitive = sensitive self.spoilerText = spoilerText + self.application = application self.mentions = mentions self.emojis = emojis self.tags = tags @@ -215,6 +219,7 @@ public extension Toot { public let visibility: String? public let sensitive: Bool public let spoilerText: String? + public let application: Application? public let mentions: [Mention]? public let emojis: [Emoji]? diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index 046fbf1e4..eb61a8d76 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -36,6 +36,8 @@ 2D927F1425C7EDD9004F19B8 /* Emoji.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D927F1325C7EDD9004F19B8 /* Emoji.swift */; }; 2DA7D04425CA52B200804E11 /* TimelineLoaderTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DA7D04325CA52B200804E11 /* TimelineLoaderTableViewCell.swift */; }; 2DA7D04A25CA52CB00804E11 /* TimelineBottomLoaderTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DA7D04925CA52CB00804E11 /* TimelineBottomLoaderTableViewCell.swift */; }; + 2DA7D05125CA545E00804E11 /* LoadMoreConfigurableTableViewContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DA7D05025CA545E00804E11 /* LoadMoreConfigurableTableViewContainer.swift */; }; + 2DA7D05725CA693F00804E11 /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DA7D05625CA693F00804E11 /* Application.swift */; }; 2DF123A725C3B0210020F248 /* ActiveLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DF123A625C3B0210020F248 /* ActiveLabel.swift */; }; 3533495136D843E85211E3E2 /* Pods_Mastodon_MastodonUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1B4523A7981F1044DE89C21 /* Pods_Mastodon_MastodonUITests.framework */; }; 45B49097460EDE530AD5AA72 /* Pods_Mastodon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A4ABE34829701A4496C5BB64 /* Pods_Mastodon.framework */; }; @@ -177,6 +179,7 @@ 2DA7D04325CA52B200804E11 /* TimelineLoaderTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineLoaderTableViewCell.swift; sourceTree = ""; }; 2DA7D04925CA52CB00804E11 /* TimelineBottomLoaderTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineBottomLoaderTableViewCell.swift; sourceTree = ""; }; 2DA7D05025CA545E00804E11 /* LoadMoreConfigurableTableViewContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadMoreConfigurableTableViewContainer.swift; sourceTree = ""; }; + 2DA7D05625CA693F00804E11 /* Application.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Application.swift; sourceTree = ""; }; 2DF123A625C3B0210020F248 /* ActiveLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActiveLabel.swift; sourceTree = ""; }; 2E1F6A67FDF9771D3E064FDC /* Pods-Mastodon.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon.debug.xcconfig"; path = "Target Support Files/Pods-Mastodon/Pods-Mastodon.debug.xcconfig"; sourceTree = ""; }; 3C030226D3C73DCC23D67452 /* Pods_Mastodon_MastodonUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Mastodon_MastodonUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -621,6 +624,7 @@ 2D927F0D25C7E9C9004F19B8 /* History.swift */, 2D927F1325C7EDD9004F19B8 /* Emoji.swift */, DB45FAEC25CA7A9A005A8AC7 /* MastodonAuthentication.swift */, + 2DA7D05625CA693F00804E11 /* Application.swift */, ); path = Entity; sourceTree = ""; @@ -1126,6 +1130,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 2DA7D05725CA693F00804E11 /* Application.swift in Sources */, 2D927F1425C7EDD9004F19B8 /* Emoji.swift in Sources */, DB89BA1225C1105C008580ED /* CoreDataStack.swift in Sources */, DB89BA1C25C1107F008580ED /* NSManagedObjectContext.swift in Sources */, diff --git a/Mastodon/Service/APIService/Persist/APIService+Persist+Timeline.swift b/Mastodon/Service/APIService/Persist/APIService+Persist+Timeline.swift index d3e9ed5eb..4a8a1c3e6 100644 --- a/Mastodon/Service/APIService/Persist/APIService+Persist+Timeline.swift +++ b/Mastodon/Service/APIService/Persist/APIService+Persist+Timeline.swift @@ -27,6 +27,9 @@ extension APIService.Persist { let _ = toots.map { let userProperty = MastodonUser.Property(id: $0.account.id, domain: domain, acct: $0.account.acct, username: $0.account.username, displayName: $0.account.displayName,avatar: $0.account.avatar,avatarStatic: $0.account.avatarStatic, createdAt: $0.createdAt, networkDate: $0.createdAt) let author = MastodonUser.insert(into: managedObjectContext, property: userProperty) + let application = $0.application.flatMap { (app) -> Application? in + Application.insert(into: managedObjectContext, property: Application.Property(name: app.name, website: app.website, vapidKey: app.vapidKey)) + } let metions = $0.mentions?.compactMap({ (mention) -> Mention in Mention.insert(into: managedObjectContext, property: Mention.Property(id: mention.id, username: mention.username, acct: mention.acct, url: mention.url)) }) @@ -49,6 +52,7 @@ extension APIService.Persist { visibility: $0.visibility?.rawValue, sensitive: $0.sensitive ?? false, spoilerText: $0.spoilerText, + application: application, mentions: metions, emojis: emojis, tags: tags,