Merge branch 'develop' into bugfix/CXTDT-139439

* develop: (24 commits)
  Moved isSecureTextEntry as false to reset method.
  undo label
  fix
  Added isSecureTextEntry as false for number keyboard type.
  revised
  validator check
  Added keyboardtype in default case.
  added selectable flag to match how android validates
  undo testing change
  Changes for form validator to work
  Code changes after review comment.
  revised
  undo
  undo
  error check.
  styler additon. label width value
  changed access specifier public to open for Button model and static property to class property
  reverting code which was added for infinite loop crash only in ipads and force crash
  infinite loop crash fix in setting up bottom progress bar
  Carousel form changes
  ...
This commit is contained in:
Damodaram 2021-03-12 16:26:28 +05:30
commit d25d75fea0
14 changed files with 124 additions and 21 deletions

View File

@ -11,12 +11,14 @@ import UIKit
public typealias FacadeElements = (fill: UIColor?, text: UIColor?, border: UIColor?) public typealias FacadeElements = (fill: UIColor?, text: UIColor?, border: UIColor?)
public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWatcherFieldProtocol, EnableableModelProtocol { open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWatcherFieldProtocol, EnableableModelProtocol {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
//Making static property as class property so that subclasses can override getter function of the property
public static var identifier: String = "button" open class var identifier: String {
"button"
}
public var backgroundColor: Color? public var backgroundColor: Color?
public var accessibilityIdentifier: String? public var accessibilityIdentifier: String?
public var title: String public var title: String
@ -247,7 +249,7 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupW
} }
} }
public func encode(to encoder: Encoder) throws { open func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName) try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(title, forKey: .title) try container.encode(title, forKey: .title)

View File

@ -319,12 +319,14 @@ import UIKit
model.updateUIDynamicError = { [weak self] in model.updateUIDynamicError = { [weak self] in
MVMCoreDispatchUtility.performBlock(onMainThread: { MVMCoreDispatchUtility.performBlock(onMainThread: {
guard let self = self else { return } guard let self = self else { return }
let validState = model.isValid ?? false let validState = model.isValid ?? false
self.updateValidation(validState)
if !validState && model.shouldClearText { if !validState && model.shouldClearText {
self.text = "" self.text = ""
model.shouldClearText = false model.shouldClearText = false
} }
_ = FormValidator.validate(delegate: self.delegateObject?.formHolderDelegate)
self.updateValidation(validState)
}) })
} }

View File

@ -147,6 +147,16 @@ import MVMCore
MVMCoreNavigationHandler.shared()?.present(picker, animated: true) MVMCoreNavigationHandler.shared()?.present(picker, animated: true)
} }
//--------------------------------------------------
// MARK: - MoleculeViewProtocol
//--------------------------------------------------
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData)
textField.keyboardType = .phonePad
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Contact Picker Delegate // MARK: - Contact Picker Delegate
//-------------------------------------------------- //--------------------------------------------------

View File

@ -200,6 +200,7 @@ import UIKit
open override func reset() { open override func reset() {
super.reset() super.reset()
textField.isSecureTextEntry = false
textField.font = Styler.Font.RegularBodyLarge.getFont() textField.font = Styler.Font.RegularBodyLarge.getFont()
} }
@ -350,7 +351,8 @@ import UIKit
case .phone: case .phone:
textField.keyboardType = .phonePad textField.keyboardType = .phonePad
default: break default:
textField.keyboardType = .default
} }
// Override the preset keyboard set in type. // Override the preset keyboard set in type.

View File

@ -22,7 +22,7 @@
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
// Fill for left vertical alignment because bottom constraint was breaking with leading. CXTDT-145456 // Fill for left vertical alignment because bottom constraint was breaking with leading. CXTDT-145456
stack = Stack<StackModel>.createStack(with: [(view: eyebrowHeadlineBodyLink, model: StackItemModel(horizontalAlignment: .leading, verticalAlignment: .fill)), (view: rightLabel, model: StackItemModel(horizontalAlignment:.fill, verticalAlignment: .leading))], axis: .horizontal) stack = Stack<StackModel>.createStack(with: [(view: eyebrowHeadlineBodyLink, model: StackItemModel(horizontalAlignment: .leading, verticalAlignment: .fill)), (view: rightLabel, model: StackItemModel(horizontalAlignment: .trailing, verticalAlignment: .leading))], axis: .horizontal)
super.init(style: style, reuseIdentifier: reuseIdentifier) super.init(style: style, reuseIdentifier: reuseIdentifier)
} }
@ -37,6 +37,8 @@
open override func setupView() { open override func setupView() {
super.setupView() super.setupView()
rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal) rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal)
rightLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 900), for: .horizontal)
rightLabel.numberOfLines = 1
addMolecule(stack) addMolecule(stack)
stack.restack() stack.restack()
} }

View File

@ -21,6 +21,9 @@ import Foundation
public var peakingUI: Bool? public var peakingUI: Bool?
public var peakingArrowColor: Color? public var peakingArrowColor: Color?
public var analyticsData: JSONValueDictionary? public var analyticsData: JSONValueDictionary?
public var fieldValue: String?
public func formFieldValue() -> AnyHashable? { return fieldValue }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Keys // MARK: - Keys
@ -30,6 +33,7 @@ import Foundation
case peakingUI case peakingUI
case peakingArrowColor case peakingArrowColor
case analyticsData case analyticsData
case fieldValue
} }
//-------------------------------------------------- //--------------------------------------------------
@ -41,6 +45,7 @@ import Foundation
peakingUI = try typeContainer.decodeIfPresent(Bool.self, forKey: .peakingUI) peakingUI = try typeContainer.decodeIfPresent(Bool.self, forKey: .peakingUI)
peakingArrowColor = try typeContainer.decodeIfPresent(Color.self, forKey: .peakingArrowColor) peakingArrowColor = try typeContainer.decodeIfPresent(Color.self, forKey: .peakingArrowColor)
analyticsData = try typeContainer.decodeIfPresent(JSONValueDictionary.self, forKey: .analyticsData) analyticsData = try typeContainer.decodeIfPresent(JSONValueDictionary.self, forKey: .analyticsData)
fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue)
try super.init(from: decoder) try super.init(from: decoder)
} }
@ -50,5 +55,6 @@ import Foundation
try container.encodeIfPresent(peakingUI, forKey: .peakingUI) try container.encodeIfPresent(peakingUI, forKey: .peakingUI)
try container.encodeIfPresent(peakingArrowColor, forKey: .peakingArrowColor) try container.encodeIfPresent(peakingArrowColor, forKey: .peakingArrowColor)
try container.encodeIfPresent(analyticsData, forKey: .analyticsData) try container.encodeIfPresent(analyticsData, forKey: .analyticsData)
try container.encodeIfPresent(fieldValue, forKey: .fieldValue)
} }
} }

View File

@ -167,12 +167,17 @@ open class Carousel: View {
registerCells(with: carouselModel, delegateObject: delegateObject) registerCells(with: carouselModel, delegateObject: delegateObject)
prepareMolecules(with: carouselModel) prepareMolecules(with: carouselModel)
FormValidator.setupValidation(for: carouselModel, delegate: delegateObject?.formHolderDelegate)
setupPagingMolecule(carouselModel.pagingMolecule, delegateObject: delegateObject) setupPagingMolecule(carouselModel.pagingMolecule, delegateObject: delegateObject)
pageIndex = carouselModel.index pageIndex = carouselModel.index
pagingView?.currentIndex = carouselModel.index pagingView?.currentIndex = carouselModel.index
collectionView.reloadData() collectionView.reloadData()
if let selectedIndex = carouselModel.selectedIndex {
let adjustedIndex = loop ? selectedIndex + 2 : selectedIndex
collectionView.selectItem(at: IndexPath(row: adjustedIndex, section: 0), animated: false, scrollPosition: [])
}
} }
//-------------------------------------------------- //--------------------------------------------------
@ -391,8 +396,25 @@ extension Carousel: UICollectionViewDataSource {
} }
extension Carousel: UICollectionViewDelegate { extension Carousel: UICollectionViewDelegate {
public func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
guard let cell = collectionView.cellForItem(at: indexPath) as? CollectionTemplateItemProtocol else { return false }
return cell.shouldSelect(at: indexPath, delegateObject: delegateObject, additionalData: nil)
}
open func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { open func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
(collectionView.cellForItem(at: indexPath) as? CollectionTemplateItemProtocol)?.didSelectCell(at: indexPath, delegateObject: delegateObject, additionalData: nil) // Set the selection in the model
if let model = model as? CarouselModel {
// Adjust for looping
var adjustedIndex = loop ? indexPath.row - 2 : indexPath.row
if adjustedIndex < 0 {
adjustedIndex = adjustedIndex + numberOfPages
}
model.selectedIndex = adjustedIndex
}
if let cell = collectionView.cellForItem(at: indexPath) as? CollectionTemplateItemProtocol {
cell.didSelectCell(at: indexPath, delegateObject: delegateObject, additionalData: nil)
}
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
} }
} }
@ -414,6 +436,7 @@ extension Carousel: UIScrollViewDelegate {
if !animated { if !animated {
scrollViewDidEndScrollingAnimation(collectionView) scrollViewDidEndScrollingAnimation(collectionView)
} }
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
} }
/// Adjusts the current contentOffset if we are going onto buffer cells while looping to help with the endless scrolling appearance. /// Adjusts the current contentOffset if we are going onto buffer cells while looping to help with the endless scrolling appearance.

View File

@ -9,7 +9,8 @@
import UIKit import UIKit
@objcMembers public class CarouselModel: MoleculeModelProtocol { @objcMembers public class CarouselModel: MoleculeModelProtocol, FormFieldProtocol {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
@ -33,11 +34,31 @@ import UIKit
public var leftPadding: CGFloat? public var leftPadding: CGFloat?
public var rightPadding: CGFloat? public var rightPadding: CGFloat?
public var accessibilityText: String? public var accessibilityText: String?
public var baseValue: AnyHashable?
public var fieldKey: String?
public var groupName: String = FormValidator.defaultGroupName
public var selectable = false
public var selectedIndex: Int?
public init(molecules: [MoleculeModelProtocol & CarouselItemModelProtocol]) { public init(molecules: [MoleculeModelProtocol & CarouselItemModelProtocol]) {
self.molecules = molecules self.molecules = molecules
} }
public func formFieldValue() -> AnyHashable? {
guard selectable else {
// Use visible item value, else index
if let fieldValue = molecules[index].formFieldValue() {
return fieldValue
}
return index
}
// Use selected item value, else index
guard let selectedIndex = selectedIndex else { return nil }
guard let fieldValue = molecules[selectedIndex].formFieldValue() else { return selectedIndex }
return fieldValue
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Keys // MARK: - Keys
//-------------------------------------------------- //--------------------------------------------------
@ -59,6 +80,10 @@ import UIKit
case leftPadding case leftPadding
case rightPadding case rightPadding
case accessibilityText case accessibilityText
case groupName
case fieldKey
case selectable
case selectedIndex
} }
//-------------------------------------------------- //--------------------------------------------------
@ -69,6 +94,8 @@ import UIKit
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
molecules = try typeContainer.decodeModels(codingKey: .molecules) molecules = try typeContainer.decodeModels(codingKey: .molecules)
index = try typeContainer.decodeIfPresent(Int.self, forKey: .index) ?? 0 index = try typeContainer.decodeIfPresent(Int.self, forKey: .index) ?? 0
selectable = try typeContainer.decodeIfPresent(Bool.self, forKey: .selectable) ?? false
selectedIndex = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedIndex)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing) spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing)
border = try typeContainer.decodeIfPresent(Bool.self, forKey: .border) border = try typeContainer.decodeIfPresent(Bool.self, forKey: .border)
@ -86,6 +113,11 @@ import UIKit
leftPadding = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .leftPadding) leftPadding = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .leftPadding)
rightPadding = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .rightPadding) rightPadding = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .rightPadding)
accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText) accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
self.groupName = groupName
}
baseValue = formFieldValue()
} }
public func encode(to encoder: Encoder) throws { public func encode(to encoder: Encoder) throws {
@ -105,5 +137,10 @@ import UIKit
try container.encodeIfPresent(leftPadding, forKey: .leftPadding) try container.encodeIfPresent(leftPadding, forKey: .leftPadding)
try container.encodeIfPresent(rightPadding, forKey: .rightPadding) try container.encodeIfPresent(rightPadding, forKey: .rightPadding)
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText) try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
try container.encode(groupName, forKey: .groupName)
try container.encode(index, forKey: .index)
try container.encode(selectable, forKey: .selectable)
try container.encode(selectedIndex, forKey: .selectedIndex)
} }
} }

View File

@ -11,11 +11,14 @@ import Foundation
public protocol CarouselItemModelProtocol: ContainerModelProtocol { public protocol CarouselItemModelProtocol: ContainerModelProtocol {
var analyticsData: JSONValueDictionary? { get set } var analyticsData: JSONValueDictionary? { get set }
func formFieldValue() -> AnyHashable?
} }
public extension CarouselItemModelProtocol { public extension CarouselItemModelProtocol {
var analyticsData: JSONValueDictionary? { var analyticsData: JSONValueDictionary? {
get { return nil } get { return nil }
set { analyticsData = newValue } set { analyticsData = newValue }
} }
func formFieldValue() -> AnyHashable? { return nil }
} }

View File

@ -19,6 +19,9 @@ public protocol CollectionTemplateItemProtocol: UICollectionViewCell {
/// Called when the cell will display. /// Called when the cell will display.
func willDisplay() func willDisplay()
/// Handle the selection of cell
func shouldSelect(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> Bool
} }
// Default implementation does nothing // Default implementation does nothing
@ -26,4 +29,8 @@ extension CollectionTemplateItemProtocol {
public func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {} public func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {}
public func willDisplay() {} public func willDisplay() {}
public func shouldSelect(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> Bool {
return false
}
} }

View File

@ -116,11 +116,15 @@ open class CollectionViewCell: UICollectionViewCell, MoleculeViewProtocol, MVMCo
// MARK: - Override // MARK: - Override
open func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { open func shouldSelect(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> Bool {
guard let action = model?.action else { return } if let action = model?.action {
Button.performButtonAction(with: action, button: self, delegateObject: delegateObject, additionalData: additionalData) Button.performButtonAction(with: action, button: self, delegateObject: delegateObject, additionalData: additionalData)
}
return false
} }
open func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {}
// Column logic, set width. // Column logic, set width.
override open func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes { override open func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
let autoLayoutAttributes = super.preferredLayoutAttributesFitting(layoutAttributes) let autoLayoutAttributes = super.preferredLayoutAttributesFitting(layoutAttributes)

View File

@ -461,7 +461,7 @@ import UIKit
open func handleOpenPage(for requestParameters: MVMCoreRequestParameters, actionInformation: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?) { open func handleOpenPage(for requestParameters: MVMCoreRequestParameters, actionInformation: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?) {
addFormParams(requestParameters) addFormParams(requestParameters)
requestParameters.parentPageType = loadObject?.pageJSON?.optionalStringForKey("parentPageType") requestParameters.parentPageType = loadObject?.pageJSON?.optionalStringForKey("parentPageType")
MVMCoreActionHandler.defaultHandleOpenPage(for: requestParameters, additionalData: additionalData, delegateObject: delegateObject()) MVMCoreActionHandler.defaultHandleOpenPage(for: requestParameters, actionInformation: actionInformation, additionalData: additionalData, delegateObject: delegateObject())
} }
open func logAction(withActionInformation actionInformation: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?) { open func logAction(withActionInformation actionInformation: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?) {

View File

@ -6,8 +6,6 @@
// Copyright © 2020 Verizon Wireless. All rights reserved. // Copyright © 2020 Verizon Wireless. All rights reserved.
// //
import Foundation
/// Padding is a multiple based on the number 4. /// Padding is a multiple based on the number 4.
public struct Padding { public struct Padding {
@ -30,19 +28,19 @@ public struct Padding {
public static let VerticalMarginSpacing: CGFloat = 24 public static let VerticalMarginSpacing: CGFloat = 24
public static var horizontalPaddingForApplicationWidth: CGFloat { public static var horizontalPaddingForApplicationWidth: CGFloat {
return MFSizeObject(scalingStandardSize: HorizontalMarginSpacing)?.getValueBasedOnApplicationWidth() ?? HorizontalMarginSpacing MFSizeObject(scalingStandardSize: HorizontalMarginSpacing)?.getValueBasedOnApplicationWidth() ?? HorizontalMarginSpacing
} }
public static var verticalPaddingForApplicationWidth: CGFloat { public static var verticalPaddingForApplicationWidth: CGFloat {
return MFSizeObject(scalingStandardSize: VerticalMarginSpacing)?.getValueBasedOnApplicationWidth() ?? VerticalMarginSpacing MFSizeObject(scalingStandardSize: VerticalMarginSpacing)?.getValueBasedOnApplicationWidth() ?? VerticalMarginSpacing
} }
public static func horizontalPaddingForSize(_ size: CGFloat) -> CGFloat { public static func horizontalPaddingForSize(_ size: CGFloat) -> CGFloat {
return MFSizeObject(scalingStandardSize: HorizontalMarginSpacing)?.getValueBased(onSize: size) ?? HorizontalMarginSpacing MFSizeObject(scalingStandardSize: HorizontalMarginSpacing)?.getValueBased(onSize: size) ?? HorizontalMarginSpacing
} }
public static func verticalPaddingForSize(_ size: CGFloat) -> CGFloat { public static func verticalPaddingForSize(_ size: CGFloat) -> CGFloat {
return MFSizeObject(scalingStandardSize: VerticalMarginSpacing)?.getValueBased(onSize: size) ?? VerticalMarginSpacing MFSizeObject(scalingStandardSize: VerticalMarginSpacing)?.getValueBased(onSize: size) ?? VerticalMarginSpacing
} }
} }
} }

View File

@ -209,7 +209,14 @@ open class Styler {
} }
open class func sizeFontGeneric(forCurrentDevice size: CGFloat) -> CGFloat { open class func sizeFontGeneric(forCurrentDevice size: CGFloat) -> CGFloat {
return sizeObjectGeneric(forCurrentDevice: size)?.getValueBasedOnApplicationWidth() ?? size sizeObjectGeneric(forCurrentDevice: size)?.getValueBasedOnApplicationWidth() ?? size
}
/// Provide additional size information to help calculate its intrinsic height.
/// - Returns: The available spacing that can be used for intrinsic content width.
open class func maxAvailableLayoutWidth(size: CGFloat) -> CGFloat {
// The 2 is the product of both sides of padding.
size - (Padding.Component.horizontalPaddingForSize(size) * 2)
} }
//-------------------------------------------------- //--------------------------------------------------