diff --git a/Reader.xcodeproj/project.pbxproj b/Reader.xcodeproj/project.pbxproj index 2c848ca..cd690a2 100644 --- a/Reader.xcodeproj/project.pbxproj +++ b/Reader.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + D608238D27DE729E00D7D5F9 /* ItemListType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D608238C27DE729E00D7D5F9 /* ItemListType.swift */; }; D65B18B22750469D004A9448 /* LoginViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65B18B12750469D004A9448 /* LoginViewController.swift */; }; D65B18B4275048D9004A9448 /* ClientRegistration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65B18B3275048D9004A9448 /* ClientRegistration.swift */; }; D65B18B627504920004A9448 /* FervorController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65B18B527504920004A9448 /* FervorController.swift */; }; @@ -116,6 +117,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + D608238C27DE729E00D7D5F9 /* ItemListType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemListType.swift; sourceTree = ""; }; D65B18B12750469D004A9448 /* LoginViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewController.swift; sourceTree = ""; }; D65B18B3275048D9004A9448 /* ClientRegistration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientRegistration.swift; sourceTree = ""; }; D65B18B527504920004A9448 /* FervorController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FervorController.swift; sourceTree = ""; }; @@ -324,6 +326,7 @@ D68B303527907D9200E8B3FA /* ExcerptGenerator.swift */, D68B304127932ED500E8B3FA /* UserActivities.swift */, D68408EE2794808E00E327D2 /* Preferences.swift */, + D608238C27DE729E00D7D5F9 /* ItemListType.swift */, D6A8A33527766E9300CCEC72 /* CoreData */, D65B18AF2750468B004A9448 /* Screens */, D6C687F7272CD27700874C10 /* Assets.xcassets */, @@ -632,6 +635,7 @@ files = ( D6A8A33427766C2800CCEC72 /* PersistentContainer.swift in Sources */, D6E24357278B96E40005E546 /* Feed+CoreDataClass.swift in Sources */, + D608238D27DE729E00D7D5F9 /* ItemListType.swift in Sources */, D65B18B627504920004A9448 /* FervorController.swift in Sources */, D68B304227932ED500E8B3FA /* UserActivities.swift in Sources */, D6C687EC272CD27600874C10 /* AppDelegate.swift in Sources */, diff --git a/Reader/ItemListType.swift b/Reader/ItemListType.swift new file mode 100644 index 0000000..1ffb8e8 --- /dev/null +++ b/Reader/ItemListType.swift @@ -0,0 +1,60 @@ +// +// ItemListType.swift +// Reader +// +// Created by Shadowfacts on 3/13/22. +// + +import Foundation +import CoreData + +enum ItemListType: Hashable { + case unread + case all + case group(Group) + case feed(Feed) + + var title: String { + switch self { + case .unread: + return "Unread Articles" + case .all: + return "All Articles" + case let .group(group): + return group.title + case let .feed(feed): + return feed.title! + } + } + + var idFetchRequest: NSFetchRequest { + let req = NSFetchRequest(entityName: "Item") + req.resultType = .managedObjectIDResultType + switch self { + case .unread: + req.predicate = NSPredicate(format: "read = NO") + case .all: + break + case .group(let group): + req.predicate = NSPredicate(format: "feed in %@", group.feeds!) + case .feed(let feed): + req.predicate = NSPredicate(format: "feed = %@", feed) + } + return req + } + + var countFetchRequest: NSFetchRequest? { + let req = Reader.Item.fetchRequest() + switch self { + case .unread: + req.predicate = NSPredicate(format: "read = NO") + case .all: + return nil + case .group(let group): + req.predicate = NSPredicate(format: "read = NO AND feed in %@", group.feeds!) + case .feed(let feed): + req.predicate = NSPredicate(format: "read = NO AND feed = %@", feed) + } + return req + } +} diff --git a/Reader/SceneDelegate.swift b/Reader/SceneDelegate.swift index 098cedd..08c44be 100644 --- a/Reader/SceneDelegate.swift +++ b/Reader/SceneDelegate.swift @@ -119,9 +119,9 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { } switch activity.activityType { case NSUserActivity.readUnreadType: - split.selectHomeItem(.unread) + split.showItemList(.unread) case NSUserActivity.readAllType: - split.selectHomeItem(.all) + split.showItemList(.all) case NSUserActivity.readFeedType: guard let feedID = activity.feedID() else { break @@ -129,7 +129,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { let req = Feed.fetchRequest() req.predicate = NSPredicate(format: "id = %@", feedID) if let feed = try? fervorController.persistentContainer.viewContext.fetch(req).first { - split.selectHomeItem(.feed(feed)) + split.showItemList(.feed(feed)) } case NSUserActivity.readGroupType: guard let groupID = activity.groupID() else { @@ -138,7 +138,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { let req = Group.fetchRequest() req.predicate = NSPredicate(format: "id = %@", groupID) if let group = try? fervorController.persistentContainer.viewContext.fetch(req).first { - split.selectHomeItem(.group(group)) + split.showItemList(.group(group)) } default: break diff --git a/Reader/Screens/AppSplitViewController.swift b/Reader/Screens/AppSplitViewController.swift index 228f4e5..3ff8ad1 100644 --- a/Reader/Screens/AppSplitViewController.swift +++ b/Reader/Screens/AppSplitViewController.swift @@ -54,7 +54,7 @@ class AppSplitViewController: UISplitViewController { setViewController(nav, for: .compact) } - func selectHomeItem(_ item: HomeViewController.Item) { + func showItemList(_ type: ItemListType) { let column: Column if traitCollection.horizontalSizeClass == .compact { column = .compact @@ -63,7 +63,7 @@ class AppSplitViewController: UISplitViewController { } let nav = viewController(for: column) as! UINavigationController let home = nav.viewControllers.first! as! HomeViewController - home.selectItem(item) + home.selectItem(type) } } diff --git a/Reader/Screens/Home/HomeViewController.swift b/Reader/Screens/Home/HomeViewController.swift index 3680aba..9301873 100644 --- a/Reader/Screens/Home/HomeViewController.swift +++ b/Reader/Screens/Home/HomeViewController.swift @@ -23,7 +23,7 @@ class HomeViewController: UIViewController { var enableStretchyMenu = true private var collectionView: UICollectionView! - private var dataSource: UICollectionViewDiffableDataSource! + private var dataSource: UICollectionViewDiffableDataSource! private var groupResultsController: NSFetchedResultsController! private var feedResultsController: NSFetchedResultsController! @@ -76,7 +76,7 @@ class HomeViewController: UIViewController { dataSource = createDataSource() - var snapshot = NSDiffableDataSourceSnapshot() + var snapshot = NSDiffableDataSourceSnapshot() snapshot.appendSections([.all, .groups, .feeds]) snapshot.appendItems([.unread, .all], toSection: .all) dataSource.apply(snapshot, animatingDifferences: false) @@ -116,14 +116,14 @@ class HomeViewController: UIViewController { dataSource.apply(snapshot) } - private func createDataSource() -> UICollectionViewDiffableDataSource { + private func createDataSource() -> UICollectionViewDiffableDataSource { let sectionHeaderCell = UICollectionView.SupplementaryRegistration(elementKind: UICollectionView.elementKindSectionHeader) { supplementaryView, elementKind, indexPath in let section = self.dataSource.sectionIdentifier(for: indexPath.section)! var config = supplementaryView.defaultContentConfiguration() config.text = section.title supplementaryView.contentConfiguration = config } - let listCell = UICollectionView.CellRegistration { cell, indexPath, item in + let listCell = UICollectionView.CellRegistration { cell, indexPath, item in var config = UIListContentConfiguration.valueCell() config.text = item.title if let req = item.countFetchRequest, @@ -135,7 +135,7 @@ class HomeViewController: UIViewController { cell.accessories = [.disclosureIndicator()] } - let dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView) { collectionView, indexPath, item in + let dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView) { collectionView, indexPath, item in return collectionView.dequeueConfiguredReusableCell(using: listCell, for: indexPath, item: item) } dataSource.supplementaryViewProvider = { collectionView, elementKind, indexPath in @@ -206,26 +206,26 @@ class HomeViewController: UIViewController { } } - private func itemsViewController(for item: Item) -> ItemsViewController { - let vc = ItemsViewController(fetchRequest: item.idFetchRequest, fervorController: fervorController) - vc.title = item.title + private func itemsViewController(for item: ItemListType) -> ItemsViewController { + let vc = ItemsViewController(type: item, fervorController: fervorController) vc.delegate = itemsDelegate - switch item { - case .all: - vc.userActivity = .readAll(account: fervorController.account!) - case .unread: - vc.userActivity = .readUnread(account: fervorController.account!) - case .group(let group): - vc.userActivity = .readGroup(group, account: fervorController.account!) - case .feed(let feed): - vc.userActivity = .readFeed(feed, account: fervorController.account!) - } return vc } - func selectItem(_ item: Item) { - navigationController!.popToRootViewController(animated: false) - navigationController!.pushViewController(itemsViewController(for: item), animated: false) + func selectItem(_ item: ItemListType) { + guard let navigationController = navigationController else { + return + } + if navigationController.viewControllers.count >= 2, + let second = navigationController.viewControllers[1] as? ItemsViewController, + second.type == item { + while navigationController.viewControllers.count > 2 { + navigationController.popViewController(animated: false) + } + } else { + navigationController.popToRootViewController(animated: false) + navigationController.pushViewController(itemsViewController(for: item), animated: false) + } } } @@ -247,56 +247,6 @@ extension HomeViewController { } } } - enum Item: Hashable { - case unread - case all - case group(Group) - case feed(Feed) - - var title: String { - switch self { - case .unread: - return "Unread Articles" - case .all: - return "All Articles" - case let .group(group): - return group.title - case let .feed(feed): - return feed.title! - } - } - - var idFetchRequest: NSFetchRequest { - let req = NSFetchRequest(entityName: "Item") - req.resultType = .managedObjectIDResultType - switch self { - case .unread: - req.predicate = NSPredicate(format: "read = NO") - case .all: - break - case .group(let group): - req.predicate = NSPredicate(format: "feed in %@", group.feeds!) - case .feed(let feed): - req.predicate = NSPredicate(format: "feed = %@", feed) - } - return req - } - - var countFetchRequest: NSFetchRequest? { - let req = Reader.Item.fetchRequest() - switch self { - case .unread: - req.predicate = NSPredicate(format: "read = NO") - case .all: - return nil - case .group(let group): - req.predicate = NSPredicate(format: "read = NO AND feed in %@", group.feeds!) - case .feed(let feed): - req.predicate = NSPredicate(format: "read = NO AND feed = %@", feed) - } - return req - } - } } extension HomeViewController: NSFetchedResultsControllerDelegate { diff --git a/Reader/Screens/Items/ItemsViewController.swift b/Reader/Screens/Items/ItemsViewController.swift index c64bb2a..6d4e8ee 100644 --- a/Reader/Screens/Items/ItemsViewController.swift +++ b/Reader/Screens/Items/ItemsViewController.swift @@ -18,20 +18,32 @@ class ItemsViewController: UIViewController { weak var delegate: ItemsViewControllerDelegate? let fervorController: FervorController - let fetchRequest: NSFetchRequest + let type: ItemListType + private let fetchRequest: NSFetchRequest private var collectionView: UICollectionView! private var dataSource: UICollectionViewDiffableDataSource! private var batchUpdates: [() -> Void] = [] - init(fetchRequest: NSFetchRequest, fervorController: FervorController) { - precondition(fetchRequest.entityName == "Item") - + init(type: ItemListType, fervorController: FervorController) { self.fervorController = fervorController - self.fetchRequest = fetchRequest + self.type = type + self.fetchRequest = type.idFetchRequest super.init(nibName: nil, bundle: nil) + + self.title = type.title + switch type { + case .all: + self.userActivity = .readAll(account: fervorController.account!) + case .unread: + self.userActivity = .readUnread(account: fervorController.account!) + case .group(let group): + self.userActivity = .readGroup(group, account: fervorController.account!) + case .feed(let feed): + self.userActivity = .readFeed(feed, account: fervorController.account!) + } } required init?(coder: NSCoder) {