Merge branch 'mbruce/bugfixes' into 'develop'

fixed constraint error

See merge request BPHV_MIPS/vds_ios!108
This commit is contained in:
Bruce, Matt R 2023-09-14 13:36:59 +00:00
commit 8c23dbb09f
14 changed files with 85 additions and 146 deletions

View File

@ -92,6 +92,7 @@
EAA5EEEF28F5C908003B3210 /* VDSTypographyTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAA5EEEC28F5C908003B3210 /* VDSTypographyTokens.xcframework */; };
EAA5EEF128F5C909003B3210 /* VDSColorTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAA5EEED28F5C908003B3210 /* VDSColorTokens.xcframework */; };
EAA5EEF328F5C909003B3210 /* VDSFormControlsTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAA5EEEE28F5C908003B3210 /* VDSFormControlsTokens.xcframework */; };
EAA7456C2AB23E2000C1841F /* TooltipModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA7456B2AB23E2000C1841F /* TooltipModel.swift */; };
EAB1D29C28A5618900DAE764 /* RadioButtonGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB1D29B28A5618900DAE764 /* RadioButtonGroup.swift */; };
EAB1D2CD28ABE76100DAE764 /* Withable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB1D2CC28ABE76000DAE764 /* Withable.swift */; };
EAB1D2CF28ABEF2B00DAE764 /* Typography+Base.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB1D2CE28ABEF2B00DAE764 /* Typography+Base.swift */; };
@ -240,6 +241,7 @@
EAA5EEEC28F5C908003B3210 /* VDSTypographyTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSTypographyTokens.xcframework; path = ../SharedFrameworks/VDSTypographyTokens.xcframework; sourceTree = "<group>"; };
EAA5EEED28F5C908003B3210 /* VDSColorTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSColorTokens.xcframework; path = ../SharedFrameworks/VDSColorTokens.xcframework; sourceTree = "<group>"; };
EAA5EEEE28F5C908003B3210 /* VDSFormControlsTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSFormControlsTokens.xcframework; path = ../SharedFrameworks/VDSFormControlsTokens.xcframework; sourceTree = "<group>"; };
EAA7456B2AB23E2000C1841F /* TooltipModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TooltipModel.swift; sourceTree = "<group>"; };
EAB1D29B28A5618900DAE764 /* RadioButtonGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtonGroup.swift; sourceTree = "<group>"; };
EAB1D2CC28ABE76000DAE764 /* Withable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Withable.swift; sourceTree = "<group>"; };
EAB1D2CE28ABEF2B00DAE764 /* Typography+Base.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Typography+Base.swift"; sourceTree = "<group>"; };
@ -691,6 +693,7 @@
children = (
EAB2375C29E8789100AABE9A /* Tooltip.swift */,
EA8E40922A82889500934ED3 /* TooltipDialog.swift */,
EAA7456B2AB23E2000C1841F /* TooltipModel.swift */,
EAB2376729E9992800AABE9A /* TooltipAlertViewController.swift */,
EAB2376929E9E59100AABE9A /* TooltipLaunchable.swift */,
EAB2376129E9880400AABE9A /* TrailingTooltipLabel.swift */,
@ -979,6 +982,7 @@
EAF1FE9929D4850E00101452 /* Clickable.swift in Sources */,
EAD0688E2A55F819002E3A2D /* Loader.swift in Sources */,
EAB5FEF829393A7200998C17 /* ButtonGroupConstants.swift in Sources */,
EAA7456C2AB23E2000C1841F /* TooltipModel.swift in Sources */,
EA3361AF288B26310071C351 /* FormFieldable.swift in Sources */,
EA513A952A4E1F82002A4DFF /* TitleLockupStyleConfiguration.swift in Sources */,
44604AD729CE196600E62B51 /* Line.swift in Sources */,

View File

@ -62,15 +62,13 @@ open class Control: UIControl, ViewProtocol, UserInfoable, Clickable {
/// Whether the Control can handle the isHighlighted state.
open var canHighlight: Bool = true
open var touchUpInsideCount: Int = 0
var isHighlightAnimating = false
/// Whether the Control is highlighted or not.
open override var isHighlighted: Bool {
didSet {
if canHighlight && isHighlightAnimating == false && touchUpInsideCount > 0 {
if canHighlight && isHighlightAnimating == false && onClickSubscriber != nil {
isHighlightAnimating = true
UIView.animate(withDuration: 0.1, animations: { [weak self] in
self?.setNeedsUpdate()

View File

@ -96,15 +96,13 @@ open class ButtonBase: UIButton, ViewProtocol, UserInfoable, Clickable {
open var useScaledFont: Bool = false { didSet { setNeedsUpdate() } }
open var userInfo = [String: Primitive]()
open var touchUpInsideCount: Int = 0
internal var isHighlightAnimating = false
/// Whether the Control is highlighted or not.
open override var isHighlighted: Bool {
didSet {
if isHighlightAnimating == false && touchUpInsideCount > 0 {
if isHighlightAnimating == false && onClickSubscriber != nil {
isHighlightAnimating = true
UIView.animate(withDuration: 0.1, animations: { [weak self] in
self?.setNeedsUpdate()

View File

@ -20,10 +20,7 @@ public class TooltipLabelAttribute: ActionLabelAttributeModel, TooltipLaunchable
/// Current Surface and this is used to pass down to child objects that implement Surfacable
public var surface: Surface = .light
public var accessibleText: String? = "Tool Tip"
public var closeButtonText: String = "Close"
public var title: String?
public var content: String?
public var contentView: UIView?
public var model: Tooltip.TooltipModel
public var presenter: UIView?
public func setAttribute(on attributedString: NSMutableAttributedString) {
@ -67,27 +64,24 @@ public class TooltipLabelAttribute: ActionLabelAttributeModel, TooltipLaunchable
attributedString.append(NSAttributedString(attachment: tooltip))
addHandler(on: attributedString)
}
public init(id: UUID = UUID(), subscriber: AnyCancellable? = nil, surface: Surface, accessibleText: String? = nil, closeButtonText: String = "Close", title: String? = nil, content: String? = nil, contentView: UIView? = nil, presenter: UIView? = nil) {
public init(id: UUID = UUID(),
subscriber: AnyCancellable? = nil,
accessibleText: String? = nil,
surface: Surface = .light,
model: Tooltip.TooltipModel,
presenter: UIView? = nil) {
self.id = id
self.subscriber = subscriber
self.surface = surface
self.model = model
self.accessibleText = accessibleText
self.closeButtonText = closeButtonText
self.title = title
self.content = content
self.contentView = contentView
self.presenter = presenter
//create the tooltip click event
self.subscriber = action.sink { [weak self] in
guard let self else { return }
self.presentTooltip(surface: self.surface,
title: self.title,
content: self.content,
contentView: contentView,
closeButtonText: self.closeButtonText,
presenter: self.presenter)
self.presentTooltip(surface: surface, tooltipModel: model, presenter: self.presenter)
}
}

View File

@ -124,7 +124,6 @@ open class EntryFieldBase: Control, Changeable {
$0.textStyle = .bodySmall
}
open var tooltipView: UIView?
open var icon: Icon = Icon().with {
$0.size = .small
}
@ -149,12 +148,8 @@ open class EntryFieldBase: Control, Changeable {
open var errorText: String? { didSet { setNeedsUpdate() } }
open var tooltipTitle: String? { didSet { setNeedsUpdate() } }
open var tooltipContent: String? { didSet { setNeedsUpdate() } }
open var tooltipContentView: UIView? { didSet { setNeedsUpdate() } }
open var tooltipModel: Tooltip.TooltipModel? { didSet { setNeedsUpdate() } }
open var transparentBackground: Bool = false { didSet { setNeedsUpdate() } }
open var width: CGFloat? { didSet { setNeedsUpdate() } }
@ -244,8 +239,7 @@ open class EntryFieldBase: Control, Changeable {
helperText = nil
showError = false
errorText = nil
tooltipTitle = nil
tooltipContent = nil
tooltipModel = nil
transparentBackground = false
width = nil
maxLength = nil
@ -299,8 +293,8 @@ open class EntryFieldBase: Control, Changeable {
updatedLabelText = "\(oldText) Optional"
}
if let tooltipTitle, let tooltipContent {
attributes.append(TooltipLabelAttribute(surface: surface, title: tooltipTitle, content: tooltipContent, contentView: tooltipContentView, presenter: self))
if let tooltipModel {
attributes.append(TooltipLabelAttribute(surface: surface, model: tooltipModel, presenter: self))
}
//set the titleLabel

View File

@ -379,7 +379,7 @@ open class TitleLockup: View {
}
//pin the last view to the bottom of this view
previousView?.pinBottom()
previousView?.pinBottom(0, .defaultHigh)
//debugging for borders
eyebrowLabel.debugBorder(show: hasDebugBorder, color: .green)

View File

@ -134,10 +134,10 @@ open class Tooltip: Control, TooltipLaunchable {
.sink(receiveValue: { [weak self] tooltip in
guard let self else { return}
self.presentTooltip(surface: tooltip.surface,
title: tooltip.title,
content: tooltip.content,
contentView: tooltip.contentView,
closeButtonText: tooltip.closeButtonText,
tooltipModel: .init(closeButtonText: tooltip.closeButtonText,
title: tooltip.title,
content: tooltip.content,
contentView: tooltip.contentView),
presenter: self)
})
}

View File

@ -33,10 +33,7 @@ open class TooltipAlertViewController: UIViewController, Surfaceable {
//--------------------------------------------------
/// Current Surface and this is used to pass down to child objects that implement Surfacable
open var surface: Surface = .light { didSet { updateView() }}
open var titleText: String? { didSet { updateView() }}
open var contentText: String? { didSet { updateView() }}
open var contentView: UIView? { didSet { updateView() }}
open var closeButtonText: String = "Close" { didSet { updateView() }}
open var tooltipModel = Tooltip.TooltipModel() { didSet { updateView() }}
open var presenter: UIView? { didSet { updateView() }}
//--------------------------------------------------
@ -106,9 +103,6 @@ open class TooltipAlertViewController: UIViewController, Surfaceable {
open func updateView() {
view.backgroundColor = backgroundColorConfiguration.getColor(self).withAlphaComponent(0.3)
tooltipDialog.surface = surface
tooltipDialog.titleText = titleText
tooltipDialog.contentText = contentText
tooltipDialog.contentView = contentView
tooltipDialog.closeButtonText = closeButtonText
tooltipDialog.tooltipModel = tooltipModel
}
}

View File

@ -37,6 +37,7 @@ open class TooltipDialog: View, UIScrollViewDelegate {
private let contentStackView = UIStackView().with {
$0.translatesAutoresizingMaskIntoConstraints = false
$0.axis = .vertical
$0.alignment = .leading
$0.distribution = .fillProportionally
$0.spacing = 0
}
@ -54,22 +55,18 @@ open class TooltipDialog: View, UIScrollViewDelegate {
//--------------------------------------------------
// MARK: - Public Properties
//--------------------------------------------------
open var titleText: String? { didSet { setNeedsUpdate() } }
open var tooltipModel = Tooltip.TooltipModel() { didSet { setNeedsUpdate() } }
open var titleLabel = Label().with { label in
label.isAccessibilityElement = true
label.textStyle = .boldTitleMedium
}
open var contentText: String? { didSet { setNeedsUpdate() } }
open var contentLabel = Label().with { label in
label.isAccessibilityElement = true
label.textStyle = .bodyLarge
}
open var contentView: UIView? = nil
open var closeButtonText: String = "Close" { didSet { setNeedsUpdate() } }
open lazy var closeButton: UIButton = {
let button = UIButton(type: .system)
button.isAccessibilityElement = true
@ -145,50 +142,39 @@ open class TooltipDialog: View, UIScrollViewDelegate {
/// Used to make changes to the View based off a change events or from local properties.
open override func updateView() {
super.updateView()
backgroundColor = backgroundColorConfiguration.getColor(self)
scrollView.indicatorStyle = surface == .light ? .black : .white
titleLabel.removeFromSuperview()
contentLabel.removeFromSuperview()
contentView?.removeFromSuperview()
contentStackView.arrangedSubviews.forEach { $0.removeFromSuperview() }
titleLabel.surface = surface
contentLabel.surface = surface
line.surface = surface
titleLabel.text = titleText
contentLabel.text = contentText
titleLabel.text = tooltipModel.title
contentLabel.text = tooltipModel.content
titleLabel.sizeToFit()
contentLabel.sizeToFit()
var addedTitle = false
if let titleText, !titleText.isEmpty {
if let titleText = tooltipModel.title, !titleText.isEmpty {
contentStackView.addArrangedSubview(titleLabel)
addedTitle = true
}
var addedContent = false
if let contentText, !contentText.isEmpty {
if let contentText = tooltipModel.content, !contentText.isEmpty {
contentStackView.addArrangedSubview(contentLabel)
addedContent = true
} else if let contentView {
} else if let contentView = tooltipModel.contentView {
contentView.translatesAutoresizingMaskIntoConstraints = false
if var surfaceable = contentView as? Surfaceable {
surfaceable.surface = surface
}
let wrapper = View()
wrapper.addSubview(contentView)
contentView
.pinTop()
.pinLeading()
.pinBottom()
.pinTrailingLessThanOrEqualTo()
contentView.setNeedsLayout()
contentStackView.addArrangedSubview(wrapper)
contentStackView.addArrangedSubview(contentView)
addedContent = true
}
@ -199,8 +185,8 @@ open class TooltipDialog: View, UIScrollViewDelegate {
let closeButtonTextColor = closeButtonTextColorConfiguration.getColor(self)
closeButton.setTitleColor(closeButtonTextColor, for: .normal)
closeButton.setTitleColor(closeButtonTextColor, for: .highlighted)
closeButton.setTitle(closeButtonText, for: .normal)
closeButton.accessibilityLabel = closeButtonText
closeButton.setTitle(tooltipModel.closeButtonText, for: .normal)
closeButton.accessibilityLabel = tooltipModel.closeButtonText
contentStackView.setNeedsLayout()
contentStackView.layoutIfNeeded()
@ -234,7 +220,7 @@ open class TooltipDialog: View, UIScrollViewDelegate {
open override func updateAccessibility() {
super.updateAccessibility()
primaryAccessibilityElement.accessibilityHint = "Double tap on the \(closeButtonText) button to close."
primaryAccessibilityElement.accessibilityHint = "Double tap on the \(tooltipModel.closeButtonText) button to close."
var elements: [Any] = [primaryAccessibilityElement]
contentStackView.arrangedSubviews.forEach{ elements.append($0) }

View File

@ -9,18 +9,15 @@ import Foundation
import UIKit
public protocol TooltipLaunchable {
func presentTooltip(surface: Surface, title: String?, content: String?, contentView: UIView?, closeButtonText: String, presenter: UIView?)
func presentTooltip(surface: Surface, tooltipModel: Tooltip.TooltipModel, presenter: UIView?)
}
extension TooltipLaunchable {
public func presentTooltip(surface: Surface, title: String?, content: String?, contentView: UIView? = nil, closeButtonText: String = "Close", presenter: UIView? = nil) {
public func presentTooltip(surface: Surface, tooltipModel: Tooltip.TooltipModel, presenter: UIView? = nil) {
if let presenting = UIApplication.topViewController() {
let tooltipViewController = TooltipAlertViewController(nibName: nil, bundle: nil).with {
$0.surface = surface
$0.titleText = title
$0.contentText = content
$0.contentView = contentView
$0.closeButtonText = closeButtonText
$0.tooltipModel = tooltipModel
$0.presenter = presenter
$0.modalPresentationStyle = .overCurrentContext
$0.modalTransitionStyle = .crossDissolve

View File

@ -0,0 +1,33 @@
//
// TooltipModel.swift
// VDS
//
// Created by Matt Bruce on 9/13/23.
//
import Foundation
import UIKit
extension Tooltip {
/// Model used to represent the tooltip.
public struct TooltipModel {
/// Current Surface and this is used to pass down to child objects that implement Surfacable
public var closeButtonText: String
public var title: String?
public var content: String?
public var contentView: UIView?
public var contentViewAlignment: UIStackView.Alignment?
public init(closeButtonText: String = "Close",
title: String? = nil,
content: String? = nil,
contentView: UIView? = nil,
contentViewAlignment: UIStackView.Alignment = .leading) {
self.closeButtonText = closeButtonText
self.title = title
self.content = content
self.contentView = contentView
self.contentViewAlignment = contentViewAlignment
}
}
}

View File

@ -29,11 +29,6 @@ open class TrailingTooltipLabel: View, TooltipLaunchable {
super.init(coder: coder)
}
//--------------------------------------------------
// MARK: - Private Properties
//--------------------------------------------------
private let tooltipAction = PassthroughSubject<Void, Never>()
//--------------------------------------------------
// MARK: - Public Properties
//--------------------------------------------------
@ -58,16 +53,7 @@ open class TrailingTooltipLabel: View, TooltipLaunchable {
}() { didSet { setNeedsUpdate() } }
/// Will render the text for Close button for tooltip dialog when on mobile devices
open var tooltipCloseButtonText: String = "Close" { didSet { setNeedsUpdate() } }
/// Text rendered for the title of the tooltip
open var tooltipTitle: String? { didSet { setNeedsUpdate() } }
/// Text rendered for the content of the tooltip
open var tooltipContent: String? { didSet { setNeedsUpdate() } }
/// UIView rendered for the content area of the tooltip
open var tooltipContentView: UIView? { didSet { setNeedsUpdate() } }
open var tooltipModel: Tooltip.TooltipModel? { didSet { setNeedsUpdate() } }
//--------------------------------------------------
// MARK: - Overrides
@ -79,15 +65,6 @@ open class TrailingTooltipLabel: View, TooltipLaunchable {
addSubview(label)
label.pinToSuperView()
//create the tooltip click event
tooltipAction.sink { [weak self] in
guard let self else { return }
self.presentTooltip(surface: self.surface,
title: self.tooltipTitle,
content: self.tooltipContent,
closeButtonText: self.tooltipCloseButtonText,
presenter: self)
}.store(in: &subscribers)
}
/// Used to make changes to the View based off a change events or from local properties.
@ -102,8 +79,8 @@ open class TrailingTooltipLabel: View, TooltipLaunchable {
label.isEnabled = isEnabled
//add tooltip
if let labelText, !labelText.isEmpty {
label.addTooltip(model: .init(surface: surface, closeButtonText: tooltipCloseButtonText, title: tooltipTitle, content: tooltipContent, contentView: tooltipContentView))
if let labelText, let tooltipModel, !labelText.isEmpty {
label.addTooltip(tooltipModel)
}
}
@ -115,9 +92,7 @@ open class TrailingTooltipLabel: View, TooltipLaunchable {
labelAttributes = nil
labelTextStyle = .defaultStyle
labelTextAlignment = .left
tooltipCloseButtonText = "Close"
tooltipTitle = ""
tooltipContent = ""
tooltipModel = nil
shouldUpdateView = true
setNeedsUpdate()
}
@ -125,25 +100,9 @@ open class TrailingTooltipLabel: View, TooltipLaunchable {
extension Label {
/// Model used to represent the tooltip.
public struct TooltipModel {
/// Current Surface and this is used to pass down to child objects that implement Surfacable
public var surface: Surface
public var closeButtonText: String
public var title: String?
public var content: String?
public var contentView: UIView?
public init(surface: Surface = .light, closeButtonText: String = "Close", title: String?, content: String?, contentView: UIView?) {
self.surface = surface
self.closeButtonText = closeButtonText
self.title = title
self.content = content
self.contentView = contentView
}
}
/// Helper to add a tool tip attribute to an existing label.
public func addTooltip(model: TooltipModel) {
public func addTooltip(_ tooltipModel: Tooltip.TooltipModel) {
var newAttributes: [any LabelAttributeModel] = []
if let attributes {
@ -155,12 +114,7 @@ extension Label {
}
if let text = text, !text.isEmpty {
let tooltip = TooltipLabelAttribute(surface: surface,
closeButtonText: model.closeButtonText,
title: model.title,
content: model.content,
contentView: model.contentView,
presenter: self)
let tooltip = TooltipLabelAttribute(surface: surface, model: tooltipModel, presenter: self)
newAttributes.append(tooltip)
}

View File

@ -10,8 +10,6 @@ import UIKit
import Combine
public protocol Clickable: ViewProtocol where Self: UIControl {
/// Reference count used when a subscriber is listening for the UIControl event .touchUpInside.
var touchUpInsideCount: Int { get set }
/// Sets the primary Subscriber used for the UIControl event .touchUpInside.
var onClickSubscriber: AnyCancellable? { get set }
}

View File

@ -20,10 +20,6 @@ public final class UIControlSubscription<SubscriberType: Subscriber, Control: UI
self.control = control
self.event = event
//allow highlight for VDS.Controls on "onClick" events
if let c = control as? Clickable, event == .touchUpInside {
c.touchUpInsideCount += 1
}
control.addTarget(self, action: #selector(eventHandler), for: event)
}
@ -35,13 +31,6 @@ public final class UIControlSubscription<SubscriberType: Subscriber, Control: UI
public func cancel() {
subscriber = nil
}
deinit {
//remove highlight for VDS.Controls on "onClick" events
if let c = control as? Clickable, event == .touchUpInside, c.touchUpInsideCount > 0 {
c.touchUpInsideCount -= 1
}
}
@objc private func eventHandler() {
_ = subscriber?.receive(control)