Don't destroy/recreate same items view controller during handoff
This commit is contained in:
parent
c65b69cfbd
commit
00096e6df8
|
@ -7,6 +7,7 @@
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* 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 */; };
|
D65B18B22750469D004A9448 /* LoginViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65B18B12750469D004A9448 /* LoginViewController.swift */; };
|
||||||
D65B18B4275048D9004A9448 /* ClientRegistration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65B18B3275048D9004A9448 /* ClientRegistration.swift */; };
|
D65B18B4275048D9004A9448 /* ClientRegistration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65B18B3275048D9004A9448 /* ClientRegistration.swift */; };
|
||||||
D65B18B627504920004A9448 /* FervorController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65B18B527504920004A9448 /* FervorController.swift */; };
|
D65B18B627504920004A9448 /* FervorController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65B18B527504920004A9448 /* FervorController.swift */; };
|
||||||
|
@ -116,6 +117,7 @@
|
||||||
/* End PBXCopyFilesBuildPhase section */
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXFileReference 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>"; };
|
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>"; };
|
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>"; };
|
D65B18B527504920004A9448 /* FervorController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FervorController.swift; sourceTree = "<group>"; };
|
||||||
|
@ -324,6 +326,7 @@
|
||||||
D68B303527907D9200E8B3FA /* ExcerptGenerator.swift */,
|
D68B303527907D9200E8B3FA /* ExcerptGenerator.swift */,
|
||||||
D68B304127932ED500E8B3FA /* UserActivities.swift */,
|
D68B304127932ED500E8B3FA /* UserActivities.swift */,
|
||||||
D68408EE2794808E00E327D2 /* Preferences.swift */,
|
D68408EE2794808E00E327D2 /* Preferences.swift */,
|
||||||
|
D608238C27DE729E00D7D5F9 /* ItemListType.swift */,
|
||||||
D6A8A33527766E9300CCEC72 /* CoreData */,
|
D6A8A33527766E9300CCEC72 /* CoreData */,
|
||||||
D65B18AF2750468B004A9448 /* Screens */,
|
D65B18AF2750468B004A9448 /* Screens */,
|
||||||
D6C687F7272CD27700874C10 /* Assets.xcassets */,
|
D6C687F7272CD27700874C10 /* Assets.xcassets */,
|
||||||
|
@ -632,6 +635,7 @@
|
||||||
files = (
|
files = (
|
||||||
D6A8A33427766C2800CCEC72 /* PersistentContainer.swift in Sources */,
|
D6A8A33427766C2800CCEC72 /* PersistentContainer.swift in Sources */,
|
||||||
D6E24357278B96E40005E546 /* Feed+CoreDataClass.swift in Sources */,
|
D6E24357278B96E40005E546 /* Feed+CoreDataClass.swift in Sources */,
|
||||||
|
D608238D27DE729E00D7D5F9 /* ItemListType.swift in Sources */,
|
||||||
D65B18B627504920004A9448 /* FervorController.swift in Sources */,
|
D65B18B627504920004A9448 /* FervorController.swift in Sources */,
|
||||||
D68B304227932ED500E8B3FA /* UserActivities.swift in Sources */,
|
D68B304227932ED500E8B3FA /* UserActivities.swift in Sources */,
|
||||||
D6C687EC272CD27600874C10 /* AppDelegate.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 {
|
switch activity.activityType {
|
||||||
case NSUserActivity.readUnreadType:
|
case NSUserActivity.readUnreadType:
|
||||||
split.selectHomeItem(.unread)
|
split.showItemList(.unread)
|
||||||
case NSUserActivity.readAllType:
|
case NSUserActivity.readAllType:
|
||||||
split.selectHomeItem(.all)
|
split.showItemList(.all)
|
||||||
case NSUserActivity.readFeedType:
|
case NSUserActivity.readFeedType:
|
||||||
guard let feedID = activity.feedID() else {
|
guard let feedID = activity.feedID() else {
|
||||||
break
|
break
|
||||||
|
@ -129,7 +129,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||||
let req = Feed.fetchRequest()
|
let req = Feed.fetchRequest()
|
||||||
req.predicate = NSPredicate(format: "id = %@", feedID)
|
req.predicate = NSPredicate(format: "id = %@", feedID)
|
||||||
if let feed = try? fervorController.persistentContainer.viewContext.fetch(req).first {
|
if let feed = try? fervorController.persistentContainer.viewContext.fetch(req).first {
|
||||||
split.selectHomeItem(.feed(feed))
|
split.showItemList(.feed(feed))
|
||||||
}
|
}
|
||||||
case NSUserActivity.readGroupType:
|
case NSUserActivity.readGroupType:
|
||||||
guard let groupID = activity.groupID() else {
|
guard let groupID = activity.groupID() else {
|
||||||
|
@ -138,7 +138,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||||
let req = Group.fetchRequest()
|
let req = Group.fetchRequest()
|
||||||
req.predicate = NSPredicate(format: "id = %@", groupID)
|
req.predicate = NSPredicate(format: "id = %@", groupID)
|
||||||
if let group = try? fervorController.persistentContainer.viewContext.fetch(req).first {
|
if let group = try? fervorController.persistentContainer.viewContext.fetch(req).first {
|
||||||
split.selectHomeItem(.group(group))
|
split.showItemList(.group(group))
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
|
|
|
@ -54,7 +54,7 @@ class AppSplitViewController: UISplitViewController {
|
||||||
setViewController(nav, for: .compact)
|
setViewController(nav, for: .compact)
|
||||||
}
|
}
|
||||||
|
|
||||||
func selectHomeItem(_ item: HomeViewController.Item) {
|
func showItemList(_ type: ItemListType) {
|
||||||
let column: Column
|
let column: Column
|
||||||
if traitCollection.horizontalSizeClass == .compact {
|
if traitCollection.horizontalSizeClass == .compact {
|
||||||
column = .compact
|
column = .compact
|
||||||
|
@ -63,7 +63,7 @@ class AppSplitViewController: UISplitViewController {
|
||||||
}
|
}
|
||||||
let nav = viewController(for: column) as! UINavigationController
|
let nav = viewController(for: column) as! UINavigationController
|
||||||
let home = nav.viewControllers.first! as! HomeViewController
|
let home = nav.viewControllers.first! as! HomeViewController
|
||||||
home.selectItem(item)
|
home.selectItem(type)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ class HomeViewController: UIViewController {
|
||||||
var enableStretchyMenu = true
|
var enableStretchyMenu = true
|
||||||
|
|
||||||
private var collectionView: UICollectionView!
|
private var collectionView: UICollectionView!
|
||||||
private var dataSource: UICollectionViewDiffableDataSource<Section, Item>!
|
private var dataSource: UICollectionViewDiffableDataSource<Section, ItemListType>!
|
||||||
private var groupResultsController: NSFetchedResultsController<Group>!
|
private var groupResultsController: NSFetchedResultsController<Group>!
|
||||||
private var feedResultsController: NSFetchedResultsController<Feed>!
|
private var feedResultsController: NSFetchedResultsController<Feed>!
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ class HomeViewController: UIViewController {
|
||||||
|
|
||||||
dataSource = createDataSource()
|
dataSource = createDataSource()
|
||||||
|
|
||||||
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
|
var snapshot = NSDiffableDataSourceSnapshot<Section, ItemListType>()
|
||||||
snapshot.appendSections([.all, .groups, .feeds])
|
snapshot.appendSections([.all, .groups, .feeds])
|
||||||
snapshot.appendItems([.unread, .all], toSection: .all)
|
snapshot.appendItems([.unread, .all], toSection: .all)
|
||||||
dataSource.apply(snapshot, animatingDifferences: false)
|
dataSource.apply(snapshot, animatingDifferences: false)
|
||||||
|
@ -116,14 +116,14 @@ class HomeViewController: UIViewController {
|
||||||
dataSource.apply(snapshot)
|
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 sectionHeaderCell = UICollectionView.SupplementaryRegistration<UICollectionViewListCell>(elementKind: UICollectionView.elementKindSectionHeader) { supplementaryView, elementKind, indexPath in
|
||||||
let section = self.dataSource.sectionIdentifier(for: indexPath.section)!
|
let section = self.dataSource.sectionIdentifier(for: indexPath.section)!
|
||||||
var config = supplementaryView.defaultContentConfiguration()
|
var config = supplementaryView.defaultContentConfiguration()
|
||||||
config.text = section.title
|
config.text = section.title
|
||||||
supplementaryView.contentConfiguration = config
|
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()
|
var config = UIListContentConfiguration.valueCell()
|
||||||
config.text = item.title
|
config.text = item.title
|
||||||
if let req = item.countFetchRequest,
|
if let req = item.countFetchRequest,
|
||||||
|
@ -135,7 +135,7 @@ class HomeViewController: UIViewController {
|
||||||
|
|
||||||
cell.accessories = [.disclosureIndicator()]
|
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)
|
return collectionView.dequeueConfiguredReusableCell(using: listCell, for: indexPath, item: item)
|
||||||
}
|
}
|
||||||
dataSource.supplementaryViewProvider = { collectionView, elementKind, indexPath in
|
dataSource.supplementaryViewProvider = { collectionView, elementKind, indexPath in
|
||||||
|
@ -206,26 +206,26 @@ class HomeViewController: UIViewController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func itemsViewController(for item: Item) -> ItemsViewController {
|
private func itemsViewController(for item: ItemListType) -> ItemsViewController {
|
||||||
let vc = ItemsViewController(fetchRequest: item.idFetchRequest, fervorController: fervorController)
|
let vc = ItemsViewController(type: item, fervorController: fervorController)
|
||||||
vc.title = item.title
|
|
||||||
vc.delegate = itemsDelegate
|
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
|
return vc
|
||||||
}
|
}
|
||||||
|
|
||||||
func selectItem(_ item: Item) {
|
func selectItem(_ item: ItemListType) {
|
||||||
navigationController!.popToRootViewController(animated: false)
|
guard let navigationController = navigationController else {
|
||||||
navigationController!.pushViewController(itemsViewController(for: item), animated: false)
|
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 {
|
extension HomeViewController: NSFetchedResultsControllerDelegate {
|
||||||
|
|
|
@ -18,20 +18,32 @@ class ItemsViewController: UIViewController {
|
||||||
weak var delegate: ItemsViewControllerDelegate?
|
weak var delegate: ItemsViewControllerDelegate?
|
||||||
|
|
||||||
let fervorController: FervorController
|
let fervorController: FervorController
|
||||||
let fetchRequest: NSFetchRequest<NSManagedObjectID>
|
let type: ItemListType
|
||||||
|
private let fetchRequest: NSFetchRequest<NSManagedObjectID>
|
||||||
|
|
||||||
private var collectionView: UICollectionView!
|
private var collectionView: UICollectionView!
|
||||||
private var dataSource: UICollectionViewDiffableDataSource<Section, NSManagedObjectID>!
|
private var dataSource: UICollectionViewDiffableDataSource<Section, NSManagedObjectID>!
|
||||||
|
|
||||||
private var batchUpdates: [() -> Void] = []
|
private var batchUpdates: [() -> Void] = []
|
||||||
|
|
||||||
init(fetchRequest: NSFetchRequest<NSManagedObjectID>, fervorController: FervorController) {
|
init(type: ItemListType, fervorController: FervorController) {
|
||||||
precondition(fetchRequest.entityName == "Item")
|
|
||||||
|
|
||||||
self.fervorController = fervorController
|
self.fervorController = fervorController
|
||||||
self.fetchRequest = fetchRequest
|
self.type = type
|
||||||
|
self.fetchRequest = type.idFetchRequest
|
||||||
|
|
||||||
super.init(nibName: nil, bundle: nil)
|
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) {
|
required init?(coder: NSCoder) {
|
||||||
|
|
Loading…
Reference in New Issue