diff --git a/iOS/AppCoordinator.swift b/iOS/AppCoordinator.swift index 2c0627897..70eb0635f 100644 --- a/iOS/AppCoordinator.swift +++ b/iOS/AppCoordinator.swift @@ -34,12 +34,16 @@ class AppCoordinator: NSObject, UndoableCommandRunner { private var masterTimelineViewController: MasterTimelineViewController? private var detailViewController: DetailViewController? { - if let detailNavController = rootSplitViewController.viewControllers.last as? UINavigationController { + if let detailNavController = targetSplitForDetail().viewControllers.last as? UINavigationController { return detailNavController.topViewController as? DetailViewController } return nil } + private var isThreePane: Bool { + return rootSplitViewController.traitCollection.horizontalSizeClass == .regular + } + private let fetchAndMergeArticlesQueue = CoalescingQueue(name: "Fetch and Merge Articles", interval: 0.5) private var articleRowMap = [String: Int]() // articleID: rowIndex @@ -182,8 +186,7 @@ class AppCoordinator: NSObject, UndoableCommandRunner { return appDelegate.unreadCount > 0 } - init(_ rootSplitViewController: UISplitViewController) { - + override init() { super.init() for section in treeController.rootNode.childNodes { @@ -201,18 +204,19 @@ class AppCoordinator: NSObject, UndoableCommandRunner { NotificationCenter.default.addObserver(self, selector: #selector(userDefaultsDidChange(_:)), name: UserDefaults.didChangeNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(accountDidDownloadArticles(_:)), name: .AccountDidDownloadArticles, object: nil) - - self.rootSplitViewController = rootSplitViewController + } + + func start() -> UIViewController { + rootSplitViewController = UISplitViewController.template() rootSplitViewController.delegate = self masterNavigationController = (rootSplitViewController.viewControllers.first as! UINavigationController) masterNavigationController.delegate = self - masterFeedViewController = (masterNavigationController.topViewController as! MasterFeedViewController) + masterFeedViewController = UIStoryboard.main.instantiateController(ofType: MasterFeedViewController.self) masterFeedViewController.coordinator = self + masterNavigationController.pushViewController(masterFeedViewController, animated: false) - let systemMessageNavController = (rootSplitViewController.viewControllers.last as! UINavigationController) - systemMessageNavController.topViewController!.navigationItem.leftBarButtonItem = rootSplitViewController.displayModeButtonItem - + return rootSplitViewController } // MARK: Notifications @@ -422,7 +426,6 @@ class AppCoordinator: NSObject, UndoableCommandRunner { } func indexesForArticleIDs(_ articleIDs: Set) -> IndexSet { - var indexes = IndexSet() articleIDs.forEach { (articleID) in @@ -441,22 +444,21 @@ class AppCoordinator: NSObject, UndoableCommandRunner { masterTimelineViewController = UIStoryboard.main.instantiateController(ofType: MasterTimelineViewController.self) masterTimelineViewController!.coordinator = self currentMasterIndexPath = indexPath - masterNavigationController.pushViewController(masterTimelineViewController!, animated: true) + navControllerForTimeline().pushViewController(masterTimelineViewController!, animated: true) } func selectArticle(_ indexPath: IndexPath) { - if let detailNavigationController = rootSplitViewController.viewControllers.last as? UINavigationController, - let _ = detailNavigationController.topViewController as? DetailViewController { + if detailViewController != nil { currentArticleIndexPath = indexPath } else { - let detailNavigationController = UIStoryboard.main.instantiateViewController(identifier: "DetailNavigationController") as! UINavigationController - let detailViewController = detailNavigationController.topViewController as! DetailViewController + let targetSplit = targetSplitForDetail() + let detailViewController = UIStoryboard.main.instantiateController(ofType: DetailViewController.self) detailViewController.coordinator = self - detailViewController.navigationItem.leftBarButtonItem = rootSplitViewController.displayModeButtonItem + detailViewController.navigationItem.leftBarButtonItem = targetSplit.displayModeButtonItem detailViewController.navigationItem.leftItemsSupplementBackButton = true currentArticleIndexPath = indexPath // rootSplitViewController.toggleMasterView() - rootSplitViewController.showDetailViewController(detailNavigationController, sender: self) + targetSplit.showDetailViewController(detailViewController, sender: self) } } @@ -572,12 +574,11 @@ class AppCoordinator: NSObject, UndoableCommandRunner { extension AppCoordinator: UINavigationControllerDelegate { func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) { - if navigationController.viewControllers.count == 1 { - let systemMessageNavController = UIStoryboard.main.instantiateViewController(identifier: "SystemMessageNavigationController") as! UINavigationController - let systemMessageViewController = systemMessageNavController.topViewController as! SystemMessageViewController + if isThreePane && navigationController.viewControllers.count == 1 { + let systemMessageViewController = UIStoryboard.main.instantiateController(ofType: SystemMessageViewController.self) systemMessageViewController.navigationItem.leftBarButtonItem = rootSplitViewController.displayModeButtonItem systemMessageViewController.navigationItem.leftItemsSupplementBackButton = true - rootSplitViewController.showDetailViewController(systemMessageNavController, sender: self) + rootSplitViewController.showDetailViewController(systemMessageViewController, sender: self) } } @@ -817,4 +818,35 @@ private extension AppCoordinator { } + // MARK: Double Split + + func ensureDoubleSplit() -> UISplitViewController { + if let subSplit = rootSplitViewController.viewControllers.last as? UISplitViewController { + return subSplit + } + + let subSplit = UISplitViewController.template() + subSplit.delegate = self + subSplit.preferredPrimaryColumnWidthFraction = 0.5 + rootSplitViewController.showDetailViewController(subSplit, sender: self) + return subSplit + } + + func navControllerForTimeline() -> UINavigationController { + if isThreePane { + let subSplit = ensureDoubleSplit() + return subSplit.viewControllers.first as! UINavigationController + } else { + return masterNavigationController + } + } + + func targetSplitForDetail() -> UISplitViewController { + if isThreePane { + return ensureDoubleSplit() + } else { + return rootSplitViewController + } + } + } diff --git a/iOS/Base.lproj/Main.storyboard b/iOS/Base.lproj/Main.storyboard index f9b62e18d..53594f2ed 100644 --- a/iOS/Base.lproj/Main.storyboard +++ b/iOS/Base.lproj/Main.storyboard @@ -36,7 +36,7 @@ - + @@ -137,23 +137,7 @@ - - - - - - - - - - - - - - - - - + @@ -185,7 +169,7 @@ - + @@ -241,7 +225,7 @@ - + @@ -299,26 +283,6 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/iOS/Extensions/UISplitViewController-Extensions.swift b/iOS/Extensions/UISplitViewController-Extensions.swift index fc2ffb229..5badbaf34 100644 --- a/iOS/Extensions/UISplitViewController-Extensions.swift +++ b/iOS/Extensions/UISplitViewController-Extensions.swift @@ -13,7 +13,11 @@ extension UISplitViewController { static func template() -> UISplitViewController { let splitViewController = UISplitViewController() splitViewController.preferredDisplayMode = .allVisible - splitViewController.viewControllers = [UINavigationController()] + + let navController = UINavigationController() + navController.isToolbarHidden = false + splitViewController.viewControllers = [navController] + return splitViewController } diff --git a/iOS/SceneDelegate.swift b/iOS/SceneDelegate.swift index 283b16e84..3188b5279 100644 --- a/iOS/SceneDelegate.swift +++ b/iOS/SceneDelegate.swift @@ -11,14 +11,14 @@ import UIKit class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? - var coordinator: AppCoordinator? + var coordinator = AppCoordinator() // UIWindowScene delegate func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { window!.tintColor = AppAssets.netNewsWireBlueColor - coordinator = AppCoordinator(window!.rootViewController as! UISplitViewController) + window?.rootViewController = coordinator.start() // if let userActivity = connectionOptions.userActivities.first ?? session.stateRestorationActivity { // if !configure(window: window, with: userActivity) {