// // Notification.swift // VDS // // Created by Nadigadda, Sumanth on 14/03/23. // import Foundation import UIKit import VDSColorTokens @objc(VDSNotification) /// A VDS Component that will render a view with information public class Notification: View { //-------------------------------------------------- // MARK: - Enums //-------------------------------------------------- public enum NotificationStyle: String, CaseIterable { case info, success, warning, error func styleIconName() -> Icon.Name { switch self { case .info: return .infoBold case .success: return .checkmarkAltBold case .warning: return .warningBold case .error: return .errorBold } } } //-------------------------------------------------- // MARK: - Private Properties //-------------------------------------------------- private var mainStackView = UIStackView().with { $0.translatesAutoresizingMaskIntoConstraints = false $0.alignment = .top $0.axis = .horizontal $0.spacing = VDSLayout.Spacing.space2X.value } private var labelsView = UIStackView().with { $0.translatesAutoresizingMaskIntoConstraints = false $0.alignment = .top $0.axis = .vertical } private var edgeSpacing: CGFloat { return UIDevice.isIPad ? VDSLayout.Spacing.space5X.value : VDSLayout.Spacing.space4X.value } //-------------------------------------------------- // MARK: - View Properties //-------------------------------------------------- open var typeIcon = Icon().with { $0.name = .infoBold } open var closeButton = Icon().with { $0.name = .close } open var titleLabel = Label().with { $0.textStyle = .boldBodySmall } open var subTitleLabel = Label().with { $0.textStyle = .bodySmall } open var buttonsView = ButtonGroup() //-------------------------------------------------- // MARK: - Modal Properties //-------------------------------------------------- open var type: NotificationStyle = .info { didSet{didChange()}} //-------------------------------------------------- // MARK: - Configuration //-------------------------------------------------- private var backgroundColorConfiguration: StateColorConfiguration = { let config = StateColorConfiguration() config.setSurfaceColors(VDSColor.feedbackInformationBackgroundOnlight, VDSColor.feedbackInformationBackgroundOndark, forState: .info) config.setSurfaceColors(VDSColor.feedbackWarningBackgroundOnlight, VDSColor.feedbackWarningBackgroundOndark, forState: .warning) config.setSurfaceColors(VDSColor.feedbackSuccessBackgroundOnlight, VDSColor.feedbackSuccessBackgroundOndark, forState: .success) config.setSurfaceColors(VDSColor.feedbackErrorBackgroundOnlight, VDSColor.feedbackErrorBackgroundOndark, forState: .error) return config }() private var textColorConfig = ViewColorConfiguration() public func updateTextColorConfig() { textColorConfig.reset() switch type { case .info, .success, .warning, .error: textColorConfig.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forDisabled: false) textColorConfig.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forDisabled: true) } } //-------------------------------------------------- // MARK: - Initializers //-------------------------------------------------- required public init() { super.init(frame: .zero) } public override init(frame: CGRect) { super.init(frame: .zero) } public required init?(coder: NSCoder) { super.init(coder: coder) } //-------------------------------------------------- // MARK: - Lifecycle //-------------------------------------------------- open override func setup() { super.setup() addSubview(mainStackView) mainStackView.pinToSuperView(.init(top: edgeSpacing, left: edgeSpacing, bottom: edgeSpacing, right: edgeSpacing)) mainStackView.addArrangedSubview(typeIcon) mainStackView.addArrangedSubview(labelsView) mainStackView.addArrangedSubview(closeButton) labelsView.addArrangedSubview(titleLabel) labelsView.addArrangedSubview(subTitleLabel) labelsView.addArrangedSubview(buttonsView) publisher(for: UITapGestureRecognizer()).sink { [weak self] _ in self?.didClickOnCloseButton() }.store(in: &subscribers) } open override func reset() { super.reset() } //-------------------------------------------------- // MARK: - State //-------------------------------------------------- open override func updateView() { updateTextColorConfig() backgroundColor = backgroundColorConfiguration.getColor(surface, forState: type) typeIcon.name = type.styleIconName() typeIcon.color = surface == .dark ? Icon.Color.white : Icon.Color.black closeButton.color = surface == .dark ? Icon.Color.white : Icon.Color.black titleLabel.textColorConfiguration = textColorConfig.eraseToAnyColorable() subTitleLabel.textColorConfiguration = textColorConfig.eraseToAnyColorable() titleLabel.surface = surface subTitleLabel.surface = surface } func didClickOnCloseButton() { print("Notification close button clicked!!!") } ///Temporary Place holder 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 } } 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 } } }