apps-sdk 1.1.90 → 1.1.92
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/package.json +2 -2
- package/src/components/AdaptyOnboarding.js +63 -55
- package/src/libraries/Adapty.js +1 -19
- package/types/index.d.ts +3 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { AdaptyOnboardingView } from 'react-native-adapty
|
|
3
|
-
import { View } from "react-native";
|
|
2
|
+
import { AdaptyOnboardingView } from 'react-native-adapty';
|
|
3
|
+
import { View, Platform } from "react-native";
|
|
4
4
|
import Adapty from '../libraries/Adapty';
|
|
5
5
|
import * as config from '../../config';
|
|
6
6
|
|
|
@@ -10,6 +10,7 @@ class AdaptyOnboarding extends React.Component {
|
|
|
10
10
|
this.state = {
|
|
11
11
|
onboarding: null,
|
|
12
12
|
isLoading: true,
|
|
13
|
+
webViewReady: false,
|
|
13
14
|
};
|
|
14
15
|
this.remoteConfig = null;
|
|
15
16
|
this.currentStep = 0;
|
|
@@ -19,28 +20,26 @@ class AdaptyOnboarding extends React.Component {
|
|
|
19
20
|
componentDidMount() {
|
|
20
21
|
const { preloadedOnboarding, placementID, lang } = this.props;
|
|
21
22
|
|
|
22
|
-
// If preloaded onboarding is provided, use it immediately (no loading screen!)
|
|
23
23
|
if (preloadedOnboarding) {
|
|
24
|
-
config.DEBUG_MODE && console.log('[ONBOARDING] Using preloaded onboarding data
|
|
24
|
+
config.DEBUG_MODE && console.log('[ONBOARDING] Using preloaded onboarding data');
|
|
25
25
|
this.remoteConfig = preloadedOnboarding.remoteConfig || {};
|
|
26
26
|
|
|
27
27
|
if (this.props.onRemoteConfigLoaded && this.remoteConfig) {
|
|
28
|
-
config.DEBUG_MODE && console.log('Remote config loaded from preload:', this.remoteConfig);
|
|
29
28
|
this.props.onRemoteConfigLoaded(this.remoteConfig);
|
|
30
29
|
}
|
|
31
30
|
|
|
32
31
|
this.setState({ onboarding: preloadedOnboarding, isLoading: false });
|
|
33
32
|
} else {
|
|
34
|
-
// Fallback to loading if not preloaded
|
|
35
|
-
config.DEBUG_MODE && console.log('[ONBOARDING] No preloaded data, loading normally');
|
|
36
33
|
this.loadOnboarding(placementID, lang);
|
|
37
34
|
}
|
|
38
35
|
}
|
|
39
36
|
|
|
40
37
|
async componentDidUpdate(prevProps) {
|
|
41
38
|
if (this.props.visible && !prevProps.visible) {
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
if (!this.state.onboarding) {
|
|
40
|
+
const { placementID, lang } = this.props;
|
|
41
|
+
await this.loadOnboarding(placementID, lang);
|
|
42
|
+
}
|
|
44
43
|
}
|
|
45
44
|
if (!this.props.visible && prevProps.visible) {
|
|
46
45
|
this.handleModalDismiss();
|
|
@@ -50,26 +49,24 @@ class AdaptyOnboarding extends React.Component {
|
|
|
50
49
|
loadOnboarding = async (placementID, lang) => {
|
|
51
50
|
try {
|
|
52
51
|
this.setState({ isLoading: true });
|
|
52
|
+
|
|
53
53
|
const onboarding = await Adapty.getOnboardingForPlacement(placementID, lang);
|
|
54
54
|
|
|
55
55
|
if (onboarding) {
|
|
56
56
|
this.remoteConfig = onboarding.remoteConfig || {};
|
|
57
57
|
|
|
58
58
|
if (this.props.onRemoteConfigLoaded && this.remoteConfig) {
|
|
59
|
-
config.DEBUG_MODE && console.log('Remote config loaded:', this.remoteConfig);
|
|
60
59
|
this.props.onRemoteConfigLoaded(this.remoteConfig);
|
|
61
60
|
}
|
|
62
61
|
|
|
63
62
|
this.setState({ onboarding, isLoading: false });
|
|
64
63
|
} else {
|
|
65
|
-
console.log('Onboarding not found for placement:', placementID, 'and language:', lang);
|
|
66
64
|
this.setState({ isLoading: false });
|
|
67
65
|
if (this.props.onError) {
|
|
68
66
|
this.props.onError(new Error('Onboarding not found'), this.remoteConfig);
|
|
69
67
|
}
|
|
70
68
|
}
|
|
71
69
|
} catch (error) {
|
|
72
|
-
console.log('Error loading onboarding:', error);
|
|
73
70
|
this.setState({ isLoading: false });
|
|
74
71
|
if (this.props.onError) {
|
|
75
72
|
this.props.onError(error, this.remoteConfig);
|
|
@@ -79,33 +76,22 @@ class AdaptyOnboarding extends React.Component {
|
|
|
79
76
|
|
|
80
77
|
// --------------------------------------- Event Handlers ---------------------------------------
|
|
81
78
|
handleCustom = (actionId, meta) => {
|
|
82
|
-
config.DEBUG_MODE && console.log('Onboarding custom AdaptyOnboarding:', actionId, meta);
|
|
83
|
-
|
|
84
79
|
if (this.props.onCustom) {
|
|
85
80
|
this.props.onCustom(actionId, meta, this.remoteConfig);
|
|
86
81
|
}
|
|
87
82
|
}
|
|
88
83
|
|
|
89
84
|
handleClose = (actionId, meta) => {
|
|
90
|
-
const isLastStep = this.totalSteps > 0 && this.currentStep === this.totalSteps - 1;
|
|
91
|
-
|
|
92
|
-
config.DEBUG_MODE && console.log('Onboarding close attempt AdaptyOnboarding:', {actionId, meta, currentStep: this.currentStep, totalSteps: this.totalSteps, isLastStep });
|
|
93
|
-
|
|
94
85
|
if (this.props.onClose) {
|
|
95
86
|
this.props.onClose(actionId, meta, this.remoteConfig);
|
|
96
87
|
}
|
|
97
|
-
|
|
98
88
|
return true;
|
|
99
89
|
}
|
|
100
90
|
|
|
101
91
|
handleModalDismiss = () => {
|
|
102
|
-
config.DEBUG_MODE && console.log('AdaptyOnboarding Modal fully dismissed');
|
|
103
|
-
|
|
104
|
-
// Reset state after modal is fully dismissed
|
|
105
92
|
this.currentStep = 0;
|
|
106
93
|
this.totalSteps = 0;
|
|
107
94
|
|
|
108
|
-
// Notify parent that modal is fully closed
|
|
109
95
|
if (this.props.onModalDismissed) {
|
|
110
96
|
this.props.onModalDismissed();
|
|
111
97
|
}
|
|
@@ -115,8 +101,6 @@ class AdaptyOnboarding extends React.Component {
|
|
|
115
101
|
if (meta && typeof meta === 'object') {
|
|
116
102
|
this.currentStep = meta.screen_index ?? this.currentStep;
|
|
117
103
|
this.totalSteps = meta.total_screens ?? this.totalSteps;
|
|
118
|
-
|
|
119
|
-
config.DEBUG_MODE && console.log('State updated AdaptyOnboarding:', {action, meta, currentStep: this.currentStep, totalSteps: this.totalSteps});
|
|
120
104
|
}
|
|
121
105
|
|
|
122
106
|
if (this.props.onStateUpdated) {
|
|
@@ -125,15 +109,10 @@ class AdaptyOnboarding extends React.Component {
|
|
|
125
109
|
}
|
|
126
110
|
|
|
127
111
|
handleError = (error) => {
|
|
128
|
-
console.log('Onboarding error:', error);
|
|
129
|
-
|
|
130
|
-
// Check if it's a WebResource ORB error (common on Android)
|
|
131
112
|
const isORBError = error?.message?.includes('ERR_BLOCKED_BY_ORB');
|
|
132
113
|
|
|
133
114
|
if (isORBError) {
|
|
134
|
-
|
|
135
|
-
// Don't propagate ORB errors as they don't break functionality
|
|
136
|
-
return false; // Continue
|
|
115
|
+
return false;
|
|
137
116
|
}
|
|
138
117
|
|
|
139
118
|
if (this.props.onError) {
|
|
@@ -143,23 +122,32 @@ class AdaptyOnboarding extends React.Component {
|
|
|
143
122
|
}
|
|
144
123
|
|
|
145
124
|
handleAnalytics = (event, data) => {
|
|
146
|
-
|
|
147
|
-
|
|
125
|
+
// Available events from Adapty:
|
|
126
|
+
// - onboarding_started (screenIndex: 0, totalScreens: 4)
|
|
127
|
+
// - screen_presented (screenIndex: 0-3, totalScreens: 4) - fires for each screen
|
|
128
|
+
// - screen_completed (screenIndex: 0-2) - fires when leaving a screen
|
|
129
|
+
//
|
|
130
|
+
// To track these events: Access event.name and data.screenIndex in onAnalytics callback
|
|
131
|
+
// Example: if (event?.name === 'screen_presented') { track(data.screenIndex) }
|
|
132
|
+
|
|
148
133
|
if (this.props.onAnalytics) {
|
|
149
134
|
this.props.onAnalytics(event, data, this.remoteConfig);
|
|
150
135
|
}
|
|
151
136
|
}
|
|
152
137
|
|
|
153
138
|
handlePaywall = (actionId, meta) => {
|
|
154
|
-
config.DEBUG_MODE && console.log('Onboarding paywall AdaptyOnboarding:', actionId, meta);
|
|
155
|
-
|
|
156
139
|
if (this.props.onPaywall) {
|
|
157
140
|
this.props.onPaywall(actionId, meta, this.remoteConfig);
|
|
158
141
|
}
|
|
159
142
|
}
|
|
160
143
|
|
|
161
144
|
handleFinishedLoading = (meta) => {
|
|
162
|
-
|
|
145
|
+
// Prop: loaderMaskDelay - Delay before showing onboarding content (default: 300ms)
|
|
146
|
+
const delay = this.props.loaderMaskDelay ?? 300;
|
|
147
|
+
|
|
148
|
+
setTimeout(() => {
|
|
149
|
+
this.setState({ webViewReady: true });
|
|
150
|
+
}, delay);
|
|
163
151
|
|
|
164
152
|
if (this.props.onFinishedLoading) {
|
|
165
153
|
this.props.onFinishedLoading(meta, this.remoteConfig);
|
|
@@ -169,39 +157,59 @@ class AdaptyOnboarding extends React.Component {
|
|
|
169
157
|
|
|
170
158
|
render() {
|
|
171
159
|
const { visible } = this.props;
|
|
172
|
-
const { onboarding, isLoading } = this.state;
|
|
160
|
+
const { onboarding, isLoading, webViewReady } = this.state;
|
|
173
161
|
|
|
174
162
|
if (!visible) {
|
|
175
163
|
return null;
|
|
176
164
|
}
|
|
177
165
|
|
|
178
|
-
|
|
166
|
+
// Prop: loaderMaskColor - Background color for the loader mask (default: '#121212')
|
|
167
|
+
const maskColor = this.props.loaderMaskColor || '#121212';
|
|
168
|
+
|
|
169
|
+
return (
|
|
179
170
|
<View style={styles.container}>
|
|
171
|
+
{/* Loader mask: Hides WebView white loader without blocking touch events */}
|
|
172
|
+
{!webViewReady && onboarding && (
|
|
173
|
+
<View style={[styles.loaderMask, { backgroundColor: maskColor }]} />
|
|
174
|
+
)}
|
|
175
|
+
|
|
180
176
|
{!isLoading && onboarding ? (
|
|
181
|
-
<
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
onAnalytics
|
|
186
|
-
onClose
|
|
187
|
-
onCustom
|
|
188
|
-
onPaywall
|
|
189
|
-
onStateUpdated
|
|
190
|
-
onFinishedLoading
|
|
191
|
-
onError
|
|
192
|
-
|
|
193
|
-
|
|
177
|
+
<View style={styles.onboardingWrapper}>
|
|
178
|
+
<AdaptyOnboardingView
|
|
179
|
+
onboarding={onboarding}
|
|
180
|
+
style={styles.onboardingView}
|
|
181
|
+
onAnalytics={this.handleAnalytics}
|
|
182
|
+
onClose={this.handleClose}
|
|
183
|
+
onCustom={this.handleCustom}
|
|
184
|
+
onPaywall={this.handlePaywall}
|
|
185
|
+
onStateUpdated={this.handleStateUpdated}
|
|
186
|
+
onFinishedLoading={this.handleFinishedLoading}
|
|
187
|
+
onError={this.handleError}
|
|
188
|
+
/>
|
|
189
|
+
</View>
|
|
194
190
|
) : null}
|
|
195
191
|
</View>
|
|
196
192
|
);
|
|
197
|
-
|
|
198
|
-
return content;
|
|
199
193
|
}
|
|
200
194
|
}
|
|
201
195
|
|
|
202
196
|
const styles = {
|
|
203
197
|
container: {
|
|
204
|
-
backgroundColor: '#
|
|
198
|
+
backgroundColor: '#121212',
|
|
199
|
+
flex: 1,
|
|
200
|
+
width: '100%',
|
|
201
|
+
height: '100%',
|
|
202
|
+
},
|
|
203
|
+
loaderMask: {
|
|
204
|
+
position: 'absolute',
|
|
205
|
+
top: 0,
|
|
206
|
+
left: 0,
|
|
207
|
+
right: 0,
|
|
208
|
+
bottom: 0,
|
|
209
|
+
zIndex: 10,
|
|
210
|
+
},
|
|
211
|
+
onboardingWrapper: {
|
|
212
|
+
flex: 1,
|
|
205
213
|
width: '100%',
|
|
206
214
|
height: '100%',
|
|
207
215
|
},
|
|
@@ -210,4 +218,4 @@ const styles = {
|
|
|
210
218
|
},
|
|
211
219
|
}
|
|
212
220
|
|
|
213
|
-
export default AdaptyOnboarding;
|
|
221
|
+
export default AdaptyOnboarding;
|
package/src/libraries/Adapty.js
CHANGED
|
@@ -245,24 +245,6 @@ class Adapty {
|
|
|
245
245
|
return onboarding !== null;
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
-
async preloadOnboarding(placementID, lang) {
|
|
249
|
-
try {
|
|
250
|
-
const onboarding = await this.getOnboardingForPlacement(placementID, lang);
|
|
251
|
-
if (onboarding) {
|
|
252
|
-
const onboardingView = await this.createOnboardingView(onboarding);
|
|
253
|
-
if (onboardingView) {
|
|
254
|
-
return onboardingView;
|
|
255
|
-
} else {
|
|
256
|
-
console.warn('Error preloading onboarding: onboarding view not created for placement', placementID, 'and language', lang);
|
|
257
|
-
return null;
|
|
258
|
-
}
|
|
259
|
-
} else {
|
|
260
|
-
console.warn('Error preloading onboarding: onboarding not found for placement', placementID, 'and language', lang);
|
|
261
|
-
}
|
|
262
|
-
} catch (error) {
|
|
263
|
-
console.error('Error preloading onboarding:', error);
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
248
|
|
|
267
249
|
async closeOnboarding() {
|
|
268
250
|
const onboardingView = await adapty.getCurrentOnboardingView();
|
|
@@ -299,4 +281,4 @@ class Adapty {
|
|
|
299
281
|
}
|
|
300
282
|
}
|
|
301
283
|
|
|
302
|
-
export default new Adapty();
|
|
284
|
+
export default new Adapty();
|
package/types/index.d.ts
CHANGED
|
@@ -228,6 +228,9 @@ declare module 'apps-sdk' {
|
|
|
228
228
|
visible: boolean;
|
|
229
229
|
placementID: string;
|
|
230
230
|
lang: string;
|
|
231
|
+
preloadedOnboarding?: any;
|
|
232
|
+
loaderMaskColor?: string; // Color of the mask that hides WebView loader (default: '#121212')
|
|
233
|
+
loaderMaskDelay?: number; // Delay in ms before showing content (default: 300ms)
|
|
231
234
|
onAnalytics?: (event: any, meta: any, remoteConfig?: any) => void;
|
|
232
235
|
onClose?: (actionId: string, meta: any, remoteConfig?: any) => Promise<boolean> | boolean;
|
|
233
236
|
onCustom?: (actionId: string, meta: any, remoteConfig?: any) => void;
|
|
@@ -259,7 +262,6 @@ declare module 'apps-sdk' {
|
|
|
259
262
|
createOnboardingView(onboarding: any): Promise<any>;
|
|
260
263
|
showOnboarding(placementID: string, lang: string, eventHandlers?: OnboardingEventHandlers): Promise<void>;
|
|
261
264
|
checkOnboardingExists(placementID: string, lang: string): Promise<boolean>;
|
|
262
|
-
preloadOnboarding(placementID: string, lang: string): Promise<any>;
|
|
263
265
|
closeOnboarding(): Promise<void>;
|
|
264
266
|
showOnboardingPreloaded(onboardingView: any, eventHandlers?: OnboardingEventHandlers): Promise<void>;
|
|
265
267
|
closePaywallFromView(paywallView: any): Promise<void>;
|