react-native-purchases-ui 8.11.9 → 9.0.0
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 +3 -3
- package/android/src/main/java/com/revenuecat/purchases/react/ui/views/WrappedPaywallComposeView.kt +17 -0
- package/lib/commonjs/index.js +152 -50
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/preview/previewComponents.js +147 -0
- package/lib/commonjs/preview/previewComponents.js.map +1 -0
- package/lib/commonjs/utils/environment.js +16 -5
- package/lib/commonjs/utils/environment.js.map +1 -1
- package/lib/module/index.js +152 -50
- package/lib/module/index.js.map +1 -1
- package/lib/module/preview/previewComponents.js +139 -0
- package/lib/module/preview/previewComponents.js.map +1 -0
- package/lib/module/utils/environment.js +17 -6
- package/lib/module/utils/environment.js.map +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/preview/previewComponents.d.ts +28 -0
- package/lib/typescript/src/preview/previewComponents.d.ts.map +1 -0
- package/lib/typescript/src/utils/environment.d.ts +2 -2
- package/lib/typescript/src/utils/environment.d.ts.map +1 -1
- package/package.json +11 -4
- package/src/index.tsx +188 -70
- package/src/preview/previewComponents.tsx +171 -0
- package/src/utils/environment.ts +17 -6
package/src/index.tsx
CHANGED
@@ -19,12 +19,13 @@ import {
|
|
19
19
|
import React, { type ReactNode, useEffect, useState } from "react";
|
20
20
|
import { shouldUsePreviewAPIMode } from "./utils/environment";
|
21
21
|
import { previewNativeModuleRNCustomerCenter, previewNativeModuleRNPaywalls } from "./preview/nativeModules";
|
22
|
+
import { PreviewPaywall } from "./preview/previewComponents";
|
22
23
|
|
23
24
|
export { PAYWALL_RESULT } from "@revenuecat/purchases-typescript-internal";
|
24
25
|
|
25
26
|
const LINKING_ERROR =
|
26
27
|
`The package 'react-native-purchases-ui' doesn't seem to be linked. Make sure: \n\n` +
|
27
|
-
|
28
|
+
'- You have run \'pod install\'\n' +
|
28
29
|
'- You rebuilt the app after installing the package\n';
|
29
30
|
|
30
31
|
|
@@ -42,21 +43,118 @@ if (!RNCustomerCenter) {
|
|
42
43
|
throw new Error(LINKING_ERROR);
|
43
44
|
}
|
44
45
|
|
45
|
-
const
|
46
|
-
|
46
|
+
const NativePaywall = !usingPreviewAPIMode && UIManager.getViewManagerConfig('Paywall') != null
|
47
|
+
? requireNativeComponent<FullScreenPaywallViewProps>('Paywall')
|
48
|
+
: null;
|
47
49
|
|
48
|
-
const
|
49
|
-
UIManager.getViewManagerConfig('Paywall') != null
|
50
|
-
? requireNativeComponent<FullScreenPaywallViewProps>('Paywall')
|
51
|
-
: () => {
|
52
|
-
throw new Error(LINKING_ERROR);
|
53
|
-
};
|
54
|
-
|
55
|
-
const InternalPaywallFooterView = UIManager.getViewManagerConfig('Paywall') != null
|
50
|
+
const NativePaywallFooter = !usingPreviewAPIMode && UIManager.getViewManagerConfig('Paywall') != null
|
56
51
|
? requireNativeComponent<InternalFooterPaywallViewProps>('RCPaywallFooterView')
|
57
|
-
:
|
58
|
-
|
59
|
-
|
52
|
+
: null;
|
53
|
+
|
54
|
+
const eventEmitter = usingPreviewAPIMode ? null : new NativeEventEmitter(RNPaywalls);
|
55
|
+
const customerCenterEventEmitter = usingPreviewAPIMode ? null : new NativeEventEmitter(RNCustomerCenter);
|
56
|
+
|
57
|
+
const InternalPaywall: React.FC<FullScreenPaywallViewProps> = ({
|
58
|
+
style,
|
59
|
+
children,
|
60
|
+
options,
|
61
|
+
onPurchaseStarted,
|
62
|
+
onPurchaseCompleted,
|
63
|
+
onPurchaseError,
|
64
|
+
onPurchaseCancelled,
|
65
|
+
onRestoreStarted,
|
66
|
+
onRestoreCompleted,
|
67
|
+
onRestoreError,
|
68
|
+
onDismiss,
|
69
|
+
}) => {
|
70
|
+
if (usingPreviewAPIMode) {
|
71
|
+
return (
|
72
|
+
<PreviewPaywall
|
73
|
+
offering={options?.offering}
|
74
|
+
displayCloseButton={options?.displayCloseButton}
|
75
|
+
fontFamily={options?.fontFamily}
|
76
|
+
onPurchaseStarted={onPurchaseStarted}
|
77
|
+
onPurchaseCompleted={onPurchaseCompleted}
|
78
|
+
onPurchaseError={onPurchaseError}
|
79
|
+
onPurchaseCancelled={onPurchaseCancelled}
|
80
|
+
onRestoreStarted={onRestoreStarted}
|
81
|
+
onRestoreCompleted={onRestoreCompleted}
|
82
|
+
onRestoreError={onRestoreError}
|
83
|
+
onDismiss={onDismiss}
|
84
|
+
/>
|
85
|
+
);
|
86
|
+
} else if (!!NativePaywall) {
|
87
|
+
return (
|
88
|
+
<NativePaywall
|
89
|
+
style={style}
|
90
|
+
children={children}
|
91
|
+
options={options}
|
92
|
+
onPurchaseStarted={(event: any) => onPurchaseStarted && onPurchaseStarted(event.nativeEvent)}
|
93
|
+
onPurchaseCompleted={(event: any) => onPurchaseCompleted && onPurchaseCompleted(event.nativeEvent)}
|
94
|
+
onPurchaseError={(event: any) => onPurchaseError && onPurchaseError(event.nativeEvent)}
|
95
|
+
onPurchaseCancelled={() => onPurchaseCancelled && onPurchaseCancelled()}
|
96
|
+
onRestoreStarted={() => onRestoreStarted && onRestoreStarted()}
|
97
|
+
onRestoreCompleted={(event: any) => onRestoreCompleted && onRestoreCompleted(event.nativeEvent)}
|
98
|
+
onRestoreError={(event: any) => onRestoreError && onRestoreError(event.nativeEvent)}
|
99
|
+
onDismiss={() => onDismiss && onDismiss()}
|
100
|
+
/>
|
101
|
+
);
|
102
|
+
}
|
103
|
+
|
104
|
+
throw new Error(LINKING_ERROR);
|
105
|
+
};
|
106
|
+
|
107
|
+
const InternalPaywallFooterView: React.FC<InternalFooterPaywallViewProps> = ({
|
108
|
+
style,
|
109
|
+
children,
|
110
|
+
options,
|
111
|
+
onPurchaseStarted,
|
112
|
+
onPurchaseCompleted,
|
113
|
+
onPurchaseError,
|
114
|
+
onPurchaseCancelled,
|
115
|
+
onRestoreStarted,
|
116
|
+
onRestoreCompleted,
|
117
|
+
onRestoreError,
|
118
|
+
onDismiss,
|
119
|
+
onMeasure,
|
120
|
+
}) => {
|
121
|
+
if (usingPreviewAPIMode) {
|
122
|
+
return (
|
123
|
+
<PreviewPaywall
|
124
|
+
offering={options?.offering}
|
125
|
+
displayCloseButton={true}
|
126
|
+
fontFamily={options?.fontFamily}
|
127
|
+
onPurchaseStarted={onPurchaseStarted}
|
128
|
+
onPurchaseCompleted={onPurchaseCompleted}
|
129
|
+
onPurchaseError={onPurchaseError}
|
130
|
+
onPurchaseCancelled={onPurchaseCancelled}
|
131
|
+
onRestoreStarted={onRestoreStarted}
|
132
|
+
onRestoreCompleted={onRestoreCompleted}
|
133
|
+
onRestoreError={onRestoreError}
|
134
|
+
onDismiss={onDismiss}
|
135
|
+
/>
|
136
|
+
);
|
137
|
+
} else if (!!NativePaywallFooter) {
|
138
|
+
return (
|
139
|
+
<NativePaywallFooter
|
140
|
+
style={style}
|
141
|
+
children={children}
|
142
|
+
options={options}
|
143
|
+
onPurchaseStarted={(event: any) => onPurchaseStarted && onPurchaseStarted(event.nativeEvent)}
|
144
|
+
onPurchaseCompleted={(event: any) => onPurchaseCompleted && onPurchaseCompleted(event.nativeEvent)}
|
145
|
+
onPurchaseError={(event: any) => onPurchaseError && onPurchaseError(event.nativeEvent)}
|
146
|
+
onPurchaseCancelled={() => onPurchaseCancelled && onPurchaseCancelled()}
|
147
|
+
onRestoreStarted={() => onRestoreStarted && onRestoreStarted()}
|
148
|
+
onRestoreCompleted={(event: any) => onRestoreCompleted && onRestoreCompleted(event.nativeEvent)}
|
149
|
+
onRestoreError={(event: any) => onRestoreError && onRestoreError(event.nativeEvent)}
|
150
|
+
onDismiss={() => onDismiss && onDismiss()}
|
151
|
+
onMeasure={onMeasure}
|
152
|
+
/>
|
153
|
+
);
|
154
|
+
}
|
155
|
+
|
156
|
+
throw new Error(LINKING_ERROR);
|
157
|
+
};
|
60
158
|
|
61
159
|
export interface PresentPaywallParams {
|
62
160
|
/**
|
@@ -162,7 +260,7 @@ type InternalFooterPaywallViewProps = FooterPaywallViewProps & {
|
|
162
260
|
onMeasure?: ({height}: { height: number }) => void;
|
163
261
|
};
|
164
262
|
|
165
|
-
export type CustomerCenterManagementOption =
|
263
|
+
export type CustomerCenterManagementOption =
|
166
264
|
| 'cancel'
|
167
265
|
| 'custom_url'
|
168
266
|
| 'missing_purchase'
|
@@ -171,7 +269,7 @@ export type CustomerCenterManagementOption =
|
|
171
269
|
| 'unknown'
|
172
270
|
| string; // This is to prevent breaking changes when the native SDK adds new options
|
173
271
|
|
174
|
-
export type CustomerCenterManagementOptionEvent =
|
272
|
+
export type CustomerCenterManagementOptionEvent =
|
175
273
|
| { option: 'custom_url'; url: string }
|
176
274
|
| { option: Exclude<CustomerCenterManagementOption, 'custom_url'>; url: null };
|
177
275
|
|
@@ -180,22 +278,22 @@ export interface CustomerCenterCallbacks {
|
|
180
278
|
* Called when a feedback survey is completed with the selected option ID.
|
181
279
|
*/
|
182
280
|
onFeedbackSurveyCompleted?: ({feedbackSurveyOptionId}: { feedbackSurveyOptionId: string }) => void;
|
183
|
-
|
281
|
+
|
184
282
|
/**
|
185
283
|
* Called when the manage subscriptions section is being shown.
|
186
284
|
*/
|
187
285
|
onShowingManageSubscriptions?: () => void;
|
188
|
-
|
286
|
+
|
189
287
|
/**
|
190
288
|
* Called when a restore operation is completed successfully.
|
191
289
|
*/
|
192
290
|
onRestoreCompleted?: ({customerInfo}: { customerInfo: CustomerInfo }) => void;
|
193
|
-
|
291
|
+
|
194
292
|
/**
|
195
293
|
* Called when a restore operation fails.
|
196
294
|
*/
|
197
295
|
onRestoreFailed?: ({error}: { error: PurchasesError }) => void;
|
198
|
-
|
296
|
+
|
199
297
|
/**
|
200
298
|
* Called when a restore operation starts.
|
201
299
|
*/
|
@@ -205,7 +303,7 @@ export interface CustomerCenterCallbacks {
|
|
205
303
|
* Called when a refund request starts with the product identifier. iOS-only callback.
|
206
304
|
*/
|
207
305
|
onRefundRequestStarted?: ({productIdentifier}: { productIdentifier: string }) => void;
|
208
|
-
|
306
|
+
|
209
307
|
/**
|
210
308
|
* Called when a refund request completes with status information. iOS-only callback.
|
211
309
|
*/
|
@@ -254,7 +352,7 @@ export default class RevenueCatUI {
|
|
254
352
|
displayCloseButton = RevenueCatUI.Defaults.PRESENT_PAYWALL_DISPLAY_CLOSE_BUTTON,
|
255
353
|
fontFamily,
|
256
354
|
}: PresentPaywallParams = {}): Promise<PAYWALL_RESULT> {
|
257
|
-
RevenueCatUI.logWarningIfPreviewAPIMode("presentPaywall");
|
355
|
+
RevenueCatUI.logWarningIfPreviewAPIMode("presentPaywall");
|
258
356
|
return RNPaywalls.presentPaywall(
|
259
357
|
offering?.identifier ?? null,
|
260
358
|
displayCloseButton,
|
@@ -281,7 +379,7 @@ export default class RevenueCatUI {
|
|
281
379
|
displayCloseButton = RevenueCatUI.Defaults.PRESENT_PAYWALL_DISPLAY_CLOSE_BUTTON,
|
282
380
|
fontFamily,
|
283
381
|
}: PresentPaywallIfNeededParams): Promise<PAYWALL_RESULT> {
|
284
|
-
RevenueCatUI.logWarningIfPreviewAPIMode("presentPaywallIfNeeded");
|
382
|
+
RevenueCatUI.logWarningIfPreviewAPIMode("presentPaywallIfNeeded");
|
285
383
|
return RNPaywalls.presentPaywallIfNeeded(
|
286
384
|
requiredEntitlementIdentifier,
|
287
385
|
offering?.identifier ?? null,
|
@@ -302,19 +400,23 @@ export default class RevenueCatUI {
|
|
302
400
|
onRestoreCompleted,
|
303
401
|
onRestoreError,
|
304
402
|
onDismiss,
|
305
|
-
}) =>
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
403
|
+
}) => {
|
404
|
+
return (
|
405
|
+
<InternalPaywall
|
406
|
+
options={options}
|
407
|
+
children={children}
|
408
|
+
onPurchaseStarted={onPurchaseStarted}
|
409
|
+
onPurchaseCompleted={onPurchaseCompleted}
|
410
|
+
onPurchaseError={onPurchaseError}
|
411
|
+
onPurchaseCancelled={onPurchaseCancelled}
|
412
|
+
onRestoreStarted={onRestoreStarted}
|
413
|
+
onRestoreCompleted={onRestoreCompleted}
|
414
|
+
onRestoreError={onRestoreError}
|
415
|
+
onDismiss={onDismiss}
|
416
|
+
style={[{flex: 1}, style]}
|
417
|
+
/>
|
418
|
+
);
|
419
|
+
};
|
318
420
|
|
319
421
|
public static OriginalTemplatePaywallFooterContainerView: React.FC<FooterPaywallViewProps> = ({
|
320
422
|
style,
|
@@ -345,13 +447,13 @@ export default class RevenueCatUI {
|
|
345
447
|
setPaddingBottom(20 + bottom);
|
346
448
|
};
|
347
449
|
|
348
|
-
const subscription = eventEmitter
|
450
|
+
const subscription = eventEmitter?.addListener(
|
349
451
|
'safeAreaInsetsDidChange',
|
350
452
|
handleSafeAreaInsetsChange
|
351
453
|
);
|
352
454
|
|
353
455
|
return () => {
|
354
|
-
subscription
|
456
|
+
subscription?.remove();
|
355
457
|
};
|
356
458
|
}, []);
|
357
459
|
|
@@ -367,14 +469,14 @@ export default class RevenueCatUI {
|
|
367
469
|
android: {marginTop: -20, height}
|
368
470
|
})}
|
369
471
|
options={options}
|
370
|
-
onPurchaseStarted={
|
371
|
-
onPurchaseCompleted={
|
372
|
-
onPurchaseError={
|
373
|
-
onPurchaseCancelled={
|
374
|
-
onRestoreStarted={
|
375
|
-
onRestoreCompleted={
|
376
|
-
onRestoreError={
|
377
|
-
onDismiss={
|
472
|
+
onPurchaseStarted={onPurchaseStarted}
|
473
|
+
onPurchaseCompleted={onPurchaseCompleted}
|
474
|
+
onPurchaseError={onPurchaseError}
|
475
|
+
onPurchaseCancelled={onPurchaseCancelled}
|
476
|
+
onRestoreStarted={onRestoreStarted}
|
477
|
+
onRestoreCompleted={onRestoreCompleted}
|
478
|
+
onRestoreError={onRestoreError}
|
479
|
+
onDismiss={onDismiss}
|
378
480
|
onMeasure={(event: any) => setHeight(event.nativeEvent.measurements.height)}
|
379
481
|
/>
|
380
482
|
</View>
|
@@ -383,7 +485,7 @@ export default class RevenueCatUI {
|
|
383
485
|
|
384
486
|
/**
|
385
487
|
* Presents the customer center to the user.
|
386
|
-
*
|
488
|
+
*
|
387
489
|
* @param {PresentCustomerCenterParams} params - Optional parameters for presenting the customer center.
|
388
490
|
* @returns {Promise<void>} A promise that resolves when the customer center is presented.
|
389
491
|
*/
|
@@ -393,73 +495,89 @@ export default class RevenueCatUI {
|
|
393
495
|
const callbacks = params.callbacks as CustomerCenterCallbacks;
|
394
496
|
|
395
497
|
if (callbacks.onFeedbackSurveyCompleted) {
|
396
|
-
const subscription = customerCenterEventEmitter
|
498
|
+
const subscription = customerCenterEventEmitter?.addListener(
|
397
499
|
'onFeedbackSurveyCompleted',
|
398
|
-
(event: { feedbackSurveyOptionId: string }) => callbacks.onFeedbackSurveyCompleted &&
|
500
|
+
(event: { feedbackSurveyOptionId: string }) => callbacks.onFeedbackSurveyCompleted &&
|
399
501
|
callbacks.onFeedbackSurveyCompleted(event)
|
400
502
|
);
|
401
|
-
|
503
|
+
if (subscription) {
|
504
|
+
subscriptions.push(subscription);
|
505
|
+
}
|
402
506
|
}
|
403
507
|
|
404
508
|
if (callbacks.onShowingManageSubscriptions) {
|
405
|
-
const subscription = customerCenterEventEmitter
|
509
|
+
const subscription = customerCenterEventEmitter?.addListener(
|
406
510
|
'onShowingManageSubscriptions',
|
407
511
|
() => callbacks.onShowingManageSubscriptions && callbacks.onShowingManageSubscriptions()
|
408
512
|
);
|
409
|
-
|
513
|
+
if (subscription) {
|
514
|
+
subscriptions.push(subscription);
|
515
|
+
}
|
410
516
|
}
|
411
517
|
|
412
518
|
if (callbacks.onRestoreCompleted) {
|
413
|
-
const subscription = customerCenterEventEmitter
|
519
|
+
const subscription = customerCenterEventEmitter?.addListener(
|
414
520
|
'onRestoreCompleted',
|
415
|
-
(event: { customerInfo: CustomerInfo }) => callbacks.onRestoreCompleted &&
|
521
|
+
(event: { customerInfo: CustomerInfo }) => callbacks.onRestoreCompleted &&
|
416
522
|
callbacks.onRestoreCompleted(event)
|
417
523
|
);
|
418
|
-
|
524
|
+
if (subscription) {
|
525
|
+
subscriptions.push(subscription);
|
526
|
+
}
|
419
527
|
}
|
420
528
|
|
421
529
|
if (callbacks.onRestoreFailed) {
|
422
|
-
const subscription = customerCenterEventEmitter
|
530
|
+
const subscription = customerCenterEventEmitter?.addListener(
|
423
531
|
'onRestoreFailed',
|
424
|
-
(event: { error: PurchasesError }) => callbacks.onRestoreFailed &&
|
532
|
+
(event: { error: PurchasesError }) => callbacks.onRestoreFailed &&
|
425
533
|
callbacks.onRestoreFailed(event)
|
426
534
|
);
|
427
|
-
|
535
|
+
if (subscription) {
|
536
|
+
subscriptions.push(subscription);
|
537
|
+
}
|
428
538
|
}
|
429
539
|
|
430
540
|
if (callbacks.onRestoreStarted) {
|
431
|
-
const subscription = customerCenterEventEmitter
|
541
|
+
const subscription = customerCenterEventEmitter?.addListener(
|
432
542
|
'onRestoreStarted',
|
433
543
|
() => callbacks.onRestoreStarted && callbacks.onRestoreStarted()
|
434
544
|
);
|
435
|
-
|
545
|
+
if (subscription) {
|
546
|
+
subscriptions.push(subscription);
|
547
|
+
}
|
436
548
|
}
|
437
549
|
|
438
550
|
if (callbacks.onRefundRequestStarted) {
|
439
|
-
const subscription = customerCenterEventEmitter
|
551
|
+
const subscription = customerCenterEventEmitter?.addListener(
|
440
552
|
'onRefundRequestStarted',
|
441
|
-
(event: { productIdentifier: string }) => callbacks.onRefundRequestStarted &&
|
553
|
+
(event: { productIdentifier: string }) => callbacks.onRefundRequestStarted &&
|
442
554
|
callbacks.onRefundRequestStarted(event)
|
443
555
|
);
|
444
|
-
|
556
|
+
if (subscription) {
|
557
|
+
subscriptions.push(subscription);
|
558
|
+
}
|
445
559
|
}
|
446
560
|
|
447
561
|
if (callbacks.onRefundRequestCompleted) {
|
448
|
-
const subscription = customerCenterEventEmitter
|
562
|
+
const subscription = customerCenterEventEmitter?.addListener(
|
449
563
|
'onRefundRequestCompleted',
|
450
|
-
(event: { productIdentifier: string; refundRequestStatus: REFUND_REQUEST_STATUS }) => callbacks.onRefundRequestCompleted &&
|
564
|
+
(event: { productIdentifier: string; refundRequestStatus: REFUND_REQUEST_STATUS }) => callbacks.onRefundRequestCompleted &&
|
451
565
|
callbacks.onRefundRequestCompleted(event)
|
452
566
|
);
|
453
|
-
|
567
|
+
if (subscription) {
|
568
|
+
subscriptions.push(subscription);
|
569
|
+
}
|
454
570
|
}
|
455
571
|
|
456
572
|
if (callbacks.onManagementOptionSelected) {
|
457
|
-
const subscription = customerCenterEventEmitter
|
573
|
+
const subscription = customerCenterEventEmitter?.addListener(
|
458
574
|
'onManagementOptionSelected',
|
459
|
-
(event: CustomerCenterManagementOptionEvent) => callbacks.onManagementOptionSelected &&
|
575
|
+
(event: CustomerCenterManagementOptionEvent) => callbacks.onManagementOptionSelected &&
|
460
576
|
callbacks.onManagementOptionSelected(event)
|
461
577
|
);
|
462
|
-
|
578
|
+
if (subscription) {
|
579
|
+
subscriptions.push(subscription);
|
580
|
+
}
|
463
581
|
}
|
464
582
|
|
465
583
|
// Return a promise that resolves when the customer center is dismissed
|
@@ -478,7 +596,7 @@ export default class RevenueCatUI {
|
|
478
596
|
*/
|
479
597
|
public static PaywallFooterContainerView: React.FC<FooterPaywallViewProps> =
|
480
598
|
RevenueCatUI.OriginalTemplatePaywallFooterContainerView;
|
481
|
-
|
599
|
+
|
482
600
|
private static logWarningIfPreviewAPIMode(methodName: string) {
|
483
601
|
if (usingPreviewAPIMode) {
|
484
602
|
// tslint:disable-next-line:no-console
|
@@ -0,0 +1,171 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { View, Text, StyleSheet, TouchableOpacity } from 'react-native';
|
3
|
+
import {
|
4
|
+
type CustomerInfo,
|
5
|
+
type PurchasesError,
|
6
|
+
type PurchasesOffering,
|
7
|
+
type PurchasesPackage,
|
8
|
+
type PurchasesStoreTransaction,
|
9
|
+
} from "@revenuecat/purchases-typescript-internal";
|
10
|
+
|
11
|
+
export interface PreviewPaywallProps {
|
12
|
+
offering?: PurchasesOffering | null;
|
13
|
+
displayCloseButton?: boolean;
|
14
|
+
fontFamily?: string | null;
|
15
|
+
onPurchaseStarted?: ({packageBeingPurchased}: { packageBeingPurchased: PurchasesPackage }) => void;
|
16
|
+
onPurchaseCompleted?: ({
|
17
|
+
customerInfo,
|
18
|
+
storeTransaction
|
19
|
+
}: { customerInfo: CustomerInfo, storeTransaction: PurchasesStoreTransaction }) => void;
|
20
|
+
onPurchaseError?: ({error}: { error: PurchasesError }) => void;
|
21
|
+
onPurchaseCancelled?: () => void;
|
22
|
+
onRestoreStarted?: () => void;
|
23
|
+
onRestoreCompleted?: ({customerInfo}: { customerInfo: CustomerInfo }) => void;
|
24
|
+
onRestoreError?: ({error}: { error: PurchasesError }) => void;
|
25
|
+
onDismiss?: () => void;
|
26
|
+
}
|
27
|
+
|
28
|
+
export const PreviewPaywall: React.FC<PreviewPaywallProps> = ({
|
29
|
+
displayCloseButton = true,
|
30
|
+
fontFamily,
|
31
|
+
onDismiss,
|
32
|
+
}) => {
|
33
|
+
const handleClose = () => {
|
34
|
+
onDismiss?.();
|
35
|
+
};
|
36
|
+
|
37
|
+
const textStyle = fontFamily ? { fontFamily } : undefined;
|
38
|
+
|
39
|
+
return (
|
40
|
+
<View style={styles.container}>
|
41
|
+
<View style={styles.header}>
|
42
|
+
<Text style={[styles.title, textStyle]}>
|
43
|
+
Preview Paywall
|
44
|
+
</Text>
|
45
|
+
{displayCloseButton && (
|
46
|
+
<TouchableOpacity onPress={handleClose} style={styles.closeButton}>
|
47
|
+
<Text style={styles.closeButtonText}>✕</Text>
|
48
|
+
</TouchableOpacity>
|
49
|
+
)}
|
50
|
+
</View>
|
51
|
+
|
52
|
+
<View style={styles.content}>
|
53
|
+
<Text style={[styles.notSupportedMessage, textStyle]}>
|
54
|
+
Web paywalls are not supported yet.
|
55
|
+
</Text>
|
56
|
+
<Text style={[styles.fakeMessage, textStyle]}>
|
57
|
+
This is a fake preview implementation.
|
58
|
+
</Text>
|
59
|
+
<Text style={[styles.previewMode, textStyle]}>
|
60
|
+
Currently in preview mode
|
61
|
+
</Text>
|
62
|
+
|
63
|
+
<TouchableOpacity style={styles.closePaywallButton} onPress={handleClose}>
|
64
|
+
<Text style={[styles.closePaywallButtonText, textStyle]}>
|
65
|
+
Close Paywall
|
66
|
+
</Text>
|
67
|
+
</TouchableOpacity>
|
68
|
+
</View>
|
69
|
+
</View>
|
70
|
+
);
|
71
|
+
};
|
72
|
+
|
73
|
+
const styles = StyleSheet.create({
|
74
|
+
container: {
|
75
|
+
flex: 1,
|
76
|
+
backgroundColor: '#ffffff',
|
77
|
+
borderRadius: 12,
|
78
|
+
overflow: 'hidden',
|
79
|
+
maxWidth: 400,
|
80
|
+
maxHeight: 600,
|
81
|
+
},
|
82
|
+
header: {
|
83
|
+
flexDirection: 'row',
|
84
|
+
justifyContent: 'space-between',
|
85
|
+
alignItems: 'center',
|
86
|
+
padding: 20,
|
87
|
+
borderBottomWidth: 1,
|
88
|
+
borderBottomColor: '#e0e0e0',
|
89
|
+
},
|
90
|
+
title: {
|
91
|
+
fontSize: 24,
|
92
|
+
fontWeight: 'bold',
|
93
|
+
color: '#333333',
|
94
|
+
},
|
95
|
+
closeButton: {
|
96
|
+
width: 30,
|
97
|
+
height: 30,
|
98
|
+
borderRadius: 15,
|
99
|
+
backgroundColor: '#f0f0f0',
|
100
|
+
justifyContent: 'center',
|
101
|
+
alignItems: 'center',
|
102
|
+
},
|
103
|
+
closeButtonText: {
|
104
|
+
fontSize: 16,
|
105
|
+
color: '#666666',
|
106
|
+
},
|
107
|
+
content: {
|
108
|
+
flex: 1,
|
109
|
+
padding: 20,
|
110
|
+
justifyContent: 'center',
|
111
|
+
alignItems: 'center',
|
112
|
+
},
|
113
|
+
notSupportedMessage: {
|
114
|
+
fontSize: 18,
|
115
|
+
fontWeight: 'bold',
|
116
|
+
color: '#333333',
|
117
|
+
textAlign: 'center',
|
118
|
+
marginBottom: 16,
|
119
|
+
},
|
120
|
+
fakeMessage: {
|
121
|
+
fontSize: 16,
|
122
|
+
color: '#666666',
|
123
|
+
textAlign: 'center',
|
124
|
+
marginBottom: 8,
|
125
|
+
},
|
126
|
+
previewMode: {
|
127
|
+
fontSize: 14,
|
128
|
+
color: '#999999',
|
129
|
+
textAlign: 'center',
|
130
|
+
marginBottom: 32,
|
131
|
+
},
|
132
|
+
closePaywallButton: {
|
133
|
+
backgroundColor: '#007AFF',
|
134
|
+
padding: 16,
|
135
|
+
borderRadius: 8,
|
136
|
+
minWidth: 120,
|
137
|
+
alignItems: 'center',
|
138
|
+
},
|
139
|
+
closePaywallButtonText: {
|
140
|
+
fontSize: 16,
|
141
|
+
fontWeight: 'bold',
|
142
|
+
color: '#ffffff',
|
143
|
+
},
|
144
|
+
description: {
|
145
|
+
fontSize: 16,
|
146
|
+
color: '#666666',
|
147
|
+
marginBottom: 20,
|
148
|
+
textAlign: 'center',
|
149
|
+
},
|
150
|
+
optionButton: {
|
151
|
+
backgroundColor: '#f8f9fa',
|
152
|
+
padding: 16,
|
153
|
+
borderRadius: 8,
|
154
|
+
marginBottom: 12,
|
155
|
+
alignItems: 'center',
|
156
|
+
},
|
157
|
+
optionButtonText: {
|
158
|
+
fontSize: 16,
|
159
|
+
color: '#333333',
|
160
|
+
},
|
161
|
+
footer: {
|
162
|
+
padding: 20,
|
163
|
+
borderTopWidth: 1,
|
164
|
+
borderTopColor: '#e0e0e0',
|
165
|
+
},
|
166
|
+
disclaimer: {
|
167
|
+
fontSize: 12,
|
168
|
+
color: '#999999',
|
169
|
+
textAlign: 'center',
|
170
|
+
},
|
171
|
+
});
|
package/src/utils/environment.ts
CHANGED
@@ -1,18 +1,22 @@
|
|
1
|
-
import { NativeModules } from "react-native";
|
1
|
+
import { NativeModules, Platform } from "react-native";
|
2
2
|
|
3
3
|
/**
|
4
4
|
* Detects if the app is running in an environment where native modules are not available
|
5
|
-
* (like Expo Go) or if the required native modules are missing.
|
5
|
+
* (like Expo Go or Web) or if the required native modules are missing.
|
6
6
|
*
|
7
7
|
* @returns {boolean} True if the app is running in an environment where native modules are not available
|
8
|
-
* (like Expo Go) or if the required native modules are missing.
|
8
|
+
* (like Expo Go or Web) or if the required native modules are missing.
|
9
9
|
*/
|
10
10
|
export function shouldUsePreviewAPIMode(): boolean {
|
11
|
-
|
12
|
-
if (usePreviewAPIMode) {
|
11
|
+
if (isExpoGo()) {
|
13
12
|
console.log('Expo Go app detected. Using RevenueCat in Preview API Mode.');
|
13
|
+
return true;
|
14
|
+
} else if (isWebPlatform()) {
|
15
|
+
console.log('Web platform detected. Using RevenueCat in Preview API Mode.');
|
16
|
+
return true;
|
17
|
+
} else {
|
18
|
+
return false;
|
14
19
|
}
|
15
|
-
return usePreviewAPIMode;
|
16
20
|
}
|
17
21
|
|
18
22
|
declare global {
|
@@ -32,4 +36,11 @@ function isExpoGo(): boolean {
|
|
32
36
|
}
|
33
37
|
|
34
38
|
return !!globalThis.expo?.modules?.ExpoGo;
|
39
|
+
}
|
40
|
+
|
41
|
+
/**
|
42
|
+
* Detects if the app is running on web platform
|
43
|
+
*/
|
44
|
+
function isWebPlatform(): boolean {
|
45
|
+
return Platform.OS === 'web';
|
35
46
|
}
|