diff --git a/android/api-tests/src/test/java/com/revenuecat/apitests/java/PaywallApiTests.java b/android/api-tests/src/test/java/com/revenuecat/apitests/java/PaywallApiTests.java index a776d6af..866ef8cb 100644 --- a/android/api-tests/src/test/java/com/revenuecat/apitests/java/PaywallApiTests.java +++ b/android/api-tests/src/test/java/com/revenuecat/apitests/java/PaywallApiTests.java @@ -21,7 +21,8 @@ public void onPaywallResult(@NonNull PaywallResult paywallResult) { private void checkPresentPaywall( FragmentActivity fragmentActivity, String requiredEntitlementIdentifier, - PaywallResultListener listener + PaywallResultListener listener, + Boolean shouldDisplayDismissButton ) { PaywallHelpersKt.presentPaywallFromFragment( fragmentActivity @@ -32,5 +33,8 @@ private void checkPresentPaywall( PaywallHelpersKt.presentPaywallFromFragment( fragmentActivity, requiredEntitlementIdentifier, listener ); + PaywallHelpersKt.presentPaywallFromFragment( + fragmentActivity, requiredEntitlementIdentifier, listener, shouldDisplayDismissButton + ); } } diff --git a/android/api-tests/src/test/java/com/revenuecat/apitests/kotlin/PaywallApiTests.kt b/android/api-tests/src/test/java/com/revenuecat/apitests/kotlin/PaywallApiTests.kt index 17a485bd..17868f5a 100644 --- a/android/api-tests/src/test/java/com/revenuecat/apitests/kotlin/PaywallApiTests.kt +++ b/android/api-tests/src/test/java/com/revenuecat/apitests/kotlin/PaywallApiTests.kt @@ -21,6 +21,7 @@ private class PaywallApiTests { fragmentActivity: FragmentActivity, requiredEntitlementIdentifier: String?, paywallResultListener: PaywallResultListener?, + shouldDisplayDismissButton: Boolean?, ) { presentPaywallFromFragment( fragment = fragmentActivity, @@ -34,5 +35,11 @@ private class PaywallApiTests { requiredEntitlementIdentifier = requiredEntitlementIdentifier, paywallResultListener = paywallResultListener, ) + presentPaywallFromFragment( + fragment = fragmentActivity, + requiredEntitlementIdentifier = requiredEntitlementIdentifier, + paywallResultListener = paywallResultListener, + shouldDisplayDismissButton = shouldDisplayDismissButton, + ) } } diff --git a/android/hybridcommon-ui/src/main/java/com/revenuecat/purchases/hybridcommon/ui/PaywallFragment.kt b/android/hybridcommon-ui/src/main/java/com/revenuecat/purchases/hybridcommon/ui/PaywallFragment.kt index 0ebe4b46..411b5f27 100644 --- a/android/hybridcommon-ui/src/main/java/com/revenuecat/purchases/hybridcommon/ui/PaywallFragment.kt +++ b/android/hybridcommon-ui/src/main/java/com/revenuecat/purchases/hybridcommon/ui/PaywallFragment.kt @@ -13,6 +13,7 @@ import com.revenuecat.purchases.ui.revenuecatui.activity.PaywallResultHandler internal class PaywallFragment : Fragment(), PaywallResultHandler { companion object { private const val requiredEntitlementIdentifierKey = "requiredEntitlementIdentifier" + private const val shouldDisplayDismissButtonKey = "shouldDisplayDismissButton" const val tag: String = "revenuecat-paywall-fragment" @JvmStatic @@ -20,12 +21,14 @@ internal class PaywallFragment : Fragment(), PaywallResultHandler { activity: FragmentActivity, requiredEntitlementIdentifier: String? = null, paywallResultListener: PaywallResultListener? = null, + shouldDisplayDismissButton: Boolean? = null, ): PaywallFragment { val paywallFragmentViewModel = ViewModelProvider(activity)[PaywallFragmentViewModel::class.java] paywallFragmentViewModel.paywallResultListener = paywallResultListener return PaywallFragment().apply { arguments = Bundle().apply { putString(requiredEntitlementIdentifierKey, requiredEntitlementIdentifier) + shouldDisplayDismissButton?.let { putBoolean(shouldDisplayDismissButtonKey, it) } } } } @@ -37,6 +40,9 @@ internal class PaywallFragment : Fragment(), PaywallResultHandler { private val requiredEntitlementIdentifier: String? get() = arguments?.getString(requiredEntitlementIdentifierKey) + private val shouldDisplayDismissButton: Boolean? + get() = arguments?.getBoolean(shouldDisplayDismissButtonKey) + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -46,12 +52,27 @@ internal class PaywallFragment : Fragment(), PaywallResultHandler { ) viewModel = ViewModelProvider(requireActivity())[PaywallFragmentViewModel::class.java] - requiredEntitlementIdentifier?.let { - launcher.launchIfNeeded(requiredEntitlementIdentifier = it) - } ?: launcher.launch() + requiredEntitlementIdentifier?.let { requiredEntitlementIdentifier -> + launchPaywallIfNeeded(requiredEntitlementIdentifier) + } ?: launchPaywall() } override fun onActivityResult(result: PaywallResult) { viewModel.paywallResultListener?.onPaywallResult(result) } + + private fun launchPaywallIfNeeded(requiredEntitlementIdentifier: String) { + shouldDisplayDismissButton?.let { shouldDisplayDismissButton -> + launcher.launchIfNeeded( + requiredEntitlementIdentifier = requiredEntitlementIdentifier, + shouldDisplayDismissButton = shouldDisplayDismissButton, + ) + } ?: launcher.launchIfNeeded(requiredEntitlementIdentifier = requiredEntitlementIdentifier) + } + + private fun launchPaywall() { + shouldDisplayDismissButton?.let { + launcher.launch(shouldDisplayDismissButton = it) + } ?: launcher.launch() + } } diff --git a/android/hybridcommon-ui/src/main/java/com/revenuecat/purchases/hybridcommon/ui/PaywallHelpers.kt b/android/hybridcommon-ui/src/main/java/com/revenuecat/purchases/hybridcommon/ui/PaywallHelpers.kt index abd9ec91..d494e906 100644 --- a/android/hybridcommon-ui/src/main/java/com/revenuecat/purchases/hybridcommon/ui/PaywallHelpers.kt +++ b/android/hybridcommon-ui/src/main/java/com/revenuecat/purchases/hybridcommon/ui/PaywallHelpers.kt @@ -7,6 +7,7 @@ fun presentPaywallFromFragment( fragment: FragmentActivity, requiredEntitlementIdentifier: String? = null, paywallResultListener: PaywallResultListener? = null, + shouldDisplayDismissButton: Boolean? = null, ) { fragment .supportFragmentManager @@ -16,6 +17,7 @@ fun presentPaywallFromFragment( fragment, requiredEntitlementIdentifier, paywallResultListener, + shouldDisplayDismissButton, ), PaywallFragment.tag, ) diff --git a/ios/PurchasesHybridCommon/ObjCAPITester/RCPaywallProxyAPITest.m b/ios/PurchasesHybridCommon/ObjCAPITester/RCPaywallProxyAPITest.m index a9f1c00b..cc76bf69 100644 --- a/ios/PurchasesHybridCommon/ObjCAPITester/RCPaywallProxyAPITest.m +++ b/ios/PurchasesHybridCommon/ObjCAPITester/RCPaywallProxyAPITest.m @@ -21,7 +21,9 @@ - (void)testAPI { if (@available(iOS 15.0, *)) { PaywallProxy *proxy = [PaywallProxy new]; [proxy presentPaywall]; + [proxy presentPaywallWithDisplayCloseButton:true]; [proxy presentPaywallIfNeededWithRequiredEntitlementIdentifier:@""]; + [proxy presentPaywallIfNeededWithRequiredEntitlementIdentifier:@"" displayCloseButton:YES]; } } diff --git a/ios/PurchasesHybridCommon/PurchasesHybridCommon/PaywallProxy.swift b/ios/PurchasesHybridCommon/PurchasesHybridCommon/PaywallProxy.swift index be405dd7..faa07c91 100644 --- a/ios/PurchasesHybridCommon/PurchasesHybridCommon/PaywallProxy.swift +++ b/ios/PurchasesHybridCommon/PurchasesHybridCommon/PaywallProxy.swift @@ -27,25 +27,37 @@ import UIKit @objc public func presentPaywall() { - guard let rootController = UIApplication.shared.keyWindow?.rootViewController else { - NSLog("Unable to find root UIViewController") - return - } - - let controller = PaywallViewController(displayCloseButton: true) - controller.delegate = self - controller.modalPresentationStyle = .pageSheet + presentPaywall(optionalDisplayCloseButton: nil) + } - rootController.present(controller, animated: true) + @objc + public func presentPaywall(displayCloseButton: Bool) { + presentPaywall(optionalDisplayCloseButton: displayCloseButton) } @objc public func presentPaywallIfNeeded(requiredEntitlementIdentifier: String) { + presentPaywallIfNeeded(requiredEntitlementIdentifier: requiredEntitlementIdentifier, + optionalDisplayCloseButton: nil) + } + + @objc + public func presentPaywallIfNeeded(requiredEntitlementIdentifier: String, displayCloseButton: Bool) { + presentPaywallIfNeeded(requiredEntitlementIdentifier: requiredEntitlementIdentifier, + optionalDisplayCloseButton: displayCloseButton) + } + + private func presentPaywallIfNeeded(requiredEntitlementIdentifier: String, optionalDisplayCloseButton: Bool?) { _ = Task { @MainActor in do { let customerInfo = try await Purchases.shared.customerInfo() if !customerInfo.entitlements.active.keys.contains(requiredEntitlementIdentifier) { - self.presentPaywall() + if let displayCloseButton = optionalDisplayCloseButton { + self.presentPaywall(displayCloseButton: displayCloseButton) + } else { + self.presentPaywall() + } + } } catch { NSLog("Failed presenting paywall: \(error)") @@ -53,6 +65,24 @@ import UIKit } } + private func presentPaywall(optionalDisplayCloseButton: Bool?) { + guard let rootController = UIApplication.shared.keyWindow?.rootViewController else { + NSLog("Unable to find root UIViewController") + return + } + + let controller: PaywallViewController + if let displayCloseButton = optionalDisplayCloseButton { + controller = PaywallViewController(displayCloseButton: displayCloseButton) + } else { + controller = PaywallViewController() + } + + controller.delegate = self + controller.modalPresentationStyle = .pageSheet + rootController.present(controller, animated: true) + } + } @available(iOS 15.0, *)