From 33ad637fc051ec555a5be9f7c5cb95cd5ea3782a Mon Sep 17 00:00:00 2001 From: Miltiadis Vasilakis Date: Mon, 8 Jan 2024 17:21:12 +0200 Subject: [PATCH] Improve DetailCoordinator presented item replacement for multiple items --- .../Architecture/Coordinator.swift | 2 +- Zotero/Scenes/Detail/DetailCoordinator.swift | 24 ++++++++++++----- .../Views/NavigationViewController.swift | 26 +++++++++++++++++-- 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/Zotero/Controllers/Architecture/Coordinator.swift b/Zotero/Controllers/Architecture/Coordinator.swift index e0c8f1725..645b0715c 100644 --- a/Zotero/Controllers/Architecture/Coordinator.swift +++ b/Zotero/Controllers/Architecture/Coordinator.swift @@ -16,7 +16,7 @@ enum SourceView { protocol Coordinator: AnyObject { var parentCoordinator: Coordinator? { get } var childCoordinators: [Coordinator] { get set } - var navigationController: UINavigationController? { get } + var navigationController: UINavigationController? { get set } func start(animated: Bool) func childDidFinish(_ child: Coordinator) diff --git a/Zotero/Scenes/Detail/DetailCoordinator.swift b/Zotero/Scenes/Detail/DetailCoordinator.swift index 091f916ac..afde42ac4 100644 --- a/Zotero/Scenes/Detail/DetailCoordinator.swift +++ b/Zotero/Scenes/Detail/DetailCoordinator.swift @@ -290,10 +290,10 @@ final class DetailCoordinator: Coordinator { navigationController.present(controller, animated: true, completion: nil) } - func createPDFController(key: String, parentKey: String?, library: Library, url: URL, page: Int? = nil, preselectedAnnotationKey: String? = nil) -> NavigationViewController { - let navigationController = NavigationViewController() + func createPDFController(key: String, parentKey: String?, library: Library, url: URL, page: Int? = nil, preselectedAnnotationKey: String? = nil) -> DetailNavigationViewController { + let navigationController = DetailNavigationViewController() navigationController.modalPresentationStyle = .fullScreen - + let coordinator = PDFCoordinator( key: key, parentKey: parentKey, @@ -304,6 +304,7 @@ final class DetailCoordinator: Coordinator { navigationController: navigationController, controllers: controllers ) + navigationController.coordinator = coordinator coordinator.parentCoordinator = self childCoordinators.append(coordinator) coordinator.start(animated: false) @@ -315,10 +316,14 @@ final class DetailCoordinator: Coordinator { guard let navigationController else { return } controllers.userControllers?.openItemsController.open(.pdf(libraryId: library.identifier, key: key), for: sessionIdentifier) - let viewControllerProvider: () -> UIViewController = { + let viewControllerProvider: () -> DetailNavigationViewController = { self.createPDFController(key: key, parentKey: parentKey, library: library, url: url) } if let presentedViewController = navigationController.presentedViewController { + if let presentedDetailNavigationController = presentedViewController as? DetailNavigationViewController { + presentedDetailNavigationController.replaceContents(with: viewControllerProvider(), animated: false) + return + } guard let window = presentedViewController.view.window else { return } show(viewControllerProvider: viewControllerProvider, by: navigationController, in: window, animated: false) return @@ -471,8 +476,8 @@ extension DetailCoordinator: DetailItemsCoordinatorDelegate { tags: [Tag], title: NoteEditorState.TitleData?, saveCallback: @escaping NoteEditorSaveCallback - ) -> NavigationViewController { - let navigationController = NavigationViewController() + ) -> DetailNavigationViewController { + let navigationController = DetailNavigationViewController() navigationController.modalPresentationStyle = .fullScreen navigationController.isModalInPresentation = true @@ -487,6 +492,7 @@ extension DetailCoordinator: DetailItemsCoordinatorDelegate { sessionIdentifier: sessionIdentifier, controllers: controllers ) + navigationController.coordinator = coordinator coordinator.parentCoordinator = self childCoordinators.append(coordinator) coordinator.start(animated: false) @@ -947,10 +953,14 @@ extension DetailCoordinator: DetailNoteEditorCoordinatorDelegate { controllers.userControllers?.openItemsController.open(.note(libraryId: library.identifier, key: key), for: sessionIdentifier) } - let viewControllerProvider: () -> UIViewController = { + let viewControllerProvider: () -> DetailNavigationViewController = { self.createNoteController(library: library, kind: kind, text: text, tags: tags, title: title, saveCallback: amendedSaveCallback) } if let presentedViewController = navigationController.presentedViewController { + if let presentedDetailNavigationController = presentedViewController as? DetailNavigationViewController { + presentedDetailNavigationController.replaceContents(with: viewControllerProvider(), animated: false) + return + } guard let window = presentedViewController.view.window else { return } show(viewControllerProvider: viewControllerProvider, by: navigationController, in: window, animated: false) return diff --git a/Zotero/Scenes/General/Views/NavigationViewController.swift b/Zotero/Scenes/General/Views/NavigationViewController.swift index bbc6ef27c..de164f285 100644 --- a/Zotero/Scenes/General/Views/NavigationViewController.swift +++ b/Zotero/Scenes/General/Views/NavigationViewController.swift @@ -13,10 +13,32 @@ class NavigationViewController: UINavigationController { var statusBarVisible: Bool = true override var prefersStatusBarHidden: Bool { - return !self.statusBarVisible + return !statusBarVisible } deinit { - self.dismissHandler?() + dismissHandler?() + } +} + +class DetailNavigationViewController: NavigationViewController { + weak var coordinator: Coordinator? + public func replaceContents(with replacement: DetailNavigationViewController, animated: Bool) { + // Set replacement properties to self. + // Swap coordinators and dismiss handlers, so that the original coordinator is properly deinitialized, along with the original view controllers. + // Swap also the navigation controller property of the two coordinators. + // Store original + let originalCoordinator = coordinator + let originalDismissHandler = dismissHandler + // Swap replacement to original + coordinator = replacement.coordinator + coordinator?.navigationController = self + dismissHandler = replacement.dismissHandler + statusBarVisible = replacement.statusBarVisible + setViewControllers(replacement.viewControllers, animated: animated) + // Swap original to replacement + replacement.coordinator = originalCoordinator + replacement.coordinator?.navigationController = replacement + replacement.dismissHandler = originalDismissHandler } }