diff --git a/RevenueCatUI/Data/TestData.swift b/RevenueCatUI/Data/TestData.swift index 820a46129d..afbd4a6075 100644 --- a/RevenueCatUI/Data/TestData.swift +++ b/RevenueCatUI/Data/TestData.swift @@ -8,6 +8,8 @@ import Foundation import RevenueCat +// swiftlint:disable type_body_length + #if DEBUG @available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *) @@ -167,13 +169,15 @@ internal enum TestData { background: "#FFFFFF", foreground: "#000000", callToActionBackground: "#EC807C", - callToActionForeground: "#FFFFFF" + callToActionForeground: "#FFFFFF", + accent1: "#BC66FF" ), dark: .init( background: "#000000", foreground: "#FFFFFF", callToActionBackground: "#ACD27A", - callToActionForeground: "#000000" + callToActionForeground: "#000000", + accent1: "#B022BB" ) ), blurredBackgroundImage: true, @@ -192,13 +196,17 @@ internal enum TestData { background: "#FFFFFF", foreground: "#000000", callToActionBackground: "#5CD27A", - callToActionForeground: "#FFFFFF" + callToActionForeground: "#FFFFFF", + accent1: "#BC66FF", + accent2: "#00FF00" ) static let darkColors: PaywallData.Configuration.Colors = .init( background: "#000000", foreground: "#FFFFFF", callToActionBackground: "#ACD27A", - callToActionForeground: "#000000" + callToActionForeground: "#000000", + accent1: "#B022BB", + accent2: "#FF00FF" ) #if canImport(SwiftUI) && canImport(UIKit) diff --git a/RevenueCatUI/Helpers/ColorInformation+MultiScheme.swift b/RevenueCatUI/Helpers/ColorInformation+MultiScheme.swift index 2df170cea7..fb7b43d11c 100644 --- a/RevenueCatUI/Helpers/ColorInformation+MultiScheme.swift +++ b/RevenueCatUI/Helpers/ColorInformation+MultiScheme.swift @@ -34,12 +34,26 @@ extension PaywallData.Configuration.Colors { background: .init(light: light.background, dark: dark.background), foreground: .init(light: light.foreground, dark: dark.foreground), callToActionBackground: .init(light: light.callToActionBackground, dark: dark.callToActionBackground), - callToActionForeground: .init(light: light.callToActionForeground, dark: dark.callToActionForeground) + callToActionForeground: .init(light: light.callToActionForeground, dark: dark.callToActionForeground), + accent1: .init(light: light.accent1, dark: dark.accent1), + accent2: .init(light: light.accent2, dark: dark.accent2) ) } } +@available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *) +private extension PaywallColor { + + /// Creates a dynamic color for 2 ``ColorScheme``s from 2 optional colors. + init?(light: PaywallColor?, dark: PaywallColor?) { + guard let light, let dark else { return nil } + + self.init(light: light, dark: dark) + } + +} + #else extension PaywallData.Configuration.ColorInformation { @@ -66,6 +80,8 @@ extension PaywallData.Configuration.Colors { var foregroundColor: Color { self.foreground.underlyingColor } var callToActionBackgroundColor: Color { self.callToActionBackground.underlyingColor } var callToActionForegroundColor: Color { self.callToActionForeground.underlyingColor } + var accent1Color: Color { self.accent1.underlyingColor } + var accent2Color: Color { self.accent2?.underlyingColor ?? self.accent1Color } } diff --git a/RevenueCatUI/Helpers/PaywallData+Default.swift b/RevenueCatUI/Helpers/PaywallData+Default.swift index 64e8b1005d..e999471f89 100644 --- a/RevenueCatUI/Helpers/PaywallData+Default.swift +++ b/RevenueCatUI/Helpers/PaywallData+Default.swift @@ -37,13 +37,15 @@ private extension PaywallData { background: try! .init(stringRepresentation: "#FFFFFF"), foreground: try! .init(stringRepresentation: "#000000"), callToActionBackground: try! .init(stringRepresentation: "#EC807C"), - callToActionForeground: try! .init(stringRepresentation: "#FFFFFF") + callToActionForeground: try! .init(stringRepresentation: "#FFFFFF"), + accent1: try! .init(stringRepresentation: "#EC807C") ), dark: .init( background: try! .init(stringRepresentation: "#000000"), foreground: try! .init(stringRepresentation: "#FFFFFF"), callToActionBackground: try! .init(stringRepresentation: "#ACD27A"), - callToActionForeground: try! .init(stringRepresentation: "#000000") + callToActionForeground: try! .init(stringRepresentation: "#000000"), + accent1: try! .init(stringRepresentation: "#ACD27A") ) ) // swiftlint:enable force_try diff --git a/RevenueCatUI/Templates/MultiPackageTemplate.swift b/RevenueCatUI/Templates/MultiPackageTemplate.swift index 4434186567..75188a2cbd 100644 --- a/RevenueCatUI/Templates/MultiPackageTemplate.swift +++ b/RevenueCatUI/Templates/MultiPackageTemplate.swift @@ -136,15 +136,19 @@ private struct MultiPackageTemplateContent: View { VStack(alignment: alignment.horizontal, spacing: 5) { HStack { Image(systemName: "checkmark.circle.fill") - .foregroundColor( - selected - ? self.configuration.colors.callToActionBackgroundColor - : .gray - ) + .hidden(if: !selected) + .overlay { + if selected { + EmptyView() + } else { + Circle() + .foregroundColor(Self.selectedBackgroundColor.opacity(0.5)) + } + } Text(self.localization(for: package.content).offerName ?? package.content.productName) } - .foregroundColor(self.configuration.colors.callToActionBackgroundColor) + .foregroundColor(self.configuration.colors.accent1Color) IntroEligibilityStateView( textWithNoIntroOffer: package.localization.offerDetails, @@ -165,7 +169,11 @@ private struct MultiPackageTemplateContent: View { .foregroundColor(self.configuration.colors.foregroundColor) .background { RoundedRectangle(cornerRadius: 15, style: .continuous) - .foregroundColor(selected ? .black : .init(white: 0.8)) + .foregroundColor( + selected + ? Self.selectedBackgroundColor + : .clear + ) } } @@ -213,6 +221,15 @@ private struct MultiPackageTemplateContent: View { private static let iconSize: CGFloat = 100 + #if !os(macOS) && !os(watchOS) + private static let selectedBackgroundColor: Color = .init( + light: .init(white: 0.3), + dark: .init(white: 0.6) + ) + #else + private static let selectedBackgroundColor: Color = .init(white: 0.3) + #endif + } // MARK: - Extensions diff --git a/RevenueCatUI/Views/FooterView.swift b/RevenueCatUI/Views/FooterView.swift index 425afab8bd..fd0d8b6f0d 100644 --- a/RevenueCatUI/Views/FooterView.swift +++ b/RevenueCatUI/Views/FooterView.swift @@ -115,7 +115,7 @@ private struct LinkButton: View { } -#if DEBUG +#if DEBUG && canImport(SwiftUI) && canImport(UIKit) @available(iOS 16.0, macOS 13.0, tvOS 16.0, *) @available(watchOS, unavailable) diff --git a/Sources/Paywalls/PaywallColor.swift b/Sources/Paywalls/PaywallColor.swift index 63229d73d5..e82bebafc0 100644 --- a/Sources/Paywalls/PaywallColor.swift +++ b/Sources/Paywalls/PaywallColor.swift @@ -191,8 +191,9 @@ private extension Color { } @available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *) -private extension Color { +public extension Color { + /// Creates a `Color` given a light and a dark `Color`. init(light: Color, dark: Color) { self.init(light: UIColor(light), dark: UIColor(dark)) } diff --git a/Sources/Paywalls/PaywallData.swift b/Sources/Paywalls/PaywallData.swift index 7c39f3b2b0..df653a5377 100644 --- a/Sources/Paywalls/PaywallData.swift +++ b/Sources/Paywalls/PaywallData.swift @@ -275,18 +275,26 @@ extension PaywallData.Configuration { public var callToActionBackground: PaywallColor /// Foreground color of the main call to action button. public var callToActionForeground: PaywallColor + /// Primary accent color. + public var accent1: PaywallColor + /// Secondary accent color + public var accent2: PaywallColor? // swiftlint:disable:next missing_docs public init( background: PaywallColor, foreground: PaywallColor, callToActionBackground: PaywallColor, - callToActionForeground: PaywallColor + callToActionForeground: PaywallColor, + accent1: PaywallColor, + accent2: PaywallColor? = nil ) { self.background = background self.foreground = foreground self.callToActionBackground = callToActionBackground self.callToActionForeground = callToActionForeground + self.accent1 = accent1 + self.accent2 = accent2 } } diff --git a/Tests/APITesters/SwiftAPITester/SwiftAPITester/PaywallAPI.swift b/Tests/APITesters/SwiftAPITester/SwiftAPITester/PaywallAPI.swift index ee313d4d6b..8fbf3e2a23 100644 --- a/Tests/APITesters/SwiftAPITester/SwiftAPITester/PaywallAPI.swift +++ b/Tests/APITesters/SwiftAPITester/SwiftAPITester/PaywallAPI.swift @@ -88,12 +88,16 @@ func checkPaywallColors(_ config: PaywallData.Configuration.Colors) { let foreground: PaywallColor = config.foreground let callToActionBackground: PaywallColor = config.callToActionBackground let callToActionForeground: PaywallColor = config.callToActionForeground + let accent1: PaywallColor = config.accent1 + let accent2: PaywallColor? = config.accent2 _ = PaywallData.Configuration.Colors( background: background, foreground: foreground, callToActionBackground: callToActionBackground, - callToActionForeground: callToActionForeground + callToActionForeground: callToActionForeground, + accent1: accent1, + accent2: accent2 ) } diff --git a/Tests/RevenueCatUITests/PaywallViewLocalizationTests.swift b/Tests/RevenueCatUITests/PaywallViewLocalizationTests.swift index e7005a04ac..eeceab6237 100644 --- a/Tests/RevenueCatUITests/PaywallViewLocalizationTests.swift +++ b/Tests/RevenueCatUITests/PaywallViewLocalizationTests.swift @@ -58,18 +58,8 @@ import SwiftUI packages: [.weekly, .annual, .monthly], images: TestData.images, colors: .init( - light: .init( - background: "#FFFFFF", - foreground: "#000000", - callToActionBackground: "#EC807C", - callToActionForeground: "#FFFFFF" - ), - dark: .init( - background: "#000000", - foreground: "#FFFFFF", - callToActionBackground: "#ACD27A", - callToActionForeground: "#000000" - ) + light: TestData.lightColors, + dark: TestData.lightColors ), termsOfServiceURL: URL(string: "https://revenuecat.com/tos")!, privacyURL: URL(string: "https://revenuecat.com/tos")! diff --git a/Tests/RevenueCatUITests/__Snapshots__/MultiPackagePaywallViewTests/iOS16-testDarkMode.1.png b/Tests/RevenueCatUITests/__Snapshots__/MultiPackagePaywallViewTests/iOS16-testDarkMode.1.png index b6135f63f7..2078999104 100644 Binary files a/Tests/RevenueCatUITests/__Snapshots__/MultiPackagePaywallViewTests/iOS16-testDarkMode.1.png and b/Tests/RevenueCatUITests/__Snapshots__/MultiPackagePaywallViewTests/iOS16-testDarkMode.1.png differ diff --git a/Tests/RevenueCatUITests/__Snapshots__/MultiPackagePaywallViewTests/iOS16-testSamplePaywall.1.png b/Tests/RevenueCatUITests/__Snapshots__/MultiPackagePaywallViewTests/iOS16-testSamplePaywall.1.png index 9efff9c693..f463696087 100644 Binary files a/Tests/RevenueCatUITests/__Snapshots__/MultiPackagePaywallViewTests/iOS16-testSamplePaywall.1.png and b/Tests/RevenueCatUITests/__Snapshots__/MultiPackagePaywallViewTests/iOS16-testSamplePaywall.1.png differ diff --git a/Tests/RevenueCatUITests/__Snapshots__/OtherPaywallViewTests/iOS16-testDefaultPaywall.1.png b/Tests/RevenueCatUITests/__Snapshots__/OtherPaywallViewTests/iOS16-testDefaultPaywall.1.png index 33e49d2d87..25765bc5f6 100644 Binary files a/Tests/RevenueCatUITests/__Snapshots__/OtherPaywallViewTests/iOS16-testDefaultPaywall.1.png and b/Tests/RevenueCatUITests/__Snapshots__/OtherPaywallViewTests/iOS16-testDefaultPaywall.1.png differ diff --git a/Tests/RevenueCatUITests/__Snapshots__/OtherPaywallViewTests/iOS16-testLoadingPaywallView.1.png b/Tests/RevenueCatUITests/__Snapshots__/OtherPaywallViewTests/iOS16-testLoadingPaywallView.1.png index 830afcb99d..76cb8797a5 100644 Binary files a/Tests/RevenueCatUITests/__Snapshots__/OtherPaywallViewTests/iOS16-testLoadingPaywallView.1.png and b/Tests/RevenueCatUITests/__Snapshots__/OtherPaywallViewTests/iOS16-testLoadingPaywallView.1.png differ diff --git a/Tests/RevenueCatUITests/__Snapshots__/PaywallViewLocalizationTests/iOS16-testSpanish.1.png b/Tests/RevenueCatUITests/__Snapshots__/PaywallViewLocalizationTests/iOS16-testSpanish.1.png index 174d754913..3bc2c4be2a 100644 Binary files a/Tests/RevenueCatUITests/__Snapshots__/PaywallViewLocalizationTests/iOS16-testSpanish.1.png and b/Tests/RevenueCatUITests/__Snapshots__/PaywallViewLocalizationTests/iOS16-testSpanish.1.png differ diff --git a/Tests/UnitTests/Networking/Responses/Fixtures/Offerings.json b/Tests/UnitTests/Networking/Responses/Fixtures/Offerings.json index 1bb08ce702..11353b4f32 100644 --- a/Tests/UnitTests/Networking/Responses/Fixtures/Offerings.json +++ b/Tests/UnitTests/Networking/Responses/Fixtures/Offerings.json @@ -69,7 +69,8 @@ "background": "#FF00AA", "foreground": "#FF00AA22", "call_to_action_background": "#FF00AACC", - "call_to_action_foreground": "#FF00AA" + "call_to_action_foreground": "#FF00AA", + "accent_1": "#FF0000" }, "dark": null } diff --git a/Tests/UnitTests/Networking/Responses/Fixtures/PaywallData-Sample1.json b/Tests/UnitTests/Networking/Responses/Fixtures/PaywallData-Sample1.json index 1f888bf7d4..6e02fffe77 100644 --- a/Tests/UnitTests/Networking/Responses/Fixtures/PaywallData-Sample1.json +++ b/Tests/UnitTests/Networking/Responses/Fixtures/PaywallData-Sample1.json @@ -37,13 +37,17 @@ "background": "#FF00AA", "foreground": "#FF00AA22", "call_to_action_background": "#FF00AACC", - "call_to_action_foreground": "#FF00AA" + "call_to_action_foreground": "#FF00AA", + "accent_1": "#FF0000", + "accent_2": "#00FF00" }, "dark": { "background": "#FF0000", "foreground": "#1100FFAA", "call_to_action_background": "#112233AA", - "call_to_action_foreground": "#AABBCC" + "call_to_action_foreground": "#AABBCC", + "accent_1": "#00FFFF", + "accent_2": "#FF00FF" } } }, diff --git a/Tests/UnitTests/Networking/Responses/Fixtures/PaywallData-missing_current_and_default_locale.json b/Tests/UnitTests/Networking/Responses/Fixtures/PaywallData-missing_current_and_default_locale.json index 958ee13280..b98c6c6dab 100644 --- a/Tests/UnitTests/Networking/Responses/Fixtures/PaywallData-missing_current_and_default_locale.json +++ b/Tests/UnitTests/Networking/Responses/Fixtures/PaywallData-missing_current_and_default_locale.json @@ -19,7 +19,8 @@ "background": "#FFFFFF", "foreground": "#FFFFFF", "call_to_action_background": "#FFFFFF", - "call_to_action_foreground": "#FFFFFF" + "call_to_action_foreground": "#FFFFFF", + "accent_1": "#FFFFFF" }, "dark": null } diff --git a/Tests/UnitTests/Networking/Responses/Fixtures/PaywallData-missing_current_locale.json b/Tests/UnitTests/Networking/Responses/Fixtures/PaywallData-missing_current_locale.json index 43f41c0c6b..36ff8d42fd 100644 --- a/Tests/UnitTests/Networking/Responses/Fixtures/PaywallData-missing_current_locale.json +++ b/Tests/UnitTests/Networking/Responses/Fixtures/PaywallData-missing_current_locale.json @@ -19,7 +19,8 @@ "background": "#FFFFFF", "foreground": "#FFFFFF", "call_to_action_background": "#FFFFFF", - "call_to_action_foreground": "#FFFFFF" + "call_to_action_foreground": "#FFFFFF", + "accent_1": "#FFFFFF" }, "dark": null } diff --git a/Tests/UnitTests/Paywalls/PaywallDataTests.swift b/Tests/UnitTests/Paywalls/PaywallDataTests.swift index fb13bcce44..7bbb6963e5 100644 --- a/Tests/UnitTests/Paywalls/PaywallDataTests.swift +++ b/Tests/UnitTests/Paywalls/PaywallDataTests.swift @@ -48,11 +48,15 @@ class PaywallDataTests: BaseHTTPResponseTest { expect(paywall.config.colors.light.foreground.stringRepresentation) == "#FF00AA22" expect(paywall.config.colors.light.callToActionBackground.stringRepresentation) == "#FF00AACC" expect(paywall.config.colors.light.callToActionForeground.stringRepresentation) == "#FF00AA" + expect(paywall.config.colors.light.accent1.stringRepresentation) == "#FF0000" + expect(paywall.config.colors.light.accent2?.stringRepresentation) == "#00FF00" expect(paywall.config.colors.dark?.background.stringRepresentation) == "#FF0000" expect(paywall.config.colors.dark?.foreground.stringRepresentation) == "#1100FFAA" expect(paywall.config.colors.dark?.callToActionBackground.stringRepresentation) == "#112233AA" expect(paywall.config.colors.dark?.callToActionForeground.stringRepresentation) == "#AABBCC" + expect(paywall.config.colors.dark?.accent1.stringRepresentation) == "#00FFFF" + expect(paywall.config.colors.dark?.accent2?.stringRepresentation) == "#FF00FF" let enConfig = try XCTUnwrap(paywall.config(for: Locale(identifier: "en_US"))) expect(enConfig.title) == "Paywall"