From 2e75f8638c4b4cc4f0111e49944f6f68d8f8b8ab Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Mon, 29 Mar 2021 18:44:26 -0400 Subject: [PATCH 1/6] iterate throw all rules --- MVMCoreUI/FormUIHelpers/FormValidator.swift | 7 ++++- .../Rules/Rules/RuleAnyRequiredModel.swift | 20 +++++++++----- .../Rules/RuleAnyValueChangedModel.swift | 16 ++++++++--- .../Rules/RuleEqualsIgnoreCaseModel.swift | 19 +++++++++---- .../Rules/Rules/RuleEqualsModel.swift | 17 ++++++++---- .../Rules/Rules/RulesProtocol.swift | 27 ++++++++++++------- 6 files changed, 75 insertions(+), 31 deletions(-) diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index a0785c41..090202c0 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -96,8 +96,13 @@ import MVMCore public func validateGroup(_ group: FormGroupRule) -> Bool { // Validate each rule. var valid = true + var previousValidity: [String: Bool] = [:] for rule in group.rules { - valid = valid && rule.validate(fields) + let tuple = rule.validate(fields, previousValidity) + let temp = tuple.0 + let returnedValidity = tuple.1 + previousValidity = previousValidity.merging(returnedValidity) { (_, new) in new } + valid = valid && temp } // Notify the group watchers of validity. diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift index 7f153e83..2addbf90 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift @@ -36,15 +36,23 @@ public class RuleAnyRequiredModel: RulesProtocol { return false } - public func validate(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool { - + public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidiity: [String: Bool]) -> (Bool, [String: Bool]) { + + var previousValidity: [String: Bool] = [:] for formKey in fields { guard let formField = fieldMolecules[formKey] else { continue } - - if isValid(formField) { - return true + + var fieldValidity = isValid(formField) + // If past rule is invalid forr a field, the current rule should not flip the validity of a field + if let validity = previousFieldValidiity[formKey], !validity, fieldValidity { + fieldValidity = false } + + if fieldValidity { + return (fieldValidity, previousValidity) + } + previousValidity[formKey] = false } - return false + return (false, previousValidity) } } diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift index 07cf451f..d7413419 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift @@ -27,13 +27,21 @@ public class RuleAnyValueChangedModel: RulesProtocol { return formField.baseValue != formField.formFieldValue() } - public func validate(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool { + public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidiity: [String: Bool]) -> (Bool, [String: Bool]) { + var previousValidity: [String: Bool] = [:] for formKey in fields { guard let formField = fieldMolecules[formKey] else { continue } - if isValid(formField) { - return true + var fieldValidity = isValid(formField) + // If past rule is invalid forr a field, the current rule should not flip the validity of a field + if let validity = previousFieldValidiity[formKey], !validity, fieldValidity { + fieldValidity = false } + + if fieldValidity { + return (true, previousValidity) + } + previousValidity[formKey] = false } - return false + return (false, previousValidity) } } diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsIgnoreCaseModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsIgnoreCaseModel.swift index 5e014cff..4979adf2 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsIgnoreCaseModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsIgnoreCaseModel.swift @@ -27,10 +27,11 @@ public class RuleEqualsIgnoreCaseModel: RulesProtocol { return false } - public func validate(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool { - var valid = false - var compareText: String? + public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidiity: [String: Bool]) -> (Bool, [String: Bool]) { + var valid = false + var compareText: String? + var previousValidity: [String: Bool] = [:] for formKey in fields { guard let formField = fieldMolecules[formKey] else { continue } @@ -42,16 +43,24 @@ public class RuleEqualsIgnoreCaseModel: RulesProtocol { if let fieldValue = formField.formFieldValue() as? String, compareString.caseInsensitiveCompare(fieldValue) == .orderedSame { valid = true + + var fieldValidity = valid + // If past rule is invalid forr a field, the current rule should not flip the validity of a field + if let validity = previousFieldValidiity[formKey], !validity, fieldValidity { + fieldValidity = false + } + for formKey in fields { guard let formField = fieldMolecules[formKey] else { continue } (formField as? FormRuleWatcherFieldProtocol)?.setValidity(true, rule: self) } break } - + + previousValidity[formKey] = valid (formField as? FormRuleWatcherFieldProtocol)?.setValidity(valid, rule: self) } - return valid + return (valid, previousValidity) } } diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift index fa73ed51..7795ab39 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift @@ -27,9 +27,10 @@ public class RuleEqualsModel: RulesProtocol { return false } - public func validate(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool { - var valid = true - var compareValue: AnyHashable? + public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidiity: [String: Bool]) -> (Bool, [String: Bool]) { + var valid = true + var compareValue: AnyHashable? + var previousValidity: [String: Bool] = [:] for formKey in fields { guard let formField = fieldMolecules[formKey] else { continue } @@ -41,13 +42,19 @@ public class RuleEqualsModel: RulesProtocol { if compareValue != formField.formFieldValue() { valid = false + previousValidity[formKey] = valid (formField as? FormRuleWatcherFieldProtocol)?.setValidity(valid, rule: self) break } else { - (formField as? FormRuleWatcherFieldProtocol)?.setValidity(valid, rule: self) + var fieldValidity = valid + // If past rule is invalid forr a field, the current rule should not flip the validity of a field + if let validity = previousFieldValidiity[formKey], !validity, fieldValidity { + fieldValidity = false + } + (formField as? FormRuleWatcherFieldProtocol)?.setValidity(fieldValidity, rule: self) } } - return valid + return (valid, previousValidity) } } diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift index 5a8b47a8..c48fd111 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift @@ -26,7 +26,7 @@ public protocol RulesProtocol: ModelProtocol { func isValid(_ formField: FormFieldProtocol) -> Bool // Validates the rule and returns the result. - func validate(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool + func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidiity: [String: Bool]) -> (Bool, [String: Bool]) } public extension RulesProtocol { @@ -38,14 +38,21 @@ public extension RulesProtocol { static var categoryName: String { "\(RulesProtocol.self)" } // Individual rule can override the function to validate based on the rule type. - func validate(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool { - var valid = true - for formKey in fields { - guard let formField = fieldMolecules[formKey] else { continue } - let fieldValidity = isValid(formField) - (formField as? FormRuleWatcherFieldProtocol)?.setValidity(fieldValidity, rule: self) - valid = valid && fieldValidity - } - return valid + func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidiity: [String: Bool]) -> (Bool, [String: Bool]) { + var valid = true + var previousValidity: [String: Bool] = [:] + for formKey in fields { + guard let formField = fieldMolecules[formKey] else { continue } + + var fieldValidity = isValid(formField) + // If past rule is invalid forr a field, the current rule should not flip the validity of a field + if let validity = previousFieldValidiity[formKey], !validity, fieldValidity { + fieldValidity = false + } + (formField as? FormRuleWatcherFieldProtocol)?.setValidity(fieldValidity, rule: self) + valid = valid && fieldValidity + previousValidity[formKey] = fieldValidity + } + return (valid, previousValidity) } } From 766ba93499ab32b848f2e62852ce37cdc0d0b1ba Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Tue, 30 Mar 2021 12:12:12 -0400 Subject: [PATCH 2/6] code review --- MVMCoreUI/FormUIHelpers/FormValidator.swift | 6 +++--- .../Rules/Rules/RuleAnyRequiredModel.swift | 6 +++--- .../Rules/Rules/RuleAnyValueChangedModel.swift | 8 ++++---- .../Rules/Rules/RuleEqualsIgnoreCaseModel.swift | 7 +++---- .../FormUIHelpers/Rules/Rules/RuleEqualsModel.swift | 7 +++---- .../FormUIHelpers/Rules/Rules/RulesProtocol.swift | 12 ++++++------ 6 files changed, 22 insertions(+), 24 deletions(-) diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index 090202c0..bed97391 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -99,10 +99,10 @@ import MVMCore var previousValidity: [String: Bool] = [:] for rule in group.rules { let tuple = rule.validate(fields, previousValidity) - let temp = tuple.0 - let returnedValidity = tuple.1 + let isValidRule = tuple.valid + let returnedValidity = tuple.fieldValidity previousValidity = previousValidity.merging(returnedValidity) { (_, new) in new } - valid = valid && temp + valid = valid && isValidRule } // Notify the group watchers of validity. diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift index 2addbf90..0df84c4a 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift @@ -36,7 +36,7 @@ public class RuleAnyRequiredModel: RulesProtocol { return false } - public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidiity: [String: Bool]) -> (Bool, [String: Bool]) { + public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidity: [String: Bool]) -> (valid: Bool, fieldValidity: [String: Bool]) { var previousValidity: [String: Bool] = [:] for formKey in fields { @@ -44,7 +44,7 @@ public class RuleAnyRequiredModel: RulesProtocol { var fieldValidity = isValid(formField) // If past rule is invalid forr a field, the current rule should not flip the validity of a field - if let validity = previousFieldValidiity[formKey], !validity, fieldValidity { + if let validity = previousFieldValidity[formKey], !validity, fieldValidity { fieldValidity = false } @@ -53,6 +53,6 @@ public class RuleAnyRequiredModel: RulesProtocol { } previousValidity[formKey] = false } - return (false, previousValidity) + return (valid: false, fieldValidity: previousValidity) } } diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift index d7413419..2a982e45 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift @@ -27,13 +27,13 @@ public class RuleAnyValueChangedModel: RulesProtocol { return formField.baseValue != formField.formFieldValue() } - public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidiity: [String: Bool]) -> (Bool, [String: Bool]) { + public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidity: [String: Bool]) -> (valid: Bool, fieldValidity: [String: Bool]) { var previousValidity: [String: Bool] = [:] for formKey in fields { guard let formField = fieldMolecules[formKey] else { continue } var fieldValidity = isValid(formField) // If past rule is invalid forr a field, the current rule should not flip the validity of a field - if let validity = previousFieldValidiity[formKey], !validity, fieldValidity { + if let validity = previousFieldValidity[formKey], !validity, fieldValidity { fieldValidity = false } @@ -41,7 +41,7 @@ public class RuleAnyValueChangedModel: RulesProtocol { return (true, previousValidity) } previousValidity[formKey] = false - } - return (false, previousValidity) + } + return (valid: false, fieldValidity: previousValidity) } } diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsIgnoreCaseModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsIgnoreCaseModel.swift index 4979adf2..ee165b9a 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsIgnoreCaseModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsIgnoreCaseModel.swift @@ -27,7 +27,7 @@ public class RuleEqualsIgnoreCaseModel: RulesProtocol { return false } - public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidiity: [String: Bool]) -> (Bool, [String: Bool]) { + public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidity: [String: Bool]) -> (valid: Bool, fieldValidity: [String: Bool]) { var valid = false var compareText: String? @@ -46,7 +46,7 @@ public class RuleEqualsIgnoreCaseModel: RulesProtocol { var fieldValidity = valid // If past rule is invalid forr a field, the current rule should not flip the validity of a field - if let validity = previousFieldValidiity[formKey], !validity, fieldValidity { + if let validity = previousFieldValidity[formKey], !validity, fieldValidity { fieldValidity = false } @@ -60,7 +60,6 @@ public class RuleEqualsIgnoreCaseModel: RulesProtocol { previousValidity[formKey] = valid (formField as? FormRuleWatcherFieldProtocol)?.setValidity(valid, rule: self) } - - return (valid, previousValidity) + return (valid: valid, fieldValidity: previousValidity) } } diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift index 7795ab39..7a8c25e4 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift @@ -27,7 +27,7 @@ public class RuleEqualsModel: RulesProtocol { return false } - public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidiity: [String: Bool]) -> (Bool, [String: Bool]) { + public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidity: [String: Bool]) -> (valid: Bool, fieldValidity: [String: Bool]) { var valid = true var compareValue: AnyHashable? var previousValidity: [String: Bool] = [:] @@ -48,13 +48,12 @@ public class RuleEqualsModel: RulesProtocol { } else { var fieldValidity = valid // If past rule is invalid forr a field, the current rule should not flip the validity of a field - if let validity = previousFieldValidiity[formKey], !validity, fieldValidity { + if let validity = previousFieldValidity[formKey], !validity, fieldValidity { fieldValidity = false } (formField as? FormRuleWatcherFieldProtocol)?.setValidity(fieldValidity, rule: self) } } - - return (valid, previousValidity) + return (valid: valid, fieldValidity: previousValidity) } } diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift index c48fd111..db8614ac 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift @@ -26,7 +26,7 @@ public protocol RulesProtocol: ModelProtocol { func isValid(_ formField: FormFieldProtocol) -> Bool // Validates the rule and returns the result. - func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidiity: [String: Bool]) -> (Bool, [String: Bool]) + func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidity: [String: Bool]) -> (valid: Bool, fieldValidity: [String: Bool]) } public extension RulesProtocol { @@ -38,21 +38,21 @@ public extension RulesProtocol { static var categoryName: String { "\(RulesProtocol.self)" } // Individual rule can override the function to validate based on the rule type. - func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidiity: [String: Bool]) -> (Bool, [String: Bool]) { + func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidity: [String: Bool]) -> (valid: Bool, fieldValidity: [String: Bool]) { var valid = true var previousValidity: [String: Bool] = [:] for formKey in fields { guard let formField = fieldMolecules[formKey] else { continue } - var fieldValidity = isValid(formField) - // If past rule is invalid forr a field, the current rule should not flip the validity of a field - if let validity = previousFieldValidiity[formKey], !validity, fieldValidity { + var fieldValidity = isValid(formField) + // If past rule is invalid for a field, the current rule should not flip the validity of a field + if let validity = previousFieldValidity[formKey], !validity, fieldValidity { fieldValidity = false } (formField as? FormRuleWatcherFieldProtocol)?.setValidity(fieldValidity, rule: self) valid = valid && fieldValidity previousValidity[formKey] = fieldValidity } - return (valid, previousValidity) + return (valid: valid, fieldValidity: previousValidity) } } From a50e3346e7220099d456dd34da8e62be8ef06038 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Thu, 8 Apr 2021 15:34:21 -0400 Subject: [PATCH 3/6] code review --- MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift | 2 +- .../FormUIHelpers/Rules/Rules/RuleEqualsIgnoreCaseModel.swift | 2 +- MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift index 0df84c4a..3a9b3871 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyRequiredModel.swift @@ -43,7 +43,7 @@ public class RuleAnyRequiredModel: RulesProtocol { guard let formField = fieldMolecules[formKey] else { continue } var fieldValidity = isValid(formField) - // If past rule is invalid forr a field, the current rule should not flip the validity of a field + // If past rule is invalid for a field, the current rule should not flip the validity of a field if let validity = previousFieldValidity[formKey], !validity, fieldValidity { fieldValidity = false } diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsIgnoreCaseModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsIgnoreCaseModel.swift index ee165b9a..8326cf4f 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsIgnoreCaseModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsIgnoreCaseModel.swift @@ -45,7 +45,7 @@ public class RuleEqualsIgnoreCaseModel: RulesProtocol { valid = true var fieldValidity = valid - // If past rule is invalid forr a field, the current rule should not flip the validity of a field + // If past rule is invalid for a field, the current rule should not flip the validity of a field if let validity = previousFieldValidity[formKey], !validity, fieldValidity { fieldValidity = false } diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift index 7a8c25e4..a405e2e7 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift @@ -47,7 +47,7 @@ public class RuleEqualsModel: RulesProtocol { break } else { var fieldValidity = valid - // If past rule is invalid forr a field, the current rule should not flip the validity of a field + // If past rule is invalid for a field, the current rule should not flip the validity of a field if let validity = previousFieldValidity[formKey], !validity, fieldValidity { fieldValidity = false } From 0673c5b3a8bab0da08a48eac72d25f14475d9d84 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 30 Apr 2021 13:28:49 -0400 Subject: [PATCH 4/6] style for notification --- .../TopNotification/NotificationModel.swift | 76 +++++++++++++++++-- .../TopNotification/NotificationXButton.swift | 2 +- .../NotificationXButtonModel.swift | 4 +- 3 files changed, 73 insertions(+), 9 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationModel.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationModel.swift index 3d02cecd..267f17d2 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationModel.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationModel.swift @@ -8,6 +8,21 @@ open class NotificationModel: MoleculeModelProtocol { + + /** + The style of the notification: + - success, green background, white content + - error, orange background, black content + - \warning, yellow background, black content + - information, blue background, white content + */ + public enum Style: String, Codable { + case success + case error + case warning + case information + } + //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -19,6 +34,7 @@ open class NotificationModel: MoleculeModelProtocol { public var body: LabelModel? public var button: ButtonModel? public var closeButton: NotificationXButtonModel? + public var style: NotificationModel.Style = .success //-------------------------------------------------- // MARK: - Initializer @@ -34,20 +50,63 @@ open class NotificationModel: MoleculeModelProtocol { open func setDefault() { if backgroundColor == nil { - backgroundColor = Color(uiColor: .mvmGreen) + switch style { + case .error: + backgroundColor = Color(uiColor: .mvmOrange) + case .warning: + backgroundColor = Color(uiColor: .mvmYellow) + case .information: + backgroundColor = Color(uiColor: .mvmBlue) + default: + backgroundColor = Color(uiColor: .mvmGreen) + } } if headline.textColor == nil { - headline.textColor = Color(uiColor: .mvmWhite) + switch style { + case .error, .warning: + headline.textColor = Color(uiColor: .mvmBlack) + default: + headline.textColor = Color(uiColor: .mvmWhite) + } } if body?.textColor == nil { - body?.textColor = Color(uiColor: .mvmWhite) + switch style { + case .error, .warning: + body?.textColor = Color(uiColor: .mvmBlack) + default: + body?.textColor = Color(uiColor: .mvmWhite) + } + } + + button?.size = .tiny + if button?.enabledTextColor == nil { + switch style { + case .error, .warning: + button?.enabledTextColor = Color(uiColor: .mvmBlack) + default: + button?.enabledTextColor = Color(uiColor: .mvmWhite) + } + } + if button?.enabledBorderColor == nil { + switch style { + case .error, .warning: + button?.enabledBorderColor = Color(uiColor: .mvmBlack) + default: + button?.enabledBorderColor = Color(uiColor: .mvmWhite) + } } if button?.style == nil { button?.style = .secondary } - button?.size = .tiny - button?.enabledTextColor = Color(uiColor: .mvmWhite) - button?.enabledBorderColor = Color(uiColor: .mvmWhite) + + if closeButton?.color == nil { + switch style { + case .error, .warning: + closeButton?.color = Color(uiColor: .mvmBlack) + default: + closeButton?.color = Color(uiColor: .mvmWhite) + } + } } //-------------------------------------------------- @@ -62,6 +121,7 @@ open class NotificationModel: MoleculeModelProtocol { case body case button case closeButton + case style } //-------------------------------------------------- @@ -76,6 +136,9 @@ open class NotificationModel: MoleculeModelProtocol { body = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .body) button = try typeContainer.decodeIfPresent(ButtonModel.self, forKey: .button) closeButton = try typeContainer.decodeIfPresent(NotificationXButtonModel.self, forKey: .closeButton) + if let style = try typeContainer.decodeIfPresent(NotificationModel.Style.self, forKey: .style) { + self.style = style + } setDefault() } @@ -88,5 +151,6 @@ open class NotificationModel: MoleculeModelProtocol { try container.encodeIfPresent(body, forKey: .body) try container.encodeIfPresent(button, forKey: .button) try container.encodeIfPresent(closeButton, forKey: .closeButton) + try container.encode(style, forKey: .style) } } diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButton.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButton.swift index d2696722..204785cb 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButton.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButton.swift @@ -33,7 +33,7 @@ import Foundation open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { super.set(with: model, delegateObject, additionalData) guard let model = model as? NotificationXButtonModel else { return } - tintColor = model.color.uiColor + tintColor = model.color?.uiColor ?? .white // TODO: Temporary, consider action for dismissing top alert if model.action.actionType == ActionNoopModel.identifier { diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButtonModel.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButtonModel.swift index 81dae17e..9661d9b3 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButtonModel.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButtonModel.swift @@ -11,7 +11,7 @@ import Foundation public class NotificationXButtonModel: ButtonModelProtocol, MoleculeModelProtocol { public static var identifier: String = "notificationXButton" public var backgroundColor: Color? - public var color = Color(uiColor: .white) + public var color: Color? public var action: ActionModelProtocol = ActionNoopModel() private enum CodingKeys: String, CodingKey { @@ -33,7 +33,7 @@ public class NotificationXButtonModel: ButtonModelProtocol, MoleculeModelProtoco public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) - try container.encode(color, forKey: .color) + try container.encodeIfPresent(color, forKey: .color) try container.encodeModel(action, forKey: .action) } } From eedd4e8174b4f837921fe7f7e2a69f3410ef6d35 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Fri, 30 Apr 2021 14:47:35 -0400 Subject: [PATCH 5/6] fix missed color for notifications --- .../Molecules/TopNotification/NotificationXButtonModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButtonModel.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButtonModel.swift index 9661d9b3..59da1868 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButtonModel.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/NotificationXButtonModel.swift @@ -24,7 +24,7 @@ public class NotificationXButtonModel: ButtonModelProtocol, MoleculeModelProtoco public required init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - color = try typeContainer.decodeIfPresent(Color.self, forKey: .color) ?? Color(uiColor: .white) + color = try typeContainer.decodeIfPresent(Color.self, forKey: .color) if let action: ActionModelProtocol = try typeContainer.decodeModelIfPresent(codingKey: .action) { self.action = action } From c5bbed2fb2f421f1717d46d889c58a1135beea98 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Mon, 3 May 2021 17:22:26 -0400 Subject: [PATCH 6/6] don't dismiss top alert when focus is nil --- .../Molecules/TopNotification/CollapsableNotification.swift | 2 +- MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.m | 2 +- MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotification.swift b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotification.swift index 8539c817..82983f4d 100644 --- a/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotification.swift +++ b/MVMCoreUI/Atomic/Molecules/TopNotification/CollapsableNotification.swift @@ -160,7 +160,7 @@ import Foundation /// Collapse if focus is no longer on this top alert. @objc func accessibilityFocusChanged(notification: Notification) { - if !MVMCoreUIUtility.viewContainsAccessiblityFocus(self) { + if (notification.userInfo?[UIAccessibility.focusedElementUserInfoKey] != nil) && !MVMCoreUIUtility.viewContainsAccessiblityFocus(self) { NotificationCenter.default.removeObserver(self, name: UIAccessibility.elementFocusedNotification, object: nil) collapse() } diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.m b/MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.m index 46ecd793..405dd781 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.m +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertExpandableView.m @@ -423,7 +423,7 @@ } - (void)accessibilityFocusChanged:(NSNotification *)notification { - if (![MVMCoreUIUtility viewContainsAccessiblityFocus:self]) { + if (notification.userInfo[UIAccessibilityFocusedElementKey] && ![MVMCoreUIUtility viewContainsAccessiblityFocus:self]) { [[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityElementFocusedNotification object:nil]; [self collapse]; } diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m index ad0a833f..eba4cfcc 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m @@ -335,7 +335,7 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed."; /// If the voice over user leaves top alert focus, hide. - (void)accessibilityFocusChanged:(NSNotification *)notification { - if (![MVMCoreUIUtility viewContainsAccessiblityFocus:self]) { + if (notification.userInfo[UIAccessibilityFocusedElementKey] && ![MVMCoreUIUtility viewContainsAccessiblityFocus:self]) { [[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityElementFocusedNotification object:nil]; [self hideAlertView:YES completionHandler:self.hideCompletionHandler]; self.hideCompletionHandler = nil;