@adadapted/react-native-sdk 3.3.0 → 3.5.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.
Files changed (87) hide show
  1. package/android/bin/build.gradle +9 -8
  2. package/android/bin/gradle.properties +1 -1
  3. package/android/build.gradle +17 -80
  4. package/android/gradle.properties +2 -2
  5. package/android/src/main/java/com/adadaptedreactnativesdk/AdadaptedReactNativeSdkModule.kt +39 -54
  6. package/ios/AdadaptedReactNativeSdk.m +1 -1
  7. package/lib/commonjs/api/adadaptedApiRequests.js +12 -12
  8. package/lib/commonjs/api/adadaptedApiRequests.js.map +1 -1
  9. package/lib/commonjs/api/adadaptedApiRequests.mock.js.map +1 -1
  10. package/lib/commonjs/api/adadaptedApiTypes.js +5 -10
  11. package/lib/commonjs/api/adadaptedApiTypes.js.map +1 -1
  12. package/lib/commonjs/componentTypes/AdZone.js +11 -0
  13. package/lib/commonjs/componentTypes/AdZone.js.map +1 -0
  14. package/lib/commonjs/componentTypes/Device.js +22 -0
  15. package/lib/commonjs/componentTypes/Device.js.map +1 -0
  16. package/lib/commonjs/componentTypes/Environment.js +34 -0
  17. package/lib/commonjs/componentTypes/Environment.js.map +1 -0
  18. package/lib/commonjs/components/AdZone.js +76 -85
  19. package/lib/commonjs/components/AdZone.js.map +1 -1
  20. package/lib/commonjs/components/ReportAdButton.js +9 -7
  21. package/lib/commonjs/components/ReportAdButton.js.map +1 -1
  22. package/lib/commonjs/index.js +108 -132
  23. package/lib/commonjs/index.js.map +1 -1
  24. package/lib/commonjs/package.json +1 -0
  25. package/lib/commonjs/types.js.map +1 -1
  26. package/lib/commonjs/util.js +1 -4
  27. package/lib/commonjs/util.js.map +1 -1
  28. package/lib/module/api/adadaptedApiRequests.js +11 -9
  29. package/lib/module/api/adadaptedApiRequests.js.map +1 -1
  30. package/lib/module/api/adadaptedApiRequests.mock.js +2 -0
  31. package/lib/module/api/adadaptedApiRequests.mock.js.map +1 -1
  32. package/lib/module/api/adadaptedApiTypes.js +16 -0
  33. package/lib/module/api/adadaptedApiTypes.js.map +1 -1
  34. package/lib/module/componentTypes/AdZone.js +7 -0
  35. package/lib/module/componentTypes/AdZone.js.map +1 -0
  36. package/lib/module/componentTypes/Device.js +18 -0
  37. package/lib/module/componentTypes/Device.js.map +1 -0
  38. package/lib/module/componentTypes/Environment.js +30 -0
  39. package/lib/module/componentTypes/Environment.js.map +1 -0
  40. package/lib/module/components/AdZone.js +70 -80
  41. package/lib/module/components/AdZone.js.map +1 -1
  42. package/lib/module/components/ReportAdButton.js +9 -5
  43. package/lib/module/components/ReportAdButton.js.map +1 -1
  44. package/lib/module/index.js +102 -130
  45. package/lib/module/index.js.map +1 -1
  46. package/lib/module/package.json +1 -0
  47. package/lib/module/types.js +2 -0
  48. package/lib/module/types.js.map +1 -1
  49. package/lib/module/util.js +5 -5
  50. package/lib/module/util.js.map +1 -1
  51. package/lib/typescript/src/api/adadaptedApiRequests.d.ts +10 -9
  52. package/lib/typescript/src/api/adadaptedApiRequests.d.ts.map +1 -1
  53. package/lib/typescript/src/api/adadaptedApiTypes.d.ts +11 -0
  54. package/lib/typescript/src/api/adadaptedApiTypes.d.ts.map +1 -1
  55. package/lib/typescript/src/componentTypes/AdZone.d.ts +95 -0
  56. package/lib/typescript/src/componentTypes/AdZone.d.ts.map +1 -0
  57. package/lib/typescript/src/componentTypes/Device.d.ts +80 -0
  58. package/lib/typescript/src/componentTypes/Device.d.ts.map +1 -0
  59. package/lib/typescript/src/componentTypes/Environment.d.ts +57 -0
  60. package/lib/typescript/src/componentTypes/Environment.d.ts.map +1 -0
  61. package/lib/typescript/src/components/AdZone.d.ts +5 -54
  62. package/lib/typescript/src/components/AdZone.d.ts.map +1 -1
  63. package/lib/typescript/src/components/ReportAdButton.d.ts +2 -2
  64. package/lib/typescript/src/components/ReportAdButton.d.ts.map +1 -1
  65. package/lib/typescript/src/index.d.ts +34 -139
  66. package/lib/typescript/src/index.d.ts.map +1 -1
  67. package/package.json +10 -14
  68. package/src/api/adadaptedApiRequests.ts +25 -24
  69. package/src/api/adadaptedApiTypes.ts +11 -0
  70. package/src/componentTypes/AdZone.ts +97 -0
  71. package/src/componentTypes/Device.ts +79 -0
  72. package/src/componentTypes/Environment.ts +58 -0
  73. package/src/components/AdZone.tsx +82 -144
  74. package/src/components/ReportAdButton.tsx +1 -1
  75. package/src/index.tsx +168 -255
  76. package/lib/typescript/example/index.d.ts +0 -2
  77. package/lib/typescript/example/index.d.ts.map +0 -1
  78. package/lib/typescript/example/src/App.d.ts +0 -29
  79. package/lib/typescript/example/src/App.d.ts.map +0 -1
  80. package/lib/typescript/example/src/OffScreenAdZone.d.ts +0 -38
  81. package/lib/typescript/example/src/OffScreenAdZone.d.ts.map +0 -1
  82. package/lib/typescript/example/src/StandardAdZone.d.ts +0 -38
  83. package/lib/typescript/example/src/StandardAdZone.d.ts.map +0 -1
  84. package/lib/typescript/index.d.ts +0 -2
  85. package/lib/typescript/index.d.ts.map +0 -1
  86. package/lib/typescript/jest.setup.d.ts +0 -6
  87. package/lib/typescript/jest.setup.d.ts.map +0 -1
@@ -2,111 +2,15 @@
2
2
  * Component for creating an {@link AdZone}.
3
3
  * @module
4
4
  */
5
- import * as React from "react";
6
- import {
7
- DeviceEventEmitter,
8
- Linking,
9
- StyleSheet,
10
- View,
11
- ViewStyle,
12
- } from "react-native";
5
+ import React, { useEffect, useState } from "react";
6
+ import { DeviceEventEmitter, Linking, StyleSheet, View } from "react-native";
13
7
  import * as adadaptedApiRequests from "../api/adadaptedApiRequests";
14
- import {
15
- Ad,
16
- AdActionType,
17
- DetailedListItem,
18
- ReportedEventType,
19
- Zone,
20
- } from "../api/adadaptedApiTypes";
8
+ import { Ad, AdActionType, ReportedEventType } from "../api/adadaptedApiTypes";
21
9
  import { WebView } from "react-native-webview";
22
- import { ApiEnv, DeviceOS } from "../index";
23
10
  import { safeInvoke } from "../util";
24
- import { useEffect, useState } from "react";
25
11
  import { ReportAdButton } from "./ReportAdButton";
12
+ import { AdZoneTypes } from "src/componentTypes/AdZone";
26
13
 
27
- /**
28
- * Props interface for {@link AdZone}.
29
- */
30
- interface Props {
31
- /**
32
- * The app ID.
33
- */
34
- appId: string;
35
- /**
36
- * The session ID.
37
- */
38
- sessionId: string;
39
- /**
40
- * The UDID.
41
- */
42
- udid: string;
43
- /**
44
- * The touch sensitivity of the Ad Zone in both the X and Y directions.
45
- * This is used to determine the click/press sensitivity when the
46
- * Ad Zone is being touched by the user as a regular touch or while
47
- * scrolling the view. If the amount of touch "drag" distance in either
48
- * X or Y direction is less than this value, we will treat the action as
49
- * a click/press on the Ad Zone.
50
- */
51
- xyDragDistanceAllowed: number;
52
- /**
53
- * The device OS used for API requests.
54
- */
55
- deviceOs: DeviceOS;
56
- /**
57
- * The API environment to use when making an API request.
58
- */
59
- apiEnv: ApiEnv;
60
- /**
61
- * The ad zone data.
62
- */
63
- adZoneData: Zone;
64
- /**
65
- * Callback that gets triggered when an "add to list" item/items are clicked.
66
- * @param items - The array of items to "add to list".
67
- */
68
- onAddToListTriggered?(items: DetailedListItem[]): void;
69
- /**
70
- * Is the ad zone visible on render.
71
- */
72
- offScreenAdZone: boolean;
73
- /**
74
- * Track the ad zone visibility in parent component. (for off-screen ads)
75
- */
76
- isAdZoneVisible?: boolean;
77
- }
78
-
79
- /**
80
- * Interface for tracking "touch" coordinates.
81
- */
82
- interface TouchCoordinates {
83
- /**
84
- * The X coordinate for the touch.
85
- */
86
- x: number;
87
- /**
88
- * The Y coordinate for the touch.
89
- */
90
- y: number;
91
- }
92
-
93
- /**
94
- * Defines the style typing for the component.
95
- */
96
- interface StyleDef {
97
- /**
98
- * Styles for the main View element.
99
- */
100
- mainView: ViewStyle;
101
- /**
102
- * Styles for the WebView element.
103
- */
104
- webView: ViewStyle;
105
- /**
106
- * Styles for the ReportAdButton.
107
- */
108
- reportAd: ViewStyle;
109
- }
110
14
  /**
111
15
  * Timer used for cycling through ads in the zone
112
16
  * based on the ad "refresh time" for each ad.
@@ -118,24 +22,26 @@ let cycleAdTimer: ReturnType<typeof setTimeout> | undefined;
118
22
  * @param props - properties passed to AdZone.
119
23
  * @returns an AdZone JSX Element.
120
24
  */
121
- export function AdZone(props: Props): JSX.Element {
122
- // Generates a random number between 0 and (number of available ads - 1).
123
- const startingAdIndex = Math.floor(
124
- Math.random() * props.adZoneData.ads.length
125
- );
126
-
25
+ export const AdZone = (props: AdZoneTypes.Props): React.ReactElement => {
127
26
  /**
128
27
  * Tracks the current ad index being shown.
129
28
  */
130
- const [adIndexShown, setAdIndexShown] = useState(startingAdIndex);
29
+ const [adIndexShown, setAdIndexShown] = useState(
30
+ Math.floor(Math.random() * props.adZoneData.ads.length)
31
+ );
131
32
  /**
132
33
  * Tracks the coordinates when the user started touching the Ad View.
133
34
  */
134
- const [touchStartCoords, setTouchStartCoords] = useState({ x: 0, y: 0 });
35
+ const [touchStartCoords, setTouchStartCoords] =
36
+ useState<AdZoneTypes.TouchCoordinates>({
37
+ x: 0,
38
+ y: 0,
39
+ });
40
+
135
41
  /**
136
42
  * Track ad visibility (for off-screen ads).
137
43
  */
138
- const [isAdVisible, setIsAdVisibile] = useState(props.isAdZoneVisible);
44
+ const [isAdZoneVisible, setIsAdVisibile] = useState(props.isAdZoneVisible);
139
45
 
140
46
  // Setup device listeners.
141
47
  useEffect(() => {
@@ -147,16 +53,10 @@ export function AdZone(props: Props): JSX.Element {
147
53
  acknowledge(itemName);
148
54
  });
149
55
 
150
- if (props.offScreenAdZone && isAdVisible) {
151
- sendAdImpression();
152
- } else if (!props.offScreenAdZone) {
153
- sendAdImpression();
154
- }
155
-
156
56
  return () => {
157
57
  clearTimeout(cycleAdTimer);
158
- DeviceEventEmitter.removeAllListeners("visibility-event");
159
58
  DeviceEventEmitter.removeAllListeners("acknowledge");
59
+ DeviceEventEmitter.removeAllListeners("visibility-event");
160
60
  };
161
61
  // eslint-disable-next-line react-hooks/exhaustive-deps
162
62
  }, []);
@@ -164,29 +64,38 @@ export function AdZone(props: Props): JSX.Element {
164
64
  // Send impression on ad cycle.
165
65
  useEffect(() => {
166
66
  startAdTimer();
167
- if (props.offScreenAdZone && isAdVisible) {
168
- sendAdImpression();
169
- } else if (!props.offScreenAdZone) {
67
+ if (isAdZoneVisible) {
170
68
  sendAdImpression();
171
69
  }
172
70
  // eslint-disable-next-line react-hooks/exhaustive-deps
173
71
  }, [adIndexShown]);
174
72
 
175
- // Send impression based on visibility change. (for off-screen ads)
176
73
  useEffect(() => {
177
- if (props.offScreenAdZone && isAdVisible) {
178
- sendAdImpression();
179
- } else if (!props.offScreenAdZone) {
74
+ if (
75
+ props.offScreenAdZone &&
76
+ isAdZoneVisible &&
77
+ props.adZoneData &&
78
+ props.adZoneData.ads &&
79
+ props.adZoneData.ads.length > adIndexShown &&
80
+ !props.adZoneData.ads[adIndexShown].impression_tracked
81
+ ) {
180
82
  sendAdImpression();
181
83
  }
182
84
  // eslint-disable-next-line react-hooks/exhaustive-deps
183
- }, [isAdVisible]);
85
+ }, [isAdZoneVisible]);
86
+
87
+ useEffect(() => {
88
+ if (props.adZoneData.ads.length > 0) {
89
+ cycleDisplayedAd();
90
+ }
91
+ // eslint-disable-next-line react-hooks/exhaustive-deps
92
+ }, [props.isContextualAd]);
184
93
 
185
94
  /**
186
95
  * Generates all component related styles.
187
96
  * @returns the styles needed for the component.
188
97
  */
189
- function generateStyles(): StyleDef {
98
+ function generateStyles(): AdZoneTypes.StyleDef {
190
99
  return StyleSheet.create({
191
100
  mainView: {
192
101
  width: "100%",
@@ -207,11 +116,12 @@ export function AdZone(props: Props): JSX.Element {
207
116
  // Generate the styles each render in case the ad is updated with
208
117
  // new settings that need to be reflected in the styles of the view.
209
118
  const styles = generateStyles();
210
- const currentAd: Ad | undefined =
211
- props.adZoneData.ads[adIndexShown] || undefined;
212
119
  const finalMainViewStyle = styles.mainView;
213
120
 
214
- if (!currentAd || !currentAd.creative_url) {
121
+ if (
122
+ !props.adZoneData.ads[adIndexShown] ||
123
+ !props.adZoneData.ads[adIndexShown].creative_url
124
+ ) {
215
125
  // If there is no ad to display, make the view take up no space.
216
126
  finalMainViewStyle.width = 0;
217
127
  finalMainViewStyle.height = 0;
@@ -303,10 +213,15 @@ export function AdZone(props: Props): JSX.Element {
303
213
  function startAdTimer(): void {
304
214
  clearTimeout(cycleAdTimer);
305
215
 
306
- if (props.adZoneData.ads.length > 0) {
216
+ if (
217
+ props.adZoneData.ads.length > 0 &&
218
+ props.adZoneData.ads[adIndexShown]
219
+ ) {
307
220
  const refreshTime: number =
308
221
  props.adZoneData.ads[adIndexShown].refresh_time * 1000;
309
222
  cycleAdTimer = setTimeout(cycleDisplayedAd, refreshTime);
223
+ } else {
224
+ cycleAdTimer = setTimeout(cycleDisplayedAd, 30000);
310
225
  }
311
226
  }
312
227
 
@@ -314,18 +229,18 @@ export function AdZone(props: Props): JSX.Element {
314
229
  * Cycles to the next ad to display in the current available sequence of ads.
315
230
  */
316
231
  function cycleDisplayedAd(): void {
317
- // Start by determining the next ad index to display.
318
232
  let nextAdIndex = 0;
233
+
234
+ // Start by determining the next ad index to display.
319
235
  const lastAd = props.adZoneData.ads[adIndexShown];
320
236
 
321
237
  if (adIndexShown < props.adZoneData.ads.length - 1) {
322
238
  nextAdIndex = adIndexShown + 1;
239
+ } else {
240
+ nextAdIndex = 0;
323
241
  }
324
242
 
325
- if (nextAdIndex !== adIndexShown && lastAd.impression_tracked) {
326
- // Reset ad impression tracking status.
327
- lastAd.impression_tracked = false;
328
- } else {
243
+ if (lastAd && !lastAd.impression_tracked && !isAdZoneVisible) {
329
244
  // Send invisible ad impression if ad was not visible before end of timer cycle.
330
245
  triggerReportAdEvent(
331
246
  lastAd,
@@ -333,6 +248,11 @@ export function AdZone(props: Props): JSX.Element {
333
248
  );
334
249
  }
335
250
 
251
+ if (lastAd && lastAd.impression_tracked) {
252
+ // Reset ad impression tracking status.
253
+ lastAd.impression_tracked = false;
254
+ }
255
+
336
256
  setAdIndexShown(nextAdIndex);
337
257
  }
338
258
 
@@ -342,7 +262,10 @@ export function AdZone(props: Props): JSX.Element {
342
262
  function sendAdImpression(): void {
343
263
  const ad = props.adZoneData.ads[adIndexShown];
344
264
 
345
- if (!ad.impression_tracked) {
265
+ if (
266
+ ad &&
267
+ (ad.impression_tracked === undefined || !ad.impression_tracked)
268
+ ) {
346
269
  triggerReportAdEvent(ad, ReportedEventType.IMPRESSION);
347
270
  ad.impression_tracked = true;
348
271
  }
@@ -351,15 +274,20 @@ export function AdZone(props: Props): JSX.Element {
351
274
  // Returned JSX.
352
275
  return (
353
276
  <View style={finalMainViewStyle}>
354
- {currentAd && currentAd.creative_url ? (
277
+ {props.adZoneData.ads[adIndexShown] &&
278
+ props.adZoneData.ads[adIndexShown].creative_url ? (
355
279
  <WebView
356
280
  source={{
357
- uri: currentAd.creative_url,
281
+ uri: props.adZoneData.ads[adIndexShown].creative_url,
358
282
  }}
359
283
  androidLayerType="hardware"
360
284
  automaticallyAdjustContentInsets={false}
361
285
  style={styles.webView}
362
286
  onTouchStart={(e) => {
287
+ triggerReportAdEvent(
288
+ props.adZoneData.ads[adIndexShown],
289
+ ReportedEventType.INTERACTION
290
+ );
363
291
  setTouchStartCoords({
364
292
  x: e.nativeEvent.pageX,
365
293
  y: e.nativeEvent.pageY,
@@ -367,10 +295,11 @@ export function AdZone(props: Props): JSX.Element {
367
295
  }}
368
296
  onTouchEnd={(e) => {
369
297
  if (touchStartCoords) {
370
- const touchEndCoords: TouchCoordinates = {
371
- x: e.nativeEvent.pageX,
372
- y: e.nativeEvent.pageY,
373
- };
298
+ const touchEndCoords: AdZoneTypes.TouchCoordinates =
299
+ {
300
+ x: e.nativeEvent.pageX,
301
+ y: e.nativeEvent.pageY,
302
+ };
374
303
 
375
304
  if (
376
305
  Math.abs(
@@ -380,7 +309,9 @@ export function AdZone(props: Props): JSX.Element {
380
309
  touchStartCoords.y - touchEndCoords.y
381
310
  ) < props.xyDragDistanceAllowed
382
311
  ) {
383
- onAdZoneSelected(currentAd);
312
+ onAdZoneSelected(
313
+ props.adZoneData.ads[adIndexShown]
314
+ );
384
315
  }
385
316
 
386
317
  // Make sure to reset the start coords
@@ -390,8 +321,15 @@ export function AdZone(props: Props): JSX.Element {
390
321
  />
391
322
  ) : undefined}
392
323
  <View style={styles.reportAd}>
393
- <ReportAdButton adId={currentAd.ad_id} udid={props.udid} />
324
+ {props.adZoneData && props.adZoneData.ads[adIndexShown] ? (
325
+ <ReportAdButton
326
+ adId={props.adZoneData.ads[adIndexShown].ad_id}
327
+ udid={props.udid}
328
+ />
329
+ ) : (
330
+ <></>
331
+ )}
394
332
  </View>
395
333
  </View>
396
334
  );
397
- }
335
+ };
@@ -17,7 +17,7 @@ interface Props {
17
17
  * @param props The component's props.
18
18
  * @returns a reportSdButton JSX Element.
19
19
  */
20
- export function ReportAdButton(props: Props): JSX.Element {
20
+ export function ReportAdButton(props: Props): React.JSX.Element {
21
21
  const reportAdUrlBase = new URL("https://feedback.add-it.io/");
22
22
 
23
23
  const styles = StyleSheet.create({