Merge branch 'feature/develop_mvp_3' of https://gitlab.verizon.com/BPHV_MIPS/mvm_core_ui into feature/VDS_Button

This commit is contained in:
Sumanth Nadigadda 2022-05-06 23:29:33 +05:30
commit 9c3d211a81
16 changed files with 159 additions and 114 deletions

View File

@ -348,7 +348,7 @@
D22479942316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22479932316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift */; };
D22479962316AF6E003FCCF9 /* HeadlineBodyLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22479952316AF6D003FCCF9 /* HeadlineBodyLink.swift */; };
D224799B231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D224799A231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift */; };
D22D8393241C27B100D3DF69 /* TemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22D8392241C27B100D3DF69 /* TemplateModel.swift */; };
D22D8393241C27B100D3DF69 /* BaseTemplateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22D8392241C27B100D3DF69 /* BaseTemplateModel.swift */; };
D22D8395241FB41200D3DF69 /* UIStackView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22D8394241FB41200D3DF69 /* UIStackView+Extension.swift */; };
D23118B325124E18001C8440 /* Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23118B225124E18001C8440 /* Notification.swift */; };
D2351C7A24A4D433007DF0BC /* ListRightVariableToggleAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2351C7924A4D433007DF0BC /* ListRightVariableToggleAllTextAndLinksModel.swift */; };
@ -936,7 +936,7 @@
D22479932316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSLayoutConstraintExtension.swift; sourceTree = "<group>"; };
D22479952316AF6D003FCCF9 /* HeadlineBodyLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyLink.swift; sourceTree = "<group>"; };
D224799A231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccordionMoleculeTableViewCell.swift; sourceTree = "<group>"; };
D22D8392241C27B100D3DF69 /* TemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateModel.swift; sourceTree = "<group>"; };
D22D8392241C27B100D3DF69 /* BaseTemplateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseTemplateModel.swift; sourceTree = "<group>"; };
D22D8394241FB41200D3DF69 /* UIStackView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIStackView+Extension.swift"; sourceTree = "<group>"; };
D23118B225124E18001C8440 /* Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notification.swift; sourceTree = "<group>"; };
D2351C7924A4D433007DF0BC /* ListRightVariableToggleAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListRightVariableToggleAllTextAndLinksModel.swift; sourceTree = "<group>"; };
@ -1986,7 +1986,7 @@
D29DF0DF21E418B2003B2FB9 /* Templates */ = {
isa = PBXGroup;
children = (
D22D8392241C27B100D3DF69 /* TemplateModel.swift */,
D22D8392241C27B100D3DF69 /* BaseTemplateModel.swift */,
D2092356244FA1EF0044AD09 /* ThreeLayerModelBase.swift */,
014AA72823C5059B006F3E93 /* StackPageTemplateModel.swift */,
D2A5146022121FBF00345BFB /* MoleculeStackTemplate.swift */,
@ -3077,7 +3077,7 @@
D23EA7FE247EBBB700D60C34 /* NavigationLabelButtonModel.swift in Sources */,
D28A839123CD4FD400DFE4FC /* CornerLabelsModel.swift in Sources */,
012A88F123985E0100FE3DA1 /* Color.swift in Sources */,
D22D8393241C27B100D3DF69 /* TemplateModel.swift in Sources */,
D22D8393241C27B100D3DF69 /* BaseTemplateModel.swift in Sources */,
012A889C23889E8400FE3DA1 /* TemplateModelProtocol.swift in Sources */,
EAA0CFB1275E823A00D65EB0 /* HideFormFieldEffectModel.swift in Sources */,
D23A8FFB26123189007E14CE /* PageBehaviorModelProtocol.swift in Sources */,

View File

@ -23,4 +23,33 @@ public protocol MoleculeDelegateProtocol: AnyObject {
extension MoleculeDelegateProtocol {
public func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) { }
public func getModuleWithName(_ moleculeName: String) -> MoleculeModelProtocol? {
let moduleJSON: [AnyHashable: Any]? = getModuleWithName(moleculeName)
guard let moduleJSON = moduleJSON as? [String: Any],
let moleculeName = moduleJSON.optionalStringForKey("moleculeName"),
let modelType = ModelRegistry.getType(for: moleculeName, with: MoleculeModelProtocol.self)
else { return nil }
do {
return try modelType.decode(jsonDict: moduleJSON as [String : Any]) as? MoleculeModelProtocol
} catch {
MVMCoreUILoggingHandler.logDebugMessage(withDelegate: "error: \(error)")
}
return nil
}
}
extension MoleculeDelegateProtocol where Self: TemplateProtocol {
public func getRootMolecules() -> [MoleculeModelProtocol] {
templateModel?.rootMolecules ?? []
}
}
extension MoleculeDelegateProtocol where Self: MVMCoreViewControllerProtocol {
public func getModuleWithName(_ name: String?) -> [AnyHashable : Any]? {
guard let name = name else { return nil }
return loadObject??.modulesJSON?.optionalDictionaryForKey(name)
}
}

View File

@ -8,43 +8,46 @@
import Foundation
public protocol TemplateProtocol: AnyObject {
public protocol TemplateProtocol: AnyObject, PageProtocol {
associatedtype TemplateModel: TemplateModelProtocol
var templateModel: TemplateModel? { get set }
func decodeTemplate(using decoder: JSONDecoder, from data: Data) throws -> TemplateModel
}
public extension TemplateProtocol where Self: ViewController {
public extension TemplateProtocol {
// Utilize existing underlying property
var templateModel: TemplateModel? {
get {
pageModel as? TemplateModel
}
set {
var mutableSelf = self
mutableSelf.pageModel = newValue
}
}
/// Helper function to do common parsing logic.
func parseTemplate(json: [AnyHashable: Any]?) throws {
guard let pageJSON = json else { return }
let delegateObject = (self as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject
let data = try JSONSerialization.data(withJSONObject: pageJSON)
let decoder = JSONDecoder()
try decoder.add(delegateObject: delegateObjectIVar)
if let delegateObject = delegateObject {
// Add the delegate to access mid parsing if applicable.
try decoder.add(delegateObject: delegateObject)
}
templateModel = try decodeTemplate(using: decoder, from: data)
model = templateModel as? MVMControllerModelProtocol
guard let model = model else { return }
traverseAndAddRequiredBehaviors()
var behaviorHandler = self
behaviorHandler.createBehaviors(for: model, delegateObject: delegateObjectIVar)
// Add additional required behaviors if applicable.
guard var behaviorHandlerModel = templateModel as? TemplateModelProtocol & PageBehaviorHandlerModelProtocol,
var behaviorHandler = self as? PageBehaviorHandlerProtocol else { return }
behaviorHandlerModel.traverseAndAddRequiredBehaviors()
behaviorHandler.createBehaviors(for: behaviorHandlerModel, delegateObject: delegateObject)
}
func decodeTemplate(using decoder: JSONDecoder, from data: Data) throws -> TemplateModel {
try decoder.decode(TemplateModel.self, from: data)
}
/// Traverses all models and adds any required behavior models.
func traverseAndAddRequiredBehaviors() {
guard var model = model else { return }
let behaviorModels: [PageBehaviorModelProtocol] = model.reduceDepthFirstTraverse(options: .childFirst, depth: 0, initialResult: []) { (accumulator, molecule, depth) in
if let behaviorRequirer = molecule as? PageBehaviorProtocolRequirer {
return accumulator + behaviorRequirer.getRequiredBehaviors()
}
return accumulator
}
for behavior in behaviorModels {
model.add(behavior: behavior)
}
}
}

View File

@ -1,5 +1,5 @@
//
// TemplateModel.swift
// BaseTemplateModel.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 3/13/20.
@ -9,7 +9,7 @@
import Foundation
@objcMembers open class TemplateModel: MVMControllerModelProtocol, TabPageModelProtocol {
@objcMembers open class BaseTemplateModel: MVMControllerModelProtocol, TabPageModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------

View File

@ -13,7 +13,6 @@
//--------------------------------------------------
public typealias TemplateModel = CollectionTemplateModel
public var templateModel: CollectionTemplateModel?
public var moleculesInfo: [(identifier: String, class: AnyClass, molecule: (CollectionItemModelProtocol & MoleculeModelProtocol))]?

View File

@ -19,9 +19,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
public var moleculesInfo: [MoleculeInfo]?
var observer: NSKeyValueObservation?
public var templateModel: ListPageTemplateModel?
//--------------------------------------------------
// MARK: - Computed Properties
//--------------------------------------------------

View File

@ -15,7 +15,6 @@ open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol {
//--------------------------------------------------
var observer: NSKeyValueObservation?
public var templateModel: StackPageTemplateModel?
//--------------------------------------------------
// MARK: - Lifecycle

View File

@ -7,7 +7,7 @@
//
@objcMembers open class ThreeLayerModelBase: TemplateModel, ThreeLayerTemplateModelProtocol {
@objcMembers open class ThreeLayerModelBase: BaseTemplateModel, ThreeLayerTemplateModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------

View File

@ -9,11 +9,6 @@
import UIKit
@objcMembers open class ThreeLayerTemplate<TemplateModel: ThreeLayerPageTemplateModel>: ThreeLayerViewController, TemplateProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public var templateModel: TemplateModel?
//--------------------------------------------------
// MARK: - Lifecycle

View File

@ -43,9 +43,6 @@ import UIKit
public var selectedField: UIView?
// Stores the previous tab bar index.
public var tabBarIndex: Int?
/// Checks if the screen width has changed
open func screenSizeChanged() -> Bool {
!MVMCoreGetterUtility.cgfequalwiththreshold(previousScreenSize.width, view.bounds.size.width, 0.1)
@ -244,12 +241,6 @@ import UIKit
view.backgroundColor = backgroundColor.uiColor
}
// Update splitview properties
if self == MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() {
MVMCoreUISplitViewController.main()?.setBottomProgressBarProgress(bottomProgress() ?? 0)
updateTabBar()
}
// Notify the manager of new data
manager?.newDataReceived?(in: self)
}
@ -267,34 +258,6 @@ import UIKit
return model?.navigationBar
}
//--------------------------------------------------
// MARK: - TabBar
//--------------------------------------------------
open func updateTabBar() {
guard MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() == self else { return }
MVMCoreUISplitViewController.main()?.tabBar?.delegateObject = delegateObjectIVar
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)
} else if let index = self.tabBarIndex {
MVMCoreUISplitViewController.main()?.tabBar?.highlightTab(at: index)
} else if let index = MVMCoreUISplitViewController.main()?.tabBar?.currentTabIndex() {
// Store current tab index for cases like back button.
self.tabBarIndex = index
}
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)
} else {
MVMCoreUISplitViewController.main()?.updateTabBarShowing(true)
}
}
//--------------------------------------------------
// MARK: - View Lifecycle
//--------------------------------------------------
@ -349,12 +312,6 @@ import UIKit
}
open func pageShown() {
// Update split view properties if this is the current detail controller.
if self == MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() {
MVMCoreUISplitViewController.main()?.setBottomProgressBarProgress(bottomProgress() ?? 0)
updateTabBar()
}
// Track.
MVMCoreUISession.sharedGlobal()?.currentPageType = pageType
MVMCoreUILoggingHandler.shared()?.defaultLogPageState(forController: self)
@ -484,26 +441,6 @@ import UIKit
model?.rootMolecules ?? []
}
open func getModuleWithName(_ name: String?) -> [AnyHashable: Any]? {
guard let name = name else { return nil }
return loadObject?.modulesJSON?.optionalDictionaryForKey(name)
}
open func getModuleWithName(_ moleculeName: String) -> MoleculeModelProtocol? {
guard let moduleJSON = loadObject?.modulesJSON?.optionalDictionaryForKey(moleculeName),
let moleculeName = moduleJSON.optionalStringForKey("moleculeName"),
let modelType = ModelRegistry.getType(for: moleculeName, with: MoleculeModelProtocol.self)
else { return nil }
do {
return try modelType.decode(jsonDict: moduleJSON) as? MoleculeModelProtocol
} catch {
MVMCoreUILoggingHandler.logDebugMessage(withDelegate: "error: \(error)")
}
return nil
}
// Needed otherwise when subclassed, the extension gets called.
open func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) { }
@ -618,12 +555,4 @@ import UIKit
selectedField = nil
}
}
//--------------------------------------------------
// MARK: - Behavior Execution
//--------------------------------------------------
public func executeBehaviors<T>(_ behaviorBlock: (_ behavior: T) -> Void) {
behaviors?.compactMap { $0 as? T }.forEach { behaviorBlock($0) }
}
}

View File

@ -23,3 +23,19 @@ public extension PageBehaviorHandlerModelProtocol {
self.behaviors = newBehaviors
}
}
public extension PageBehaviorHandlerModelProtocol where Self: MoleculeTreeTraversalProtocol {
/// Traverses all models and adds any required behavior models.
mutating func traverseAndAddRequiredBehaviors() {
let behaviorModels: [PageBehaviorModelProtocol] = reduceDepthFirstTraverse(options: .childFirst, depth: 0, initialResult: []) { (accumulator, molecule, depth) in
if let behaviorRequirer = molecule as? PageBehaviorProtocolRequirer {
return accumulator + behaviorRequirer.getRequiredBehaviors()
}
return accumulator
}
for behavior in behaviorModels {
add(behavior: behavior)
}
}
}

View File

@ -34,4 +34,9 @@ public extension PageBehaviorHandlerProtocol {
}
self.behaviors = behaviors.count > 0 ? behaviors : nil
}
/// Executes all behaviors of type.
func executeBehaviors<T>(_ behaviorBlock: (_ behavior: T) -> Void) {
behaviors?.compactMap { $0 as? T }.forEach { behaviorBlock($0) }
}
}

View File

@ -50,8 +50,11 @@ public protocol PageCustomActionHandlerBehavior: PageBehaviorProtocol {
}
public extension MVMCoreUIDelegateObject {
var behaviorModelDelegate: PageBehaviorHandlerModelProtocol? {
(moleculeDelegate as? PageProtocol)?.pageModel as? PageBehaviorHandlerModelProtocol
}
weak var behaviorTemplateDelegate: (PageBehaviorHandlerProtocol & NSObjectProtocol)? {
(moleculeDelegate as? PageProtocol)?.pageModel as? (PageBehaviorHandlerProtocol & NSObjectProtocol)
moleculeDelegate as? (PageBehaviorHandlerProtocol & NSObjectProtocol)
}
}

View File

@ -12,6 +12,64 @@ import UIKit
// Navigation bar update functions
public extension MVMCoreUISplitViewController {
/// Updates the state for various controls (navigation, tab, progress) for the controller.
func updateState(with viewController: UIViewController) {
guard let navigationController = navigationController,
navigationController.isDisplayed(viewController: viewController) else { return }
updateNavigationBarFor(viewController: viewController)
updateProgressBar(for: viewController)
updateTabBar(for: viewController)
}
// MARK: - Progress Bar
/// Updates the progress bar based on the page json for the view controller.
func updateProgressBar(for viewController: UIViewController) {
guard let viewController = viewController as? MVMCoreViewControllerProtocol else { return }
var progress: Float = 0.0
if let progressString = viewController.loadObject??.pageJSON?.optionalStringForKey(KeyProgressPercent),
let floatValue = Float(progressString) {
progress = floatValue/100
}
setBottomProgressBarProgress(progress)
}
// MARK: - Tab Bar
/// Updates the tab bar based on the page json for the view controller.
func updateTabBar(for viewController: UIViewController) {
let mvmViewController = viewController as? MVMCoreViewControllerProtocol
tabBar?.delegateObject = mvmViewController?.delegateObject?() as? MVMCoreUIDelegateObject
let navigationIndex = (MVMCoreNavigationHandler.shared()?.getViewControllers(for: navigationController)?.count ?? 1) - 1
// Set the highlighted index. In terms of priority, Page > Action > Previous.
if let index = ((viewController as? PageProtocol)?.pageModel as? TabPageModelProtocol)?.tabBarIndex {
tabBar?.highlightTab(at: index)
} else if let index = mvmViewController?.loadObject??.requestParameters?.actionMap?["tabBarIndex"] as? Int {
tabBar?.highlightTab(at: index)
} else if navigationIndex < tabBarIndices.count {
let index = (tabBarIndices[navigationIndex] as! NSNumber).intValue
tabBar?.highlightTab(at: index)
}
// Store current tab index, so we can switch back when going back in hierarchy.
if tabBarIndices.count > 0 {
tabBarIndices.removeObjects(in: NSRange(location: navigationIndex, length: tabBarIndices.count - navigationIndex))
}
if let currentIndex = tabBar?.currentTabIndex() {
tabBarIndices.add(NSNumber(integerLiteral: currentIndex))
}
// Show/Hide. In terms of priority, Page > Action > Always Show.
if let hidden = ((viewController as? PageProtocol)?.pageModel as? TabPageModelProtocol)?.tabBarHidden {
updateTabBarShowing(!hidden)
} else if let hidden = mvmViewController?.loadObject??.requestParameters?.actionMap?["tabBarHidden"] as? Bool {
updateTabBarShowing(!hidden)
} else {
updateTabBarShowing(true)
}
}
// MARK: - Navigation Bar
/// 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.
func setNavigationBar(for viewController: UIViewController, navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol) {
guard navigationController == self.navigationController,
@ -122,6 +180,7 @@ public extension MVMCoreUISplitViewController {
setStatusBarForCurrentViewController()
}
// MARK: - Status Bar
/// Returns the bar style for the background color. Light if on a dark background, otherwise default.
func getStatusBarStyle(for backgroundColor: UIColor?) -> UIStatusBarStyle {
var greyScale: CGFloat = 0
@ -155,10 +214,10 @@ extension MVMCoreUISplitViewController: MVMCoreViewManagerProtocol {
public func willDisplay(_ viewController: UIViewController) {
setupPanels()
updateNavigationBarFor(viewController: viewController)
updateState(with: viewController)
}
public func newDataReceived(in viewController: UIViewController) {
updateNavigationBarFor(viewController: viewController)
updateState(with: viewController)
}
}

View File

@ -55,6 +55,9 @@ typedef NS_ENUM(NSInteger, MFNumberOfDrawers) {
/// Reference to the tabbar.
@property (nullable, weak, nonatomic) UIView <TabBarProtocol>*tabBar;
/// Tab bar index history.
@property (nonnull, strong, nonatomic) NSMutableArray <NSNumber *>*tabBarIndices;
// Convenience getter
+ (nullable instancetype)mainSplitViewController;

View File

@ -93,13 +93,20 @@ CGFloat const PanelAnimationDuration = 0.2;
}
- (nullable instancetype)initWithLeftPanel:(nullable UIViewController <MVMCoreUIPanelProtocol> *)leftPanel rightPanel:(nullable UIViewController <MVMCoreUIPanelProtocol> *)rightPanel {
if (self = [super init]) {
if (self = [self init]) {
self.globalLeftPanel = leftPanel;
self.globalRightPanel = rightPanel;
}
return self;
}
- (nullable instancetype)init {
if (self = [super init]) {
self.tabBarIndices = [NSMutableArray array];
}
return self;
}
#pragma mark - Main Subclassables
- (MFNumberOfDrawers)numberOfDrawersShouldShow:(NSNumber *)forWidth {