react-native-applovin-max 8.2.0 → 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.
Files changed (151) hide show
  1. package/android/build.gradle +13 -2
  2. package/android/src/main/java/com/applovin/reactnative/AppLovinMAXAdView.java +33 -26
  3. package/android/src/main/java/com/applovin/reactnative/AppLovinMAXAdViewManagerImpl.java +110 -0
  4. package/android/src/main/java/com/applovin/reactnative/AppLovinMAXAdViewUiComponent.java +15 -13
  5. package/android/src/main/java/com/applovin/reactnative/{AppLovinMAXModule.java → AppLovinMAXModuleImpl.java} +107 -168
  6. package/android/src/main/java/com/applovin/reactnative/AppLovinMAXNativeAdView.java +84 -56
  7. package/android/src/main/java/com/applovin/reactnative/AppLovinMAXNativeAdViewManagerImpl.java +101 -0
  8. package/android/src/main/java/com/applovin/reactnative/AppLovinMAXPackage.java +44 -11
  9. package/android/src/main/java/com/applovin/reactnative/AppLovinMAXUtils.java +56 -0
  10. package/android/src/newarch/com/applovin/reactnative/AppLovinMAXAdViewManager.java +151 -0
  11. package/android/src/newarch/com/applovin/reactnative/AppLovinMAXModule.java +453 -0
  12. package/android/src/newarch/com/applovin/reactnative/AppLovinMAXNativeAdViewManager.java +130 -0
  13. package/android/src/oldarch/com/applovin/reactnative/AppLovinMAXAdViewManager.java +128 -0
  14. package/android/src/oldarch/com/applovin/reactnative/AppLovinMAXModule.java +453 -0
  15. package/android/src/oldarch/com/applovin/reactnative/AppLovinMAXNativeAdViewManager.java +93 -0
  16. package/ios/AppLovinMAX.h +8 -3
  17. package/ios/{AppLovinMAX.m → AppLovinMAX.mm} +66 -53
  18. package/ios/AppLovinMAXAdView.h +7 -2
  19. package/ios/AppLovinMAXAdView.mm +747 -0
  20. package/ios/{AppLovinMAXAdViewManager.m → AppLovinMAXAdViewManager.mm} +3 -2
  21. package/ios/{AppLovinMAXAdViewUIComponent.m → AppLovinMAXAdViewUIComponent.mm} +2 -1
  22. package/ios/AppLovinMAXNativeAdView.h +15 -4
  23. package/ios/AppLovinMAXNativeAdView.mm +745 -0
  24. package/ios/AppLovinMAXNativeAdViewManager.mm +116 -0
  25. package/lib/commonjs/AdView.js +61 -85
  26. package/lib/commonjs/AdView.js.map +1 -1
  27. package/lib/commonjs/AppLovinMAX.js +11 -10
  28. package/lib/commonjs/AppLovinMAX.js.map +1 -1
  29. package/lib/commonjs/AppOpenAd.js +8 -10
  30. package/lib/commonjs/AppOpenAd.js.map +1 -1
  31. package/lib/commonjs/BannerAd.js +19 -21
  32. package/lib/commonjs/BannerAd.js.map +1 -1
  33. package/lib/commonjs/ErrorCode.js +3 -5
  34. package/lib/commonjs/ErrorCode.js.map +1 -1
  35. package/lib/commonjs/EventEmitter.js +3 -5
  36. package/lib/commonjs/EventEmitter.js.map +1 -1
  37. package/lib/commonjs/InterstitialAd.js +8 -10
  38. package/lib/commonjs/InterstitialAd.js.map +1 -1
  39. package/lib/commonjs/MRecAd.js +14 -16
  40. package/lib/commonjs/MRecAd.js.map +1 -1
  41. package/lib/commonjs/Privacy.js +3 -5
  42. package/lib/commonjs/Privacy.js.map +1 -1
  43. package/lib/commonjs/RewardedAd.js +8 -10
  44. package/lib/commonjs/RewardedAd.js.map +1 -1
  45. package/lib/commonjs/Utils.js +25 -0
  46. package/lib/commonjs/Utils.js.map +1 -0
  47. package/lib/commonjs/nativeAd/NativeAdView.js +65 -42
  48. package/lib/commonjs/nativeAd/NativeAdView.js.map +1 -1
  49. package/lib/commonjs/nativeAd/NativeAdViewComponents.js +51 -47
  50. package/lib/commonjs/nativeAd/NativeAdViewComponents.js.map +1 -1
  51. package/lib/commonjs/nativeAd/NativeAdViewProvider.js +38 -8
  52. package/lib/commonjs/nativeAd/NativeAdViewProvider.js.map +1 -1
  53. package/lib/commonjs/nativeAd/img/blank_icon.png +0 -0
  54. package/lib/commonjs/specs/AppLovinMAXAdViewNativeComponent.js +14 -0
  55. package/lib/commonjs/specs/AppLovinMAXAdViewNativeComponent.js.map +1 -0
  56. package/lib/commonjs/specs/AppLovinMAXNativeAdViewNativeComponent.js +14 -0
  57. package/lib/commonjs/specs/AppLovinMAXNativeAdViewNativeComponent.js.map +1 -0
  58. package/lib/commonjs/specs/NativeAppLovinMAXModule.js +9 -0
  59. package/lib/commonjs/specs/NativeAppLovinMAXModule.js.map +1 -0
  60. package/lib/module/AdView.js +56 -81
  61. package/lib/module/AdView.js.map +1 -1
  62. package/lib/module/AppLovinMAX.js +7 -7
  63. package/lib/module/AppLovinMAX.js.map +1 -1
  64. package/lib/module/AppOpenAd.js +1 -4
  65. package/lib/module/AppOpenAd.js.map +1 -1
  66. package/lib/module/BannerAd.js +1 -4
  67. package/lib/module/BannerAd.js.map +1 -1
  68. package/lib/module/ErrorCode.js +1 -4
  69. package/lib/module/ErrorCode.js.map +1 -1
  70. package/lib/module/EventEmitter.js +2 -4
  71. package/lib/module/EventEmitter.js.map +1 -1
  72. package/lib/module/InterstitialAd.js +2 -5
  73. package/lib/module/InterstitialAd.js.map +1 -1
  74. package/lib/module/MRecAd.js +1 -4
  75. package/lib/module/MRecAd.js.map +1 -1
  76. package/lib/module/Privacy.js +1 -4
  77. package/lib/module/Privacy.js.map +1 -1
  78. package/lib/module/RewardedAd.js +2 -5
  79. package/lib/module/RewardedAd.js.map +1 -1
  80. package/lib/module/Utils.js +17 -0
  81. package/lib/module/Utils.js.map +1 -0
  82. package/lib/module/nativeAd/NativeAdView.js +63 -40
  83. package/lib/module/nativeAd/NativeAdView.js.map +1 -1
  84. package/lib/module/nativeAd/NativeAdViewComponents.js +53 -49
  85. package/lib/module/nativeAd/NativeAdViewComponents.js.map +1 -1
  86. package/lib/module/nativeAd/NativeAdViewProvider.js +39 -9
  87. package/lib/module/nativeAd/NativeAdViewProvider.js.map +1 -1
  88. package/lib/module/nativeAd/img/blank_icon.png +0 -0
  89. package/lib/module/specs/AppLovinMAXAdViewNativeComponent.js +7 -0
  90. package/lib/module/specs/AppLovinMAXAdViewNativeComponent.js.map +1 -0
  91. package/lib/module/specs/AppLovinMAXNativeAdViewNativeComponent.js +7 -0
  92. package/lib/module/specs/AppLovinMAXNativeAdViewNativeComponent.js.map +1 -0
  93. package/lib/module/specs/NativeAppLovinMAXModule.js +3 -0
  94. package/lib/module/specs/NativeAppLovinMAXModule.js.map +1 -0
  95. package/lib/typescript/src/AdView.d.ts +11 -11
  96. package/lib/typescript/src/AdView.d.ts.map +1 -1
  97. package/lib/typescript/src/AppLovinMAX.d.ts.map +1 -1
  98. package/lib/typescript/src/AppOpenAd.d.ts.map +1 -1
  99. package/lib/typescript/src/BannerAd.d.ts.map +1 -1
  100. package/lib/typescript/src/ErrorCode.d.ts.map +1 -1
  101. package/lib/typescript/src/EventEmitter.d.ts.map +1 -1
  102. package/lib/typescript/src/InterstitialAd.d.ts.map +1 -1
  103. package/lib/typescript/src/MRecAd.d.ts.map +1 -1
  104. package/lib/typescript/src/Privacy.d.ts.map +1 -1
  105. package/lib/typescript/src/RewardedAd.d.ts.map +1 -1
  106. package/lib/typescript/src/Utils.d.ts +16 -0
  107. package/lib/typescript/src/Utils.d.ts.map +1 -0
  108. package/lib/typescript/src/nativeAd/NativeAdView.d.ts.map +1 -1
  109. package/lib/typescript/src/nativeAd/NativeAdViewComponents.d.ts.map +1 -1
  110. package/lib/typescript/src/nativeAd/NativeAdViewProvider.d.ts +14 -5
  111. package/lib/typescript/src/nativeAd/NativeAdViewProvider.d.ts.map +1 -1
  112. package/lib/typescript/src/specs/AppLovinMAXAdViewNativeComponent.d.ts +86 -0
  113. package/lib/typescript/src/specs/AppLovinMAXAdViewNativeComponent.d.ts.map +1 -0
  114. package/lib/typescript/src/specs/AppLovinMAXNativeAdViewNativeComponent.d.ts +80 -0
  115. package/lib/typescript/src/specs/AppLovinMAXNativeAdViewNativeComponent.d.ts.map +1 -0
  116. package/lib/typescript/src/specs/NativeAppLovinMAXModule.d.ts +132 -0
  117. package/lib/typescript/src/specs/NativeAppLovinMAXModule.d.ts.map +1 -0
  118. package/lib/typescript/src/types/AdInfo.d.ts +1 -1
  119. package/lib/typescript/src/types/AdInfo.d.ts.map +1 -1
  120. package/lib/typescript/src/types/AdProps.d.ts +2 -2
  121. package/lib/typescript/src/types/AdProps.d.ts.map +1 -1
  122. package/lib/typescript/src/types/NativeAd.d.ts +4 -0
  123. package/lib/typescript/src/types/NativeAd.d.ts.map +1 -1
  124. package/package.json +9 -1
  125. package/react-native-applovin-max.podspec +2 -2
  126. package/src/AdView.tsx +56 -121
  127. package/src/AppLovinMAX.ts +7 -8
  128. package/src/AppOpenAd.ts +1 -3
  129. package/src/BannerAd.ts +1 -3
  130. package/src/ErrorCode.ts +1 -3
  131. package/src/EventEmitter.ts +2 -3
  132. package/src/InterstitialAd.ts +2 -4
  133. package/src/MRecAd.ts +1 -3
  134. package/src/Privacy.ts +1 -3
  135. package/src/RewardedAd.ts +2 -4
  136. package/src/Utils.ts +26 -0
  137. package/src/nativeAd/NativeAdView.tsx +65 -65
  138. package/src/nativeAd/NativeAdViewComponents.tsx +32 -60
  139. package/src/nativeAd/NativeAdViewProvider.tsx +37 -12
  140. package/src/nativeAd/img/blank_icon.png +0 -0
  141. package/src/specs/AppLovinMAXAdViewNativeComponent.ts +96 -0
  142. package/src/specs/AppLovinMAXNativeAdViewNativeComponent.ts +89 -0
  143. package/src/specs/NativeAppLovinMAXModule.ts +208 -0
  144. package/src/types/AdInfo.ts +1 -1
  145. package/src/types/AdProps.ts +2 -2
  146. package/src/types/NativeAd.ts +5 -0
  147. package/android/src/main/java/com/applovin/reactnative/AppLovinMAXAdViewManager.java +0 -149
  148. package/android/src/main/java/com/applovin/reactnative/AppLovinMAXNativeAdViewManager.java +0 -163
  149. package/ios/AppLovinMAXAdView.m +0 -325
  150. package/ios/AppLovinMAXNativeAdView.m +0 -432
  151. package/ios/AppLovinMAXNativeAdViewManager.m +0 -64
package/src/BannerAd.ts CHANGED
@@ -1,11 +1,9 @@
1
- import { NativeModules } from 'react-native';
2
1
  import { addEventListener, removeEventListener } from './EventEmitter';
3
2
  import type { AdInfo, AdLoadFailedInfo } from './types/AdInfo';
4
3
  import type { LocalExtraParameterValue } from './types/AdProps';
5
4
  import type { BannerAdType } from './types/BannerAd';
6
5
  import type { AdViewPosition } from './AdView';
7
-
8
- const { AppLovinMAX } = NativeModules;
6
+ import AppLovinMAX from './specs/NativeAppLovinMAXModule';
9
7
 
10
8
  const {
11
9
  ON_BANNER_AD_LOADED_EVENT,
package/src/ErrorCode.ts CHANGED
@@ -1,6 +1,4 @@
1
- import { NativeModules } from 'react-native';
2
-
3
- const { AppLovinMAX } = NativeModules;
1
+ import AppLovinMAX from './specs/NativeAppLovinMAXModule';
4
2
 
5
3
  const {
6
4
  MAX_ERROR_CODE_UNSPECIFIED,
@@ -1,8 +1,7 @@
1
- import { NativeModules, NativeEventEmitter } from 'react-native';
1
+ import { NativeEventEmitter } from 'react-native';
2
2
  import type { EventSubscription } from 'react-native';
3
3
  import type { AdEventObject, AdEventListener } from './types/AdEvent';
4
-
5
- const { AppLovinMAX } = NativeModules;
4
+ import AppLovinMAX from './specs/NativeAppLovinMAXModule';
6
5
 
7
6
  // Note that this is a singleton in ES6 module
8
7
  const emitter = new NativeEventEmitter(AppLovinMAX);
@@ -1,10 +1,8 @@
1
- import { NativeModules } from 'react-native';
2
1
  import { addEventListener, removeEventListener } from './EventEmitter';
3
2
  import type { AdDisplayFailedInfo, AdInfo, AdLoadFailedInfo } from './types/AdInfo';
4
3
  import type { LocalExtraParameterValue } from './types/AdProps';
5
4
  import type { InterstitialAdType } from './types/InterstitialAd';
6
-
7
- const { AppLovinMAX } = NativeModules;
5
+ import AppLovinMAX from './specs/NativeAppLovinMAXModule';
8
6
 
9
7
  const {
10
8
  ON_INTERSTITIAL_LOADED_EVENT,
@@ -25,7 +23,7 @@ const loadAd = (adUnitId: string): void => {
25
23
  };
26
24
 
27
25
  const showAd = (adUnitId: string, placement?: string | null, customData?: string | null): void => {
28
- AppLovinMAX.showInterstitial(adUnitId, placement ?? null, customData ?? null);
26
+ AppLovinMAX.showInterstitial(adUnitId, placement ?? undefined, customData ?? undefined);
29
27
  };
30
28
 
31
29
  const setExtraParameter = (adUnitId: string, key: string, value: string | null): void => {
package/src/MRecAd.ts CHANGED
@@ -1,11 +1,9 @@
1
- import { NativeModules } from 'react-native';
2
1
  import { addEventListener, removeEventListener } from './EventEmitter';
3
2
  import type { AdInfo, AdLoadFailedInfo } from './types/AdInfo';
4
3
  import type { LocalExtraParameterValue } from './types/AdProps';
5
4
  import type { MRecAdType } from './types/MRecAd';
6
5
  import type { AdViewPosition } from './AdView';
7
-
8
- const { AppLovinMAX } = NativeModules;
6
+ import AppLovinMAX from './specs/NativeAppLovinMAXModule';
9
7
 
10
8
  const { ON_MREC_AD_LOADED_EVENT, ON_MREC_AD_LOAD_FAILED_EVENT, ON_MREC_AD_CLICKED_EVENT, ON_MREC_AD_COLLAPSED_EVENT, ON_MREC_AD_EXPANDED_EVENT, ON_MREC_AD_REVENUE_PAID } =
11
9
  AppLovinMAX.getConstants();
package/src/Privacy.ts CHANGED
@@ -1,6 +1,4 @@
1
- import { NativeModules } from 'react-native';
2
1
  import type { PrivacyType } from './types/Privacy';
3
-
4
- const { AppLovinMAX } = NativeModules;
2
+ import AppLovinMAX from './specs/NativeAppLovinMAXModule';
5
3
 
6
4
  export const Privacy: PrivacyType = AppLovinMAX;
package/src/RewardedAd.ts CHANGED
@@ -1,10 +1,8 @@
1
- import { NativeModules } from 'react-native';
2
1
  import { addEventListener, removeEventListener } from './EventEmitter';
3
2
  import type { AdDisplayFailedInfo, AdInfo, AdLoadFailedInfo, AdRewardInfo } from './types/AdInfo';
4
3
  import type { LocalExtraParameterValue } from './types/AdProps';
5
4
  import type { RewardedAdType } from './types/RewardedAd';
6
-
7
- const { AppLovinMAX } = NativeModules;
5
+ import AppLovinMAX from './specs/NativeAppLovinMAXModule';
8
6
 
9
7
  const {
10
8
  ON_REWARDED_AD_LOADED_EVENT,
@@ -26,7 +24,7 @@ const loadAd = (adUnitId: string): void => {
26
24
  };
27
25
 
28
26
  const showAd = (adUnitId: string, placement?: string | null, customData?: string | null): void => {
29
- AppLovinMAX.showRewardedAd(adUnitId, placement ?? null, customData ?? null);
27
+ AppLovinMAX.showRewardedAd(adUnitId, placement ?? undefined, customData ?? undefined);
30
28
  };
31
29
 
32
30
  const setExtraParameter = (adUnitId: string, key: string, value: string | null): void => {
package/src/Utils.ts ADDED
@@ -0,0 +1,26 @@
1
+ import type { LocalExtraParameterValue } from './types/AdProps';
2
+
3
+ export const makeExtraParametersArray = (input?: Record<string, string | null>) => (input ? Object.entries(input).map(([key, value]) => ({ key, value })) : []);
4
+
5
+ type LocalExtraParameterType = 'str' | 'bool';
6
+
7
+ type LocalExtraParameterValueMap = {
8
+ str: string | null;
9
+ bool: boolean | null;
10
+ };
11
+
12
+ export const makeLocalExtraParametersArray = <T extends LocalExtraParameterType>(
13
+ input: Record<string, LocalExtraParameterValue> | undefined,
14
+ type: T
15
+ ): { key: string; value: LocalExtraParameterValueMap[T] }[] => {
16
+ if (!input) return [];
17
+
18
+ return Object.entries(input)
19
+ .filter(([_, value]) => {
20
+ if (value === null) return true;
21
+ if (type === 'str') return typeof value === 'string';
22
+ if (type === 'bool') return typeof value === 'boolean';
23
+ return false;
24
+ })
25
+ .map(([key, value]) => ({ key, value: value as LocalExtraParameterValueMap[T] }));
26
+ };
@@ -1,24 +1,14 @@
1
1
  import * as React from 'react';
2
2
  import { forwardRef, useContext, useImperativeHandle, useRef, useState, useEffect, useCallback } from 'react';
3
- import { NativeModules, requireNativeComponent, UIManager, findNodeHandle, View } from 'react-native';
4
- import type { ViewProps } from 'react-native';
3
+ import { findNodeHandle, View } from 'react-native';
4
+ import type { NativeSyntheticEvent, ViewProps } from 'react-native';
5
+ import AppLovinMAX from '../specs/NativeAppLovinMAXModule';
6
+ import NativeAdViewComponent, { Commands } from '../specs/AppLovinMAXNativeAdViewNativeComponent';
7
+ import type { AdInfoEvent, AdLoadFailedEvent } from '../specs/AppLovinMAXNativeAdViewNativeComponent';
5
8
  import { NativeAdViewContext, NativeAdViewProvider } from './NativeAdViewProvider';
6
- import type { AdInfo, AdLoadFailedInfo } from '../types/AdInfo';
7
- import type { AdNativeEvent } from '../types/AdEvent';
8
- import type { NativeAd } from '../types/NativeAd';
9
+ import type { NativeAdViewContextType } from './NativeAdViewProvider';
9
10
  import type { NativeAdViewHandler, NativeAdViewProps } from '../types/NativeAdViewProps';
10
- import type { NativeAdViewType, NativeAdViewContextType } from './NativeAdViewProvider';
11
-
12
- const { AppLovinMAX } = NativeModules;
13
-
14
- type NativeAdViewNativeEvents = {
15
- onAdLoadedEvent(event: { nativeEvent: { nativeAd: NativeAd; adInfo: AdInfo } }): void;
16
- onAdLoadFailedEvent(event: AdNativeEvent<AdLoadFailedInfo>): void;
17
- onAdClickedEvent(event: AdNativeEvent<AdInfo>): void;
18
- onAdRevenuePaidEvent(event: AdNativeEvent<AdInfo>): void;
19
- };
20
-
21
- const NativeAdViewComponent = requireNativeComponent<NativeAdViewProps & ViewProps & NativeAdViewNativeEvents>('AppLovinMAXNativeAdView');
11
+ import { makeExtraParametersArray, makeLocalExtraParametersArray } from '../Utils';
22
12
 
23
13
  /**
24
14
  * The {@link NativeAdView} component that you use building a native ad. This loads a native ad and
@@ -61,15 +51,13 @@ export const NativeAdView = forwardRef<NativeAdViewHandler, NativeAdViewProps &
61
51
  const [isInitialized, setIsInitialized] = useState<boolean>(false);
62
52
 
63
53
  useEffect(() => {
64
- const checkInitialization = async () => {
54
+ (async () => {
65
55
  const result = await AppLovinMAX.isInitialized();
66
56
  setIsInitialized(result);
67
57
  if (!result) {
68
58
  console.warn('NativeAdView is mounted before the initialization of the AppLovin MAX React Native module.');
69
59
  }
70
- };
71
-
72
- checkInitialization();
60
+ })();
73
61
  }, []);
74
62
 
75
63
  // Avoid rendering the NativeAdView if the SDK is not initialized
@@ -84,76 +72,88 @@ export const NativeAdView = forwardRef<NativeAdViewHandler, NativeAdViewProps &
84
72
  );
85
73
  });
86
74
 
75
+ const handleNativeAdViewEvent = <T extends AdInfoEvent | AdLoadFailedEvent>(event: NativeSyntheticEvent<T>, callback?: (adInfo: T) => void) => {
76
+ if (!callback) return;
77
+
78
+ let adInfo: any = { ...event.nativeEvent };
79
+
80
+ if ('nativeAd' in event.nativeEvent) {
81
+ adInfo.nativeAd = {
82
+ ...event.nativeEvent.nativeAd,
83
+ isIconImageAvailable: event.nativeEvent.nativeAd?.isIconImageAvailable ?? false,
84
+ isOptionsViewAvailable: event.nativeEvent.nativeAd?.isOptionsViewAvailable ?? false,
85
+ isMediaViewAvailable: event.nativeEvent.nativeAd?.isMediaViewAvailable ?? false,
86
+ };
87
+ }
88
+
89
+ callback(adInfo);
90
+ };
91
+
87
92
  const NativeAdViewImpl = forwardRef<NativeAdViewHandler, NativeAdViewProps & ViewProps>(function NativeAdViewImpl(
88
93
  { adUnitId, placement, customData, extraParameters, localExtraParameters, onAdLoaded, onAdLoadFailed, onAdClicked, onAdRevenuePaid, children, style, ...otherProps },
89
94
  ref
90
95
  ) {
91
96
  // Context provides functions to manage native ad and native ad view state
92
- const { setNativeAd, setNativeAdView } = useContext(NativeAdViewContext) as NativeAdViewContextType;
97
+ const { titleRef, advertiserRef, bodyRef, callToActionRef, imageRef, optionViewRef, mediaViewRef, setNativeAd } = useContext(NativeAdViewContext) as NativeAdViewContextType;
93
98
 
94
- const nativeAdViewRef = useRef<NativeAdViewType | null>(null);
99
+ const nativeAdViewRef = useRef<React.ElementRef<typeof NativeAdViewComponent> | undefined>();
95
100
 
96
101
  // Load a new ad
97
102
  const loadAd = useCallback(() => {
98
- const nativeAdView = nativeAdViewRef.current;
99
- if (nativeAdView) {
100
- const viewManagerConfig = UIManager.getViewManagerConfig('AppLovinMAXNativeAdView');
101
- if (viewManagerConfig?.Commands && typeof viewManagerConfig.Commands.loadAd === 'number') {
102
- UIManager.dispatchViewManagerCommand(findNodeHandle(nativeAdView), viewManagerConfig.Commands.loadAd, []);
103
- }
104
- }
103
+ nativeAdViewRef.current && Commands.loadAd(nativeAdViewRef.current);
105
104
  }, []);
106
105
 
107
106
  useImperativeHandle(ref, () => ({ loadAd }), [loadAd]);
108
107
 
109
- // Save the DOM element reference
110
- const saveElement = useCallback(
111
- (element: NativeAdViewType | null) => {
112
- if (element) {
113
- nativeAdViewRef.current = element;
114
- setNativeAdView(element);
115
- }
116
- },
117
- [setNativeAdView]
118
- );
108
+ const updateAssetView = useCallback((assetViewRef: React.RefObject<View>, type: string) => {
109
+ if (!nativeAdViewRef.current || !assetViewRef.current) return;
110
+
111
+ const node = findNodeHandle(assetViewRef.current);
112
+ if (node) {
113
+ Commands.updateAssetView(nativeAdViewRef.current, node, type);
114
+ }
115
+ }, []);
119
116
 
120
117
  const onAdLoadedEvent = useCallback(
121
- (event: { nativeEvent: { nativeAd: NativeAd; adInfo: AdInfo } }) => {
122
- setNativeAd(event.nativeEvent.nativeAd);
123
- onAdLoaded?.(event.nativeEvent.adInfo);
124
- },
125
- [onAdLoaded, setNativeAd]
126
- );
118
+ (event: NativeSyntheticEvent<AdInfoEvent>) => {
119
+ const nativeAdImpl = event.nativeEvent.nativeAdImpl;
120
+
121
+ if (nativeAdImpl) {
122
+ setNativeAd({ ...nativeAdImpl });
123
+
124
+ if (nativeAdImpl.title) updateAssetView(titleRef, 'TitleView');
125
+ if (nativeAdImpl.advertiser) updateAssetView(advertiserRef, 'AdvertiserView');
126
+ if (nativeAdImpl.body) updateAssetView(bodyRef, 'BodyView');
127
+ if (nativeAdImpl.callToAction) updateAssetView(callToActionRef, 'CallToActionView');
128
+ if (nativeAdImpl.url || nativeAdImpl.image || nativeAdImpl.imageSource) updateAssetView(imageRef, 'IconView');
129
+ if (nativeAdImpl.isOptionsViewAvailable) updateAssetView(optionViewRef, 'OptionsView');
130
+ if (nativeAdImpl.isMediaViewAvailable) updateAssetView(mediaViewRef, 'MediaView');
131
+ }
127
132
 
128
- const onAdLoadFailedEvent = useCallback(
129
- (event: AdNativeEvent<AdLoadFailedInfo>) => {
130
- onAdLoadFailed?.(event.nativeEvent);
131
- },
132
- [onAdLoadFailed]
133
- );
133
+ if (nativeAdViewRef.current) {
134
+ Commands.renderNativeAd(nativeAdViewRef.current);
135
+ }
134
136
 
135
- const onAdClickedEvent = useCallback(
136
- (event: AdNativeEvent<AdInfo>) => {
137
- onAdClicked?.(event.nativeEvent);
137
+ handleNativeAdViewEvent(event, onAdLoaded);
138
138
  },
139
- [onAdClicked]
139
+ [setNativeAd, onAdLoaded, updateAssetView, titleRef, advertiserRef, bodyRef, callToActionRef, imageRef, optionViewRef, mediaViewRef]
140
140
  );
141
141
 
142
- const onAdRevenuePaidEvent = useCallback(
143
- (event: AdNativeEvent<AdInfo>) => {
144
- onAdRevenuePaid?.(event.nativeEvent);
145
- },
146
- [onAdRevenuePaid]
147
- );
142
+ const onAdLoadFailedEvent = useCallback((event: NativeSyntheticEvent<AdLoadFailedEvent>) => handleNativeAdViewEvent(event, onAdLoadFailed), [onAdLoadFailed]);
143
+
144
+ const onAdClickedEvent = useCallback((event: NativeSyntheticEvent<AdInfoEvent>) => handleNativeAdViewEvent(event, onAdClicked), [onAdClicked]);
145
+
146
+ const onAdRevenuePaidEvent = useCallback((event: NativeSyntheticEvent<AdInfoEvent>) => handleNativeAdViewEvent(event, onAdRevenuePaid), [onAdRevenuePaid]);
148
147
 
149
148
  return (
150
149
  <NativeAdViewComponent
151
- ref={saveElement}
150
+ ref={(element) => (nativeAdViewRef.current = element ?? undefined)}
152
151
  adUnitId={adUnitId}
153
152
  placement={placement}
154
153
  customData={customData}
155
- extraParameters={extraParameters}
156
- localExtraParameters={localExtraParameters}
154
+ extraParameters={makeExtraParametersArray(extraParameters)}
155
+ strLocalExtraParameters={makeLocalExtraParametersArray(localExtraParameters, 'str')}
156
+ boolLocalExtraParameters={makeLocalExtraParametersArray(localExtraParameters, 'bool')}
157
157
  onAdLoadedEvent={onAdLoadedEvent}
158
158
  onAdLoadFailedEvent={onAdLoadFailedEvent}
159
159
  onAdClickedEvent={onAdClickedEvent}
@@ -1,77 +1,50 @@
1
1
  import * as React from 'react';
2
- import { useContext, useRef, useEffect, useCallback, useMemo } from 'react';
3
- import { findNodeHandle, Text, Image, View, TouchableOpacity, StyleSheet, Platform } from 'react-native';
4
- import type { ViewProps, ImageProps, TextStyle, StyleProp, TextProps } from 'react-native';
2
+ import { useContext, useMemo } from 'react';
3
+ import { Text, Image, View, TouchableOpacity, StyleSheet, Platform } from 'react-native';
4
+ import type { ViewProps, ImageProps, TextStyle, TextProps } from 'react-native';
5
5
  import { NativeAdViewContext } from './NativeAdViewProvider';
6
- import type { NativeAd } from '../types/NativeAd';
7
-
8
- // Custom hook to handle setting native ad view properties and return nativeAd
9
- const useNativeAdViewProps = (nativeAdProp: keyof NativeAd, ref: React.RefObject<any>, nativePropKey: string) => {
10
- const { nativeAd, nativeAdView } = useContext(NativeAdViewContext);
11
-
12
- const setNativeProps = useCallback(() => {
13
- if (!nativeAd[nativeAdProp] || !ref.current) return;
14
- nativeAdView?.setNativeProps({
15
- [nativePropKey]: findNodeHandle(ref.current),
16
- });
17
- }, [nativeAd, nativeAdProp, nativeAdView, ref, nativePropKey]);
18
-
19
- useEffect(() => {
20
- setNativeProps();
21
- }, [setNativeProps]);
22
-
23
- return nativeAd;
24
- };
25
6
 
26
7
  export const TitleView = (props: TextProps) => {
27
- const titleRef = useRef<Text | null>(null);
28
- const nativeAd = useNativeAdViewProps('title', titleRef, 'titleView');
29
-
8
+ const { titleRef, nativeAd } = useContext(NativeAdViewContext);
30
9
  return (
31
10
  <Text {...props} ref={titleRef}>
32
- {nativeAd.title || null}
11
+ {nativeAd.title ?? ''}
33
12
  </Text>
34
13
  );
35
14
  };
36
15
 
37
16
  export const AdvertiserView = (props: TextProps) => {
38
- const advertiserRef = useRef<Text | null>(null);
39
- const nativeAd = useNativeAdViewProps('advertiser', advertiserRef, 'advertiserView');
40
-
17
+ const { advertiserRef, nativeAd } = useContext(NativeAdViewContext);
41
18
  return (
42
19
  <Text {...props} ref={advertiserRef}>
43
- {nativeAd.advertiser || null}
20
+ {nativeAd.advertiser ?? ''}
44
21
  </Text>
45
22
  );
46
23
  };
47
24
 
48
25
  export const BodyView = (props: TextProps) => {
49
- const bodyRef = useRef<Text | null>(null);
50
- const nativeAd = useNativeAdViewProps('body', bodyRef, 'bodyView');
51
-
26
+ const { bodyRef, nativeAd } = useContext(NativeAdViewContext);
52
27
  return (
53
28
  <Text {...props} ref={bodyRef}>
54
- {nativeAd.body || null}
29
+ {nativeAd.body ?? ''}
55
30
  </Text>
56
31
  );
57
32
  };
58
33
 
59
34
  export const CallToActionView = (props: TextProps) => {
60
- const callToActionRef = useRef<Text | null>(null);
61
- const nativeAd = useNativeAdViewProps('callToAction', callToActionRef, 'callToActionView');
62
-
35
+ const { callToActionRef, nativeAd } = useContext(NativeAdViewContext);
63
36
  // TouchableOpacity disables clicking on certain Android devices.
64
37
  if (Platform.OS === 'android') {
65
38
  return (
66
39
  <Text {...props} ref={callToActionRef}>
67
- {nativeAd.callToAction || null}
40
+ {nativeAd.callToAction ?? ''}
68
41
  </Text>
69
42
  );
70
43
  } else {
71
44
  return (
72
45
  <TouchableOpacity>
73
46
  <Text {...props} ref={callToActionRef}>
74
- {nativeAd.callToAction || null}
47
+ {nativeAd.callToAction ?? ''}
75
48
  </Text>
76
49
  </TouchableOpacity>
77
50
  );
@@ -79,39 +52,38 @@ export const CallToActionView = (props: TextProps) => {
79
52
  };
80
53
 
81
54
  export const IconView = (props: Omit<ImageProps, 'source'>) => {
82
- const imageRef = useRef<Image | null>(null);
83
- const nativeAd = useNativeAdViewProps('image', imageRef, 'iconView');
55
+ const { imageRef, nativeAd } = useContext(NativeAdViewContext);
56
+ const defaultIcon = require('./img/blank_icon.png');
84
57
 
85
- return nativeAd.url ? (
86
- <Image {...props} ref={imageRef} source={{ uri: nativeAd.url }} />
87
- ) : nativeAd.image ? (
88
- <Image {...props} ref={imageRef} source={0} />
89
- ) : (
90
- <View {...props} />
91
- );
58
+ const imageSource = (() => {
59
+ if (nativeAd?.url) {
60
+ return { uri: nativeAd.url };
61
+ }
62
+ if (nativeAd?.imageSource) {
63
+ return { uri: `data:image/jpeg;base64,${nativeAd.imageSource}` };
64
+ }
65
+ return defaultIcon;
66
+ })();
67
+
68
+ return <Image {...props} ref={imageRef} source={imageSource} />;
92
69
  };
93
70
 
94
71
  export const OptionsView = (props: ViewProps) => {
95
- const viewRef = useRef<View | null>(null);
96
- useNativeAdViewProps('isOptionsViewAvailable', viewRef, 'optionsView');
97
-
98
- return <View {...props} ref={viewRef} />;
72
+ const { optionViewRef } = useContext(NativeAdViewContext);
73
+ return <View {...props} ref={optionViewRef} />;
99
74
  };
100
75
 
101
76
  export const MediaView = (props: ViewProps) => {
102
- const viewRef = useRef<View | null>(null);
103
- useNativeAdViewProps('isMediaViewAvailable', viewRef, 'mediaView');
104
-
105
- return <View {...props} ref={viewRef} />;
77
+ const { mediaViewRef } = useContext(NativeAdViewContext);
78
+ return <View {...props} ref={mediaViewRef} />;
106
79
  };
107
80
 
108
81
  export const StarRatingView = (props: ViewProps) => {
109
82
  const { style, ...restProps } = props;
110
-
111
83
  const maxStarCount = 5;
112
- const starColor = StyleSheet.flatten((style as StyleProp<TextStyle>) || {}).color ?? '#ffe234';
113
- const starSize = StyleSheet.flatten((style as StyleProp<TextStyle>) || {}).fontSize ?? 10;
114
-
84
+ const starTextStyle = useMemo(() => StyleSheet.flatten(style) as TextStyle, [style]);
85
+ const starColor = starTextStyle.color ?? '#ffe234';
86
+ const starSize = starTextStyle.fontSize ?? 10;
115
87
  const { nativeAd } = useContext(NativeAdViewContext);
116
88
 
117
89
  // Memoize the star rendering process
@@ -1,17 +1,26 @@
1
1
  import * as React from 'react';
2
- import { useState, createContext } from 'react';
2
+ import { useState, createContext, useRef } from 'react';
3
3
  import type { ReactNode } from 'react';
4
- import type { NativeMethods } from 'react-native';
4
+ import type { Image, NativeMethods, Text, View } from 'react-native';
5
5
  import type { NativeAd } from '../types/NativeAd';
6
- import type { NativeAdViewProps } from '../types/NativeAdViewProps';
6
+ import type { NativeProps } from '../specs/AppLovinMAXNativeAdViewNativeComponent';
7
7
 
8
- export type NativeAdViewType = React.Component<NativeAdViewProps> & NativeMethods;
8
+ export type NativeAdViewType = React.Component<NativeProps> & NativeMethods;
9
+
10
+ type TextRef = React.ElementRef<typeof Text>;
11
+ type ImageRef = React.ElementRef<typeof Image>;
12
+ type ViewRef = React.ElementRef<typeof View>;
9
13
 
10
14
  export type NativeAdViewContextType = {
15
+ titleRef: React.RefObject<TextRef>;
16
+ advertiserRef: React.RefObject<TextRef>;
17
+ bodyRef: React.RefObject<TextRef>;
18
+ callToActionRef: React.RefObject<TextRef>;
19
+ imageRef: React.RefObject<ImageRef>;
20
+ optionViewRef: React.RefObject<ViewRef>;
21
+ mediaViewRef: React.RefObject<ViewRef>;
11
22
  nativeAd: NativeAd;
12
- nativeAdView: NativeAdViewType | null;
13
23
  setNativeAd: React.Dispatch<React.SetStateAction<NativeAd>>;
14
- setNativeAdView: React.Dispatch<React.SetStateAction<NativeAdViewType | null>>;
15
24
  };
16
25
 
17
26
  const defaultNativeAd: NativeAd = {
@@ -20,24 +29,40 @@ const defaultNativeAd: NativeAd = {
20
29
  };
21
30
 
22
31
  export const NativeAdViewContext = createContext<NativeAdViewContextType>({
32
+ titleRef: { current: null },
33
+ advertiserRef: { current: null },
34
+ bodyRef: { current: null },
35
+ callToActionRef: { current: null },
36
+ imageRef: { current: null },
37
+ optionViewRef: { current: null },
38
+ mediaViewRef: { current: null },
23
39
  nativeAd: defaultNativeAd,
24
- nativeAdView: null,
25
40
  setNativeAd: () => {},
26
- setNativeAdView: () => {},
27
41
  });
28
42
 
29
43
  export const NativeAdViewProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
44
+ const titleRef = useRef<TextRef | null>(null);
45
+ const advertiserRef = useRef<TextRef | null>(null);
46
+ const bodyRef = useRef<TextRef | null>(null);
47
+ const callToActionRef = useRef<TextRef | null>(null);
48
+ const imageRef = useRef<ImageRef | null>(null);
49
+ const optionViewRef = useRef<ViewRef | null>(null);
50
+ const mediaViewRef = useRef<ViewRef | null>(null);
30
51
  const [nativeAd, setNativeAd] = useState<NativeAd>(defaultNativeAd);
31
- const [nativeAdView, setNativeAdView] = useState<NativeAdViewType | null>(null);
32
52
 
33
53
  const providerValue = React.useMemo(
34
54
  () => ({
55
+ titleRef,
56
+ advertiserRef,
57
+ bodyRef,
58
+ callToActionRef,
59
+ imageRef,
60
+ optionViewRef,
61
+ mediaViewRef,
35
62
  nativeAd,
36
- nativeAdView,
37
63
  setNativeAd,
38
- setNativeAdView,
39
64
  }),
40
- [nativeAd, nativeAdView]
65
+ [nativeAd]
41
66
  );
42
67
 
43
68
  return <NativeAdViewContext.Provider value={providerValue}>{children}</NativeAdViewContext.Provider>;
Binary file
@@ -0,0 +1,96 @@
1
+ import type { HostComponent, ViewProps } from 'react-native';
2
+ import type { Double, DirectEventHandler, WithDefault } from 'react-native/Libraries/Types/CodegenTypes';
3
+ import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands';
4
+ import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
5
+
6
+ export type AdInfoEvent = Readonly<{
7
+ adUnitId: string;
8
+ adFormat: string;
9
+ adViewId?: Double;
10
+ networkName: string;
11
+ networkPlacement: string;
12
+ creativeId?: string | null;
13
+ placement?: string | null;
14
+ revenue: Double;
15
+ revenuePrecision: string;
16
+ latencyMillis: Double;
17
+ dspName?: string | null;
18
+ size: Readonly<{
19
+ width: Double;
20
+ height: Double;
21
+ }>;
22
+ }>;
23
+
24
+ export type AdLoadFailedEvent = Readonly<{
25
+ adUnitId: string;
26
+ adViewId?: Double;
27
+ code: Double;
28
+ message?: string | null;
29
+ mediatedNetworkErrorCode: Double;
30
+ mediatedNetworkErrorMessage: string;
31
+ adLoadFailureInfo?: string | null;
32
+ }>;
33
+
34
+ export type AdDisplayFailedEvent = Readonly<{
35
+ adUnitId: string;
36
+ adFormat: string;
37
+ adViewId?: Double;
38
+ networkName: string;
39
+ networkPlacement: string;
40
+ creativeId?: string | null;
41
+ placement?: string | null;
42
+ revenue: Double;
43
+ revenuePrecision: string;
44
+ latencyMillis: Double;
45
+ dspName?: string | null;
46
+ size: Readonly<{
47
+ width: Double;
48
+ height: Double;
49
+ }>;
50
+ code: Double;
51
+ message?: string | null;
52
+ mediatedNetworkErrorCode: Double;
53
+ mediatedNetworkErrorMessage: string;
54
+ }>;
55
+
56
+ export interface NativeProps extends ViewProps {
57
+ adUnitId: string;
58
+ adFormat?: string;
59
+ adViewId?: WithDefault<Double, 0>;
60
+ placement?: string | null;
61
+ customData?: string | null;
62
+ adaptiveBannerEnabled?: WithDefault<boolean, true>;
63
+ autoRefresh?: WithDefault<boolean, true>;
64
+ loadOnMount?: WithDefault<boolean, true>;
65
+ extraParameters?: ReadonlyArray<{
66
+ key: string;
67
+ value: string | null;
68
+ }>;
69
+ strLocalExtraParameters?: ReadonlyArray<{
70
+ key: string;
71
+ value: string | null;
72
+ }>;
73
+ boolLocalExtraParameters?: ReadonlyArray<{
74
+ key: string;
75
+ value: boolean | null;
76
+ }>;
77
+ onAdLoadedEvent: DirectEventHandler<AdInfoEvent>;
78
+ onAdLoadFailedEvent: DirectEventHandler<AdLoadFailedEvent>;
79
+ onAdDisplayFailedEvent: DirectEventHandler<AdDisplayFailedEvent>;
80
+ onAdClickedEvent: DirectEventHandler<AdInfoEvent>;
81
+ onAdExpandedEvent: DirectEventHandler<AdInfoEvent>;
82
+ onAdCollapsedEvent: DirectEventHandler<AdInfoEvent>;
83
+ onAdRevenuePaidEvent: DirectEventHandler<AdInfoEvent>;
84
+ }
85
+
86
+ type AppLovinMAXAdViewNativeComponentType = HostComponent<NativeProps>;
87
+
88
+ interface NativeCommands {
89
+ loadAd: (viewRef: React.ElementRef<AppLovinMAXAdViewNativeComponentType>) => void;
90
+ }
91
+
92
+ export const Commands: NativeCommands = codegenNativeCommands<NativeCommands>({
93
+ supportedCommands: ['loadAd'],
94
+ });
95
+
96
+ export default codegenNativeComponent<NativeProps>('AppLovinMAXAdView') as HostComponent<NativeProps>;