From d6dc299a36ac424a8fd57d1a1338fd99280e7d92 Mon Sep 17 00:00:00 2001 From: Huw Rowlands Date: Mon, 10 May 2021 08:30:34 +1000 Subject: [PATCH 1/6] Move up a minor compiler version --- Sources/Afterpay/Resources/SVG.swift | 2 +- Sources/Afterpay/Views/SVGView.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Afterpay/Resources/SVG.swift b/Sources/Afterpay/Resources/SVG.swift index ba34c343..8e53cc1f 100644 --- a/Sources/Afterpay/Resources/SVG.swift +++ b/Sources/Afterpay/Resources/SVG.swift @@ -7,7 +7,7 @@ // import Foundation -#if compiler(>=5.1) && compiler(<5.4) +#if compiler(>=5.1) && compiler(<5.5) @_implementationOnly import Macaw #else import Macaw diff --git a/Sources/Afterpay/Views/SVGView.swift b/Sources/Afterpay/Views/SVGView.swift index eaa31075..c8b7615d 100644 --- a/Sources/Afterpay/Views/SVGView.swift +++ b/Sources/Afterpay/Views/SVGView.swift @@ -7,7 +7,7 @@ // import Foundation -#if compiler(>=5.1) && compiler(<5.4) +#if compiler(>=5.1) && compiler(<5.5) @_implementationOnly import Macaw #else import Macaw From 82a69e7ef370beb09f5c9d9038a0779936342a73 Mon Sep 17 00:00:00 2001 From: Huw Rowlands Date: Mon, 10 May 2021 08:31:19 +1000 Subject: [PATCH 2/6] Add different kinds of payment buttons Previously, we just had one payment button. Now, we have a few more options for different wording. --- .../Example/Purchase/CartViewController.swift | 3 +- Sources/Afterpay/Resources/ColorScheme.swift | 20 + Sources/Afterpay/Resources/SVG.swift | 366 ++++++++++++++++++ .../Afterpay/Resources/SVGConfiguration.swift | 112 ++++-- Sources/Afterpay/Resources/Strings.swift | 1 - Sources/Afterpay/Views/PaymentButton.swift | 9 +- 6 files changed, 474 insertions(+), 37 deletions(-) diff --git a/Example/Example/Purchase/CartViewController.swift b/Example/Example/Purchase/CartViewController.swift index 388a67ed..ee9613d9 100644 --- a/Example/Example/Purchase/CartViewController.swift +++ b/Example/Example/Purchase/CartViewController.swift @@ -48,7 +48,8 @@ final class CartViewController: UIViewController, UITableViewDataSource { tableView.register(CheckoutOptionsCell.self, forCellReuseIdentifier: checkoutOptionsCellIdentifier) tableView.register(TitleSubtitleCell.self, forCellReuseIdentifier: titleSubtitleCellIdentifier) - let payButton: UIButton = PaymentButton() + let payButton: UIButton = + PaymentButton(colorScheme: .dynamic(lightPalette: .blackOnMint, darkPalette: .mintOnBlack), buttonKind: .checkout) payButton.isEnabled = cart.payEnabled payButton.accessibilityIdentifier = "payNow" payButton.addTarget(self, action: #selector(didTapPay), for: .touchUpInside) diff --git a/Sources/Afterpay/Resources/ColorScheme.swift b/Sources/Afterpay/Resources/ColorScheme.swift index 41ab7411..22653ec2 100644 --- a/Sources/Afterpay/Resources/ColorScheme.swift +++ b/Sources/Afterpay/Resources/ColorScheme.swift @@ -38,3 +38,23 @@ public enum ColorPalette { case whiteOnBlack case blackOnWhite } + +public enum ButtonKind { + case buyNow + case checkout + case payNow + case placeOrder + + var accessibilityLabel: String { + switch self { + case .buyNow: + return "buy now with" + case .checkout: + return "checkout with" + case .payNow: + return "pay now with" + case .placeOrder: + return "place order with" + } + } +} diff --git a/Sources/Afterpay/Resources/SVG.swift b/Sources/Afterpay/Resources/SVG.swift index 8e53cc1f..c2739c7f 100644 --- a/Sources/Afterpay/Resources/SVG.swift +++ b/Sources/Afterpay/Resources/SVG.swift @@ -490,5 +490,371 @@ struct SVG: Equatable { """ ) + static let afterpayBuyNowWhiteOnBlack = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + """ + ) + + static let afterpayBuyNowBlackOnMint = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + """ + ) + + static let afterpayCheckoutWhiteOnBlack = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + + + """ + ) + + static let afterpayCheckoutBlackOnMint = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + + + """ + ) + + static let afterpayPlaceOrderWhiteOnBlack = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + + + + + """ + ) + + static let afterpayPlaceOrderBlackOnMint = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + + + + + """ + ) + + static let clearpayBuyNowWhiteOnBlack = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + + """ + ) + + static let clearpayBuyNowBlackOnMint = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + + """ + ) + + static let clearpayCheckoutWhiteOnBlack = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + + + + """ + ) + + static let clearpayCheckoutBlackOnMint = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + + + + """ + ) + + static let clearpayPlaceOrderWhiteOnBlack = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + ) + + static let clearpayPlaceOrderBlackOnMint = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + ) + } // swiftlint:enable line_length file_length type_body_length diff --git a/Sources/Afterpay/Resources/SVGConfiguration.swift b/Sources/Afterpay/Resources/SVGConfiguration.swift index c1de543f..ea9b76e8 100644 --- a/Sources/Afterpay/Resources/SVGConfiguration.swift +++ b/Sources/Afterpay/Resources/SVGConfiguration.swift @@ -67,41 +67,87 @@ struct BadgeConfiguration: SVGConfiguration { struct PaymentButtonConfiguration: SVGConfiguration { var colorScheme: ColorScheme + var buttonKind: ButtonKind + + // swiftlint:disable:next cyclomatic_complexity + private func svg(for palette: ColorPalette, locale: Locale) -> SVG { + switch (palette, buttonKind, locale) { + + //BUY NOW WITH AFTERPAY + case (.whiteOnBlack, .buyNow, Locales.greatBritain), + (.mintOnBlack, .buyNow, Locales.greatBritain): + return .clearpayBuyNowWhiteOnBlack + case (.blackOnMint, .buyNow, Locales.greatBritain), + (.blackOnWhite, .buyNow, Locales.greatBritain): + return .clearpayBuyNowBlackOnMint + + case (.mintOnBlack, .buyNow, _), + (.whiteOnBlack, .buyNow, _): + return .afterpayBuyNowWhiteOnBlack + case (.blackOnMint, .buyNow, _), + (.blackOnWhite, .buyNow, _): + return .afterpayBuyNowBlackOnMint + + //CHECKOUT WITH AFTERPAY + case (.whiteOnBlack, .checkout, Locales.greatBritain), + (.mintOnBlack, .checkout, Locales.greatBritain): + return .clearpayCheckoutWhiteOnBlack + case (.blackOnMint, .checkout, Locales.greatBritain), + (.blackOnWhite, .checkout, Locales.greatBritain): + return .clearpayCheckoutBlackOnMint + + case (.mintOnBlack, .checkout, _), + (.whiteOnBlack, .checkout, _): + return .afterpayCheckoutWhiteOnBlack + case (.blackOnMint, .checkout, _), + (.blackOnWhite, .checkout, _): + return .afterpayCheckoutBlackOnMint + + //PAY NOW WITH AFTERPAY + case (.blackOnMint, .payNow, Locales.greatBritain): + return .clearpayPayNowBlackOnMint + case (.mintOnBlack, .payNow, Locales.greatBritain): + return .clearpayPayNowMintOnBlack + case (.whiteOnBlack, .payNow, Locales.greatBritain): + return .clearpayPayNowWhiteOnBlack + case (.blackOnWhite, .payNow, Locales.greatBritain): + return .clearpayPayNowBlackOnWhite + + case (.blackOnMint, .payNow, _): + return .afterpayPayNowBlackOnMint + case (.mintOnBlack, .payNow, _): + return .afterpayPayNowMintOnBlack + case (.whiteOnBlack, .payNow, _): + return .afterpayPayNowWhiteOnBlack + case (.blackOnWhite, .payNow, _): + return .afterpayPayNowBlackOnWhite + + //PLACE ORDER WITH AFTERPAY + case (.whiteOnBlack, .placeOrder, Locales.greatBritain), + (.mintOnBlack, .placeOrder, Locales.greatBritain): + return .clearpayPlaceOrderWhiteOnBlack + case (.blackOnMint, .placeOrder, Locales.greatBritain), + (.blackOnWhite, .placeOrder, Locales.greatBritain): + return .clearpayPlaceOrderBlackOnMint + + case (.mintOnBlack, .placeOrder, _), + (.whiteOnBlack, .placeOrder, _): + return .afterpayPlaceOrderWhiteOnBlack + case (.blackOnMint, .placeOrder, _), + (.blackOnWhite, .placeOrder, _): + return .afterpayPlaceOrderBlackOnMint + } + } func svg(localizedFor locale: Locale, withTraits traitCollection: UITraitCollection) -> SVG { - let svgForPalette: (ColorPalette) -> SVG = { palette in - switch (palette, locale) { - case (.blackOnMint, Locales.greatBritain): - return .clearpayPayNowBlackOnMint - case (.mintOnBlack, Locales.greatBritain): - return .clearpayPayNowMintOnBlack - case (.whiteOnBlack, Locales.greatBritain): - return .clearpayPayNowWhiteOnBlack - case (.blackOnWhite, Locales.greatBritain): - return .clearpayPayNowBlackOnWhite - case (.blackOnMint, _): - return .afterpayPayNowBlackOnMint - case (.mintOnBlack, _): - return .afterpayPayNowMintOnBlack - case (.whiteOnBlack, _): - return .afterpayPayNowWhiteOnBlack - case (.blackOnWhite, _): - return .afterpayPayNowBlackOnWhite - } + switch traitCollection.userInterfaceStyle { + case .dark: + return svg(for: colorScheme.darkPalette, locale: locale) + case .light, .unspecified: + fallthrough + @unknown default: + return svg(for: colorScheme.lightPalette, locale: locale) } - - let svg: SVG = { - switch traitCollection.userInterfaceStyle { - case .dark: - return svgForPalette(colorScheme.darkPalette) - case .light, .unspecified: - fallthrough - @unknown default: - return svgForPalette(colorScheme.lightPalette) - } - }() - - return svg } func accessibilityLabel(localizedFor locale: Locale) -> String { @@ -109,7 +155,7 @@ struct PaymentButtonConfiguration: SVGConfiguration { ? Strings.accessibleClearpay : Strings.accessibleAfterpay - return "\(Strings.payNowWith) \(accessiblePaymentMethod)" + return "\(buttonKind.accessibilityLabel) \(accessiblePaymentMethod)" } } diff --git a/Sources/Afterpay/Resources/Strings.swift b/Sources/Afterpay/Resources/Strings.swift index 66157345..9623cb4b 100644 --- a/Sources/Afterpay/Resources/Strings.swift +++ b/Sources/Afterpay/Resources/Strings.swift @@ -16,7 +16,6 @@ enum Strings { static let info = "Info" static let orPayWith = "or pay with" - static let payNowWith = "pay now with" // MARK: - String Formats diff --git a/Sources/Afterpay/Views/PaymentButton.swift b/Sources/Afterpay/Views/PaymentButton.swift index e9ee5445..511fddc3 100644 --- a/Sources/Afterpay/Views/PaymentButton.swift +++ b/Sources/Afterpay/Views/PaymentButton.swift @@ -15,12 +15,17 @@ public final class PaymentButton: UIButton { didSet { updateImage() } } + public var buttonKind: ButtonKind = .buyNow { + didSet { updateImage() } + } + private var configuration: SVGConfiguration { - PaymentButtonConfiguration(colorScheme: colorScheme) + PaymentButtonConfiguration(colorScheme: colorScheme, buttonKind: buttonKind) } - public init(colorScheme: ColorScheme = .static(.blackOnMint)) { + public init(colorScheme: ColorScheme = .static(.blackOnMint), buttonKind: ButtonKind = .payNow) { self.colorScheme = colorScheme + self.buttonKind = buttonKind super.init(frame: .zero) From 4a7943b430c24246c26a163885d9fda22cfa6cec Mon Sep 17 00:00:00 2001 From: Huw Rowlands Date: Mon, 10 May 2021 09:30:15 +1000 Subject: [PATCH 3/6] Make functions for getting the right svgs Previously, there was a very big switch statement for finding the right SVG. This worked, but it is unsustainable as we add more different kinds of palettes and button kinds and locales. Now, we moved the logic for finding the SVG to the SVG struct itself. I have also moved SVG sources to new file. Before, all the SVG sources were in the SVG.swift file. This was too much for that file. I want to separate out the long, bland SVG source from the other logic in the SVG struct. This will be more important as we add more logic to the SVG struct. --- Afterpay.xcodeproj/project.pbxproj | 4 + Sources/Afterpay/Resources/SVG+Source.swift | 856 +++++++++++++++++ Sources/Afterpay/Resources/SVG.swift | 892 ++---------------- .../Afterpay/Resources/SVGConfiguration.swift | 118 +-- 4 files changed, 948 insertions(+), 922 deletions(-) create mode 100644 Sources/Afterpay/Resources/SVG+Source.swift diff --git a/Afterpay.xcodeproj/project.pbxproj b/Afterpay.xcodeproj/project.pbxproj index 9bfc1a96..a0d07fee 100644 --- a/Afterpay.xcodeproj/project.pbxproj +++ b/Afterpay.xcodeproj/project.pbxproj @@ -25,6 +25,7 @@ 557511BB264259C30040CC51 /* CombineWrapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 557511BA264259C30040CC51 /* CombineWrapperTests.swift */; }; 557511BF2644CAA50040CC51 /* WKWebView+Cache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 557511BE2644CAA50040CC51 /* WKWebView+Cache.swift */; }; 557511C12644D0890040CC51 /* WKWebViewConfiguration+UserAgent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 557511C02644D0890040CC51 /* WKWebViewConfiguration+UserAgent.swift */; }; + 557511C326489F090040CC51 /* SVG+Source.swift in Sources */ = {isa = PBXBuildFile; fileRef = 557511C226489F090040CC51 /* SVG+Source.swift */; }; 55A2D307261BB36C00D8E23A /* Money.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55A2D306261BB36C00D8E23A /* Money.swift */; }; 6602EF0F25358A8000A0468C /* ColorScheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6602EF0E25358A8000A0468C /* ColorScheme.swift */; }; 6605666324E5199500DA588E /* Locales.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6605666224E5199500DA588E /* Locales.swift */; }; @@ -89,6 +90,7 @@ 557511BA264259C30040CC51 /* CombineWrapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CombineWrapperTests.swift; sourceTree = ""; }; 557511BE2644CAA50040CC51 /* WKWebView+Cache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WKWebView+Cache.swift"; sourceTree = ""; }; 557511C02644D0890040CC51 /* WKWebViewConfiguration+UserAgent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WKWebViewConfiguration+UserAgent.swift"; sourceTree = ""; }; + 557511C226489F090040CC51 /* SVG+Source.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SVG+Source.swift"; sourceTree = ""; }; 55A2D306261BB36C00D8E23A /* Money.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Money.swift; sourceTree = ""; }; 6602EF0E25358A8000A0468C /* ColorScheme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorScheme.swift; sourceTree = ""; }; 6605666224E5199500DA588E /* Locales.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Locales.swift; sourceTree = ""; }; @@ -333,6 +335,7 @@ 151A4FEA258C1F8A0046CEEE /* StaticContent.swift */, 66E255AD24E3C14600C81F20 /* Strings.swift */, 6615F99A24D14620005036F1 /* SVG.swift */, + 557511C226489F090040CC51 /* SVG+Source.swift */, 6672982925357D80001D1C5A /* SVGConfiguration.swift */, ); path = Resources; @@ -545,6 +548,7 @@ 66DAAC8B24E0CF0100127460 /* PriceBreakdown.swift in Sources */, 551BEDFC25F9C56600FDF9EE /* WidgetEvent.swift in Sources */, 661CFDB62570E7F000D8A1E8 /* PaymentButton.swift in Sources */, + 557511C326489F090040CC51 /* SVG+Source.swift in Sources */, 662A3AED24A999A500EFD826 /* CheckoutResult.swift in Sources */, 551BEDF825F9B95C00FDF9EE /* WidgetView.swift in Sources */, 1522246025C925E5004B9CE5 /* Environment.swift in Sources */, diff --git a/Sources/Afterpay/Resources/SVG+Source.swift b/Sources/Afterpay/Resources/SVG+Source.swift new file mode 100644 index 00000000..b5e7ff9d --- /dev/null +++ b/Sources/Afterpay/Resources/SVG+Source.swift @@ -0,0 +1,856 @@ +// +// SVG+Source.swift +// Afterpay +// +// Created by Huw Rowlands on 10/5/21. +// Copyright © 2021 Afterpay. All rights reserved. +// + +import UIKit +#if compiler(>=5.1) && compiler(<5.5) +@_implementationOnly import Macaw +#else +import Macaw +#endif + +// swiftlint:disable line_length file_length +extension SVG { + + // MARK: Badge + + static let afterpayBadgeBlackOnMint = SVG( + size: CGSize(width: 1582, height: 551), + minimumWidth: 64, + svgString: """ + + + + + + + + + + + + + + + + + + + """ + ) + + static let clearpayBadgeBlackOnMint = SVG( + size: CGSize(width: 1620, height: 551), + minimumWidth: 64, + svgString: """ + + + + + + + + + + + + + """ + ) + + static let afterpayBadgeMintOnBlack = SVG( + size: CGSize(width: 1582, height: 551), + minimumWidth: 64, + svgString: """ + + + + + + + + + + + + + + + + + + + """ + ) + + static let clearpayBadgeMintOnBlack = SVG( + size: CGSize(width: 1620, height: 551), + minimumWidth: 64, + svgString: """ + + + + + + + + + + + + + """ + ) + + static let afterpayBadgeWhiteOnBlack: SVG = SVG( + size: CGSize(width: 1582, height: 551), + minimumWidth: 64, + svgString: """ + + + + + + + + + + + + + + + + + + + """ + ) + + static let clearpayBadgeWhiteOnBlack = SVG( + size: CGSize(width: 1620, height: 551), + minimumWidth: 64, + svgString: """ + + + + + + + + + + + + + """ + ) + + static let afterpayBadgeBlackOnWhite: SVG = SVG( + size: CGSize(width: 1582, height: 551), + minimumWidth: 64, + svgString: """ + + + + + + + + + + + + + + + + + + + """ + ) + + static let clearpayBadgeBlackOnWhite = SVG( + size: CGSize(width: 1620, height: 551), + minimumWidth: 64, + svgString: """ + + + + + + + + + + + + + """ + ) + + // MARK: Pay now + + static let afterpayPayNowBlackOnMint = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + ) + + static let clearpayPayNowBlackOnMint = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + ) + + static let afterpayPayNowMintOnBlack = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + ) + + static let clearpayPayNowMintOnBlack = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + ) + + static let afterpayPayNowWhiteOnBlack = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + ) + + static let clearpayPayNowWhiteOnBlack = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + ) + + static let afterpayPayNowBlackOnWhite = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + ) + + static let clearpayPayNowBlackOnWhite = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + ) + + // MARK: Buy now + + static let afterpayBuyNowWhiteOnBlack = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + """ + ) + + static let clearpayBuyNowWhiteOnBlack = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + + """ + ) + + static let afterpayBuyNowBlackOnMint = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + """ + ) + + static let clearpayBuyNowBlackOnMint = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + + """ + ) + + // MARK: Checkout + + static let afterpayCheckoutWhiteOnBlack = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + + + """ + ) + + static let clearpayCheckoutWhiteOnBlack = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + + + + """ + ) + + static let afterpayCheckoutBlackOnMint = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + + + """ + ) + + static let clearpayCheckoutBlackOnMint = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + + + + """ + ) + + // MARK: Place Order + + static let afterpayPlaceOrderWhiteOnBlack = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + + + + + """ + ) + + static let clearpayPlaceOrderWhiteOnBlack = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + ) + + static let afterpayPlaceOrderBlackOnMint = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + + + + + """ + ) + + static let clearpayPlaceOrderBlackOnMint = SVG( + size: CGSize(width: 1200, height: 180), + minimumWidth: 256, + svgString: """ + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + ) + +} +// swiftlint:enable line_length file_length diff --git a/Sources/Afterpay/Resources/SVG.swift b/Sources/Afterpay/Resources/SVG.swift index c2739c7f..a5e5a025 100644 --- a/Sources/Afterpay/Resources/SVG.swift +++ b/Sources/Afterpay/Resources/SVG.swift @@ -14,7 +14,6 @@ import Macaw #endif import UIKit -// swiftlint:disable line_length file_length type_body_length struct SVG: Equatable { let size: CGSize @@ -30,831 +29,76 @@ struct SVG: Equatable { self.svgString = svgString } - static let afterpayBadgeBlackOnMint = SVG( - size: CGSize(width: 1582, height: 551), - minimumWidth: 64, - svgString: """ - - - - - - - - - - - - - - - - - - - """ - ) - - static let clearpayBadgeBlackOnMint = SVG( - size: CGSize(width: 1620, height: 551), - minimumWidth: 64, - svgString: """ - - - - - - - - - - - - - """ - ) - - static let afterpayBadgeMintOnBlack = SVG( - size: CGSize(width: 1582, height: 551), - minimumWidth: 64, - svgString: """ - - - - - - - - - - - - - - - - - - - """ - ) - - static let clearpayBadgeMintOnBlack = SVG( - size: CGSize(width: 1620, height: 551), - minimumWidth: 64, - svgString: """ - - - - - - - - - - - - - """ - ) - - static let afterpayBadgeWhiteOnBlack: SVG = SVG( - size: CGSize(width: 1582, height: 551), - minimumWidth: 64, - svgString: """ - - - - - - - - - - - - - - - - - - - """ - ) - - static let clearpayBadgeWhiteOnBlack = SVG( - size: CGSize(width: 1620, height: 551), - minimumWidth: 64, - svgString: """ - - - - - - - - - - - - - """ - ) - - static let afterpayBadgeBlackOnWhite: SVG = SVG( - size: CGSize(width: 1582, height: 551), - minimumWidth: 64, - svgString: """ - - - - - - - - - - - - - - - - - - - """ - ) - - static let clearpayBadgeBlackOnWhite = SVG( - size: CGSize(width: 1620, height: 551), - minimumWidth: 64, - svgString: """ - - - - - - - - - - - - - """ - ) - - static let afterpayPayNowBlackOnMint = SVG( - size: CGSize(width: 1200, height: 180), - minimumWidth: 256, - svgString: """ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - """ - ) - - static let clearpayPayNowBlackOnMint = SVG( - size: CGSize(width: 1200, height: 180), - minimumWidth: 256, - svgString: """ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - """ - ) - - static let afterpayPayNowMintOnBlack = SVG( - size: CGSize(width: 1200, height: 180), - minimumWidth: 256, - svgString: """ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - """ - ) - - static let clearpayPayNowMintOnBlack = SVG( - size: CGSize(width: 1200, height: 180), - minimumWidth: 256, - svgString: """ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - """ - ) - - static let afterpayPayNowWhiteOnBlack = SVG( - size: CGSize(width: 1200, height: 180), - minimumWidth: 256, - svgString: """ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - """ - ) - - static let clearpayPayNowWhiteOnBlack = SVG( - size: CGSize(width: 1200, height: 180), - minimumWidth: 256, - svgString: """ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - """ - ) - - static let afterpayPayNowBlackOnWhite = SVG( - size: CGSize(width: 1200, height: 180), - minimumWidth: 256, - svgString: """ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - """ - ) - - static let clearpayPayNowBlackOnWhite = SVG( - size: CGSize(width: 1200, height: 180), - minimumWidth: 256, - svgString: """ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - """ - ) - - static let afterpayBuyNowWhiteOnBlack = SVG( - size: CGSize(width: 1200, height: 180), - minimumWidth: 256, - svgString: """ - - - - - - - - - - - - - - - - - - - - - - """ - ) - - static let afterpayBuyNowBlackOnMint = SVG( - size: CGSize(width: 1200, height: 180), - minimumWidth: 256, - svgString: """ - - - - - - - - - - - - - - - - - - - - - - """ - ) - - static let afterpayCheckoutWhiteOnBlack = SVG( - size: CGSize(width: 1200, height: 180), - minimumWidth: 256, - svgString: """ - - - - - - - - - - - - - - - - - - - - - - - - """ - ) - - static let afterpayCheckoutBlackOnMint = SVG( - size: CGSize(width: 1200, height: 180), - minimumWidth: 256, - svgString: """ - - - - - - - - - - - - - - - - - - - - - - - - """ - ) - - static let afterpayPlaceOrderWhiteOnBlack = SVG( - size: CGSize(width: 1200, height: 180), - minimumWidth: 256, - svgString: """ - - - - - - - - - - - - - - - - - - - - - - - - - - """ - ) - - static let afterpayPlaceOrderBlackOnMint = SVG( - size: CGSize(width: 1200, height: 180), - minimumWidth: 256, - svgString: """ - - - - - - - - - - - - - - - - - - - - - - - - - - """ - ) - - static let clearpayBuyNowWhiteOnBlack = SVG( - size: CGSize(width: 1200, height: 180), - minimumWidth: 256, - svgString: """ - - - - - - - - - - - - - - - - - - - - - - - """ - ) - - static let clearpayBuyNowBlackOnMint = SVG( - size: CGSize(width: 1200, height: 180), - minimumWidth: 256, - svgString: """ - - - - - - - - - - - - - - - - - - - - - - - """ - ) - - static let clearpayCheckoutWhiteOnBlack = SVG( - size: CGSize(width: 1200, height: 180), - minimumWidth: 256, - svgString: """ - - - - - - - - - - - - - - - - - - - - - - - - - """ - ) + static func badge(palette: ColorPalette, locale: Locale) -> SVG { + switch (palette, locale) { + case (.blackOnMint, Locales.greatBritain): + return .clearpayBadgeBlackOnMint + case (.mintOnBlack, Locales.greatBritain): + return .clearpayBadgeMintOnBlack + case (.whiteOnBlack, Locales.greatBritain): + return .clearpayBadgeWhiteOnBlack + case (.blackOnWhite, Locales.greatBritain): + return .clearpayBadgeBlackOnWhite + case (.blackOnMint, _): + return .afterpayBadgeBlackOnMint + case (.mintOnBlack, _): + return .afterpayBadgeMintOnBlack + case (.whiteOnBlack, _): + return .afterpayBadgeWhiteOnBlack + case (.blackOnWhite, _): + return .afterpayBadgeBlackOnWhite + } + } - static let clearpayCheckoutBlackOnMint = SVG( - size: CGSize(width: 1200, height: 180), - minimumWidth: 256, - svgString: """ - - - - - - - - - - - - - - - - - - - - - - - - - """ - ) + static func buyNow(palette: ColorPalette, locale: Locale) -> SVG { + switch (palette, locale) { + case (.blackOnMint, Locales.greatBritain), (.blackOnWhite, Locales.greatBritain): + return .clearpayBuyNowBlackOnMint + case (.whiteOnBlack, Locales.greatBritain), (.mintOnBlack, Locales.greatBritain): + return .clearpayBuyNowWhiteOnBlack + case (.blackOnMint, _), (.blackOnWhite, _): + return .afterpayBuyNowBlackOnMint + case (.whiteOnBlack, _), (.mintOnBlack, _): + return .afterpayBuyNowWhiteOnBlack + } + } - static let clearpayPlaceOrderWhiteOnBlack = SVG( - size: CGSize(width: 1200, height: 180), - minimumWidth: 256, - svgString: """ - - - - - - - - - - - - - - - - - - - - - - - - - - - """ - ) + static func checkout(palette: ColorPalette, locale: Locale) -> SVG { + switch (palette, locale) { + case (.blackOnMint, Locales.greatBritain), (.blackOnWhite, Locales.greatBritain): + return .clearpayCheckoutBlackOnMint + case (.whiteOnBlack, Locales.greatBritain), (.mintOnBlack, Locales.greatBritain): + return .clearpayCheckoutWhiteOnBlack + case (.blackOnMint, _), (.blackOnWhite, _): + return .afterpayCheckoutBlackOnMint + case (.whiteOnBlack, _), (.mintOnBlack, _): + return .afterpayCheckoutWhiteOnBlack + } + } - static let clearpayPlaceOrderBlackOnMint = SVG( - size: CGSize(width: 1200, height: 180), - minimumWidth: 256, - svgString: """ - - - - - - - - - - - - - - - - - - - - - - - - - - - """ - ) + static func payNow(palette: ColorPalette, locale: Locale) -> SVG { + switch (palette, locale) { + case (.blackOnMint, Locales.greatBritain), (.blackOnWhite, Locales.greatBritain): + return .clearpayPayNowBlackOnMint + case (.whiteOnBlack, Locales.greatBritain), (.mintOnBlack, Locales.greatBritain): + return .clearpayPayNowWhiteOnBlack + case (.blackOnMint, _), (.blackOnWhite, _): + return .afterpayPayNowBlackOnMint + case (.whiteOnBlack, _), (.mintOnBlack, _): + return .afterpayPayNowWhiteOnBlack + } + } + static func placeOrder(palette: ColorPalette, locale: Locale) -> SVG { + switch (palette, locale) { + case (.blackOnMint, Locales.greatBritain), (.blackOnWhite, Locales.greatBritain): + return .clearpayPlaceOrderBlackOnMint + case (.whiteOnBlack, Locales.greatBritain), (.mintOnBlack, Locales.greatBritain): + return .clearpayPlaceOrderWhiteOnBlack + case (.blackOnMint, _), (.blackOnWhite, _): + return .afterpayPlaceOrderBlackOnMint + case (.whiteOnBlack, _), (.mintOnBlack, _): + return .afterpayPlaceOrderWhiteOnBlack + } + } } -// swiftlint:enable line_length file_length type_body_length diff --git a/Sources/Afterpay/Resources/SVGConfiguration.swift b/Sources/Afterpay/Resources/SVGConfiguration.swift index ea9b76e8..5c75423b 100644 --- a/Sources/Afterpay/Resources/SVGConfiguration.swift +++ b/Sources/Afterpay/Resources/SVGConfiguration.swift @@ -23,39 +23,14 @@ struct BadgeConfiguration: SVGConfiguration { var colorScheme: ColorScheme = .static(.blackOnMint) func svg(localizedFor locale: Locale, withTraits traitCollection: UITraitCollection) -> SVG { - let svgForPalette: (ColorPalette) -> SVG = { palette in - switch (palette, locale) { - case (.blackOnMint, Locales.greatBritain): - return .clearpayBadgeBlackOnMint - case (.mintOnBlack, Locales.greatBritain): - return .clearpayBadgeMintOnBlack - case (.whiteOnBlack, Locales.greatBritain): - return .clearpayBadgeWhiteOnBlack - case (.blackOnWhite, Locales.greatBritain): - return .clearpayBadgeBlackOnWhite - case (.blackOnMint, _): - return .afterpayBadgeBlackOnMint - case (.mintOnBlack, _): - return .afterpayBadgeMintOnBlack - case (.whiteOnBlack, _): - return .afterpayBadgeWhiteOnBlack - case (.blackOnWhite, _): - return .afterpayBadgeBlackOnWhite - } + switch traitCollection.userInterfaceStyle { + case .dark: + return SVG.badge(palette: colorScheme.darkPalette, locale: locale) + case .light, .unspecified: + fallthrough + @unknown default: + return SVG.badge(palette: colorScheme.lightPalette, locale: locale) } - - let svg: SVG = { - switch traitCollection.userInterfaceStyle { - case .dark: - return svgForPalette(colorScheme.darkPalette) - case .light, .unspecified: - fallthrough - @unknown default: - return svgForPalette(colorScheme.lightPalette) - } - }() - - return svg } func accessibilityLabel(localizedFor locale: Locale) -> String { @@ -69,74 +44,21 @@ struct PaymentButtonConfiguration: SVGConfiguration { var colorScheme: ColorScheme var buttonKind: ButtonKind - // swiftlint:disable:next cyclomatic_complexity private func svg(for palette: ColorPalette, locale: Locale) -> SVG { - switch (palette, buttonKind, locale) { - - //BUY NOW WITH AFTERPAY - case (.whiteOnBlack, .buyNow, Locales.greatBritain), - (.mintOnBlack, .buyNow, Locales.greatBritain): - return .clearpayBuyNowWhiteOnBlack - case (.blackOnMint, .buyNow, Locales.greatBritain), - (.blackOnWhite, .buyNow, Locales.greatBritain): - return .clearpayBuyNowBlackOnMint - - case (.mintOnBlack, .buyNow, _), - (.whiteOnBlack, .buyNow, _): - return .afterpayBuyNowWhiteOnBlack - case (.blackOnMint, .buyNow, _), - (.blackOnWhite, .buyNow, _): - return .afterpayBuyNowBlackOnMint - - //CHECKOUT WITH AFTERPAY - case (.whiteOnBlack, .checkout, Locales.greatBritain), - (.mintOnBlack, .checkout, Locales.greatBritain): - return .clearpayCheckoutWhiteOnBlack - case (.blackOnMint, .checkout, Locales.greatBritain), - (.blackOnWhite, .checkout, Locales.greatBritain): - return .clearpayCheckoutBlackOnMint - - case (.mintOnBlack, .checkout, _), - (.whiteOnBlack, .checkout, _): - return .afterpayCheckoutWhiteOnBlack - case (.blackOnMint, .checkout, _), - (.blackOnWhite, .checkout, _): - return .afterpayCheckoutBlackOnMint - - //PAY NOW WITH AFTERPAY - case (.blackOnMint, .payNow, Locales.greatBritain): - return .clearpayPayNowBlackOnMint - case (.mintOnBlack, .payNow, Locales.greatBritain): - return .clearpayPayNowMintOnBlack - case (.whiteOnBlack, .payNow, Locales.greatBritain): - return .clearpayPayNowWhiteOnBlack - case (.blackOnWhite, .payNow, Locales.greatBritain): - return .clearpayPayNowBlackOnWhite - - case (.blackOnMint, .payNow, _): - return .afterpayPayNowBlackOnMint - case (.mintOnBlack, .payNow, _): - return .afterpayPayNowMintOnBlack - case (.whiteOnBlack, .payNow, _): - return .afterpayPayNowWhiteOnBlack - case (.blackOnWhite, .payNow, _): - return .afterpayPayNowBlackOnWhite - - //PLACE ORDER WITH AFTERPAY - case (.whiteOnBlack, .placeOrder, Locales.greatBritain), - (.mintOnBlack, .placeOrder, Locales.greatBritain): - return .clearpayPlaceOrderWhiteOnBlack - case (.blackOnMint, .placeOrder, Locales.greatBritain), - (.blackOnWhite, .placeOrder, Locales.greatBritain): - return .clearpayPlaceOrderBlackOnMint - - case (.mintOnBlack, .placeOrder, _), - (.whiteOnBlack, .placeOrder, _): - return .afterpayPlaceOrderWhiteOnBlack - case (.blackOnMint, .placeOrder, _), - (.blackOnWhite, .placeOrder, _): - return .afterpayPlaceOrderBlackOnMint + let svg: (ColorPalette, Locale) -> SVG + + switch buttonKind { + case .buyNow: + svg = SVG.buyNow(palette:locale:) + case .checkout: + svg = SVG.checkout(palette:locale:) + case .payNow: + svg = SVG.payNow(palette:locale:) + case .placeOrder: + svg = SVG.placeOrder(palette:locale:) } + + return svg(palette, locale) } func svg(localizedFor locale: Locale, withTraits traitCollection: UITraitCollection) -> SVG { From 0ae159dca36a39f972e95e04fb53710e0d472d72 Mon Sep 17 00:00:00 2001 From: Huw Rowlands Date: Mon, 10 May 2021 10:54:27 +1000 Subject: [PATCH 4/6] Add other button kinds to the readme --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 844aeeb6..7983d080 100644 --- a/README.md +++ b/README.md @@ -257,6 +257,13 @@ Below are examples of the button in each of the color schemes: | ![Black on Mint button][button-black-on-mint] | ![White on Black button][button-white-on-black] | | ![Mint on Black button][button-mint-on-black] | ![Black on White button][button-black-on-white] | +There are also a few other kinds of payment available, with different wording: + +* Buy Now +* Checkout +* Pay Now +* Place Order + ## Price Breakdown The price breakdown component displays information about Afterpay instalments and handles a number of common scenarios. From 99a64e2bbfc87ce7fa6eff590fcef7ec6fd260aa Mon Sep 17 00:00:00 2001 From: Huw Rowlands Date: Mon, 10 May 2021 10:58:40 +1000 Subject: [PATCH 5/6] Add more to the readme explaining PaymentButton --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7983d080..eaaf9963 100644 --- a/README.md +++ b/README.md @@ -249,7 +249,7 @@ Below are examples of the badge in each of the color schemes: ### Payment Button -The Afterpay Payment Button is a subclass of `UIButton` that can be scaled to suit your layout, to guarantee legibility it has a maximum width constraint of 256 points. +The Afterpay `PaymentButton` is a subclass of `UIButton` that can be scaled to suit your layout, to guarantee legibility it has a maximum width constraint of 256 points. Below are examples of the button in each of the color schemes: | Mint and Black | Black and White | @@ -264,6 +264,12 @@ There are also a few other kinds of payment available, with different wording: * Pay Now * Place Order +Using a `PaymentButton` is easy. Configure it with some parameters sent to its initialiser. These parameters are optional, however. + +```swift +let payButton = PaymentButton(colorScheme: .dynamic(lightPalette: .blackOnMint, darkPalette: .mintOnBlack), buttonKind: .checkout) +``` + ## Price Breakdown The price breakdown component displays information about Afterpay instalments and handles a number of common scenarios. From 6a8e6c7a1d8977683f5d86c9d00a21465371238d Mon Sep 17 00:00:00 2001 From: Huw Rowlands Date: Mon, 10 May 2021 11:10:36 +1000 Subject: [PATCH 6/6] Skip tokenless widget UI test It is flakey because it is using the real bootstrap and the real widget. We will have a better way to test this by using a mock bootstrap. Soon. --- Example/ExampleUITests/ExampleUITests.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Example/ExampleUITests/ExampleUITests.swift b/Example/ExampleUITests/ExampleUITests.swift index 22607681..9f4a522f 100644 --- a/Example/ExampleUITests/ExampleUITests.swift +++ b/Example/ExampleUITests/ExampleUITests.swift @@ -35,7 +35,8 @@ final class ExampleUITests: XCTestCase { app.buttons["Yes"].tap() } - func testTokenlessWidgetAppears() throws { + // Skipped while we come up with a better way to end to end test the bootstrap + func skip_testTokenlessWidgetAppears() throws { app.buttons["Tokenless…"].tap() XCTAssertTrue(app.staticTexts["Due today"].waitForExistence(timeout: 10))