From 8eae881bf1539d972196cc15b55eeae86543cf22 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Mon, 24 Jun 2019 10:47:43 -0400 Subject: [PATCH] code review --- MVMCoreUI/FormUIHelpers/FormValidator.swift | 2 +- MVMCoreUI/Molecules/RadioButton.swift | 48 ++++++-- MVMCoreUI/Molecules/RadioButtonList.swift | 113 ------------------ MVMCoreUI/Styles/MFStyler.h | 2 - .../Strings/en.lproj/Localizable.strings | 7 ++ .../Templates/MoleculeStackTemplate.swift | 16 +-- 6 files changed, 53 insertions(+), 135 deletions(-) delete mode 100644 MVMCoreUI/Molecules/RadioButtonList.swift diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index af40b2de..91928f3e 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -16,7 +16,7 @@ import UIKit var extraValidationBlock: (() -> Bool)? var radioButtonsModelByGroup: [String: RadioButtonModel] = [:] - public func insertMolecule(_ molecule: FormValidationProtocol) { + public func insertMolecule(_ molecule: FormValidationProtocol) { molecules.append(molecule) } diff --git a/MVMCoreUI/Molecules/RadioButton.swift b/MVMCoreUI/Molecules/RadioButton.swift index 90c4fd5e..ad9e72e7 100644 --- a/MVMCoreUI/Molecules/RadioButton.swift +++ b/MVMCoreUI/Molecules/RadioButton.swift @@ -45,22 +45,35 @@ import UIKit radioButton.translatesAutoresizingMaskIntoConstraints = false addSubview(radioButton) + isAccessibilityElement = true + accessibilityTraits = .none + accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "radio_action_hint") radioButton.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor, constant: 0).isActive = true - radioButton.topAnchor.constraint(greaterThanOrEqualTo: topAnchor, constant: PaddingOne).isActive = true - bottomAnchor.constraint(greaterThanOrEqualTo: radioButton.bottomAnchor, constant: PaddingOne).isActive = true + var constraint = radioButton.topAnchor.constraint(greaterThanOrEqualTo: topAnchor, constant: PaddingOne) + constraint.priority = .defaultLow + constraint.isActive = true + + constraint = bottomAnchor.constraint(greaterThanOrEqualTo: radioButton.bottomAnchor, constant: PaddingOne) + constraint.priority = .defaultLow + constraint.isActive = true + radioButton.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true if let rightView = createRightView() { addSubview(rightView) rightView.leftAnchor.constraint(equalTo: radioButton.rightAnchor, constant: PaddingHorizontalBetweenRelatedItems).isActive = true rightView.rightAnchor.constraint(equalTo: layoutMarginsGuide.rightAnchor, constant: 0).isActive = true - rightView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor, constant: PaddingOne).isActive = true - rightView.bottomAnchor.constraint(greaterThanOrEqualTo: bottomAnchor, constant: PaddingOne).isActive = true - rightView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true + + constraint = rightView.topAnchor.constraint(equalTo: topAnchor, constant: PaddingOne) + constraint.priority = .defaultHigh + constraint.isActive = true + + constraint = bottomAnchor.constraint(greaterThanOrEqualTo: rightView.bottomAnchor, constant: PaddingOne) + constraint.priority = .defaultHigh + constraint.isActive = true } addActionHandler() - addActionHandler() } func createRightView() -> ViewConstrainingView? { @@ -92,7 +105,8 @@ import UIKit } else { radioButton.isSelected = !radioButton.isSelected } - FormValidator.enableByValidationWith(delegate: self.delegateObject?.formValidationProtocol) + FormValidator.enableByValidationWith(delegate: delegateObject?.formValidationProtocol) + changeAccessibilityLabel() } } @@ -113,20 +127,21 @@ extension RadioButton { self.delegateObject = delegateObject radioButtonModel = RadioButtonModel.setupForRadioButtonGroup(radioButton: self, - formValidator: self.delegateObject?.formValidationProtocol?.formValidatorModel?()) + formValidator: delegateObject?.formValidationProtocol?.formValidatorModel?()) /* If the radio button has a group, it will have RadioButtonModel. In this case the RadioButtonModel should be the validator */ if let radioButtonModel = radioButtonModel { - FormValidator.setupValidation(molecule: radioButtonModel, delegate: self.delegateObject?.formValidationProtocol) + FormValidator.setupValidation(molecule: radioButtonModel, delegate: delegateObject?.formValidationProtocol) } else { - FormValidator.setupValidation(molecule: self, delegate: self.delegateObject?.formValidationProtocol) + FormValidator.setupValidation(molecule: self, delegate: delegateObject?.formValidationProtocol) } label.setWithJSON(jsonDictionary.optionalDictionaryForKey(KeyLabel), delegateObject: delegateObject, additionalData: additionalData) + changeAccessibilityLabel() } } @@ -146,8 +161,19 @@ extension RadioButton: FormValidationProtocol { return radioButtonModel?.formFieldName() ?? json?.optionalStringForKey("fieldKey") } - // The Feild value key value paid for sending to server + // The Field value key value pair for sending to server @objc public func formFieldValue() -> Any? { return radioButtonModel?.formFieldValue() ?? radioButton.isSelected } } + +// MARK: Accessibility +extension RadioButton { + func changeAccessibilityLabel() { + let stateString = radioButton.isSelected ? "radio_selected_state" : "radio_not_selected_state" + let localizedStringState = MVMCoreUIUtility.hardcodedString(withKey: stateString) ?? "" + let accebilityString = (label.accessibilityLabel ?? (json?.optionalStringForKey("accessibilityText") ?? "")) + + (MVMCoreUIUtility.hardcodedString(withKey: "radio_desc_state") ?? "") + localizedStringState + accessibilityLabel = accebilityString + } +} diff --git a/MVMCoreUI/Molecules/RadioButtonList.swift b/MVMCoreUI/Molecules/RadioButtonList.swift deleted file mode 100644 index 1b597214..00000000 --- a/MVMCoreUI/Molecules/RadioButtonList.swift +++ /dev/null @@ -1,113 +0,0 @@ -// -// RadioButton.swift -// MVMCoreUI -// -// Created by Suresh, Kamlesh on 4/9/19. -// Copyright © 2019 Verizon Wireless. All rights reserved. -// - -import UIKit - -@objc public protocol RadioButtonListProtocol: NSObjectProtocol { - - @objc optional func selected(_ radioButton: RadioButton) -} - -@objcMembers open class RadioButtonList: ViewConstrainingView, RadioButtonListProtocol { - - var selectedRadioButton: RadioButton? - var selectedValue: String? - var delegateObject:MVMCoreUIDelegateObject? - - - // MARK: - Inits - public init() { - super.init(frame: .zero) - } - - public override init(frame: CGRect) { - super.init(frame: frame) - } - - required public init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - } - - public func selected(_ radioButton: RadioButton) { - selectedRadioButton?.radioButton.isSelected = false - selectedRadioButton = radioButton - selectedRadioButton?.radioButton.isSelected = true - - FormValidator.enableByValidationWith(delegate: self.delegateObject?.formValidationProtocol) - } - - open override func setupView() { - super.setupView() - self.translatesAutoresizingMaskIntoConstraints = false - } -} - -// MARK: - FormValidationProtocol -extension RadioButtonList: FormValidationProtocol { - // Used to check the validity of the field, to enable/disable the primary button. - @objc public func isValidField() -> Bool { - if !(json?.boolForKey("required") ?? true) { - return true - } - return selectedRadioButton != nil - } - - // The Field name key value pair for sending to server - @objc public func formFieldName() -> String? { - return json?.optionalStringForKey("fieldKey") - } - - // The Feild value key value paid for sending to server - @objc public func formFieldValue() -> Any? { - return selectedRadioButton?.formFieldValue() - } -} - -// MARK: - MVMCoreUIMoleculeViewProtocol -extension RadioButtonList { - - open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) { - super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - - // Configure class properties with JSON values - guard let jsonDictionary = json, - let optionsList = jsonDictionary.optionalArrayForKey("optionsList") as? [[AnyHashable: Any]], - let delegateObject = delegateObject as? MVMCoreUIDelegateObject else { - return - } - - self.delegateObject = delegateObject - FormValidator.setupValidation(molecule: self, delegate: delegateObject.formValidationProtocol) - - StackableViewController.remove(self.subviews) - - var items:[UIView] = [] - for option in optionsList { - let radioButton = RadioButton(target: self) - radioButton.setWithJSON(option, delegateObject: delegateObject, additionalData: nil) - items.append(radioButton) - } - - let verticalSpace = MFStyler.defaultVerticalPaddingForApplicationWidth() - StackableViewController.populateView(self, - withUIArray: items) { (item) -> UIEdgeInsets in - return UIEdgeInsets(top: verticalSpace, - left: 0, - bottom: 0, - right: 0) - } - } - - open override func needsToBeConstrained() -> Bool { - return true - } - - open override func moleculeAlignment() -> UIStackView.Alignment { - return UIStackView.Alignment.leading; - } -} diff --git a/MVMCoreUI/Styles/MFStyler.h b/MVMCoreUI/Styles/MFStyler.h index 095426ad..f5632dca 100644 --- a/MVMCoreUI/Styles/MFStyler.h +++ b/MVMCoreUI/Styles/MFStyler.h @@ -35,8 +35,6 @@ extern CGFloat const PaddingHorizontalLarge; extern CGFloat const PaddingVerticalWhiteGrayView; extern CGFloat const PaddingVerticalHeadlineAlternate; extern CGFloat const PaddingPrimaryButtonTop; - -// extern CGFloat const PaddingHorizontalBetweenRelatedItems; // These are based on the multiple of 6 rule diff --git a/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings b/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings index 96088cab..8bfb4511 100644 --- a/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings +++ b/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings @@ -35,6 +35,13 @@ "checkbox_checked_state" = "Checked"; "checkbox_unchecked_state" = "Unchecked"; "checkbox_desc_state" = "%@ CheckBox %@"; + +// Radio Button +"radio_action_hint" = "Double tap to select"; +"radio_selected_state" = "Selected"; +"radio_not_selected_state" = "Not Selected"; +"radio_desc_state" = "Option"; + // Switch "mfswitch_buttonlabel" = "Switch Button"; "AccOn" = "on"; diff --git a/MVMCoreUI/Templates/MoleculeStackTemplate.swift b/MVMCoreUI/Templates/MoleculeStackTemplate.swift index 3f5e04da..1fb6e0c8 100644 --- a/MVMCoreUI/Templates/MoleculeStackTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeStackTemplate.swift @@ -8,9 +8,9 @@ import UIKit -public class MoleculeStackTemplate: ThreeLayerViewController { +open class MoleculeStackTemplate: ThreeLayerViewController { - public override func shouldFinishProcessingLoad(_ loadObject: MVMCoreLoadObject, error: AutoreleasingUnsafeMutablePointer) -> Bool { + open override func shouldFinishProcessingLoad(_ loadObject: MVMCoreLoadObject, error: AutoreleasingUnsafeMutablePointer) -> Bool { var shouldFinish = super.shouldFinishProcessingLoad(loadObject, error: error) if shouldFinish, let firstError = modulesNeeded().errors?.first { // Don't continue if there was an error loading needed modules. @@ -20,25 +20,25 @@ public class MoleculeStackTemplate: ThreeLayerViewController { return shouldFinish } - public override func spaceBetweenTopAndMiddle() -> CGFloat? { + open override func spaceBetweenTopAndMiddle() -> CGFloat? { return 0 } - public override func viewForTop() -> UIView? { + open override func viewForTop() -> UIView? { guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("header"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else { return nil } return molecule } - public override func viewForMiddle() -> UIView? { + open override func viewForMiddle() -> UIView? { guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("moleculeStack") else { return nil } return MoleculeStackView(withJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, additionalData: nil) } - override public func viewForBottom() -> UIView? { + override open func viewForBottom() -> UIView? { guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("footer"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else { return nil } @@ -46,14 +46,14 @@ public class MoleculeStackTemplate: ThreeLayerViewController { } // MARK: - cache handling - public override func pageTypesToListenFor() -> [Any]? { + open override func pageTypesToListenFor() -> [Any]? { guard let pageType = self.pageType else { return super.pageTypesToListenFor() } return [pageType] } - public override func modulesToListenFor() -> [Any]? { + open override func modulesToListenFor() -> [Any]? { // Get all of the molecules that need modules. return modulesNeeded().modules }