Navigation model

This commit is contained in:
Pfeil, Scott Robert 2020-03-16 09:15:49 -04:00
parent 621a878756
commit 87fb08fb72
11 changed files with 212 additions and 90 deletions

View File

@ -196,6 +196,7 @@
D22D1F47220496A30077CEC0 /* MVMCoreUISwitch.m in Sources */ = {isa = PBXBuildFile; fileRef = D22D1F45220496A30077CEC0 /* MVMCoreUISwitch.m */; };
D22D1F562204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D22D1F542204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
D22D1F572204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D22D1F552204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m */; };
D22D8393241C27B100D3DF69 /* TemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22D8392241C27B100D3DF69 /* TemplateModel.swift */; };
D243859923A16B1800332775 /* Container.swift in Sources */ = {isa = PBXBuildFile; fileRef = D243859823A16B1800332775 /* Container.swift */; };
D256E9932412880000360572 /* Header.swift in Sources */ = {isa = PBXBuildFile; fileRef = D256E9922412880000360572 /* Header.swift */; };
D260105323CEA61600764D80 /* ToggleModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D260105223CEA61600764D80 /* ToggleModel.swift */; };
@ -563,6 +564,7 @@
D22D1F45220496A30077CEC0 /* MVMCoreUISwitch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUISwitch.m; sourceTree = "<group>"; };
D22D1F542204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIStackableViewController.h; sourceTree = "<group>"; };
D22D1F552204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIStackableViewController.m; sourceTree = "<group>"; };
D22D8392241C27B100D3DF69 /* TemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateModel.swift; sourceTree = "<group>"; };
D243859823A16B1800332775 /* Container.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container.swift; sourceTree = "<group>"; };
D256E9922412880000360572 /* Header.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Header.swift; sourceTree = "<group>"; };
D260105223CEA61600764D80 /* ToggleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToggleModel.swift; sourceTree = "<group>"; };
@ -1237,6 +1239,7 @@
isa = PBXGroup;
children = (
012A88AC238C418100FE3DA1 /* TemplateProtocol.swift */,
D22D8392241C27B100D3DF69 /* TemplateModel.swift */,
014AA72823C5059B006F3E93 /* StackPageTemplateModel.swift */,
D2A5146022121FBF00345BFB /* MoleculeStackTemplate.swift */,
942C378D2412F5B60066E45E /* ModalMoleculeStackTemplate.swift */,
@ -2033,6 +2036,7 @@
D29DF26C21E6AA0B003B2FB9 /* FLAnimatedImage.m in Sources */,
D28A839123CD4FD400DFE4FC /* CornerLabelsModel.swift in Sources */,
012A88F123985E0100FE3DA1 /* Color.swift in Sources */,
D22D8393241C27B100D3DF69 /* TemplateModel.swift in Sources */,
012A889C23889E8400FE3DA1 /* TemplateModelProtocol.swift in Sources */,
D29770FC21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m in Sources */,
52267A0723FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift in Sources */,

View File

@ -32,26 +32,6 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC
private var previousScreenSize = CGSize.zero
public var selectedField: UIView?
public var masterShouldBeAccessible: Bool = false {
didSet {
if let manager = manager as? MFViewController {
manager.masterShouldBeAccessible = masterShouldBeAccessible
} else if MVMCoreUISplitViewController.main()?.getCurrentVisibleController() == self {
MVMCoreUISplitViewController.main()?.setLeftPanelIsAccessible(masterShouldBeAccessible, for: self)
}
}
}
public var supportShouldBeAccessible: Bool = false {
didSet {
if let manager = manager as? MFViewController {
manager.supportShouldBeAccessible = supportShouldBeAccessible
} else if MVMCoreUISplitViewController.main()?.getCurrentVisibleController() == self {
MVMCoreUISplitViewController.main()?.setRightPanelIsAccessible(supportShouldBeAccessible, for: self)
}
}
}
/// Checks if the screen width has changed
open func screenSizeChanged() -> Bool {
@ -143,6 +123,24 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC
}
open func parsePageJSON() throws {
if pageModel?.navigationItem == nil {
let navigationModel = NavigationItemModel()
if navigationModel.title == nil {
navigationModel.title = pageModel?.screenHeading
}
if navigationModel.showLeftPanelButton == nil {
navigationModel.showLeftPanelButton = isMasterInitiallyAccessible()
}
if navigationModel.showRightPanelButton == nil {
navigationModel.showRightPanelButton = isSupportInitiallyAccessible()
}
pageModel?.navigationItem = navigationModel
}
if self.formValidator == nil,
let model = pageModel as? FormHolderModelProtocol {
let rules = model.formRules
self.formValidator = FormValidator(rules)
}
}
open class func verifyRequiredModulesLoaded(for loadObject: MVMCoreLoadObject?, error: inout MVMCoreErrorObject?) -> Bool {
@ -175,37 +173,35 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC
/// Processes any new data. Called after the page is loaded the first time and on response updates for this page,
open func handleNewData() {
// TODO atomize the navigation item
set(navigationController: navigationController)
formValidator?.validate()
}
// MARK: - Navigation Item (Move to model base)
open func set(navigationController: UINavigationController?) {
navigationItem.title = pageModel?.screenHeading
navigationItem.accessibilityLabel = pageModel?.screenHeading
guard let navigationController = navigationController else {
guard let navigationItemModel = pageModel?.navigationItem,
let navigationController = navigationController else {
MVMCoreUISession.sharedGlobal()?.splitViewController?.parent?.setNeedsStatusBarAppearanceUpdate()
return
}
navigationController.setNavigationBarHidden(isNavigationBarHidden(), animated: true)
UIColor.setBackgroundColor(forNavigationBar: navigationBarColor(), navigationBar: navigationController.navigationBar, transparent: navigationBarTransparent())
navigationItem.title = navigationItemModel.title
navigationItem.accessibilityLabel = navigationItemModel.title
let tint = navigationBarTintColor() ?? .black
navigationController.setNavigationBarHidden(navigationItemModel.hidden, animated: true)
UIColor.setBackgroundColor(forNavigationBar: navigationItemModel.backgroundColor?.uiColor ?? .white, navigationBar: navigationController.navigationBar, transparent: navigationItemModel.transparent)
let tint = navigationItemModel.tintColor.uiColor
navigationController.navigationBar.tintColor = tint
// Have the navigation title match the tint color
navigationController.navigationBar.titleTextAttributes?.updateValue(navigationBarTintColor, forKey: .foregroundColor)
navigationController.navigationBar.titleTextAttributes?.updateValue(tint, forKey: .foregroundColor)
if navigationController == MVMCoreUISplitViewController.main()?.navigationController {
// Update icons if main navigation controller.
// Update icons if main navigation controller.
if navigationController == MVMCoreUISplitViewController.main()?.navigationController,
MVMCoreUISplitViewController.main()?.getCurrentVisibleController() == self {
MVMCoreUISession.sharedGlobal()?.splitViewController?.setupPanels()
let master = masterShouldBeAccessible
masterShouldBeAccessible = master
let support = supportShouldBeAccessible
supportShouldBeAccessible = support
showBottomProgressBar()
MVMCoreUISplitViewController.main()?.setLeftPanelIsAccessible(navigationItemModel.showLeftPanelButton ?? false, for: self)
MVMCoreUISplitViewController.main()?.setRightPanelIsAccessible(navigationItemModel.showRightPanelButton ?? false, for: self)
showBottomProgressBar()
MVMCoreUISession.sharedGlobal()?.splitViewController?.setNavigationIconColor(tint)
// Update separator.
@ -213,22 +209,6 @@ open class ViewController: UIViewController, MVMCoreViewControllerProtocol, MVMC
}
}
open func navigationBarColor() -> UIColor {
return .white
}
open func isNavigationBarHidden() -> Bool {
return false
}
open func navigationBarTransparent() -> Bool {
return false
}
open func navigationBarTintColor() -> UIColor? {
return nil
}
open func isMasterInitiallyAccessible() -> Bool {
if loadObject?.pageJSON?.boolForKey(KeyHideMainMenu) ?? false {
return false

View File

@ -9,7 +9,6 @@
import Foundation
//Protocol for Validation
public protocol FormProtocol: class {
public protocol FormHolderModelProtocol: class {
var formRules: [FormGroupRule]? { get set }
var formValidator: FormValidator? { get set }
}

View File

@ -9,7 +9,7 @@
import Foundation
public protocol TemplateModelProtocol: PageModelProtocol, ModelProtocol, FormProtocol {
public protocol TemplateModelProtocol: PageModelProtocol, ModelProtocol, FormHolderModelProtocol {
var template: String { get }
}

View File

@ -8,10 +8,112 @@
import Foundation
public protocol NavigationItemModelProtocol: ModelProtocol {
public protocol NavigationItemModelProtocol: MoleculeModelProtocol {
var title: String? { get set }
var titleView: MoleculeModelProtocol? { get set }
var hidden: Bool { get set }
var backgroundColor: Color? { get set }
var transparent: Bool { get set }
var tintColor: Color { get set }
var systemBackButton: Bool? { get set }
var showLeftPanelButton: Bool? { get set }
var showRightPanelButton: Bool? { get set }
var additionalLeftItems: [NavigationItemButtonModel]? { get set }
var additionalRightItems: [NavigationItemButtonModel]? { get set }
}
public protocol NavigationItemButtonModelProtocol {
public class NavigationItemButtonModel: Codable {
var imageName: String
var action: ActionModelProtocol
public init(with imageName: String, action: ActionModelProtocol) {
self.imageName = imageName
self.action = action
}
private enum CodingKeys: String, CodingKey {
case imageName
case action
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
imageName = try typeContainer.decode(String.self, forKey: .imageName)
action = try typeContainer.decodeModel(codingKey: .action)
}
open func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(imageName, forKey: .imageName)
try container.encodeModel(action, forKey: .action)
}
}
public class NavigationItemModel: NavigationItemModelProtocol {
public class var identifier: String {
return "navigationItem"
}
public var title: String?
public var titleView: MoleculeModelProtocol?
public var hidden: Bool
public var backgroundColor: Color?
public var transparent: Bool
public var tintColor: Color
public var systemBackButton: Bool?
public var showLeftPanelButton: Bool?
public var showRightPanelButton: Bool?
public var additionalLeftItems: [NavigationItemButtonModel]?
public var additionalRightItems: [NavigationItemButtonModel]?
init() {
hidden = false
transparent = false
backgroundColor = Color(uiColor: .white)
tintColor = Color(uiColor: .black)
}
private enum CodingKeys: String, CodingKey {
case title
case titleView
case hidden
case backgroundColor
case transparent
case tintColor
case systemBackButton
case showLeftPanelButton
case showRightPanelButton
case additionalLeftItems
case additionalRightItems
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
title = try typeContainer.decodeIfPresent(String.self, forKey: .title)
titleView = try typeContainer.decodeModelIfPresent(codingKey: .titleView)
hidden = try typeContainer.decodeIfPresent(Bool.self, forKey: .hidden) ?? false
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) ?? Color(uiColor: .white)
transparent = try typeContainer.decodeIfPresent(Bool.self, forKey: .transparent) ?? false
tintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .tintColor) ?? Color(uiColor: .black)
systemBackButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .systemBackButton) ?? false
showLeftPanelButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .showLeftPanelButton)
showRightPanelButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .showRightPanelButton)
additionalLeftItems = try typeContainer.decodeIfPresent([NavigationItemButtonModel].self, forKey: .additionalLeftItems)
additionalRightItems = try typeContainer.decodeIfPresent([NavigationItemButtonModel].self, forKey: .additionalRightItems)
}
open func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(title, forKey: .title)
try container.encodeModelIfPresent(titleView, forKey: .titleView)
try container.encode(hidden, forKey: .hidden)
try container.encode(backgroundColor, forKey: .backgroundColor)
try container.encode(transparent, forKey: .transparent)
try container.encode(tintColor, forKey: .tintColor)
try container.encodeIfPresent(systemBackButton, forKey: .systemBackButton)
try container.encode(showLeftPanelButton, forKey: .showLeftPanelButton)
try container.encode(showRightPanelButton, forKey: .showRightPanelButton)
try container.encodeIfPresent(additionalLeftItems, forKey: .additionalLeftItems)
try container.encodeIfPresent(additionalRightItems, forKey: .additionalRightItems)
}
}

View File

@ -22,7 +22,8 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
// MARK: - Computed Properties
//--------------------------------------------------
open override func parsePageJSON() throws {
try parseTemplateJSON()
try parseTemplate(json: loadObject?.pageJSON)
try super.parsePageJSON()
}
open override var loadObject: MVMCoreLoadObject? {

View File

@ -13,7 +13,8 @@ open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol {
public var templateModel: StackPageTemplateModel?
open override func parsePageJSON() throws {
try parseTemplateJSON()
try parseTemplate(json: loadObject?.pageJSON)
try super.parsePageJSON()
}
open override var loadObject: MVMCoreLoadObject? {

View File

@ -9,55 +9,39 @@
import Foundation
@objcMembers public class StackPageTemplateModel: TemplateModelProtocol {
public var formRules: [FormGroupRule]?
public var formValidator: FormValidator?
public static var identifier: String = "stack"
public var pageType: String
public var screenHeading: String?
public var isAtomicTabs: Bool?
public var navigationItem: NavigationItemModelProtocol?
@objcMembers public class StackPageTemplateModel: TemplateModel {
public override class var identifier: String {
return "stack"
}
public var header: MoleculeModelProtocol?
public var moleculeStack: MoleculeStackModel
public var footer: MoleculeModelProtocol?
public init(pageType: String, moleculeStack: MoleculeStackModel) {
self.pageType = pageType
self.moleculeStack = moleculeStack
super.init(pageType: pageType)
}
private enum CodingKeys: String, CodingKey {
case pageType
case screenHeading
case header
case footer
case stack
case isAtomicTabs
case formRules
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
pageType = try typeContainer.decode(String.self, forKey: .pageType)
moleculeStack = try typeContainer.decode(MoleculeStackModel.self, forKey: .stack)
screenHeading = try typeContainer.decodeIfPresent(String.self, forKey: .screenHeading)
isAtomicTabs = try typeContainer.decodeIfPresent(Bool.self, forKey: .isAtomicTabs)
header = try typeContainer.decodeModelIfPresent(codingKey: .header)
footer = try typeContainer.decodeModelIfPresent(codingKey: .footer)
formRules = try typeContainer.decodeIfPresent([FormGroupRule].self, forKey: .formRules)
try super.init(from: decoder)
}
public func encode(to encoder: Encoder) throws {
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(pageType, forKey: .pageType)
try container.encode(moleculeStack, forKey: .stack)
try container.encodeIfPresent(screenHeading, forKey: .screenHeading)
try container.encodeIfPresent(isAtomicTabs, forKey: .isAtomicTabs)
try container.encodeModelIfPresent(header, forKey: .header)
try container.encodeModelIfPresent(footer, forKey: .footer)
try container.encodeIfPresent(formRules, forKey: .formRules)
}
}

View File

@ -0,0 +1,50 @@
//
// TemplateModel.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 3/13/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers public class TemplateModel: TemplateModelProtocol {
public class var identifier: String {
return ""
}
public var pageType: String
public var screenHeading: String?
public var isAtomicTabs: Bool?
public var navigationItem: NavigationItemModelProtocol?
public var formRules: [FormGroupRule]?
public init(pageType: String) {
self.pageType = pageType
}
private enum CodingKeys: String, CodingKey {
case pageType
case screenHeading
case isAtomicTabs
case formRules
case navigationItem
}
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
pageType = try typeContainer.decode(String.self, forKey: .pageType)
screenHeading = try typeContainer.decodeIfPresent(String.self, forKey: .screenHeading)
isAtomicTabs = try typeContainer.decodeIfPresent(Bool.self, forKey: .isAtomicTabs)
formRules = try typeContainer.decodeIfPresent([FormGroupRule].self, forKey: .formRules)
navigationItem = try typeContainer.decodeModelIfPresent(codingKey: .navigationItem)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(pageType, forKey: .pageType)
try container.encodeIfPresent(screenHeading, forKey: .screenHeading)
try container.encodeIfPresent(isAtomicTabs, forKey: .isAtomicTabs)
try container.encodeIfPresent(formRules, forKey: .formRules)
try container.encodeModelIfPresent(navigationItem, forKey: .navigationItem)
}
}

View File

@ -15,16 +15,16 @@ public protocol TemplateProtocol: FormHolderProtocol {
}
public extension TemplateProtocol where Self: ViewController {
func parseTemplateJSON() throws {
guard let pageJSON = self.loadObject?.pageJSON else { return }
func parseTemplate(json: [AnyHashable: Any]?) throws {
guard let pageJSON = json else { return }
let data = try JSONSerialization.data(withJSONObject: pageJSON)
let decoder = JSONDecoder()
let templateModel = try decoder.decode(TemplateModel.self, from: data)
self.templateModel = templateModel
if self.formValidator == nil {
let rules = templateModel.formRules
self.formValidator = FormValidator(rules)
}
self.templateModel = templateModel
}
}

View File

@ -15,7 +15,8 @@ import UIKit
public var templateModel: ThreeLayerPageTemplateModel?
open override func parsePageJSON() throws {
try parseTemplateJSON()
try parseTemplate(json: loadObject?.pageJSON)
try super.parsePageJSON()
}
override open func viewDidLoad() {