diff --git a/Tusker.xcodeproj/project.pbxproj b/Tusker.xcodeproj/project.pbxproj index 5afec677..b23acb78 100644 --- a/Tusker.xcodeproj/project.pbxproj +++ b/Tusker.xcodeproj/project.pbxproj @@ -23,6 +23,9 @@ D6028B9B2150811100F223B9 /* MastodonCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6028B9A2150811100F223B9 /* MastodonCache.swift */; }; D60309B52419D4F100A465FF /* ComposeAttachmentsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D60309B42419D4F100A465FF /* ComposeAttachmentsViewController.swift */; }; 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 */; }; + 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 */; }; D61099BD2144B0CC00432DC2 /* Pachyderm.h in Headers */ = {isa = PBXBuildFile; fileRef = D61099AD2144B0CC00432DC2 /* Pachyderm.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -105,6 +108,7 @@ D6333B792139AEFD00CE884A /* Date+TimeAgo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6333B782139AEFD00CE884A /* Date+TimeAgo.swift */; }; D63569E023908A8D003DD353 /* StatusState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D60A4FFB238B726A008AC647 /* StatusState.swift */; }; D63661C02381C144004B9E16 /* PreferencesNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D63661BF2381C144004B9E16 /* PreferencesNavigationController.swift */; }; + D6370B9C24421FF30092A7FF /* Tusker.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = D6370B9A24421FF30092A7FF /* Tusker.xcdatamodeld */; }; D63F9C66241C4CC3004C03CF /* AddAttachmentTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D63F9C65241C4CC3004C03CF /* AddAttachmentTableViewCell.xib */; }; D63F9C68241C4F79004C03CF /* AddAttachmentTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D63F9C67241C4F79004C03CF /* AddAttachmentTableViewCell.swift */; }; D63F9C6B241C50B9004C03CF /* ComposeAttachmentTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D63F9C69241C50B9004C03CF /* ComposeAttachmentTableViewCell.swift */; }; @@ -307,6 +311,10 @@ D60309B42419D4F100A465FF /* ComposeAttachmentsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeAttachmentsViewController.swift; sourceTree = ""; }; D60A4FFB238B726A008AC647 /* StatusState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusState.swift; sourceTree = ""; }; D60D2B8123844C71001B87A3 /* BaseStatusTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseStatusTableViewCell.swift; sourceTree = ""; }; + D60E2F232442372B005F8713 /* StatusMO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusMO.swift; sourceTree = ""; }; + D60E2F252442372B005F8713 /* AccountMO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountMO.swift; sourceTree = ""; }; + D60E2F2B24423EAD005F8713 /* LazilyDecoding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LazilyDecoding.swift; sourceTree = ""; }; + D60E2F2D244248BF005F8713 /* MastodonCachePersistentStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonCachePersistentStore.swift; sourceTree = ""; }; D61099AB2144B0CC00432DC2 /* Pachyderm.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pachyderm.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D61099AD2144B0CC00432DC2 /* Pachyderm.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Pachyderm.h; sourceTree = ""; }; D61099AE2144B0CC00432DC2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -389,6 +397,7 @@ D6333B362137838300CE884A /* AttributedString+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AttributedString+Helpers.swift"; sourceTree = ""; }; D6333B782139AEFD00CE884A /* Date+TimeAgo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Date+TimeAgo.swift"; sourceTree = ""; }; D63661BF2381C144004B9E16 /* PreferencesNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesNavigationController.swift; sourceTree = ""; }; + D6370B9B24421FF30092A7FF /* Tusker.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Tusker.xcdatamodel; sourceTree = ""; }; D63F9C65241C4CC3004C03CF /* AddAttachmentTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AddAttachmentTableViewCell.xib; sourceTree = ""; }; D63F9C67241C4F79004C03CF /* AddAttachmentTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddAttachmentTableViewCell.swift; sourceTree = ""; }; D63F9C69241C50B9004C03CF /* ComposeAttachmentTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeAttachmentTableViewCell.swift; sourceTree = ""; }; @@ -789,6 +798,17 @@ path = Shortcuts; sourceTree = ""; }; + D6370B9924421FE00092A7FF /* CoreData */ = { + isa = PBXGroup; + children = ( + D6370B9A24421FF30092A7FF /* Tusker.xcdatamodeld */, + D60E2F232442372B005F8713 /* StatusMO.swift */, + D60E2F252442372B005F8713 /* AccountMO.swift */, + D60E2F2D244248BF005F8713 /* MastodonCachePersistentStore.swift */, + ); + path = CoreData; + sourceTree = ""; + }; D641C780213DD7C4004B4513 /* Screens */ = { isa = PBXGroup; children = ( @@ -1223,6 +1243,7 @@ D6AEBB3F2321640F00E5038B /* Activities */, D667E5F62135C2ED0057A976 /* Extensions */, D61959D2241E846D00A37B8E /* Models */, + D6370B9924421FE00092A7FF /* CoreData */, D6F953F121251A2F00CF0F2B /* Controllers */, D641C780213DD7C4004B4513 /* Screens */, D6BED1722126661300F02DA0 /* Views */, @@ -1606,6 +1627,7 @@ D6DD353D22F28CD000A9563A /* ContentWarningCopyMode.swift in Sources */, 0427033A22B31269000D31B6 /* AdvancedPrefsView.swift in Sources */, D626493C23C1000300612E6E /* AlbumTableViewCell.swift in Sources */, + D60E2F292442372B005F8713 /* AccountMO.swift in Sources */, D6757A822157E8FA00721E32 /* XCBSession.swift in Sources */, D6EBF01723C55E0D00AE061B /* UISceneSession+MastodonController.swift in Sources */, 04DACE8C212CB14B009840C4 /* MainTabBarViewController.swift in Sources */, @@ -1632,6 +1654,7 @@ D66362712136338600C9CBA2 /* ComposeViewController.swift in Sources */, D6AC956723C4347E008C9946 /* SceneDelegate.swift in Sources */, D6BC9DD7232D7811002CA326 /* TimelinesPageViewController.swift in Sources */, + D60E2F2E244248BF005F8713 /* MastodonCachePersistentStore.swift in Sources */, D620483623D38075008A63EF /* ContentTextView.swift in Sources */, D6028B9B2150811100F223B9 /* MastodonCache.swift in Sources */, D6A3BC802321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.swift in Sources */, @@ -1640,6 +1663,7 @@ D60309B52419D4F100A465FF /* ComposeAttachmentsViewController.swift in Sources */, D62D2422217AA7E1005076CC /* UserActivityManager.swift in Sources */, D60D2B8223844C71001B87A3 /* BaseStatusTableViewCell.swift in Sources */, + D60E2F272442372B005F8713 /* StatusMO.swift in Sources */, D62D2424217ABF3F005076CC /* NSUserActivity+Extensions.swift in Sources */, D646C958213B367000269FB5 /* LargeImageShrinkAnimationController.swift in Sources */, D6A3BC852321F6C100FD64D5 /* AccountListTableViewController.swift in Sources */, @@ -1651,6 +1675,7 @@ D6B053A623BD2D0C00A066FA /* AssetCollectionViewController.swift in Sources */, 04DACE8E212CC7CC009840C4 /* ImageCache.swift in Sources */, D627FF7B217E951500CC0648 /* DraftsTableViewController.swift in Sources */, + D6370B9C24421FF30092A7FF /* Tusker.xcdatamodeld in Sources */, D6A3BC8F2321FFB900FD64D5 /* StatusActionAccountListTableViewController.swift in Sources */, D6AEBB4823216B1D00E5038B /* AccountActivity.swift in Sources */, 04ED00B121481ED800567C53 /* SteppedProgressView.swift in Sources */, @@ -2231,6 +2256,19 @@ productName = SheetController; }; /* End XCSwiftPackageProductDependency section */ + +/* Begin XCVersionGroup section */ + D6370B9A24421FF30092A7FF /* Tusker.xcdatamodeld */ = { + isa = XCVersionGroup; + children = ( + D6370B9B24421FF30092A7FF /* Tusker.xcdatamodel */, + ); + currentVersion = D6370B9B24421FF30092A7FF /* Tusker.xcdatamodel */; + path = Tusker.xcdatamodeld; + sourceTree = ""; + versionGroupType = wrapper.xcdatamodel; + }; +/* End XCVersionGroup section */ }; rootObject = D6D4DDC4212518A000E1C4BB /* Project object */; } diff --git a/Tusker/Controllers/MastodonController.swift b/Tusker/Controllers/MastodonController.swift index 7bde68b4..899b35cd 100644 --- a/Tusker/Controllers/MastodonController.swift +++ b/Tusker/Controllers/MastodonController.swift @@ -32,6 +32,8 @@ class MastodonController { private(set) lazy var cache = MastodonCache(mastodonController: self) + private(set) lazy var persistentContainer = MastodonCachePersistentStore(for: self) + let instanceURL: URL private(set) var accountInfo: LocalData.UserAccountInfo? diff --git a/Tusker/CoreData/AccountMO.swift b/Tusker/CoreData/AccountMO.swift new file mode 100644 index 00000000..b46da8f9 --- /dev/null +++ b/Tusker/CoreData/AccountMO.swift @@ -0,0 +1,39 @@ +// +// AccountMO.swift +// Tusker +// +// Created by Shadowfacts on 4/11/20. +// Copyright © 2020 Shadowfacts. All rights reserved. +// +// + +import Foundation +import CoreData + +@objc(AccountMO) +public class AccountMO: NSManagedObject { + + @nonobjc public class func fetchRequest() -> NSFetchRequest { + return NSFetchRequest(entityName: "Account") + } + + @NSManaged public var acct: String? + @NSManaged public var avatar: URL? + @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 followersCount: Int64 + @NSManaged public var followingCount: Int64 + @NSManaged public var header: URL? + @NSManaged public var id: String? + @NSManaged public var locked: Bool + @NSManaged public var moved: Bool + @NSManaged public var note: String? + @NSManaged public var statusesCount: Int64 + @NSManaged public var url: URL? + @NSManaged public var username: String? + @NSManaged public var movedTo: AccountMO? + +} diff --git a/Tusker/CoreData/MastodonCachePersistentStore.swift b/Tusker/CoreData/MastodonCachePersistentStore.swift new file mode 100644 index 00000000..a522cfa1 --- /dev/null +++ b/Tusker/CoreData/MastodonCachePersistentStore.swift @@ -0,0 +1,47 @@ +// +// MastodonCachePersistentStore.swift +// Tusker +// +// Created by Shadowfacts on 4/11/20. +// Copyright © 2020 Shadowfacts. All rights reserved. +// + +import Foundation +import CoreData + +class MastodonCachePersistentStore: NSPersistentContainer { + + init(for controller: MastodonController) { + let url = Bundle.main.url(forResource: "Tusker", withExtension: "momd")! + let model = NSManagedObjectModel(contentsOf: url)! + super.init(name: "\(controller.accountInfo!.id)_cache", managedObjectModel: model) + loadPersistentStores { (description, error) in + if let error = error { + fatalError("Unable to load persistent store: \(error)") + } + } + } + + func status(for id: String) -> StatusMO? { + let request: NSFetchRequest = StatusMO.fetchRequest() + request.predicate = NSPredicate(format: "id = %@", id) + request.fetchLimit = 1 + if let result = try? viewContext.fetch(request), let status = result.first { + return status + } else { + return nil + } + } + + func account(for id: String) -> AccountMO? { + let request: NSFetchRequest = AccountMO.fetchRequest() + request.predicate = NSPredicate(format: "id = %@", id) + request.fetchLimit = 1 + if let result = try? viewContext.fetch(request), let account = result.first { + return account + } else { + return nil + } + } + +} diff --git a/Tusker/CoreData/StatusMO.swift b/Tusker/CoreData/StatusMO.swift new file mode 100644 index 00000000..aacde0d5 --- /dev/null +++ b/Tusker/CoreData/StatusMO.swift @@ -0,0 +1,44 @@ +// +// StatusMO.swift +// Tusker +// +// Created by Shadowfacts on 4/11/20. +// Copyright © 2020 Shadowfacts. All rights reserved. +// +// + +import Foundation +import CoreData + +@objc(StatusMO) +public final class StatusMO: NSManagedObject { + + @nonobjc public class func fetchRequest() -> NSFetchRequest { + return NSFetchRequest(entityName: "Status") + } + + @NSManaged public var application: String? + @NSManaged public var attachmentsData: Data? + @NSManaged public var bookmarked: Bool + @NSManaged public var content: String + @NSManaged public var createdAt: Date + @NSManaged public var emojisData: Data? + @NSManaged public var favourited: Bool + @NSManaged public var favouritesCount: Int + @NSManaged public var hashtagsData: Data? + @NSManaged public var id: String + @NSManaged public var mentionsData: Data? + @NSManaged public var muted: Bool + @NSManaged public var pinned: Bool + @NSManaged public var reblogged: Bool + @NSManaged public var reblogsCount: Int + @NSManaged public var sensitive: Bool + @NSManaged public var uri: String + @NSManaged public var url: URL? + @NSManaged public var visibility: String? + @NSManaged public var account: AccountMO + @NSManaged public var inReplyTo: StatusMO? + @NSManaged public var inReplyToAccount: AccountMO? + @NSManaged public var reblog: StatusMO? + +} diff --git a/Tusker/CoreData/Tusker.xcdatamodeld/Tusker.xcdatamodel/contents b/Tusker/CoreData/Tusker.xcdatamodeld/Tusker.xcdatamodel/contents new file mode 100644 index 00000000..9bd9aa12 --- /dev/null +++ b/Tusker/CoreData/Tusker.xcdatamodeld/Tusker.xcdatamodel/contents @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file