From fb623627bf1467f1995bb9e7d12fa4ddde1da9f4 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 15 Feb 2024 15:38:25 -0600 Subject: [PATCH 01/32] fixed bug where someone could nil out attributedText and resetting the text with the same value wouldn't trigger setNeedsUpdate() Signed-off-by: Matt Bruce --- VDS/Components/Label/Label.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/VDS/Components/Label/Label.swift b/VDS/Components/Label/Label.swift index 7ecb79cd..67e53abe 100644 --- a/VDS/Components/Label/Label.swift +++ b/VDS/Components/Label/Label.swift @@ -135,15 +135,15 @@ open class Label: UILabel, ViewProtocol, UserInfoable { override open var text: String? { get { _text } set { - if _text != newValue { + if _text != newValue || newValue != attributedText?.string { _text = newValue useAttributedText = false - attributes = nil + attributes?.removeAll() setNeedsUpdate() } } } - + /// Whether the View is enabled or not. open override var isEnabled: Bool { didSet { setNeedsUpdate() } } From aa30561b298ccfc36bb792702a7bc3e2581c2a2f Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 16 Feb 2024 09:33:39 -0600 Subject: [PATCH 02/32] refactored naming conventions Signed-off-by: Matt Bruce --- VDS/Components/Tilelet/TileletSubTitleModel.swift | 12 ++++++------ VDS/Components/TitleLockup/TitleLockup.swift | 2 +- .../TitleLockup/TitleLockupSubTitleModel.swift | 8 ++++---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/VDS/Components/Tilelet/TileletSubTitleModel.swift b/VDS/Components/Tilelet/TileletSubTitleModel.swift index dab4c81c..ae28d958 100644 --- a/VDS/Components/Tilelet/TileletSubTitleModel.swift +++ b/VDS/Components/Tilelet/TileletSubTitleModel.swift @@ -14,7 +14,7 @@ extension Tilelet { // MARK: - Enums //-------------------------------------------------- /// Enum used to describe the textStyle of the subTitle label. - public enum StandardStyle: String, EnumSubset { + public enum OtherStandardStyle: String, EnumSubset { case bodyLarge case bodyMedium case bodySmall @@ -28,7 +28,7 @@ extension Tilelet { public var text: String = "" /// Text style that will be used for the subTitle label. - public var standardStyle: StandardStyle = .bodySmall + public var otherStandardStyle: OtherStandardStyle = .bodySmall /// Text attributes that will be used for the subTitle label. public var textAttributes: [any LabelAttributeModel]? @@ -40,13 +40,13 @@ extension Tilelet { // MARK: - Initializers //-------------------------------------------------- public init(text: String, + otherStandardStyle: OtherStandardStyle = .bodySmall, textColor: Use = .primary, - textAttributes: [any LabelAttributeModel]? = nil, - standardStyle: StandardStyle = .bodySmall) { + textAttributes: [any LabelAttributeModel]? = nil) { self.text = text + self.otherStandardStyle = otherStandardStyle self.textAttributes = textAttributes self.textColor = textColor - self.standardStyle = standardStyle } //-------------------------------------------------- @@ -55,7 +55,7 @@ extension Tilelet { /// Converts this type of model to a TitleLockup.SubTitleModel. public func toTitleLockupSubTitleModel() -> TitleLockup.SubTitleModel { TitleLockup.SubTitleModel(text: text, - standardStyle: standardStyle.value, + otherStandardStyle: otherStandardStyle.value, textColor: textColor, textAttributes: textAttributes) } diff --git a/VDS/Components/TitleLockup/TitleLockup.swift b/VDS/Components/TitleLockup/TitleLockup.swift index dbfd8637..e11b674d 100644 --- a/VDS/Components/TitleLockup/TitleLockup.swift +++ b/VDS/Components/TitleLockup/TitleLockup.swift @@ -45,7 +45,7 @@ open class TitleLockup: View { //-------------------------------------------------- private var otherStandardStyle: OtherStandardStyle { if let subTitleModel, !subTitleModel.text.isEmpty { - return subTitleModel.standardStyle + return subTitleModel.otherStandardStyle } else if let eyebrowModel, !eyebrowModel.text.isEmpty { return eyebrowModel.standardStyle } else { diff --git a/VDS/Components/TitleLockup/TitleLockupSubTitleModel.swift b/VDS/Components/TitleLockup/TitleLockupSubTitleModel.swift index 3ba6c7ff..4ac0922c 100644 --- a/VDS/Components/TitleLockup/TitleLockupSubTitleModel.swift +++ b/VDS/Components/TitleLockup/TitleLockupSubTitleModel.swift @@ -14,7 +14,7 @@ extension TitleLockup { public var text: String /// Standard style that will be used for the subTitle label. - public var standardStyle: OtherStandardStyle + public var otherStandardStyle: OtherStandardStyle /// Text color used in the subtitle label. public var textColor: Use @@ -26,19 +26,19 @@ extension TitleLockup { public var numberOfLines: Int public init(text: String, - standardStyle: OtherStandardStyle = .bodyLarge, + otherStandardStyle: OtherStandardStyle = .bodyLarge, textColor: Use = .primary, textAttributes: [any LabelAttributeModel]? = nil, numberOfLines: Int = 0) { self.text = text - self.standardStyle = standardStyle + self.otherStandardStyle = otherStandardStyle self.textColor = textColor self.textAttributes = textAttributes self.numberOfLines = numberOfLines } /// TextStyle used to render the text. - public var textStyle: TextStyle { standardStyle.value.regular } + public var textStyle: TextStyle { otherStandardStyle.value.regular } } From 9883bd6214df931069fbe5a090bd4fbff461de71 Mon Sep 17 00:00:00 2001 From: vasavk Date: Thu, 22 Feb 2024 23:55:46 +0530 Subject: [PATCH 03/32] Digital ACT191 story ONEAPP-6682 Flex Height as per Layout and spacing --- .../TextFields/TextArea/TextArea.swift | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/VDS/Components/TextFields/TextArea/TextArea.swift b/VDS/Components/TextFields/TextArea/TextArea.swift index 7d70cb44..4494f1b7 100644 --- a/VDS/Components/TextFields/TextArea/TextArea.swift +++ b/VDS/Components/TextFields/TextArea/TextArea.swift @@ -5,7 +5,6 @@ // Created by Matt Bruce on 1/10/23. // -import Foundation import Foundation import UIKit import VDSColorTokens @@ -49,7 +48,7 @@ open class TextArea: EntryFieldBase { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- - override var containerSize: CGSize { CGSize(width: 45, height: 88) } + override var containerSize: CGSize { CGSize(width: 182, height: 88) } /// UITextView shown in the TextArea. open var textView = UITextView().with { @@ -72,7 +71,7 @@ open class TextArea: EntryFieldBase { open override func setup() { super.setup() - minWidthConstraint = containerView.widthAnchor.constraint(greaterThanOrEqualToConstant: 0) + minWidthConstraint = containerView.widthAnchor.constraint(greaterThanOrEqualToConstant: containerSize.width) minWidthConstraint?.isActive = true controlContainerView.addSubview(textView) @@ -81,8 +80,8 @@ open class TextArea: EntryFieldBase { .pinLeading() .pinTrailingLessThanOrEqualTo(nil, 0, .defaultHigh) .pinBottom(0, .defaultHigh) - - textViewHeightConstraint = textView.heightAnchor.constraint(greaterThanOrEqualToConstant: 64) + textView.isScrollEnabled = true + textViewHeightConstraint = textView.heightAnchor.constraint(greaterThanOrEqualToConstant: containerSize.height) textViewHeightConstraint?.isActive = true backgroundColorConfiguration.setSurfaceColors(VDSColor.feedbackSuccessBackgroundOnlight, VDSColor.feedbackSuccessBackgroundOndark, forState: .success) borderColorConfiguration.setSurfaceColors(VDSColor.feedbackSuccessOnlight, VDSColor.feedbackSuccessOndark, forState: .success) @@ -132,17 +131,15 @@ extension TextArea: UITextViewDelegate { //if you want it to work "as-is" delete this code //since it will autogrow with the current settings if let textViewHeightConstraint, textView.isEditable { - let height = textView.frame.size.height - let constraintHeight = textViewHeightConstraint.constant - if height > constraintHeight { - if height > 64 && height < 152 { - textViewHeightConstraint.constant = 152 - } else if height > 152 { - textViewHeightConstraint.constant = 328 + let height = textView.contentSize.height + if height > 88 && height < 176 { + textViewHeightConstraint.constant = 176 + } else if height > 176 { + textViewHeightConstraint.constant = 352 } else { - textViewHeightConstraint.constant = 64 + textViewHeightConstraint.constant = 88 } - } + textViewHeightConstraint.isActive = true } //setting the value and firing control event From 783143717c71d219d725deeef868ea40312a03fd Mon Sep 17 00:00:00 2001 From: vasavk Date: Fri, 23 Feb 2024 12:47:47 +0530 Subject: [PATCH 04/32] Digital ACT191 story ONEAPP-6682 adding character count limit to container --- .../TextFields/EntryFieldBase.swift | 35 ++++++++++++++++-- .../TextFields/TextArea/TextArea.swift | 37 ++++++++++++++++++- 2 files changed, 68 insertions(+), 4 deletions(-) diff --git a/VDS/Components/TextFields/EntryFieldBase.swift b/VDS/Components/TextFields/EntryFieldBase.swift index aaf03256..31529f61 100644 --- a/VDS/Components/TextFields/EntryFieldBase.swift +++ b/VDS/Components/TextFields/EntryFieldBase.swift @@ -70,6 +70,20 @@ open class EntryFieldBase: Control, Changeable { } }() + internal var bottomContainerView: UIView = { + return UIView().with { + $0.translatesAutoresizingMaskIntoConstraints = false + } + }() + + internal var bottomContainerStackView: UIStackView = { + return UIStackView().with { + $0.translatesAutoresizingMaskIntoConstraints = false + $0.axis = .vertical + $0.distribution = .fill + } + }() + //-------------------------------------------------- // MARK: - Configuration Properties //-------------------------------------------------- @@ -204,14 +218,24 @@ open class EntryFieldBase: Control, Changeable { containerStackView.addArrangedSubview(controlContainerView) containerStackView.addArrangedSubview(icon) + //get the container this is what show helper text, error text + //can include other for character count, max length + let bottomContainer = getBottomContainer() + + //add bottomContainerStackView + //this is the vertical stack that contains error text, helper text + bottomContainer.addSubview(bottomContainerStackView) + bottomContainerStackView.pinToSuperView() + bottomContainerStackView.addArrangedSubview(errorLabel) + bottomContainerStackView.addArrangedSubview(helperLabel) + stackView.addArrangedSubview(titleLabel) stackView.addArrangedSubview(container) - stackView.addArrangedSubview(errorLabel) - stackView.addArrangedSubview(helperLabel) + stackView.addArrangedSubview(bottomContainer) stackView.setCustomSpacing(4, after: titleLabel) stackView.setCustomSpacing(8, after: container) - stackView.setCustomSpacing(8, after: errorLabel) + stackView.setCustomSpacing(8, after: bottomContainer) stackView .pinTop() @@ -273,6 +297,11 @@ open class EntryFieldBase: Control, Changeable { open func getContainer() -> UIView { return containerView } + + /// Container for the area in which helper or error text presents. + open func getBottomContainer() -> UIView { + return bottomContainerView + } open func updateTitleLabel() { diff --git a/VDS/Components/TextFields/TextArea/TextArea.swift b/VDS/Components/TextFields/TextArea/TextArea.swift index 4494f1b7..7cca53da 100644 --- a/VDS/Components/TextFields/TextArea/TextArea.swift +++ b/VDS/Components/TextFields/TextArea/TextArea.swift @@ -45,6 +45,30 @@ open class TextArea: EntryFieldBase { } }() + internal var bottomView: UIView = { + return UIView().with { + $0.translatesAutoresizingMaskIntoConstraints = false + } + }() + + internal var bottomStackView: UIStackView = { + return UIStackView().with { + $0.translatesAutoresizingMaskIntoConstraints = false + $0.axis = .horizontal + $0.distribution = .fill + $0.alignment = .top + } + }() + + open var characterCountLabel = Label().with { + $0.setContentCompressionResistancePriority(.required, for: .vertical) + $0.textStyle = .bodySmall + } + open var maxLengthLabel = Label().with { + $0.setContentCompressionResistancePriority(.required, for: .vertical) + $0.textStyle = .bodySmall + } + //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- @@ -70,9 +94,10 @@ open class TextArea: EntryFieldBase { /// Called once when a view is initialized and is used to Setup additional UI or other constants and configurations. open override func setup() { super.setup() - minWidthConstraint = containerView.widthAnchor.constraint(greaterThanOrEqualToConstant: containerSize.width) minWidthConstraint?.isActive = true + characterCountLabel.text = "0" + maxLengthLabel.text = "/200" controlContainerView.addSubview(textView) textView @@ -119,6 +144,16 @@ open class TextArea: EntryFieldBase { minWidthConstraint?.isActive = true } } + + /// Container for the area which shows helper text, error text, character count, max length value. + open override func getBottomContainer() -> UIView { + bottomView.addSubview(bottomStackView) + bottomStackView.pinToSuperView() + bottomStackView.addArrangedSubview(bottomContainerView) + bottomStackView.addArrangedSubview(characterCountLabel) + bottomStackView.addArrangedSubview(maxLengthLabel) + return bottomView + } } extension TextArea: UITextViewDelegate { From e319153ac659f79f581ab4a939848b90f895a8d1 Mon Sep 17 00:00:00 2001 From: vasavk Date: Fri, 23 Feb 2024 16:11:14 +0530 Subject: [PATCH 05/32] Digital ACT191 story ONEAPP-6682 Checking character count overflow --- .../TextFields/TextArea/TextArea.swift | 41 ++++++++++++------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/VDS/Components/TextFields/TextArea/TextArea.swift b/VDS/Components/TextFields/TextArea/TextArea.swift index 7cca53da..105286b5 100644 --- a/VDS/Components/TextFields/TextArea/TextArea.swift +++ b/VDS/Components/TextFields/TextArea/TextArea.swift @@ -35,7 +35,8 @@ open class TextArea: EntryFieldBase { //-------------------------------------------------- internal var minWidthConstraint: NSLayoutConstraint? internal var textViewHeightConstraint: NSLayoutConstraint? - + internal var allowCharCount: Int = 0 + internal var inputFieldStackView: UIStackView = { return UIStackView().with { $0.translatesAutoresizingMaskIntoConstraints = false @@ -64,10 +65,6 @@ open class TextArea: EntryFieldBase { $0.setContentCompressionResistancePriority(.required, for: .vertical) $0.textStyle = .bodySmall } - open var maxLengthLabel = Label().with { - $0.setContentCompressionResistancePriority(.required, for: .vertical) - $0.textStyle = .bodySmall - } //-------------------------------------------------- // MARK: - Public Properties @@ -96,9 +93,6 @@ open class TextArea: EntryFieldBase { super.setup() minWidthConstraint = containerView.widthAnchor.constraint(greaterThanOrEqualToConstant: containerSize.width) minWidthConstraint?.isActive = true - characterCountLabel.text = "0" - maxLengthLabel.text = "/200" - controlContainerView.addSubview(textView) textView .pinTop() @@ -118,6 +112,8 @@ open class TextArea: EntryFieldBase { open override func reset() { super.reset() textView.text = "" + characterCountLabel.reset() + characterCountLabel.textStyle = .bodySmall } /// Container for the area in which the user interacts. @@ -132,7 +128,6 @@ open class TextArea: EntryFieldBase { textView.isEditable = isEnabled textView.textColor = textViewTextColorConfiguration.getColor(self) - //set the width constraints if let width { widthConstraint?.constant = width @@ -143,6 +138,12 @@ open class TextArea: EntryFieldBase { widthConstraint?.isActive = false minWidthConstraint?.isActive = true } + + // allow - 20% of character limit + let overflowLimit = Double(maxLength ?? 0) * 0.20 + allowCharCount = Int(overflowLimit) + (maxLength ?? 0) + characterCountLabel.text = getLimitText() + } /// Container for the area which shows helper text, error text, character count, max length value. @@ -151,9 +152,18 @@ open class TextArea: EntryFieldBase { bottomStackView.pinToSuperView() bottomStackView.addArrangedSubview(bottomContainerView) bottomStackView.addArrangedSubview(characterCountLabel) - bottomStackView.addArrangedSubview(maxLengthLabel) return bottomView } + + //-------------------------------------------------- + // MARK: - Private Methods + //-------------------------------------------------- + private func getLimitText() -> String { + let count = textView.text.count + let countStr = (count > maxLength ?? 0) ? ("-" + "\(count-(maxLength ?? 0))") : "\(count)" + let text = "\(countStr)" + "/" + "\(maxLength ?? 0)" + return text + } } extension TextArea: UITextViewDelegate { @@ -177,9 +187,12 @@ extension TextArea: UITextViewDelegate { textViewHeightConstraint.isActive = true } - //setting the value and firing control event - value = textView.text - sendActions(for: .valueChanged) - + if textView.text.count <= allowCharCount { + //setting the value and firing control event + value = textView.text + sendActions(for: .valueChanged) + } else { + textView.text.removeLast() + } } } From 967eed952266cfe5e8cb7b966bb2ffc5879e4f13 Mon Sep 17 00:00:00 2001 From: vasavk Date: Fri, 23 Feb 2024 19:12:17 +0530 Subject: [PATCH 06/32] Digital ACT191 story ONEAPP-6682 changes for error icon --- VDS/Components/TextFields/EntryFieldBase.swift | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/VDS/Components/TextFields/EntryFieldBase.swift b/VDS/Components/TextFields/EntryFieldBase.swift index 31529f61..0d6a93e5 100644 --- a/VDS/Components/TextFields/EntryFieldBase.swift +++ b/VDS/Components/TextFields/EntryFieldBase.swift @@ -59,7 +59,7 @@ open class EntryFieldBase: Control, Changeable { return UIStackView().with { $0.translatesAutoresizingMaskIntoConstraints = false $0.axis = .horizontal - $0.distribution = .fillProportionally + $0.distribution = .fill $0.alignment = .top } }() @@ -198,7 +198,7 @@ open class EntryFieldBase: Control, Changeable { //create the wrapping view heightConstraint = containerView.heightAnchor.constraint(greaterThanOrEqualToConstant: containerSize.height) - widthConstraint?.priority = .defaultHigh + heightConstraint?.priority = .defaultHigh heightConstraint?.isActive = true widthConstraint = containerView.widthAnchor.constraint(equalToConstant: 0) @@ -212,11 +212,12 @@ open class EntryFieldBase: Control, Changeable { //this is the horizontal stack that contains //the left, InputContainer, Icons, Buttons container.addSubview(containerStackView) - containerStackView.pinToSuperView(.uniform(12)) + containerStackView.pinToSuperView(.uniform(VDSFormControls.spaceInset)) //add the view to add input fields containerStackView.addArrangedSubview(controlContainerView) containerStackView.addArrangedSubview(icon) + containerStackView.setCustomSpacing(VDSLayout.Spacing.space3X.value, after: controlContainerView) //get the container this is what show helper text, error text //can include other for character count, max length From c2662aaf307023e21e73e50ca7440de5d15a3fa6 Mon Sep 17 00:00:00 2001 From: vasavk Date: Fri, 23 Feb 2024 19:26:41 +0530 Subject: [PATCH 07/32] Digital ACT191 story ONEAPP-6682 added change log --- VDS.xcodeproj/project.pbxproj | 4 ++ .../TextFields/TextArea/TextAreaChangeLog.txt | 38 +++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 VDS/Components/TextFields/TextArea/TextAreaChangeLog.txt diff --git a/VDS.xcodeproj/project.pbxproj b/VDS.xcodeproj/project.pbxproj index b13f7df5..125d88a8 100644 --- a/VDS.xcodeproj/project.pbxproj +++ b/VDS.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 186B2A8A2B88DA7F001AB71F /* TextAreaChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 186B2A892B88DA7F001AB71F /* TextAreaChangeLog.txt */; }; 18792A902B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18792A8F2B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift */; }; 18BDEE822B75316E00452358 /* ButtonIconChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = 18BDEE812B75316E00452358 /* ButtonIconChangeLog.txt */; }; 445BA07829C07B3D0036A7C5 /* Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 445BA07729C07B3D0036A7C5 /* Notification.swift */; }; @@ -173,6 +174,7 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 186B2A892B88DA7F001AB71F /* TextAreaChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = TextAreaChangeLog.txt; sourceTree = ""; }; 18792A8F2B7431F2008C0D29 /* ButtonIconBadgeIndicatorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonIconBadgeIndicatorModel.swift; sourceTree = ""; }; 18BDEE812B75316E00452358 /* ButtonIconChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = ButtonIconChangeLog.txt; sourceTree = ""; }; 445BA07729C07B3D0036A7C5 /* Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notification.swift; sourceTree = ""; }; @@ -715,6 +717,7 @@ isa = PBXGroup; children = ( EA985C22296E033A00F2FF2E /* TextArea.swift */, + 186B2A892B88DA7F001AB71F /* TextAreaChangeLog.txt */, ); path = TextArea; sourceTree = ""; @@ -946,6 +949,7 @@ EA3362042891E14D0071C351 /* VerizonNHGeTX-Bold.otf in Resources */, 71C02B382B7BD98F00E93E66 /* NotificationChangeLog.txt in Resources */, EAEEECA72B1F952000531FC2 /* TabsChangeLog.txt in Resources */, + 186B2A8A2B88DA7F001AB71F /* TextAreaChangeLog.txt in Resources */, EAEEEC962B1F893B00531FC2 /* ButtonChangeLog.txt in Resources */, EA5F86CC2A1D28B500BC83E4 /* ReleaseNotes.txt in Resources */, EAEEEC982B1F8DD100531FC2 /* LineChangeLog.txt in Resources */, diff --git a/VDS/Components/TextFields/TextArea/TextAreaChangeLog.txt b/VDS/Components/TextFields/TextArea/TextAreaChangeLog.txt new file mode 100644 index 00000000..555ad730 --- /dev/null +++ b/VDS/Components/TextFields/TextArea/TextAreaChangeLog.txt @@ -0,0 +1,38 @@ +MM/DD/YYYY +---------------- +- Initial Brand 3.0 handoff + +12/27/2021 +---------------- +- Removed Max idth Updated the SPECS with FormControl tokens + +02/25/2022 +---------------- +- Replaced Info and Error Non-Scaling icons with VDS Icon. +- Removed “weight” and “vector effect” from Anatomy and States. + +07/27/2022 +---------------- +- Added Configurations section with transparentBackground principles. + +08/10/2022 +---------------- +- Updated default and inverted prop to light and dark surface. + +11/30/2022 +---------------- +- Added "(web only)" to any instance of "keyboard focus" + +12/13/2022 +---------------- +- Replaced form border and focus border pixel values and style & spacing with tokens. + +01/18/2023 +---------------- +- Updated Anatomy items: +- Added “Highlight” to item #10 +- Changed item #7 to “Tooltip” from “Tooltip Component” + +04/12/2023 +---------------- +- Updated hex colors for updated feedback tokens in error states. From f7134b9b8cd0e763b0a79952974e390b0a7fe2f8 Mon Sep 17 00:00:00 2001 From: vasavk Date: Mon, 26 Feb 2024 11:52:06 +0530 Subject: [PATCH 08/32] Digital ACT191 story ONEAPP-6682 Character limit, error text, and readonly changes. - show error text when exceeds character limit. - No restriction if character counter does not display. - color changes for character counter label, error text, and readonly. - Showing Character count overflow. --- .../TextFields/EntryFieldBase.swift | 42 +++++++++++---- .../TextFields/TextArea/TextArea.swift | 54 +++++++++++++------ 2 files changed, 72 insertions(+), 24 deletions(-) diff --git a/VDS/Components/TextFields/EntryFieldBase.swift b/VDS/Components/TextFields/EntryFieldBase.swift index 0d6a93e5..dcb16fbf 100644 --- a/VDS/Components/TextFields/EntryFieldBase.swift +++ b/VDS/Components/TextFields/EntryFieldBase.swift @@ -107,11 +107,15 @@ open class EntryFieldBase: Control, Changeable { } internal var borderColorConfiguration = ControlColorConfiguration().with { - $0.setSurfaceColors(VDSFormControlsColor.borderOnlight, VDSFormControlsColor.borderOnlight, forState: .normal) + $0.setSurfaceColors(VDSFormControlsColor.borderOnlight, VDSFormControlsColor.borderOndark, forState: .normal) $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forState: .disabled) $0.setSurfaceColors(VDSColor.feedbackErrorOnlight, VDSColor.feedbackErrorOndark, forState: .error) } + internal var readOnlyBorderColorConfiguration = ControlColorConfiguration().with { + $0.setSurfaceColors(VDSFormControlsColor.borderReadonlyOnlight, VDSFormControlsColor.borderReadonlyOndark, forState: .normal) + } + //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- @@ -160,8 +164,22 @@ open class EntryFieldBase: Control, Changeable { } } - open var errorText: String? { didSet { setNeedsUpdate() } } - + private var _errorText: String? + + open var errorText: String? { + get { return _errorText } + set { + if let newValue { + _errorText = newValue + } else { + _errorText = nil + } + updateContainerView() + updateErrorLabel() + setNeedsUpdate() + } + } + open var tooltipModel: Tooltip.TooltipModel? { didSet { setNeedsUpdate() } } open var transparentBackground: Bool = false { didSet { setNeedsUpdate() } } @@ -212,7 +230,7 @@ open class EntryFieldBase: Control, Changeable { //this is the horizontal stack that contains //the left, InputContainer, Icons, Buttons container.addSubview(containerStackView) - containerStackView.pinToSuperView(.uniform(VDSFormControls.spaceInset)) + containerStackView.pinToSuperView(.uniform(12)) //add the view to add input fields containerStackView.addArrangedSubview(controlContainerView) @@ -279,11 +297,7 @@ open class EntryFieldBase: Control, Changeable { open override func updateView() { super.updateView() - containerView.backgroundColor = backgroundColorConfiguration.getColor(self) - containerView.layer.borderColor = borderColorConfiguration.getColor(self).cgColor - containerView.layer.borderWidth = VDSFormControls.widthBorder - containerView.layer.cornerRadius = VDSFormControls.borderradius - + updateContainerView() updateTitleLabel() updateErrorLabel() updateHelperLabel() @@ -291,6 +305,16 @@ open class EntryFieldBase: Control, Changeable { backgroundColor = surface.color } + //-------------------------------------------------- + // MARK: - Private Methods + //-------------------------------------------------- + private func updateContainerView() { + containerView.backgroundColor = backgroundColorConfiguration.getColor(self) + containerView.layer.borderColor = borderColorConfiguration.getColor(self).cgColor + containerView.layer.borderWidth = VDSFormControls.widthBorder + containerView.layer.cornerRadius = VDSFormControls.borderradius + } + //-------------------------------------------------- // MARK: - Public Methods //-------------------------------------------------- diff --git a/VDS/Components/TextFields/TextArea/TextArea.swift b/VDS/Components/TextFields/TextArea/TextArea.swift index 105286b5..1a91a099 100644 --- a/VDS/Components/TextFields/TextArea/TextArea.swift +++ b/VDS/Components/TextFields/TextArea/TextArea.swift @@ -61,9 +61,11 @@ open class TextArea: EntryFieldBase { } }() - open var characterCountLabel = Label().with { + open var characterCounterLabel = Label().with { $0.setContentCompressionResistancePriority(.required, for: .vertical) $0.textStyle = .bodySmall + $0.textAlignment = .right + $0.numberOfLines = 1 } //-------------------------------------------------- @@ -112,8 +114,8 @@ open class TextArea: EntryFieldBase { open override func reset() { super.reset() textView.text = "" - characterCountLabel.reset() - characterCountLabel.textStyle = .bodySmall + characterCounterLabel.reset() + characterCounterLabel.textStyle = .bodySmall } /// Container for the area in which the user interacts. @@ -139,11 +141,20 @@ open class TextArea: EntryFieldBase { minWidthConstraint?.isActive = true } - // allow - 20% of character limit - let overflowLimit = Double(maxLength ?? 0) * 0.20 - allowCharCount = Int(overflowLimit) + (maxLength ?? 0) - characterCountLabel.text = getLimitText() - + if ((maxLength ?? 0) > 0) { + // allow - 20% of character limit + let overflowLimit = Double(maxLength ?? 0) * 0.20 + allowCharCount = Int(overflowLimit) + (maxLength ?? 0) + characterCounterLabel.text = getCharacterCounterText() + } else { + characterCounterLabel.text = "" + } + + icon.size = .medium + containerView.layer.borderColor = readOnly ? readOnlyBorderColorConfiguration.getColor(self).cgColor : borderColorConfiguration.getColor(self).cgColor + textView.isEditable = readOnly ? false : true + textView.backgroundColor = backgroundColorConfiguration.getColor(self) + characterCounterLabel.textColorConfiguration = primaryColorConfiguration.eraseToAnyColorable() } /// Container for the area which shows helper text, error text, character count, max length value. @@ -151,18 +162,25 @@ open class TextArea: EntryFieldBase { bottomView.addSubview(bottomStackView) bottomStackView.pinToSuperView() bottomStackView.addArrangedSubview(bottomContainerView) - bottomStackView.addArrangedSubview(characterCountLabel) + bottomStackView.addArrangedSubview(characterCounterLabel) return bottomView } //-------------------------------------------------- // MARK: - Private Methods //-------------------------------------------------- - private func getLimitText() -> String { + private func getCharacterCounterText() -> String { let count = textView.text.count let countStr = (count > maxLength ?? 0) ? ("-" + "\(count-(maxLength ?? 0))") : "\(count)" - let text = "\(countStr)" + "/" + "\(maxLength ?? 0)" - return text + if count > maxLength ?? 0 { + showError = true + errorText = "You have exceeded the character limit." + return countStr + } else { + showError = false + errorText = "" + return ("\(countStr)" + "/" + "\(maxLength ?? 0)") + } } } @@ -187,12 +205,18 @@ extension TextArea: UITextViewDelegate { textViewHeightConstraint.isActive = true } - if textView.text.count <= allowCharCount { + if ((maxLength ?? 0) > 0) { + if textView.text.count <= allowCharCount { + //setting the value and firing control event + value = textView.text + sendActions(for: .valueChanged) + } else { + textView.text.removeLast() + } + } else { //setting the value and firing control event value = textView.text sendActions(for: .valueChanged) - } else { - textView.text.removeLast() } } } From 5b010275546b6428872ce76e894f9a4a74ca71a4 Mon Sep 17 00:00:00 2001 From: vasavk Date: Mon, 26 Feb 2024 14:54:15 +0530 Subject: [PATCH 09/32] Digital ACT191 story ONEAPP-6682 highlight text color, background color for character counter --- .../TextFields/TextArea/TextArea.swift | 51 +++++++++++++++---- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/VDS/Components/TextFields/TextArea/TextArea.swift b/VDS/Components/TextFields/TextArea/TextArea.swift index 1a91a099..1ac1900d 100644 --- a/VDS/Components/TextFields/TextArea/TextArea.swift +++ b/VDS/Components/TextFields/TextArea/TextArea.swift @@ -87,6 +87,21 @@ open class TextArea: EntryFieldBase { $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forDisabled: false) }.eraseToAnyColorable() { didSet { setNeedsUpdate() } } + /// Color configuration for error icon. + internal var iconColorConfiguration = ControlColorConfiguration().with { + $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .normal) + } + + /// Color configuration for character counter's highlight background color + internal var highlightBackgroundColor = ControlColorConfiguration().with { + $0.setSurfaceColors(VDSColor.backgroundPrimaryDark, VDSColor.backgroundPrimaryLight, forState: .normal) + } + + /// Color configuration for character counter's highlight text color + internal var highlightTextColor = ControlColorConfiguration().with { + $0.setSurfaceColors(VDSColor.elementsPrimaryOndark, VDSColor.elementsPrimaryOnlight, forState: .normal) + } + //-------------------------------------------------- // MARK: - Overrides //-------------------------------------------------- @@ -106,7 +121,6 @@ open class TextArea: EntryFieldBase { textViewHeightConstraint?.isActive = true backgroundColorConfiguration.setSurfaceColors(VDSColor.feedbackSuccessBackgroundOnlight, VDSColor.feedbackSuccessBackgroundOndark, forState: .success) borderColorConfiguration.setSurfaceColors(VDSColor.feedbackSuccessOnlight, VDSColor.feedbackSuccessOndark, forState: .success) - textView.delegate = self } @@ -151,13 +165,15 @@ open class TextArea: EntryFieldBase { } icon.size = .medium + icon.color = iconColorConfiguration.getColor(self) containerView.layer.borderColor = readOnly ? readOnlyBorderColorConfiguration.getColor(self).cgColor : borderColorConfiguration.getColor(self).cgColor textView.isEditable = readOnly ? false : true textView.backgroundColor = backgroundColorConfiguration.getColor(self) characterCounterLabel.textColorConfiguration = primaryColorConfiguration.eraseToAnyColorable() + textView.tintColor = iconColorConfiguration.getColor(self) } - /// Container for the area which shows helper text, error text, character count, max length value. + /// Container for the area showing helper text, error text, character count, maximum length value. open override func getBottomContainer() -> UIView { bottomView.addSubview(bottomStackView) bottomStackView.pinToSuperView() @@ -182,6 +198,15 @@ open class TextArea: EntryFieldBase { return ("\(countStr)" + "/" + "\(maxLength ?? 0)") } } + + open func highlightCharacterOverflow() { + let count = textView.text.count + print("count: \(count), maxLength: \(maxLength ?? 0)") + guard let text = textView.attributedText?.mutableCopy() as? NSMutableAttributedString else { return } + text.addAttribute(NSAttributedString.Key.backgroundColor, value: highlightBackgroundColor.getColor(self), range: NSRange(location:(maxLength ?? 0 ), length: (count - (maxLength ?? 0)))) + text.addAttribute(NSAttributedString.Key.foregroundColor, value: highlightTextColor.getColor(self), range: NSRange(location:(maxLength ?? 0 ), length: (count - (maxLength ?? 0)))) + textView.attributedText = text.copy() as? NSAttributedString + } } extension TextArea: UITextViewDelegate { @@ -189,29 +214,35 @@ extension TextArea: UITextViewDelegate { // MARK: - UITextViewDelegate //-------------------------------------------------- public func textViewDidChange(_ textView: UITextView) { - + //dynamic textView Height sizing based on Figma //if you want it to work "as-is" delete this code //since it will autogrow with the current settings if let textViewHeightConstraint, textView.isEditable { let height = textView.contentSize.height - if height > 88 && height < 176 { - textViewHeightConstraint.constant = 176 - } else if height > 176 { - textViewHeightConstraint.constant = 352 - } else { - textViewHeightConstraint.constant = 88 - } + if height > 88 && height < 176 { + textViewHeightConstraint.constant = 176 + } else if height > 176 { + textViewHeightConstraint.constant = 352 + } else { + textViewHeightConstraint.constant = 88 + } textViewHeightConstraint.isActive = true } + //The exceeding characters will be highlighted to help users correct their entry. if ((maxLength ?? 0) > 0) { if textView.text.count <= allowCharCount { //setting the value and firing control event value = textView.text sendActions(for: .valueChanged) + + if (textView.text.count > (maxLength ?? 0)) { + highlightCharacterOverflow() + } } else { textView.text.removeLast() + highlightCharacterOverflow() } } else { //setting the value and firing control event From 72ef366eedddeeae35e4fdae1fb005777957b033 Mon Sep 17 00:00:00 2001 From: vasavk Date: Mon, 26 Feb 2024 17:02:36 +0530 Subject: [PATCH 10/32] Digital ACT191 story ONEAPP-6682 added accessibility, focused border color to container --- .../TextFields/TextArea/TextArea.swift | 35 ++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/VDS/Components/TextFields/TextArea/TextArea.swift b/VDS/Components/TextFields/TextArea/TextArea.swift index 1ac1900d..01604134 100644 --- a/VDS/Components/TextFields/TextArea/TextArea.swift +++ b/VDS/Components/TextFields/TextArea/TextArea.swift @@ -108,6 +108,10 @@ open class TextArea: EntryFieldBase { /// Called once when a view is initialized and is used to Setup additional UI or other constants and configurations. open override func setup() { super.setup() + accessibilityLabel = "TextArea" + isAccessibilityElement = true + + containerStackView.pinToSuperView(.uniform(VDSFormControls.spaceInset)) minWidthConstraint = containerView.widthAnchor.constraint(greaterThanOrEqualToConstant: containerSize.width) minWidthConstraint?.isActive = true controlContainerView.addSubview(textView) @@ -117,10 +121,12 @@ open class TextArea: EntryFieldBase { .pinTrailingLessThanOrEqualTo(nil, 0, .defaultHigh) .pinBottom(0, .defaultHigh) textView.isScrollEnabled = true + textView.autocorrectionType = .no textViewHeightConstraint = textView.heightAnchor.constraint(greaterThanOrEqualToConstant: containerSize.height) textViewHeightConstraint?.isActive = true backgroundColorConfiguration.setSurfaceColors(VDSColor.feedbackSuccessBackgroundOnlight, VDSColor.feedbackSuccessBackgroundOndark, forState: .success) borderColorConfiguration.setSurfaceColors(VDSColor.feedbackSuccessOnlight, VDSColor.feedbackSuccessOndark, forState: .success) + borderColorConfiguration.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .focused) textView.delegate = self } @@ -182,26 +188,39 @@ open class TextArea: EntryFieldBase { return bottomView } + /// Used to update any Accessibility properties. + open override func updateAccessibility() { + super.updateAccessibility() + if showError { + setAccessibilityLabel(for: [titleLabel, textView, errorLabel, helperLabel]) + } else { + setAccessibilityLabel(for: [titleLabel, textView, helperLabel]) + } + } + //-------------------------------------------------- // MARK: - Private Methods //-------------------------------------------------- private func getCharacterCounterText() -> String { let count = textView.text.count let countStr = (count > maxLength ?? 0) ? ("-" + "\(count-(maxLength ?? 0))") : "\(count)" - if count > maxLength ?? 0 { - showError = true - errorText = "You have exceeded the character limit." - return countStr + if ((maxLength ?? 0) > 0) { + if (count > (maxLength ?? 0)) { + showError = true + errorText = "You have exceeded the character limit." + return countStr + } else { + showError = false + errorText = "" + return ("\(countStr)" + "/" + "\(maxLength ?? 0)") + } } else { - showError = false - errorText = "" - return ("\(countStr)" + "/" + "\(maxLength ?? 0)") + return "" } } open func highlightCharacterOverflow() { let count = textView.text.count - print("count: \(count), maxLength: \(maxLength ?? 0)") guard let text = textView.attributedText?.mutableCopy() as? NSMutableAttributedString else { return } text.addAttribute(NSAttributedString.Key.backgroundColor, value: highlightBackgroundColor.getColor(self), range: NSRange(location:(maxLength ?? 0 ), length: (count - (maxLength ?? 0)))) text.addAttribute(NSAttributedString.Key.foregroundColor, value: highlightTextColor.getColor(self), range: NSRange(location:(maxLength ?? 0 ), length: (count - (maxLength ?? 0)))) From f527ec5483ea03bf8f7318f73c54913175098b01 Mon Sep 17 00:00:00 2001 From: vasavk Date: Mon, 26 Feb 2024 18:02:37 +0530 Subject: [PATCH 11/32] Digital ACT191 story ONEAPP-6682 minor changes --- .../TextFields/TextArea/TextArea.swift | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/VDS/Components/TextFields/TextArea/TextArea.swift b/VDS/Components/TextFields/TextArea/TextArea.swift index 01604134..135a2421 100644 --- a/VDS/Components/TextFields/TextArea/TextArea.swift +++ b/VDS/Components/TextFields/TextArea/TextArea.swift @@ -42,7 +42,7 @@ open class TextArea: EntryFieldBase { $0.translatesAutoresizingMaskIntoConstraints = false $0.axis = .horizontal $0.distribution = .fill - $0.spacing = 12 + $0.spacing = VDSLayout.Spacing.space3X.value } }() @@ -58,6 +58,7 @@ open class TextArea: EntryFieldBase { $0.axis = .horizontal $0.distribution = .fill $0.alignment = .top + $0.spacing = VDSLayout.Spacing.space2X.value } }() @@ -128,6 +129,8 @@ open class TextArea: EntryFieldBase { borderColorConfiguration.setSurfaceColors(VDSColor.feedbackSuccessOnlight, VDSColor.feedbackSuccessOndark, forState: .success) borderColorConfiguration.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .focused) textView.delegate = self + characterCounterLabel.textColorConfiguration = primaryColorConfiguration.eraseToAnyColorable() + bottomContainerStackView.spacing = VDSLayout.Spacing.space2X.value } /// Resets to default settings. @@ -161,10 +164,10 @@ open class TextArea: EntryFieldBase { minWidthConstraint?.isActive = true } - if ((maxLength ?? 0) > 0) { + if let maxLength, maxLength > 0 { // allow - 20% of character limit - let overflowLimit = Double(maxLength ?? 0) * 0.20 - allowCharCount = Int(overflowLimit) + (maxLength ?? 0) + let overflowLimit = Double(maxLength) * 0.20 + allowCharCount = Int(overflowLimit) + maxLength characterCounterLabel.text = getCharacterCounterText() } else { characterCounterLabel.text = "" @@ -175,8 +178,9 @@ open class TextArea: EntryFieldBase { containerView.layer.borderColor = readOnly ? readOnlyBorderColorConfiguration.getColor(self).cgColor : borderColorConfiguration.getColor(self).cgColor textView.isEditable = readOnly ? false : true textView.backgroundColor = backgroundColorConfiguration.getColor(self) - characterCounterLabel.textColorConfiguration = primaryColorConfiguration.eraseToAnyColorable() textView.tintColor = iconColorConfiguration.getColor(self) + characterCounterLabel.surface = surface + highlightCharacterOverflow() } /// Container for the area showing helper text, error text, character count, maximum length value. @@ -221,9 +225,11 @@ open class TextArea: EntryFieldBase { open func highlightCharacterOverflow() { let count = textView.text.count - guard let text = textView.attributedText?.mutableCopy() as? NSMutableAttributedString else { return } - text.addAttribute(NSAttributedString.Key.backgroundColor, value: highlightBackgroundColor.getColor(self), range: NSRange(location:(maxLength ?? 0 ), length: (count - (maxLength ?? 0)))) - text.addAttribute(NSAttributedString.Key.foregroundColor, value: highlightTextColor.getColor(self), range: NSRange(location:(maxLength ?? 0 ), length: (count - (maxLength ?? 0)))) + guard let maxLength, + count > maxLength, + let text = textView.attributedText?.mutableCopy() as? NSMutableAttributedString else { return } + text.addAttribute(NSAttributedString.Key.backgroundColor, value: highlightBackgroundColor.getColor(self), range: NSRange(location:maxLength, length: (count - maxLength))) + text.addAttribute(NSAttributedString.Key.foregroundColor, value: highlightTextColor.getColor(self), range: NSRange(location:maxLength, length: (count - maxLength))) textView.attributedText = text.copy() as? NSAttributedString } } From 4f41d9cc93b07d6cf3481bbe8ae141b2827184ff Mon Sep 17 00:00:00 2001 From: vasavk Date: Mon, 26 Feb 2024 22:46:33 +0530 Subject: [PATCH 12/32] Digital ACT191 story ONEAPP-6682 added preset default height property. --- .../TextFields/TextArea/TextArea.swift | 54 +++++++++++++++---- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/VDS/Components/TextFields/TextArea/TextArea.swift b/VDS/Components/TextFields/TextArea/TextArea.swift index 135a2421..a9c1cbf4 100644 --- a/VDS/Components/TextFields/TextArea/TextArea.swift +++ b/VDS/Components/TextFields/TextArea/TextArea.swift @@ -69,11 +69,44 @@ open class TextArea: EntryFieldBase { $0.numberOfLines = 1 } + private var _minHeight: Height = .twoX + + open var minHeight: Height? { + get { return _minHeight } + set { + if let newValue { + _minHeight = newValue + } else { + _minHeight = .twoX + } + textViewHeightConstraint?.constant = _minHeight.value + setNeedsUpdate() + } + } + //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- override var containerSize: CGSize { CGSize(width: 182, height: 88) } - + + /// Enum used to describe the the height of TextArea. + public enum Height: String, CaseIterable { + case twoX = "2X" + case fourX = "4X" + case eightX = "8X" + + var value: CGFloat { + switch self { + case .twoX: + 88 + case .fourX: + 176 + case .eightX: + 352 + } + } + } + /// UITextView shown in the TextArea. open var textView = UITextView().with { $0.translatesAutoresizingMaskIntoConstraints = false @@ -139,6 +172,8 @@ open class TextArea: EntryFieldBase { textView.text = "" characterCounterLabel.reset() characterCounterLabel.textStyle = .bodySmall + minHeight = .twoX + setNeedsUpdate() } /// Container for the area in which the user interacts. @@ -230,7 +265,7 @@ open class TextArea: EntryFieldBase { let text = textView.attributedText?.mutableCopy() as? NSMutableAttributedString else { return } text.addAttribute(NSAttributedString.Key.backgroundColor, value: highlightBackgroundColor.getColor(self), range: NSRange(location:maxLength, length: (count - maxLength))) text.addAttribute(NSAttributedString.Key.foregroundColor, value: highlightTextColor.getColor(self), range: NSRange(location:maxLength, length: (count - maxLength))) - textView.attributedText = text.copy() as? NSAttributedString + textView.attributedText = text } } @@ -244,15 +279,15 @@ extension TextArea: UITextViewDelegate { //if you want it to work "as-is" delete this code //since it will autogrow with the current settings if let textViewHeightConstraint, textView.isEditable { - let height = textView.contentSize.height - if height > 88 && height < 176 { - textViewHeightConstraint.constant = 176 - } else if height > 176 { - textViewHeightConstraint.constant = 352 + var height = textView.contentSize.height + height = max(height, _minHeight.value) + if height > Height.twoX.value && height < Height.fourX.value { + textViewHeightConstraint.constant = Height.fourX.value + } else if height > Height.fourX.value { + textViewHeightConstraint.constant = Height.eightX.value } else { - textViewHeightConstraint.constant = 88 + textViewHeightConstraint.constant = Height.twoX.value } - textViewHeightConstraint.isActive = true } //The exceeding characters will be highlighted to help users correct their entry. @@ -261,7 +296,6 @@ extension TextArea: UITextViewDelegate { //setting the value and firing control event value = textView.text sendActions(for: .valueChanged) - if (textView.text.count > (maxLength ?? 0)) { highlightCharacterOverflow() } From 9e91f38c52475851f072a4291dc891968904b3e3 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 26 Feb 2024 17:50:47 -0600 Subject: [PATCH 13/32] added "text" as a property Signed-off-by: Matt Bruce --- VDS/Components/TextFields/EntryFieldBase.swift | 6 ++++++ VDS/Components/TextFields/InputField/InputField.swift | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/VDS/Components/TextFields/EntryFieldBase.swift b/VDS/Components/TextFields/EntryFieldBase.swift index dcb16fbf..e66d31a5 100644 --- a/VDS/Components/TextFields/EntryFieldBase.swift +++ b/VDS/Components/TextFields/EntryFieldBase.swift @@ -180,6 +180,12 @@ open class EntryFieldBase: Control, Changeable { } } + /// Override this to conveniently get/set the textfield(s). + open var text: String? { + get { nil } + set { fatalError("You MUST override EntryField's 'text' variable in your subclass.") } + } + open var tooltipModel: Tooltip.TooltipModel? { didSet { setNeedsUpdate() } } open var transparentBackground: Bool = false { didSet { setNeedsUpdate() } } diff --git a/VDS/Components/TextFields/InputField/InputField.swift b/VDS/Components/TextFields/InputField/InputField.swift index 94ef5231..589ba28f 100644 --- a/VDS/Components/TextFields/InputField/InputField.swift +++ b/VDS/Components/TextFields/InputField/InputField.swift @@ -78,6 +78,14 @@ open class InputField: EntryFieldBase, UITextFieldDelegate { /// Representing the type of input. open var fieldType: FieldType = .text { didSet { setNeedsUpdate() } } + /// The text of this textField. + open override var text: String? { + get { textField.text } + set { + textField.text = newValue + } + } + var _showError: Bool = false /// Whether not to show the error. open override var showError: Bool { From 6d38474675932ac6cf855e88aa59d82e5c5090cb Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 26 Feb 2024 17:51:16 -0600 Subject: [PATCH 14/32] added text as a property added subclass of UITextField to deal with text rendering and attributes. Signed-off-by: Matt Bruce --- .../TextFields/TextArea/TextArea.swift | 179 ++++++++++++++++-- 1 file changed, 164 insertions(+), 15 deletions(-) diff --git a/VDS/Components/TextFields/TextArea/TextArea.swift b/VDS/Components/TextFields/TextArea/TextArea.swift index a9c1cbf4..e9da9b11 100644 --- a/VDS/Components/TextFields/TextArea/TextArea.swift +++ b/VDS/Components/TextFields/TextArea/TextArea.swift @@ -107,20 +107,21 @@ open class TextArea: EntryFieldBase { } } + /// The text of this textField. + open override var text: String? { + get { textView.text } + set { + textView.text = newValue + } + } + /// UITextView shown in the TextArea. - open var textView = UITextView().with { + open var textView = TextView().with { $0.translatesAutoresizingMaskIntoConstraints = false - $0.font = TextStyle.bodyLarge.font $0.sizeToFit() $0.isScrollEnabled = false } - /// Color configuration for the textView. - open var textViewTextColorConfiguration: AnyColorable = ViewColorConfiguration().with { - $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forDisabled: true) - $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forDisabled: false) - }.eraseToAnyColorable() { didSet { setNeedsUpdate() } } - /// Color configuration for error icon. internal var iconColorConfiguration = ControlColorConfiguration().with { $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .normal) @@ -187,7 +188,9 @@ open class TextArea: EntryFieldBase { super.updateView() textView.isEditable = isEnabled - textView.textColor = textViewTextColorConfiguration.getColor(self) + textView.isEnabled = isEnabled + textView.surface = surface + //set the width constraints if let width { widthConstraint?.constant = width @@ -260,12 +263,18 @@ open class TextArea: EntryFieldBase { open func highlightCharacterOverflow() { let count = textView.text.count - guard let maxLength, - count > maxLength, - let text = textView.attributedText?.mutableCopy() as? NSMutableAttributedString else { return } - text.addAttribute(NSAttributedString.Key.backgroundColor, value: highlightBackgroundColor.getColor(self), range: NSRange(location:maxLength, length: (count - maxLength))) - text.addAttribute(NSAttributedString.Key.foregroundColor, value: highlightTextColor.getColor(self), range: NSRange(location:maxLength, length: (count - maxLength))) - textView.attributedText = text + guard let maxLength, count > maxLength else { + textView.textAttributes = nil + return + } + + var textAttributes = [any LabelAttributeModel]() + let location = maxLength + let length = count - maxLength + textAttributes.append(ColorLabelAttribute(location: location, length: length, color: highlightBackgroundColor.getColor(self), isForegroundColor: false)) + textAttributes.append(ColorLabelAttribute(location: location, length: length, color: highlightTextColor.getColor(self), isForegroundColor: true)) + + textView.textAttributes = textAttributes } } @@ -310,3 +319,143 @@ extension TextArea: UITextViewDelegate { } } } + +/// Will move this into a new file, need to talk with Scott/Kyle +open class TextView: UITextView, ViewProtocol { + + //-------------------------------------------------- + // MARK: - Initializers + //-------------------------------------------------- + required public init() { + super.init(frame: .zero, textContainer: nil) + initialSetup() + } + + public override init(frame: CGRect, textContainer: NSTextContainer?) { + super.init(frame: frame, textContainer: textContainer) + initialSetup() + } + + public required init?(coder: NSCoder) { + super.init(coder: coder) + initialSetup() + } + + //-------------------------------------------------- + // MARK: - Combine Properties + //-------------------------------------------------- + /// Set of Subscribers for any Publishers for this Control. + open var subscribers = Set() + + //-------------------------------------------------- + // MARK: - Private Properties + //-------------------------------------------------- + private var initialSetupPerformed = false + + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + /// Key of whether or not updateView() is called in setNeedsUpdate() + open var shouldUpdateView: Bool = true + + open var surface: Surface = .light { didSet { setNeedsUpdate() } } + + /// Array of LabelAttributeModel objects used in rendering the text. + open var textAttributes: [any LabelAttributeModel]? { didSet { setNeedsUpdate() } } + + /// TextStyle used on the titleLabel. + open var textStyle: TextStyle { .defaultStyle } + + /// Will determine if a scaled font should be used for the titleLabel font. + open var useScaledFont: Bool = false { didSet { setNeedsUpdate() } } + + open var isEnabled: Bool = true { didSet { setNeedsUpdate() } } + + open var textColorConfiguration: AnyColorable = ViewColorConfiguration().with { + $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forDisabled: true) + $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forDisabled: false) + }.eraseToAnyColorable(){ didSet { setNeedsUpdate() }} + + open override var textColor: UIColor? { + get { textColorConfiguration.getColor(self) } + set { } + } + + override public var text: String! { + get { super.text } + set { + super.text = newValue + updateLabel() + } + } + + override public var textAlignment: NSTextAlignment { + didSet { + if textAlignment != oldValue { + // Text alignment can be part of our paragraph style, so we may need to + // re-style when changed + updateLabel() + } + } + } + + //-------------------------------------------------- + // MARK: - Lifecycle + //-------------------------------------------------- + open func initialSetup() { + if !initialSetupPerformed { + backgroundColor = .clear + translatesAutoresizingMaskIntoConstraints = false + accessibilityCustomActions = [] + setup() + setNeedsUpdate() + } + } + + + open func setup() { + translatesAutoresizingMaskIntoConstraints = false + } + + open func updateView() { + updateLabel() + } + + open func updateAccessibility() {} + + open func reset() { + shouldUpdateView = false + surface = .light + text = nil + accessibilityCustomActions = [] + shouldUpdateView = true + setNeedsUpdate() + } + + //-------------------------------------------------- + // MARK: - Private Methods + //-------------------------------------------------- + private func updateLabel() { + + //clear the arrays holding actions + accessibilityCustomActions = [] + if let text, !text.isEmpty { + //create the primary string + let mutableText = NSMutableAttributedString.mutableText(for: text, + textStyle: textStyle, + useScaledFont: useScaledFont, + textColor: textColor!, + alignment: textAlignment, + lineBreakMode: .byWordWrapping) + //apply any attributes + if let attributes = textAttributes { + mutableText.apply(attributes: attributes) + } + attributedText = mutableText + } else { + attributedText = nil + } + } + + +} From a2026a4319069a7b56b67a7953511e22d334b75c Mon Sep 17 00:00:00 2001 From: vasavk Date: Tue, 27 Feb 2024 17:24:16 +0530 Subject: [PATCH 15/32] Digital ACT191 story ONEAPP-6682 removed unnecessary code --- VDS/Components/TextFields/TextArea/TextArea.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/VDS/Components/TextFields/TextArea/TextArea.swift b/VDS/Components/TextFields/TextArea/TextArea.swift index a9c1cbf4..3cf465dc 100644 --- a/VDS/Components/TextFields/TextArea/TextArea.swift +++ b/VDS/Components/TextFields/TextArea/TextArea.swift @@ -143,7 +143,6 @@ open class TextArea: EntryFieldBase { open override func setup() { super.setup() accessibilityLabel = "TextArea" - isAccessibilityElement = true containerStackView.pinToSuperView(.uniform(VDSFormControls.spaceInset)) minWidthConstraint = containerView.widthAnchor.constraint(greaterThanOrEqualToConstant: containerSize.width) @@ -172,7 +171,6 @@ open class TextArea: EntryFieldBase { textView.text = "" characterCounterLabel.reset() characterCounterLabel.textStyle = .bodySmall - minHeight = .twoX setNeedsUpdate() } From f4f6a005e40e99bb8b620cbeaada917d0be4a792 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 27 Feb 2024 09:47:50 -0600 Subject: [PATCH 16/32] put accessibility changes to method. Signed-off-by: Matt Bruce --- VDS/Components/Loader/Loader.swift | 37 +++++++++++++++--------------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/VDS/Components/Loader/Loader.swift b/VDS/Components/Loader/Loader.swift index 90d589be..baf6ecdb 100644 --- a/VDS/Components/Loader/Loader.swift +++ b/VDS/Components/Loader/Loader.swift @@ -87,8 +87,26 @@ open class Loader: View { } invalidateIntrinsicContentSize() } - + open override func updateAccessibility() { + super.updateAccessibility() + + // check to make sure VoiceOver is running + guard UIAccessibility.isVoiceOverRunning, isActive else { + loadingTimer?.invalidate() + loadingTimer = nil + return + } + + // Focus VoiceOver on this view + UIAccessibility.post(notification: .layoutChanged, argument: self) + + // setup timer for post + loadingTimer = Timer.scheduledTimer(withTimeInterval: 60, repeats: true) { [weak self] _ in + guard let self, self.isActive, self.isVisibleOnScreen else { return } + self.accessibilityLabel = "Still Loading" + UIAccessibility.post(notification: .announcement, argument: "Still Loading") + } } //-------------------------------------------------- @@ -107,23 +125,6 @@ open class Loader: View { rotation.duration = 0.5 rotation.repeatCount = .infinity icon.layer.add(rotation, forKey: rotationLayerName) - - // check to make sure VoiceOver is running - guard UIAccessibility.isVoiceOverRunning else { - loadingTimer?.invalidate() - loadingTimer = nil - return - } - - // Focus VoiceOver on this view - UIAccessibility.post(notification: .layoutChanged, argument: self) - - // setup timer for post - loadingTimer = Timer.scheduledTimer(withTimeInterval: 60, repeats: true) { [weak self] _ in - guard let self, self.isActive, self.isVisibleOnScreen else { return } - self.accessibilityLabel = "Still Loading" - UIAccessibility.post(notification: .announcement, argument: "Still Loading") - } } private func stopAnimating() { From d8e393049a8c4bc189e85d1f68e230396cfa122e Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 27 Feb 2024 10:02:09 -0600 Subject: [PATCH 17/32] updated release notes and version Signed-off-by: Matt Bruce --- VDS.xcodeproj/project.pbxproj | 4 ++-- VDS/SupportingFiles/ReleaseNotes.txt | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/VDS.xcodeproj/project.pbxproj b/VDS.xcodeproj/project.pbxproj index b13f7df5..ef6acb80 100644 --- a/VDS.xcodeproj/project.pbxproj +++ b/VDS.xcodeproj/project.pbxproj @@ -1253,7 +1253,7 @@ BUILD_LIBRARY_FOR_DISTRIBUTION = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 54; + CURRENT_PROJECT_VERSION = 55; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; @@ -1290,7 +1290,7 @@ BUILD_LIBRARY_FOR_DISTRIBUTION = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 54; + CURRENT_PROJECT_VERSION = 55; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; diff --git a/VDS/SupportingFiles/ReleaseNotes.txt b/VDS/SupportingFiles/ReleaseNotes.txt index 404e531b..e1cd12fd 100644 --- a/VDS/SupportingFiles/ReleaseNotes.txt +++ b/VDS/SupportingFiles/ReleaseNotes.txt @@ -1,3 +1,8 @@ +1.0.55 +---------------- +- ONEAPP-6305 - BadgeIndicator - Finished Development +- ONEAPP-6679 - TileContainer - Finished Development + 1.0.54 ---------------- - CXTDT-518373 Accessibility Voiceover is reading “Still Loading” after waiting for a short time in all the screens. From af2c5cd368d09b083f1f9712d770edc20ab2d39e Mon Sep 17 00:00:00 2001 From: vasavk Date: Wed, 28 Feb 2024 16:39:44 +0530 Subject: [PATCH 18/32] Digital ACT-191 ONEAPP-6682 story: Fixed minor issue for TextArea height --- VDS/Components/TextFields/TextArea/TextArea.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VDS/Components/TextFields/TextArea/TextArea.swift b/VDS/Components/TextFields/TextArea/TextArea.swift index aee4ab9a..92f5525a 100644 --- a/VDS/Components/TextFields/TextArea/TextArea.swift +++ b/VDS/Components/TextFields/TextArea/TextArea.swift @@ -288,7 +288,7 @@ extension TextArea: UITextViewDelegate { if let textViewHeightConstraint, textView.isEditable { var height = textView.contentSize.height height = max(height, _minHeight.value) - if height > Height.twoX.value && height < Height.fourX.value { + if height > Height.twoX.value && height <= Height.fourX.value { textViewHeightConstraint.constant = Height.fourX.value } else if height > Height.fourX.value { textViewHeightConstraint.constant = Height.eightX.value From 301ead74474f52670eac2d3945e88dbf2608f092 Mon Sep 17 00:00:00 2001 From: vasavk Date: Wed, 28 Feb 2024 22:03:17 +0530 Subject: [PATCH 19/32] Digital ACT-191 ONEAPP-6682 story: Fix for the observed crash on removing last char when having char counter and exceeded limit. --- VDS/Components/TextFields/TextArea/TextArea.swift | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/VDS/Components/TextFields/TextArea/TextArea.swift b/VDS/Components/TextFields/TextArea/TextArea.swift index 92f5525a..432d24bd 100644 --- a/VDS/Components/TextFields/TextArea/TextArea.swift +++ b/VDS/Components/TextFields/TextArea/TextArea.swift @@ -300,12 +300,11 @@ extension TextArea: UITextViewDelegate { //The exceeding characters will be highlighted to help users correct their entry. if ((maxLength ?? 0) > 0) { if textView.text.count <= allowCharCount { + highlightCharacterOverflow() + //setting the value and firing control event value = textView.text sendActions(for: .valueChanged) - if (textView.text.count > (maxLength ?? 0)) { - highlightCharacterOverflow() - } } else { textView.text.removeLast() highlightCharacterOverflow() From a4582f11a597b50af9bd082500819f256c61e504 Mon Sep 17 00:00:00 2001 From: vasavk Date: Thu, 29 Feb 2024 00:45:54 +0530 Subject: [PATCH 20/32] Digital ACT-191 ONEAPP-6682 story: fixed the bug dealing with the character counter --- VDS/Components/TextFields/TextArea/TextArea.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/VDS/Components/TextFields/TextArea/TextArea.swift b/VDS/Components/TextFields/TextArea/TextArea.swift index 432d24bd..8e5f8e58 100644 --- a/VDS/Components/TextFields/TextArea/TextArea.swift +++ b/VDS/Components/TextFields/TextArea/TextArea.swift @@ -251,7 +251,7 @@ open class TextArea: EntryFieldBase { return countStr } else { showError = false - errorText = "" + errorText = nil return ("\(countStr)" + "/" + "\(maxLength ?? 0)") } } else { @@ -261,7 +261,7 @@ open class TextArea: EntryFieldBase { open func highlightCharacterOverflow() { let count = textView.text.count - guard let maxLength, count > maxLength else { + guard let maxLength, maxLength > 0, count > maxLength else { textView.textAttributes = nil return } @@ -315,6 +315,7 @@ extension TextArea: UITextViewDelegate { sendActions(for: .valueChanged) } } + } /// Will move this into a new file, need to talk with Scott/Kyle From 4df689b27558182c8a1676a1e7ae59b789d0a227 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 29 Feb 2024 12:14:12 -0600 Subject: [PATCH 21/32] added internalShowError/internalErrorText so that you won't overwrite external validators Signed-off-by: Matt Bruce --- .../TextFields/EntryFieldBase.swift | 45 ++++++++++++++----- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/VDS/Components/TextFields/EntryFieldBase.swift b/VDS/Components/TextFields/EntryFieldBase.swift index e66d31a5..8eed853c 100644 --- a/VDS/Components/TextFields/EntryFieldBase.swift +++ b/VDS/Components/TextFields/EntryFieldBase.swift @@ -153,27 +153,30 @@ open class EntryFieldBase: Control, Changeable { /// Whether not to show the error. open var showError: Bool = false { didSet { setNeedsUpdate() } } + /// Whether or not to show the internal error + internal var showInternalError: Bool = false { didSet { setNeedsUpdate() } } + /// Override UIControl state to add the .error state if showError is true. open override var state: UIControl.State { get { var state = super.state - if showError { + if showError || showInternalError { state.insert(.error) } return state } } - - private var _errorText: String? - + open var errorText: String? { - get { return _errorText } - set { - if let newValue { - _errorText = newValue - } else { - _errorText = nil - } + didSet { + updateContainerView() + updateErrorLabel() + setNeedsUpdate() + } + } + + internal var internalErrorText: String? { + didSet { updateContainerView() updateErrorLabel() setNeedsUpdate() @@ -365,7 +368,16 @@ open class EntryFieldBase: Control, Changeable { } open func updateErrorLabel(){ - if showError, let errorText { + if showError, showInternalError, let errorText, let internalErrorText { + errorLabel.text = [internalErrorText, errorText].joined(separator: "\n") + errorLabel.surface = surface + errorLabel.isEnabled = isEnabled + errorLabel.isHidden = false + icon.name = .error + icon.color = VDSColor.paletteBlack + icon.surface = surface + icon.isHidden = !isEnabled + } else if showError, let errorText { errorLabel.text = errorText errorLabel.surface = surface errorLabel.isEnabled = isEnabled @@ -374,6 +386,15 @@ open class EntryFieldBase: Control, Changeable { icon.color = VDSColor.paletteBlack icon.surface = surface icon.isHidden = !isEnabled + } else if showInternalError, let internalErrorText { + errorLabel.text = internalErrorText + errorLabel.surface = surface + errorLabel.isEnabled = isEnabled + errorLabel.isHidden = false + icon.name = .error + icon.color = VDSColor.paletteBlack + icon.surface = surface + icon.isHidden = !isEnabled } else { icon.isHidden = true errorLabel.isHidden = true From b907e0e001099d480fabcb714bb5cc5afc2c432b Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 29 Feb 2024 12:14:27 -0600 Subject: [PATCH 22/32] implemented new internal error handling Signed-off-by: Matt Bruce --- .../TextFields/TextArea/TextArea.swift | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/VDS/Components/TextFields/TextArea/TextArea.swift b/VDS/Components/TextFields/TextArea/TextArea.swift index 8e5f8e58..d4f11a9e 100644 --- a/VDS/Components/TextFields/TextArea/TextArea.swift +++ b/VDS/Components/TextFields/TextArea/TextArea.swift @@ -112,6 +112,7 @@ open class TextArea: EntryFieldBase { get { textView.text } set { textView.text = newValue + value = newValue } } @@ -227,7 +228,7 @@ open class TextArea: EntryFieldBase { bottomStackView.addArrangedSubview(characterCounterLabel) return bottomView } - + /// Used to update any Accessibility properties. open override func updateAccessibility() { super.updateAccessibility() @@ -246,12 +247,13 @@ open class TextArea: EntryFieldBase { let countStr = (count > maxLength ?? 0) ? ("-" + "\(count-(maxLength ?? 0))") : "\(count)" if ((maxLength ?? 0) > 0) { if (count > (maxLength ?? 0)) { - showError = true - errorText = "You have exceeded the character limit." + showInternalError = true + internalErrorText = "You have exceeded the character limit." return countStr } else { - showError = false - errorText = nil + + showInternalError = false + internalErrorText = nil return ("\(countStr)" + "/" + "\(maxLength ?? 0)") } } else { @@ -303,7 +305,7 @@ extension TextArea: UITextViewDelegate { highlightCharacterOverflow() //setting the value and firing control event - value = textView.text + text = textView.text sendActions(for: .valueChanged) } else { textView.text.removeLast() @@ -311,7 +313,7 @@ extension TextArea: UITextViewDelegate { } } else { //setting the value and firing control event - value = textView.text + text = textView.text sendActions(for: .valueChanged) } } From 3ada7fa0375fbeb7347f6b05d2e8afcc3b1a10ba Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 29 Feb 2024 12:14:35 -0600 Subject: [PATCH 23/32] updated property Signed-off-by: Matt Bruce --- VDS/Components/TextFields/InputField/InputField.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/VDS/Components/TextFields/InputField/InputField.swift b/VDS/Components/TextFields/InputField/InputField.swift index 589ba28f..83768a6b 100644 --- a/VDS/Components/TextFields/InputField/InputField.swift +++ b/VDS/Components/TextFields/InputField/InputField.swift @@ -83,6 +83,7 @@ open class InputField: EntryFieldBase, UITextFieldDelegate { get { textField.text } set { textField.text = newValue + value = newValue } } From de973fd7b87b84ea80ea0e00a95ded23a0946f7b Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 29 Feb 2024 14:06:13 -0600 Subject: [PATCH 24/32] added formfieldable Signed-off-by: Matt Bruce --- VDS/Components/TextFields/EntryFieldBase.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VDS/Components/TextFields/EntryFieldBase.swift b/VDS/Components/TextFields/EntryFieldBase.swift index 8eed853c..121b1510 100644 --- a/VDS/Components/TextFields/EntryFieldBase.swift +++ b/VDS/Components/TextFields/EntryFieldBase.swift @@ -13,7 +13,7 @@ import Combine /// Base Class used to build out a Input controls. @objc(VDSEntryField) -open class EntryFieldBase: Control, Changeable { +open class EntryFieldBase: Control, Changeable, FormFieldable { //-------------------------------------------------- // MARK: - Initializers From 98b30237b285557e00b392b80c5960691d1c41f2 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 28 Feb 2024 13:04:11 -0600 Subject: [PATCH 25/32] updated labels to ensure string is valid Signed-off-by: Matt Bruce --- VDS/Components/Label/Attributes/AnyLabelAttribute.swift | 1 + VDS/Components/Label/Attributes/ColorLabelAttribute.swift | 2 ++ VDS/Components/Label/Attributes/LabelAttributeModel.swift | 4 ++++ .../Label/Attributes/StrikeThroughLabelAttribute.swift | 1 + VDS/Components/Label/Attributes/TextStyleLabelAttribute.swift | 1 + VDS/Components/Label/Attributes/UnderlineLabelAttribute.swift | 3 ++- 6 files changed, 11 insertions(+), 1 deletion(-) diff --git a/VDS/Components/Label/Attributes/AnyLabelAttribute.swift b/VDS/Components/Label/Attributes/AnyLabelAttribute.swift index b914c912..50e76ba7 100644 --- a/VDS/Components/Label/Attributes/AnyLabelAttribute.swift +++ b/VDS/Components/Label/Attributes/AnyLabelAttribute.swift @@ -30,6 +30,7 @@ public struct AnyAttribute: LabelAttributeModel { } public func setAttribute(on attributedString: NSMutableAttributedString) { + guard isValidRange(on: attributedString) else { return } attributedString.removeAttribute(key, range: range) attributedString.addAttribute(key, value: value, range: range) } diff --git a/VDS/Components/Label/Attributes/ColorLabelAttribute.swift b/VDS/Components/Label/Attributes/ColorLabelAttribute.swift index 354fbc93..50229ab0 100644 --- a/VDS/Components/Label/Attributes/ColorLabelAttribute.swift +++ b/VDS/Components/Label/Attributes/ColorLabelAttribute.swift @@ -31,6 +31,8 @@ public struct ColorLabelAttribute: LabelAttributeModel { } public func setAttribute(on attributedString: NSMutableAttributedString) { + guard isValidRange(on: attributedString) else { return } + var colorRange = range if length == 0 && location == 0 { colorRange = .init(location: location, length: attributedString.length) diff --git a/VDS/Components/Label/Attributes/LabelAttributeModel.swift b/VDS/Components/Label/Attributes/LabelAttributeModel.swift index 62e1bbd8..87708ffb 100644 --- a/VDS/Components/Label/Attributes/LabelAttributeModel.swift +++ b/VDS/Components/Label/Attributes/LabelAttributeModel.swift @@ -29,6 +29,10 @@ extension LabelAttributeModel { public static func == (lhs: any LabelAttributeModel, rhs: any LabelAttributeModel) -> Bool { lhs.isEqual(rhs) } + + public func isValidRange(on attributedString: NSMutableAttributedString) -> Bool { + true//range.location + range.length <= attributedString.string.count + } } public extension NSAttributedString { diff --git a/VDS/Components/Label/Attributes/StrikeThroughLabelAttribute.swift b/VDS/Components/Label/Attributes/StrikeThroughLabelAttribute.swift index 93650f2b..ba4c97ac 100644 --- a/VDS/Components/Label/Attributes/StrikeThroughLabelAttribute.swift +++ b/VDS/Components/Label/Attributes/StrikeThroughLabelAttribute.swift @@ -24,6 +24,7 @@ public struct StrikeThroughLabelAttribute: LabelAttributeModel { } public func setAttribute(on attributedString: NSMutableAttributedString) { + guard isValidRange(on: attributedString) else { return } attributedString.addAttribute(.strikethroughStyle, value: NSUnderlineStyle.thick.rawValue, range: range) attributedString.addAttribute(.baselineOffset, value: 0, range: range) } diff --git a/VDS/Components/Label/Attributes/TextStyleLabelAttribute.swift b/VDS/Components/Label/Attributes/TextStyleLabelAttribute.swift index ae3ea1e5..a161d580 100644 --- a/VDS/Components/Label/Attributes/TextStyleLabelAttribute.swift +++ b/VDS/Components/Label/Attributes/TextStyleLabelAttribute.swift @@ -44,6 +44,7 @@ public struct TextStyleLabelAttribute: LabelAttributeModel { } public func setAttribute(on attributedString: NSMutableAttributedString) { + guard isValidRange(on: attributedString) else { return } attributedString.removeAttribute(.font, range: range) attributedString.addAttribute(.font, value: textStyle.font, range: range) if let textColor { diff --git a/VDS/Components/Label/Attributes/UnderlineLabelAttribute.swift b/VDS/Components/Label/Attributes/UnderlineLabelAttribute.swift index 0ca4e2f9..a2ad403e 100644 --- a/VDS/Components/Label/Attributes/UnderlineLabelAttribute.swift +++ b/VDS/Components/Label/Attributes/UnderlineLabelAttribute.swift @@ -52,7 +52,8 @@ public struct UnderlineLabelAttribute: LabelAttributeModel { //-------------------------------------------------- // MARK: - Public Methods //-------------------------------------------------- - public func setAttribute(on attributedString: NSMutableAttributedString) { + public func setAttribute(on attributedString: NSMutableAttributedString) { + guard isValidRange(on: attributedString) else { return } attributedString.addAttribute(.underlineStyle, value: underlineValue.rawValue, range: range) if let color = color { attributedString.addAttribute(.underlineColor, value: color, range: range) From e7a1698602a44946f158c8bafd9b6d8e7def2244 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 29 Feb 2024 14:08:33 -0600 Subject: [PATCH 26/32] removed test Signed-off-by: Matt Bruce --- VDS/Components/Label/Attributes/LabelAttributeModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VDS/Components/Label/Attributes/LabelAttributeModel.swift b/VDS/Components/Label/Attributes/LabelAttributeModel.swift index 87708ffb..ac43472f 100644 --- a/VDS/Components/Label/Attributes/LabelAttributeModel.swift +++ b/VDS/Components/Label/Attributes/LabelAttributeModel.swift @@ -31,7 +31,7 @@ extension LabelAttributeModel { } public func isValidRange(on attributedString: NSMutableAttributedString) -> Bool { - true//range.location + range.length <= attributedString.string.count + range.location + range.length <= attributedString.string.count } } From c75064e84e6f81b35d5bf7275c97fae37b68d64d Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 29 Feb 2024 14:19:51 -0600 Subject: [PATCH 27/32] added more logic to the text/value properties Signed-off-by: Matt Bruce --- VDS/Components/TextFields/EntryFieldBase.swift | 14 +++++++++++++- .../TextFields/InputField/InputField.swift | 7 +++++-- VDS/Components/TextFields/TextArea/TextArea.swift | 9 ++++++--- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/VDS/Components/TextFields/EntryFieldBase.swift b/VDS/Components/TextFields/EntryFieldBase.swift index 121b1510..6964ae0a 100644 --- a/VDS/Components/TextFields/EntryFieldBase.swift +++ b/VDS/Components/TextFields/EntryFieldBase.swift @@ -198,8 +198,20 @@ open class EntryFieldBase: Control, Changeable, FormFieldable { open var maxLength: Int? { didSet { setNeedsUpdate() } } open var inputId: String? { didSet { setNeedsUpdate() } } + + /// The text of this textField. + private var _value: AnyHashable? + open var value: AnyHashable? { + get { _value } + set { + if let newValue, newValue != _value { + _value = newValue + text = newValue as? String + } + setNeedsUpdate() + } + } - open var value: AnyHashable? { didSet { setNeedsUpdate() } } open var defaultValue: AnyHashable? { didSet { setNeedsUpdate() } } diff --git a/VDS/Components/TextFields/InputField/InputField.swift b/VDS/Components/TextFields/InputField/InputField.swift index 83768a6b..ac350bc1 100644 --- a/VDS/Components/TextFields/InputField/InputField.swift +++ b/VDS/Components/TextFields/InputField/InputField.swift @@ -82,8 +82,11 @@ open class InputField: EntryFieldBase, UITextFieldDelegate { open override var text: String? { get { textField.text } set { - textField.text = newValue - value = newValue + if let newValue, newValue != text { + textField.text = newValue + value = newValue + } + setNeedsUpdate() } } diff --git a/VDS/Components/TextFields/TextArea/TextArea.swift b/VDS/Components/TextFields/TextArea/TextArea.swift index d4f11a9e..5fe4e68b 100644 --- a/VDS/Components/TextFields/TextArea/TextArea.swift +++ b/VDS/Components/TextFields/TextArea/TextArea.swift @@ -107,12 +107,15 @@ open class TextArea: EntryFieldBase { } } - /// The text of this textField. + /// The text of this textView open override var text: String? { get { textView.text } set { - textView.text = newValue - value = newValue + if let newValue, newValue != text { + textView.text = newValue + value = newValue + } + setNeedsUpdate() } } From 6cd8b31985091607221d499303247cb45702b710 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 29 Feb 2024 14:38:17 -0600 Subject: [PATCH 28/32] refactored out TextView Signed-off-by: Matt Bruce --- VDS.xcodeproj/project.pbxproj | 4 + .../TextFields/TextArea/TextArea.swift | 169 ++---------------- .../TextFields/TextArea/TextView.swift | 150 ++++++++++++++++ 3 files changed, 169 insertions(+), 154 deletions(-) create mode 100644 VDS/Components/TextFields/TextArea/TextView.swift diff --git a/VDS.xcodeproj/project.pbxproj b/VDS.xcodeproj/project.pbxproj index 125d88a8..10b469ed 100644 --- a/VDS.xcodeproj/project.pbxproj +++ b/VDS.xcodeproj/project.pbxproj @@ -68,6 +68,7 @@ EA5F86C82A1BD99100BC83E4 /* TabModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5F86C72A1BD99100BC83E4 /* TabModel.swift */; }; EA5F86CC2A1D28B500BC83E4 /* ReleaseNotes.txt in Resources */ = {isa = PBXBuildFile; fileRef = EA5F86CB2A1D28B500BC83E4 /* ReleaseNotes.txt */; }; EA5F86D02A1F936100BC83E4 /* TabsContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5F86CF2A1F936100BC83E4 /* TabsContainer.swift */; }; + EA6F330E2B911E9000BACAB9 /* TextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA6F330D2B911E9000BACAB9 /* TextView.swift */; }; EA81410B2A0E8E3C004F60D2 /* ButtonIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA81410A2A0E8E3C004F60D2 /* ButtonIcon.swift */; }; EA8141102A127066004F60D2 /* UIColor+VDSColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA81410F2A127066004F60D2 /* UIColor+VDSColor.swift */; }; EA89200428AECF4B006B9984 /* UITextField+Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA89200328AECF4B006B9984 /* UITextField+Publisher.swift */; }; @@ -236,6 +237,7 @@ EA5F86C72A1BD99100BC83E4 /* TabModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabModel.swift; sourceTree = ""; }; EA5F86CB2A1D28B500BC83E4 /* ReleaseNotes.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = ReleaseNotes.txt; sourceTree = ""; }; EA5F86CF2A1F936100BC83E4 /* TabsContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabsContainer.swift; sourceTree = ""; }; + EA6F330D2B911E9000BACAB9 /* TextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextView.swift; sourceTree = ""; }; EA81410A2A0E8E3C004F60D2 /* ButtonIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonIcon.swift; sourceTree = ""; }; EA81410F2A127066004F60D2 /* UIColor+VDSColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+VDSColor.swift"; sourceTree = ""; }; EA89200328AECF4B006B9984 /* UITextField+Publisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITextField+Publisher.swift"; sourceTree = ""; }; @@ -717,6 +719,7 @@ isa = PBXGroup; children = ( EA985C22296E033A00F2FF2E /* TextArea.swift */, + EA6F330D2B911E9000BACAB9 /* TextView.swift */, 186B2A892B88DA7F001AB71F /* TextAreaChangeLog.txt */, ); path = TextArea; @@ -1059,6 +1062,7 @@ EAF1FE9B29DB1A6000101452 /* Changeable.swift in Sources */, EAF7F0A2289AFB3900B287F5 /* Errorable.swift in Sources */, EA8E40912A7D3F6300934ED3 /* UIView+Accessibility.swift in Sources */, + EA6F330E2B911E9000BACAB9 /* TextView.swift in Sources */, EA985C7D297DAED300F2FF2E /* Primitive.swift in Sources */, EAF1FE9929D4850E00101452 /* Clickable.swift in Sources */, EAD0688E2A55F819002E3A2D /* Loader.swift in Sources */, diff --git a/VDS/Components/TextFields/TextArea/TextArea.swift b/VDS/Components/TextFields/TextArea/TextArea.swift index 5fe4e68b..317748e4 100644 --- a/VDS/Components/TextFields/TextArea/TextArea.swift +++ b/VDS/Components/TextFields/TextArea/TextArea.swift @@ -35,7 +35,6 @@ open class TextArea: EntryFieldBase { //-------------------------------------------------- internal var minWidthConstraint: NSLayoutConstraint? internal var textViewHeightConstraint: NSLayoutConstraint? - internal var allowCharCount: Int = 0 internal var inputFieldStackView: UIStackView = { return UIStackView().with { @@ -204,11 +203,9 @@ open class TextArea: EntryFieldBase { minWidthConstraint?.isActive = true } + let characterError = getCharacterCounterText() if let maxLength, maxLength > 0 { - // allow - 20% of character limit - let overflowLimit = Double(maxLength) * 0.20 - allowCharCount = Int(overflowLimit) + maxLength - characterCounterLabel.text = getCharacterCounterText() + characterCounterLabel.text = characterError } else { characterCounterLabel.text = "" } @@ -245,22 +242,23 @@ open class TextArea: EntryFieldBase { //-------------------------------------------------- // MARK: - Private Methods //-------------------------------------------------- - private func getCharacterCounterText() -> String { + private func getCharacterCounterText() -> String? { let count = textView.text.count let countStr = (count > maxLength ?? 0) ? ("-" + "\(count-(maxLength ?? 0))") : "\(count)" - if ((maxLength ?? 0) > 0) { - if (count > (maxLength ?? 0)) { + if let maxLength, maxLength > 0 { + if count > maxLength { showInternalError = true internalErrorText = "You have exceeded the character limit." return countStr } else { - showInternalError = false internalErrorText = nil - return ("\(countStr)" + "/" + "\(maxLength ?? 0)") + return ("\(countStr)" + "/" + "\(maxLength)") } } else { - return "" + showInternalError = false + internalErrorText = nil + return nil } } @@ -303,7 +301,11 @@ extension TextArea: UITextViewDelegate { } //The exceeding characters will be highlighted to help users correct their entry. - if ((maxLength ?? 0) > 0) { + if let maxLength, maxLength > 0 { + // allow - 20% of character limit + let overflowLimit = Double(maxLength) * 0.20 + let allowCharCount = Int(overflowLimit) + maxLength + if textView.text.count <= allowCharCount { highlightCharacterOverflow() @@ -319,146 +321,5 @@ extension TextArea: UITextViewDelegate { text = textView.text sendActions(for: .valueChanged) } - } - -} - -/// Will move this into a new file, need to talk with Scott/Kyle -open class TextView: UITextView, ViewProtocol { - - //-------------------------------------------------- - // MARK: - Initializers - //-------------------------------------------------- - required public init() { - super.init(frame: .zero, textContainer: nil) - initialSetup() - } - - public override init(frame: CGRect, textContainer: NSTextContainer?) { - super.init(frame: frame, textContainer: textContainer) - initialSetup() - } - - public required init?(coder: NSCoder) { - super.init(coder: coder) - initialSetup() - } - - //-------------------------------------------------- - // MARK: - Combine Properties - //-------------------------------------------------- - /// Set of Subscribers for any Publishers for this Control. - open var subscribers = Set() - - //-------------------------------------------------- - // MARK: - Private Properties - //-------------------------------------------------- - private var initialSetupPerformed = false - - //-------------------------------------------------- - // MARK: - Properties - //-------------------------------------------------- - /// Key of whether or not updateView() is called in setNeedsUpdate() - open var shouldUpdateView: Bool = true - - open var surface: Surface = .light { didSet { setNeedsUpdate() } } - - /// Array of LabelAttributeModel objects used in rendering the text. - open var textAttributes: [any LabelAttributeModel]? { didSet { setNeedsUpdate() } } - - /// TextStyle used on the titleLabel. - open var textStyle: TextStyle { .defaultStyle } - - /// Will determine if a scaled font should be used for the titleLabel font. - open var useScaledFont: Bool = false { didSet { setNeedsUpdate() } } - - open var isEnabled: Bool = true { didSet { setNeedsUpdate() } } - - open var textColorConfiguration: AnyColorable = ViewColorConfiguration().with { - $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forDisabled: true) - $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forDisabled: false) - }.eraseToAnyColorable(){ didSet { setNeedsUpdate() }} - - open override var textColor: UIColor? { - get { textColorConfiguration.getColor(self) } - set { } - } - - override public var text: String! { - get { super.text } - set { - super.text = newValue - updateLabel() - } - } - - override public var textAlignment: NSTextAlignment { - didSet { - if textAlignment != oldValue { - // Text alignment can be part of our paragraph style, so we may need to - // re-style when changed - updateLabel() - } - } - } - - //-------------------------------------------------- - // MARK: - Lifecycle - //-------------------------------------------------- - open func initialSetup() { - if !initialSetupPerformed { - backgroundColor = .clear - translatesAutoresizingMaskIntoConstraints = false - accessibilityCustomActions = [] - setup() - setNeedsUpdate() - } - } - - - open func setup() { - translatesAutoresizingMaskIntoConstraints = false - } - - open func updateView() { - updateLabel() - } - - open func updateAccessibility() {} - - open func reset() { - shouldUpdateView = false - surface = .light - text = nil - accessibilityCustomActions = [] - shouldUpdateView = true - setNeedsUpdate() - } - - //-------------------------------------------------- - // MARK: - Private Methods - //-------------------------------------------------- - private func updateLabel() { - - //clear the arrays holding actions - accessibilityCustomActions = [] - if let text, !text.isEmpty { - //create the primary string - let mutableText = NSMutableAttributedString.mutableText(for: text, - textStyle: textStyle, - useScaledFont: useScaledFont, - textColor: textColor!, - alignment: textAlignment, - lineBreakMode: .byWordWrapping) - //apply any attributes - if let attributes = textAttributes { - mutableText.apply(attributes: attributes) - } - attributedText = mutableText - } else { - attributedText = nil - } - } - - + } } diff --git a/VDS/Components/TextFields/TextArea/TextView.swift b/VDS/Components/TextFields/TextArea/TextView.swift new file mode 100644 index 00000000..cc1567bf --- /dev/null +++ b/VDS/Components/TextFields/TextArea/TextView.swift @@ -0,0 +1,150 @@ +// +// TextView.swift +// VDS +// +// Created by Matt Bruce on 2/29/24. +// + +import Foundation +import UIKit +import Combine +import VDSColorTokens + +/// Will move this into a new file, need to talk with Scott/Kyle +open class TextView: UITextView, ViewProtocol { + + //-------------------------------------------------- + // MARK: - Initializers + //-------------------------------------------------- + required public init() { + super.init(frame: .zero, textContainer: nil) + initialSetup() + } + + public override init(frame: CGRect, textContainer: NSTextContainer?) { + super.init(frame: frame, textContainer: textContainer) + initialSetup() + } + + public required init?(coder: NSCoder) { + super.init(coder: coder) + initialSetup() + } + + //-------------------------------------------------- + // MARK: - Combine Properties + //-------------------------------------------------- + /// Set of Subscribers for any Publishers for this Control. + open var subscribers = Set() + + //-------------------------------------------------- + // MARK: - Private Properties + //-------------------------------------------------- + private var initialSetupPerformed = false + + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + /// Key of whether or not updateView() is called in setNeedsUpdate() + open var shouldUpdateView: Bool = true + + open var surface: Surface = .light { didSet { setNeedsUpdate() } } + + /// Array of LabelAttributeModel objects used in rendering the text. + open var textAttributes: [any LabelAttributeModel]? { didSet { setNeedsUpdate() } } + + /// TextStyle used on the titleLabel. + open var textStyle: TextStyle { .defaultStyle } + + /// Will determine if a scaled font should be used for the titleLabel font. + open var useScaledFont: Bool = false { didSet { setNeedsUpdate() } } + + open var isEnabled: Bool = true { didSet { setNeedsUpdate() } } + + open var textColorConfiguration: AnyColorable = ViewColorConfiguration().with { + $0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forDisabled: true) + $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forDisabled: false) + }.eraseToAnyColorable(){ didSet { setNeedsUpdate() }} + + open override var textColor: UIColor? { + get { textColorConfiguration.getColor(self) } + set { } + } + + override public var text: String! { + get { super.text } + set { + super.text = newValue + updateLabel() + } + } + + override public var textAlignment: NSTextAlignment { + didSet { + if textAlignment != oldValue { + // Text alignment can be part of our paragraph style, so we may need to + // re-style when changed + updateLabel() + } + } + } + + //-------------------------------------------------- + // MARK: - Lifecycle + //-------------------------------------------------- + open func initialSetup() { + if !initialSetupPerformed { + backgroundColor = .clear + translatesAutoresizingMaskIntoConstraints = false + accessibilityCustomActions = [] + setup() + setNeedsUpdate() + } + } + + + open func setup() { + translatesAutoresizingMaskIntoConstraints = false + } + + open func updateView() { + updateLabel() + } + + open func updateAccessibility() {} + + open func reset() { + shouldUpdateView = false + surface = .light + text = nil + accessibilityCustomActions = [] + shouldUpdateView = true + setNeedsUpdate() + } + + //-------------------------------------------------- + // MARK: - Private Methods + //-------------------------------------------------- + private func updateLabel() { + + //clear the arrays holding actions + accessibilityCustomActions = [] + if let text, !text.isEmpty { + //create the primary string + let mutableText = NSMutableAttributedString.mutableText(for: text, + textStyle: textStyle, + useScaledFont: useScaledFont, + textColor: textColor!, + alignment: textAlignment, + lineBreakMode: .byWordWrapping) + //apply any attributes + if let attributes = textAttributes { + mutableText.apply(attributes: attributes) + } + attributedText = mutableText + } else { + attributedText = nil + } + } +} + From cedba7ba8c6090bd2f8f0f28ad81ad60e37ef3b4 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 29 Feb 2024 16:34:55 -0600 Subject: [PATCH 29/32] added namespace for control Signed-off-by: Matt Bruce --- VDS/Components/TextFields/TextArea/TextView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VDS/Components/TextFields/TextArea/TextView.swift b/VDS/Components/TextFields/TextArea/TextView.swift index cc1567bf..ea96ed6e 100644 --- a/VDS/Components/TextFields/TextArea/TextView.swift +++ b/VDS/Components/TextFields/TextArea/TextView.swift @@ -10,7 +10,7 @@ import UIKit import Combine import VDSColorTokens -/// Will move this into a new file, need to talk with Scott/Kyle +@objc(VDSTextView) open class TextView: UITextView, ViewProtocol { //-------------------------------------------------- From 25058dd92de108c46d141e135b866d2dd4716834 Mon Sep 17 00:00:00 2001 From: Keerthy Date: Fri, 1 Mar 2024 12:41:13 +0530 Subject: [PATCH 30/32] self.isVisibleOnScreen for isActive --- VDS/Components/Loader/Loader.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VDS/Components/Loader/Loader.swift b/VDS/Components/Loader/Loader.swift index baf6ecdb..3b4c8ebd 100644 --- a/VDS/Components/Loader/Loader.swift +++ b/VDS/Components/Loader/Loader.swift @@ -80,7 +80,7 @@ open class Loader: View { super.updateView() icon.color = iconColorConfiguration.getColor(self) icon.customSize = size - if isActive { + if isActive, self.isVisibleOnScreen { startAnimating() } else { stopAnimating() From 6e8fe4ea91625d847489cadfe477eb00e1fabcbf Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 1 Mar 2024 09:14:13 -0600 Subject: [PATCH 31/32] use && instead of comma (,) if you don't use if let Signed-off-by: Matt Bruce --- VDS/Components/Loader/Loader.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VDS/Components/Loader/Loader.swift b/VDS/Components/Loader/Loader.swift index 3b4c8ebd..1cfb02c4 100644 --- a/VDS/Components/Loader/Loader.swift +++ b/VDS/Components/Loader/Loader.swift @@ -80,7 +80,7 @@ open class Loader: View { super.updateView() icon.color = iconColorConfiguration.getColor(self) icon.customSize = size - if isActive, self.isVisibleOnScreen { + if isActive && isVisibleOnScreen { startAnimating() } else { stopAnimating() From 1cce53922283de8dec505b47b6d14941028d88d1 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 1 Mar 2024 10:14:05 -0600 Subject: [PATCH 32/32] added layoutsubviews to call setNeedsUpdate Signed-off-by: Matt Bruce --- VDS/BaseClasses/Control.swift | 4 ++++ VDS/BaseClasses/View.swift | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/VDS/BaseClasses/Control.swift b/VDS/BaseClasses/Control.swift index e4ba8cde..cc2246aa 100644 --- a/VDS/BaseClasses/Control.swift +++ b/VDS/BaseClasses/Control.swift @@ -132,4 +132,8 @@ open class Control: UIControl, ViewProtocol, UserInfoable, Clickable { return true } + open override func layoutSubviews() { + super.layoutSubviews() + setNeedsUpdate() + } } diff --git a/VDS/BaseClasses/View.swift b/VDS/BaseClasses/View.swift index 89e5ce4b..a807c25c 100644 --- a/VDS/BaseClasses/View.swift +++ b/VDS/BaseClasses/View.swift @@ -86,4 +86,9 @@ open class View: UIView, ViewProtocol, UserInfoable { isEnabled = true } + open override func layoutSubviews() { + super.layoutSubviews() + setNeedsUpdate() + } + }