MFViewController Model

Dynamic Root Non Root navigation item
This commit is contained in:
Pfeil, Scott Robert 2020-10-07 15:36:02 -04:00
parent b44dcaa1fd
commit fc9272d0b7
9 changed files with 81 additions and 36 deletions

View File

@ -303,6 +303,7 @@
D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; };
D20C7009250BF99B0095B21C /* TopNotificationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20C7008250BF99B0095B21C /* TopNotificationModel.swift */; };
D20C700B250BFDE40095B21C /* MVMCoreUITopAlertView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20C700A250BFDE40095B21C /* MVMCoreUITopAlertView+Extension.swift */; };
D20F3B44252E00E4004B3F56 /* PageProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20F3B43252E00E4004B3F56 /* PageProtocol.swift */; };
D20FB165241A5D75004AFC3A /* NavigationItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20FB164241A5D75004AFC3A /* NavigationItemModel.swift */; };
D213347723843825008E41B3 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = D213347623843825008E41B3 /* Line.swift */; };
D21B7F602437C5BC00051ABF /* MoleculeStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21B7F5E2437C5BC00051ABF /* MoleculeStackView.swift */; };
@ -796,6 +797,7 @@
D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonView.swift; sourceTree = "<group>"; };
D20C7008250BF99B0095B21C /* TopNotificationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopNotificationModel.swift; sourceTree = "<group>"; };
D20C700A250BFDE40095B21C /* MVMCoreUITopAlertView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreUITopAlertView+Extension.swift"; sourceTree = "<group>"; };
D20F3B43252E00E4004B3F56 /* PageProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageProtocol.swift; sourceTree = "<group>"; };
D20FB164241A5D75004AFC3A /* NavigationItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationItemModel.swift; sourceTree = "<group>"; };
D213347623843825008E41B3 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = "<group>"; };
D21B7F5E2437C5BC00051ABF /* MoleculeStackView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeStackView.swift; sourceTree = "<group>"; };
@ -2077,6 +2079,7 @@
children = (
012A88C7238DB02000FE3DA1 /* MoleculeDelegateProtocol.swift */,
017BEB47236230DB0024EF95 /* MoleculeViewProtocol.swift */,
D20F3B43252E00E4004B3F56 /* PageProtocol.swift */,
012A88AC238C418100FE3DA1 /* TemplateProtocol.swift */,
D28BA7442481652D00B75CB8 /* TabBarProtocol.swift */,
011B58EE23A2AA850085F53C /* ModelProtocols */,
@ -2345,6 +2348,7 @@
525239C02407BCFF00454969 /* ListTwoColumnPriceDetailsModel.swift in Sources */,
D2E2A99A23D8D6B4000B42E6 /* HeadlineBodyButtonModel.swift in Sources */,
D202AFE6242A6A9C00E5BEDF /* UICollectionViewScrollPosition+Extension.swift in Sources */,
D20F3B44252E00E4004B3F56 /* PageProtocol.swift in Sources */,
8D084AD22410BF7600951227 /* ListOneColumnFullWidthTextBodyText.swift in Sources */,
94C0150C2421564A005811A9 /* ActionCollapseNotificationModel.swift in Sources */,
D2CAC7CB251104E100C75681 /* NotificationXButtonModel.swift in Sources */,

View File

@ -35,12 +35,12 @@ import Foundation
}
/// Convenience function for legacy classes
public func getMoleculeModelForJSON(_ json: [String: Any]) throws -> MoleculeModelProtocol? {
public func getMoleculeModelForJSON(_ json: [String: Any], delegateObject: DelegateObject? = nil) throws -> MoleculeModelProtocol? {
guard let moleculeName = json.optionalStringForKey(KeyMoleculeName),
let type = ModelRegistry.getType(for: moleculeName, with: MoleculeModelProtocol.self) else {
throw ModelRegistry.Error.decoderErrorModelNotMapped()
}
guard let model = try type.decode(jsonDict: json) as? MoleculeModelProtocol else {
guard let model = try type.decode(jsonDict: json, delegateObject: delegateObject) as? MoleculeModelProtocol else {
throw ModelRegistry.Error.decoderError
}
return model

View File

@ -8,25 +8,25 @@
import Foundation
public class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtocol {
public class var identifier: String {
open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtocol {
open class var identifier: String {
return "navigationBar"
}
public var title: String?
public var hidden: Bool
public var backgroundColor: Color?
public var tintColor: Color
public var line: LineModel?
public var hidesSystemBackButton = true
open var title: String?
open var hidden: Bool
open var backgroundColor: Color?
open var tintColor: Color
open var line: LineModel?
open var hidesSystemBackButton = true
/// If true, we add the button in the backButton property. If false we do not add the button. If nil, we add the button if the controller is not the bottom of the stack
public var alwaysShowBackButton: Bool?
public var backButton: (NavigationButtonModelProtocol & MoleculeModelProtocol)?
open var alwaysShowBackButton: Bool?
open var backButton: (NavigationButtonModelProtocol & MoleculeModelProtocol)?
public var additionalLeftButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]?
public var additionalRightButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]?
public var titleView: MoleculeModelProtocol?
open var additionalLeftButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]?
open var additionalRightButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]?
open var titleView: MoleculeModelProtocol?
public init() {
hidden = false
@ -44,8 +44,6 @@ public class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProt
case line
case alwaysShowBackButton
case backButton
case showLeftPanelButton
case showRightPanelButton
case additionalLeftButtons
case additionalRightButtons
case titleView

View File

@ -0,0 +1,28 @@
//
// PageProtocol.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 10/7/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
public protocol PageProtocol {
var pageModel: PageModelProtocol? { get set }
mutating func updateNavigation(with model: NavigationItemModelProtocol & MoleculeModelProtocol)
}
public extension PageProtocol where Self: UIViewController {
mutating func updateNavigation(with model: NavigationItemModelProtocol & MoleculeModelProtocol) {
pageModel?.navigationBar = model
if var manager = ((self as? MVMCoreViewManagerViewControllerProtocol)?.manager as? PageProtocol) {
// Go through the manager if possible.
manager.updateNavigation(with: model)
} else if let navigationController = navigationController {
NavigationController.setNavigationItem(navigationController: navigationController, navigationItemModel: model, viewController: self)
MVMCoreUISplitViewController.setNavigationBarUI(for: self, navigationController: navigationController, navigationItemModel: model, leftPanelAccessible: (self as? MVMCoreUIDetailViewProtocol)?.isLeftPanelAccessible?(), rightPanelAccessible: (self as? MVMCoreUIDetailViewProtocol)?.isRightPanelAccessible?())
}
}
}

View File

@ -23,7 +23,7 @@ public extension TemplateProtocol where Self: ViewController {
let decoder = JSONDecoder()
try decoder.add(delegateObject: delegateObjectIVar)
self.templateModel = try decodeTemplate(using: decoder, from: data)
self.pageModel = templateModel as? MVMControllerModelProtocol
self.model = templateModel as? MVMControllerModelProtocol
}
func decodeTemplate(using decoder: JSONDecoder, from data: Data) throws -> TemplateModel {

View File

@ -8,15 +8,23 @@
import UIKit
@objc open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMCoreViewManagerViewControllerProtocol, MoleculeDelegateProtocol, FormHolderProtocol, MVMCoreActionDelegateProtocol, MVMCoreLoadDelegateProtocol, UITextFieldDelegate, UITextViewDelegate, ObservingTextFieldDelegate, MVMCoreUIDetailViewProtocol {
@objc open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMCoreViewManagerViewControllerProtocol, MoleculeDelegateProtocol, FormHolderProtocol, MVMCoreActionDelegateProtocol, MVMCoreLoadDelegateProtocol, UITextFieldDelegate, UITextViewDelegate, ObservingTextFieldDelegate, MVMCoreUIDetailViewProtocol, PageProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
@objc public var pageType: String?
@objc public var loadObject: MVMCoreLoadObject?
public var pageModel: MVMControllerModelProtocol?
public var model: MVMControllerModelProtocol?
public var pageModel: PageModelProtocol? {
get {
return model
}
set {
model = newValue as? MVMControllerModelProtocol
}
}
/// Set if this page is containted in a manager.
public var manager: (UIViewController & MVMCoreViewManagerProtocol)?
@ -214,18 +222,18 @@ import UIKit
/// Creates a legacy navigation model.
open func createDefaultLegacyNavigationModel() -> NavigationItemModel {
let navigationModel = NavigationItemModel()
navigationModel.title = pageModel?.screenHeading
navigationModel.title = model?.screenHeading
return navigationModel
}
/// Processes any new data. Called after the page is loaded the first time and on response updates for this page,
open func handleNewData() {
if formValidator == nil {
let rules = pageModel?.formRules
let rules = model?.formRules
formValidator = FormValidator(rules)
}
if let backgroundColor = pageModel?.backgroundColor {
if let backgroundColor = model?.backgroundColor {
view.backgroundColor = backgroundColor.uiColor
}
@ -239,11 +247,11 @@ import UIKit
open func getNavigationModel() -> NavigationItemModelProtocol? {
// TODO: remove legacy. Temporary, convert legacy to navigation model.
if pageModel?.navigationBar == nil {
if model?.navigationBar == nil {
let navigationItem = createDefaultLegacyNavigationModel()
pageModel?.navigationBar = navigationItem
model?.navigationBar = navigationItem
}
return pageModel?.navigationBar
return model?.navigationBar
}
/// Sets the navigation item for this view controller.
@ -252,9 +260,6 @@ import UIKit
let navigationController = navigationController
else { return }
// We additionally want our left items
navigationItem.leftItemsSupplementBackButton = true
// Utilize helper function to set the navigation item state.
NavigationController.setNavigationItem(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: self)
}
@ -324,7 +329,7 @@ import UIKit
guard MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() == self else { return }
MVMCoreUISplitViewController.main()?.tabBar?.delegateObject = delegateObjectIVar
if let index = (pageModel as? TabPageModelProtocol)?.tabBarIndex {
if let index = (model as? TabPageModelProtocol)?.tabBarIndex {
MVMCoreUISplitViewController.main()?.tabBar?.highlightTab(at: index)
} else if let index = loadObject?.requestParameters?.actionMap?["tabBarIndex"] as? Int {
MVMCoreUISplitViewController.main()?.tabBar?.highlightTab(at: index)
@ -335,7 +340,7 @@ import UIKit
self.tabBarIndex = index
}
if let hidden = (pageModel as? TabPageModelProtocol)?.tabBarHidden {
if let hidden = (model as? TabPageModelProtocol)?.tabBarHidden {
MVMCoreUISplitViewController.main()?.updateTabBarShowing(!hidden)
} else if let hidden = loadObject?.requestParameters?.actionMap?["tabBarHidden"] as? Bool {
MVMCoreUISplitViewController.main()?.updateTabBarShowing(!hidden)
@ -594,6 +599,6 @@ import UIKit
//--------------------------------------------------
func executeBehaviors<T>(_ behaviorBlock:(_ behavior:T)->Void) {
pageModel?.behaviors?.compactMap({ $0 as? T }).forEach { behaviorBlock($0) }
model?.behaviors?.compactMap({ $0 as? T }).forEach { behaviorBlock($0) }
}
}

View File

@ -48,6 +48,7 @@ import UIKit
viewController.navigationItem.title = navigationItemModel.title
viewController.navigationItem.accessibilityLabel = navigationItemModel.title
viewController.navigationItem.hidesBackButton = navigationItemModel.hidesSystemBackButton
viewController.navigationItem.leftItemsSupplementBackButton = !navigationItemModel.hidesSystemBackButton
setNavigationButtons(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: viewController)
setNavigationTitleView(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: viewController)
}
@ -97,7 +98,8 @@ import UIKit
/// Convenience setter for legacy files
public static func setNavigationItem(navigationController: UINavigationController, navigationJSON: [String: Any], viewController: UIViewController) throws {
guard let barModel = try MoleculeObjectMapping.shared()?.getMoleculeModelForJSON(navigationJSON) as? (MoleculeModelProtocol & NavigationItemModelProtocol) else {
let delegate = (viewController as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject
guard let barModel = try MoleculeObjectMapping.shared()?.getMoleculeModelForJSON(navigationJSON, delegateObject: delegate) as? (MoleculeModelProtocol & NavigationItemModelProtocol) else {
throw ModelRegistry.Error.decoderOther(message: "Model not a bar model")
}
setNavigationItem(navigationController: navigationController, navigationItemModel: barModel, viewController: viewController)
@ -105,7 +107,8 @@ import UIKit
/// Convenience setter for legacy files
public static func setNavigationBarUI(navigationController: UINavigationController, navigationJSON: [String: Any], viewController: UIViewController) throws {
guard let barModel = try MoleculeObjectMapping.shared()?.getMoleculeModelForJSON(navigationJSON) as? (MoleculeModelProtocol & NavigationItemModelProtocol) else {
let delegate = (viewController as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject
guard let barModel = try MoleculeObjectMapping.shared()?.getMoleculeModelForJSON(navigationJSON, delegateObject: delegate) as? (MoleculeModelProtocol & NavigationItemModelProtocol) else {
throw ModelRegistry.Error.decoderOther(message: "Model not a bar model")
}
setNavigationBarUI(navigationController: navigationController, navigationItemModel: barModel, viewController: viewController)

View File

@ -15,6 +15,12 @@ NS_ASSUME_NONNULL_BEGIN
@optional
/// Returns if the left panel should be accessible.
- (BOOL)isLeftPanelAccessible;
/// Returns if the right panel should be accessible.
- (BOOL)isRightPanelAccessible;
- (void)panelWillAppear:(nonnull NSObject <MVMCoreUIPanelProtocol>*)panel;
- (void)panelWillAppear:(nonnull NSObject <MVMCoreUIPanelProtocol>*)panel overtakingDetail:(BOOL)willOvertake;
- (void)panelDidAppear:(nonnull NSObject <MVMCoreUIPanelProtocol>*)panel;

View File

@ -111,7 +111,8 @@ public extension MVMCoreUISplitViewController {
// 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 {
guard let navigationItemModel = try MoleculeObjectMapping.shared()?.getMoleculeModelForJSON(navigationJSON) as? (MoleculeModelProtocol & NavigationItemModelProtocol) else {
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(),