Merge remote-tracking branch 'origin/release/10_2_0' into bugfix/label_range_safety
This commit is contained in:
commit
bd4cadce3f
@ -129,6 +129,8 @@
|
||||
187FEB2A2844D2A600BF29C2 /* VDSFormControlsTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 187FEB292844D2A600BF29C2 /* VDSFormControlsTokens.xcframework */; };
|
||||
1D6D258826899B0C00DEBB08 /* ImageButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D6D258626899B0B00DEBB08 /* ImageButtonModel.swift */; };
|
||||
1D6D258926899B0C00DEBB08 /* ImageButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D6D258726899B0B00DEBB08 /* ImageButton.swift */; };
|
||||
27559EFC27D691D3000836C1 /* ViewMaskingProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27559EFB27D691D3000836C1 /* ViewMaskingProtocol.swift */; };
|
||||
27577DCD286CA959001EC47E /* MoleculeMaskingProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27577DCC286CA959001EC47E /* MoleculeMaskingProtocol.swift */; };
|
||||
279B1569242BBC2F00921D6C /* ActionModelAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 279B1568242BBC2F00921D6C /* ActionModelAdapter.swift */; };
|
||||
27F6B08826051831008529AA /* MoleculeTreeTraversalProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27F6B08726051831008529AA /* MoleculeTreeTraversalProtocol.swift */; };
|
||||
27F6B08C26052AFF008529AA /* ParentMoleculeModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27F6B08B26052AFF008529AA /* ParentMoleculeModelProtocol.swift */; };
|
||||
@ -719,6 +721,8 @@
|
||||
187FEB292844D2A600BF29C2 /* VDSFormControlsTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSFormControlsTokens.xcframework; path = ../SharedFrameworks/VDSFormControlsTokens.xcframework; sourceTree = "<group>"; };
|
||||
1D6D258626899B0B00DEBB08 /* ImageButtonModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ImageButtonModel.swift; path = MVMCoreUI/Atomic/Atoms/Buttons/ImageButtonModel.swift; sourceTree = SOURCE_ROOT; };
|
||||
1D6D258726899B0B00DEBB08 /* ImageButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ImageButton.swift; path = MVMCoreUI/Atomic/Atoms/Buttons/ImageButton.swift; sourceTree = SOURCE_ROOT; };
|
||||
27559EFB27D691D3000836C1 /* ViewMaskingProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewMaskingProtocol.swift; sourceTree = "<group>"; };
|
||||
27577DCC286CA959001EC47E /* MoleculeMaskingProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeMaskingProtocol.swift; sourceTree = "<group>"; };
|
||||
279B1568242BBC2F00921D6C /* ActionModelAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionModelAdapter.swift; sourceTree = "<group>"; };
|
||||
27F6B08726051831008529AA /* MoleculeTreeTraversalProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeTreeTraversalProtocol.swift; sourceTree = "<group>"; };
|
||||
27F6B08B26052AFF008529AA /* ParentMoleculeModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParentMoleculeModelProtocol.swift; sourceTree = "<group>"; };
|
||||
@ -1218,6 +1222,7 @@
|
||||
D2509ED02472ED9B001BFB9D /* NavigationItemModelProtocol.swift */,
|
||||
D28BA74C248589C800B75CB8 /* TabPageModelProtocol.swift */,
|
||||
27F6B08B26052AFF008529AA /* ParentMoleculeModelProtocol.swift */,
|
||||
27577DCC286CA959001EC47E /* MoleculeMaskingProtocol.swift */,
|
||||
);
|
||||
path = ModelProtocols;
|
||||
sourceTree = "<group>";
|
||||
@ -2419,6 +2424,7 @@
|
||||
D28BA7442481652D00B75CB8 /* TabBarProtocol.swift */,
|
||||
D2B9D0E3265EEE9D0084735C /* MoleculeListProtocol.swift */,
|
||||
011B58EE23A2AA850085F53C /* ModelProtocols */,
|
||||
27559EFB27D691D3000836C1 /* ViewMaskingProtocol.swift */,
|
||||
);
|
||||
path = Protocols;
|
||||
sourceTree = "<group>";
|
||||
@ -2888,6 +2894,7 @@
|
||||
D23EA800247EBD6C00D60C34 /* LabelBarButtonItem.swift in Sources */,
|
||||
01EB368F23609801006832FA /* LabelModel.swift in Sources */,
|
||||
0A6682AC243531C300AD3CA1 /* Padding.swift in Sources */,
|
||||
27559EFC27D691D3000836C1 /* ViewMaskingProtocol.swift in Sources */,
|
||||
AA1EC59924373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift in Sources */,
|
||||
AA37CBD52519072F0027344C /* Stars.swift in Sources */,
|
||||
942C378E2412F5B60066E45E /* ModalMoleculeStackTemplate.swift in Sources */,
|
||||
@ -3064,6 +3071,7 @@
|
||||
D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */,
|
||||
EA41F4AC2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift in Sources */,
|
||||
011D95892404249B000E3791 /* FormHolderModelProtocol.swift in Sources */,
|
||||
27577DCD286CA959001EC47E /* MoleculeMaskingProtocol.swift in Sources */,
|
||||
BB54C5202434D92F0038326C /* ListRightVariableButtonAllTextAndLinks.swift in Sources */,
|
||||
948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */,
|
||||
013F801923FB4A8E00AD8013 /* UIContentMode+Extension.swift in Sources */,
|
||||
|
||||
@ -32,6 +32,8 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
|
||||
public var inverted = false
|
||||
public var size:linkFontSize = linkFontSize.small
|
||||
|
||||
public var shouldMaskRecordedView: Bool? = false
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializer
|
||||
//--------------------------------------------------
|
||||
@ -61,6 +63,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
|
||||
case activeColor_inverted
|
||||
case inverted
|
||||
case size
|
||||
case shouldMaskRecordedView
|
||||
}
|
||||
|
||||
public enum linkFontSize: String, Codable {
|
||||
@ -117,7 +120,7 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
|
||||
if let disabledColor_inverted = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledColor_inverted) {
|
||||
self.disabledColor_inverted = disabledColor_inverted
|
||||
}
|
||||
|
||||
|
||||
if let activeColor = try typeContainer.decodeIfPresent(Color.self, forKey: .activeColor) {
|
||||
self.activeColor = activeColor
|
||||
}
|
||||
@ -128,6 +131,8 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
|
||||
if let size = try typeContainer.decodeIfPresent(linkFontSize.self, forKey: .size) {
|
||||
self.size = size
|
||||
}
|
||||
|
||||
shouldMaskRecordedView = try typeContainer.decodeIfPresent(Bool.self, forKey: .shouldMaskRecordedView) ?? shouldMaskRecordedView
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
@ -146,5 +151,6 @@ open class LinkModel: ButtonModelProtocol, MoleculeModelProtocol, EnableableMode
|
||||
try container.encode(activeColor, forKey: .activeColor)
|
||||
try container.encode(activeColor_inverted, forKey: .activeColor_inverted)
|
||||
try container.encodeIfPresent(size, forKey: .size)
|
||||
try container.encode(shouldMaskRecordedView, forKey: .shouldMaskRecordedView)
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,7 +42,8 @@ import Foundation
|
||||
public var wasInitiallySelected: Bool = false
|
||||
public var title: String?
|
||||
public var feedback: String?
|
||||
|
||||
public var shouldMaskRecordedView: Bool? = true
|
||||
|
||||
//used to drive the EntryFieldView UI
|
||||
public var titleStateLabel: FormLabelModel
|
||||
public var feedbackStateLabel: FormLabelModel
|
||||
@ -79,6 +80,7 @@ import Foundation
|
||||
case fieldKey
|
||||
case groupName
|
||||
case required
|
||||
case shouldMaskRecordedView
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -143,6 +145,7 @@ import Foundation
|
||||
hideBorders = try typeContainer.decodeIfPresent(Bool.self, forKey: .hideBorders) ?? false
|
||||
baseValue = text
|
||||
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
|
||||
shouldMaskRecordedView = try typeContainer.decodeIfPresent(Bool.self, forKey: .shouldMaskRecordedView) ?? shouldMaskRecordedView
|
||||
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
|
||||
self.groupName = groupName
|
||||
}
|
||||
@ -172,5 +175,6 @@ import Foundation
|
||||
try container.encode(enabled, forKey: .enabled)
|
||||
try container.encode(required, forKey: .required)
|
||||
try container.encode(hideBorders, forKey: .hideBorders)
|
||||
try container.encode(shouldMaskRecordedView, forKey: .shouldMaskRecordedView)
|
||||
}
|
||||
}
|
||||
|
||||
@ -337,12 +337,16 @@ import UIKit
|
||||
text = model.text
|
||||
placeholder = model.placeholder
|
||||
|
||||
textField.shouldMaskWhileRecording = model.shouldMaskRecordedView ?? true
|
||||
|
||||
switch model.type {
|
||||
case .password, .secure:
|
||||
textField.isSecureTextEntry = true
|
||||
textField.shouldMaskWhileRecording = true
|
||||
|
||||
case .numberSecure:
|
||||
textField.isSecureTextEntry = true
|
||||
textField.shouldMaskWhileRecording = true
|
||||
textField.keyboardType = .numberPad
|
||||
|
||||
case .number:
|
||||
|
||||
@ -23,6 +23,7 @@ import MVMCore
|
||||
public var baseValue: AnyHashable?
|
||||
public var enabled: Bool = true
|
||||
public var readOnly: Bool = false
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Methods
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
public var localBundle: Bundle?
|
||||
public var cornerRadius: CGFloat?
|
||||
public var clipsImage: Bool?
|
||||
public var shouldMaskRecordedView: Bool? = false
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializer
|
||||
@ -54,5 +55,6 @@
|
||||
case contentMode
|
||||
case cornerRadius
|
||||
case clipsImage
|
||||
case shouldMaskRecordedView
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,7 +12,8 @@ import MVMCore
|
||||
public typealias ActionBlock = () -> ()
|
||||
|
||||
|
||||
@objcMembers open class Label: UILabel, MVMCoreViewProtocol, MoleculeViewProtocol, MVMCoreUIViewConstrainingProtocol, MFButtonProtocol {
|
||||
@objcMembers open class Label: UILabel, MVMCoreViewProtocol, MoleculeViewProtocol, MVMCoreUIViewConstrainingProtocol, MFButtonProtocol, ViewMaskingProtocol {
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//------------------------------------------------------
|
||||
@ -41,6 +42,8 @@ public typealias ActionBlock = () -> ()
|
||||
NSRange(location: 0, length: text?.count ?? 0)
|
||||
}
|
||||
|
||||
public var shouldMaskWhileRecording: Bool = false
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Multi-Action Text
|
||||
//------------------------------------------------------
|
||||
@ -244,6 +247,7 @@ public typealias ActionBlock = () -> ()
|
||||
text = nil
|
||||
attributedText = nil
|
||||
originalAttributedString = nil
|
||||
shouldMaskWhileRecording = model.shouldMaskRecordedView ?? false
|
||||
|
||||
guard let labelModel = model as? LabelModel else { return }
|
||||
|
||||
|
||||
@ -36,6 +36,7 @@
|
||||
public var hero: Int?
|
||||
public var makeWholeViewClickable: Bool?
|
||||
public var numberOfLines: Int?
|
||||
public var shouldMaskRecordedView: Bool? = false
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Keys
|
||||
@ -56,6 +57,7 @@
|
||||
case hero
|
||||
case makeWholeViewClickable
|
||||
case numberOfLines
|
||||
case shouldMaskRecordedView
|
||||
}
|
||||
|
||||
enum AttributeTypeKey: String, CodingKey {
|
||||
@ -96,6 +98,7 @@
|
||||
hero = try typeContainer.decodeIfPresent(Int.self, forKey: .hero)
|
||||
makeWholeViewClickable = try typeContainer.decodeIfPresent(Bool.self, forKey: .makeWholeViewClickable)
|
||||
numberOfLines = try typeContainer.decodeIfPresent(Int.self, forKey: .numberOfLines)
|
||||
shouldMaskRecordedView = try typeContainer.decodeIfPresent(Bool.self, forKey: .shouldMaskRecordedView) ?? false
|
||||
}
|
||||
|
||||
open func encode(to encoder: Encoder) throws {
|
||||
@ -114,5 +117,6 @@
|
||||
try container.encodeIfPresent(hero, forKey: .hero)
|
||||
try container.encodeIfPresent(makeWholeViewClickable, forKey: .makeWholeViewClickable)
|
||||
try container.encodeIfPresent(numberOfLines, forKey: .numberOfLines)
|
||||
try container.encodeIfPresent(shouldMaskRecordedView, forKey: .shouldMaskRecordedView)
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
public var addSizeConstraintsForAspectRatio = true
|
||||
public var shouldNotifyDelegateOnUpdate = true
|
||||
public var shouldNotifyDelegateOnDefaultSizeChange = false
|
||||
|
||||
|
||||
// Allows for a view to hardcode which height to use if there is none in the json.
|
||||
var imageWidth: CGFloat?
|
||||
var imageHeight: CGFloat?
|
||||
|
||||
@ -155,6 +155,9 @@ import VDSColorTokens
|
||||
self.additionalData = additionalData
|
||||
selectedIndex = tabsModel?.selectedIndex ?? 0
|
||||
selectionLine.backgroundColor = tabsModel?.selectedBarColor.uiColor
|
||||
let lineModel = bottomLine.lineModel ?? LineModel(type: .secondary)
|
||||
lineModel.inverted = tabsModel?.style == .dark
|
||||
bottomLine.set(with: lineModel, delegateObject, additionalData)
|
||||
reloadData()
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,17 @@
|
||||
//
|
||||
// MaskedMoleculeProtocol.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Kyle on 6/29/22.
|
||||
// Copyright © 2022 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public protocol MoleculeMaskingProtocol {
|
||||
var shouldMaskRecordedView: Bool? { get }
|
||||
}
|
||||
|
||||
public extension MoleculeMaskingProtocol {
|
||||
var shouldMaskRecordedView: Bool? { return false }
|
||||
}
|
||||
@ -5,7 +5,7 @@ public enum MolecularError: Swift.Error {
|
||||
}
|
||||
|
||||
|
||||
public protocol MoleculeModelProtocol: ModelProtocol, AccessibilityModelProtocol, MoleculeTreeTraversalProtocol {
|
||||
public protocol MoleculeModelProtocol: ModelProtocol, AccessibilityModelProtocol, MoleculeTreeTraversalProtocol, MoleculeMaskingProtocol {
|
||||
var moleculeName: String { get }
|
||||
var backgroundColor: Color? { get set }
|
||||
}
|
||||
|
||||
@ -13,4 +13,5 @@ public protocol PageModelProtocol {
|
||||
var screenHeading: String? { get set }
|
||||
var backgroundColor: Color? { get set }
|
||||
var navigationBar: (NavigationItemModelProtocol & MoleculeModelProtocol)? { get set }
|
||||
var shouldMaskScreenWhileRecording: Bool? { get }
|
||||
}
|
||||
|
||||
@ -41,6 +41,9 @@ public extension TemplateProtocol {
|
||||
var behaviorHandler = self as? PageBehaviorHandlerProtocol else { return }
|
||||
behaviorHandlerModel.traverseAndAddRequiredBehaviors()
|
||||
behaviorHandler.createBehaviors(for: behaviorHandlerModel, delegateObject: delegateObject)
|
||||
if let viewController = self as? UIViewController {
|
||||
MVMCoreUISession.sharedGlobal()?.applyGlobalBehaviors(to: viewController)
|
||||
}
|
||||
}
|
||||
|
||||
func decodeTemplate(using decoder: JSONDecoder, from data: Data) throws -> TemplateModel {
|
||||
|
||||
15
MVMCoreUI/Atomic/Protocols/ViewMaskingProtocol.swift
Normal file
15
MVMCoreUI/Atomic/Protocols/ViewMaskingProtocol.swift
Normal file
@ -0,0 +1,15 @@
|
||||
//
|
||||
// ViewMaskingProtocol.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Kyle on 3/7/22.
|
||||
// Copyright © 2022 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public protocol ViewMaskingProtocol: UIView {
|
||||
|
||||
var shouldMaskWhileRecording: Bool { get }
|
||||
|
||||
}
|
||||
@ -30,6 +30,8 @@ import Foundation
|
||||
|
||||
public var tabBarHidden: Bool = false
|
||||
public var tabBarIndex: Int?
|
||||
|
||||
public var shouldMaskScreenWhileRecording: Bool?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializer
|
||||
@ -53,6 +55,7 @@ import Foundation
|
||||
case navigationBar
|
||||
case tabBarHidden
|
||||
case tabBarIndex
|
||||
case shouldMaskScreenWhileRecording
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -77,6 +80,7 @@ import Foundation
|
||||
self.tabBarHidden = tabBarHidden
|
||||
}
|
||||
tabBarIndex = try typeContainer.decodeIfPresent(Int.self, forKey: .tabBarIndex)
|
||||
shouldMaskScreenWhileRecording = try typeContainer.decodeIfPresent(Bool.self, forKey: .shouldMaskScreenWhileRecording)
|
||||
}
|
||||
|
||||
open func encode(to encoder: Encoder) throws {
|
||||
@ -89,5 +93,6 @@ import Foundation
|
||||
try container.encodeModelIfPresent(navigationBar, forKey: .navigationBar)
|
||||
try container.encode(tabBarHidden, forKey: .tabBarHidden)
|
||||
try container.encodeIfPresent(tabBarIndex, forKey: .tabBarIndex)
|
||||
try container.encode(shouldMaskScreenWhileRecording, forKey: .shouldMaskScreenWhileRecording)
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
open override func viewForTop() -> UIView? {
|
||||
guard let headerModel = templateModel?.header,
|
||||
let molecule = ModelRegistry.createMolecule(headerModel, delegateObject: delegateObjectIVar)
|
||||
let molecule = generateMoleculeView(from: headerModel)
|
||||
else { return super.viewForTop() }
|
||||
|
||||
// Temporary, Default the horizontal padding
|
||||
@ -59,7 +59,7 @@
|
||||
|
||||
override open func viewForBottom() -> UIView? {
|
||||
guard let footerModel = templateModel?.footer,
|
||||
let molecule = ModelRegistry.createMolecule(footerModel, delegateObject: delegateObjectIVar)
|
||||
let molecule = generateMoleculeView(from: footerModel)
|
||||
else { return super.viewForBottom() }
|
||||
|
||||
return molecule
|
||||
@ -124,7 +124,9 @@
|
||||
|
||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: moleculeInfo.identifier, for: indexPath)
|
||||
(cell as? MoleculeViewProtocol)?.reset()
|
||||
(cell as? MoleculeViewProtocol)?.set(with: moleculeInfo.molecule, delegateObjectIVar, nil)
|
||||
if let molecularCell = cell as? MoleculeViewProtocol {
|
||||
updateMoleculeView(molecularCell, from: moleculeInfo.molecule)
|
||||
}
|
||||
update(cell: cell, size: view.frame.width)
|
||||
// Neded to fix an apple defect where the cell is not the correct size on certain devices for certain cells
|
||||
cell.layoutIfNeeded()
|
||||
|
||||
@ -58,7 +58,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
||||
|
||||
open override func viewForTop() -> UIView {
|
||||
guard let headerModel = templateModel?.header,
|
||||
let molecule = ModelRegistry.createMolecule(headerModel, delegateObject: delegateObjectIVar)
|
||||
let molecule = generateMoleculeView(from: headerModel)
|
||||
else { return super.viewForTop() }
|
||||
|
||||
// Temporary, Default the horizontal padding
|
||||
@ -71,7 +71,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
||||
|
||||
override open func viewForBottom() -> UIView {
|
||||
guard let footerModel = templateModel?.footer,
|
||||
let molecule = ModelRegistry.createMolecule(footerModel, delegateObject: delegateObjectIVar)
|
||||
let molecule = generateMoleculeView(from: footerModel)
|
||||
else { return super.viewForBottom() }
|
||||
|
||||
return molecule
|
||||
@ -140,7 +140,9 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
||||
|
||||
(cell as? MoleculeViewProtocol)?.reset()
|
||||
(cell as? MoleculeListCellProtocol)?.setLines(with: templateModel?.line, delegateObject: delegateObjectIVar, additionalData: nil, indexPath: indexPath)
|
||||
(cell as? MoleculeViewProtocol)?.set(with: moleculeInfo.molecule, delegateObjectIVar, nil)
|
||||
if let moleculeView = cell as? MoleculeViewProtocol {
|
||||
updateMoleculeView(moleculeView, from: moleculeInfo.molecule)
|
||||
}
|
||||
(cell as? MVMCoreViewProtocol)?.updateView(tableView.bounds.width)
|
||||
// Neded to fix an apple defect where the cell is not the correct size on certain devices for certain cells
|
||||
cell.layoutIfNeeded()
|
||||
|
||||
@ -54,7 +54,7 @@ open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol {
|
||||
|
||||
open override func viewForTop() -> UIView? {
|
||||
guard let headerModel = templateModel?.header,
|
||||
let molecule = ModelRegistry.createMolecule(headerModel, delegateObject: delegateObjectIVar)
|
||||
let molecule = generateMoleculeView(from: headerModel)
|
||||
else { return nil }
|
||||
|
||||
return molecule
|
||||
@ -73,13 +73,13 @@ open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol {
|
||||
|
||||
stackItem.useHorizontalMargins = true
|
||||
}
|
||||
stack.set(with: moleculeStackModel, delegateObject() as? MVMCoreUIDelegateObject, nil)
|
||||
updateMoleculeView(stack, from: moleculeStackModel)
|
||||
return stack
|
||||
}
|
||||
|
||||
override open func viewForBottom() -> UIView? {
|
||||
guard let footerModel = templateModel?.footer,
|
||||
let molecule = ModelRegistry.createMolecule(footerModel, delegateObject: delegateObjectIVar)
|
||||
let molecule = generateMoleculeView(from: footerModel)
|
||||
else { return nil }
|
||||
|
||||
return molecule
|
||||
|
||||
@ -27,7 +27,7 @@ import UIKit
|
||||
|
||||
open override func viewForTop() -> UIView? {
|
||||
guard let headerModel = templateModel?.header,
|
||||
let molecule = ModelRegistry.createMolecule(headerModel, delegateObject: delegateObjectIVar)
|
||||
let molecule = generateMoleculeView(from: headerModel)
|
||||
else { return nil }
|
||||
|
||||
return molecule
|
||||
@ -35,7 +35,7 @@ import UIKit
|
||||
|
||||
open override func viewForMiddle() -> UIView? {
|
||||
guard let middleModel = templateModel?.middle,
|
||||
let molecule = ModelRegistry.createMolecule(middleModel, delegateObject: delegateObjectIVar)
|
||||
let molecule = generateMoleculeView(from: middleModel)
|
||||
else { return nil }
|
||||
|
||||
return molecule
|
||||
@ -43,7 +43,7 @@ import UIKit
|
||||
|
||||
override open func viewForBottom() -> UIView? {
|
||||
guard let footerModel = templateModel?.footer,
|
||||
let molecule = ModelRegistry.createMolecule(footerModel, delegateObject: delegateObjectIVar)
|
||||
let molecule = generateMoleculeView(from: footerModel)
|
||||
else { return nil }
|
||||
|
||||
return molecule
|
||||
|
||||
@ -13,7 +13,8 @@ public protocol TextInputDidDeleteProtocol: AnyObject {
|
||||
}
|
||||
|
||||
|
||||
@objcMembers open class TextField: UITextField {
|
||||
@objcMembers open class TextField: UITextField, ViewMaskingProtocol {
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
@ -23,6 +24,8 @@ public protocol TextInputDidDeleteProtocol: AnyObject {
|
||||
/// Set to true to hide the blinking textField cursor.
|
||||
public var hideBlinkingCaret = false
|
||||
|
||||
public var shouldMaskWhileRecording: Bool = true
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Delegate
|
||||
//--------------------------------------------------
|
||||
@ -97,6 +100,8 @@ extension TextField: MoleculeViewProtocol {
|
||||
if let accessibilityIdentifier = model.accessibilityIdentifier {
|
||||
self.accessibilityIdentifier = accessibilityIdentifier
|
||||
}
|
||||
|
||||
shouldMaskWhileRecording = model.shouldMaskRecordedView ?? true
|
||||
}
|
||||
|
||||
open func reset() {
|
||||
|
||||
@ -9,7 +9,8 @@
|
||||
import UIKit
|
||||
|
||||
|
||||
@objcMembers open class View: UIView, MoleculeViewProtocol {
|
||||
@objcMembers open class View: UIView, MoleculeViewProtocol, ViewMaskingProtocol {
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
@ -18,6 +19,10 @@ import UIKit
|
||||
|
||||
private var initialSetupPerformed = false
|
||||
|
||||
public var shouldMaskWhileRecording: Bool {
|
||||
return model?.shouldMaskRecordedView ?? false
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initialization
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -245,6 +245,27 @@ import UIKit
|
||||
manager?.newDataReceived?(in: self)
|
||||
}
|
||||
|
||||
public func generateMoleculeView(from model: MoleculeModelProtocol) -> MoleculeViewProtocol? {
|
||||
executeBehaviors { (behavior: PageMoleculeTransformationBehavior) in
|
||||
behavior.willSetupMolecule(with: model, updating: nil)
|
||||
}
|
||||
guard let moleculeView = ModelRegistry.createMolecule(model, delegateObject: delegateObjectIVar) else { return nil }
|
||||
executeBehaviors { (behavior: PageMoleculeTransformationBehavior) in
|
||||
behavior.didSetupMolecule(view: moleculeView, withModel: model)
|
||||
}
|
||||
return moleculeView
|
||||
}
|
||||
|
||||
public func updateMoleculeView(_ view: MoleculeViewProtocol, from model: MoleculeModelProtocol) {
|
||||
executeBehaviors { (behavior: PageMoleculeTransformationBehavior) in
|
||||
behavior.willSetupMolecule(with: model, updating: view)
|
||||
}
|
||||
view.set(with: model, delegateObjectIVar, nil)
|
||||
executeBehaviors { (behavior: PageMoleculeTransformationBehavior) in
|
||||
behavior.didSetupMolecule(view: view, withModel: model)
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Navigation Item
|
||||
//--------------------------------------------------
|
||||
@ -321,6 +342,14 @@ import UIKit
|
||||
}
|
||||
}
|
||||
|
||||
open override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
executeBehaviors { [weak self] (behavior: PageVisibilityBehavior) in
|
||||
behavior.willShowPage(self?.delegateObjectIVar)
|
||||
}
|
||||
}
|
||||
|
||||
open override func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
@ -329,6 +358,14 @@ import UIKit
|
||||
}
|
||||
}
|
||||
|
||||
open override func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
|
||||
executeBehaviors { [weak self] (behavior: PageVisibilityBehavior) in
|
||||
behavior.willHidePage(self?.delegateObjectIVar)
|
||||
}
|
||||
}
|
||||
|
||||
open override func viewDidDisappear(_ animated: Bool) {
|
||||
super.viewDidDisappear(animated)
|
||||
|
||||
|
||||
@ -14,12 +14,17 @@ public protocol PageBehaviorHandlerProtocol {
|
||||
public extension PageBehaviorHandlerProtocol {
|
||||
/// Creates the behaviors and sets the variable.
|
||||
mutating func createBehaviors(for model: PageBehaviorHandlerModelProtocol, delegateObject: MVMCoreUIDelegateObject?) {
|
||||
guard let behaviorModels = model.behaviors else {
|
||||
|
||||
behaviors = behaviors?.filter { $0.transcendsPageUpdates }
|
||||
if behaviors?.isEmpty ?? false {
|
||||
behaviors = nil
|
||||
}
|
||||
|
||||
guard let behaviorModels = model.behaviors else {
|
||||
return
|
||||
}
|
||||
|
||||
var behaviors: [PageBehaviorProtocol] = []
|
||||
var behaviors: [PageBehaviorProtocol] = behaviors ?? []
|
||||
|
||||
for behaviorModel in behaviorModels {
|
||||
do {
|
||||
|
||||
@ -9,25 +9,50 @@
|
||||
|
||||
public protocol PageBehaviorProtocol: ModelHandlerProtocol {
|
||||
|
||||
/// Should the behavior persist regardless of page behavior model updates.
|
||||
var transcendsPageUpdates: Bool { get }
|
||||
|
||||
/// Initializes the behavior with the model
|
||||
init(model: PageBehaviorModelProtocol, delegateObject: MVMCoreUIDelegateObject?)
|
||||
}
|
||||
|
||||
public extension PageBehaviorProtocol {
|
||||
var transcendsPageUpdates: Bool { return false }
|
||||
}
|
||||
|
||||
/**
|
||||
Behavior conforming protocols. Behaviors will conform to one or more of these protocols to receive page lifecycle events that pertain to them.
|
||||
*/
|
||||
|
||||
public protocol PageMoleculeTransformationBehavior: PageBehaviorProtocol {
|
||||
|
||||
func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject?)
|
||||
func willSetupMolecule(with model: MoleculeModelProtocol, updating view: MoleculeViewProtocol?)
|
||||
func didSetupMolecule(view: MoleculeViewProtocol, withModel: MoleculeModelProtocol)
|
||||
}
|
||||
|
||||
public extension PageMoleculeTransformationBehavior {
|
||||
// All optional.
|
||||
func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject?) {}
|
||||
func willSetupMolecule(with model: MoleculeModelProtocol, updating view: MoleculeViewProtocol?) {}
|
||||
func didSetupMolecule(view: MoleculeViewProtocol, withModel: MoleculeModelProtocol) {}
|
||||
}
|
||||
|
||||
public protocol PageVisibilityBehavior: PageBehaviorProtocol {
|
||||
|
||||
func willShowPage(_ delegateObject: MVMCoreUIDelegateObject?)
|
||||
func onPageShown(_ delegateObject: MVMCoreUIDelegateObject?)
|
||||
func willHidePage(_ delegateObject: MVMCoreUIDelegateObject?)
|
||||
func onPageHidden(_ delegateObject: MVMCoreUIDelegateObject?)
|
||||
}
|
||||
|
||||
public extension PageVisibilityBehavior {
|
||||
// All optional.
|
||||
func willShowPage(_ delegateObject: MVMCoreUIDelegateObject?) {}
|
||||
func onPageShown(_ delegateObject: MVMCoreUIDelegateObject?) {}
|
||||
func willHidePage(_ delegateObject: MVMCoreUIDelegateObject?) {}
|
||||
func onPageHidden(_ delegateObject: MVMCoreUIDelegateObject?) {}
|
||||
}
|
||||
|
||||
public protocol PageScrolledBehavior: PageBehaviorProtocol {
|
||||
|
||||
func pageScrolled(scrollView: UIScrollView, _ delegateObject: MVMCoreUIDelegateObject?)
|
||||
|
||||
@ -145,7 +145,9 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol,
|
||||
|
||||
open func shouldContinue(toErrorPage loadObject: MVMCoreLoadObject, error: MVMCoreErrorObject?) -> Bool {
|
||||
// Push error screens so they do not replace the tab page.
|
||||
loadObject.requestParameters?.navigationController = navigationController
|
||||
MVMCoreDispatchUtility.performSyncBlock(onMainThread: {
|
||||
loadObject.requestParameters?.navigationController = self.navigationController
|
||||
})
|
||||
loadObject.requestParameters?.loadStyle = .push
|
||||
return true
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
@class MFViewController;
|
||||
@class MFLoadingViewController;
|
||||
@class NavigationController;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface MVMCoreUISession : MVMCoreSessionObject
|
||||
@ -25,18 +26,21 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
/// Tracks the current page type the user is currently viewing. KVO compliant.
|
||||
@property (nonatomic, strong, nullable) NSString *currentPageType;
|
||||
|
||||
// for handscroll Animation on subclasses of MFScrollingViewController
|
||||
/// for handscroll Animation on subclasses of MFScrollingViewController
|
||||
@property (assign, nonatomic) BOOL enableHandScrollAnimation;
|
||||
|
||||
//indicates if the app launched successfully
|
||||
/// indicates if the app launched successfully
|
||||
@property (assign, nonatomic) BOOL launchAppLoadedSuccessfully;
|
||||
|
||||
// Allows a global overload of the title view of navigation item.
|
||||
/// Allows a global overload of the title view of navigation item.
|
||||
- (nullable UIView *)titleViewForController:(nonnull MFViewController *)controller;
|
||||
|
||||
// Sets up the session as delegate for standard load view controller. Pass the view controller that will be used to present and will be disabled when load view is presented.
|
||||
/// Sets up the session as delegate for standard load view controller. Pass the view controller that will be used to present and will be disabled when load view is presented.
|
||||
- (void)setupAsStandardLoadViewDelegate:(nonnull UIViewController *)mainViewController;
|
||||
|
||||
/// Applies additional behaviors to a controller according to the session. Allows for packages to add additional cross cutting concerns.
|
||||
- (void)applyGlobalBehaviorsToController:(nonnull UIViewController *)viewController;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@ -62,4 +62,8 @@
|
||||
self.mainViewController.view.userInteractionEnabled = YES;
|
||||
}
|
||||
|
||||
- (void)applyGlobalBehaviorsToController:(nonnull UIViewController *)viewController {
|
||||
// Allow extending frameworks to apply behaviors to add cross cutting concerns to the base controllers.
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Loading…
Reference in New Issue
Block a user