cloudx-react-native 3.4.5 → 3.4.7

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 (63) hide show
  1. package/android/build.gradle +1 -1
  2. package/android/src/main/java/com/cloudxreactnative/CloudXAdEvents.kt +10 -0
  3. package/android/src/main/java/com/cloudxreactnative/CloudXAdView.kt +244 -0
  4. package/android/src/main/java/com/cloudxreactnative/CloudXAdViewEvent.kt +28 -0
  5. package/android/src/main/java/com/cloudxreactnative/CloudXAdViewManagerImpl.kt +54 -0
  6. package/android/src/main/java/com/cloudxreactnative/CloudXExtraParameters.kt +101 -0
  7. package/android/src/main/java/com/cloudxreactnative/CloudXModuleImpl.kt +5 -57
  8. package/android/src/main/java/com/cloudxreactnative/CloudXPackage.kt +1 -1
  9. package/android/src/newarch/com/cloudxreactnative/CloudXAdViewManager.kt +52 -0
  10. package/android/src/oldarch/com/cloudxreactnative/CloudXAdViewManager.kt +46 -0
  11. package/ios/CloudX.mm +13 -57
  12. package/ios/CloudXAdView.h +35 -0
  13. package/ios/CloudXAdView.mm +505 -0
  14. package/ios/CloudXAdViewManager.h +12 -0
  15. package/ios/CloudXAdViewManager.mm +38 -0
  16. package/ios/CloudXExtraParameters.h +27 -0
  17. package/ios/CloudXExtraParameters.mm +117 -0
  18. package/lib/commonjs/CloudXAdViewBase.js +248 -0
  19. package/lib/commonjs/CloudXAdViewBase.js.map +1 -0
  20. package/lib/commonjs/CloudXBannerView.js +27 -0
  21. package/lib/commonjs/CloudXBannerView.js.map +1 -0
  22. package/lib/commonjs/CloudXMRECView.js +27 -0
  23. package/lib/commonjs/CloudXMRECView.js.map +1 -0
  24. package/lib/commonjs/index.js +16 -0
  25. package/lib/commonjs/index.js.map +1 -1
  26. package/lib/commonjs/specs/CloudXAdViewNativeComponent.js +30 -0
  27. package/lib/commonjs/specs/CloudXAdViewNativeComponent.js.map +1 -0
  28. package/lib/commonjs/version.js +5 -2
  29. package/lib/commonjs/version.js.map +1 -1
  30. package/lib/module/CloudXAdViewBase.js +240 -0
  31. package/lib/module/CloudXAdViewBase.js.map +1 -0
  32. package/lib/module/CloudXBannerView.js +19 -0
  33. package/lib/module/CloudXBannerView.js.map +1 -0
  34. package/lib/module/CloudXMRECView.js +19 -0
  35. package/lib/module/CloudXMRECView.js.map +1 -0
  36. package/lib/module/index.js +3 -0
  37. package/lib/module/index.js.map +1 -1
  38. package/lib/module/specs/CloudXAdViewNativeComponent.js +27 -0
  39. package/lib/module/specs/CloudXAdViewNativeComponent.js.map +1 -0
  40. package/lib/module/version.js +5 -2
  41. package/lib/module/version.js.map +1 -1
  42. package/lib/typescript/src/CloudXAdViewBase.d.ts +28 -0
  43. package/lib/typescript/src/CloudXAdViewBase.d.ts.map +1 -0
  44. package/lib/typescript/src/CloudXBannerView.d.ts +16 -0
  45. package/lib/typescript/src/CloudXBannerView.d.ts.map +1 -0
  46. package/lib/typescript/src/CloudXMRECView.d.ts +16 -0
  47. package/lib/typescript/src/CloudXMRECView.d.ts.map +1 -0
  48. package/lib/typescript/src/index.d.ts +3 -0
  49. package/lib/typescript/src/index.d.ts.map +1 -1
  50. package/lib/typescript/src/specs/CloudXAdViewNativeComponent.d.ts +62 -0
  51. package/lib/typescript/src/specs/CloudXAdViewNativeComponent.d.ts.map +1 -0
  52. package/lib/typescript/src/types/AdProps.d.ts +3 -0
  53. package/lib/typescript/src/types/AdProps.d.ts.map +1 -1
  54. package/lib/typescript/src/version.d.ts +1 -1
  55. package/lib/typescript/src/version.d.ts.map +1 -1
  56. package/package.json +1 -1
  57. package/src/CloudXAdViewBase.tsx +293 -0
  58. package/src/CloudXBannerView.tsx +20 -0
  59. package/src/CloudXMRECView.tsx +20 -0
  60. package/src/index.ts +5 -0
  61. package/src/specs/CloudXAdViewNativeComponent.ts +84 -0
  62. package/src/types/AdProps.ts +4 -0
  63. package/src/version.ts +5 -2
@@ -72,5 +72,5 @@ repositories {
72
72
  dependencies {
73
73
  implementation "com.facebook.react:react-native:0.76.2"
74
74
 
75
- implementation "io.cloudx:sdk:4.1.3"
75
+ implementation "io.cloudx:sdk:4.1.7"
76
76
  }
@@ -17,6 +17,16 @@ object CloudXAdEvents {
17
17
  const val ON_MREC_AD_COLLAPSED_EVENT = "OnMRecAdCollapsedEvent"
18
18
  const val ON_MREC_AD_REVENUE_PAID = "OnMRecAdRevenuePaid"
19
19
 
20
+ /*
21
+ * In-tree Ad View component (CloudXBannerView / CloudXMRECView) per-view
22
+ * direct events. These strings are both the event key and the JS prop
23
+ * registrationName.
24
+ */
25
+ const val ON_AD_VIEW_LOADED_EVENT = "onAdLoadedEvent"
26
+ const val ON_AD_VIEW_LOAD_FAILED_EVENT = "onAdLoadFailedEvent"
27
+ const val ON_AD_VIEW_CLICKED_EVENT = "onAdClickedEvent"
28
+ const val ON_AD_VIEW_REVENUE_PAID_EVENT = "onAdRevenuePaidEvent"
29
+
20
30
  // Interstitial Events
21
31
  const val ON_INTERSTITIAL_LOADED_EVENT = "OnInterstitialLoadedEvent"
22
32
  const val ON_INTERSTITIAL_LOAD_FAILED_EVENT = "OnInterstitialLoadFailedEvent"
@@ -0,0 +1,244 @@
1
+ package com.cloudxreactnative
2
+
3
+ import android.util.Log
4
+ import android.widget.FrameLayout
5
+ import com.facebook.react.bridge.Arguments
6
+ import com.facebook.react.bridge.WritableMap
7
+ import com.facebook.react.uimanager.ThemedReactContext
8
+ import com.facebook.react.uimanager.UIManagerHelper
9
+ import io.cloudx.sdk.CloudX
10
+ import io.cloudx.sdk.CloudXAd
11
+ import io.cloudx.sdk.CloudXAdRevenueListener
12
+ import io.cloudx.sdk.CloudXAdView as SdkAdView
13
+ import io.cloudx.sdk.CloudXAdViewListener
14
+ import io.cloudx.sdk.CloudXError
15
+ import org.json.JSONObject
16
+
17
+ /**
18
+ * In-tree banner/MREC view component.
19
+ *
20
+ * Extends [FrameLayout] (not ReactViewGroup, whose requestLayout is a no-op that
21
+ * would leave the hosted ad view at 0x0) and hosts the CloudX SDK ad view as a
22
+ * real child. Because it lives in the React view tree, app overlays such as
23
+ * toasts layer above it via normal RN z-ordering.
24
+ */
25
+ class CloudXAdView(private val reactContext: ThemedReactContext) : FrameLayout(reactContext) {
26
+
27
+ private companion object {
28
+ const val TAG = "CloudXAdView"
29
+ }
30
+
31
+ /*
32
+ * adUnitId / adFormat are immutable once the ad view is created. Changing
33
+ * them on a mounted view is ignored (with a warning) - remount via a React
34
+ * key instead. The value check keeps benign same-value re-renders quiet.
35
+ */
36
+ var adUnitId: String? = null
37
+ set(value) {
38
+ if (adView != null && value != field) {
39
+ Log.w(TAG, "adUnitId cannot change after the ad view is created; remount the component (e.g. via a React key).")
40
+ return
41
+ }
42
+ field = value
43
+ }
44
+ var adFormat: String? = null
45
+ set(value) {
46
+ if (adView != null && value != field) {
47
+ Log.w(TAG, "adFormat cannot change after the ad view is created; remount the component (e.g. via a React key).")
48
+ return
49
+ }
50
+ field = value
51
+ }
52
+ var placement: String? = null
53
+ set(value) {
54
+ field = value
55
+ adView?.setPlacement(value)
56
+ }
57
+ var customData: String? = null
58
+ set(value) {
59
+ field = value
60
+ adView?.setCustomData(value)
61
+ }
62
+
63
+ /** Latest declarative extra parameters from the RN component. */
64
+ var extraParameters: Map<String, Any?> = emptyMap()
65
+ set(value) {
66
+ field = value
67
+ applyExtraParametersIfReady()
68
+ }
69
+
70
+ private var adView: SdkAdView? = null
71
+ private var appliedExtraParameterKeys: Set<String> = emptySet()
72
+
73
+ private val measureAndLayoutRunnable = Runnable {
74
+ measure(
75
+ MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
76
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY),
77
+ )
78
+ layout(left, top, right, bottom)
79
+ }
80
+
81
+ /*
82
+ * ReactViewGroup no-ops requestLayout, and getWidth()/getHeight() are 0 on
83
+ * attach - re-run measure/layout on the next frame so the hosted ad renders.
84
+ */
85
+ override fun requestLayout() {
86
+ super.requestLayout()
87
+ removeCallbacks(measureAndLayoutRunnable)
88
+ post(measureAndLayoutRunnable)
89
+ }
90
+
91
+ /** Invoked from the ViewManager's onAfterUpdateTransaction, after all props are set. */
92
+ fun onSetProps() {
93
+ maybeAttachAdView()
94
+ }
95
+
96
+ private fun maybeAttachAdView() {
97
+ if (adView != null) return
98
+ val unitId = adUnitId ?: return
99
+ val format = adFormat ?: return
100
+
101
+ val created = if (format.equals("MREC", ignoreCase = true)) {
102
+ CloudX.createMREC(reactContext, unitId)
103
+ } else {
104
+ CloudX.createBanner(reactContext, unitId)
105
+ }
106
+
107
+ created.listener = createListener()
108
+ created.revenueListener = createRevenueListener()
109
+ placement?.let { created.setPlacement(it) }
110
+ customData?.let { created.setCustomData(it) }
111
+
112
+ adView = created
113
+ applyExtraParametersIfReady()
114
+ addView(created)
115
+ created.load()
116
+ updateAutoRefresh()
117
+ }
118
+
119
+ private fun updateAutoRefresh() {
120
+ val view = adView ?: return
121
+ if (isAttachedToWindow) view.startAutoRefresh() else view.stopAutoRefresh()
122
+ }
123
+
124
+ override fun onAttachedToWindow() {
125
+ super.onAttachedToWindow()
126
+ adView?.startAutoRefresh()
127
+ }
128
+
129
+ override fun onDetachedFromWindow() {
130
+ super.onDetachedFromWindow()
131
+ adView?.stopAutoRefresh()
132
+
133
+ /*
134
+ * Defer one frame: a tab switch detaches but keeps the parent, a real
135
+ * unmount removes it. Destroy only on a genuine unmount.
136
+ */
137
+ post {
138
+ if (parent == null) {
139
+ destroyAdView()
140
+ } else {
141
+ /*
142
+ * Still parented on the deferred frame = a tab switch, not an
143
+ * unmount, so re-arm refresh. If the view is instead being
144
+ * dropped, CloudXAdViewManagerImpl.onDropViewInstance calls
145
+ * destroyAdView() first (nulling adView), so this stays a
146
+ * null-safe no-op - refresh is never armed on a dead view.
147
+ */
148
+ adView?.startAutoRefresh()
149
+ }
150
+ }
151
+ }
152
+
153
+ fun destroyAdView() {
154
+ val view = adView ?: return
155
+ view.stopAutoRefresh()
156
+ view.listener = null
157
+ view.revenueListener = null
158
+ view.destroy()
159
+ removeView(view)
160
+ adView = null
161
+ appliedExtraParameterKeys = emptySet()
162
+ }
163
+
164
+ private fun applyExtraParametersIfReady() {
165
+ val view = adView ?: return
166
+ CloudXExtraParameters.applyToAdView(view, extraParameters)
167
+
168
+ val currentKeys = extraParameters.keys.toSet()
169
+ for (key in appliedExtraParameterKeys - currentKeys) {
170
+ view.setExtraParameter(key, null)
171
+ }
172
+ appliedExtraParameterKeys = currentKeys
173
+ }
174
+
175
+ private fun dispatchAdEvent(eventName: String, payload: WritableMap) {
176
+ val dispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, id) ?: return
177
+ val surfaceId = UIManagerHelper.getSurfaceId(reactContext)
178
+ dispatcher.dispatchEvent(CloudXAdViewEvent(surfaceId, id, eventName, payload))
179
+ }
180
+
181
+ private fun createListener(): CloudXAdViewListener = object : CloudXAdViewListener {
182
+ override fun onAdLoaded(cloudXAd: CloudXAd) {
183
+ dispatchAdEvent(CloudXAdEvents.ON_AD_VIEW_LOADED_EVENT, adInfoPayload(cloudXAd))
184
+ }
185
+
186
+ override fun onAdLoadFailed(failedAdUnitId: String, cloudXError: CloudXError) {
187
+ dispatchAdEvent(CloudXAdEvents.ON_AD_VIEW_LOAD_FAILED_EVENT, loadFailedPayload(failedAdUnitId, cloudXError))
188
+ }
189
+
190
+ override fun onAdClicked(cloudXAd: CloudXAd) {
191
+ dispatchAdEvent(CloudXAdEvents.ON_AD_VIEW_CLICKED_EVENT, adInfoPayload(cloudXAd))
192
+ }
193
+
194
+ override fun onAdExpanded(cloudXAd: CloudXAd) = Unit
195
+
196
+ override fun onAdCollapsed(cloudXAd: CloudXAd) = Unit
197
+ }
198
+
199
+ private fun createRevenueListener(): CloudXAdRevenueListener = object : CloudXAdRevenueListener {
200
+ override fun onAdRevenuePaid(cloudXAd: CloudXAd) {
201
+ dispatchAdEvent(CloudXAdEvents.ON_AD_VIEW_REVENUE_PAID_EVENT, adInfoPayload(cloudXAd))
202
+ }
203
+ }
204
+
205
+ /*
206
+ * Codegen cannot express Record<string,string>, so ad values are serialized
207
+ * to a JSON string here and re-parsed by the JS wrapper.
208
+ */
209
+ private fun adInfoPayload(ad: CloudXAd): WritableMap {
210
+ val map = Arguments.createMap()
211
+ map.putString("adUnitId", ad.adUnitId)
212
+ map.putString("adFormat", ad.adFormat.name)
213
+ map.putString("networkName", ad.networkName)
214
+ map.putString("networkPlacement", ad.networkPlacement ?: "")
215
+ map.putString("placement", ad.placement ?: "")
216
+ map.putDouble("revenue", ad.revenue)
217
+ /*
218
+ * The SDK types adValues as Map<String, String>, so the cast is safe
219
+ * today. Guard defensively anyway: an unexpected type or serialization
220
+ * failure here would otherwise crash the ad listener. Log rather than
221
+ * swallow silently so a genuine SDK contract change stays visible.
222
+ */
223
+ val adValuesJson = try {
224
+ JSONObject(ad.adValues as Map<*, *>).toString()
225
+ } catch (e: Exception) {
226
+ Log.w(TAG, "Failed to serialize adValues; delivering empty object", e)
227
+ "{}"
228
+ }
229
+ map.putString("adValuesJson", adValuesJson)
230
+ return map
231
+ }
232
+
233
+ private fun loadFailedPayload(failedAdUnitId: String, error: CloudXError): WritableMap {
234
+ val map = Arguments.createMap()
235
+ map.putString("adUnitId", failedAdUnitId)
236
+ /*
237
+ * Codegen spec declares `code` as Double; emit a double to match (and
238
+ * to stay consistent with `revenue` and the iOS side).
239
+ */
240
+ map.putDouble("code", error.code.code.toDouble())
241
+ map.putString("message", error.message)
242
+ return map
243
+ }
244
+ }
@@ -0,0 +1,28 @@
1
+ package com.cloudxreactnative
2
+
3
+ import com.facebook.react.bridge.WritableMap
4
+ import com.facebook.react.uimanager.events.Event
5
+
6
+ /**
7
+ * A per-view direct event for the in-tree CloudXAdView. The event name doubles
8
+ * as the JS prop registrationName (see CloudXAdViewManagerImpl).
9
+ */
10
+ class CloudXAdViewEvent(
11
+ surfaceId: Int,
12
+ viewId: Int,
13
+ private val eventName: String,
14
+ private val payload: WritableMap,
15
+ ) : Event<CloudXAdViewEvent>(surfaceId, viewId) {
16
+
17
+ override fun getEventName(): String = eventName
18
+
19
+ override fun getEventData(): WritableMap = payload
20
+
21
+ /*
22
+ * Ad-lifecycle events are discrete and must never be dropped. The default
23
+ * (true) lets the dispatcher coalesce events sharing the same
24
+ * (eventName, viewId) within a batch, keeping only the latest - which would
25
+ * silently drop, e.g., back-to-back revenue events on the same view.
26
+ */
27
+ override fun canCoalesce(): Boolean = false
28
+ }
@@ -0,0 +1,54 @@
1
+ package com.cloudxreactnative
2
+
3
+ import com.facebook.react.common.MapBuilder
4
+ import com.facebook.react.bridge.ReadableArray
5
+ import com.facebook.react.uimanager.ThemedReactContext
6
+
7
+ /**
8
+ * Shared logic for the CloudXAdView view manager, used by both the Old (Paper)
9
+ * and New (Fabric) architecture manager variants under src/oldarch and src/newarch.
10
+ */
11
+ object CloudXAdViewManagerImpl {
12
+
13
+ const val NAME = "CloudXAdView"
14
+
15
+ fun createViewInstance(reactContext: ThemedReactContext): CloudXAdView = CloudXAdView(reactContext)
16
+
17
+ fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> =
18
+ MapBuilder.builder<String, Any>()
19
+ .put(CloudXAdEvents.ON_AD_VIEW_LOADED_EVENT, eventRegistration(CloudXAdEvents.ON_AD_VIEW_LOADED_EVENT))
20
+ .put(CloudXAdEvents.ON_AD_VIEW_LOAD_FAILED_EVENT, eventRegistration(CloudXAdEvents.ON_AD_VIEW_LOAD_FAILED_EVENT))
21
+ .put(CloudXAdEvents.ON_AD_VIEW_CLICKED_EVENT, eventRegistration(CloudXAdEvents.ON_AD_VIEW_CLICKED_EVENT))
22
+ .put(CloudXAdEvents.ON_AD_VIEW_REVENUE_PAID_EVENT, eventRegistration(CloudXAdEvents.ON_AD_VIEW_REVENUE_PAID_EVENT))
23
+ .build()
24
+
25
+ private fun eventRegistration(name: String): Map<String, String> = MapBuilder.of("registrationName", name)
26
+
27
+ fun setAdUnitId(view: CloudXAdView, adUnitId: String?) {
28
+ view.adUnitId = adUnitId
29
+ }
30
+
31
+ fun setAdFormat(view: CloudXAdView, adFormat: String?) {
32
+ view.adFormat = adFormat
33
+ }
34
+
35
+ fun setPlacement(view: CloudXAdView, placement: String?) {
36
+ view.placement = placement
37
+ }
38
+
39
+ fun setCustomData(view: CloudXAdView, customData: String?) {
40
+ view.customData = customData
41
+ }
42
+
43
+ fun setExtraParameters(view: CloudXAdView, extraParameters: ReadableArray?) {
44
+ view.extraParameters = CloudXExtraParameters.entryArrayToMap(extraParameters)
45
+ }
46
+
47
+ fun onAfterUpdateTransaction(view: CloudXAdView) {
48
+ view.onSetProps()
49
+ }
50
+
51
+ fun onDropViewInstance(view: CloudXAdView) {
52
+ view.destroyAdView()
53
+ }
54
+ }
@@ -0,0 +1,101 @@
1
+ package com.cloudxreactnative
2
+
3
+ import com.facebook.react.bridge.ReadableArray
4
+ import com.facebook.react.bridge.ReadableMap
5
+ import com.facebook.react.bridge.ReadableType
6
+ import io.cloudx.sdk.CloudXAdView as SdkAdView
7
+
8
+ /**
9
+ * Shared conversion and application helpers for CloudX extra parameters.
10
+ *
11
+ * Programmatic APIs receive a [ReadableMap], while component props receive a
12
+ * [ReadableArray] of key/value entries from codegen. Both paths normalize into
13
+ * Kotlin values before calling the same SDK setter behavior.
14
+ */
15
+ object CloudXExtraParameters {
16
+
17
+ /**
18
+ * Iterates a programmatic [ReadableMap], ignoring blank keys and preserving
19
+ * nested arrays/maps as Kotlin collections.
20
+ */
21
+ fun forEach(extraParameters: ReadableMap, apply: (String, Any?) -> Unit) {
22
+ val iterator = extraParameters.keySetIterator()
23
+ while (iterator.hasNextKey()) {
24
+ val key = iterator.nextKey()
25
+ if (key.isBlank()) continue
26
+ apply(key, readableMapValue(extraParameters, key))
27
+ }
28
+ }
29
+
30
+ /**
31
+ * Converts component prop entries into a key/value map that can be diffed
32
+ * by the owning component view before being applied.
33
+ */
34
+ fun entryArrayToMap(extraParameters: ReadableArray?): Map<String, Any?> {
35
+ if (extraParameters == null) {
36
+ return emptyMap()
37
+ }
38
+
39
+ val result = linkedMapOf<String, Any?>()
40
+ for (index in 0 until extraParameters.size()) {
41
+ if (extraParameters.getType(index) != ReadableType.Map) continue
42
+
43
+ val entry = extraParameters.getMap(index) ?: continue
44
+ if (!entry.hasKey("key") || entry.getType("key") != ReadableType.String) continue
45
+
46
+ val key = entry.getString("key") ?: continue
47
+ if (key.isBlank()) continue
48
+ result[key] = if (entry.hasKey("value")) readableMapValue(entry, "value") else null
49
+ }
50
+ return result
51
+ }
52
+
53
+ /**
54
+ * Applies already-normalized extra parameters to [adView].
55
+ */
56
+ fun applyToAdView(adView: SdkAdView, extraParameters: Map<String, Any?>) {
57
+ for ((key, value) in extraParameters) {
58
+ adView.setExtraParameter(key, value)
59
+ }
60
+ }
61
+
62
+ private fun readableMapValue(map: ReadableMap, key: String): Any? {
63
+ return when (map.getType(key)) {
64
+ ReadableType.Null -> null
65
+ ReadableType.Boolean -> map.getBoolean(key)
66
+ ReadableType.Number -> map.getDouble(key)
67
+ ReadableType.String -> map.getString(key)
68
+ ReadableType.Map -> map.getMap(key)?.let(::readableMapToMap)
69
+ ReadableType.Array -> map.getArray(key)?.let(::readableArrayToList)
70
+ }
71
+ }
72
+
73
+ private fun readableMapToMap(readableMap: ReadableMap): Map<String, Any?> {
74
+ val result = mutableMapOf<String, Any?>()
75
+ val iterator = readableMap.keySetIterator()
76
+ while (iterator.hasNextKey()) {
77
+ val key = iterator.nextKey()
78
+ result[key] = readableMapValue(readableMap, key)
79
+ }
80
+ return result
81
+ }
82
+
83
+ private fun readableArrayToList(readableArray: ReadableArray): List<Any?> {
84
+ val result = mutableListOf<Any?>()
85
+ for (index in 0 until readableArray.size()) {
86
+ result.add(readableArrayValue(readableArray, index))
87
+ }
88
+ return result
89
+ }
90
+
91
+ private fun readableArrayValue(array: ReadableArray, index: Int): Any? {
92
+ return when (array.getType(index)) {
93
+ ReadableType.Null -> null
94
+ ReadableType.Boolean -> array.getBoolean(index)
95
+ ReadableType.Number -> array.getDouble(index)
96
+ ReadableType.String -> array.getString(index)
97
+ ReadableType.Map -> array.getMap(index)?.let(::readableMapToMap)
98
+ ReadableType.Array -> array.getArray(index)?.let(::readableArrayToList)
99
+ }
100
+ }
101
+ }
@@ -13,7 +13,6 @@ import com.facebook.react.bridge.Arguments
13
13
  import com.facebook.react.bridge.LifecycleEventListener
14
14
  import com.facebook.react.bridge.Promise
15
15
  import com.facebook.react.bridge.ReactApplicationContext
16
- import com.facebook.react.bridge.ReadableArray
17
16
  import com.facebook.react.bridge.ReadableMap
18
17
  import com.facebook.react.bridge.ReadableType
19
18
  import com.facebook.react.bridge.WritableMap
@@ -229,7 +228,7 @@ class CloudXModuleImpl(private val reactApplicationContext: ReactApplicationCont
229
228
  }
230
229
 
231
230
  fun setInterstitialExtraParameters(adUnitId: String, extraParameters: ReadableMap) {
232
- applyExtraParameters(extraParameters) { key, value ->
231
+ CloudXExtraParameters.forEach(extraParameters) { key, value ->
233
232
  retrieveInterstitial(adUnitId).setExtraParameter(key, value)
234
233
  }
235
234
  }
@@ -269,7 +268,7 @@ class CloudXModuleImpl(private val reactApplicationContext: ReactApplicationCont
269
268
  }
270
269
 
271
270
  fun setRewardedExtraParameters(adUnitId: String, extraParameters: ReadableMap) {
272
- applyExtraParameters(extraParameters) { key, value ->
271
+ CloudXExtraParameters.forEach(extraParameters) { key, value ->
273
272
  retrieveRewarded(adUnitId).setExtraParameter(key, value)
274
273
  }
275
274
  }
@@ -458,14 +457,14 @@ class CloudXModuleImpl(private val reactApplicationContext: ReactApplicationCont
458
457
  reactApplicationContext.runOnUiQueueThread {
459
458
  val adView = retrieveAdView(adUnitId, adFormat)
460
459
  if (adView != null) {
461
- applyExtraParameters(extraParameters) { key, value ->
460
+ CloudXExtraParameters.forEach(extraParameters) { key, value ->
462
461
  adView.setExtraParameter(key, value)
463
462
  }
464
463
  return@runOnUiQueueThread
465
464
  }
466
465
 
467
466
  val pending = adViewExtraParameters.getOrPut(adUnitId) { ConcurrentHashMap() }
468
- applyExtraParameters(extraParameters) { key, value ->
467
+ CloudXExtraParameters.forEach(extraParameters) { key, value ->
469
468
  if (value == null) {
470
469
  pending.remove(key)
471
470
  } else {
@@ -477,58 +476,7 @@ class CloudXModuleImpl(private val reactApplicationContext: ReactApplicationCont
477
476
 
478
477
  private fun applyPendingExtraParameters(adUnitId: String, adView: SdkAdView) {
479
478
  val pending = adViewExtraParameters[adUnitId] ?: return
480
- for ((key, value) in pending) {
481
- adView.setExtraParameter(key, value)
482
- }
483
- }
484
-
485
- private fun applyExtraParameters(extraParameters: ReadableMap, apply: (String, Any?) -> Unit) {
486
- val iterator = extraParameters.keySetIterator()
487
- while (iterator.hasNextKey()) {
488
- val key = iterator.nextKey()
489
- if (key.isBlank()) continue
490
- apply(key, readableMapValue(extraParameters, key))
491
- }
492
- }
493
-
494
- private fun readableMapValue(map: ReadableMap, key: String): Any? {
495
- return when (map.getType(key)) {
496
- ReadableType.Null -> null
497
- ReadableType.Boolean -> map.getBoolean(key)
498
- ReadableType.Number -> map.getDouble(key)
499
- ReadableType.String -> map.getString(key)
500
- ReadableType.Map -> map.getMap(key)?.let(::readableMapToMap)
501
- ReadableType.Array -> map.getArray(key)?.let(::readableArrayToList)
502
- }
503
- }
504
-
505
- private fun readableMapToMap(readableMap: ReadableMap): Map<String, Any?> {
506
- val result = mutableMapOf<String, Any?>()
507
- val iterator = readableMap.keySetIterator()
508
- while (iterator.hasNextKey()) {
509
- val key = iterator.nextKey()
510
- result[key] = readableMapValue(readableMap, key)
511
- }
512
- return result
513
- }
514
-
515
- private fun readableArrayToList(readableArray: ReadableArray): List<Any?> {
516
- val result = mutableListOf<Any?>()
517
- for (index in 0 until readableArray.size()) {
518
- result.add(readableArrayValue(readableArray, index))
519
- }
520
- return result
521
- }
522
-
523
- private fun readableArrayValue(array: ReadableArray, index: Int): Any? {
524
- return when (array.getType(index)) {
525
- ReadableType.Null -> null
526
- ReadableType.Boolean -> array.getBoolean(index)
527
- ReadableType.Number -> array.getDouble(index)
528
- ReadableType.String -> array.getString(index)
529
- ReadableType.Map -> array.getMap(index)?.let(::readableMapToMap)
530
- ReadableType.Array -> array.getArray(index)?.let(::readableArrayToList)
531
- }
479
+ CloudXExtraParameters.applyToAdView(adView, pending)
532
480
  }
533
481
 
534
482
  private fun arbiterBids(configuration: ReadableMap): List<CloudXArbiterBid> {
@@ -9,7 +9,7 @@ import com.facebook.react.uimanager.ViewManager
9
9
 
10
10
  class CloudXPackage : TurboReactPackage() {
11
11
  override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
12
- return emptyList()
12
+ return listOf(CloudXAdViewManager())
13
13
  }
14
14
 
15
15
  override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
@@ -0,0 +1,52 @@
1
+ package com.cloudxreactnative
2
+
3
+ import com.facebook.react.module.annotations.ReactModule
4
+ import com.facebook.react.bridge.ReadableArray
5
+ import com.facebook.react.uimanager.SimpleViewManager
6
+ import com.facebook.react.uimanager.ThemedReactContext
7
+ import com.facebook.react.uimanager.ViewManagerDelegate
8
+ import com.facebook.react.viewmanagers.CloudXAdViewManagerDelegate
9
+ import com.facebook.react.viewmanagers.CloudXAdViewManagerInterface
10
+
11
+ /**
12
+ * New-Architecture (Fabric) view manager for CloudXAdView. Props are routed
13
+ * through the codegen-generated delegate/interface; all logic delegates to the
14
+ * shared CloudXAdViewManagerImpl.
15
+ */
16
+ @ReactModule(name = CloudXAdViewManagerImpl.NAME)
17
+ class CloudXAdViewManager :
18
+ SimpleViewManager<CloudXAdView>(),
19
+ CloudXAdViewManagerInterface<CloudXAdView> {
20
+
21
+ private val delegate = CloudXAdViewManagerDelegate(this)
22
+
23
+ override fun getDelegate(): ViewManagerDelegate<CloudXAdView> = delegate
24
+
25
+ override fun getName(): String = CloudXAdViewManagerImpl.NAME
26
+
27
+ override fun createViewInstance(reactContext: ThemedReactContext): CloudXAdView =
28
+ CloudXAdViewManagerImpl.createViewInstance(reactContext)
29
+
30
+ override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> =
31
+ CloudXAdViewManagerImpl.getExportedCustomDirectEventTypeConstants()
32
+
33
+ override fun setAdUnitId(view: CloudXAdView, value: String?) = CloudXAdViewManagerImpl.setAdUnitId(view, value)
34
+
35
+ override fun setAdFormat(view: CloudXAdView, value: String?) = CloudXAdViewManagerImpl.setAdFormat(view, value)
36
+
37
+ override fun setPlacement(view: CloudXAdView, value: String?) = CloudXAdViewManagerImpl.setPlacement(view, value)
38
+
39
+ override fun setCustomData(view: CloudXAdView, value: String?) = CloudXAdViewManagerImpl.setCustomData(view, value)
40
+
41
+ override fun setExtraParameters(view: CloudXAdView, value: ReadableArray?) = CloudXAdViewManagerImpl.setExtraParameters(view, value)
42
+
43
+ override fun onAfterUpdateTransaction(view: CloudXAdView) {
44
+ super.onAfterUpdateTransaction(view)
45
+ CloudXAdViewManagerImpl.onAfterUpdateTransaction(view)
46
+ }
47
+
48
+ override fun onDropViewInstance(view: CloudXAdView) {
49
+ CloudXAdViewManagerImpl.onDropViewInstance(view)
50
+ super.onDropViewInstance(view)
51
+ }
52
+ }
@@ -0,0 +1,46 @@
1
+ package com.cloudxreactnative
2
+
3
+ import com.facebook.react.bridge.ReadableArray
4
+ import com.facebook.react.uimanager.SimpleViewManager
5
+ import com.facebook.react.uimanager.ThemedReactContext
6
+ import com.facebook.react.uimanager.annotations.ReactProp
7
+
8
+ /**
9
+ * Old-Architecture (Paper) view manager for CloudXAdView. Props are wired via
10
+ * [ReactProp]; all logic delegates to the shared CloudXAdViewManagerImpl.
11
+ */
12
+ class CloudXAdViewManager : SimpleViewManager<CloudXAdView>() {
13
+
14
+ override fun getName(): String = CloudXAdViewManagerImpl.NAME
15
+
16
+ override fun createViewInstance(reactContext: ThemedReactContext): CloudXAdView =
17
+ CloudXAdViewManagerImpl.createViewInstance(reactContext)
18
+
19
+ override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> =
20
+ CloudXAdViewManagerImpl.getExportedCustomDirectEventTypeConstants()
21
+
22
+ @ReactProp(name = "adUnitId")
23
+ fun setAdUnitId(view: CloudXAdView, value: String?) = CloudXAdViewManagerImpl.setAdUnitId(view, value)
24
+
25
+ @ReactProp(name = "adFormat")
26
+ fun setAdFormat(view: CloudXAdView, value: String?) = CloudXAdViewManagerImpl.setAdFormat(view, value)
27
+
28
+ @ReactProp(name = "placement")
29
+ fun setPlacement(view: CloudXAdView, value: String?) = CloudXAdViewManagerImpl.setPlacement(view, value)
30
+
31
+ @ReactProp(name = "customData")
32
+ fun setCustomData(view: CloudXAdView, value: String?) = CloudXAdViewManagerImpl.setCustomData(view, value)
33
+
34
+ @ReactProp(name = "extraParameters")
35
+ fun setExtraParameters(view: CloudXAdView, value: ReadableArray?) = CloudXAdViewManagerImpl.setExtraParameters(view, value)
36
+
37
+ override fun onAfterUpdateTransaction(view: CloudXAdView) {
38
+ super.onAfterUpdateTransaction(view)
39
+ CloudXAdViewManagerImpl.onAfterUpdateTransaction(view)
40
+ }
41
+
42
+ override fun onDropViewInstance(view: CloudXAdView) {
43
+ CloudXAdViewManagerImpl.onDropViewInstance(view)
44
+ super.onDropViewInstance(view)
45
+ }
46
+ }