Don't destroy/recreate same items view controller during handoff
This commit is contained in:
parent
c65b69cfbd
commit
00096e6df8
|
@ -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 = "<group>"; };
|
||||
D65B18B12750469D004A9448 /* LoginViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewController.swift; sourceTree = "<group>"; };
|
||||
D65B18B3275048D9004A9448 /* ClientRegistration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientRegistration.swift; sourceTree = "<group>"; };
|
||||
D65B18B527504920004A9448 /* FervorController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FervorController.swift; sourceTree = "<group>"; };
|
||||
|
@ -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 */,
|
||||
|
|
|
@ -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<NSManagedObjectID> {
|
||||
let req = NSFetchRequest<NSManagedObjectID>(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<Reader.Item>? {
|
||||
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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ class HomeViewController: UIViewController {
|
|||
var enableStretchyMenu = true
|
||||
|
||||
private var collectionView: UICollectionView!
|
||||
private var dataSource: UICollectionViewDiffableDataSource<Section, Item>!
|
||||
private var dataSource: UICollectionViewDiffableDataSource<Section, ItemListType>!
|
||||
private var groupResultsController: NSFetchedResultsController<Group>!
|
||||
private var feedResultsController: NSFetchedResultsController<Feed>!
|
||||
|
||||
|
@ -76,7 +76,7 @@ class HomeViewController: UIViewController {
|
|||
|
||||
dataSource = createDataSource()
|
||||
|
||||
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
|
||||
var snapshot = NSDiffableDataSourceSnapshot<Section, ItemListType>()
|
||||
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<Section, Item> {
|
||||
private func createDataSource() -> UICollectionViewDiffableDataSource<Section, ItemListType> {
|
||||
let sectionHeaderCell = UICollectionView.SupplementaryRegistration<UICollectionViewListCell>(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<HomeCollectionViewCell, Item> { cell, indexPath, item in
|
||||
let listCell = UICollectionView.CellRegistration<HomeCollectionViewCell, ItemListType> { 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<Section, Item>(collectionView: collectionView) { collectionView, indexPath, item in
|
||||
let dataSource = UICollectionViewDiffableDataSource<Section, ItemListType>(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<NSManagedObjectID> {
|
||||
let req = NSFetchRequest<NSManagedObjectID>(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<Reader.Item>? {
|
||||
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 {
|
||||
|
|
|
@ -18,20 +18,32 @@ class ItemsViewController: UIViewController {
|
|||
weak var delegate: ItemsViewControllerDelegate?
|
||||
|
||||
let fervorController: FervorController
|
||||
let fetchRequest: NSFetchRequest<NSManagedObjectID>
|
||||
let type: ItemListType
|
||||
private let fetchRequest: NSFetchRequest<NSManagedObjectID>
|
||||
|
||||
private var collectionView: UICollectionView!
|
||||
private var dataSource: UICollectionViewDiffableDataSource<Section, NSManagedObjectID>!
|
||||
|
||||
private var batchUpdates: [() -> Void] = []
|
||||
|
||||
init(fetchRequest: NSFetchRequest<NSManagedObjectID>, 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) {
|
||||
|
|
Loading…
Reference in New Issue