diff --git a/MVMCoreUI/Atomic/Protocols/PageProtocol.swift b/MVMCoreUI/Atomic/Protocols/PageProtocol.swift index c96742a4..8cd8bf34 100644 --- a/MVMCoreUI/Atomic/Protocols/PageProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/PageProtocol.swift @@ -10,16 +10,6 @@ import Foundation public protocol PageProtocol { var pageModel: PageModelProtocol? { get set } - - /// Sets the navigationBar property of the pageModel and attempts to refresh the ui. - mutating func updateNavigationBar(with model: NavigationItemModelProtocol & MoleculeModelProtocol) -} - -extension PageProtocol { - mutating public func updateNavigationBar(with model: NavigationItemModelProtocol & MoleculeModelProtocol) { - pageModel?.navigationBar = model - (self as? NavigationBarRefreshProtocol)?.refreshNavigationUI() - } } /// A protocol to inform that we should refresh the navigation bar ui. @@ -32,12 +22,13 @@ public extension UINavigationBar { /// Convenience function to refresh the navigation bar ui. @objc static func refreshNavigationUI(for viewController: UIViewController) { guard let model = (viewController as? PageProtocol)?.pageModel?.navigationBar else { return } - if let manager = ((viewController as? MVMCoreViewManagerViewControllerProtocol)?.manager as? NavigationBarRefreshProtocol) { - // Go through the manager if possible. - manager.refreshNavigationUI() - } else if let navigationController = viewController.navigationController { + if let navigationController = viewController.navigationController { NavigationController.setNavigationItem(navigationController: navigationController, navigationItemModel: model, viewController: viewController) - MVMCoreUISplitViewController.setNavigationBarUI(for: viewController, navigationController: navigationController, navigationItemModel: model, leftPanelAccessible: (viewController as? MVMCoreUIDetailViewProtocol)?.isLeftPanelAccessible?(), rightPanelAccessible: (viewController as? MVMCoreUIDetailViewProtocol)?.isRightPanelAccessible?()) + MVMCoreUISplitViewController.setNavigationBarUI(for: viewController, navigationController: navigationController, navigationItemModel: model) + } + if let manager = ((viewController as? MVMCoreViewManagerViewControllerProtocol)?.manager as? NavigationBarRefreshProtocol) { + // Refresh the manager if possible. + manager.refreshNavigationUI() } } } diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index a751f2b1..e7563faa 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -119,14 +119,15 @@ import UIKit MVMCoreDispatchUtility.performBlock(onMainThread: { self.handleNewDataAndUpdateUI() - // Update navigation bar if showing. if MVMCoreUIUtility.getCurrentVisibleController() == self { - if let manager = self.manager { - // Let manager handle - manager.refreshNavigationUI() - } else { - self.setNavigationBar() - } + // Update navigation bar if showing. + self.setNavigationBar() + self.manager?.refreshNavigationUI() + } + // Update splitview properties + if self == MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() { + MVMCoreUISplitViewController.main()?.setBottomProgressBarProgress(self.bottomProgress() ?? 0) + self.updateTabBar() } }) } catch { @@ -140,7 +141,7 @@ import UIKit pageType = loadObject.pageType self.loadObject = loadObject - // Verifies all modules needed are loaded. TODO: change to ViewController + // Verifies all modules needed are loaded. guard ViewController.verifyRequiredModulesLoaded(for: loadObject, error: error) else { return false } // Parse the model for the page. @@ -247,7 +248,7 @@ import UIKit } //-------------------------------------------------- - // MARK: - Navigation Item (Move to model base) + // MARK: - Navigation Item //-------------------------------------------------- open func getNavigationModel() -> NavigationItemModelProtocol? { @@ -271,61 +272,16 @@ import UIKit /// Sets the appearance of the navigation bar based on the model. open func setNavigationBar() { - let viewController = manager ?? self guard let navigationItemModel = getNavigationModel(), - let navigationController = viewController.navigationController else { + let navigationController = navigationController else { MVMCoreUISession.sharedGlobal()?.splitViewController?.parent?.setNeedsStatusBarAppearanceUpdate() return } // Utilize helper function to set the split view and navigation item state. - MVMCoreUISplitViewController.setNavigationBarUI(for: viewController, navigationController: navigationController, navigationItemModel: navigationItemModel, leftPanelAccessible: isMasterInitiallyAccessible(), rightPanelAccessible: isSupportInitiallyAccessible(), progress: bottomProgress() ?? 0) + MVMCoreUISplitViewController.setNavigationBarUI(for: self, navigationController: navigationController, navigationItemModel: navigationItemModel) } - // Eventually will be moved to server - open func isMasterInitiallyAccessible() -> Bool { - if loadObject?.pageJSON?.boolForKey(KeyHideMainMenu) ?? false { - return false - } - return MVMCoreUISession.sharedGlobal()?.launchAppLoadedSuccessfully ?? false - } - - // Eventually will be moved to server - open func isSupportInitiallyAccessible() -> Bool { - if loadObject?.pageJSON?.boolForKey(KeyHideMainMenu) ?? false { - return false - } - return (MVMCoreUISession.sharedGlobal()?.launchAppLoadedSuccessfully ?? false) || showRightPanelForScreenBeforeLaunchApp() - } - - open func showRightPanelForScreenBeforeLaunchApp() -> Bool { - return loadObject?.pageJSON?.lenientBoolForKey("showRightPanel") ?? false - } - - // Eventually will be moved to separate button in navigation item model - open func isOverridingRightButton() -> Bool { - guard let rightPanelLink = loadObject?.pageJSON?.optionalDictionaryForKey("rightPanelButtonLink") - else { return false } - MVMCoreActionHandler.shared()?.handleAction(with: rightPanelLink, additionalData: nil, delegateObject: delegateObject()) - return true - } - - // Eventually will be moved to separate button in navigation item model - open func isOverridingLeftButton() -> Bool { - guard let leftPanelLink = loadObject?.pageJSON?.optionalDictionaryForKey("leftPanelButtonLink") - else { return false } - MVMCoreActionHandler.shared()?.handleAction(with: leftPanelLink, additionalData: nil, delegateObject: delegateObject()) - return true - } - - // Eventually will be moved to Model - open func bottomProgress() -> Float? { - guard let progressString = loadObject?.pageJSON?.optionalStringForKey(KeyProgressPercent), - let progress = Float(progressString) - else { return nil } - - return progress / Float(100) - } //-------------------------------------------------- // MARK: - TabBar //-------------------------------------------------- @@ -408,14 +364,15 @@ import UIKit } open func pageShown() { - // Update the navigation bar ui when view is appearing. + // Update split view properties if this is the current detail controller. if self == MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() { MVMCoreUISplitViewController.main()?.setupPanels() + MVMCoreUISplitViewController.main()?.setBottomProgressBarProgress(bottomProgress() ?? 0) + updateTabBar() } - setNavigationBar() - // Update tab if needed. - updateTabBar() + // Update the navigation bar ui when view is appearing. + setNavigationBar() // Track. MVMCoreUISession.sharedGlobal()?.currentPageType = pageType @@ -536,6 +493,51 @@ import UIKit setNavigationBar() } + public func isLeftPanelAccessible() -> Bool { + // TODO: Remove when hamburger menu is fully phased out. + if loadObject?.pageJSON?.boolForKey(KeyHideMainMenu) ?? false { + return false + } + return MVMCoreUISession.sharedGlobal()?.launchAppLoadedSuccessfully ?? false + } + + public func isRightPanelAccessible() -> Bool { + // TODO: Remove when FAB is 100%. + if loadObject?.pageJSON?.boolForKey(KeyHideMainMenu) ?? false { + return false + } + return (MVMCoreUISession.sharedGlobal()?.launchAppLoadedSuccessfully ?? false) || showRightPanelForScreenBeforeLaunchApp() + } + + open func showRightPanelForScreenBeforeLaunchApp() -> Bool { + return loadObject?.pageJSON?.lenientBoolForKey("showRightPanel") ?? false + } + + // TODO: make molecular + open func isOverridingRightButton() -> Bool { + guard let rightPanelLink = loadObject?.pageJSON?.optionalDictionaryForKey("rightPanelButtonLink") + else { return false } + MVMCoreActionHandler.shared()?.handleAction(with: rightPanelLink, additionalData: nil, delegateObject: delegateObject()) + return true + } + + // TODO: make molecular + open func isOverridingLeftButton() -> Bool { + guard let leftPanelLink = loadObject?.pageJSON?.optionalDictionaryForKey("leftPanelButtonLink") + else { return false } + MVMCoreActionHandler.shared()?.handleAction(with: leftPanelLink, additionalData: nil, delegateObject: delegateObject()) + return true + } + + // Eventually will be moved to Model + open func bottomProgress() -> Float? { + guard let progressString = loadObject?.pageJSON?.optionalStringForKey(KeyProgressPercent), + let progress = Float(progressString) + else { return nil } + + return progress / Float(100) + } + //-------------------------------------------------- // MARK: - UITextFieldDelegate //-------------------------------------------------- diff --git a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift index 2f452647..eb22eccb 100644 --- a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift +++ b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift @@ -10,32 +10,29 @@ import Foundation public extension MVMCoreUISplitViewController { - /// Convenience function. Sets the navigation and split view properties for the view controller. Optional parameters use current value if not set. - static func setNavigationBarUI(for viewController: UIViewController, navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol, leftPanelAccessible: Bool? = nil, rightPanelAccessible: Bool? = nil, progress: Float? = nil) { + /// Convenience function. Sets the navigation and split view properties for the view controller. Panel access is determined if view controller is a detail view protocol. + static func setNavigationBarUI(for viewController: UIViewController, navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol) { guard let splitView = MVMCoreUISplitViewController.main(), navigationController == splitView.navigationController, navigationController.topViewController == viewController else { - NavigationController.setNavigationBarUI(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: viewController) - return + /// Not the split view navigation controller, skip split functions. + NavigationController.setNavigationBarUI(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: viewController) + return } - splitView.set(for: viewController, navigationController: navigationController, navigationItemModel: navigationItemModel, leftPanelAccessible: leftPanelAccessible, rightPanelAccessible: rightPanelAccessible, progress: progress) + splitView.set(for: viewController, navigationController: navigationController, navigationItemModel: navigationItemModel) } /// Sets the navigation item for the view controller based on the model and splitview controller - private func set(for viewController: UIViewController, navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol, leftPanelAccessible: Bool? = nil, rightPanelAccessible: Bool? = nil, progress: Float? = nil) { + private func set(for viewController: UIViewController, navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol) { NavigationController.setNavigationBarUI(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: viewController) - setLeftPanelIsAccessible(leftPanelAccessible ?? leftPanelIsAccessible, for: viewController, updateNavigationButtons: false) - setRightPanelIsAccessible(rightPanelAccessible ?? rightPanelIsAccessible, for: viewController, updateNavigationButtons: false) + setLeftPanelIsAccessible((viewController as? MVMCoreUIDetailViewProtocol)?.isLeftPanelAccessible?() ?? false, for: viewController, updateNavigationButtons: false) + setRightPanelIsAccessible((viewController as? MVMCoreUIDetailViewProtocol)?.isRightPanelAccessible?() ?? false, for: viewController, updateNavigationButtons: false) setLeftNavigationButtons(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: viewController) setRightNavigationButtons(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: viewController) setNavigationIconColor(navigationItemModel.tintColor.uiColor) - - if let progress = progress { - setBottomProgressBarProgress(progress) - } } /// Sets the left navigation items for the view controller based on model and splitview. @@ -107,21 +104,4 @@ public extension MVMCoreUISplitViewController { viewController.navigationItem.setRightBarButtonItems(rightItems.count > 0 ? rightItems : nil, animated: !DisableAnimations.boolValue) } - - // MARK: - Legacy Functions - /// Convenience setter for legacy files. Sets the navigation item for the view controller based on the json and splitview controller - @objc static func setNavigationBarUI(for viewController: UIViewController, navigationController: UINavigationController, navigationJSON: [String: Any], leftPanelAccessible: Bool, rightPanelAccessible: Bool, progress: NSNumber?) throws { - let delegate = (viewController as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject - guard let navigationItemModel = try MoleculeObjectMapping.shared()?.getMoleculeModelForJSON(navigationJSON, delegateObject: delegate) as? (MoleculeModelProtocol & NavigationItemModelProtocol) else { - throw ModelRegistry.Error.decoderOther(message: "Model not a bar model") - } - guard let splitView = MVMCoreUISplitViewController.main(), - navigationController == splitView.navigationController, - navigationController.topViewController == viewController else { - NavigationController.setNavigationBarUI(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: viewController) - return - } - let progress = progress?.floatValue - splitView.set(for: viewController, navigationController: navigationController, navigationItemModel: navigationItemModel, leftPanelAccessible: leftPanelAccessible, rightPanelAccessible: rightPanelAccessible, progress: progress) - } }