Skip to content

Commit 2dd0167

Browse files
authored
Add displayCloseButton and onDismiss options to paywall views (#913)
Depends on: - RevenueCat/purchases-ios#3708 - RevenueCat/purchases-ios#3738 - RevenueCat/purchases-hybrid-common#746 With this PR, there's a change in functionality in the way the dismissal of the paywall works in iOS. In iOS I noticed there was a bug that prevented the `onDismiss` callback from getting called when using `PaywallView` after dismissal of the paywall, and I also noticed that the paywall was getting automatically dismissed. In Android, I noticed the behavior was different, and the paywall wouldn't close by itself and the `onDismiss` would be called, so the `PaywallView` could be _dismissed_ by the developer. Taking into account the way React Native views work, I think the developer should have the responsability of not showing the paywall (dimissing it). So I consider Android implemntation's the correct one. Those PRs (RevenueCat/purchases-ios#3738 and RevenueCat/purchases-hybrid-common#746) make some changes in the way iOS behaves, so if the view is created from `PaywallProxy`, which is what React Native uses to create a `PaywallView` the view wouldn't close itself after the close button is pressed (or a successful purchase happens). It's a change in behavior, but I think it's a actually something we overlooked in iOS implementation's. Also, take into account that `PaywallView` in iOS used to do `self.dismiss`, which I believe would only work if the PaywallView in React Native is being presented using something like Navigator, where the dismiss event would bubble up and close the container controller.
1 parent 0701418 commit 2dd0167

File tree

8 files changed

+32
-4
lines changed

8 files changed

+32
-4
lines changed

apitesters/paywalls.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ function checkFullScreenPaywallViewOptions(
7070
) {
7171
const offering: PurchasesOffering | undefined | null = options.offering;
7272
const fontFamily: string | undefined | null = options.fontFamily;
73+
const displayCloseButton: boolean | undefined = options.displayCloseButton;
7374
}
7475

7576
function checkFooterPaywallViewOptions(options: FooterPaywallViewOptions) {

examples/purchaseTesterTypescript/app/screens/FooterPaywallScreen.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212

1313
type Props = NativeStackScreenProps<RootStackParamList, 'FooterPaywall'>;
1414

15-
const FooterPaywallScreen: React.FC<Props> = ({route}: Props) => {
15+
const FooterPaywallScreen: React.FC<Props> = ({route, navigation}: Props) => {
1616
// Example handlers for the events
1717
const onPurchaseCompleted = ({customerInfo, storeTransaction}: {
1818
customerInfo: CustomerInfo, storeTransaction: PurchasesStoreTransaction
@@ -46,6 +46,7 @@ const FooterPaywallScreen: React.FC<Props> = ({route}: Props) => {
4646

4747
const onDismiss = () => {
4848
console.log('Dismissed');
49+
navigation.pop();
4950
};
5051

5152
return (

examples/purchaseTesterTypescript/app/screens/PaywallScreen.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212

1313
type Props = NativeStackScreenProps<RootStackParamList, 'Paywall'>;
1414

15-
const PaywallScreen: React.FC<Props> = ({route}: Props) => {
15+
const PaywallScreen: React.FC<Props> = ({route, navigation}: Props) => {
1616
// Example handlers for the events
1717
const onPurchaseCompleted = ({customerInfo, storeTransaction}: {
1818
customerInfo: CustomerInfo, storeTransaction: PurchasesStoreTransaction
@@ -46,6 +46,7 @@ const PaywallScreen: React.FC<Props> = ({route}: Props) => {
4646

4747
const onDismiss = () => {
4848
console.log('Dismissed');
49+
navigation.pop();
4950
};
5051

5152
const styles = StyleSheet.create({
@@ -60,6 +61,7 @@ const PaywallScreen: React.FC<Props> = ({route}: Props) => {
6061
options={{
6162
offering: route.params.offering,
6263
fontFamily: route.params.fontFamily,
64+
displayCloseButton: true,
6365
}}
6466
onPurchaseStarted={onPurchaseStarted}
6567
onPurchaseCompleted={onPurchaseCompleted}

react-native-purchases-ui/android/src/main/java/com/revenuecat/purchases/react/ui/BasePaywallViewManager.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ internal abstract class BasePaywallViewManager<T : View> : SimpleViewManager<T>(
2323

2424
abstract fun setOfferingId(view: T, identifier: String)
2525

26+
abstract fun setDisplayDismissButton(view: T, display: Boolean)
27+
2628
override fun getExportedCustomDirectEventTypeConstants(): Map<String, Any>? {
2729
return MapBuilder.builder<String, Any>()
2830
.putEvent(PaywallEvent.ON_PURCHASE_STARTED)
@@ -44,6 +46,7 @@ internal abstract class BasePaywallViewManager<T : View> : SimpleViewManager<T>(
4446
options?.let { props ->
4547
setOfferingIdProp(view, props)
4648
setFontFamilyProp(view, props)
49+
setDisplayCloseButton(view, props)
4750
}
4851
}
4952

@@ -60,7 +63,12 @@ internal abstract class BasePaywallViewManager<T : View> : SimpleViewManager<T>(
6063
FontAssetManager.getFontFamily(fontFamilyName = it, view.resources.assets)?.let {
6164
setFontFamily(view, CustomFontProvider(it))
6265
}
66+
}
67+
}
6368

69+
private fun setDisplayCloseButton(view: T, options: ReadableMap) {
70+
options.takeIf { it.hasKey("displayCloseButton") }?.let {
71+
setDisplayDismissButton(view, it.getBoolean("displayCloseButton"))
6472
}
6573
}
6674

react-native-purchases-ui/android/src/main/java/com/revenuecat/purchases/react/ui/PaywallFooterViewManager.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,9 @@ internal class PaywallFooterViewManager : BasePaywallViewManager<PaywallFooterVi
6868
override fun setFontFamily(view: PaywallFooterView, customFontProvider: CustomFontProvider) {
6969
view.setFontProvider(customFontProvider)
7070
}
71+
72+
override fun setDisplayDismissButton(view: PaywallFooterView, display: Boolean) {
73+
// No-op since PaywallFooterView doesn't have a dismiss button
74+
}
75+
7176
}

react-native-purchases-ui/android/src/main/java/com/revenuecat/purchases/react/ui/PaywallViewManager.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,9 @@ internal class PaywallViewManager : BasePaywallViewManager<PaywallView>() {
3434
override fun setFontFamily(view: PaywallView, customFontProvider: CustomFontProvider) {
3535
view.setFontProvider(customFontProvider)
3636
}
37+
38+
override fun setDisplayDismissButton(view: PaywallView, display: Boolean) {
39+
view.setDisplayDismissButton(display)
40+
}
41+
3742
}

react-native-purchases-ui/ios/PaywallViewWrapper.m

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,12 @@ - (void)setOptions:(NSDictionary *)options {
8989
if (fontFamily && [fontFamily isKindOfClass:[NSString class]] && fontFamily.length > 0) {
9090
[self.paywallViewController updateFontWithFontName:fontFamily];
9191
}
92+
93+
NSNumber *displayCloseButtonValue = options[@"displayCloseButton"];
94+
BOOL displayCloseButton = [displayCloseButtonValue isKindOfClass:[NSNumber class]] ? [displayCloseButtonValue boolValue] : NO;
95+
if (displayCloseButton) {
96+
[self.paywallViewController updateWithDisplayCloseButton:displayCloseButton];
97+
}
9298
} else {
9399
NSLog(@"Error: attempted to present paywalls on unsupported iOS version.");
94100
}
@@ -139,7 +145,7 @@ - (void)paywallViewController:(RCPaywallViewController *)controller
139145
});
140146
}
141147

142-
- (void)paywallViewControllerWasDismissed:(RCPaywallViewController *)controller API_AVAILABLE(ios(15.0)) {
148+
- (void)paywallViewControllerRequestedDismissal:(RCPaywallViewController *)controller API_AVAILABLE(ios(15.0)) {
143149
self.onDismiss(nil);
144150
}
145151

react-native-purchases-ui/src/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ export interface PaywallViewOptions {
8585
}
8686

8787
export interface FullScreenPaywallViewOptions extends PaywallViewOptions {
88-
// Additional properties for FullScreenPaywallViewOptions can be added here if needed in the future
88+
displayCloseButton?: boolean | false;
8989
}
9090

9191
// Currently the same as the base type, but can be extended later if needed

0 commit comments

Comments
 (0)