diff --git a/Reader.xcodeproj/project.pbxproj b/Reader.xcodeproj/project.pbxproj index 33b37f2..78569af 100644 --- a/Reader.xcodeproj/project.pbxproj +++ b/Reader.xcodeproj/project.pbxproj @@ -16,7 +16,6 @@ D65B18BE275051A1004A9448 /* LocalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65B18BD275051A1004A9448 /* LocalData.swift */; }; D65B18C127505348004A9448 /* HomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65B18C027505348004A9448 /* HomeViewController.swift */; }; D6A8A33427766C2800CCEC72 /* PersistentContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A8A33327766C2800CCEC72 /* PersistentContainer.swift */; }; - D6A8A33727766EA100CCEC72 /* ManagedObjectExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A8A33627766EA100CCEC72 /* ManagedObjectExtensions.swift */; }; D6C687EC272CD27600874C10 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C687EB272CD27600874C10 /* AppDelegate.swift */; }; D6C687EE272CD27600874C10 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C687ED272CD27600874C10 /* SceneDelegate.swift */; }; D6C687F6272CD27600874C10 /* Reader.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = D6C687F4272CD27600874C10 /* Reader.xcdatamodeld */; }; @@ -34,8 +33,13 @@ D6C68856272CD7C600874C10 /* Item.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C68855272CD7C600874C10 /* Item.swift */; }; D6C68858272CD8CD00874C10 /* Group.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6C68857272CD8CD00874C10 /* Group.swift */; }; D6E2434C278B456A0005E546 /* ItemsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E2434B278B456A0005E546 /* ItemsViewController.swift */; }; - D6E24350278B62F60005E546 /* Item.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E2434F278B62F60005E546 /* Item.swift */; }; D6E24352278B6DF90005E546 /* ItemsSyncUpdate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E24351278B6DF90005E546 /* ItemsSyncUpdate.swift */; }; + D6E24357278B96E40005E546 /* Feed+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E24355278B96E40005E546 /* Feed+CoreDataClass.swift */; }; + D6E24358278B96E40005E546 /* Feed+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E24356278B96E40005E546 /* Feed+CoreDataProperties.swift */; }; + D6E2435D278B97240005E546 /* Item+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E24359278B97240005E546 /* Item+CoreDataClass.swift */; }; + D6E2435E278B97240005E546 /* Item+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E2435A278B97240005E546 /* Item+CoreDataProperties.swift */; }; + D6E2435F278B97240005E546 /* Group+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E2435B278B97240005E546 /* Group+CoreDataClass.swift */; }; + D6E24360278B97240005E546 /* Group+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E2435C278B97240005E546 /* Group+CoreDataProperties.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -86,7 +90,6 @@ D65B18BD275051A1004A9448 /* LocalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalData.swift; sourceTree = ""; }; D65B18C027505348004A9448 /* HomeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewController.swift; sourceTree = ""; }; D6A8A33327766C2800CCEC72 /* PersistentContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersistentContainer.swift; sourceTree = ""; }; - D6A8A33627766EA100CCEC72 /* ManagedObjectExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManagedObjectExtensions.swift; sourceTree = ""; }; D6C687E8272CD27600874C10 /* Reader.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Reader.app; sourceTree = BUILT_PRODUCTS_DIR; }; D6C687EB272CD27600874C10 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; D6C687ED272CD27600874C10 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -107,8 +110,13 @@ D6C68855272CD7C600874C10 /* Item.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Item.swift; sourceTree = ""; }; D6C68857272CD8CD00874C10 /* Group.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Group.swift; sourceTree = ""; }; D6E2434B278B456A0005E546 /* ItemsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemsViewController.swift; sourceTree = ""; }; - D6E2434F278B62F60005E546 /* Item.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Item.swift; sourceTree = ""; }; D6E24351278B6DF90005E546 /* ItemsSyncUpdate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemsSyncUpdate.swift; sourceTree = ""; }; + D6E24355278B96E40005E546 /* Feed+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Feed+CoreDataClass.swift"; sourceTree = ""; }; + D6E24356278B96E40005E546 /* Feed+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Feed+CoreDataProperties.swift"; sourceTree = ""; }; + D6E24359278B97240005E546 /* Item+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Item+CoreDataClass.swift"; sourceTree = ""; }; + D6E2435A278B97240005E546 /* Item+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Item+CoreDataProperties.swift"; sourceTree = ""; }; + D6E2435B278B97240005E546 /* Group+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Group+CoreDataClass.swift"; sourceTree = ""; }; + D6E2435C278B97240005E546 /* Group+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Group+CoreDataProperties.swift"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -173,8 +181,14 @@ D6A8A33527766E9300CCEC72 /* CoreData */ = { isa = PBXGroup; children = ( + D6C687F4272CD27600874C10 /* Reader.xcdatamodeld */, D6A8A33327766C2800CCEC72 /* PersistentContainer.swift */, - D6A8A33627766EA100CCEC72 /* ManagedObjectExtensions.swift */, + D6E24355278B96E40005E546 /* Feed+CoreDataClass.swift */, + D6E24356278B96E40005E546 /* Feed+CoreDataProperties.swift */, + D6E2435B278B97240005E546 /* Group+CoreDataClass.swift */, + D6E2435C278B97240005E546 /* Group+CoreDataProperties.swift */, + D6E24359278B97240005E546 /* Item+CoreDataClass.swift */, + D6E2435A278B97240005E546 /* Item+CoreDataProperties.swift */, ); path = CoreData; sourceTree = ""; @@ -213,8 +227,6 @@ D6C687F7272CD27700874C10 /* Assets.xcassets */, D6C687F9272CD27700874C10 /* LaunchScreen.storyboard */, D6C687FC272CD27700874C10 /* Info.plist */, - D6C687F4272CD27600874C10 /* Reader.xcdatamodeld */, - D6E2434F278B62F60005E546 /* Item.swift */, ); path = Reader; sourceTree = ""; @@ -436,12 +448,16 @@ buildActionMask = 2147483647; files = ( D6A8A33427766C2800CCEC72 /* PersistentContainer.swift in Sources */, + D6E24357278B96E40005E546 /* Feed+CoreDataClass.swift in Sources */, D65B18B627504920004A9448 /* FervorController.swift in Sources */, D6C687EC272CD27600874C10 /* AppDelegate.swift in Sources */, D6C687F6272CD27600874C10 /* Reader.xcdatamodeld in Sources */, - D6A8A33727766EA100CCEC72 /* ManagedObjectExtensions.swift in Sources */, + D6E2435F278B97240005E546 /* Group+CoreDataClass.swift in Sources */, + D6E2435D278B97240005E546 /* Item+CoreDataClass.swift in Sources */, + D6E24360278B97240005E546 /* Group+CoreDataProperties.swift in Sources */, D6E2434C278B456A0005E546 /* ItemsViewController.swift in Sources */, - D6E24350278B62F60005E546 /* Item.swift in Sources */, + D6E2435E278B97240005E546 /* Item+CoreDataProperties.swift in Sources */, + D6E24358278B96E40005E546 /* Feed+CoreDataProperties.swift in Sources */, D65B18BE275051A1004A9448 /* LocalData.swift in Sources */, D65B18B22750469D004A9448 /* LoginViewController.swift in Sources */, D65B18C127505348004A9448 /* HomeViewController.swift in Sources */, diff --git a/Reader/CoreData/Feed+CoreDataClass.swift b/Reader/CoreData/Feed+CoreDataClass.swift new file mode 100644 index 0000000..a197c88 --- /dev/null +++ b/Reader/CoreData/Feed+CoreDataClass.swift @@ -0,0 +1,30 @@ +// +// Feed+CoreDataClass.swift +// Reader +// +// Created by Shadowfacts on 1/9/22. +// +// + +import Foundation +import CoreData +import Fervor + +@objc(Feed) +public class Feed: NSManagedObject { + + func updateFromServer(_ serverFeed: Fervor.Feed) { + guard self.id == nil || self.id == serverFeed.id else { return } + self.id = serverFeed.id + self.title = serverFeed.title + self.url = serverFeed.url + self.lastUpdated = serverFeed.lastUpdated + // todo: check this + self.removeFromGroups(self.groups!.filtered(using: NSPredicate(format: "NOT id IN %@", serverFeed.groupIDs)) as NSSet) + let groupsToAddReq = Group.fetchRequest() + groupsToAddReq.predicate = NSPredicate(format: "id IN %@", serverFeed.groupIDs.filter { g in !self.groups!.contains { ($0 as! Group).id == g } }) + let groupsToAdd = try! self.managedObjectContext!.fetch(groupsToAddReq) + self.addToGroups(NSSet(array: groupsToAdd)) + } + +} diff --git a/Reader/CoreData/Feed+CoreDataProperties.swift b/Reader/CoreData/Feed+CoreDataProperties.swift new file mode 100644 index 0000000..ff67cfd --- /dev/null +++ b/Reader/CoreData/Feed+CoreDataProperties.swift @@ -0,0 +1,64 @@ +// +// Feed+CoreDataProperties.swift +// Reader +// +// Created by Shadowfacts on 1/9/22. +// +// + +import Foundation +import CoreData + + +extension Feed { + + @nonobjc public class func fetchRequest() -> NSFetchRequest { + return NSFetchRequest(entityName: "Feed") + } + + @NSManaged public var id: String? + @NSManaged public var lastUpdated: Date? + @NSManaged public var title: String? + @NSManaged public var url: URL? + @NSManaged public var groups: NSSet? + @NSManaged public var items: NSSet? + +} + +// MARK: Generated accessors for groups +extension Feed { + + @objc(addGroupsObject:) + @NSManaged public func addToGroups(_ value: Group) + + @objc(removeGroupsObject:) + @NSManaged public func removeFromGroups(_ value: Group) + + @objc(addGroups:) + @NSManaged public func addToGroups(_ values: NSSet) + + @objc(removeGroups:) + @NSManaged public func removeFromGroups(_ values: NSSet) + +} + +// MARK: Generated accessors for items +extension Feed { + + @objc(addItemsObject:) + @NSManaged public func addToItems(_ value: Item) + + @objc(removeItemsObject:) + @NSManaged public func removeFromItems(_ value: Item) + + @objc(addItems:) + @NSManaged public func addToItems(_ values: NSSet) + + @objc(removeItems:) + @NSManaged public func removeFromItems(_ values: NSSet) + +} + +extension Feed : Identifiable { + +} diff --git a/Reader/CoreData/Group+CoreDataClass.swift b/Reader/CoreData/Group+CoreDataClass.swift new file mode 100644 index 0000000..0060e2e --- /dev/null +++ b/Reader/CoreData/Group+CoreDataClass.swift @@ -0,0 +1,24 @@ +// +// Group+CoreDataClass.swift +// Reader +// +// Created by Shadowfacts on 1/9/22. +// +// + +import Foundation +import CoreData +import Fervor + +@objc(Group) +public class Group: NSManagedObject { + + func updateFromServer(_ serverGroup: Fervor.Group) { + guard self.id == nil || self.id == serverGroup.id else { return } + self.id = serverGroup.id + self.title = serverGroup.title + // feeds relationships will be updated after feeds are created in PersistentContainer.sync + } + + +} diff --git a/Reader/CoreData/Group+CoreDataProperties.swift b/Reader/CoreData/Group+CoreDataProperties.swift new file mode 100644 index 0000000..5e6a902 --- /dev/null +++ b/Reader/CoreData/Group+CoreDataProperties.swift @@ -0,0 +1,44 @@ +// +// Group+CoreDataProperties.swift +// Reader +// +// Created by Shadowfacts on 1/9/22. +// +// + +import Foundation +import CoreData + + +extension Group { + + @nonobjc public class func fetchRequest() -> NSFetchRequest { + return NSFetchRequest(entityName: "Group") + } + + @NSManaged public var id: String? + @NSManaged public var title: String + @NSManaged public var feeds: NSSet? + +} + +// MARK: Generated accessors for feeds +extension Group { + + @objc(addFeedsObject:) + @NSManaged public func addToFeeds(_ value: Feed) + + @objc(removeFeedsObject:) + @NSManaged public func removeFromFeeds(_ value: Feed) + + @objc(addFeeds:) + @NSManaged public func addToFeeds(_ values: NSSet) + + @objc(removeFeeds:) + @NSManaged public func removeFromFeeds(_ values: NSSet) + +} + +extension Group : Identifiable { + +} diff --git a/Reader/CoreData/Item+CoreDataClass.swift b/Reader/CoreData/Item+CoreDataClass.swift new file mode 100644 index 0000000..49cb497 --- /dev/null +++ b/Reader/CoreData/Item+CoreDataClass.swift @@ -0,0 +1,33 @@ +// +// Item+CoreDataClass.swift +// Reader +// +// Created by Shadowfacts on 1/9/22. +// +// + +import Foundation +import CoreData +import Fervor + +@objc(Item) +public class Item: NSManagedObject { + + func updateFromServer(_ serverItem: Fervor.Item) { + guard self.id == nil || self.id == serverItem.id else { return } + self.id = serverItem.id + self.author = serverItem.author + self.content = serverItem.content + self.title = serverItem.title + self.read = serverItem.read ?? false + self.published = serverItem.published + self.url = serverItem.url + if self.feed?.id != serverItem.feedID { + let feedReq = Feed.fetchRequest() + feedReq.predicate = NSPredicate(format: "id = %@", serverItem.feedID) + self.feed = try! self.managedObjectContext!.fetch(feedReq).first! + } + } + + +} diff --git a/Reader/Item.swift b/Reader/CoreData/Item+CoreDataProperties.swift similarity index 82% rename from Reader/Item.swift rename to Reader/CoreData/Item+CoreDataProperties.swift index 031856a..c8fad1b 100644 --- a/Reader/Item.swift +++ b/Reader/CoreData/Item+CoreDataProperties.swift @@ -1,27 +1,32 @@ // -// Item.swift +// Item+CoreDataProperties.swift // Reader // // Created by Shadowfacts on 1/9/22. // +// +import Foundation import CoreData -@objc(Item) -public final class Item: NSManagedObject { - + +extension Item { + @nonobjc public class func fetchRequest() -> NSFetchRequest { return NSFetchRequest(entityName: "Item") } - + @NSManaged public var author: String? @NSManaged public var content: String? @NSManaged public var id: String? - @NSManaged public var title: String? - @NSManaged public var read: Bool @NSManaged public var published: Date? + @NSManaged public var read: Bool + @NSManaged public var title: String? @NSManaged public var url: URL? - @NSManaged public var feed: Feed? - + +} + +extension Item : Identifiable { + } diff --git a/Reader/CoreData/ManagedObjectExtensions.swift b/Reader/CoreData/ManagedObjectExtensions.swift deleted file mode 100644 index 23ff369..0000000 --- a/Reader/CoreData/ManagedObjectExtensions.swift +++ /dev/null @@ -1,58 +0,0 @@ -// -// ManagedObjectExtensions.swift -// Reader -// -// Created by Shadowfacts on 12/24/21. -// - -import Foundation -import Fervor - -extension Group { - - func updateFromServer(_ serverGroup: Fervor.Group) { - guard self.id == nil || self.id == serverGroup.id else { return } - self.id = serverGroup.id - self.title = serverGroup.title - // feeds relationships will be updated after feeds are created in PersistentContainer.sync - } - -} - -extension Feed { - - func updateFromServer(_ serverFeed: Fervor.Feed) { - guard self.id == nil || self.id == serverFeed.id else { return } - self.id = serverFeed.id - self.title = serverFeed.title - self.url = serverFeed.url - self.lastUpdated = serverFeed.lastUpdated - // todo: check this - self.removeFromGroups(self.groups!.filtered(using: NSPredicate(format: "NOT id IN %@", serverFeed.groupIDs)) as NSSet) - let groupsToAddReq = Group.fetchRequest() - groupsToAddReq.predicate = NSPredicate(format: "id IN %@", serverFeed.groupIDs.filter { g in !self.groups!.contains { ($0 as! Group).id == g } }) - let groupsToAdd = try! self.managedObjectContext!.fetch(groupsToAddReq) - self.addToGroups(NSSet(array: groupsToAdd)) - } - -} - -extension Item { - - func updateFromServer(_ serverItem: Fervor.Item) { - guard self.id == nil || self.id == serverItem.id else { return } - self.id = serverItem.id - self.author = serverItem.author - self.content = serverItem.content - self.title = serverItem.title - self.read = serverItem.read ?? false - self.published = serverItem.published - self.url = serverItem.url - if self.feed?.id != serverItem.feedID { - let feedReq = Feed.fetchRequest() - feedReq.predicate = NSPredicate(format: "id = %@", serverItem.feedID) - self.feed = try! self.managedObjectContext!.fetch(feedReq).first! - } - } - -} diff --git a/Reader/Reader.xcdatamodeld/.xccurrentversion b/Reader/CoreData/Reader.xcdatamodeld/.xccurrentversion similarity index 100% rename from Reader/Reader.xcdatamodeld/.xccurrentversion rename to Reader/CoreData/Reader.xcdatamodeld/.xccurrentversion diff --git a/Reader/Reader.xcdatamodeld/Reader.xcdatamodel/contents b/Reader/CoreData/Reader.xcdatamodeld/Reader.xcdatamodel/contents similarity index 97% rename from Reader/Reader.xcdatamodeld/Reader.xcdatamodel/contents rename to Reader/CoreData/Reader.xcdatamodeld/Reader.xcdatamodel/contents index 2d37a4a..2a5b062 100644 --- a/Reader/Reader.xcdatamodeld/Reader.xcdatamodel/contents +++ b/Reader/CoreData/Reader.xcdatamodeld/Reader.xcdatamodel/contents @@ -1,6 +1,6 @@ - + @@ -8,7 +8,7 @@ - + diff --git a/Reader/Screens/Home/HomeViewController.swift b/Reader/Screens/Home/HomeViewController.swift index 48912c5..4bb5a48 100644 --- a/Reader/Screens/Home/HomeViewController.swift +++ b/Reader/Screens/Home/HomeViewController.swift @@ -95,8 +95,7 @@ extension HomeViewController { var title: String { switch self { case let .group(group): - // todo: manual codegen for models so this force unwrap isn't necessary - return group.title! + return group.title case let .feed(feed): return feed.title! }