expo-helium 0.8.5 → 3.0.5
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/build/HeliumPaywallSdk.types.d.ts +95 -5
- package/build/HeliumPaywallSdk.types.d.ts.map +1 -1
- package/build/HeliumPaywallSdk.types.js.map +1 -1
- package/build/HeliumPaywallSdkModule.d.ts +2 -1
- package/build/HeliumPaywallSdkModule.d.ts.map +1 -1
- package/build/HeliumPaywallSdkModule.js.map +1 -1
- package/build/index.d.ts +3 -6
- package/build/index.d.ts.map +1 -1
- package/build/index.js +138 -25
- package/build/index.js.map +1 -1
- package/build/revenuecat/revenuecat.d.ts.map +1 -1
- package/build/revenuecat/revenuecat.js +6 -4
- package/build/revenuecat/revenuecat.js.map +1 -1
- package/ios/HeliumPaywallSdk.podspec +1 -1
- package/ios/HeliumPaywallSdkModule.swift +129 -57
- package/package.json +1 -1
- package/src/HeliumPaywallSdk.types.ts +110 -6
- package/src/HeliumPaywallSdkModule.ts +6 -1
- package/src/index.ts +144 -35
- package/src/revenuecat/revenuecat.ts +7 -3
package/src/index.ts
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
DelegateActionEvent,
|
|
3
3
|
HeliumConfig,
|
|
4
4
|
HeliumPaywallEvent,
|
|
5
|
-
NativeHeliumConfig, PaywallInfo,
|
|
5
|
+
NativeHeliumConfig, PaywallEventHandlers, PaywallInfo, PresentUpsellParams,
|
|
6
6
|
} from "./HeliumPaywallSdk.types";
|
|
7
7
|
import HeliumPaywallSdkModule from "./HeliumPaywallSdkModule";
|
|
8
8
|
import { EventSubscription } from 'expo-modules-core';
|
|
@@ -20,6 +20,10 @@ function addDelegateActionEventListener(listener: (event: DelegateActionEvent) =
|
|
|
20
20
|
return HeliumPaywallSdkModule.addListener('onDelegateActionEvent', listener);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
function addPaywallEventHandlersListener(listener: (event: HeliumPaywallEvent) => void): EventSubscription {
|
|
24
|
+
return HeliumPaywallSdkModule.addListener('paywallEventHandlers', listener);
|
|
25
|
+
}
|
|
26
|
+
|
|
23
27
|
let isInitialized = false;
|
|
24
28
|
export const initialize = (config: HeliumConfig) => {
|
|
25
29
|
if (isInitialized) {
|
|
@@ -29,36 +33,44 @@ export const initialize = (config: HeliumConfig) => {
|
|
|
29
33
|
|
|
30
34
|
HeliumPaywallSdkModule.removeAllListeners('onHeliumPaywallEvent');
|
|
31
35
|
HeliumPaywallSdkModule.removeAllListeners('onDelegateActionEvent');
|
|
36
|
+
HeliumPaywallSdkModule.removeAllListeners('paywallEventHandlers');
|
|
32
37
|
|
|
33
38
|
// Set up listener for paywall events
|
|
34
39
|
addHeliumPaywallEventListener((event) => {
|
|
40
|
+
handlePaywallEvent(event);
|
|
35
41
|
config.onHeliumPaywallEvent(event);
|
|
36
42
|
});
|
|
37
43
|
|
|
38
44
|
// Set up delegate action listener for purchase and restore operations
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
const purchaseConfig = config.purchaseConfig;
|
|
46
|
+
if (purchaseConfig) {
|
|
47
|
+
addDelegateActionEventListener(async (event) => {
|
|
48
|
+
try {
|
|
49
|
+
if (event.type === 'purchase') {
|
|
50
|
+
if (event.productId) {
|
|
51
|
+
const result = await purchaseConfig.makePurchase(event.productId);
|
|
52
|
+
HeliumPaywallSdkModule.handlePurchaseResult(result.status, result.error);
|
|
53
|
+
} else {
|
|
54
|
+
HeliumPaywallSdkModule.handlePurchaseResult('failed', 'No product ID for purchase event.');
|
|
55
|
+
}
|
|
56
|
+
} else if (event.type === 'restore') {
|
|
57
|
+
const success = await purchaseConfig.restorePurchases();
|
|
58
|
+
HeliumPaywallSdkModule.handleRestoreResult(success);
|
|
59
|
+
}
|
|
60
|
+
} catch (error) {
|
|
61
|
+
// Send failure result based on action type
|
|
62
|
+
if (event.type === 'purchase') {
|
|
63
|
+
console.log('[Helium] Unexpected error: ', error);
|
|
64
|
+
HeliumPaywallSdkModule.handlePurchaseResult('failed');
|
|
65
|
+
} else if (event.type === 'restore') {
|
|
66
|
+
HeliumPaywallSdkModule.handleRestoreResult(false);
|
|
47
67
|
}
|
|
48
68
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
// Send failure result based on action type
|
|
55
|
-
if (event.type === 'purchase') {
|
|
56
|
-
console.log('[Helium] Unexpected error: ', error);
|
|
57
|
-
HeliumPaywallSdkModule.handlePurchaseResult('failed');
|
|
58
|
-
} else if (event.type === 'restore') {
|
|
59
|
-
HeliumPaywallSdkModule.handleRestoreResult(false);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
addPaywallEventHandlersListener((event) => {
|
|
73
|
+
callPaywallEventHandlers(event);
|
|
62
74
|
});
|
|
63
75
|
|
|
64
76
|
nativeInitializeAsync(config).catch(error => {
|
|
@@ -95,24 +107,27 @@ const nativeInitializeAsync = async (config: HeliumConfig) => {
|
|
|
95
107
|
apiKey: config.apiKey,
|
|
96
108
|
customUserId: config.customUserId,
|
|
97
109
|
customAPIEndpoint: config.customAPIEndpoint,
|
|
98
|
-
customUserTraits: config.customUserTraits,
|
|
110
|
+
customUserTraits: convertBooleansToMarkers(config.customUserTraits),
|
|
99
111
|
revenueCatAppUserId: config.revenueCatAppUserId,
|
|
100
112
|
fallbackBundleUrlString: fallbackBundleUrlString,
|
|
101
113
|
fallbackBundleString: fallbackBundleString,
|
|
114
|
+
paywallLoadingConfig: convertBooleansToMarkers(config.paywallLoadingConfig),
|
|
115
|
+
useDefaultDelegate: !config.purchaseConfig,
|
|
102
116
|
};
|
|
103
117
|
|
|
104
118
|
// Initialize the native module
|
|
105
119
|
HeliumPaywallSdkModule.initialize(nativeConfig);
|
|
106
120
|
};
|
|
107
121
|
|
|
122
|
+
let paywallEventHandlers: PaywallEventHandlers | undefined;
|
|
123
|
+
let presentOnFallback: (() => void) | undefined;
|
|
108
124
|
export const presentUpsell = ({
|
|
109
125
|
triggerName,
|
|
110
|
-
onFallback
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
const { canPresent, reason } = HeliumPaywallSdkModule.canPresentUpsell(triggerName);
|
|
126
|
+
onFallback,
|
|
127
|
+
eventHandlers,
|
|
128
|
+
customPaywallTraits,
|
|
129
|
+
}: PresentUpsellParams) => {
|
|
130
|
+
const {canPresent, reason} = HeliumPaywallSdkModule.canPresentUpsell(triggerName);
|
|
116
131
|
|
|
117
132
|
if (!canPresent) {
|
|
118
133
|
console.log(
|
|
@@ -124,17 +139,83 @@ export const presentUpsell = ({
|
|
|
124
139
|
}
|
|
125
140
|
|
|
126
141
|
try {
|
|
127
|
-
|
|
142
|
+
paywallEventHandlers = eventHandlers;
|
|
143
|
+
presentOnFallback = onFallback;
|
|
144
|
+
HeliumPaywallSdkModule.presentUpsell(triggerName, convertBooleansToMarkers(customPaywallTraits));
|
|
128
145
|
} catch (error) {
|
|
129
146
|
console.log('Helium present error', error);
|
|
147
|
+
paywallEventHandlers = undefined;
|
|
148
|
+
presentOnFallback = undefined;
|
|
130
149
|
onFallback?.();
|
|
131
150
|
HeliumPaywallSdkModule.fallbackOpenOrCloseEvent(triggerName, true, 'presented');
|
|
132
151
|
}
|
|
133
152
|
};
|
|
134
153
|
|
|
154
|
+
function callPaywallEventHandlers(event: HeliumPaywallEvent) {
|
|
155
|
+
if (paywallEventHandlers) {
|
|
156
|
+
switch (event.type) {
|
|
157
|
+
case 'paywallOpen':
|
|
158
|
+
paywallEventHandlers?.onOpen?.({
|
|
159
|
+
type: 'paywallOpen',
|
|
160
|
+
triggerName: event.triggerName ?? 'unknown',
|
|
161
|
+
paywallName: event.paywallName ?? 'unknown',
|
|
162
|
+
isSecondTry: event.isSecondTry ?? false,
|
|
163
|
+
viewType: 'presented',
|
|
164
|
+
});
|
|
165
|
+
break;
|
|
166
|
+
case 'paywallClose':
|
|
167
|
+
paywallEventHandlers?.onClose?.({
|
|
168
|
+
type: 'paywallClose',
|
|
169
|
+
triggerName: event.triggerName ?? 'unknown',
|
|
170
|
+
paywallName: event.paywallName ?? 'unknown',
|
|
171
|
+
isSecondTry: event.isSecondTry ?? false,
|
|
172
|
+
});
|
|
173
|
+
break;
|
|
174
|
+
case 'paywallDismissed':
|
|
175
|
+
paywallEventHandlers?.onDismissed?.({
|
|
176
|
+
type: 'paywallDismissed',
|
|
177
|
+
triggerName: event.triggerName ?? 'unknown',
|
|
178
|
+
paywallName: event.paywallName ?? 'unknown',
|
|
179
|
+
isSecondTry: event.isSecondTry ?? false,
|
|
180
|
+
});
|
|
181
|
+
break;
|
|
182
|
+
case 'purchaseSucceeded':
|
|
183
|
+
paywallEventHandlers?.onPurchaseSucceeded?.({
|
|
184
|
+
type: 'purchaseSucceeded',
|
|
185
|
+
productId: event.productId ?? 'unknown',
|
|
186
|
+
triggerName: event.triggerName ?? 'unknown',
|
|
187
|
+
paywallName: event.paywallName ?? 'unknown',
|
|
188
|
+
isSecondTry: event.isSecondTry ?? false,
|
|
189
|
+
});
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function handlePaywallEvent(event: HeliumPaywallEvent) {
|
|
196
|
+
switch (event.type) {
|
|
197
|
+
case 'paywallClose':
|
|
198
|
+
if (!event.isSecondTry) {
|
|
199
|
+
paywallEventHandlers = undefined;
|
|
200
|
+
}
|
|
201
|
+
presentOnFallback = undefined;
|
|
202
|
+
break;
|
|
203
|
+
case 'paywallSkipped':
|
|
204
|
+
paywallEventHandlers = undefined;
|
|
205
|
+
presentOnFallback = undefined;
|
|
206
|
+
break;
|
|
207
|
+
case 'paywallOpenFailed':
|
|
208
|
+
paywallEventHandlers = undefined;
|
|
209
|
+
presentOnFallback?.();
|
|
210
|
+
presentOnFallback = undefined;
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
135
215
|
export const hideUpsell = HeliumPaywallSdkModule.hideUpsell;
|
|
136
216
|
export const hideAllUpsells = HeliumPaywallSdkModule.hideAllUpsells;
|
|
137
217
|
export const getDownloadStatus = HeliumPaywallSdkModule.getDownloadStatus;
|
|
218
|
+
export const setRevenueCatAppUserId = HeliumPaywallSdkModule.setRevenueCatAppUserId;
|
|
138
219
|
|
|
139
220
|
export const getPaywallInfo = (trigger: string): PaywallInfo | undefined => {
|
|
140
221
|
const result = HeliumPaywallSdkModule.getPaywallInfo(trigger);
|
|
@@ -161,9 +242,37 @@ export const handleDeepLink = (url: string | null) => {
|
|
|
161
242
|
return false;
|
|
162
243
|
};
|
|
163
244
|
|
|
164
|
-
|
|
245
|
+
/**
|
|
246
|
+
* Recursively converts boolean values to special marker strings to preserve
|
|
247
|
+
* type information when passing through native bridge.
|
|
248
|
+
*
|
|
249
|
+
* Native bridge converts booleans to NSNumber (0/1), making them
|
|
250
|
+
* indistinguishable from actual numeric values. This helper converts:
|
|
251
|
+
* - true -> "__helium_rn_bool_true__"
|
|
252
|
+
* - false -> "__helium_rn_bool_false__"
|
|
253
|
+
* - All other values remain unchanged
|
|
254
|
+
*/
|
|
255
|
+
function convertBooleansToMarkers(input: Record<string, any> | undefined): Record<string, any> | undefined {
|
|
256
|
+
if (!input) return undefined;
|
|
165
257
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
}
|
|
258
|
+
const result: Record<string, any> = {};
|
|
259
|
+
for (const [key, value] of Object.entries(input)) {
|
|
260
|
+
result[key] = convertValueBooleansToMarkers(value);
|
|
261
|
+
}
|
|
262
|
+
return result;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Helper to recursively convert booleans in any value type
|
|
266
|
+
*/
|
|
267
|
+
function convertValueBooleansToMarkers(value: any): any {
|
|
268
|
+
if (typeof value === 'boolean') {
|
|
269
|
+
return value ? "__helium_rn_bool_true__" : "__helium_rn_bool_false__";
|
|
270
|
+
} else if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
271
|
+
return convertBooleansToMarkers(value);
|
|
272
|
+
} else if (value && Array.isArray(value)) {
|
|
273
|
+
return value.map(convertValueBooleansToMarkers);
|
|
274
|
+
}
|
|
275
|
+
return value;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export {createCustomPurchaseConfig, HELIUM_CTA_NAMES} from './HeliumPaywallSdk.types';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import Purchases, {PURCHASES_ERROR_CODE, PurchasesStoreProduct} from 'react-native-purchases';
|
|
2
2
|
import type { PurchasesError, PurchasesPackage, CustomerInfoUpdateListener, CustomerInfo, PurchasesEntitlementInfo } from 'react-native-purchases';
|
|
3
3
|
import {HeliumPurchaseConfig, HeliumPurchaseResult} from "../HeliumPaywallSdk.types";
|
|
4
|
+
import {setRevenueCatAppUserId} from "../index";
|
|
4
5
|
|
|
5
6
|
// Rename the factory function
|
|
6
7
|
export function createRevenueCatPurchaseConfig(config?: {
|
|
@@ -8,7 +9,6 @@ export function createRevenueCatPurchaseConfig(config?: {
|
|
|
8
9
|
}): HeliumPurchaseConfig {
|
|
9
10
|
const rcHandler = new RevenueCatHeliumHandler(config?.apiKey);
|
|
10
11
|
return {
|
|
11
|
-
apiKey: config?.apiKey,
|
|
12
12
|
makePurchase: rcHandler.makePurchase.bind(rcHandler),
|
|
13
13
|
restorePurchases: rcHandler.restorePurchases.bind(rcHandler),
|
|
14
14
|
};
|
|
@@ -24,9 +24,8 @@ export class RevenueCatHeliumHandler {
|
|
|
24
24
|
constructor(apiKey?: string) {
|
|
25
25
|
if (apiKey) {
|
|
26
26
|
Purchases.configure({ apiKey });
|
|
27
|
-
} else {
|
|
28
27
|
}
|
|
29
|
-
this.initializePackageMapping();
|
|
28
|
+
void this.initializePackageMapping();
|
|
30
29
|
}
|
|
31
30
|
|
|
32
31
|
private async initializePackageMapping(): Promise<void> {
|
|
@@ -35,6 +34,9 @@ export class RevenueCatHeliumHandler {
|
|
|
35
34
|
}
|
|
36
35
|
this.initializationPromise = (async () => {
|
|
37
36
|
try {
|
|
37
|
+
// Keep this value as up-to-date as possible
|
|
38
|
+
setRevenueCatAppUserId(await Purchases.getAppUserID());
|
|
39
|
+
|
|
38
40
|
const offerings = await Purchases.getOfferings();
|
|
39
41
|
const allOfferings = offerings.all;
|
|
40
42
|
for (const offering of Object.values(allOfferings)) {
|
|
@@ -64,6 +66,8 @@ export class RevenueCatHeliumHandler {
|
|
|
64
66
|
|
|
65
67
|
async makePurchase(productId: string): Promise<HeliumPurchaseResult> {
|
|
66
68
|
await this.ensureMappingInitialized();
|
|
69
|
+
// Keep this value as up-to-date as possible
|
|
70
|
+
setRevenueCatAppUserId(await Purchases.getAppUserID());
|
|
67
71
|
|
|
68
72
|
const pkg: PurchasesPackage | undefined = this.productIdToPackageMapping[productId];
|
|
69
73
|
let rcProduct: PurchasesStoreProduct | undefined;
|