react-native-purchases-ui 9.10.5 → 9.11.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 +60 -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 +6 -0
- package/android/src/main/java/com/revenuecat/purchases/react/ui/events/OnPerformPurchaseEvent.kt +24 -0
- package/android/src/main/java/com/revenuecat/purchases/react/ui/events/OnPerformRestoreEvent.kt +21 -0
- package/android/src/main/java/com/revenuecat/purchases/react/ui/views/WrappedPaywallComposeView.kt +5 -0
- package/ios/PaywallViewManager.m +10 -1
- package/ios/PaywallViewWrapper.h +5 -0
- package/ios/PaywallViewWrapper.m +41 -10
- package/ios/RNPaywalls.m +8 -0
- package/lib/commonjs/index.js +94 -16
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/index.js +97 -15
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/index.d.ts +53 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/index.tsx +111 -20
package/src/index.tsx
CHANGED
|
@@ -32,6 +32,56 @@ export { CustomVariableValue, type CustomVariables } from "./customVariables";
|
|
|
32
32
|
// Re-export for testing purposes (marked as @internal)
|
|
33
33
|
export { convertCustomVariablesToStringMap, transformOptionsForNative } from "./customVariables";
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* The result of a purchase or restore operation performed by custom app-based logic.
|
|
37
|
+
* Used when `purchasesAreCompletedBy` is set to `MY_APP`.
|
|
38
|
+
* @readonly
|
|
39
|
+
* @enum {string}
|
|
40
|
+
*/
|
|
41
|
+
export enum PURCHASE_LOGIC_RESULT {
|
|
42
|
+
/** The purchase or restore was successful. */
|
|
43
|
+
SUCCESS = "SUCCESS",
|
|
44
|
+
/** The purchase was cancelled by the user. */
|
|
45
|
+
CANCELLATION = "CANCELLATION",
|
|
46
|
+
/** An error occurred during the purchase or restore. */
|
|
47
|
+
ERROR = "ERROR",
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The result of a purchase or restore operation performed by custom purchase logic.
|
|
52
|
+
* Uses a discriminated union to allow structured error information.
|
|
53
|
+
*/
|
|
54
|
+
export type PurchaseLogicResult =
|
|
55
|
+
| { result: PURCHASE_LOGIC_RESULT.SUCCESS }
|
|
56
|
+
| { result: PURCHASE_LOGIC_RESULT.CANCELLATION }
|
|
57
|
+
| { result: PURCHASE_LOGIC_RESULT.ERROR; error?: PurchasesError };
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Interface for handling purchases and restores within paywalls when
|
|
61
|
+
* `purchasesAreCompletedBy` is set to `MY_APP`.
|
|
62
|
+
*
|
|
63
|
+
* When provided, the paywall will call these functions instead of using
|
|
64
|
+
* RevenueCat's default purchase/restore behavior.
|
|
65
|
+
*/
|
|
66
|
+
export interface PurchaseLogic {
|
|
67
|
+
/**
|
|
68
|
+
* Called when the paywall wants to perform a purchase.
|
|
69
|
+
* Implement this to execute your custom purchase logic.
|
|
70
|
+
*
|
|
71
|
+
* @param args.packageToPurchase - The package the user wants to purchase.
|
|
72
|
+
* @returns A promise resolving to a PurchaseLogicResult indicating the outcome.
|
|
73
|
+
*/
|
|
74
|
+
performPurchase: (args: { packageToPurchase: PurchasesPackage }) => Promise<PurchaseLogicResult>;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Called when the paywall wants to perform a restore.
|
|
78
|
+
* Implement this to execute your custom restore logic.
|
|
79
|
+
*
|
|
80
|
+
* @returns A promise resolving to a PurchaseLogicResult indicating the outcome.
|
|
81
|
+
*/
|
|
82
|
+
performRestore: () => Promise<PurchaseLogicResult>;
|
|
83
|
+
}
|
|
84
|
+
|
|
35
85
|
const NATIVE_MODULE_NOT_FOUND_ERROR =
|
|
36
86
|
`[RevenueCatUI] Native module not found. This can happen if:\n\n` +
|
|
37
87
|
`- You are running in an unsupported environment (e.g., A browser or a container app that doesn't actually use the native modules)\n` +
|
|
@@ -56,22 +106,71 @@ function throwIfNativeModulesNotAvailable(): void {
|
|
|
56
106
|
}
|
|
57
107
|
}
|
|
58
108
|
|
|
109
|
+
// Internal native props include purchase logic bridge events and native custom variable transforms
|
|
110
|
+
type NativeFullScreenPaywallViewProps = Omit<FullScreenPaywallViewProps, 'options'> & {
|
|
111
|
+
options?: WithNativeCustomVariables<FullScreenPaywallViewOptions>;
|
|
112
|
+
onPerformPurchase?: (event: any) => void;
|
|
113
|
+
onPerformRestore?: (event: any) => void;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
type NativeFooterPaywallViewProps = Omit<InternalFooterPaywallViewProps, 'options'> & {
|
|
117
|
+
options?: WithNativeCustomVariables<FooterPaywallViewOptions>;
|
|
118
|
+
};
|
|
119
|
+
|
|
59
120
|
const NativePaywall = !usingPreviewAPIMode && UIManager.getViewManagerConfig('Paywall') != null
|
|
60
121
|
? requireNativeComponent<NativeFullScreenPaywallViewProps>('Paywall')
|
|
61
122
|
: null;
|
|
62
123
|
|
|
63
124
|
const NativePaywallFooter = !usingPreviewAPIMode && UIManager.getViewManagerConfig('Paywall') != null
|
|
64
|
-
? requireNativeComponent<
|
|
125
|
+
? requireNativeComponent<NativeFooterPaywallViewProps>('RCPaywallFooterView')
|
|
65
126
|
: null;
|
|
66
127
|
|
|
67
128
|
// Only create event emitters if native modules are available
|
|
68
129
|
const eventEmitter = !usingPreviewAPIMode && RNPaywalls ? new NativeEventEmitter(RNPaywalls) : null;
|
|
69
130
|
const customerCenterEventEmitter = !usingPreviewAPIMode && RNCustomerCenter ? new NativeEventEmitter(RNCustomerCenter) : null;
|
|
70
131
|
|
|
132
|
+
function resolveLogicResult(requestId: string, logicResult: PurchaseLogicResult) {
|
|
133
|
+
const errorMessage = logicResult.result === PURCHASE_LOGIC_RESULT.ERROR && logicResult.error
|
|
134
|
+
? logicResult.error.message
|
|
135
|
+
: null;
|
|
136
|
+
RNPaywalls?.resolvePurchaseLogicResult(requestId, logicResult.result, errorMessage);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function createPurchaseLogicHandlers(purchaseLogic?: PurchaseLogic) {
|
|
140
|
+
if (!purchaseLogic) {
|
|
141
|
+
return { nativeOptions: {}, handlePerformPurchase: undefined, handlePerformRestore: undefined };
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const nativeOptions = { hasPurchaseLogic: true };
|
|
145
|
+
|
|
146
|
+
const handlePerformPurchase = async (event: any) => {
|
|
147
|
+
const { requestId, packageBeingPurchased } = event.nativeEvent;
|
|
148
|
+
try {
|
|
149
|
+
const logicResult = await purchaseLogic.performPurchase({ packageToPurchase: packageBeingPurchased });
|
|
150
|
+
resolveLogicResult(requestId, logicResult);
|
|
151
|
+
} catch (e) {
|
|
152
|
+
RNPaywalls?.resolvePurchaseLogicResult(requestId, PURCHASE_LOGIC_RESULT.ERROR, e instanceof Error ? e.message : null);
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
const handlePerformRestore = async (event: any) => {
|
|
157
|
+
const { requestId } = event.nativeEvent;
|
|
158
|
+
try {
|
|
159
|
+
const logicResult = await purchaseLogic.performRestore();
|
|
160
|
+
resolveLogicResult(requestId, logicResult);
|
|
161
|
+
} catch (e) {
|
|
162
|
+
RNPaywalls?.resolvePurchaseLogicResult(requestId, PURCHASE_LOGIC_RESULT.ERROR, e instanceof Error ? e.message : null);
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
return { nativeOptions, handlePerformPurchase, handlePerformRestore };
|
|
167
|
+
}
|
|
168
|
+
|
|
71
169
|
const InternalPaywall: React.FC<FullScreenPaywallViewProps> = ({
|
|
72
170
|
style,
|
|
73
171
|
children,
|
|
74
172
|
options,
|
|
173
|
+
purchaseLogic,
|
|
75
174
|
onPurchaseStarted,
|
|
76
175
|
onPurchaseCompleted,
|
|
77
176
|
onPurchaseError,
|
|
@@ -82,6 +181,8 @@ const InternalPaywall: React.FC<FullScreenPaywallViewProps> = ({
|
|
|
82
181
|
onDismiss,
|
|
83
182
|
onPurchasePackageInitiated,
|
|
84
183
|
}) => {
|
|
184
|
+
const { nativeOptions, handlePerformPurchase, handlePerformRestore } = createPurchaseLogicHandlers(purchaseLogic);
|
|
185
|
+
|
|
85
186
|
if (usingPreviewAPIMode) {
|
|
86
187
|
return (
|
|
87
188
|
<PreviewPaywall
|
|
@@ -100,12 +201,12 @@ const InternalPaywall: React.FC<FullScreenPaywallViewProps> = ({
|
|
|
100
201
|
);
|
|
101
202
|
} else if (!!NativePaywall) {
|
|
102
203
|
// Transform options to native format (CustomVariables -> string map)
|
|
103
|
-
const
|
|
204
|
+
const transformedOptions = transformOptionsForNative(options);
|
|
104
205
|
return (
|
|
105
206
|
<NativePaywall
|
|
106
207
|
style={style}
|
|
107
208
|
children={children}
|
|
108
|
-
options={nativeOptions}
|
|
209
|
+
options={{ ...transformedOptions, ...nativeOptions }}
|
|
109
210
|
onPurchaseStarted={(event: any) => onPurchaseStarted && onPurchaseStarted(event.nativeEvent)}
|
|
110
211
|
onPurchaseCompleted={(event: any) => onPurchaseCompleted && onPurchaseCompleted(event.nativeEvent)}
|
|
111
212
|
onPurchaseError={(event: any) => onPurchaseError && onPurchaseError(event.nativeEvent)}
|
|
@@ -125,6 +226,8 @@ const InternalPaywall: React.FC<FullScreenPaywallViewProps> = ({
|
|
|
125
226
|
RNPaywalls!.resumePurchasePackageInitiated(requestId, true);
|
|
126
227
|
}
|
|
127
228
|
}}
|
|
229
|
+
onPerformPurchase={handlePerformPurchase}
|
|
230
|
+
onPerformRestore={handlePerformRestore}
|
|
128
231
|
/>
|
|
129
232
|
);
|
|
130
233
|
}
|
|
@@ -164,12 +267,12 @@ const InternalPaywallFooterView: React.FC<InternalFooterPaywallViewProps> = ({
|
|
|
164
267
|
);
|
|
165
268
|
} else if (!!NativePaywallFooter) {
|
|
166
269
|
// Transform options to native format (CustomVariables -> string map)
|
|
167
|
-
const
|
|
270
|
+
const transformedOptions = transformOptionsForNative(options);
|
|
168
271
|
return (
|
|
169
272
|
<NativePaywallFooter
|
|
170
273
|
style={style}
|
|
171
274
|
children={children}
|
|
172
|
-
options={
|
|
275
|
+
options={transformedOptions}
|
|
173
276
|
onPurchaseStarted={(event: any) => onPurchaseStarted && onPurchaseStarted(event.nativeEvent)}
|
|
174
277
|
onPurchaseCompleted={(event: any) => onPurchaseCompleted && onPurchaseCompleted(event.nativeEvent)}
|
|
175
278
|
onPurchaseError={(event: any) => onPurchaseError && onPurchaseError(event.nativeEvent)}
|
|
@@ -288,6 +391,7 @@ type FullScreenPaywallViewProps = {
|
|
|
288
391
|
style?: StyleProp<ViewStyle>;
|
|
289
392
|
children?: ReactNode;
|
|
290
393
|
options?: FullScreenPaywallViewOptions;
|
|
394
|
+
purchaseLogic?: PurchaseLogic;
|
|
291
395
|
onPurchaseStarted?: ({packageBeingPurchased}: { packageBeingPurchased: PurchasesPackage }) => void;
|
|
292
396
|
onPurchaseCompleted?: ({
|
|
293
397
|
customerInfo,
|
|
@@ -333,21 +437,6 @@ type InternalFooterPaywallViewProps = FooterPaywallViewProps & {
|
|
|
333
437
|
type WithNativeCustomVariables<T extends { customVariables?: CustomVariables }> =
|
|
334
438
|
Omit<T, 'customVariables'> & { customVariables?: NativeCustomVariables | null };
|
|
335
439
|
|
|
336
|
-
/**
|
|
337
|
-
* Native props for FullScreenPaywall component.
|
|
338
|
-
* @internal
|
|
339
|
-
*/
|
|
340
|
-
type NativeFullScreenPaywallViewProps = Omit<FullScreenPaywallViewProps, 'options'> & {
|
|
341
|
-
options?: WithNativeCustomVariables<FullScreenPaywallViewOptions>;
|
|
342
|
-
};
|
|
343
|
-
|
|
344
|
-
/**
|
|
345
|
-
* Native props for FooterPaywall component.
|
|
346
|
-
* @internal
|
|
347
|
-
*/
|
|
348
|
-
type NativeInternalFooterPaywallViewProps = Omit<InternalFooterPaywallViewProps, 'options'> & {
|
|
349
|
-
options?: WithNativeCustomVariables<FooterPaywallViewOptions>;
|
|
350
|
-
};
|
|
351
440
|
|
|
352
441
|
const InternalCustomerCenterView = !usingPreviewAPIMode && UIManager.getViewManagerConfig('CustomerCenterView') != null
|
|
353
442
|
? requireNativeComponent<CustomerCenterViewProps>('CustomerCenterView')
|
|
@@ -517,6 +606,7 @@ export default class RevenueCatUI {
|
|
|
517
606
|
style,
|
|
518
607
|
children,
|
|
519
608
|
options,
|
|
609
|
+
purchaseLogic,
|
|
520
610
|
onPurchaseStarted,
|
|
521
611
|
onPurchaseCompleted,
|
|
522
612
|
onPurchaseError,
|
|
@@ -531,6 +621,7 @@ export default class RevenueCatUI {
|
|
|
531
621
|
<InternalPaywall
|
|
532
622
|
options={options}
|
|
533
623
|
children={children}
|
|
624
|
+
purchaseLogic={purchaseLogic}
|
|
534
625
|
onPurchaseStarted={onPurchaseStarted}
|
|
535
626
|
onPurchaseCompleted={onPurchaseCompleted}
|
|
536
627
|
onPurchaseError={onPurchaseError}
|