diff --git a/CoreDataStack/CoreData.xcdatamodeld/CoreData.xcdatamodel/contents b/CoreDataStack/CoreData.xcdatamodeld/CoreData.xcdatamodel/contents index a6208aaeb..d76831ea8 100644 --- a/CoreDataStack/CoreData.xcdatamodeld/CoreData.xcdatamodel/contents +++ b/CoreDataStack/CoreData.xcdatamodeld/CoreData.xcdatamodel/contents @@ -1,11 +1,25 @@ - + + + + + + + + + + + + + + + - + @@ -20,20 +34,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + - + + + \ No newline at end of file diff --git a/CoreDataStack/Entity/Emoji.swift b/CoreDataStack/Entity/Emoji.swift new file mode 100644 index 000000000..3936fa21e --- /dev/null +++ b/CoreDataStack/Entity/Emoji.swift @@ -0,0 +1,59 @@ +// +// Emoji.swift +// CoreDataStack +// +// Created by sxiaojian on 2021/2/1. +// + +import CoreData +import Foundation + +public final class Emoji: NSManagedObject { + public typealias ID = String + @NSManaged public private(set) var identifier: ID + @NSManaged public private(set) var shortcode: String + @NSManaged public private(set) var url: String + @NSManaged public private(set) var staticURL: String + @NSManaged public private(set) var visibleInPicker: Bool + @NSManaged public private(set) var toot: Toot? +} + +public extension Emoji { + @discardableResult + static func insert( + into context: NSManagedObjectContext, + property: Property + ) -> Emoji { + let emoji: Emoji = context.insertObject() + + emoji.identifier = UUID().uuidString + emoji.shortcode = property.shortcode + emoji.url = property.url + emoji.staticURL = property.staticURL + emoji.visibleInPicker = property.visibleInPicker + return emoji + } +} + +public extension Emoji { + struct Property { + + public let shortcode: String + public let url: String + public let staticURL: String + public let visibleInPicker: Bool + + public init(shortcode: String, url: String, staticURL: String, visibleInPicker: Bool) { + self.shortcode = shortcode + self.url = url + self.staticURL = staticURL + self.visibleInPicker = visibleInPicker + } + } +} + +extension Emoji: Managed { + public static var defaultSortDescriptors: [NSSortDescriptor] { + return [NSSortDescriptor(keyPath: \Emoji.identifier, ascending: false)] + } +} diff --git a/CoreDataStack/Entity/History.swift b/CoreDataStack/Entity/History.swift new file mode 100644 index 000000000..e17ba4bb5 --- /dev/null +++ b/CoreDataStack/Entity/History.swift @@ -0,0 +1,56 @@ +// +// History.swift +// CoreDataStack +// +// Created by sxiaojian on 2021/2/1. +// + +import Foundation +import CoreData + +final public class History: NSManagedObject { + + public typealias ID = String + @NSManaged public private(set) var identifier: ID + @NSManaged public private(set) var day: Date + @NSManaged public private(set) var uses: Int + @NSManaged public private(set) var accounts: Int + @NSManaged public private(set) var tag: Tag? +} + +extension History { + @discardableResult + public static func insert( + into context: NSManagedObjectContext, + property:Property + ) -> History { + let history :History = context.insertObject() + + history.identifier = UUID().uuidString + history.day = property.day + history.uses = property.uses + history.accounts = property.accounts + return history + } +} + +extension History { + public struct Property { + + public let day: Date + public let uses: Int + public let accounts: Int + + public init(day: Date, uses: Int, accounts: Int) { + self.day = day + self.uses = uses + self.accounts = accounts + } + + } +} +extension History: Managed { + public static var defaultSortDescriptors: [NSSortDescriptor] { + return [NSSortDescriptor(keyPath: \History.identifier, ascending: false)] + } +} diff --git a/CoreDataStack/Entity/Mention.swift b/CoreDataStack/Entity/Mention.swift new file mode 100644 index 000000000..5e1164274 --- /dev/null +++ b/CoreDataStack/Entity/Mention.swift @@ -0,0 +1,59 @@ +// +// Mention.swift +// CoreDataStack +// +// Created by sxiaojian on 2021/2/1. +// + +import Foundation +import CoreData + +final public class Mention: NSManagedObject { + + public typealias ID = String + @NSManaged public private(set) var identifier: ID + @NSManaged public private(set) var id: String + @NSManaged public private(set) var username: String + @NSManaged public private(set) var acct: String + @NSManaged public private(set) var url: String + @NSManaged public private(set) var toot: Toot? +} + +extension Mention { + @discardableResult + public static func insert( + into context: NSManagedObjectContext, + property:Property + ) -> Mention { + let mention :Mention = context.insertObject() + + mention.identifier = UUID().uuidString + mention.id = property.id + mention.username = property.username + mention.acct = property.acct + mention.url = property.url + return mention + } +} + +extension Mention { + public struct Property { + public let id: String + public let username: String + public let acct: String + public let url: String + + public init(id: String, username: String, acct: String, url: String) { + self.id = id + self.username = username + self.acct = acct + self.url = url + } + } +} + +extension Mention: Managed { + public static var defaultSortDescriptors: [NSSortDescriptor] { + return [NSSortDescriptor(keyPath: \Mention.id, ascending: false)] + } +} diff --git a/CoreDataStack/Entity/Tag.swift b/CoreDataStack/Entity/Tag.swift new file mode 100644 index 000000000..ef2fe1db7 --- /dev/null +++ b/CoreDataStack/Entity/Tag.swift @@ -0,0 +1,54 @@ +// +// Tag.swift +// CoreDataStack +// +// Created by sxiaojian on 2021/2/1. +// + +import CoreData +import Foundation + +public final class Tag: NSManagedObject { + public typealias ID = String + @NSManaged public private(set) var identifier: ID + @NSManaged public private(set) var name: String + @NSManaged public private(set) var url: String + //on to many + @NSManaged public private(set) var history: [History]? +} + +public extension Tag { + @discardableResult + static func insert( + into context: NSManagedObjectContext, + property: Property + ) -> Tag { + let Tag: Tag = context.insertObject() + + Tag.identifier = UUID().uuidString + Tag.name = property.name + Tag.url = property.url + Tag.history = property.history + return Tag + } +} + +public extension Tag { + struct Property { + public let name: String + public let url: String + public let history: [History]? + + public init(name: String, url: String, history: [History]?) { + self.name = name + self.url = url + self.history = history + } + } +} + +extension Tag: Managed { + public static var defaultSortDescriptors: [NSSortDescriptor] { + return [NSSortDescriptor(keyPath: \Tag.identifier, ascending: false)] + } +} diff --git a/CoreDataStack/Entity/Toot.swift b/CoreDataStack/Entity/Toot.swift index 546ec8ce3..0e7120692 100644 --- a/CoreDataStack/Entity/Toot.swift +++ b/CoreDataStack/Entity/Toot.swift @@ -5,19 +5,47 @@ // Created by MainasuK Cirno on 2021/1/27. // -import Foundation import CoreData +import Foundation -final public class Toot: NSManagedObject { - +public final class Toot: NSManagedObject { public typealias ID = String @NSManaged public private(set) var identifier: ID @NSManaged public private(set) var domain: String @NSManaged public private(set) var id: String + @NSManaged public private(set) var uri: String + @NSManaged public private(set) var createdAt: Date @NSManaged public private(set) var content: String - @NSManaged public private(set) var createdAt: Date + @NSManaged public private(set) var visibility: String? + @NSManaged public private(set) var sensitive: Bool + @NSManaged public private(set) var spoilerText: String? + + // rendering + //one to many + @NSManaged public private(set) var mentions: Set? + //one to many + @NSManaged public private(set) var emojis: Set? + //one to many + @NSManaged public private(set) var tags: [Tag]? + // Informational + @NSManaged public private(set) var reblogsCount: Int + @NSManaged public private(set) var favouritesCount: Int + @NSManaged public private(set) var repliesCount: Int + + @NSManaged public private(set) var url: String? + @NSManaged public private(set) var inReplyToID: Toot.ID? + @NSManaged public private(set) var inReplyToAccountID: MastodonUser.ID? + @NSManaged public private(set) var reblog: Toot? + @NSManaged public private(set) var language: String? // (ISO 639 Part @NSManaged public private(set) varletter language code) + @NSManaged public private(set) var text: String? + + @NSManaged public private(set) var favourited: Bool + @NSManaged public private(set) var reblogged: Bool + @NSManaged public private(set) var muted: Bool + @NSManaged public private(set) var bookmarked: Bool + @NSManaged public private(set) var pinned: Bool @NSManaged public private(set) var updatedAt: Date @NSManaged public private(set) var deletedAt: Date? @@ -26,58 +54,163 @@ final public class Toot: NSManagedObject { // one-to-many relationship @NSManaged public private(set) var homeTimelineIndexes: Set? - } -extension Toot { - +public extension Toot { @discardableResult - public static func insert( + static func insert( into context: NSManagedObjectContext, property: Property, author: MastodonUser ) -> Toot { - let toots: Toot = context.insertObject() + let toot: Toot = context.insertObject() - toots.identifier = property.identifier - toots.domain = property.domain + toot.identifier = property.identifier + toot.domain = property.domain + + toot.id = property.id + toot.uri = property.uri + toot.createdAt = property.createdAt + toot.content = property.content - toots.id = property.id - toots.content = property.content - toots.createdAt = property.createdAt - toots.updatedAt = property.networkDate + toot.visibility = property.visibility + toot.sensitive = property.sensitive + toot.spoilerText = property.spoilerText - toots.author = author + if let mentions = property.mentions { + toot.mutableSetValue(forKey: #keyPath(Toot.mentions)).addObjects(from: mentions) + } + + if let emojis = property.emojis { + toot.mutableSetValue(forKey: #keyPath(Toot.mentions)).addObjects(from: emojis) + } - return toots + + toot.reblogsCount = property.reblogsCount + toot.favouritesCount = property.favouritesCount + toot.repliesCount = property.repliesCount + + toot.url = property.url + toot.inReplyToID = property.inReplyToID + toot.inReplyToAccountID = property.inReplyToAccountID + toot.reblog = property.reblog + toot.language = property.language + toot.text = property.text + + toot.favourited = property.favourited + toot.reblogged = property.reblogged + toot.muted = property.muted + toot.bookmarked = property.bookmarked + toot.pinned = property.pinned + toot.updatedAt = property.updatedAt + toot.deletedAt = property.deletedAt + toot.author = property.author + toot.content = property.content + toot.homeTimelineIndexes = property.homeTimelineIndexes + + return toot } - } -extension Toot { - public struct Property { - public let identifier: String - public let domain: String - - public let id: String - public let content: String - public let createdAt: Date - public let networkDate: Date - +public extension Toot { + struct Property { public init( - id: String, domain: String, - content: String, + id: String, + uri: String, createdAt: Date, - networkDate: Date - ) { + content: String, + visibility: String?, + sensitive: Bool, + spoilerText: String?, + mentions: [Mention]?, + emojis: [Emoji]?, + reblogsCount: Int, + favouritesCount: Int, + repliesCount: Int, + url: String?, + inReplyToID: Toot.ID?, + inReplyToAccountID: MastodonUser.ID?, + reblog: Toot?, + language: String?, + text: String?, + favourited: Bool, + reblogged: Bool, + muted: Bool, + bookmarked: Bool, + pinned: Bool, + updatedAt: Date, + deletedAt: Date?, + author: MastodonUser, + homeTimelineIndexes: Set?) + { self.identifier = id + "@" + domain self.domain = domain self.id = id - self.content = content + self.uri = uri self.createdAt = createdAt - self.networkDate = networkDate + self.content = content + self.visibility = visibility + self.sensitive = sensitive + self.spoilerText = spoilerText + self.mentions = mentions + self.emojis = emojis + self.reblogsCount = reblogsCount + self.favouritesCount = favouritesCount + self.repliesCount = repliesCount + self.url = url + self.inReplyToID = inReplyToID + self.inReplyToAccountID = inReplyToAccountID + self.reblog = reblog + self.language = language + self.text = text + self.favourited = favourited + self.reblogged = reblogged + self.muted = muted + self.bookmarked = bookmarked + self.pinned = pinned + self.updatedAt = updatedAt + self.deletedAt = deletedAt + self.author = author + self.homeTimelineIndexes = homeTimelineIndexes } + + public let identifier: ID + public let domain: String + + public let id: String + public let uri: String + public let createdAt: Date + public let content: String + + public let visibility: String? + public let sensitive: Bool + public let spoilerText: String? + + public let mentions: [Mention]? + public let emojis: [Emoji]? + public let reblogsCount: Int + public let favouritesCount: Int + public let repliesCount: Int + + public let url: String? + public let inReplyToID: Toot.ID? + public let inReplyToAccountID: MastodonUser.ID? + public let reblog: Toot? + public let language: String? // (ISO 639 Part @NSManaged public private(set) varletter language public let + public let text: String? + + public let favourited: Bool + public let reblogged: Bool + public let muted: Bool + public let bookmarked: Bool + public let pinned: Bool + public let updatedAt: Date + public let deletedAt: Date? + + public let author: MastodonUser + + public let homeTimelineIndexes: Set? } } @@ -87,22 +220,20 @@ extension Toot: Managed { } } -extension Toot { - - public static func predicate(idStr: String) -> NSPredicate { +public extension Toot { + static func predicate(idStr: String) -> NSPredicate { return NSPredicate(format: "%K == %@", #keyPath(Toot.id), idStr) } - public static func predicate(idStrs: [String]) -> NSPredicate { + static func predicate(idStrs: [String]) -> NSPredicate { return NSPredicate(format: "%K IN %@", #keyPath(Toot.id), idStrs) } - public static func notDeleted() -> NSPredicate { + static func notDeleted() -> NSPredicate { return NSPredicate(format: "%K == nil", #keyPath(Toot.deletedAt)) } - public static func deleted() -> NSPredicate { + static func deleted() -> NSPredicate { return NSPredicate(format: "%K != nil", #keyPath(Toot.deletedAt)) } - } diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index bfbf71607..8940bc4e3 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -22,6 +22,10 @@ 2D76319F25C1521200929FB9 /* TimelineSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D76319E25C1521200929FB9 /* TimelineSection.swift */; }; 2D7631A825C1535600929FB9 /* TimelinePostTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D7631A725C1535600929FB9 /* TimelinePostTableViewCell.swift */; }; 2D7631B325C159F700929FB9 /* Item.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D7631B225C159F700929FB9 /* Item.swift */; }; + 2D927F0225C7E4F2004F19B8 /* Mention.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D927F0125C7E4F2004F19B8 /* Mention.swift */; }; + 2D927F0825C7E9A8004F19B8 /* Tag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D927F0725C7E9A8004F19B8 /* Tag.swift */; }; + 2D927F0E25C7E9C9004F19B8 /* History.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D927F0D25C7E9C9004F19B8 /* History.swift */; }; + 2D927F1425C7EDD9004F19B8 /* Emoji.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D927F1325C7EDD9004F19B8 /* Emoji.swift */; }; 2D9BB87B25C3FEF200678AB6 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D9BB87A25C3FEF200678AB6 /* String.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 */; }; @@ -131,6 +135,10 @@ 2D76319E25C1521200929FB9 /* TimelineSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineSection.swift; sourceTree = ""; }; 2D7631A725C1535600929FB9 /* TimelinePostTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelinePostTableViewCell.swift; sourceTree = ""; }; 2D7631B225C159F700929FB9 /* Item.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Item.swift; sourceTree = ""; }; + 2D927F0125C7E4F2004F19B8 /* Mention.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Mention.swift; sourceTree = ""; }; + 2D927F0725C7E9A8004F19B8 /* Tag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tag.swift; sourceTree = ""; }; + 2D927F0D25C7E9C9004F19B8 /* History.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = History.swift; sourceTree = ""; }; + 2D927F1325C7EDD9004F19B8 /* Emoji.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Emoji.swift; sourceTree = ""; }; 2D9BB87A25C3FEF200678AB6 /* String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = String.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 = ""; }; @@ -479,6 +487,10 @@ DB89BA2625C110B4008580ED /* Toot.swift */, DB8AF52425C131D1002E6C99 /* MastodonUser.swift */, DB8AF56725C13E2A002E6C99 /* HomeTimelineIndex.swift */, + 2D927F0125C7E4F2004F19B8 /* Mention.swift */, + 2D927F0725C7E9A8004F19B8 /* Tag.swift */, + 2D927F0D25C7E9C9004F19B8 /* History.swift */, + 2D927F1325C7EDD9004F19B8 /* Emoji.swift */, ); path = Entity; sourceTree = ""; @@ -933,8 +945,10 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 2D927F1425C7EDD9004F19B8 /* Emoji.swift in Sources */, DB89BA1225C1105C008580ED /* CoreDataStack.swift in Sources */, DB89BA1C25C1107F008580ED /* NSManagedObjectContext.swift in Sources */, + 2D927F0E25C7E9C9004F19B8 /* History.swift in Sources */, DB89BA3725C1145C008580ED /* CoreData.xcdatamodeld in Sources */, DB8AF52525C131D1002E6C99 /* MastodonUser.swift in Sources */, DB89BA1B25C1107F008580ED /* Collection.swift in Sources */, @@ -943,7 +957,9 @@ DB89BA4425C1165F008580ED /* Managed.swift in Sources */, DB89BA4325C1165F008580ED /* NetworkUpdatable.swift in Sources */, DB8AF56825C13E2A002E6C99 /* HomeTimelineIndex.swift in Sources */, + 2D927F0225C7E4F2004F19B8 /* Mention.swift in Sources */, DB89BA1D25C1107F008580ED /* URL.swift in Sources */, + 2D927F0825C7E9A8004F19B8 /* Tag.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; };