react-native-purchases-ui 9.9.0 → 9.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/RNPaywalls.podspec +1 -1
- package/android/build.gradle +2 -2
- package/android/src/main/java/com/revenuecat/purchases/react/ui/BasePaywallViewManager.kt +32 -0
- package/android/src/main/java/com/revenuecat/purchases/react/ui/PaywallEventName.kt +3 -1
- package/android/src/main/java/com/revenuecat/purchases/react/ui/PaywallFooterViewManager.kt +5 -0
- package/android/src/main/java/com/revenuecat/purchases/react/ui/PaywallViewManager.kt +5 -0
- package/android/src/main/java/com/revenuecat/purchases/react/ui/RNPaywallsModule.kt +23 -1
- package/android/src/main/java/com/revenuecat/purchases/react/ui/events/OnPurchasePackageInitiatedEvent.kt +24 -0
- package/android/src/main/java/com/revenuecat/purchases/react/ui/views/WrappedPaywallComposeView.kt +5 -0
- package/ios/PaywallViewManager.m +1 -0
- package/ios/PaywallViewWrapper.h +1 -0
- package/ios/PaywallViewWrapper.m +23 -0
- package/ios/RNPaywalls.m +15 -0
- package/lib/commonjs/customVariables.js +91 -0
- package/lib/commonjs/customVariables.js.map +1 -0
- package/lib/commonjs/index.js +71 -9
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/customVariables.js +83 -0
- package/lib/module/customVariables.js.map +1 -0
- package/lib/module/index.js +54 -9
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/customVariables.d.ts +69 -0
- package/lib/typescript/src/customVariables.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +39 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +13 -11
- package/src/customVariables.ts +86 -0
- package/src/index.tsx +94 -4
package/RNPaywalls.podspec
CHANGED
|
@@ -17,6 +17,6 @@ Pod::Spec.new do |spec|
|
|
|
17
17
|
spec.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }
|
|
18
18
|
|
|
19
19
|
spec.dependency "React-Core"
|
|
20
|
-
spec.dependency "PurchasesHybridCommonUI", '17.
|
|
20
|
+
spec.dependency "PurchasesHybridCommonUI", '17.40.0'
|
|
21
21
|
spec.swift_version = '5.7'
|
|
22
22
|
end
|
package/android/build.gradle
CHANGED
|
@@ -59,7 +59,7 @@ android {
|
|
|
59
59
|
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
|
|
60
60
|
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
|
|
61
61
|
versionCode 1
|
|
62
|
-
versionName '9.
|
|
62
|
+
versionName '9.10.1'
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
buildTypes {
|
|
@@ -91,7 +91,7 @@ dependencies {
|
|
|
91
91
|
//noinspection GradleDynamicVersion
|
|
92
92
|
implementation "com.facebook.react:react-native:+"
|
|
93
93
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
94
|
-
implementation 'com.revenuecat.purchases:purchases-hybrid-common-ui:17.
|
|
94
|
+
implementation 'com.revenuecat.purchases:purchases-hybrid-common-ui:17.40.0'
|
|
95
95
|
implementation 'androidx.compose.ui:ui-android:1.5.4'
|
|
96
96
|
implementation "androidx.appcompat:appcompat:1.6.1"
|
|
97
97
|
}
|
|
@@ -17,10 +17,12 @@ import com.revenuecat.purchases.react.ui.events.OnDismissEvent
|
|
|
17
17
|
import com.revenuecat.purchases.react.ui.events.OnPurchaseCancelledEvent
|
|
18
18
|
import com.revenuecat.purchases.react.ui.events.OnPurchaseCompletedEvent
|
|
19
19
|
import com.revenuecat.purchases.react.ui.events.OnPurchaseErrorEvent
|
|
20
|
+
import com.revenuecat.purchases.react.ui.events.OnPurchasePackageInitiatedEvent
|
|
20
21
|
import com.revenuecat.purchases.react.ui.events.OnPurchaseStartedEvent
|
|
21
22
|
import com.revenuecat.purchases.react.ui.events.OnRestoreCompletedEvent
|
|
22
23
|
import com.revenuecat.purchases.react.ui.events.OnRestoreErrorEvent
|
|
23
24
|
import com.revenuecat.purchases.react.ui.events.OnRestoreStartedEvent
|
|
25
|
+
import com.revenuecat.purchases.ui.revenuecatui.CustomVariableValue
|
|
24
26
|
import com.revenuecat.purchases.ui.revenuecatui.fonts.CustomFontProvider
|
|
25
27
|
|
|
26
28
|
internal abstract class BasePaywallViewManager<T : View> : SimpleViewManager<T>() {
|
|
@@ -31,6 +33,7 @@ internal abstract class BasePaywallViewManager<T : View> : SimpleViewManager<T>(
|
|
|
31
33
|
private const val OFFERING_IDENTIFIER = "identifier"
|
|
32
34
|
private const val OPTION_FONT_FAMILY = "fontFamily"
|
|
33
35
|
private const val OPTION_DISPLAY_CLOSE_BUTTON = "displayCloseButton"
|
|
36
|
+
private const val OPTION_CUSTOM_VARIABLES = "customVariables"
|
|
34
37
|
|
|
35
38
|
private const val OPTION_OFFERING_AVAILABLE_PACKAGES = "availablePackages"
|
|
36
39
|
|
|
@@ -41,6 +44,8 @@ internal abstract class BasePaywallViewManager<T : View> : SimpleViewManager<T>(
|
|
|
41
44
|
|
|
42
45
|
abstract fun setDisplayDismissButton(view: T, display: Boolean)
|
|
43
46
|
|
|
47
|
+
abstract fun setCustomVariables(view: T, customVariables: Map<String, CustomVariableValue>)
|
|
48
|
+
|
|
44
49
|
override fun getExportedCustomDirectEventTypeConstants(): Map<String, Any>? {
|
|
45
50
|
return MapBuilder.builder<String, Any>()
|
|
46
51
|
.putEvent(PaywallEventName.ON_PURCHASE_STARTED)
|
|
@@ -52,6 +57,7 @@ internal abstract class BasePaywallViewManager<T : View> : SimpleViewManager<T>(
|
|
|
52
57
|
.putEvent(PaywallEventName.ON_RESTORE_ERROR)
|
|
53
58
|
.putEvent(PaywallEventName.ON_DISMISS)
|
|
54
59
|
.putEvent(PaywallEventName.ON_MEASURE)
|
|
60
|
+
.putEvent(PaywallEventName.ON_PURCHASE_PACKAGE_INITIATED)
|
|
55
61
|
.build()
|
|
56
62
|
}
|
|
57
63
|
|
|
@@ -63,6 +69,7 @@ internal abstract class BasePaywallViewManager<T : View> : SimpleViewManager<T>(
|
|
|
63
69
|
setOfferingIdProp(view, options)
|
|
64
70
|
setFontFamilyProp(view, options)
|
|
65
71
|
setDisplayCloseButton(view, options)
|
|
72
|
+
setCustomVariablesProp(view, options)
|
|
66
73
|
}
|
|
67
74
|
}
|
|
68
75
|
|
|
@@ -113,6 +120,21 @@ internal abstract class BasePaywallViewManager<T : View> : SimpleViewManager<T>(
|
|
|
113
120
|
}
|
|
114
121
|
}
|
|
115
122
|
|
|
123
|
+
private fun setCustomVariablesProp(view: T, options: ReadableMap?) {
|
|
124
|
+
val customVariablesMap = options?.getMap(OPTION_CUSTOM_VARIABLES) ?: return
|
|
125
|
+
val customVariables = mutableMapOf<String, CustomVariableValue>()
|
|
126
|
+
val iterator = customVariablesMap.keySetIterator()
|
|
127
|
+
while (iterator.hasNextKey()) {
|
|
128
|
+
val key = iterator.nextKey()
|
|
129
|
+
customVariablesMap.getString(key)?.let {
|
|
130
|
+
customVariables[key] = CustomVariableValue.String(it)
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (customVariables.isNotEmpty()) {
|
|
134
|
+
setCustomVariables(view, customVariables)
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
116
138
|
internal fun createPaywallListenerWrapper(
|
|
117
139
|
themedReactContext: ThemedReactContext,
|
|
118
140
|
view: View
|
|
@@ -182,6 +204,16 @@ internal abstract class BasePaywallViewManager<T : View> : SimpleViewManager<T>(
|
|
|
182
204
|
emitEvent(themedReactContext, view.id, event)
|
|
183
205
|
}
|
|
184
206
|
|
|
207
|
+
override fun onPurchasePackageInitiated(rcPackage: Map<String, Any?>, requestId: String) {
|
|
208
|
+
val event = OnPurchasePackageInitiatedEvent(
|
|
209
|
+
surfaceId = view.surfaceId,
|
|
210
|
+
viewTag = view.id,
|
|
211
|
+
rcPackage,
|
|
212
|
+
requestId,
|
|
213
|
+
)
|
|
214
|
+
emitEvent(themedReactContext, view.id, event)
|
|
215
|
+
}
|
|
216
|
+
|
|
185
217
|
}
|
|
186
218
|
|
|
187
219
|
internal fun getDismissHandler(
|
|
@@ -9,11 +9,13 @@ internal enum class PaywallEventName(val eventName: String) {
|
|
|
9
9
|
ON_RESTORE_COMPLETED("onRestoreCompleted"),
|
|
10
10
|
ON_RESTORE_ERROR("onRestoreError"),
|
|
11
11
|
ON_DISMISS("onDismiss"),
|
|
12
|
-
ON_MEASURE("onMeasure")
|
|
12
|
+
ON_MEASURE("onMeasure"),
|
|
13
|
+
ON_PURCHASE_PACKAGE_INITIATED("onPurchasePackageInitiated");
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
internal enum class PaywallEventKey(val key: String) {
|
|
16
17
|
PACKAGE("packageBeingPurchased"),
|
|
18
|
+
REQUEST_ID("requestId"),
|
|
17
19
|
CUSTOMER_INFO("customerInfo"),
|
|
18
20
|
STORE_TRANSACTION("storeTransaction"),
|
|
19
21
|
ERROR("error"),
|
|
@@ -5,6 +5,7 @@ import com.facebook.react.uimanager.ThemedReactContext
|
|
|
5
5
|
import com.revenuecat.purchases.PresentedOfferingContext
|
|
6
6
|
import com.revenuecat.purchases.react.ui.events.OnMeasureEvent
|
|
7
7
|
import com.revenuecat.purchases.react.ui.views.WrappedPaywallFooterComposeView
|
|
8
|
+
import com.revenuecat.purchases.ui.revenuecatui.CustomVariableValue
|
|
8
9
|
import com.revenuecat.purchases.ui.revenuecatui.fonts.CustomFontProvider
|
|
9
10
|
|
|
10
11
|
internal class PaywallFooterViewManager : BasePaywallViewManager<WrappedPaywallFooterComposeView>() {
|
|
@@ -89,4 +90,8 @@ internal class PaywallFooterViewManager : BasePaywallViewManager<WrappedPaywallF
|
|
|
89
90
|
// No-op since PaywallFooterView doesn't have a dismiss button
|
|
90
91
|
}
|
|
91
92
|
|
|
93
|
+
override fun setCustomVariables(view: WrappedPaywallFooterComposeView, customVariables: Map<String, CustomVariableValue>) {
|
|
94
|
+
// No-op: Footer paywalls (legacy templates) don't support custom variables
|
|
95
|
+
}
|
|
96
|
+
|
|
92
97
|
}
|
|
@@ -3,6 +3,7 @@ package com.revenuecat.purchases.react.ui
|
|
|
3
3
|
import com.facebook.react.uimanager.ThemedReactContext
|
|
4
4
|
import com.revenuecat.purchases.PresentedOfferingContext
|
|
5
5
|
import com.revenuecat.purchases.react.ui.views.WrappedPaywallComposeView
|
|
6
|
+
import com.revenuecat.purchases.ui.revenuecatui.CustomVariableValue
|
|
6
7
|
import com.revenuecat.purchases.ui.revenuecatui.fonts.CustomFontProvider
|
|
7
8
|
|
|
8
9
|
|
|
@@ -43,4 +44,8 @@ internal class PaywallViewManager : BasePaywallViewManager<WrappedPaywallCompose
|
|
|
43
44
|
view.setDisplayDismissButton(display)
|
|
44
45
|
}
|
|
45
46
|
|
|
47
|
+
override fun setCustomVariables(view: WrappedPaywallComposeView, customVariables: Map<String, CustomVariableValue>) {
|
|
48
|
+
view.setCustomVariables(customVariables)
|
|
49
|
+
}
|
|
50
|
+
|
|
46
51
|
}
|
|
@@ -7,6 +7,7 @@ import com.facebook.react.bridge.ReactApplicationContext
|
|
|
7
7
|
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
8
8
|
import com.facebook.react.bridge.ReactMethod
|
|
9
9
|
import com.facebook.react.bridge.ReadableMap
|
|
10
|
+
import com.revenuecat.purchases.hybridcommon.ui.PaywallListenerWrapper
|
|
10
11
|
import com.revenuecat.purchases.hybridcommon.ui.PaywallResultListener
|
|
11
12
|
import com.revenuecat.purchases.hybridcommon.ui.PaywallSource
|
|
12
13
|
import com.revenuecat.purchases.hybridcommon.ui.PresentPaywallOptions
|
|
@@ -42,6 +43,7 @@ internal class RNPaywallsModule(
|
|
|
42
43
|
presentedOfferingContext: ReadableMap?,
|
|
43
44
|
displayCloseButton: Boolean?,
|
|
44
45
|
fontFamily: String?,
|
|
46
|
+
customVariables: ReadableMap?,
|
|
45
47
|
promise: Promise
|
|
46
48
|
) {
|
|
47
49
|
presentPaywall(
|
|
@@ -50,6 +52,7 @@ internal class RNPaywallsModule(
|
|
|
50
52
|
presentedOfferingContext,
|
|
51
53
|
displayCloseButton,
|
|
52
54
|
fontFamily,
|
|
55
|
+
customVariables,
|
|
53
56
|
promise
|
|
54
57
|
)
|
|
55
58
|
}
|
|
@@ -61,6 +64,7 @@ internal class RNPaywallsModule(
|
|
|
61
64
|
presentedOfferingContext: ReadableMap?,
|
|
62
65
|
displayCloseButton: Boolean,
|
|
63
66
|
fontFamily: String?,
|
|
67
|
+
customVariables: ReadableMap?,
|
|
64
68
|
promise: Promise
|
|
65
69
|
) {
|
|
66
70
|
presentPaywall(
|
|
@@ -69,10 +73,16 @@ internal class RNPaywallsModule(
|
|
|
69
73
|
presentedOfferingContext,
|
|
70
74
|
displayCloseButton,
|
|
71
75
|
fontFamily,
|
|
76
|
+
customVariables,
|
|
72
77
|
promise
|
|
73
78
|
)
|
|
74
79
|
}
|
|
75
80
|
|
|
81
|
+
@ReactMethod
|
|
82
|
+
fun resumePurchasePackageInitiated(requestId: String, shouldProceed: Boolean) {
|
|
83
|
+
PaywallListenerWrapper.resumePurchasePackageInitiated(requestId, shouldProceed)
|
|
84
|
+
}
|
|
85
|
+
|
|
76
86
|
@ReactMethod
|
|
77
87
|
fun addListener(eventName: String?) {
|
|
78
88
|
// Keep: Required for RN built in Event Emitter Calls.
|
|
@@ -89,6 +99,7 @@ internal class RNPaywallsModule(
|
|
|
89
99
|
presentedOfferingContext: ReadableMap?,
|
|
90
100
|
displayCloseButton: Boolean?,
|
|
91
101
|
fontFamilyName: String?,
|
|
102
|
+
customVariables: ReadableMap?,
|
|
92
103
|
promise: Promise
|
|
93
104
|
) {
|
|
94
105
|
val activity = currentFragmentActivity ?: return
|
|
@@ -101,6 +112,16 @@ internal class RNPaywallsModule(
|
|
|
101
112
|
PaywallSource.OfferingIdentifierWithPresentedOfferingContext(offeringIdentifier, presentedOfferingContext=presentedOfferingContextMap)
|
|
102
113
|
} ?: PaywallSource.DefaultOffering
|
|
103
114
|
|
|
115
|
+
val customVariablesMap = customVariables?.let { cv ->
|
|
116
|
+
val result = mutableMapOf<String, String>()
|
|
117
|
+
val iterator = cv.keySetIterator()
|
|
118
|
+
while (iterator.hasNextKey()) {
|
|
119
|
+
val key = iterator.nextKey()
|
|
120
|
+
cv.getString(key)?.let { result[key] = it }
|
|
121
|
+
}
|
|
122
|
+
result.takeIf { it.isNotEmpty() }
|
|
123
|
+
}
|
|
124
|
+
|
|
104
125
|
// @ReactMethod is not guaranteed to run on the main thread
|
|
105
126
|
activity.runOnUiThread {
|
|
106
127
|
presentPaywallFromFragment(
|
|
@@ -114,7 +135,8 @@ internal class RNPaywallsModule(
|
|
|
114
135
|
promise.resolve(paywallResult)
|
|
115
136
|
}
|
|
116
137
|
},
|
|
117
|
-
fontFamily = fontFamily
|
|
138
|
+
fontFamily = fontFamily,
|
|
139
|
+
customVariables = customVariablesMap
|
|
118
140
|
)
|
|
119
141
|
)
|
|
120
142
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
package com.revenuecat.purchases.react.ui.events
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.WritableMap
|
|
4
|
+
import com.revenuecat.purchases.react.ui.PaywallEventKey
|
|
5
|
+
import com.revenuecat.purchases.react.ui.PaywallEventName
|
|
6
|
+
|
|
7
|
+
internal class OnPurchasePackageInitiatedEvent(
|
|
8
|
+
surfaceId: Int,
|
|
9
|
+
viewTag: Int,
|
|
10
|
+
private val packageMap: Map<String, Any?>,
|
|
11
|
+
private val requestId: String,
|
|
12
|
+
) : PaywallEvent<OnPurchasePackageInitiatedEvent>(surfaceId, viewTag) {
|
|
13
|
+
override fun getPaywallEventName() = PaywallEventName.ON_PURCHASE_PACKAGE_INITIATED
|
|
14
|
+
|
|
15
|
+
override fun getPayload() = mapOf(
|
|
16
|
+
PaywallEventKey.PACKAGE to packageMap,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
override fun getEventData(): WritableMap {
|
|
20
|
+
return super.getEventData().apply {
|
|
21
|
+
putString(PaywallEventKey.REQUEST_ID.key, requestId)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
package/android/src/main/java/com/revenuecat/purchases/react/ui/views/WrappedPaywallComposeView.kt
CHANGED
|
@@ -3,6 +3,7 @@ package com.revenuecat.purchases.react.ui.views
|
|
|
3
3
|
import android.content.Context
|
|
4
4
|
import android.util.AttributeSet
|
|
5
5
|
import com.revenuecat.purchases.PresentedOfferingContext
|
|
6
|
+
import com.revenuecat.purchases.ui.revenuecatui.CustomVariableValue
|
|
6
7
|
import com.revenuecat.purchases.ui.revenuecatui.PaywallListener
|
|
7
8
|
import com.revenuecat.purchases.ui.revenuecatui.fonts.FontProvider
|
|
8
9
|
import com.revenuecat.purchases.ui.revenuecatui.views.PaywallView
|
|
@@ -33,6 +34,10 @@ class WrappedPaywallComposeView(context: Context) : ComposeViewWrapper<PaywallVi
|
|
|
33
34
|
wrappedView?.setDisplayDismissButton(shouldDisplayDismissButton)
|
|
34
35
|
}
|
|
35
36
|
|
|
37
|
+
fun setCustomVariables(customVariables: Map<String, CustomVariableValue>) {
|
|
38
|
+
wrappedView?.setCustomVariables(customVariables)
|
|
39
|
+
}
|
|
40
|
+
|
|
36
41
|
override fun requestLayout() {
|
|
37
42
|
super.requestLayout()
|
|
38
43
|
post(measureAndLayout)
|
package/ios/PaywallViewManager.m
CHANGED
|
@@ -30,6 +30,7 @@ RCT_EXPORT_VIEW_PROPERTY(onRestoreStarted, RCTDirectEventBlock)
|
|
|
30
30
|
RCT_EXPORT_VIEW_PROPERTY(onRestoreCompleted, RCTDirectEventBlock)
|
|
31
31
|
RCT_EXPORT_VIEW_PROPERTY(onRestoreError, RCTDirectEventBlock)
|
|
32
32
|
RCT_EXPORT_VIEW_PROPERTY(onDismiss, RCTDirectEventBlock)
|
|
33
|
+
RCT_EXPORT_VIEW_PROPERTY(onPurchasePackageInitiated, RCTDirectEventBlock)
|
|
33
34
|
|
|
34
35
|
RCT_EXPORT_MODULE(Paywall)
|
|
35
36
|
|
package/ios/PaywallViewWrapper.h
CHANGED
|
@@ -21,6 +21,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
21
21
|
@property (nonatomic, copy) RCTDirectEventBlock onRestoreCompleted;
|
|
22
22
|
@property (nonatomic, copy) RCTDirectEventBlock onRestoreError;
|
|
23
23
|
@property (nonatomic, copy) RCTDirectEventBlock onDismiss;
|
|
24
|
+
@property (nonatomic, copy, nullable) RCTDirectEventBlock onPurchasePackageInitiated;
|
|
24
25
|
|
|
25
26
|
- (instancetype)initWithCoder:(NSCoder *)coder NS_UNAVAILABLE;
|
|
26
27
|
- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;
|
package/ios/PaywallViewWrapper.m
CHANGED
|
@@ -98,6 +98,16 @@ API_AVAILABLE(ios(15.0))
|
|
|
98
98
|
if (displayCloseButton) {
|
|
99
99
|
[self.paywallViewController updateWithDisplayCloseButton:displayCloseButton];
|
|
100
100
|
}
|
|
101
|
+
|
|
102
|
+
NSDictionary *customVariables = options[@"customVariables"];
|
|
103
|
+
if (customVariables && [customVariables isKindOfClass:[NSDictionary class]]) {
|
|
104
|
+
for (NSString *key in customVariables) {
|
|
105
|
+
NSString *value = customVariables[key];
|
|
106
|
+
if ([value isKindOfClass:[NSString class]]) {
|
|
107
|
+
[self.paywallViewController setCustomVariable:value forKey:key];
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
101
111
|
} else {
|
|
102
112
|
NSLog(@"Error: attempted to present paywalls on unsupported iOS version.");
|
|
103
113
|
}
|
|
@@ -197,4 +207,17 @@ didFailRestoringWithErrorDictionary:(NSDictionary *)errorDictionary API_AVAILABL
|
|
|
197
207
|
NSLog(@"RNPaywalls - Paywall view wrapper did change size to: %@", NSStringFromCGSize(size));
|
|
198
208
|
}
|
|
199
209
|
|
|
210
|
+
- (void)paywallViewController:(RCPaywallViewController *)controller
|
|
211
|
+
didInitiatePurchaseWithPackageDictionary:(NSDictionary *)packageDictionary
|
|
212
|
+
requestId:(NSString *)requestId API_AVAILABLE(ios(15.0)) {
|
|
213
|
+
if (self.onPurchasePackageInitiated) {
|
|
214
|
+
self.onPurchasePackageInitiated(@{
|
|
215
|
+
KeyPackage: packageDictionary,
|
|
216
|
+
@"requestId": requestId,
|
|
217
|
+
});
|
|
218
|
+
} else {
|
|
219
|
+
[PaywallProxy resumePurchasePackageInitiatedWithRequestId:requestId shouldProceed:YES];
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
200
223
|
@end
|
package/ios/RNPaywalls.m
CHANGED
|
@@ -65,6 +65,7 @@ RCT_EXPORT_METHOD(presentPaywall:(nullable NSString *)offeringIdentifier
|
|
|
65
65
|
presentedOfferingContext:(nullable NSDictionary *)presentedOfferingContext
|
|
66
66
|
shouldDisplayCloseButton:(BOOL)displayCloseButton
|
|
67
67
|
withFontFamily:(nullable NSString *)fontFamily
|
|
68
|
+
customVariables:(nullable NSDictionary *)customVariables
|
|
68
69
|
withResolve:(RCTPromiseResolveBlock)resolve
|
|
69
70
|
reject:(RCTPromiseRejectBlock)reject) {
|
|
70
71
|
if (@available(iOS 15.0, *)) {
|
|
@@ -79,6 +80,9 @@ RCT_EXPORT_METHOD(presentPaywall:(nullable NSString *)offeringIdentifier
|
|
|
79
80
|
if (fontFamily) {
|
|
80
81
|
options[PaywallOptionsKeys.fontName] = fontFamily;
|
|
81
82
|
}
|
|
83
|
+
if (customVariables) {
|
|
84
|
+
options[PaywallOptionsKeys.customVariables] = customVariables;
|
|
85
|
+
}
|
|
82
86
|
|
|
83
87
|
[self.paywalls presentPaywallWithOptions:options
|
|
84
88
|
paywallResultHandler:^(NSString *result) {
|
|
@@ -94,6 +98,7 @@ RCT_EXPORT_METHOD(presentPaywallIfNeeded:(NSString *)requiredEntitlementIdentifi
|
|
|
94
98
|
presentedOfferingContext:(nullable NSDictionary *)presentedOfferingContext
|
|
95
99
|
shouldDisplayCloseButton:(BOOL)displayCloseButton
|
|
96
100
|
withFontFamily:(nullable NSString *)fontFamily
|
|
101
|
+
customVariables:(nullable NSDictionary *)customVariables
|
|
97
102
|
withResolve:(RCTPromiseResolveBlock)resolve
|
|
98
103
|
reject:(RCTPromiseRejectBlock)reject) {
|
|
99
104
|
if (@available(iOS 15.0, *)) {
|
|
@@ -109,6 +114,9 @@ RCT_EXPORT_METHOD(presentPaywallIfNeeded:(NSString *)requiredEntitlementIdentifi
|
|
|
109
114
|
if (fontFamily) {
|
|
110
115
|
options[PaywallOptionsKeys.fontName] = fontFamily;
|
|
111
116
|
}
|
|
117
|
+
if (customVariables) {
|
|
118
|
+
options[PaywallOptionsKeys.customVariables] = customVariables;
|
|
119
|
+
}
|
|
112
120
|
|
|
113
121
|
[self.paywalls presentPaywallIfNeededWithOptions:options
|
|
114
122
|
paywallResultHandler:^(NSString *result) {
|
|
@@ -119,6 +127,13 @@ RCT_EXPORT_METHOD(presentPaywallIfNeeded:(NSString *)requiredEntitlementIdentifi
|
|
|
119
127
|
}
|
|
120
128
|
}
|
|
121
129
|
|
|
130
|
+
RCT_EXPORT_METHOD(resumePurchasePackageInitiated:(NSString *)requestId
|
|
131
|
+
shouldProceed:(BOOL)shouldProceed) {
|
|
132
|
+
if (@available(iOS 15.0, *)) {
|
|
133
|
+
[PaywallProxy resumePurchasePackageInitiatedWithRequestId:requestId shouldProceed:shouldProceed];
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
122
137
|
- (void)rejectPaywallsUnsupportedError:(RCTPromiseRejectBlock)reject {
|
|
123
138
|
NSLog(@"Error: attempted to present paywalls on unsupported iOS version.");
|
|
124
139
|
reject(@"PaywallsUnsupportedCode", @"Paywalls are not supported prior to iOS 15.", nil);
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.CustomVariableValue = void 0;
|
|
7
|
+
exports.convertCustomVariablesToStringMap = convertCustomVariablesToStringMap;
|
|
8
|
+
exports.transformOptionsForNative = transformOptionsForNative;
|
|
9
|
+
/**
|
|
10
|
+
* A value type for custom paywall variables that can be passed to paywalls at runtime.
|
|
11
|
+
*
|
|
12
|
+
* Custom variables allow developers to personalize paywall text with dynamic values.
|
|
13
|
+
* Variables are defined in the RevenueCat dashboard and can be overridden at runtime.
|
|
14
|
+
*
|
|
15
|
+
* Currently only string values are supported. Additional types may be added in the future.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* RevenueCatUI.presentPaywall({
|
|
20
|
+
* customVariables: {
|
|
21
|
+
* 'player_name': CustomVariableValue.string('John'),
|
|
22
|
+
* 'level': CustomVariableValue.string('42'),
|
|
23
|
+
* },
|
|
24
|
+
* });
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* In the paywall text (configured in the dashboard), use the `custom.` prefix:
|
|
28
|
+
* ```
|
|
29
|
+
* Hello {{ custom.player_name }}!
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Factory methods for creating CustomVariableValue instances.
|
|
35
|
+
*/
|
|
36
|
+
const CustomVariableValue = exports.CustomVariableValue = {
|
|
37
|
+
/**
|
|
38
|
+
* Creates a string custom variable value.
|
|
39
|
+
* @param value The string value for the custom variable.
|
|
40
|
+
* @returns A CustomVariableValue containing the string.
|
|
41
|
+
*/
|
|
42
|
+
string: value => ({
|
|
43
|
+
type: 'string',
|
|
44
|
+
value
|
|
45
|
+
})
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* A map of custom variable names to their values.
|
|
50
|
+
*/
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Internal type for custom variables as sent to native bridge.
|
|
54
|
+
* Currently only string values are supported.
|
|
55
|
+
* @internal
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Converts CustomVariables to a string map for native bridge.
|
|
60
|
+
* @internal
|
|
61
|
+
* @visibleForTesting
|
|
62
|
+
*/
|
|
63
|
+
function convertCustomVariablesToStringMap(customVariables) {
|
|
64
|
+
if (!customVariables) return null;
|
|
65
|
+
const result = {};
|
|
66
|
+
for (const key of Object.keys(customVariables)) {
|
|
67
|
+
const variable = customVariables[key];
|
|
68
|
+
if (variable) {
|
|
69
|
+
result[key] = variable.value;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Transforms options to native format, converting CustomVariables to string map.
|
|
77
|
+
* @internal
|
|
78
|
+
* @visibleForTesting
|
|
79
|
+
*/
|
|
80
|
+
function transformOptionsForNative(options) {
|
|
81
|
+
if (!options) return undefined;
|
|
82
|
+
const {
|
|
83
|
+
customVariables,
|
|
84
|
+
...rest
|
|
85
|
+
} = options;
|
|
86
|
+
return {
|
|
87
|
+
...rest,
|
|
88
|
+
customVariables: convertCustomVariablesToStringMap(customVariables)
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=customVariables.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["CustomVariableValue","exports","string","value","type","convertCustomVariablesToStringMap","customVariables","result","key","Object","keys","variable","transformOptionsForNative","options","undefined","rest"],"sourceRoot":"../../src","sources":["customVariables.ts"],"mappings":";;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAMA;AACA;AACA;AACO,MAAMA,mBAAmB,GAAAC,OAAA,CAAAD,mBAAA,GAAG;EACjC;AACF;AACA;AACA;AACA;EACEE,MAAM,EAAGC,KAAa,KAA2B;IAAEC,IAAI,EAAE,QAAQ;IAAED;EAAM,CAAC;AAC5E,CAAU;;AAEV;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACO,SAASE,iCAAiCA,CAC/CC,eAA4C,EACd;EAC9B,IAAI,CAACA,eAAe,EAAE,OAAO,IAAI;EACjC,MAAMC,MAA6B,GAAG,CAAC,CAAC;EACxC,KAAK,MAAMC,GAAG,IAAIC,MAAM,CAACC,IAAI,CAACJ,eAAe,CAAC,EAAE;IAC9C,MAAMK,QAAQ,GAAGL,eAAe,CAACE,GAAG,CAAC;IACrC,IAAIG,QAAQ,EAAE;MACZJ,MAAM,CAACC,GAAG,CAAC,GAAGG,QAAQ,CAACR,KAAK;IAC9B;EACF;EACA,OAAOI,MAAM;AACf;;AAEA;AACA;AACA;AACA;AACA;AACO,SAASK,yBAAyBA,CACvCC,OAAsB,EACyE;EAC/F,IAAI,CAACA,OAAO,EAAE,OAAOC,SAAS;EAC9B,MAAM;IAAER,eAAe;IAAE,GAAGS;EAAK,CAAC,GAAGF,OAAO;EAC5C,OAAO;IACL,GAAGE,IAAkC;IACrCT,eAAe,EAAED,iCAAiC,CAACC,eAAe;EACpE,CAAC;AACH","ignoreList":[]}
|
package/lib/commonjs/index.js
CHANGED
|
@@ -3,21 +3,42 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
Object.defineProperty(exports, "CustomVariableValue", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _customVariables.CustomVariableValue;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
6
12
|
Object.defineProperty(exports, "PAYWALL_RESULT", {
|
|
7
13
|
enumerable: true,
|
|
8
14
|
get: function () {
|
|
9
15
|
return _purchasesTypescriptInternal.PAYWALL_RESULT;
|
|
10
16
|
}
|
|
11
17
|
});
|
|
18
|
+
Object.defineProperty(exports, "convertCustomVariablesToStringMap", {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: function () {
|
|
21
|
+
return _customVariables.convertCustomVariablesToStringMap;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
12
24
|
exports.default = void 0;
|
|
25
|
+
Object.defineProperty(exports, "transformOptionsForNative", {
|
|
26
|
+
enumerable: true,
|
|
27
|
+
get: function () {
|
|
28
|
+
return _customVariables.transformOptionsForNative;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
13
31
|
var _reactNative = require("react-native");
|
|
14
32
|
var _purchasesTypescriptInternal = require("@revenuecat/purchases-typescript-internal");
|
|
15
33
|
var _react = _interopRequireWildcard(require("react"));
|
|
16
34
|
var _environment = require("./utils/environment");
|
|
17
35
|
var _nativeModules = require("./preview/nativeModules");
|
|
18
36
|
var _previewComponents = require("./preview/previewComponents");
|
|
37
|
+
var _customVariables = require("./customVariables");
|
|
19
38
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
20
39
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
40
|
+
// Re-export for testing purposes (marked as @internal)
|
|
41
|
+
|
|
21
42
|
const NATIVE_MODULE_NOT_FOUND_ERROR = `[RevenueCatUI] Native module not found. This can happen if:\n\n` + `- You are running in an unsupported environment (e.g., A browser or a container app that doesn't actually use the native modules)\n` + `- The native module failed to initialize\n` + `- react-native-purchases is not properly installed\n\n` + `To fix this:\n` + `- If using Expo, create a development build: https://docs.expo.dev/develop/development-builds/create-a-build/\n` + `- If using bare React Native, run 'pod install' and rebuild the app\n` + `- Make sure react-native-purchases is installed and you have rebuilt the app\n`;
|
|
22
43
|
|
|
23
44
|
// Get the native module or use the preview implementation
|
|
@@ -48,7 +69,8 @@ const InternalPaywall = ({
|
|
|
48
69
|
onRestoreStarted,
|
|
49
70
|
onRestoreCompleted,
|
|
50
71
|
onRestoreError,
|
|
51
|
-
onDismiss
|
|
72
|
+
onDismiss,
|
|
73
|
+
onPurchasePackageInitiated
|
|
52
74
|
}) => {
|
|
53
75
|
if (usingPreviewAPIMode) {
|
|
54
76
|
return /*#__PURE__*/_react.default.createElement(_previewComponents.PreviewPaywall, {
|
|
@@ -65,10 +87,12 @@ const InternalPaywall = ({
|
|
|
65
87
|
onDismiss: onDismiss
|
|
66
88
|
});
|
|
67
89
|
} else if (!!NativePaywall) {
|
|
90
|
+
// Transform options to native format (CustomVariables -> string map)
|
|
91
|
+
const nativeOptions = (0, _customVariables.transformOptionsForNative)(options);
|
|
68
92
|
return /*#__PURE__*/_react.default.createElement(NativePaywall, {
|
|
69
93
|
style: style,
|
|
70
94
|
children: children,
|
|
71
|
-
options:
|
|
95
|
+
options: nativeOptions,
|
|
72
96
|
onPurchaseStarted: event => onPurchaseStarted && onPurchaseStarted(event.nativeEvent),
|
|
73
97
|
onPurchaseCompleted: event => onPurchaseCompleted && onPurchaseCompleted(event.nativeEvent),
|
|
74
98
|
onPurchaseError: event => onPurchaseError && onPurchaseError(event.nativeEvent),
|
|
@@ -76,7 +100,24 @@ const InternalPaywall = ({
|
|
|
76
100
|
onRestoreStarted: () => onRestoreStarted && onRestoreStarted(),
|
|
77
101
|
onRestoreCompleted: event => onRestoreCompleted && onRestoreCompleted(event.nativeEvent),
|
|
78
102
|
onRestoreError: event => onRestoreError && onRestoreError(event.nativeEvent),
|
|
79
|
-
onDismiss: () => onDismiss && onDismiss()
|
|
103
|
+
onDismiss: () => onDismiss && onDismiss(),
|
|
104
|
+
onPurchasePackageInitiated: event => {
|
|
105
|
+
const {
|
|
106
|
+
packageBeingPurchased,
|
|
107
|
+
requestId
|
|
108
|
+
} = event.nativeEvent;
|
|
109
|
+
if (onPurchasePackageInitiated) {
|
|
110
|
+
const resume = shouldProceed => {
|
|
111
|
+
RNPaywalls.resumePurchasePackageInitiated(requestId, shouldProceed);
|
|
112
|
+
};
|
|
113
|
+
onPurchasePackageInitiated({
|
|
114
|
+
packageBeingPurchased,
|
|
115
|
+
resume
|
|
116
|
+
});
|
|
117
|
+
} else {
|
|
118
|
+
RNPaywalls.resumePurchasePackageInitiated(requestId, true);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
80
121
|
});
|
|
81
122
|
}
|
|
82
123
|
throw new Error(NATIVE_MODULE_NOT_FOUND_ERROR);
|
|
@@ -110,10 +151,12 @@ const InternalPaywallFooterView = ({
|
|
|
110
151
|
onDismiss: onDismiss
|
|
111
152
|
});
|
|
112
153
|
} else if (!!NativePaywallFooter) {
|
|
154
|
+
// Transform options to native format (CustomVariables -> string map)
|
|
155
|
+
const nativeOptions = (0, _customVariables.transformOptionsForNative)(options);
|
|
113
156
|
return /*#__PURE__*/_react.default.createElement(NativePaywallFooter, {
|
|
114
157
|
style: style,
|
|
115
158
|
children: children,
|
|
116
|
-
options:
|
|
159
|
+
options: nativeOptions,
|
|
117
160
|
onPurchaseStarted: event => onPurchaseStarted && onPurchaseStarted(event.nativeEvent),
|
|
118
161
|
onPurchaseCompleted: event => onPurchaseCompleted && onPurchaseCompleted(event.nativeEvent),
|
|
119
162
|
onPurchaseError: event => onPurchaseError && onPurchaseError(event.nativeEvent),
|
|
@@ -130,6 +173,21 @@ const InternalPaywallFooterView = ({
|
|
|
130
173
|
|
|
131
174
|
// Currently the same as the base type, but can be extended later if needed
|
|
132
175
|
|
|
176
|
+
/**
|
|
177
|
+
* Helper type that replaces CustomVariables with NativeCustomVariables in an options type.
|
|
178
|
+
* @internal
|
|
179
|
+
*/
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Native props for FullScreenPaywall component.
|
|
183
|
+
* @internal
|
|
184
|
+
*/
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Native props for FooterPaywall component.
|
|
188
|
+
* @internal
|
|
189
|
+
*/
|
|
190
|
+
|
|
133
191
|
const InternalCustomerCenterView = !usingPreviewAPIMode && _reactNative.UIManager.getViewManagerConfig('CustomerCenterView') != null ? (0, _reactNative.requireNativeComponent)('CustomerCenterView') : null;
|
|
134
192
|
|
|
135
193
|
// This is to prevent breaking changes when the native SDK adds new options
|
|
@@ -159,12 +217,13 @@ class RevenueCatUI {
|
|
|
159
217
|
static presentPaywall({
|
|
160
218
|
offering,
|
|
161
219
|
displayCloseButton = RevenueCatUI.Defaults.PRESENT_PAYWALL_DISPLAY_CLOSE_BUTTON,
|
|
162
|
-
fontFamily
|
|
220
|
+
fontFamily,
|
|
221
|
+
customVariables
|
|
163
222
|
} = {}) {
|
|
164
223
|
var _offering$availablePa;
|
|
165
224
|
throwIfNativeModulesNotAvailable();
|
|
166
225
|
RevenueCatUI.logWarningIfPreviewAPIMode("presentPaywall");
|
|
167
|
-
return RNPaywalls.presentPaywall((offering === null || offering === void 0 ? void 0 : offering.identifier) ?? null, offering === null || offering === void 0 || (_offering$availablePa = offering.availablePackages) === null || _offering$availablePa === void 0 || (_offering$availablePa = _offering$availablePa[0]) === null || _offering$availablePa === void 0 ? void 0 : _offering$availablePa.presentedOfferingContext, displayCloseButton, fontFamily);
|
|
226
|
+
return RNPaywalls.presentPaywall((offering === null || offering === void 0 ? void 0 : offering.identifier) ?? null, offering === null || offering === void 0 || (_offering$availablePa = offering.availablePackages) === null || _offering$availablePa === void 0 || (_offering$availablePa = _offering$availablePa[0]) === null || _offering$availablePa === void 0 ? void 0 : _offering$availablePa.presentedOfferingContext, displayCloseButton, fontFamily, (0, _customVariables.convertCustomVariablesToStringMap)(customVariables));
|
|
168
227
|
}
|
|
169
228
|
|
|
170
229
|
/**
|
|
@@ -184,12 +243,13 @@ class RevenueCatUI {
|
|
|
184
243
|
requiredEntitlementIdentifier,
|
|
185
244
|
offering,
|
|
186
245
|
displayCloseButton = RevenueCatUI.Defaults.PRESENT_PAYWALL_DISPLAY_CLOSE_BUTTON,
|
|
187
|
-
fontFamily
|
|
246
|
+
fontFamily,
|
|
247
|
+
customVariables
|
|
188
248
|
}) {
|
|
189
249
|
var _offering$availablePa2;
|
|
190
250
|
throwIfNativeModulesNotAvailable();
|
|
191
251
|
RevenueCatUI.logWarningIfPreviewAPIMode("presentPaywallIfNeeded");
|
|
192
|
-
return RNPaywalls.presentPaywallIfNeeded(requiredEntitlementIdentifier, (offering === null || offering === void 0 ? void 0 : offering.identifier) ?? null, offering === null || offering === void 0 || (_offering$availablePa2 = offering.availablePackages) === null || _offering$availablePa2 === void 0 || (_offering$availablePa2 = _offering$availablePa2[0]) === null || _offering$availablePa2 === void 0 ? void 0 : _offering$availablePa2.presentedOfferingContext, displayCloseButton, fontFamily);
|
|
252
|
+
return RNPaywalls.presentPaywallIfNeeded(requiredEntitlementIdentifier, (offering === null || offering === void 0 ? void 0 : offering.identifier) ?? null, offering === null || offering === void 0 || (_offering$availablePa2 = offering.availablePackages) === null || _offering$availablePa2 === void 0 || (_offering$availablePa2 = _offering$availablePa2[0]) === null || _offering$availablePa2 === void 0 ? void 0 : _offering$availablePa2.presentedOfferingContext, displayCloseButton, fontFamily, (0, _customVariables.convertCustomVariablesToStringMap)(customVariables));
|
|
193
253
|
}
|
|
194
254
|
static Paywall = ({
|
|
195
255
|
style,
|
|
@@ -202,7 +262,8 @@ class RevenueCatUI {
|
|
|
202
262
|
onRestoreStarted,
|
|
203
263
|
onRestoreCompleted,
|
|
204
264
|
onRestoreError,
|
|
205
|
-
onDismiss
|
|
265
|
+
onDismiss,
|
|
266
|
+
onPurchasePackageInitiated
|
|
206
267
|
}) => {
|
|
207
268
|
return /*#__PURE__*/_react.default.createElement(InternalPaywall, {
|
|
208
269
|
options: options,
|
|
@@ -215,6 +276,7 @@ class RevenueCatUI {
|
|
|
215
276
|
onRestoreCompleted: onRestoreCompleted,
|
|
216
277
|
onRestoreError: onRestoreError,
|
|
217
278
|
onDismiss: onDismiss,
|
|
279
|
+
onPurchasePackageInitiated: onPurchasePackageInitiated,
|
|
218
280
|
style: [{
|
|
219
281
|
flex: 1
|
|
220
282
|
}, style]
|