Skip to content

Commit

Permalink
COIOS-774: Add logos as option for trailing view in ListItem (#1877)
Browse files Browse the repository at this point in the history
  • Loading branch information
goergisn authored Oct 29, 2024
1 parent dd33c89 commit c22eb45
Show file tree
Hide file tree
Showing 11 changed files with 270 additions and 30 deletions.
8 changes: 8 additions & 0 deletions Adyen.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@
81129AE62A4EEF8600E63EBE /* SearchViewController+InterfaceState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81129AE52A4EEF8600E63EBE /* SearchViewController+InterfaceState.swift */; };
81135C922C903DA4008AC8E4 /* JSONEncoder+SortedKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81135C912C903DA4008AC8E4 /* JSONEncoder+SortedKeys.swift */; };
8122B9BD2B9A0FF3002FC4D6 /* ErrorMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8122B9BC2B9A0FF3002FC4D6 /* ErrorMock.swift */; };
8128977B2CC93CB100275487 /* SupportedPaymentMethodsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8128977A2CC93CB000275487 /* SupportedPaymentMethodsView.swift */; };
8128977E2CCA6FE900275487 /* SupportedPaymentMethodLogosViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8128977D2CCA6FE400275487 /* SupportedPaymentMethodLogosViewTests.swift */; };
8136619E2BE0F6F7009AA0CD /* Adyen3DS2 in Frameworks */ = {isa = PBXBuildFile; productRef = 8136619D2BE0F6F7009AA0CD /* Adyen3DS2 */; };
813BF1122B2365400096940E /* XCTestCase+FirstResponder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 813BF1102B2364E00096940E /* XCTestCase+FirstResponder.swift */; };
813BF1132B2365400096940E /* XCTestCase+FirstResponder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 813BF1102B2364E00096940E /* XCTestCase+FirstResponder.swift */; };
Expand Down Expand Up @@ -1604,6 +1606,8 @@
81129AE52A4EEF8600E63EBE /* SearchViewController+InterfaceState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SearchViewController+InterfaceState.swift"; sourceTree = "<group>"; };
81135C912C903DA4008AC8E4 /* JSONEncoder+SortedKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JSONEncoder+SortedKeys.swift"; sourceTree = "<group>"; };
8122B9BC2B9A0FF3002FC4D6 /* ErrorMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorMock.swift; sourceTree = "<group>"; };
8128977A2CC93CB000275487 /* SupportedPaymentMethodsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SupportedPaymentMethodsView.swift; sourceTree = "<group>"; };
8128977D2CCA6FE400275487 /* SupportedPaymentMethodLogosViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SupportedPaymentMethodLogosViewTests.swift; sourceTree = "<group>"; };
813BF1102B2364E00096940E /* XCTestCase+FirstResponder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "XCTestCase+FirstResponder.swift"; sourceTree = "<group>"; };
813EF9DD2A5DA0BC00C65D15 /* FormPickerItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormPickerItem.swift; sourceTree = "<group>"; };
813EF9E12A5DA2D400C65D15 /* FormPickerItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormPickerItemView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3015,6 +3019,7 @@
children = (
F9FE39E22679E09200F02A9B /* LoadingViewTests.swift */,
81A2E3BD2A5C453200CF5F9C /* LinkTextViewTests.swift */,
8128977D2CCA6FE400275487 /* SupportedPaymentMethodLogosViewTests.swift */,
);
path = Views;
sourceTree = "<group>";
Expand Down Expand Up @@ -3968,6 +3973,7 @@
81B001C12A55C5C10015BFA3 /* UISearchBar+Prominent.swift */,
81BBB6732A82792100C1A04B /* UIView+Accessibility.swift */,
E2C0E0C0220D7E5E008616F6 /* SubmitButton.swift */,
8128977A2CC93CB000275487 /* SupportedPaymentMethodsView.swift */,
81A2E3BF2A5C453F00CF5F9C /* LinkTextView.swift */,
F95A788725C416A60032CF7E /* CopyLabelView.swift */,
F99D2F852665211600BB5B2F /* LoadingView.swift */,
Expand Down Expand Up @@ -6761,6 +6767,7 @@
E216D3C5221AEF450013CBCF /* IBANFormatter.swift in Sources */,
5A4702182664E9440023F264 /* APIContext.swift in Sources */,
E9AFF87A224A4C9C005A0D8D /* PaymentComponent.swift in Sources */,
8128977B2CC93CB100275487 /* SupportedPaymentMethodsView.swift in Sources */,
006DCC03295C3E930015EA79 /* SegmentedControlStyle.swift in Sources */,
E216D3C0221AD0620013CBCF /* FormViewItemManager.swift in Sources */,
00EACBB3287327C00082B360 /* FormIssuerPickerItem.swift in Sources */,
Expand Down Expand Up @@ -7225,6 +7232,7 @@
E7085C1E2629FDD700D0153B /* RedirectListnerTests.swift in Sources */,
E74CE3DF26727EB1008231D2 /* DropInDelegateMock.swift in Sources */,
A020EC5A29ED33F90050B2FE /* CashAppPayComponentTests.swift in Sources */,
8128977E2CCA6FE900275487 /* SupportedPaymentMethodLogosViewTests.swift in Sources */,
F967581527D25B1600A16FB6 /* SelfRetainingAPIClientTests.swift in Sources */,
81088A252BDBC2DD007FCDB9 /* CancellableMock.swift in Sources */,
81DA70892BDA6075006CE5D5 /* TwintSDKActionTests+Convenience.swift in Sources */,
Expand Down
2 changes: 1 addition & 1 deletion Adyen/Core/Core Protocols/PaymentMethod.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public extension PaymentMethod {
title: merchantProvidedDisplayInformation.title,
subtitle: subtitle,
logoName: defaultDisplayInformation.logoName,
disclosureText: defaultDisplayInformation.disclosureText,
trailingInfo: defaultDisplayInformation.trailingInfo,
footnoteText: defaultDisplayInformation.footnoteText
)
}
Expand Down
40 changes: 36 additions & 4 deletions Adyen/Core/Models/DisplayInformation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,19 @@ import Foundation
/// Describes a payment method display information.
public struct DisplayInformation: Equatable {

@_spi(AdyenInternal)
public enum TrailingInfoType: Equatable {
case text(String)
case logos(named: [String], trailingText: String?)

internal var accessibilityLabel: String? {
switch self {
case let .text(text): return text
case .logos: return nil
}
}
}

/// The title for the payment method, adapted for displaying in a list.
/// In the case of stored payment methods, this will include information identifying the stored payment method.
/// For example, this could be the last 4 digits of the card number, or the used email address.
Expand All @@ -23,9 +36,9 @@ public struct DisplayInformation: Equatable {
@_spi(AdyenInternal)
public let logoName: String

/// The trailing disclosure text.
/// The trailing info element
@_spi(AdyenInternal)
public let disclosureText: String?
public let trailingInfo: TrailingInfoType?

/// The footnote if any.
@_spi(AdyenInternal)
Expand All @@ -35,7 +48,7 @@ public struct DisplayInformation: Equatable {
@_spi(AdyenInternal)
public let accessibilityLabel: String?

/// Initializes a`DisplayInformation`.
/// Initializes a `DisplayInformation`
///
/// - Parameter title: The title.
/// - Parameter subtitle: The subtitle.
Expand All @@ -51,11 +64,30 @@ public struct DisplayInformation: Equatable {
disclosureText: String? = nil,
footnoteText: String? = nil,
accessibilityLabel: String? = nil
) {
self.init(
title: title,
subtitle: subtitle,
logoName: logoName,
trailingInfo: disclosureText.map { .text($0) },
footnoteText: footnoteText,
accessibilityLabel: accessibilityLabel
)
}

@_spi(AdyenInternal)
public init(
title: String,
subtitle: String?,
logoName: String,
trailingInfo: TrailingInfoType?,
footnoteText: String? = nil,
accessibilityLabel: String? = nil
) {
self.title = title
self.subtitle = subtitle
self.logoName = logoName
self.disclosureText = disclosureText
self.trailingInfo = trailingInfo
self.footnoteText = footnoteText
self.accessibilityLabel = accessibilityLabel
}
Expand Down
1 change: 1 addition & 0 deletions Adyen/Helpers/UIImageViewHelpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,6 @@ public extension AdyenScope where Base: UIImageView {
base.layer.borderWidth = style.borderWidth
base.backgroundColor = style.backgroundColor
base.tintColor = style.tintColor
base.clipsToBounds = style.clipsToBounds
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ private extension FormPickable {
title: title,
subtitle: subtitle,
icon: listItemIcon,
trailingText: trailingText,
trailingInfo: trailingText.map { .text($0) },
identifier: identifier,
selectionHandler: { selectionHandler(self) }
)
Expand Down
24 changes: 20 additions & 4 deletions Adyen/UI/List/ListItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@ import Foundation
@_spi(AdyenInternal)
public class ListItem: FormItem {

public enum TrailingInfoType {
case text(String)
case logos(urls: [URL], trailingText: String?)

internal var accessibilityLabel: String? {
switch self {
case let .text(text): return text
case .logos: return nil
}
}
}

public var isHidden: AdyenObservable<Bool> = AdyenObservable(false)

public var subitems: [FormItem] = []
Expand All @@ -27,7 +39,7 @@ public class ListItem: FormItem {
public var icon: Icon?

/// The trailing text of the item.
public var trailingText: String?
public var trailingInfo: TrailingInfoType?

/// The handler to invoke when the item is selected.
public var selectionHandler: (() -> Void)?
Expand Down Expand Up @@ -61,7 +73,7 @@ public class ListItem: FormItem {
title: String,
subtitle: String? = nil,
icon: Icon? = nil,
trailingText: String? = nil,
trailingInfo: TrailingInfoType? = nil,
style: ListItemStyle = ListItemStyle(),
identifier: String? = nil,
accessibilityLabel: String? = nil,
Expand All @@ -70,10 +82,14 @@ public class ListItem: FormItem {
self.title = title
self.subtitle = subtitle
self.icon = icon
self.trailingText = trailingText
self.trailingInfo = trailingInfo
self.style = style
self.identifier = identifier
self.accessibilityLabel = accessibilityLabel ?? [title, subtitle, trailingText].compactMap { $0 }.joined(separator: ", ")
self.accessibilityLabel = accessibilityLabel ?? [
title,
subtitle,
trailingInfo?.accessibilityLabel
].compactMap { $0 }.joined(separator: ", ")
self.selectionHandler = selectionHandler
}

Expand Down
55 changes: 42 additions & 13 deletions Adyen/UI/List/ListItemView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ public final class ListItemView: UIView, AnyFormItemView {
updateImageView(style: style)
titleLabel.adyen.apply(style.title)
subtitleLabel.adyen.apply(style.subtitle)
trailingTextLabel.adyen.apply(style.trailingText)

if let trailingTextLabel = trailingView as? UILabel {
trailingTextLabel.adyen.apply(style.trailingText)
}
}
}
}
Expand All @@ -67,11 +70,7 @@ public final class ListItemView: UIView, AnyFormItemView {
ViewIdentifierBuilder.build(scopeInstance: $0, postfix: "subtitleLabel")
}

trailingTextLabel.text = item?.trailingText
trailingTextLabel.isHidden = item?.trailingText?.isEmpty ?? true
trailingTextLabel.accessibilityIdentifier = item?.identifier.map {
ViewIdentifierBuilder.build(scopeInstance: $0, postfix: "trailingTextLabel")
}
updateTrailingView(for: item)

imageView.isHidden = item?.icon == nil
updateIcon()
Expand All @@ -90,6 +89,37 @@ public final class ListItemView: UIView, AnyFormItemView {
}
}

private func updateTrailingView(for item: ListItem?) {
contentStackView.removeArrangedSubview(trailingView)
trailingView.removeFromSuperview()

switch item?.trailingInfo {
case let .text(string):
let trailingTextLabel = UILabel()
trailingTextLabel.translatesAutoresizingMaskIntoConstraints = false
trailingTextLabel.text = string
trailingTextLabel.accessibilityIdentifier = item?.identifier.map {
ViewIdentifierBuilder.build(scopeInstance: $0, postfix: "trailingTextLabel")
}
trailingView = trailingTextLabel
trailingView.isHidden = string.isEmpty
case let .logos(urls, trailingText):
let trailingLogosView = SupportedPaymentMethodLogosView(
imageUrls: urls,
trailingText: trailingText
)
trailingLogosView.accessibilityIdentifier = item?.identifier.map {
ViewIdentifierBuilder.build(scopeInstance: $0, postfix: "trailingLogosView")
}
trailingView = trailingLogosView
case nil:
trailingView = UIView()
trailingView.isHidden = true
}

contentStackView.addArrangedSubview(trailingView)
}

private func updateImageView(style: ListItemStyle) {
imageView.contentMode = style.image.contentMode

Expand Down Expand Up @@ -140,11 +170,10 @@ public final class ListItemView: UIView, AnyFormItemView {
return subtitleLabel
}()

private lazy var trailingTextLabel: UILabel = {
let trailingTextLabel = UILabel()
trailingTextLabel.translatesAutoresizingMaskIntoConstraints = false
trailingTextLabel.isHidden = true
return trailingTextLabel
private var trailingView: UIView = {
let view = UIView()
view.isHidden = true
return view
}()

// MARK: - Text Stack View
Expand All @@ -160,7 +189,7 @@ public final class ListItemView: UIView, AnyFormItemView {
}()

private lazy var contentStackView: UIStackView = {
let stackView = UIStackView(arrangedSubviews: [imageView, titleSubtitleStackView, trailingTextLabel])
let stackView = UIStackView(arrangedSubviews: [imageView, titleSubtitleStackView, trailingView])
stackView.setCustomSpacing(16, after: imageView)
stackView.spacing = 8
stackView.translatesAutoresizingMaskIntoConstraints = false
Expand Down Expand Up @@ -188,7 +217,7 @@ public final class ListItemView: UIView, AnyFormItemView {
self.heightAnchor.constraint(greaterThanOrEqualToConstant: 48)
]

trailingTextLabel.setContentHuggingPriority(.required, for: .horizontal)
trailingView.setContentHuggingPriority(.required, for: .horizontal)
imageView.setContentHuggingPriority(.required, for: .horizontal)

NSLayoutConstraint.activate(constraints)
Expand Down
Loading

0 comments on commit c22eb45

Please sign in to comment.