Merge branch 'develop' of https://gitlab.verizon.com/BPHV_MIPS/mvm_core_ui into feature/native_mockups

This commit is contained in:
Scott Pfeil 2023-03-09 11:22:13 -05:00
commit 425ec9ea20
31 changed files with 240 additions and 69 deletions

View File

@ -22,9 +22,9 @@ download_artifacts:
- bash_shell - bash_shell
environment: environment:
name: oneartifactory name: oneartifactory
url: https://oneartifactoryprod.verizon.com/artifactory url: https://oneartifactoryci.verizon.com/artifactory
variables: variables:
ARTIFACTORY_URL: https://oneartifactoryprod.verizon.com/artifactory ARTIFACTORY_URL: https://oneartifactoryci.verizon.com/artifactory
build_project: build_project:
stage: build stage: build
@ -47,9 +47,9 @@ deploy_snapshot:
- bash_shell - bash_shell
environment: environment:
name: oneartifactory name: oneartifactory
url: https://oneartifactoryprod.verizon.com/artifactory url: https://oneartifactoryci.verizon.com/artifactory
variables: variables:
ARTIFACTORY_URL: https://oneartifactoryprod.verizon.com/artifactory ARTIFACTORY_URL: https://oneartifactoryci.verizon.com/artifactory
#promote_snapshot: #promote_snapshot:
# stage: go live # stage: go live
@ -65,9 +65,9 @@ deploy_snapshot:
# - bash_shell # - bash_shell
# environment: # environment:
# name: oneartifactory # name: oneartifactory
# url: https://oneartifactoryprod.verizon.com/artifactory # url: https://oneartifactoryci.verizon.com/artifactory
# variables: # variables:
# ARTIFACTORY_URL: https://oneartifactoryprod.verizon.com/artifactory # ARTIFACTORY_URL: https://oneartifactoryci.verizon.com/artifactory
# #
#create_version_tag: #create_version_tag:
# stage: tag # stage: tag

View File

@ -602,6 +602,7 @@
EAB14BC327D9378D0012AB2C /* RuleAnyModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB14BC227D9378D0012AB2C /* RuleAnyModelProtocol.swift */; }; EAB14BC327D9378D0012AB2C /* RuleAnyModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB14BC227D9378D0012AB2C /* RuleAnyModelProtocol.swift */; };
EABFC1412763BB8D00E78B40 /* FormLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABFC1402763BB8D00E78B40 /* FormLabel.swift */; }; EABFC1412763BB8D00E78B40 /* FormLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABFC1402763BB8D00E78B40 /* FormLabel.swift */; };
EABFC152276913E800E78B40 /* FormLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABFC151276913E800E78B40 /* FormLabelModel.swift */; }; EABFC152276913E800E78B40 /* FormLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABFC151276913E800E78B40 /* FormLabelModel.swift */; };
FD99130028E21E4900542CC3 /* RuleNotEqualsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD9912FF28E21E4900542CC3 /* RuleNotEqualsModel.swift */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
@ -1203,6 +1204,7 @@
EAB14BC227D9378D0012AB2C /* RuleAnyModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleAnyModelProtocol.swift; sourceTree = "<group>"; }; EAB14BC227D9378D0012AB2C /* RuleAnyModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleAnyModelProtocol.swift; sourceTree = "<group>"; };
EABFC1402763BB8D00E78B40 /* FormLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormLabel.swift; sourceTree = "<group>"; }; EABFC1402763BB8D00E78B40 /* FormLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormLabel.swift; sourceTree = "<group>"; };
EABFC151276913E800E78B40 /* FormLabelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormLabelModel.swift; sourceTree = "<group>"; }; EABFC151276913E800E78B40 /* FormLabelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormLabelModel.swift; sourceTree = "<group>"; };
FD9912FF28E21E4900542CC3 /* RuleNotEqualsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleNotEqualsModel.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@ -1257,6 +1259,7 @@
0A69F610241BDEA700F7231B /* RuleAnyRequiredModel.swift */, 0A69F610241BDEA700F7231B /* RuleAnyRequiredModel.swift */,
011D95A0240453D0000E3791 /* RuleEqualsModel.swift */, 011D95A0240453D0000E3791 /* RuleEqualsModel.swift */,
0A849EFD246F1775009F277F /* RuleEqualsIgnoreCaseModel.swift */, 0A849EFD246F1775009F277F /* RuleEqualsIgnoreCaseModel.swift */,
FD9912FF28E21E4900542CC3 /* RuleNotEqualsModel.swift */,
); );
name = Rules; name = Rules;
path = Rules/Rules; path = Rules/Rules;
@ -2956,6 +2959,7 @@
D2509ED12472ED9B001BFB9D /* NavigationItemModelProtocol.swift in Sources */, D2509ED12472ED9B001BFB9D /* NavigationItemModelProtocol.swift in Sources */,
EA05EFAB278DE53600828819 /* ClearableModelProtocol.swift in Sources */, EA05EFAB278DE53600828819 /* ClearableModelProtocol.swift in Sources */,
8D448E5524050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift in Sources */, 8D448E5524050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift in Sources */,
FD99130028E21E4900542CC3 /* RuleNotEqualsModel.swift in Sources */,
BBC0C4FD24811DBC0087C44F /* Tag.swift in Sources */, BBC0C4FD24811DBC0087C44F /* Tag.swift in Sources */,
94C2D9842386F3F80006CF46 /* LabelAttributeModel.swift in Sources */, 94C2D9842386F3F80006CF46 /* LabelAttributeModel.swift in Sources */,
944589212385D6E900DE9FD4 /* DashLineModel.swift in Sources */, 944589212385D6E900DE9FD4 /* DashLineModel.swift in Sources */,
@ -3221,7 +3225,6 @@
D29DF0D221E404D4003B2FB9 /* Debug */ = { D29DF0D221E404D4003B2FB9 /* Debug */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
BUILD_LIBRARY_FOR_DISTRIBUTION = YES; BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
@ -3289,7 +3292,6 @@
D29DF0D321E404D4003B2FB9 /* Release */ = { D29DF0D321E404D4003B2FB9 /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
BUILD_LIBRARY_FOR_DISTRIBUTION = YES; BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;

View File

@ -83,6 +83,11 @@
[self removeAllAlertViews]; [self removeAllAlertViews];
} }
if (alertStyle == UIAlertControllerStyleActionSheet && UIDevice.currentDevice.userInterfaceIdiom != UIUserInterfaceIdiomPhone) {
// ActionSheets are not supported on iPad interfaces without a source rect (i.e. a source element) which isn't currently supported for our generic handling.
alertStyle = UIAlertControllerStyleAlert;
}
// Create the alert. Adds the actions one by one. // Create the alert. Adds the actions one by one.
MVMCoreAlertController *alertController = [MVMCoreAlertController alertControllerWithTitle:(title ?: @"") message:message preferredStyle:alertStyle]; MVMCoreAlertController *alertController = [MVMCoreAlertController alertControllerWithTitle:(title ?: @"") message:message preferredStyle:alertStyle];
for (NSUInteger i = 0; i < [actions count]; i++) { for (NSUInteger i = 0; i < [actions count]; i++) {

View File

@ -9,6 +9,41 @@
public extension MVMCoreAlertObject { public extension MVMCoreAlertObject {
static func alertObject(from alertModel: AlertModel, actions: [UIAlertAction]? = nil, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> MVMCoreAlertObject? {
let actionsForAlert = actions ?? generateActions(from: alertModel.alertActions, additionalData: additionalData, delegateObject: delegateObject)
let alertObject = MVMCoreAlertObject(popupAlertWithTitle: alertModel.title,
message: alertModel.message,
actions: actionsForAlert,
isGreedy: false)
alertObject?.alertStyle = alertModel.style
alertObject?.pageJson = alertModel.analyticsData
return alertObject
}
static func generateActions(from buttonModels: [AlertButtonModel], additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalHandling: ((AlertButtonModel, UIAlertAction)->())? = nil) -> [UIAlertAction] {
return buttonModels.map { alertButtonModel in
let alertAction = UIAlertAction(title: alertButtonModel.title, style: alertButtonModel.style) { action in
Task(priority: .userInitiated) {
do {
try await (delegateObject?.actionDelegate as? ActionDelegateProtocol)?.performAction(
with: alertButtonModel.action,
additionalData: additionalData,
delegateObject: delegateObject
)
} catch {
}
additionalHandling?(alertButtonModel, action)
}
}
return alertAction
}
}
@objc static func alertObjectWith(action actionJson: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> MVMCoreAlertObject? { @objc static func alertObjectWith(action actionJson: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?, error: AutoreleasingUnsafeMutablePointer<MVMCoreErrorObject?>?) -> MVMCoreAlertObject? {
guard let alertJson = actionJson?.optionalDictionaryForKey("alert"), guard let alertJson = actionJson?.optionalDictionaryForKey("alert"),

View File

@ -25,7 +25,14 @@ open class ActionAlertHandler: MVMCoreJSONActionHandlerProtocol {
} }
open func execute(with model: ActionModelProtocol, delegateObject: DelegateObject?, additionalData: [AnyHashable : Any]?) async throws { open func execute(with model: ActionModelProtocol, delegateObject: DelegateObject?, additionalData: [AnyHashable : Any]?) async throws {
let json = try MVMCoreActionHandler.convertActionToJSON(model) guard let model = model as? ActionAlertModel else { return }
try await performAction(with: json, model: model, delegateObject: delegateObject, additionalData: additionalData) var error: MVMCoreErrorObject? = nil
guard let alertObject = MVMCoreAlertObject.alertObject(from: model.alert, additionalData: additionalData, delegateObject: delegateObject, error: &error) else {
throw MVMCoreError.errorObject(error!)
}
(delegateObject?.actionDelegate as? MVMCoreUIActionDelegateProtocol)?.willShowPopup(with: alertObject, alertJson: try MVMCoreActionHandler.convertActionToJSON(model))
_ = await MainActor.run {
MVMCoreAlertHandler.shared()?.showAlert(with: alertObject)
}
} }
} }

View File

@ -23,7 +23,7 @@ public class AlertButtonModel: Codable {
// MARK: - Initializer // MARK: - Initializer
//-------------------------------------------------- //--------------------------------------------------
public init(_ title: String,_ action: ActionModelProtocol,_ style: UIAlertAction.Style = .default) { public init(_ title: String, _ action: ActionModelProtocol, style: UIAlertAction.Style = .default) {
self.title = title self.title = title
self.action = action self.action = action
self.style = style self.style = style
@ -76,10 +76,11 @@ public class AlertModel: Codable {
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
public init(_ title: String,_ message: String,_ alertActions: [AlertButtonModel]) { public init(title: String, message: String, alertActions: [AlertButtonModel], style: UIAlertController.Style = .alert) {
self.title = title self.title = title
self.message = message self.message = message
self.alertActions = alertActions self.alertActions = alertActions
self.style = style
} }
//-------------------------------------------------- //--------------------------------------------------

View File

@ -26,6 +26,11 @@
case action case action
} }
open override func setDefaults() {
super.setDefaults()
enableClipboardActions = false
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Codec // MARK: - Codec
//-------------------------------------------------- //--------------------------------------------------

View File

@ -83,6 +83,9 @@ import Foundation
case shouldMaskRecordedView case shouldMaskRecordedView
} }
/// Sets the default values. Should be called on init.
open func setDefaults() { }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Validation Methods // MARK: - Validation Methods
//-------------------------------------------------- //--------------------------------------------------
@ -119,6 +122,7 @@ import Foundation
baseValue = text baseValue = text
self.titleStateLabel = FormLabelModel(text: "") self.titleStateLabel = FormLabelModel(text: "")
self.feedbackStateLabel = FormLabelModel(text: "") self.feedbackStateLabel = FormLabelModel(text: "")
setDefaults()
} }
//-------------------------------------------------- //--------------------------------------------------
@ -157,6 +161,7 @@ import Foundation
self.feedbackStateLabel = FormLabelModel(model: LabelModel(text: feedback ?? "", self.feedbackStateLabel = FormLabelModel(model: LabelModel(text: feedback ?? "",
fontStyle: FormLabelModel.defaultFontStyle, fontStyle: FormLabelModel.defaultFontStyle,
textColor: Color(uiColor: .mvmCoolGray6))) textColor: Color(uiColor: .mvmCoolGray6)))
setDefaults()
} }
public func encode(to encoder: Encoder) throws { public func encode(to encoder: Encoder) throws {

View File

@ -338,6 +338,7 @@ import UIKit
placeholder = model.placeholder placeholder = model.placeholder
textField.shouldMaskWhileRecording = model.shouldMaskRecordedView ?? true textField.shouldMaskWhileRecording = model.shouldMaskRecordedView ?? true
textField.enableClipboardActions = model.enableClipboardActions
switch model.type { switch model.type {
case .password, .secure: case .password, .secure:

View File

@ -37,6 +37,7 @@
public var clearTextOnTap: Bool = false public var clearTextOnTap: Bool = false
public var displayFormat: String? public var displayFormat: String?
public var displayMask: String? public var displayMask: String?
public var enableClipboardActions: Bool = true
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializers // MARK: - Initializers
@ -112,6 +113,7 @@
case clearTextOnTap case clearTextOnTap
case displayFormat case displayFormat
case displayMask case displayMask
case enableClipboardActions
} }
//-------------------------------------------------- //--------------------------------------------------
@ -143,6 +145,10 @@
if let textAlignment = try typeContainer.decodeIfPresent(NSTextAlignment.self, forKey: .textAlignment) { if let textAlignment = try typeContainer.decodeIfPresent(NSTextAlignment.self, forKey: .textAlignment) {
self.textAlignment = textAlignment self.textAlignment = textAlignment
} }
if let enableClipboardActions = try typeContainer.decodeIfPresent(Bool.self, forKey: .enableClipboardActions) {
self.enableClipboardActions = enableClipboardActions
}
} }
open override func encode(to encoder: Encoder) throws { open override func encode(to encoder: Encoder) throws {
@ -157,5 +163,6 @@
try container.encode(enabledTextColor, forKey: .enabledTextColor) try container.encode(enabledTextColor, forKey: .enabledTextColor)
try container.encode(disabledTextColor, forKey: .disabledTextColor) try container.encode(disabledTextColor, forKey: .disabledTextColor)
try container.encode(clearTextOnTap, forKey: .clearTextOnTap) try container.encode(clearTextOnTap, forKey: .clearTextOnTap)
try container.encode(enableClipboardActions, forKey: .enableClipboardActions)
} }
} }

View File

@ -15,8 +15,8 @@ public enum CheckboxPosition: String, Codable {
case bottom case bottom
} }
@objcMembers public class CheckboxLabelModel: MoleculeModelProtocol { @objcMembers open class CheckboxLabelModel: MoleculeModelProtocol {
public static var identifier: String = "checkboxLabel" open class var identifier: String { "checkboxLabel" }
public var moleculeName: String = CheckboxLabelModel.identifier public var moleculeName: String = CheckboxLabelModel.identifier
public var backgroundColor: Color? public var backgroundColor: Color?
public var checkboxAlignment: CheckboxPosition? public var checkboxAlignment: CheckboxPosition?

View File

@ -241,18 +241,7 @@ public typealias ActionBlock = () -> ()
case left case left
} }
public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject? = nil, _ additionalData: [AnyHashable: Any]? = nil) { @objc public func resetAttributeStyle() {
clauses = []
text = nil
attributedText = nil
originalAttributedString = nil
shouldMaskWhileRecording = model.shouldMaskRecordedView ?? false
guard let labelModel = model as? LabelModel else { return }
text = labelModel.text
/* /*
* This is to address a reuse issue with iOS 13 and up. * This is to address a reuse issue with iOS 13 and up.
* Even if you set text & attributedText to nil, the moment you set text with a value, * Even if you set text & attributedText to nil, the moment you set text with a value,
@ -274,6 +263,21 @@ public typealias ActionBlock = () -> ()
self.attributedText = attributedString self.attributedText = attributedString
} }
}
public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject? = nil, _ additionalData: [AnyHashable: Any]? = nil) {
clauses = []
text = nil
attributedText = nil
originalAttributedString = nil
shouldMaskWhileRecording = model.shouldMaskRecordedView ?? false
guard let labelModel = model as? LabelModel else { return }
text = labelModel.text
resetAttributeStyle()
hero = labelModel.hero hero = labelModel.hero
Label.setLabel(self, withHTML: labelModel.html) Label.setLabel(self, withHTML: labelModel.html)

View File

@ -7,12 +7,13 @@
// //
@objcMembers open class LabelModel: MoleculeModelProtocol { @objcMembers open class LabelModel: MoleculeModelProtocol, Identifiable {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
open class var identifier: String { "label" } open class var identifier: String { "label" }
public var id: String
public var backgroundColor: Color? public var backgroundColor: Color?
public var text: String public var text: String
public var accessibilityText: String? public var accessibilityText: String?
@ -34,6 +35,7 @@
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case id
case text case text
case accessibilityText case accessibilityText
case textColor case textColor
@ -58,7 +60,8 @@
// MARK: - Initializer // MARK: - Initializer
//-------------------------------------------------- //--------------------------------------------------
public init(text: String) { public init(id: String = UUID().uuidString, text: String) {
self.id = id
self.text = text self.text = text
} }
@ -78,6 +81,7 @@
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
text = try typeContainer.decode(String.self, forKey: .text) text = try typeContainer.decode(String.self, forKey: .text)
accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText) accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
textColor = try typeContainer.decodeIfPresent(Color.self, forKey: .textColor) textColor = try typeContainer.decodeIfPresent(Color.self, forKey: .textColor)
@ -102,6 +106,7 @@
open 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.encodeIfPresent(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(id, forKey: .id)
try container.encode(text, forKey: .text) try container.encode(text, forKey: .text)
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText) try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
try container.encodeIfPresent(textColor, forKey: .textColor) try container.encodeIfPresent(textColor, forKey: .textColor)

View File

@ -9,7 +9,7 @@
import Foundation import Foundation
public class ListOneColumnFullWidthTextBodyTextModel: ListItemModel, MoleculeModelProtocol { public class ListOneColumnFullWidthTextBodyTextModel: ListItemModel, MoleculeModelProtocol, ParentMoleculeModelProtocol {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
@ -35,6 +35,10 @@ public class ListOneColumnFullWidthTextBodyTextModel: ListItemModel, MoleculeMod
headlineBody.style = .item headlineBody.style = .item
} }
public var children: [MoleculeModelProtocol] {
return [headlineBody]
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Keys // MARK: - Keys
//-------------------------------------------------- //--------------------------------------------------

View File

@ -7,7 +7,7 @@
// //
public class ListRightVariableButtonAllTextAndLinksModel: ListItemModel, MoleculeModelProtocol { public class ListRightVariableButtonAllTextAndLinksModel: ListItemModel, MoleculeModelProtocol, ParentMoleculeModelProtocol {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
@ -36,6 +36,10 @@ public class ListRightVariableButtonAllTextAndLinksModel: ListItemModel, Molecul
self.button.style = .secondary self.button.style = .secondary
} }
public var children: [MoleculeModelProtocol] {
return [button, eyebrowHeadlineBodyLink]
}
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Keys // MARK: - Keys
//-------------------------------------------------- //--------------------------------------------------

View File

@ -71,10 +71,14 @@
func getAccessibilityMessage() -> String? { func getAccessibilityMessage() -> String? {
guard let linkText = link.titleLabel?.text else { guard var linkText = link.titleLabel?.text else {
return eyebrowHeadlineBodyLink.getAccessibilityMessage() return eyebrowHeadlineBodyLink.getAccessibilityMessage()
} }
if !link.isEnabled, let accDisabled = MVMCoreUIUtility.hardcodedString(withKey:"AccDisabled") {
linkText = linkText + ", " + accDisabled
}
guard let label = eyebrowHeadlineBodyLink.getAccessibilityMessage() else { guard let label = eyebrowHeadlineBodyLink.getAccessibilityMessage() else {
return linkText return linkText
} }

View File

@ -41,7 +41,6 @@ import Foundation
addMolecule(stack) addMolecule(stack)
stack.restack() stack.restack()
isAccessibilityElement = true isAccessibilityElement = true
updateAccessibilityLabel()
} }
//-------------------------------------------------- //--------------------------------------------------
@ -53,7 +52,8 @@ import Foundation
guard let model = model as? ListOneColumnTextWithWhitespaceDividerTallModel else { return } guard let model = model as? ListOneColumnTextWithWhitespaceDividerTallModel else { return }
stack.updateContainedMolecules(with: [model.headline, model.body], delegateObject, additionalData) stack.updateContainedMolecules(with: [model.headline, model.body], delegateObject, additionalData)
updateAccessibilityLabel()
updateAccessibilityLabel(model: model)
} }
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
@ -64,24 +64,25 @@ import Foundation
super.reset() super.reset()
headline.setFontStyle(.BoldTitleMedium) headline.setFontStyle(.BoldTitleMedium)
body.setFontStyle(.RegularBodySmall) body.setFontStyle(.RegularBodySmall)
accessibilityLabel = nil
} }
//---------------------------------------------------- //----------------------------------------------------
// MARK: - Accessibility // MARK: - Accessibility
//---------------------------------------------------- //----------------------------------------------------
func updateAccessibilityLabel() { func updateAccessibilityLabel(model: ListOneColumnTextWithWhitespaceDividerTallModel) {
var message = "" var message = ""
if let headlineLabel = headline.text, !headlineLabel.isEmpty { if let headlineLabel = model.headline.accessibilityText ?? headline.text, !headlineLabel.isEmpty {
message += headlineLabel + ", " message += headlineLabel + ", "
} }
if let bodyLabel = body.text, !bodyLabel.isEmpty { if let bodyLabel = model.body?.accessibilityText ?? body.text, !bodyLabel.isEmpty {
message += bodyLabel message += bodyLabel
} }
accessibilityLabel = message accessibilityLabel = message
} }
} }

View File

@ -150,6 +150,9 @@ open class HeadlineBody: View {
open override func reset() { open override func reset() {
super.reset() super.reset()
//Reset the text values
headlineLabel.reset()
messageLabel.reset()
stylePageHeader() stylePageHeader()
} }
} }

View File

@ -47,6 +47,11 @@
self.body = body self.body = body
} }
public init(headline: LabelModel, body: LabelModel) {
self.headline = headline
self.body = body
}
//----------------------------------------------------- //-----------------------------------------------------
// MARK: - Codec // MARK: - Codec
//----------------------------------------------------- //-----------------------------------------------------

View File

@ -7,12 +7,12 @@
// //
@objcMembers public class ThreeLayerPageTemplateModel: ThreeLayerModelBase { @objcMembers open class ThreeLayerPageTemplateModel: ThreeLayerModelBase {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
public override class var identifier: String { "threeLayer" } open override class var identifier: String { "threeLayer" }
public var middle: MoleculeModelProtocol? public var middle: MoleculeModelProtocol?
public override var rootMolecules: [MoleculeModelProtocol] { public override var rootMolecules: [MoleculeModelProtocol] {
@ -51,7 +51,7 @@
try super.init(from: decoder) try super.init(from: decoder)
} }
public override func encode(to encoder: Encoder) throws { open override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder) try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeModelIfPresent(header, forKey: .middle) try container.encodeModelIfPresent(header, forKey: .middle)

View File

@ -9,7 +9,7 @@
import UIKit import UIKit
@objcMembers open class Control: UIControl, MoleculeViewProtocol { open class Control: UIControl, MoleculeViewProtocol {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------

View File

@ -23,7 +23,7 @@ public protocol TextInputDidDeleteProtocol: AnyObject {
/// Set to true to hide the blinking textField cursor. /// Set to true to hide the blinking textField cursor.
public var hideBlinkingCaret = false public var hideBlinkingCaret = false
public var enableClipboardActions: Bool = true
public var shouldMaskWhileRecording: Bool = true public var shouldMaskWhileRecording: Bool = true
//-------------------------------------------------- //--------------------------------------------------
@ -74,6 +74,8 @@ public protocol TextInputDidDeleteProtocol: AnyObject {
super.deleteBackward() super.deleteBackward()
didDeleteDelegate?.textInputDidDelete() didDeleteDelegate?.textInputDidDelete()
} }
open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool { enableClipboardActions }
} }
/// MARK:- MVMCoreViewProtocol /// MARK:- MVMCoreViewProtocol
@ -91,7 +93,7 @@ extension TextField: MVMCoreViewProtocol {
/// MARK:- MoleculeViewProtocol /// MARK:- MoleculeViewProtocol
extension TextField: MoleculeViewProtocol { extension TextField: MoleculeViewProtocol {
open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
if let color = model.backgroundColor?.uiColor { if let color = model.backgroundColor?.uiColor {
backgroundColor = color backgroundColor = color

View File

@ -30,6 +30,8 @@ public protocol PageMoleculeTransformationBehavior: PageBehaviorProtocol {
func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject?) func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject?)
func willSetupMolecule(with model: MoleculeModelProtocol, updating view: MoleculeViewProtocol?) func willSetupMolecule(with model: MoleculeModelProtocol, updating view: MoleculeViewProtocol?)
func didSetupMolecule(view: MoleculeViewProtocol, withModel: MoleculeModelProtocol) func didSetupMolecule(view: MoleculeViewProtocol, withModel: MoleculeModelProtocol)
func willSetupNavigationBar(with model: NavigationItemModelProtocol, updating view: UINavigationBar)
func didSetupNavigationBar(view: UINavigationBar, with model: NavigationItemModelProtocol)
} }
public extension PageMoleculeTransformationBehavior { public extension PageMoleculeTransformationBehavior {
@ -37,6 +39,8 @@ public extension PageMoleculeTransformationBehavior {
func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject?) {} func onPageNew(rootMolecules: [MoleculeModelProtocol], _ delegateObject: MVMCoreUIDelegateObject?) {}
func willSetupMolecule(with model: MoleculeModelProtocol, updating view: MoleculeViewProtocol?) {} func willSetupMolecule(with model: MoleculeModelProtocol, updating view: MoleculeViewProtocol?) {}
func didSetupMolecule(view: MoleculeViewProtocol, withModel: MoleculeModelProtocol) {} func didSetupMolecule(view: MoleculeViewProtocol, withModel: MoleculeModelProtocol) {}
func willSetupNavigationBar(with model: NavigationItemModelProtocol, updating view: UINavigationBar) {}
func didSetupNavigationBar(view: UINavigationBar, with model: NavigationItemModelProtocol) {}
} }
public protocol PageVisibilityBehavior: PageBehaviorProtocol { public protocol PageVisibilityBehavior: PageBehaviorProtocol {

View File

@ -70,30 +70,30 @@ extension NavigationController: MVMCoreViewManagerProtocol {
public func newDataReceived(in viewController: UIViewController) { public func newDataReceived(in viewController: UIViewController) {
if isDisplayed(viewController: viewController), if isDisplayed(viewController: viewController),
let topViewController = topViewController,
let model = getNavigationModel(from: viewController) { let model = getNavigationModel(from: viewController) {
setNavigationItem(with: model, for: topViewController) updateNavigationView(with: model, for: viewController)
setNavigationBarUI(with: model)
navigationBar.setNeedsLayout()
navigationBar.layoutIfNeeded()
} }
manager?.newDataReceived?(in: viewController) manager?.newDataReceived?(in: viewController)
} }
public func willDisplay(_ viewController: UIViewController) { public func willDisplay(_ viewController: UIViewController) {
if let topViewController = topViewController, if isDisplayed(viewController: viewController),
isDisplayed(viewController: viewController),
let model = getNavigationModel(from: viewController) { let model = getNavigationModel(from: viewController) {
setNavigationItem(with: model, for: topViewController) updateNavigationView(with: model, for: viewController)
setNavigationBarUI(with: model)
navigationBar.setNeedsLayout()
navigationBar.layoutIfNeeded()
} }
manager?.willDisplay?(viewController) manager?.willDisplay?(viewController)
} }
private func updateNavigationView(with model: NavigationItemModelProtocol, for viewController: UIViewController) {
guard let topViewController = topViewController else { return }
setNavigationItem(with: model, for: topViewController, coordinatingWith: viewController as? PageBehaviorHandlerProtocol)
setNavigationBarUI(with: model)
navigationBar.setNeedsLayout()
navigationBar.layoutIfNeeded()
}
public func displayedViewController(_ viewController: UIViewController) { public func displayedViewController(_ viewController: UIViewController) {
manager?.displayedViewController?(viewController) manager?.displayedViewController?(viewController)
} }

View File

@ -11,13 +11,24 @@ import Foundation
public extension UINavigationController { public extension UINavigationController {
/// Convenience function for setting the navigation item. /// Convenience function for setting the navigation item.
func setNavigationItem(with model: NavigationItemModelProtocol, for viewController: UIViewController) { func setNavigationItem(with model: NavigationItemModelProtocol, for viewController: UIViewController, coordinatingWith pageBehaviorController: PageBehaviorHandlerProtocol? = nil) {
let behaviorHandler = pageBehaviorController ?? viewController as? PageBehaviorHandlerProtocol;
behaviorHandler?.executeBehaviors { (behavior: PageMoleculeTransformationBehavior) in
behavior.willSetupNavigationBar(with: model, updating: navigationBar)
}
viewController.navigationItem.title = model.title viewController.navigationItem.title = model.title
viewController.navigationItem.accessibilityLabel = model.title viewController.navigationItem.accessibilityLabel = model.title
viewController.navigationItem.hidesBackButton = model.hidesSystemBackButton viewController.navigationItem.hidesBackButton = model.hidesSystemBackButton
viewController.navigationItem.leftItemsSupplementBackButton = !model.hidesSystemBackButton viewController.navigationItem.leftItemsSupplementBackButton = !model.hidesSystemBackButton
setNavigationButtons(with: model, for: viewController) setNavigationButtons(with: model, for: viewController)
setNavigationTitleView(with: model, for: viewController) setNavigationTitleView(with: model, for: viewController, coordinatingWith: pageBehaviorController)
behaviorHandler?.executeBehaviors { (behavior: PageMoleculeTransformationBehavior) in
behavior.didSetupNavigationBar(view: navigationBar, with: model)
}
} }
/// Convenience function for setting the navigation buttons. /// Convenience function for setting the navigation buttons.
@ -48,11 +59,22 @@ public extension UINavigationController {
} }
/// Convenience function for setting the navigation titleView. /// Convenience function for setting the navigation titleView.
func setNavigationTitleView(with model: NavigationItemModelProtocol, for viewController: UIViewController) { func setNavigationTitleView(with model: NavigationItemModelProtocol, for viewController: UIViewController, coordinatingWith pageBehaviorController: PageBehaviorHandlerProtocol? = nil) {
guard let titleViewModel = model.titleView else { return }
let delegate = (viewController as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject let delegate = (viewController as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject
if let titleViewModel = model.titleView,
let molecule = ModelRegistry.createMolecule(titleViewModel, delegateObject: delegate, additionalData: nil) { let behaviorHandler = pageBehaviorController ?? viewController as? PageBehaviorHandlerProtocol;
viewController.navigationItem.titleView = molecule behaviorHandler?.executeBehaviors { (behavior: PageMoleculeTransformationBehavior) in
behavior.willSetupMolecule(with: titleViewModel, updating: nil)
}
guard let molecule = ModelRegistry.createMolecule(titleViewModel, delegateObject: delegate, additionalData: nil) else { return }
viewController.navigationItem.titleView = molecule
behaviorHandler?.executeBehaviors { (behavior: PageMoleculeTransformationBehavior) in
behavior.didSetupMolecule(view: molecule, withModel: titleViewModel)
} }
} }

View File

@ -106,7 +106,7 @@ public final class Color: Codable {
if colorString.hasPrefix("#") { if colorString.hasPrefix("#") {
hex = colorString.replacingOccurrences(of: "#", with: "") hex = colorString.replacingOccurrences(of: "#", with: "")
} else { } else {
guard let hexString = UIColor.names[colorString]?.hex else { throw ColorError.badName(reason: "Check the spelling of your color.") } guard let hexString = UIColor.names[colorString]?.hex else { throw ColorError.badName(reason: "Check the spelling of your color: \(colorString)") }
hex = hexString.replacingOccurrences(of: "#", with: "") hex = hexString.replacingOccurrences(of: "#", with: "")
name = colorString name = colorString
} }

View File

@ -0,0 +1,44 @@
//
// RuleNotEqualsModel.swift
// MVMCoreUI
//
// Created by Marakanti, Keerthy on 26/09/22.
// Copyright © 2022 Verizon Wireless. All rights reserved.
//
import Foundation
public class RuleNotEqualsModel: RuleCompareModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public static var identifier: String = "notEquals"
public var type: String = RuleNotEqualsModel.identifier
public var ruleId: String?
public var fields: [String]
public var errorMessage: [String: String]?
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(fields: [String]) {
self.fields = fields
}
//--------------------------------------------------
// MARK: - Validation
//--------------------------------------------------
public func isValid(_ formField: FormFieldProtocol) -> Bool {
return false
}
///RuleCompareModelProtocol Method
public func compare(lhs: AnyHashable?, rhs: AnyHashable?) -> Bool {
return lhs != rhs
}
}

View File

@ -244,6 +244,7 @@ open class CoreUIModelMapping: ModelMapping {
ModelRegistry.register(RuleAnyValueChangedModel.self) ModelRegistry.register(RuleAnyValueChangedModel.self)
ModelRegistry.register(RuleAllValueChangedModel.self) ModelRegistry.register(RuleAllValueChangedModel.self)
ModelRegistry.register(RuleEqualsModel.self) ModelRegistry.register(RuleEqualsModel.self)
ModelRegistry.register(RuleNotEqualsModel.self)
ModelRegistry.register(RuleEqualsIgnoreCaseModel.self) ModelRegistry.register(RuleEqualsIgnoreCaseModel.self)
ModelRegistry.register(RuleRegexModel.self) ModelRegistry.register(RuleRegexModel.self)
ModelRegistry.register(EnableFormFieldEffectModel.self) ModelRegistry.register(EnableFormFieldEffectModel.self)

View File

@ -8,7 +8,7 @@
# Create new aggregate builds # Create new aggregate builds
if [ -z $ARTIFACTORY_URL ]; then if [ -z $ARTIFACTORY_URL ]; then
ARTIFACTORY_URL="https://oneartifactoryprod.verizon.com/artifactory" ARTIFACTORY_URL="https://oneartifactoryci.verizon.com/artifactory"
fi fi
BUILD_DIR=$(xcodebuild -showBuildSettings -project ./MVMCoreUI.xcodeproj | grep -w -o 'BUILD_DIR = .*' | cut -d\ -f3-) BUILD_DIR=$(xcodebuild -showBuildSettings -project ./MVMCoreUI.xcodeproj | grep -w -o 'BUILD_DIR = .*' | cut -d\ -f3-)

View File

@ -48,7 +48,7 @@ fi
echo -e "Getting checksums..." echo -e "Getting checksums..."
echo -e "URL: ${URL}/api/storage/${REMOTEPATH}" echo -e "URL: ${URL}/api/storage/${REMOTEPATH}"
JSON=$(curl --header "X-JFrog-Art-Api: ${ARTIFACTORY_APIKEY}" -X GET "${URL}/api/storage/${REMOTEPATH}") JSON=$(curl --header "X-JFrog-Art-Api: ${ARTIFACTORY_APIKEY}" -X GET "${URL}/api/storage/${REMOTEPATH}")
CHECKSUM=$(echo "$JSON" | python -c 'import sys, json; print json.load(sys.stdin)["checksums"]["sha1"]') CHECKSUM=$(echo "$JSON" | python3 -c 'import sys, json; print (json.load(sys.stdin)["checksums"]["sha1"])')
if [[ -z "$CHECKSUM" ]]; then if [[ -z "$CHECKSUM" ]]; then
exit_with_error "No Checksum found in json: ${JSON}" exit_with_error "No Checksum found in json: ${JSON}"
fi fi

View File

@ -17,7 +17,7 @@ fi
# Create new aggregate builds # Create new aggregate builds
if [ -z $ARTIFACTORY_URL ]; then if [ -z $ARTIFACTORY_URL ]; then
ARTIFACTORY_URL="https://oneartifactoryprod.verizon.com/artifactory" ARTIFACTORY_URL="https://oneartifactoryci.verizon.com/artifactory"
fi fi
# Upload # Upload