diff --git a/Afterpay.xcodeproj/project.pbxproj b/Afterpay.xcodeproj/project.pbxproj index 3c2d9cc1..2883feee 100644 --- a/Afterpay.xcodeproj/project.pbxproj +++ b/Afterpay.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 6615F99B24D14620005036F1 /* SVG.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6615F99A24D14620005036F1 /* SVG.swift */; }; + 661B233224DA8EE70010EBCD /* ColorScheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 661B233124DA8EE70010EBCD /* ColorScheme.swift */; }; 662A3AED24A999A500EFD826 /* CheckoutResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 662A3AEC24A999A500EFD826 /* CheckoutResult.swift */; }; 6635B95F24CAA9F000EBB3A6 /* ConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6635B95E24CAA9F000EBB3A6 /* ConfigurationTests.swift */; }; 6640C15224D8E1A700F7F4CC /* Macaw in Frameworks */ = {isa = PBXBuildFile; productRef = 6640C15124D8E1A700F7F4CC /* Macaw */; }; @@ -35,6 +36,7 @@ /* Begin PBXFileReference section */ 6615F99A24D14620005036F1 /* SVG.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SVG.swift; sourceTree = ""; }; + 661B233124DA8EE70010EBCD /* ColorScheme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorScheme.swift; sourceTree = ""; }; 662A3AEC24A999A500EFD826 /* CheckoutResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckoutResult.swift; sourceTree = ""; }; 6632E0AE248A0171007F0BD9 /* Package.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; }; 6635B95E24CAA9F000EBB3A6 /* ConfigurationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationTests.swift; sourceTree = ""; }; @@ -84,6 +86,25 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 661B232F24DA87C50010EBCD /* SVG */ = { + isa = PBXGroup; + children = ( + 6615F99A24D14620005036F1 /* SVG.swift */, + 66639B5324D2619200C68558 /* SVGView.swift */, + ); + path = SVG; + sourceTree = ""; + }; + 661B233024DA87EA0010EBCD /* Views */ = { + isa = PBXGroup; + children = ( + 66EE378624D39FC50029BF42 /* BadgeView.swift */, + 661B233124DA8EE70010EBCD /* ColorScheme.swift */, + 66483F3A24D7A164000BE6B5 /* PriceBreakdownView.swift */, + ); + path = Views; + sourceTree = ""; + }; 6632E0AD248A015E007F0BD9 /* Deployment */ = { isa = PBXGroup; children = ( @@ -92,6 +113,15 @@ name = Deployment; sourceTree = ""; }; + 663F96AA24DA906800B0643A /* Wrappers */ = { + isa = PBXGroup; + children = ( + 666D334B24A48F5C00FCD464 /* ObjcWrapper.swift */, + 66D685B124BD3FB900C7287C /* SwiftUIWrapper.swift */, + ); + path = Wrappers; + sourceTree = ""; + }; 6640C15524D9211700F7F4CC /* Frameworks */ = { isa = PBXGroup; children = ( @@ -155,15 +185,12 @@ isa = PBXGroup; children = ( 66F9767B2499A11A001D38FA /* Afterpay.swift */, - 66EE378624D39FC50029BF42 /* BadgeView.swift */, 662A3AEC24A999A500EFD826 /* CheckoutResult.swift */, 6689536B24C96CB5005090B4 /* Configuration.swift */, - 666D334B24A48F5C00FCD464 /* ObjcWrapper.swift */, - 66483F3A24D7A164000BE6B5 /* PriceBreakdownView.swift */, - 6615F99A24D14620005036F1 /* SVG.swift */, - 66639B5324D2619200C68558 /* SVGView.swift */, - 66D685B124BD3FB900C7287C /* SwiftUIWrapper.swift */, + 661B232F24DA87C50010EBCD /* SVG */, + 661B233024DA87EA0010EBCD /* Views */, 667AD3532497121100BF94E5 /* WebViewController.swift */, + 663F96AA24DA906800B0643A /* Wrappers */, ); name = Sources; path = Afterpay; @@ -349,6 +376,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 661B233224DA8EE70010EBCD /* ColorScheme.swift in Sources */, 66639B5424D2619200C68558 /* SVGView.swift in Sources */, 6615F99B24D14620005036F1 /* SVG.swift in Sources */, 66483F3B24D7A164000BE6B5 /* PriceBreakdownView.swift in Sources */, diff --git a/Example/Example/Components/ComponentsViewController.swift b/Example/Example/Components/ComponentsViewController.swift index f534ab94..c6bbe42f 100644 --- a/Example/Example/Components/ComponentsViewController.swift +++ b/Example/Example/Components/ComponentsViewController.swift @@ -78,7 +78,7 @@ final class ComponentsViewController: UIViewController { titleLabel.font = .preferredFont(forTextStyle: .title1) stack.addArrangedSubview(titleLabel) - let badge = BadgeView(lightStyle: .whiteOnBlack, darkStyle: .blackOnWhite) + let badge = BadgeView() badge.widthAnchor.constraint(equalToConstant: 64).isActive = true let badgeStack = UIStackView(arrangedSubviews: [badge, UIView()]) diff --git a/Sources/Afterpay/SVG.swift b/Sources/Afterpay/SVG.swift deleted file mode 100644 index 5830ddfd..00000000 --- a/Sources/Afterpay/SVG.swift +++ /dev/null @@ -1,56 +0,0 @@ -// -// SVG.swift -// Afterpay -// -// Created by Adam Campbell on 29/7/20. -// Copyright © 2020 Afterpay. All rights reserved. -// - -import Foundation -#if compiler(>=5.1) && compiler(<5.3) -@_implementationOnly import Macaw -#else -import Macaw -#endif -import UIKit - -// swiftlint:disable line_length -struct SVG: Equatable { - - let size: CGSize - let minimumWidth: CGFloat - private let svgString: String - - var aspectRatio: CGFloat { size.height / size.width } - var node: Node { (try? SVGParser.parse(text: svgString)) ?? Group() } - - init(size: CGSize, minimumWidth: CGFloat, svgString: String) { - self.size = size - self.minimumWidth = minimumWidth - self.svgString = svgString - } - - static let badgeWhiteOnBlack: SVG = SVG( - size: CGSize(width: 1582, height: 551), - minimumWidth: 64, - svgString: """ - - - - - """ - ) - - static let badgeBlackOnWhite: SVG = SVG( - size: CGSize(width: 1582, height: 551), - minimumWidth: 64, - svgString: """ - - - - - """ - ) - -} -// swiftlint:enable line_length diff --git a/Sources/Afterpay/SVG/SVG.swift b/Sources/Afterpay/SVG/SVG.swift new file mode 100644 index 00000000..e38f48d5 --- /dev/null +++ b/Sources/Afterpay/SVG/SVG.swift @@ -0,0 +1,139 @@ +// +// SVG.swift +// Afterpay +// +// Created by Adam Campbell on 29/7/20. +// Copyright © 2020 Afterpay. All rights reserved. +// + +import Foundation +#if compiler(>=5.1) && compiler(<5.3) +@_implementationOnly import Macaw +#else +import Macaw +#endif +import UIKit + +// swiftlint:disable line_length +struct SVG: Equatable { + + let size: CGSize + let minimumWidth: CGFloat + private let svgString: String + + var aspectRatio: CGFloat { size.height / size.width } + var node: Node { (try? SVGParser.parse(text: svgString)) ?? Group() } + + init(size: CGSize, minimumWidth: CGFloat, svgString: String) { + self.size = size + self.minimumWidth = minimumWidth + self.svgString = svgString + } + + static let badgeBlackOnMint = SVG( + size: CGSize(width: 1582, height: 551), + minimumWidth: 64, + svgString: """ + + + + + + + + + + + + + + + + + + + """ + ) + + static let badgeMintOnBlack = SVG( + size: CGSize(width: 1582, height: 551), + minimumWidth: 64, + svgString: """ + + + + + + + + + + + + + + + + + + + """ + ) + + static let badgeWhiteOnBlack: SVG = SVG( + size: CGSize(width: 1582, height: 551), + minimumWidth: 64, + svgString: """ + + + + + + + + + + + + + + + + + + + """ + ) + + static let badgeBlackOnWhite: SVG = SVG( + size: CGSize(width: 1582, height: 551), + minimumWidth: 64, + svgString: """ + + + + + + + + + + + + + + + + + + + """ + ) + +} + +struct SVGPair { + let lightSVG: SVG + let darkSVG: SVG +} +// swiftlint:enable line_length diff --git a/Sources/Afterpay/SVGView.swift b/Sources/Afterpay/SVG/SVGView.swift similarity index 87% rename from Sources/Afterpay/SVGView.swift rename to Sources/Afterpay/SVG/SVGView.swift index 14800cf2..3fa43e86 100644 --- a/Sources/Afterpay/SVGView.swift +++ b/Sources/Afterpay/SVG/SVGView.swift @@ -18,16 +18,10 @@ final class SVGView: Macaw.SVGView { var svg: SVG { svg(for: traitCollection) } - private let lightSVG: SVG - private let darkSVG: SVG + private let svgPair: SVGPair - convenience init(svg: SVG) { - self.init(lightSVG: svg, darkSVG: svg) - } - - init(lightSVG: SVG, darkSVG: SVG) { - self.lightSVG = lightSVG - self.darkSVG = darkSVG + init(svgPair: SVGPair) { + self.svgPair = svgPair super.init(frame: .zero) @@ -54,11 +48,11 @@ final class SVGView: Macaw.SVGView { private func svg(for traitCollection: UITraitCollection) -> SVG { switch traitCollection.userInterfaceStyle { case .dark: - return darkSVG + return svgPair.darkSVG case .light, .unspecified: fallthrough @unknown default: - return lightSVG + return svgPair.lightSVG } } diff --git a/Sources/Afterpay/BadgeView.swift b/Sources/Afterpay/Views/BadgeView.swift similarity index 57% rename from Sources/Afterpay/BadgeView.swift rename to Sources/Afterpay/Views/BadgeView.swift index de23b42f..622cdd0a 100644 --- a/Sources/Afterpay/BadgeView.swift +++ b/Sources/Afterpay/Views/BadgeView.swift @@ -11,31 +11,11 @@ import UIKit public final class BadgeView: UIView { - public enum Style { - case whiteOnBlack, blackOnWhite - - var svg: SVG { - switch self { - case .whiteOnBlack: - return .badgeWhiteOnBlack - case .blackOnWhite: - return .badgeBlackOnWhite - } - } - } - - private let lightStyle: Style - private let darkStyle: Style - + private let colorScheme: ColorScheme private var svgView: SVGView! - public convenience init(style: Style) { - self.init(lightStyle: style, darkStyle: style) - } - - public init(lightStyle: Style, darkStyle: Style) { - self.lightStyle = lightStyle - self.darkStyle = darkStyle + public init(colorScheme: ColorScheme = .static(.blackOnMint)) { + self.colorScheme = colorScheme super.init(frame: .zero) @@ -43,8 +23,7 @@ public final class BadgeView: UIView { } required init?(coder: NSCoder) { - self.lightStyle = .whiteOnBlack - self.darkStyle = .blackOnWhite + self.colorScheme = .static(.blackOnMint) super.init(coder: coder) @@ -58,7 +37,7 @@ public final class BadgeView: UIView { accessibilityLabel = "after pay" // SVG Layout - svgView = SVGView(lightSVG: lightStyle.svg, darkSVG: darkStyle.svg) + svgView = SVGView(svgPair: colorScheme.badgeSVGPair) addSubview(svgView) diff --git a/Sources/Afterpay/Views/ColorScheme.swift b/Sources/Afterpay/Views/ColorScheme.swift new file mode 100644 index 00000000..780ea233 --- /dev/null +++ b/Sources/Afterpay/Views/ColorScheme.swift @@ -0,0 +1,56 @@ +// +// BadgeStyle.swift +// Afterpay +// +// Created by Adam Campbell on 5/8/20. +// Copyright © 2020 Afterpay. All rights reserved. +// + +import Foundation + +public enum ColorScheme { + case `static`(ColorPalette) + case dynamic(lightPalette: ColorPalette, darkPalette: ColorPalette) + + var lightPalette: ColorPalette { + switch self { + case .static(let palette): + return palette + case .dynamic(let lightPalette, _): + return lightPalette + } + } + + var darkPalette: ColorPalette { + switch self { + case .static(let palette): + return palette + case .dynamic(_, let darkPalette): + return darkPalette + } + } + + var badgeSVGPair: SVGPair { + let svg: (ColorPalette) -> SVG = { palette in + switch palette { + case .blackOnMint: + return .badgeBlackOnMint + case .mintOnBlack: + return .badgeMintOnBlack + case .whiteOnBlack: + return .badgeWhiteOnBlack + case .blackOnWhite: + return .badgeBlackOnWhite + } + } + + return SVGPair(lightSVG: svg(lightPalette), darkSVG: svg(darkPalette)) + } +} + +public enum ColorPalette { + case blackOnMint + case mintOnBlack + case whiteOnBlack + case blackOnWhite +} diff --git a/Sources/Afterpay/PriceBreakdownView.swift b/Sources/Afterpay/Views/PriceBreakdownView.swift similarity index 84% rename from Sources/Afterpay/PriceBreakdownView.swift rename to Sources/Afterpay/Views/PriceBreakdownView.swift index 7cb65c4e..9d3099d2 100644 --- a/Sources/Afterpay/PriceBreakdownView.swift +++ b/Sources/Afterpay/Views/PriceBreakdownView.swift @@ -12,14 +12,19 @@ import UIKit public final class PriceBreakdownView: UIView { private let label = UILabel() + private let colorScheme: ColorScheme + + public init(colorScheme: ColorScheme = .static(.blackOnMint)) { + self.colorScheme = colorScheme - public init() { super.init(frame: .zero) sharedInit() } required init?(coder: NSCoder) { + self.colorScheme = .static(.blackOnMint) + super.init(coder: coder) sharedInit() @@ -48,8 +53,8 @@ public final class PriceBreakdownView: UIView { } private func updateAttributedText() { - let svgView = SVGView(lightSVG: .badgeWhiteOnBlack, darkSVG: .badgeBlackOnWhite) - let svg = svgView.svg + let badgeSVGView = SVGView(svgPair: colorScheme.badgeSVGPair) + let svg = badgeSVGView.svg let font: UIFont = .preferredFont(forTextStyle: .body) let fontHeight = font.ascender - font.descender @@ -58,11 +63,11 @@ public final class PriceBreakdownView: UIView { let width = widthFittingFont > svg.minimumWidth ? widthFittingFont : svg.minimumWidth let size = CGSize(width: width, height: width * svg.aspectRatio) - svgView.frame = CGRect(origin: .zero, size: size) + badgeSVGView.frame = CGRect(origin: .zero, size: size) - let renderer = UIGraphicsImageRenderer(size: svgView.bounds.size) + let renderer = UIGraphicsImageRenderer(size: badgeSVGView.bounds.size) let image = renderer.image { rendererContext in - svgView.layer.render(in: rendererContext.cgContext) + badgeSVGView.layer.render(in: rendererContext.cgContext) } let attributedString = NSMutableAttributedString( diff --git a/Sources/Afterpay/ObjcWrapper.swift b/Sources/Afterpay/Wrappers/ObjcWrapper.swift similarity index 100% rename from Sources/Afterpay/ObjcWrapper.swift rename to Sources/Afterpay/Wrappers/ObjcWrapper.swift diff --git a/Sources/Afterpay/SwiftUIWrapper.swift b/Sources/Afterpay/Wrappers/SwiftUIWrapper.swift similarity index 100% rename from Sources/Afterpay/SwiftUIWrapper.swift rename to Sources/Afterpay/Wrappers/SwiftUIWrapper.swift