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 class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWatcherFieldProtocol, EnableableModelProtocol {
open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWatcherFieldProtocol, EnableableModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public static var identifier: String = "button"
//Making static property as class property so that subclasses can override getter function of the property
open class var identifier: String {
"button"
}
public var backgroundColor: Color?
public var accessibilityIdentifier: 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)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(title, forKey: .title)

View File

@ -319,12 +319,14 @@ import UIKit
model.updateUIDynamicError = { [weak self] in
MVMCoreDispatchUtility.performBlock(onMainThread: {
guard let self = self else { return }
let validState = model.isValid ?? false
self.updateValidation(validState)
if !validState && model.shouldClearText {
self.text = ""
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)
}
//--------------------------------------------------
// 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
//--------------------------------------------------

View File

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

View File

@ -22,7 +22,7 @@
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
// 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)
}
@ -37,6 +37,8 @@
open override func setupView() {
super.setupView()
rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal)
rightLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 900), for: .horizontal)
rightLabel.numberOfLines = 1
addMolecule(stack)
stack.restack()
}

View File

@ -21,6 +21,9 @@ import Foundation
public var peakingUI: Bool?
public var peakingArrowColor: Color?
public var analyticsData: JSONValueDictionary?
public var fieldValue: String?
public func formFieldValue() -> AnyHashable? { return fieldValue }
//--------------------------------------------------
// MARK: - Keys
@ -30,6 +33,7 @@ import Foundation
case peakingUI
case peakingArrowColor
case analyticsData
case fieldValue
}
//--------------------------------------------------
@ -41,6 +45,7 @@ import Foundation
peakingUI = try typeContainer.decodeIfPresent(Bool.self, forKey: .peakingUI)
peakingArrowColor = try typeContainer.decodeIfPresent(Color.self, forKey: .peakingArrowColor)
analyticsData = try typeContainer.decodeIfPresent(JSONValueDictionary.self, forKey: .analyticsData)
fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue)
try super.init(from: decoder)
}
@ -50,5 +55,6 @@ import Foundation
try container.encodeIfPresent(peakingUI, forKey: .peakingUI)
try container.encodeIfPresent(peakingArrowColor, forKey: .peakingArrowColor)
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)
prepareMolecules(with: carouselModel)
FormValidator.setupValidation(for: carouselModel, delegate: delegateObject?.formHolderDelegate)
setupPagingMolecule(carouselModel.pagingMolecule, delegateObject: delegateObject)
pageIndex = carouselModel.index
pagingView?.currentIndex = carouselModel.index
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 {
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) {
(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 {
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.

View File

@ -9,7 +9,8 @@
import UIKit
@objcMembers public class CarouselModel: MoleculeModelProtocol {
@objcMembers public class CarouselModel: MoleculeModelProtocol, FormFieldProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
@ -33,11 +34,31 @@ import UIKit
public var leftPadding: CGFloat?
public var rightPadding: CGFloat?
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]) {
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
//--------------------------------------------------
@ -59,6 +80,10 @@ import UIKit
case leftPadding
case rightPadding
case accessibilityText
case groupName
case fieldKey
case selectable
case selectedIndex
}
//--------------------------------------------------
@ -69,6 +94,8 @@ import UIKit
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
molecules = try typeContainer.decodeModels(codingKey: .molecules)
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)
spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing)
border = try typeContainer.decodeIfPresent(Bool.self, forKey: .border)
@ -86,6 +113,11 @@ import UIKit
leftPadding = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .leftPadding)
rightPadding = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .rightPadding)
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 {
@ -105,5 +137,10 @@ import UIKit
try container.encodeIfPresent(leftPadding, forKey: .leftPadding)
try container.encodeIfPresent(rightPadding, forKey: .rightPadding)
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 {
var analyticsData: JSONValueDictionary? { get set }
func formFieldValue() -> AnyHashable?
}
public extension CarouselItemModelProtocol {
var analyticsData: JSONValueDictionary? {
get { return nil }
set { analyticsData = newValue }
}
func formFieldValue() -> AnyHashable? { return nil }
}

View File

@ -19,6 +19,9 @@ public protocol CollectionTemplateItemProtocol: UICollectionViewCell {
/// Called when the cell will display.
func willDisplay()
/// Handle the selection of cell
func shouldSelect(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> Bool
}
// Default implementation does nothing
@ -26,4 +29,8 @@ extension CollectionTemplateItemProtocol {
public func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {}
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
open func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {
guard let action = model?.action else { return }
Button.performButtonAction(with: action, button: self, delegateObject: delegateObject, additionalData: additionalData)
open func shouldSelect(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> Bool {
if let action = model?.action {
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.
override open func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
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]?) {
addFormParams(requestParameters)
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]?) {

View File

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