From a8dd5641a3d4db195fe846a7e21e4d9558fe5a18 Mon Sep 17 00:00:00 2001 From: Sumanth Nadigadda Date: Thu, 30 Mar 2023 19:53:25 +0530 Subject: [PATCH 01/10] Adding button position for notification --- VDS.xcodeproj/project.pbxproj | 30 ++++++---------- .../Notification/Notification.swift | 36 ++++++++++++++++--- .../NotificationSubTitleModel.swift | 26 -------------- .../Notification/NotificationTitleModel.swift | 25 ------------- 4 files changed, 42 insertions(+), 75 deletions(-) delete mode 100644 VDS/Components/Notification/NotificationSubTitleModel.swift delete mode 100644 VDS/Components/Notification/NotificationTitleModel.swift diff --git a/VDS.xcodeproj/project.pbxproj b/VDS.xcodeproj/project.pbxproj index fbdf5c5c..b2395e84 100644 --- a/VDS.xcodeproj/project.pbxproj +++ b/VDS.xcodeproj/project.pbxproj @@ -7,11 +7,9 @@ objects = { /* Begin PBXBuildFile section */ - 44604AD729CE196600E62B51 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44604AD629CE196600E62B51 /* Line.swift */; }; 445BA07829C07B3D0036A7C5 /* Notification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 445BA07729C07B3D0036A7C5 /* Notification.swift */; }; - 44604AD029CE17EC00E62B51 /* NotificationTitleModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44604ACF29CE17EC00E62B51 /* NotificationTitleModel.swift */; }; - 44604AD229CE180F00E62B51 /* NotificationSubTitleModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44604AD129CE180F00E62B51 /* NotificationSubTitleModel.swift */; }; 44604AD429CE186A00E62B51 /* NotificationButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44604AD329CE186A00E62B51 /* NotificationButtonModel.swift */; }; + 44604AD729CE196600E62B51 /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44604AD629CE196600E62B51 /* Line.swift */; }; 5F21D7BF28DCEB3D003E7CD6 /* Useable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F21D7BE28DCEB3D003E7CD6 /* Useable.swift */; }; 5FC35BE328D51405004EBEAC /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FC35BE228D51405004EBEAC /* Button.swift */; }; EA0FC2C62914222900DF80B4 /* ButtonGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA0FC2C52914222900DF80B4 /* ButtonGroup.swift */; }; @@ -125,11 +123,9 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 44604AD629CE196600E62B51 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = ""; }; 445BA07729C07B3D0036A7C5 /* Notification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notification.swift; sourceTree = ""; }; - 44604ACF29CE17EC00E62B51 /* NotificationTitleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationTitleModel.swift; sourceTree = ""; }; - 44604AD129CE180F00E62B51 /* NotificationSubTitleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSubTitleModel.swift; sourceTree = ""; }; 44604AD329CE186A00E62B51 /* NotificationButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationButtonModel.swift; sourceTree = ""; }; + 44604AD629CE196600E62B51 /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = ""; }; 5F21D7BE28DCEB3D003E7CD6 /* Useable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Useable.swift; sourceTree = ""; }; 5FC35BE228D51405004EBEAC /* Button.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = ""; }; EA0FC2C52914222900DF80B4 /* ButtonGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonGroup.swift; sourceTree = ""; }; @@ -255,6 +251,15 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 445BA07629C07ABA0036A7C5 /* Notification */ = { + isa = PBXGroup; + children = ( + 445BA07729C07B3D0036A7C5 /* Notification.swift */, + 44604AD329CE186A00E62B51 /* NotificationButtonModel.swift */, + ); + path = Notification; + sourceTree = ""; + }; 44604AD529CE195300E62B51 /* Line */ = { isa = PBXGroup; children = ( @@ -263,17 +268,6 @@ path = Line; sourceTree = ""; }; - 445BA07629C07ABA0036A7C5 /* Notification */ = { - isa = PBXGroup; - children = ( - 445BA07729C07B3D0036A7C5 /* Notification.swift */, - 44604ACF29CE17EC00E62B51 /* NotificationTitleModel.swift */, - 44604AD129CE180F00E62B51 /* NotificationSubTitleModel.swift */, - 44604AD329CE186A00E62B51 /* NotificationButtonModel.swift */, - ); - path = Notification; - sourceTree = ""; - }; 5FC35BE128D513EB004EBEAC /* Button */ = { isa = PBXGroup; children = ( @@ -795,7 +789,6 @@ EA33622E2891EA3C0071C351 /* DispatchQueue+Once.swift in Sources */, EA4DB2FD28D3D0CA00103EE3 /* AnyEquatable.swift in Sources */, EAA5EEB728ECC03A003B3210 /* ToolTipLabelAttribute.swift in Sources */, - 44604AD029CE17EC00E62B51 /* NotificationTitleModel.swift in Sources */, EA5E305A29510F8B0082B959 /* EnumSubset.swift in Sources */, EA985BF7296C665E00F2FF2E /* IconName.swift in Sources */, EAF7F0AF289B144C00B287F5 /* UnderlineLabelAttribute.swift in Sources */, @@ -830,7 +823,6 @@ EAF7F09A2899B17200B287F5 /* CATransaction.swift in Sources */, EAF7F0A2289AFB3900B287F5 /* Errorable.swift in Sources */, EA985C7D297DAED300F2FF2E /* Primitive.swift in Sources */, - 44604AD229CE180F00E62B51 /* NotificationSubTitleModel.swift in Sources */, EAB5FEF829393A7200998C17 /* ButtonGroupConstants.swift in Sources */, EA3361AF288B26310071C351 /* FormFieldable.swift in Sources */, 44604AD729CE196600E62B51 /* Line.swift in Sources */, diff --git a/VDS/Components/Notification/Notification.swift b/VDS/Components/Notification/Notification.swift index 7b6c358d..5a7f18bc 100644 --- a/VDS/Components/Notification/Notification.swift +++ b/VDS/Components/Notification/Notification.swift @@ -34,6 +34,10 @@ public class Notification: View { } } + public enum ButtonsPosition: String, CaseIterable { + case bottom, right + } + //-------------------------------------------------- // MARK: - Private Properties //-------------------------------------------------- @@ -51,6 +55,14 @@ public class Notification: View { $0.axis = .vertical } + private var labelButtonView = UIStackView().with { + $0.translatesAutoresizingMaskIntoConstraints = false + $0.alignment = .top + $0.distribution = .fillEqually + $0.axis = .vertical + $0.spacing = VDSLayout.Spacing.space2X.value + } + private var edgeSpacing: CGFloat { return UIDevice.isIPad ? VDSLayout.Spacing.space5X.value : VDSLayout.Spacing.space4X.value } @@ -92,7 +104,6 @@ public class Notification: View { open var subTitleText: String? { didSet{didChange()}} - #warning("will need to think about this one, probably create a model that has 2 props - text, onClick = (Button) -> () so we are not accessing the button directly. The only reason why I leave it open is for things like accessibility, but not for setting properties outside of this class. More or less follow how Tilelet is working, look at that, below is a temp fix until we can discuss with the guys") //Buttons open var primaryButtonModel: ButtonModel? { didSet{didChange()}} open var primaryButton = Button().with { @@ -107,11 +118,22 @@ public class Notification: View { } //-------------------------------------------------- - // MARK: - Modal Properties + // MARK: - Properties //-------------------------------------------------- open var type: NotificationStyle = .info { didSet{didChange()}} + var _buttonPosition: ButtonsPosition = .bottom + open var buttonPosition: ButtonsPosition { + set { + if !UIDevice.isIPad, newValue == .right { return } + _buttonPosition = newValue + buttonsView.buttonPosition = _buttonPosition == .right ? .center : .left + didChange() + } + get { _buttonPosition } + } + //-------------------------------------------------- // MARK: - Configuration //-------------------------------------------------- @@ -159,8 +181,10 @@ public class Notification: View { ]) mainStackView.addArrangedSubview(typeIcon) - mainStackView.addArrangedSubview(labelsView) + mainStackView.addArrangedSubview(labelButtonView) mainStackView.addArrangedSubview(closeButton) + + labelButtonView.addArrangedSubview(labelsView) closeButton.publisher(for: UITapGestureRecognizer()).sink { [weak self] _ in self?.didClickOnCloseButton() @@ -183,6 +207,7 @@ public class Notification: View { type = .info typeIcon.name = .infoBold closeButton.name = .close + buttonPosition = .bottom } //-------------------------------------------------- @@ -251,9 +276,10 @@ public class Notification: View { buttonsView.removeFromSuperview() } else { labelsView.setCustomSpacing(VDSLayout.Spacing.space3X.value, after: subTitleLabel) - ///This below doesn't work + buttonsView.buttons = buttons - labelsView.addArrangedSubview(buttonsView) + labelButtonView.axis = buttonPosition == .bottom ? .vertical : .horizontal + labelButtonView.addArrangedSubview(buttonsView) buttonsView .pinLeading() diff --git a/VDS/Components/Notification/NotificationSubTitleModel.swift b/VDS/Components/Notification/NotificationSubTitleModel.swift deleted file mode 100644 index 19d4c810..00000000 --- a/VDS/Components/Notification/NotificationSubTitleModel.swift +++ /dev/null @@ -1,26 +0,0 @@ -// -// NotificationSubTitleModel.swift -// VDS -// -// Created by Nadigadda, Sumanth on 24/03/23. -// - -import Foundation - -extension Notification { - public struct SubTitleModel { - public var text: String - public var textAttributes: [any LabelAttributeModel]? - public var textStyle: TextStyle = .bodySmall - public var numberOfLines: Int - - public init(text: String, - textColor: Use = .primary, - textAttributes: [any LabelAttributeModel]? = nil, - numberOfLines: Int = 0) { - self.text = text - self.textAttributes = textAttributes - self.numberOfLines = numberOfLines - } - } -} diff --git a/VDS/Components/Notification/NotificationTitleModel.swift b/VDS/Components/Notification/NotificationTitleModel.swift deleted file mode 100644 index 31048b4d..00000000 --- a/VDS/Components/Notification/NotificationTitleModel.swift +++ /dev/null @@ -1,25 +0,0 @@ -// -// NotificationTitleModel.swift -// VDS -// -// Created by Nadigadda, Sumanth on 24/03/23. -// - -import Foundation - -extension Notification { - public struct TitleModel { - public var text: String - public var textAttributes: [any LabelAttributeModel]? - public var textStyle: TextStyle = .boldBodySmall - public var numberOfLines: Int - - public init(text: String, - textAttributes: [any LabelAttributeModel]? = nil, - numberOfLines: Int = 0) { - self.text = text - self.textAttributes = textAttributes - self.numberOfLines = numberOfLines - } - } -} From 7d14ab1f5c402aa86df5587ebf00fbea14d791cd Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 30 Mar 2023 10:40:10 -0500 Subject: [PATCH 02/10] refactored properties Signed-off-by: Matt Bruce --- VDS/Components/Notification/Notification.swift | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/VDS/Components/Notification/Notification.swift b/VDS/Components/Notification/Notification.swift index aea2be6d..f0a4d58b 100644 --- a/VDS/Components/Notification/Notification.swift +++ b/VDS/Components/Notification/Notification.swift @@ -101,9 +101,9 @@ public class Notification: View { } //Text - open var titleText: String = "" { didSet{didChange()}} + open var title: String = "" { didSet{didChange()}} - open var subTitleText: String? { didSet{didChange()}} + open var subTitle: String? { didSet{didChange()}} //Buttons open var primaryButtonModel: ButtonModel? { didSet{didChange()}} @@ -195,6 +195,8 @@ public class Notification: View { mainStackView.heightAnchor.constraint(greaterThanOrEqualToConstant: minContentHeight) ]) + labelButtonView.addArrangedSubview(labelsView) + mainStackView.addArrangedSubview(typeIcon) mainStackView.addArrangedSubview(labelButtonView) mainStackView.addArrangedSubview(closeButton) @@ -240,15 +242,15 @@ public class Notification: View { titleLabel.surface = surface subTitleLabel.surface = surface - if !titleText.isEmpty { - titleLabel.text = titleText + if !title.isEmpty { + titleLabel.text = title labelsView.addArrangedSubview(titleLabel) } else { titleLabel.removeFromSuperview() } - if let subTitleText { - subTitleLabel.text = subTitleText + if let subTitle { + subTitleLabel.text = subTitle labelsView.addArrangedSubview(subTitleLabel) } else { subTitleLabel.removeFromSuperview() From fee33a17da3a6984b1c95785c9abbe6cfbeaa044 Mon Sep 17 00:00:00 2001 From: Sumanth Nadigadda Date: Thu, 30 Mar 2023 23:13:32 +0530 Subject: [PATCH 03/10] Renaming parameters in Notification component --- VDS/Components/Notification/Notification.swift | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/VDS/Components/Notification/Notification.swift b/VDS/Components/Notification/Notification.swift index f0a4d58b..2a701d34 100644 --- a/VDS/Components/Notification/Notification.swift +++ b/VDS/Components/Notification/Notification.swift @@ -35,7 +35,7 @@ public class Notification: View { } } - public enum ButtonsPosition: String, CaseIterable { + public enum ButtonsLayout: String, CaseIterable { case bottom, right } @@ -138,15 +138,15 @@ public class Notification: View { open var type: NotificationStyle = .info { didSet{didChange()}} - var _buttonPosition: ButtonsPosition = .bottom - open var buttonPosition: ButtonsPosition { + var _layout: ButtonsLayout = .bottom + open var layout: ButtonsLayout { set { if !UIDevice.isIPad, newValue == .right { return } - _buttonPosition = newValue - buttonsView.buttonPosition = _buttonPosition == .right ? .center : .left + _layout = newValue + buttonsView.buttonPosition = _layout == .right ? .center : .left didChange() } - get { _buttonPosition } + get { _layout } } //-------------------------------------------------- @@ -218,7 +218,7 @@ public class Notification: View { type = .info typeIcon.name = .infoBold closeButton.name = .close - buttonPosition = .bottom + layout = .bottom } //-------------------------------------------------- @@ -281,7 +281,7 @@ public class Notification: View { labelsView.setCustomSpacing(VDSLayout.Spacing.space3X.value, after: subTitleLabel) buttonsView.buttons = buttons - labelButtonView.axis = buttonPosition == .bottom ? .vertical : .horizontal + labelButtonView.axis = layout == .bottom ? .vertical : .horizontal labelButtonView.addArrangedSubview(buttonsView) buttonsView From c8c63d5cd4d8c1b2a51bb41fd8712a03a2ed6ebb Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 30 Mar 2023 17:24:12 -0500 Subject: [PATCH 04/10] updated names Signed-off-by: Matt Bruce --- VDS/Components/Notification/Notification.swift | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/VDS/Components/Notification/Notification.swift b/VDS/Components/Notification/Notification.swift index 2a701d34..47785d6b 100644 --- a/VDS/Components/Notification/Notification.swift +++ b/VDS/Components/Notification/Notification.swift @@ -35,8 +35,8 @@ public class Notification: View { } } - public enum ButtonsLayout: String, CaseIterable { - case bottom, right + public enum Layout: String, CaseIterable { + case vertical, horizontal } //-------------------------------------------------- @@ -138,12 +138,12 @@ public class Notification: View { open var type: NotificationStyle = .info { didSet{didChange()}} - var _layout: ButtonsLayout = .bottom - open var layout: ButtonsLayout { + var _layout: Layout = .vertical + open var layout: Layout { set { - if !UIDevice.isIPad, newValue == .right { return } + if !UIDevice.isIPad, newValue == .horizontal { return } _layout = newValue - buttonsView.buttonPosition = _layout == .right ? .center : .left + buttonsView.buttonPosition = _layout == .horizontal ? .center : .left didChange() } get { _layout } @@ -218,7 +218,7 @@ public class Notification: View { type = .info typeIcon.name = .infoBold closeButton.name = .close - layout = .bottom + layout = .vertical } //-------------------------------------------------- @@ -281,7 +281,7 @@ public class Notification: View { labelsView.setCustomSpacing(VDSLayout.Spacing.space3X.value, after: subTitleLabel) buttonsView.buttons = buttons - labelButtonView.axis = layout == .bottom ? .vertical : .horizontal + labelButtonView.axis = layout == .vertical ? .vertical : .horizontal labelButtonView.addArrangedSubview(buttonsView) buttonsView From fc02175c5d9ee6f7ed3d33c6cde42c57f3814828 Mon Sep 17 00:00:00 2001 From: Sumanth Nadigadda Date: Fri, 31 Mar 2023 12:27:49 +0530 Subject: [PATCH 05/10] Adding logic to hide close button --- VDS/Components/Notification/Notification.swift | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/VDS/Components/Notification/Notification.swift b/VDS/Components/Notification/Notification.swift index 47785d6b..9cdba0fb 100644 --- a/VDS/Components/Notification/Notification.swift +++ b/VDS/Components/Notification/Notification.swift @@ -18,7 +18,7 @@ public class Notification: View { // MARK: - Enums //-------------------------------------------------- - public enum NotificationStyle: String, CaseIterable { + public enum Style: String, CaseIterable { case info, success, warning, error func styleIconName() -> Icon.Name { @@ -136,7 +136,9 @@ public class Notification: View { // MARK: - Properties //-------------------------------------------------- - open var type: NotificationStyle = .info { didSet{didChange()}} + open var hideCloseButton: Bool = false { didSet{didChange()}} + + open var type: Style = .info { didSet{didChange()}} var _layout: Layout = .vertical open var layout: Layout { @@ -153,7 +155,7 @@ public class Notification: View { // MARK: - Configuration //-------------------------------------------------- private var backgroundColorConfiguration: AnyColorable = { - let config = KeyedColorConfiguration(keyPath: \.type) + let config = KeyedColorConfiguration(keyPath: \.type) config.setSurfaceColors(VDSColor.feedbackInformationBackgroundOnlight, VDSColor.feedbackInformationBackgroundOndark, forKey: .info) config.setSurfaceColors(VDSColor.feedbackWarningBackgroundOnlight, VDSColor.feedbackWarningBackgroundOndark, forKey: .warning) config.setSurfaceColors(VDSColor.feedbackSuccessBackgroundOnlight, VDSColor.feedbackSuccessBackgroundOndark, forKey: .success) @@ -219,6 +221,7 @@ public class Notification: View { typeIcon.name = .infoBold closeButton.name = .close layout = .vertical + hideCloseButton = false } //-------------------------------------------------- @@ -236,6 +239,7 @@ public class Notification: View { typeIcon.name = type.styleIconName() typeIcon.color = iconColor closeButton.color = iconColor + closeButton.isHidden = hideCloseButton } private func updateLabels() { From fa273bad1c0fcd912989d53d8870b05f9962148a Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 3 Apr 2023 10:14:44 -0500 Subject: [PATCH 06/10] added changeable Signed-off-by: Matt Bruce --- VDS.xcodeproj/project.pbxproj | 4 ++++ VDS/Protocols/Changeable.swift | 31 +++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 VDS/Protocols/Changeable.swift diff --git a/VDS.xcodeproj/project.pbxproj b/VDS.xcodeproj/project.pbxproj index 3b468221..aece57ed 100644 --- a/VDS.xcodeproj/project.pbxproj +++ b/VDS.xcodeproj/project.pbxproj @@ -94,6 +94,7 @@ EAC9258F2911C9DE00091998 /* EntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAC9258B2911C9DE00091998 /* EntryField.swift */; }; EAD8D2C128BFDE8B006EB6A6 /* UIGestureRecognizer+Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAD8D2C028BFDE8B006EB6A6 /* UIGestureRecognizer+Publisher.swift */; }; EAF1FE9929D4850E00101452 /* Clickable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF1FE9829D4850E00101452 /* Clickable.swift */; }; + EAF1FE9B29DB1A6000101452 /* Changeable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF1FE9A29DB1A6000101452 /* Changeable.swift */; }; EAF7F0952899861000B287F5 /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F0932899861000B287F5 /* Checkbox.swift */; }; EAF7F09A2899B17200B287F5 /* CATransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F0992899B17200B287F5 /* CATransaction.swift */; }; EAF7F09E289AAEC000B287F5 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF7F09D289AAEC000B287F5 /* Constants.swift */; }; @@ -212,6 +213,7 @@ EAC9258B2911C9DE00091998 /* EntryField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EntryField.swift; sourceTree = ""; }; EAD8D2C028BFDE8B006EB6A6 /* UIGestureRecognizer+Publisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIGestureRecognizer+Publisher.swift"; sourceTree = ""; }; EAF1FE9829D4850E00101452 /* Clickable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Clickable.swift; sourceTree = ""; }; + EAF1FE9A29DB1A6000101452 /* Changeable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Changeable.swift; sourceTree = ""; }; EAF7F0932899861000B287F5 /* Checkbox.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Checkbox.swift; sourceTree = ""; }; EAF7F0992899B17200B287F5 /* CATransaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CATransaction.swift; sourceTree = ""; }; EAF7F09D289AAEC000B287F5 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; }; @@ -418,6 +420,7 @@ isa = PBXGroup; children = ( EA4DB2FC28D3D0CA00103EE3 /* AnyEquatable.swift */, + EAF1FE9A29DB1A6000101452 /* Changeable.swift */, EAF1FE9829D4850E00101452 /* Clickable.swift */, EAA5EEDF28F49DB3003B3210 /* Colorable.swift */, EA3361A9288B25E40071C351 /* Disabling.swift */, @@ -825,6 +828,7 @@ EA3361BD288B2C760071C351 /* TypeAlias.swift in Sources */, EAB1D2CF28ABEF2B00DAE764 /* Typography.swift in Sources */, EAF7F09A2899B17200B287F5 /* CATransaction.swift in Sources */, + EAF1FE9B29DB1A6000101452 /* Changeable.swift in Sources */, EAF7F0A2289AFB3900B287F5 /* Errorable.swift in Sources */, EA985C7D297DAED300F2FF2E /* Primitive.swift in Sources */, EAF1FE9929D4850E00101452 /* Clickable.swift in Sources */, diff --git a/VDS/Protocols/Changeable.swift b/VDS/Protocols/Changeable.swift new file mode 100644 index 00000000..850c9cf2 --- /dev/null +++ b/VDS/Protocols/Changeable.swift @@ -0,0 +1,31 @@ +// +// Changeable.swift +// VDS +// +// Created by Matt Bruce on 4/3/23. +// + +import Foundation +import UIKit +import Combine + +public protocol Changeable: Handlerable where Self: UIControl { + var onChangeSubscriber: AnyCancellable? { get set } +} + +extension Changeable { + public var onChange: ((Self) -> ())? { + get { return nil } + set { + if let newValue { + onChangeSubscriber = publisher(for: .valueChanged) + .sink { c in + newValue(c) + } + } else { + onChangeSubscriber?.cancel() + onChangeSubscriber = nil + } + } + } +} From 308ef596a43516e5ebf512f1a409433759f6cb50 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 3 Apr 2023 10:14:52 -0500 Subject: [PATCH 07/10] added onChange Signed-off-by: Matt Bruce --- VDS/Classes/SelectorGroupHandlerBase.swift | 11 ++++++++++- VDS/Components/Checkbox/Checkbox.swift | 12 ++++++++++-- VDS/Components/RadioBox/RadioBox.swift | 12 ++++++++++-- VDS/Components/RadioButton/RadioButton.swift | 11 ++++++++++- .../TextFields/EntryField/EntryField.swift | 10 +++++++++- VDS/Components/Toggle/Toggle.swift | 10 +++++++++- VDS/Protocols/Clickable.swift | 7 ------- VDS/Protocols/Handlerable.swift | 9 +++++++++ 8 files changed, 67 insertions(+), 15 deletions(-) diff --git a/VDS/Classes/SelectorGroupHandlerBase.swift b/VDS/Classes/SelectorGroupHandlerBase.swift index 3b67019d..5fee8d6c 100644 --- a/VDS/Classes/SelectorGroupHandlerBase.swift +++ b/VDS/Classes/SelectorGroupHandlerBase.swift @@ -7,14 +7,23 @@ import Foundation import UIKit +import Combine -public class SelectorGroupHandlerBase: Control { +public class SelectorGroupHandlerBase: Control, Changeable { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- public var selectorViews: [HandlerType] = [] + public var onChangeSubscriber: AnyCancellable? { + willSet { + if let onChangeSubscriber { + onChangeSubscriber.cancel() + } + } + } + //-------------------------------------------------- // MARK: - Overrides //-------------------------------------------------- diff --git a/VDS/Components/Checkbox/Checkbox.swift b/VDS/Components/Checkbox/Checkbox.swift index cfff406e..f0d690cd 100644 --- a/VDS/Components/Checkbox/Checkbox.swift +++ b/VDS/Components/Checkbox/Checkbox.swift @@ -7,13 +7,13 @@ import Foundation import UIKit +import Combine import VDSColorTokens import VDSFormControlsTokens -import Combine /// Checkboxes are a multi-select component through which a customer indicates a choice. If a binary choice, the component is a checkbox. If the choice has multiple options, the component is a ``CheckboxGroup``. @objc(VDSCheckboxBase) -open class Checkbox: Control, Errorable { +open class Checkbox: Control, Errorable, Changeable { //-------------------------------------------------- // MARK: - Initializers @@ -63,6 +63,14 @@ open class Checkbox: Control, Errorable { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + public var onChangeSubscriber: AnyCancellable? { + willSet { + if let onChangeSubscriber { + onChangeSubscriber.cancel() + } + } + } + open var label = Label().with { $0.setContentCompressionResistancePriority(.required, for: .vertical) $0.textPosition = .left diff --git a/VDS/Components/RadioBox/RadioBox.swift b/VDS/Components/RadioBox/RadioBox.swift index b71c0342..f5f8d9b9 100644 --- a/VDS/Components/RadioBox/RadioBox.swift +++ b/VDS/Components/RadioBox/RadioBox.swift @@ -7,12 +7,12 @@ import Foundation import UIKit +import Combine import VDSColorTokens import VDSFormControlsTokens -import Combine @objc(VDSRadioBox) -open class RadioBox: Control { +open class RadioBox: Control, Changeable { //-------------------------------------------------- // MARK: - Initializers @@ -56,6 +56,14 @@ open class RadioBox: Control { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + public var onChangeSubscriber: AnyCancellable? { + willSet { + if let onChangeSubscriber { + onChangeSubscriber.cancel() + } + } + } + open var textLabel = Label().with { $0.setContentCompressionResistancePriority(.required, for: .vertical) $0.textPosition = .left diff --git a/VDS/Components/RadioButton/RadioButton.swift b/VDS/Components/RadioButton/RadioButton.swift index 76d29b46..b3b35f3e 100644 --- a/VDS/Components/RadioButton/RadioButton.swift +++ b/VDS/Components/RadioButton/RadioButton.swift @@ -7,11 +7,12 @@ import Foundation import UIKit +import Combine import VDSColorTokens import VDSFormControlsTokens @objc(VDSRadioButton) -open class RadioButton: Control, Errorable { +open class RadioButton: Control, Errorable, Changeable { //-------------------------------------------------- // MARK: - Initializers @@ -61,6 +62,14 @@ open class RadioButton: Control, Errorable { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + public var onChangeSubscriber: AnyCancellable? { + willSet { + if let onChangeSubscriber { + onChangeSubscriber.cancel() + } + } + } + open var label = Label().with { $0.setContentCompressionResistancePriority(.required, for: .vertical) $0.textPosition = .left diff --git a/VDS/Components/TextFields/EntryField/EntryField.swift b/VDS/Components/TextFields/EntryField/EntryField.swift index a773ac43..20f221cb 100644 --- a/VDS/Components/TextFields/EntryField/EntryField.swift +++ b/VDS/Components/TextFields/EntryField/EntryField.swift @@ -12,7 +12,7 @@ import VDSFormControlsTokens import Combine @objc(VDSEntryField) -open class EntryField: Control { +open class EntryField: Control, Changeable { //-------------------------------------------------- // MARK: - Enums //-------------------------------------------------- @@ -98,6 +98,14 @@ open class EntryField: Control { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + public var onChangeSubscriber: AnyCancellable? { + willSet { + if let onChangeSubscriber { + onChangeSubscriber.cancel() + } + } + } + open var titleLabel = Label().with { $0.setContentCompressionResistancePriority(.required, for: .vertical) $0.attributes = [] diff --git a/VDS/Components/Toggle/Toggle.swift b/VDS/Components/Toggle/Toggle.swift index 05349779..0f6bc797 100644 --- a/VDS/Components/Toggle/Toggle.swift +++ b/VDS/Components/Toggle/Toggle.swift @@ -18,7 +18,7 @@ import Combine Knob: The circular indicator that slides on the container. */ @objc(VDSToggle) -open class Toggle: Control { +open class Toggle: Control, Changeable { //-------------------------------------------------- // MARK: - Enums //-------------------------------------------------- @@ -107,6 +107,14 @@ open class Toggle: Control { //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- + public var onChangeSubscriber: AnyCancellable? { + willSet { + if let onChangeSubscriber { + onChangeSubscriber.cancel() + } + } + } + open var label = Label().with { $0.setContentCompressionResistancePriority(.required, for: .vertical) } diff --git a/VDS/Protocols/Clickable.swift b/VDS/Protocols/Clickable.swift index 4ffecf2b..a202850a 100644 --- a/VDS/Protocols/Clickable.swift +++ b/VDS/Protocols/Clickable.swift @@ -15,13 +15,6 @@ public protocol Clickable: Handlerable where Self: UIControl { } extension Clickable { - public func addEvent(event: UIControl.Event, block: @escaping (Self)->()) { - publisher(for: event) - .sink(receiveValue: { c in - block(c) - }).store(in: &subscribers) - } - public var onClick: ((Self) -> ())? { get { return nil } set { diff --git a/VDS/Protocols/Handlerable.swift b/VDS/Protocols/Handlerable.swift index f9ad8770..41ef01b5 100644 --- a/VDS/Protocols/Handlerable.swift +++ b/VDS/Protocols/Handlerable.swift @@ -34,3 +34,12 @@ extension Handlerable where Self: UIView { subject.send() } } + +extension Handlerable where Self: UIControl { + public func addEvent(event: UIControl.Event, block: @escaping (Self)->()) { + publisher(for: event) + .sink(receiveValue: { c in + block(c) + }).store(in: &subscribers) + } +} From 027fabae12dc197dbfe73bbe8ad595c2473b7a2b Mon Sep 17 00:00:00 2001 From: Sumanth Nadigadda Date: Tue, 4 Apr 2023 16:25:48 +0530 Subject: [PATCH 08/10] Notification, default setting changes & fullBleed changes --- .../Notification/Notification.swift | 54 +++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/VDS/Components/Notification/Notification.swift b/VDS/Components/Notification/Notification.swift index 9cdba0fb..427b0ed8 100644 --- a/VDS/Components/Notification/Notification.swift +++ b/VDS/Components/Notification/Notification.swift @@ -76,24 +76,40 @@ public class Notification: View { return UIDevice.isIPad ? VDSLayout.Spacing.space5X.value : VDSLayout.Spacing.space4X.value } + private var minViewWidth: CGFloat { + return fullBleed ? 320 : 288 + } + + ///Max view width is for Tablet + private var maxViewWidth: CGFloat { + return fullBleed ? 1272 : 1232 + } + + private var maxWidthConstraint: NSLayoutConstraint? + + open var leadingConstraint: NSLayoutConstraint? + + open var trailingConstraint: NSLayoutConstraint? //-------------------------------------------------- // MARK: - View Properties //-------------------------------------------------- open var typeIcon = Icon().with { $0.name = .infoBold + $0.size = UIDevice.isIPad ? .medium : .small } open var closeButton = Icon().with { $0.name = .close + $0.size = UIDevice.isIPad ? .medium : .small } open var titleLabel = Label().with { - $0.textStyle = .boldBodyLarge + $0.textStyle = UIDevice.isIPad ? .boldBodyLarge : .boldBodySmall } open var subTitleLabel = Label().with { - $0.textStyle = .bodyLarge + $0.textStyle = UIDevice.isIPad ? .bodyLarge : .bodySmall } open var buttonsView = ButtonGroup().with { @@ -140,6 +156,8 @@ public class Notification: View { open var type: Style = .info { didSet{didChange()}} + open var fullBleed: Bool = false { didSet {didChange()}} + var _layout: Layout = .vertical open var layout: Layout { set { @@ -194,8 +212,10 @@ public class Notification: View { NSLayoutConstraint.activate([ heightAnchor.constraint(greaterThanOrEqualToConstant: minViewHeight), - mainStackView.heightAnchor.constraint(greaterThanOrEqualToConstant: minContentHeight) + mainStackView.heightAnchor.constraint(greaterThanOrEqualToConstant: minContentHeight), + widthAnchor.constraint(greaterThanOrEqualToConstant: minViewWidth) ]) + maxWidthConstraint = widthAnchor.constraint(lessThanOrEqualToConstant: maxViewWidth) labelButtonView.addArrangedSubview(labelsView) @@ -212,14 +232,24 @@ public class Notification: View { super.reset() titleLabel.reset() + titleLabel.textStyle = .boldBodyLarge + subTitleLabel.reset() + subTitleLabel.textStyle = .bodyLarge + buttonsView.reset() + buttonsView.buttonPosition = .left + primaryButton.reset() secondaryButton.reset() type = .info + typeIcon.size = .medium typeIcon.name = .infoBold + + closeButton.size = .medium closeButton.name = .close + layout = .vertical hideCloseButton = false } @@ -232,6 +262,7 @@ public class Notification: View { updateIcons() updateLabels() updateButtons() + setConstraints() } private func updateIcons() { @@ -293,5 +324,22 @@ public class Notification: View { .pinTrailing() } } + + private func setConstraints() { + + maxWidthConstraint?.constant = maxViewWidth + maxWidthConstraint?.isActive = UIDevice.isIPad + + if leadingConstraint == nil, let superview { + leadingConstraint = NSLayoutConstraint(item: self, attribute: .leading, relatedBy: .equal, toItem: superview, attribute: .leading, multiplier: 1, constant: 0) + } + + if trailingConstraint == nil, let superview { + trailingConstraint = NSLayoutConstraint(item: superview, attribute: .trailing, relatedBy: .equal, toItem: self, attribute: .trailing, multiplier: 1, constant: 0) + } + + leadingConstraint?.isActive = fullBleed + trailingConstraint?.isActive = fullBleed + } } From cf4f1451373904c95a0e32f2a333c7956a8d4f05 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 4 Apr 2023 08:56:37 -0500 Subject: [PATCH 09/10] refactored debounce for label/button (has label) Signed-off-by: Matt Bruce --- .../Buttons/Button/ButtonBase.swift | 2 +- VDS/Components/Label/Label.swift | 2 +- VDS/Protocols/Handlerable.swift | 19 +++++++++++++------ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/VDS/Components/Buttons/Button/ButtonBase.swift b/VDS/Components/Buttons/Button/ButtonBase.swift index 41633216..cafd5cd8 100644 --- a/VDS/Components/Buttons/Button/ButtonBase.swift +++ b/VDS/Components/Buttons/Button/ButtonBase.swift @@ -121,7 +121,7 @@ open class ButtonBase: UIButton, Buttonable, Handlerable, ViewProtocol, Resettab translatesAutoresizingMaskIntoConstraints = false accessibilityCustomActions = [] setup() - setupDidChangeEvent() + setupDidChangeEvent(true) updateView() } } diff --git a/VDS/Components/Label/Label.swift b/VDS/Components/Label/Label.swift index 5f347634..db15ce0d 100644 --- a/VDS/Components/Label/Label.swift +++ b/VDS/Components/Label/Label.swift @@ -94,7 +94,7 @@ public class Label: UILabel, Handlerable, ViewProtocol, Resettable, UserInfoable accessibilityCustomActions = [] accessibilityTraits = .staticText setup() - setupDidChangeEvent() + setupDidChangeEvent(true) updateView() } } diff --git a/VDS/Protocols/Handlerable.swift b/VDS/Protocols/Handlerable.swift index 41ef01b5..cefb150f 100644 --- a/VDS/Protocols/Handlerable.swift +++ b/VDS/Protocols/Handlerable.swift @@ -17,15 +17,22 @@ public protocol Handlerable: AnyObject, Initable, Disabling, Surfaceable { extension Handlerable { - public func setupDidChangeEvent() { - handlerPublisher().sink { [weak self] _ in - self?.updateView() + public func setupDidChangeEvent(_ debounce: Bool = false) { + handlerPublisher(debounce) + .sink { [weak self] _ in + self?.updateView() }.store(in: &subscribers) } - public func handlerPublisher() -> AnyPublisher { - subject - .eraseToAnyPublisher() + public func handlerPublisher(_ debounce: Bool = false) -> AnyPublisher { + if debounce { + return subject + .debounce(for: .seconds(Constants.StateDebounce), scheduler: RunLoop.main) + .eraseToAnyPublisher() + } else { + return subject + .eraseToAnyPublisher() + } } } From 51c8a8059f6ecedc6ba147f122e78c7c4e6b8d2e Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 4 Apr 2023 10:10:48 -0500 Subject: [PATCH 10/10] updated defaults in reset Signed-off-by: Matt Bruce --- VDS/Components/Notification/Notification.swift | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/VDS/Components/Notification/Notification.swift b/VDS/Components/Notification/Notification.swift index 427b0ed8..fdfe5b74 100644 --- a/VDS/Components/Notification/Notification.swift +++ b/VDS/Components/Notification/Notification.swift @@ -232,26 +232,29 @@ public class Notification: View { super.reset() titleLabel.reset() - titleLabel.textStyle = .boldBodyLarge + titleLabel.text = "" + titleLabel.textStyle = UIDevice.isIPad ? .boldBodyLarge : .boldBodySmall subTitleLabel.reset() - subTitleLabel.textStyle = .bodyLarge + subTitleLabel.textStyle = UIDevice.isIPad ? .bodyLarge : .bodySmall buttonsView.reset() buttonsView.buttonPosition = .left - primaryButton.reset() - secondaryButton.reset() + primaryButtonModel = nil + secondaryButtonModel = nil type = .info - typeIcon.size = .medium + typeIcon.size = UIDevice.isIPad ? .medium : .small typeIcon.name = .infoBold - closeButton.size = .medium + onCloseClick = nil + closeButton.size = UIDevice.isIPad ? .medium : .small closeButton.name = .close layout = .vertical hideCloseButton = false + fullBleed = false } //--------------------------------------------------