@sellwild/react-native-sdk 1.2.0 → 1.3.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.
- package/android/build/.transforms/055edc6990905b0d0e7b2a38f451ea8f/results.bin +1 -0
- package/android/build/.transforms/055edc6990905b0d0e7b2a38f451ea8f/transformed/classes/classes_dex/classes.dex +0 -0
- package/android/build/.transforms/9adcec60aa21840716976bd52bc3bd4a/results.bin +1 -0
- package/android/build/.transforms/9adcec60aa21840716976bd52bc3bd4a/transformed/classes/classes_dex/classes.dex +0 -0
- package/android/build/.transforms/f6cdcb296ca6520e70a1cebbdcbe808e/results.bin +1 -0
- package/android/build/.transforms/f6cdcb296ca6520e70a1cebbdcbe808e/transformed/classes/classes_dex/classes.dex +0 -0
- package/android/build/generated/source/buildConfig/debug/com/sellwild/rnsdk/BuildConfig.java +10 -0
- package/android/build/intermediates/aapt_friendly_merged_manifests/debug/aapt/AndroidManifest.xml +7 -0
- package/android/build/intermediates/aapt_friendly_merged_manifests/debug/aapt/output-metadata.json +18 -0
- package/android/build/intermediates/aar_metadata/debug/aar-metadata.properties +6 -0
- package/android/build/intermediates/annotation_processor_list/debug/annotationProcessors.json +1 -0
- package/android/build/intermediates/compile_library_classes_jar/debug/classes.jar +0 -0
- package/android/build/intermediates/compile_r_class_jar/debug/R.jar +0 -0
- package/android/build/intermediates/compile_symbol_list/debug/R.txt +0 -0
- package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -0
- package/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +2 -0
- package/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +2 -0
- package/android/build/intermediates/incremental/mergeDebugShaders/merger.xml +2 -0
- package/android/build/intermediates/incremental/packageDebugAssets/merger.xml +2 -0
- package/android/build/intermediates/java_res/debug/out/META-INF/sellwild-react-native-sdk_debug.kotlin_module +0 -0
- package/android/build/intermediates/javac/debug/classes/com/sellwild/rnsdk/BuildConfig.class +0 -0
- package/android/build/intermediates/local_only_symbol_list/debug/R-def.txt +2 -0
- package/android/build/intermediates/manifest_merge_blame_file/debug/manifest-merger-blame-debug-report.txt +7 -0
- package/android/build/intermediates/merged_manifest/debug/AndroidManifest.xml +7 -0
- package/android/build/intermediates/navigation_json/debug/navigation.json +1 -0
- package/android/build/intermediates/runtime_library_classes_jar/debug/classes.jar +0 -0
- package/android/build/intermediates/symbol_list_with_package_name/debug/package-aware-r.txt +1 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/counters.tab +2 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
- package/android/build/kotlin/compileDebugKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin +0 -0
- package/android/build/kotlin/compileDebugKotlin/local-state/build-history.bin +0 -0
- package/android/build/outputs/logs/manifest-merger-debug-report.txt +16 -0
- package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
- package/android/build/tmp/kotlin-classes/debug/META-INF/sellwild-react-native-sdk_debug.kotlin_module +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/sellwild/rnsdk/SellwildBannerViewManager$Companion.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/sellwild/rnsdk/SellwildBannerViewManager$PendingProps.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/sellwild/rnsdk/SellwildBannerViewManager$createViewInstance$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/sellwild/rnsdk/SellwildBannerViewManager.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/com/sellwild/rnsdk/SellwildSdkPackage.class +0 -0
- package/android/build.gradle +68 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/com/sellwild/rnsdk/SellwildBannerViewManager.kt +200 -0
- package/android/src/main/java/com/sellwild/rnsdk/SellwildSdkPackage.kt +18 -0
- package/ios/SellwildBannerViewManager.m +24 -0
- package/ios/SellwildBannerViewManager.swift +168 -0
- package/ios/SellwildSDK-RN.podspec +31 -0
- package/package.json +2 -2
- package/src/SellwildBanner.tsx +105 -39
- package/src/htmlBuilder.ts +1 -1
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
package com.sellwild.rnsdk
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.ReactContext
|
|
4
|
+
import com.facebook.react.bridge.ReadableMap
|
|
5
|
+
import com.facebook.react.common.MapBuilder
|
|
6
|
+
import com.facebook.react.uimanager.SimpleViewManager
|
|
7
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
8
|
+
import com.facebook.react.uimanager.annotations.ReactProp
|
|
9
|
+
import com.facebook.react.uimanager.events.RCTEventEmitter
|
|
10
|
+
import com.sellwild.sdk.AdSize
|
|
11
|
+
import com.sellwild.sdk.SellwildAdView
|
|
12
|
+
import com.sellwild.sdk.SellwildConfig
|
|
13
|
+
import org.json.JSONObject
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Bridges the JS <SellwildBanner> component to the native
|
|
17
|
+
* com.sellwild.sdk.SellwildAdView.
|
|
18
|
+
*
|
|
19
|
+
* Props (set from JS):
|
|
20
|
+
* - config: object — the resolved SellwildConfig (from configure()).
|
|
21
|
+
* Only the fields the native ad path reads are required:
|
|
22
|
+
* partnerCode, appBundleId, appStoreUrl, gamTag, debug,
|
|
23
|
+
* adRefreshMax, adRefreshMaxMobile, adRefreshIntervalMs,
|
|
24
|
+
* prebidServer (object), remote (object).
|
|
25
|
+
* - size: string — "320x50", "300x250", "728x90", "300x600", "160x600".
|
|
26
|
+
* - zoneId: string — Sellwild zone tag, e.g. "43".
|
|
27
|
+
*
|
|
28
|
+
* Events emitted to JS:
|
|
29
|
+
* - onAdLoaded
|
|
30
|
+
* - onAdImpression
|
|
31
|
+
* - onAdClicked
|
|
32
|
+
* - onAdFailed { message }
|
|
33
|
+
*
|
|
34
|
+
* The view defers calling SellwildAdView.setup() + load() until all three
|
|
35
|
+
* required props (config, size, zoneId) have arrived in a single transaction.
|
|
36
|
+
*/
|
|
37
|
+
class SellwildBannerViewManager : SimpleViewManager<SellwildAdView>() {
|
|
38
|
+
|
|
39
|
+
override fun getName(): String = REACT_CLASS
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Per-view scratch state. We can't call SellwildAdView.setup() until
|
|
43
|
+
* all three required props (config/size/zoneId) have arrived, so we
|
|
44
|
+
* stash them here and apply on onAfterUpdateTransaction.
|
|
45
|
+
*
|
|
46
|
+
* Keyed by the ad view itself so multiple <SellwildBanner>s on screen
|
|
47
|
+
* don't collide. Cleared on view drop.
|
|
48
|
+
*/
|
|
49
|
+
private val pending = java.util.WeakHashMap<SellwildAdView, PendingProps>()
|
|
50
|
+
|
|
51
|
+
private data class PendingProps(
|
|
52
|
+
var config: ReadableMap? = null,
|
|
53
|
+
var size: String? = null,
|
|
54
|
+
var zoneId: String? = null,
|
|
55
|
+
// Guards against running fresh auctions on every JS re-render. We
|
|
56
|
+
// only call setup() + load() once per identity tuple. Refresh of
|
|
57
|
+
// the rendered ad is driven by the SDK's internal timer.
|
|
58
|
+
var lastAppliedKey: String? = null,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
override fun createViewInstance(reactContext: ThemedReactContext): SellwildAdView {
|
|
62
|
+
val view = SellwildAdView(reactContext)
|
|
63
|
+
pending[view] = PendingProps()
|
|
64
|
+
view.listener = object : SellwildAdView.Listener {
|
|
65
|
+
override fun onAdLoaded(adView: SellwildAdView) {
|
|
66
|
+
emit(reactContext, adView, "onAdLoaded", null)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
override fun onAdImpression(adView: SellwildAdView, zoneId: String) {
|
|
70
|
+
val payload = com.facebook.react.bridge.Arguments.createMap().apply {
|
|
71
|
+
putString("zoneId", zoneId)
|
|
72
|
+
}
|
|
73
|
+
emit(reactContext, adView, "onAdImpression", payload)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
override fun onAdClicked(adView: SellwildAdView) {
|
|
77
|
+
emit(reactContext, adView, "onAdClicked", null)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
override fun onAdFailed(adView: SellwildAdView, message: String) {
|
|
81
|
+
val payload = com.facebook.react.bridge.Arguments.createMap().apply {
|
|
82
|
+
putString("message", message)
|
|
83
|
+
}
|
|
84
|
+
emit(reactContext, adView, "onAdFailed", payload)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return view
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
@ReactProp(name = "config")
|
|
91
|
+
fun setConfig(view: SellwildAdView, value: ReadableMap?) {
|
|
92
|
+
pendingFor(view).config = value
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
@ReactProp(name = "size")
|
|
96
|
+
fun setSize(view: SellwildAdView, value: String?) {
|
|
97
|
+
pendingFor(view).size = value
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
@ReactProp(name = "zoneId")
|
|
101
|
+
fun setZoneId(view: SellwildAdView, value: String?) {
|
|
102
|
+
pendingFor(view).zoneId = value
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
override fun onAfterUpdateTransaction(view: SellwildAdView) {
|
|
106
|
+
super.onAfterUpdateTransaction(view)
|
|
107
|
+
|
|
108
|
+
val p = pending[view] ?: return
|
|
109
|
+
val configMap = p.config ?: return
|
|
110
|
+
val sizeLabel = p.size ?: return
|
|
111
|
+
val zoneId = p.zoneId ?: return
|
|
112
|
+
|
|
113
|
+
val adSize = adSizeFromLabel(sizeLabel) ?: return
|
|
114
|
+
|
|
115
|
+
// Skip if the props identity hasn't changed since last apply.
|
|
116
|
+
val key = "$sizeLabel|$zoneId|${configMap.hashCode()}"
|
|
117
|
+
if (p.lastAppliedKey == key) return
|
|
118
|
+
p.lastAppliedKey = key
|
|
119
|
+
|
|
120
|
+
val config = configFromMap(configMap)
|
|
121
|
+
view.setup(config, adSize, zoneId)
|
|
122
|
+
view.load()
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
override fun onDropViewInstance(view: SellwildAdView) {
|
|
126
|
+
pending.remove(view)
|
|
127
|
+
super.onDropViewInstance(view)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private fun pendingFor(view: SellwildAdView): PendingProps =
|
|
131
|
+
pending.getOrPut(view) { PendingProps() }
|
|
132
|
+
|
|
133
|
+
override fun getExportedCustomDirectEventTypeConstants(): Map<String, Any> {
|
|
134
|
+
return MapBuilder.builder<String, Any>()
|
|
135
|
+
.put("onAdLoaded", MapBuilder.of("registrationName", "onAdLoaded"))
|
|
136
|
+
.put("onAdImpression", MapBuilder.of("registrationName", "onAdImpression"))
|
|
137
|
+
.put("onAdClicked", MapBuilder.of("registrationName", "onAdClicked"))
|
|
138
|
+
.put("onAdFailed", MapBuilder.of("registrationName", "onAdFailed"))
|
|
139
|
+
.build()
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
private fun emit(
|
|
143
|
+
context: ReactContext,
|
|
144
|
+
view: SellwildAdView,
|
|
145
|
+
name: String,
|
|
146
|
+
payload: com.facebook.react.bridge.WritableMap?,
|
|
147
|
+
) {
|
|
148
|
+
context.getJSModule(RCTEventEmitter::class.java)
|
|
149
|
+
.receiveEvent(view.id, name, payload)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
companion object {
|
|
153
|
+
const val REACT_CLASS = "SellwildBannerView"
|
|
154
|
+
|
|
155
|
+
internal fun adSizeFromLabel(label: String): AdSize? = when (label) {
|
|
156
|
+
"320x50" -> AdSize.BANNER_320x50
|
|
157
|
+
"300x250" -> AdSize.MREC_300x250
|
|
158
|
+
"728x90" -> AdSize.LEADERBOARD_728x90
|
|
159
|
+
"300x600" -> AdSize.HALF_PAGE_300x600
|
|
160
|
+
"160x600" -> AdSize.WIDE_SKYSCRAPER_160x600
|
|
161
|
+
else -> null
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Build a minimal SellwildConfig from a JS map. Only the fields the
|
|
166
|
+
* native banner path actually reads are mapped here; everything else
|
|
167
|
+
* gets sane defaults from the data class. The raw CDN JSON (if
|
|
168
|
+
* present under `remote`) is preserved as `remoteJson` for the
|
|
169
|
+
* passthrough auction params.
|
|
170
|
+
*/
|
|
171
|
+
internal fun configFromMap(map: ReadableMap): SellwildConfig {
|
|
172
|
+
val partnerCode = if (map.hasKey("partnerCode")) map.getString("partnerCode") else null
|
|
173
|
+
val appBundleId = if (map.hasKey("appBundleId")) map.getString("appBundleId") else null
|
|
174
|
+
val appStoreUrl = if (map.hasKey("appStoreUrl")) map.getString("appStoreUrl") else null
|
|
175
|
+
val gamTag = if (map.hasKey("gamTag")) map.getString("gamTag") else null
|
|
176
|
+
val debug = map.hasKey("debug") && map.getBoolean("debug")
|
|
177
|
+
val adRefreshMax = if (map.hasKey("adRefreshMax")) map.getInt("adRefreshMax") else 0
|
|
178
|
+
val adRefreshMaxMobile = if (map.hasKey("adRefreshMaxMobile")) map.getInt("adRefreshMaxMobile") else 0
|
|
179
|
+
val adRefreshIntervalMs = if (map.hasKey("adRefreshIntervalMs")) map.getDouble("adRefreshIntervalMs").toLong() else 30_000L
|
|
180
|
+
|
|
181
|
+
val remoteJson = if (map.hasKey("remote") && !map.isNull("remote")) {
|
|
182
|
+
JSONObject(map.getMap("remote")!!.toHashMap()).toString()
|
|
183
|
+
} else {
|
|
184
|
+
null
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return SellwildConfig(
|
|
188
|
+
partnerCode = partnerCode ?: "",
|
|
189
|
+
appBundleId = appBundleId,
|
|
190
|
+
appStoreUrl = appStoreUrl,
|
|
191
|
+
gamTag = gamTag,
|
|
192
|
+
debug = debug,
|
|
193
|
+
adRefreshMax = adRefreshMax,
|
|
194
|
+
adRefreshMaxMobile = adRefreshMaxMobile,
|
|
195
|
+
adRefreshIntervalMs = adRefreshIntervalMs,
|
|
196
|
+
remoteJson = remoteJson,
|
|
197
|
+
)
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
package com.sellwild.rnsdk
|
|
2
|
+
|
|
3
|
+
import android.view.View
|
|
4
|
+
import com.facebook.react.ReactPackage
|
|
5
|
+
import com.facebook.react.bridge.NativeModule
|
|
6
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
7
|
+
import com.facebook.react.uimanager.ReactShadowNode
|
|
8
|
+
import com.facebook.react.uimanager.ViewManager
|
|
9
|
+
|
|
10
|
+
class SellwildSdkPackage : ReactPackage {
|
|
11
|
+
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> = emptyList()
|
|
12
|
+
|
|
13
|
+
override fun createViewManagers(
|
|
14
|
+
reactContext: ReactApplicationContext,
|
|
15
|
+
): List<ViewManager<out View, out ReactShadowNode<*>>> = listOf(
|
|
16
|
+
SellwildBannerViewManager(),
|
|
17
|
+
)
|
|
18
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#import <React/RCTViewManager.h>
|
|
2
|
+
#import <React/RCTUIManager.h>
|
|
3
|
+
#import <React/RCTBridgeModule.h>
|
|
4
|
+
|
|
5
|
+
// Register the view manager class with React Native. We export it under
|
|
6
|
+
// the JS name "SellwildBannerView" to match the Android side
|
|
7
|
+
// (com.sellwild.rnsdk.SellwildBannerViewManager.REACT_CLASS).
|
|
8
|
+
@interface RCT_EXTERN_REMAP_MODULE(SellwildBannerView,
|
|
9
|
+
SellwildBannerViewManager,
|
|
10
|
+
RCTViewManager)
|
|
11
|
+
|
|
12
|
+
// Props set from JS — these forward to @objc properties on
|
|
13
|
+
// SellwildBannerHostView.
|
|
14
|
+
RCT_EXPORT_VIEW_PROPERTY(config, NSDictionary)
|
|
15
|
+
RCT_EXPORT_VIEW_PROPERTY(size, NSString)
|
|
16
|
+
RCT_EXPORT_VIEW_PROPERTY(zoneId, NSString)
|
|
17
|
+
|
|
18
|
+
// Direct events emitted to JS callbacks.
|
|
19
|
+
RCT_EXPORT_VIEW_PROPERTY(onAdLoaded, RCTDirectEventBlock)
|
|
20
|
+
RCT_EXPORT_VIEW_PROPERTY(onAdImpression, RCTDirectEventBlock)
|
|
21
|
+
RCT_EXPORT_VIEW_PROPERTY(onAdClicked, RCTDirectEventBlock)
|
|
22
|
+
RCT_EXPORT_VIEW_PROPERTY(onAdFailed, RCTDirectEventBlock)
|
|
23
|
+
|
|
24
|
+
@end
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import React
|
|
3
|
+
import SellwildSDK
|
|
4
|
+
import UIKit
|
|
5
|
+
|
|
6
|
+
/// Bridges the JS `<SellwildBanner>` component to the native
|
|
7
|
+
/// `SellwildAdView` (Prebid Mobile + AdManagerBannerView). Mirrors the
|
|
8
|
+
/// Android `SellwildBannerViewManager` shape.
|
|
9
|
+
///
|
|
10
|
+
/// Props (set from JS):
|
|
11
|
+
/// - config: object — the resolved SellwildConfig (from configure()).
|
|
12
|
+
/// Only the fields the native ad path reads are required.
|
|
13
|
+
/// - size: string — "320x50", "300x250", "728x90", "300x600", "160x600".
|
|
14
|
+
/// - zoneId: string — Sellwild zone tag, e.g. "43".
|
|
15
|
+
///
|
|
16
|
+
/// Events emitted to JS:
|
|
17
|
+
/// - onAdLoaded
|
|
18
|
+
/// - onAdImpression { zoneId }
|
|
19
|
+
/// - onAdClicked
|
|
20
|
+
/// - onAdFailed { message }
|
|
21
|
+
@objc(SellwildBannerViewManager)
|
|
22
|
+
public final class SellwildBannerViewManager: RCTViewManager {
|
|
23
|
+
|
|
24
|
+
public override static func requiresMainQueueSetup() -> Bool { true }
|
|
25
|
+
|
|
26
|
+
public override func view() -> UIView! {
|
|
27
|
+
return SellwildBannerHostView()
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/// The actual UIView that hosts a `SellwildAdView`. We can't construct
|
|
32
|
+
/// `SellwildAdView` until all three required props (config / size /
|
|
33
|
+
/// zoneId) have arrived, so we cache them and apply once on
|
|
34
|
+
/// `didSetProps:`.
|
|
35
|
+
final class SellwildBannerHostView: UIView, SellwildAdViewDelegate {
|
|
36
|
+
|
|
37
|
+
// MARK: RN-set props
|
|
38
|
+
|
|
39
|
+
@objc var config: NSDictionary? { didSet { needsApply = true } }
|
|
40
|
+
@objc var size: NSString? { didSet { needsApply = true } }
|
|
41
|
+
@objc var zoneId: NSString? { didSet { needsApply = true } }
|
|
42
|
+
|
|
43
|
+
// MARK: RN events
|
|
44
|
+
|
|
45
|
+
@objc var onAdLoaded: RCTDirectEventBlock?
|
|
46
|
+
@objc var onAdImpression: RCTDirectEventBlock?
|
|
47
|
+
@objc var onAdClicked: RCTDirectEventBlock?
|
|
48
|
+
@objc var onAdFailed: RCTDirectEventBlock?
|
|
49
|
+
|
|
50
|
+
// MARK: Internals
|
|
51
|
+
|
|
52
|
+
private var adView: SellwildAdView?
|
|
53
|
+
private var lastAppliedKey: String?
|
|
54
|
+
private var needsApply: Bool = false
|
|
55
|
+
|
|
56
|
+
override init(frame: CGRect) {
|
|
57
|
+
super.init(frame: frame)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
required init?(coder: NSCoder) { fatalError("init(coder:) not used") }
|
|
61
|
+
|
|
62
|
+
// RN calls didSetProps once per JS render after all @objc setters
|
|
63
|
+
// have run, which lets us batch setup() + load() into a single
|
|
64
|
+
// native call instead of firing one per prop change.
|
|
65
|
+
override func didSetProps(_ changedProps: [String]) {
|
|
66
|
+
guard needsApply else { return }
|
|
67
|
+
needsApply = false
|
|
68
|
+
applyIfReady()
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private func applyIfReady() {
|
|
72
|
+
guard
|
|
73
|
+
let cfgMap = config,
|
|
74
|
+
let sizeStr = size as String?,
|
|
75
|
+
let zid = zoneId as String?,
|
|
76
|
+
let adSize = AdSize(rawValue: sizeStr)
|
|
77
|
+
else { return }
|
|
78
|
+
|
|
79
|
+
// Skip if the props identity hasn't changed since last apply —
|
|
80
|
+
// refresh of the rendered ad is driven by the SDK's internal
|
|
81
|
+
// timer, not by JS re-renders.
|
|
82
|
+
let key = "\(sizeStr)|\(zid)|\(cfgMap.hash)"
|
|
83
|
+
if lastAppliedKey == key { return }
|
|
84
|
+
lastAppliedKey = key
|
|
85
|
+
|
|
86
|
+
let sellwildConfig = Self.configFromMap(cfgMap)
|
|
87
|
+
|
|
88
|
+
// Tear down any previous ad view; SellwildAdView itself does not
|
|
89
|
+
// support adUnitId reassignment after load.
|
|
90
|
+
adView?.removeFromSuperview()
|
|
91
|
+
|
|
92
|
+
let view = SellwildAdView(config: sellwildConfig, adSize: adSize, zoneId: zid)
|
|
93
|
+
view.delegate = self
|
|
94
|
+
view.translatesAutoresizingMaskIntoConstraints = false
|
|
95
|
+
addSubview(view)
|
|
96
|
+
NSLayoutConstraint.activate([
|
|
97
|
+
view.leadingAnchor.constraint(equalTo: leadingAnchor),
|
|
98
|
+
view.topAnchor.constraint(equalTo: topAnchor),
|
|
99
|
+
view.widthAnchor.constraint(equalToConstant: adSize.cgSize.width),
|
|
100
|
+
view.heightAnchor.constraint(equalToConstant: adSize.cgSize.height),
|
|
101
|
+
])
|
|
102
|
+
adView = view
|
|
103
|
+
view.load()
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// MARK: SellwildAdViewDelegate
|
|
107
|
+
|
|
108
|
+
func sellwildAdViewDidLoad(_ adView: SellwildAdView) {
|
|
109
|
+
onAdLoaded?([:])
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
func sellwildAdView(_ adView: SellwildAdView, didReceiveImpressionForZoneId zoneId: String) {
|
|
113
|
+
onAdImpression?(["zoneId": zoneId])
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
func sellwildAdViewDidRecordClick(_ adView: SellwildAdView) {
|
|
117
|
+
onAdClicked?([:])
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
func sellwildAdView(_ adView: SellwildAdView, didFailWithError error: Error) {
|
|
121
|
+
onAdFailed?(["message": error.localizedDescription])
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// MARK: Config marshalling
|
|
125
|
+
|
|
126
|
+
/// Build a minimal SellwildConfig from a JS dictionary. Only the
|
|
127
|
+
/// fields the native banner path actually reads are mapped; the
|
|
128
|
+
/// rest get the data class defaults. The raw CDN JSON (if present
|
|
129
|
+
/// under `remote`) is preserved as `remoteJSON` for passthrough.
|
|
130
|
+
static func configFromMap(_ map: NSDictionary) -> SellwildConfig {
|
|
131
|
+
let partnerCode = (map["partnerCode"] as? String) ?? ""
|
|
132
|
+
|
|
133
|
+
var cfg = SellwildConfig(partnerCode: partnerCode)
|
|
134
|
+
|
|
135
|
+
if let v = map["appBundleId"] as? String { cfg.appBundleId = v }
|
|
136
|
+
if let v = map["appStoreUrl"] as? String { cfg.appStoreUrl = v }
|
|
137
|
+
if let v = map["gamTag"] as? String { cfg.gamTag = v }
|
|
138
|
+
if let v = map["debug"] as? Bool { cfg.debug = v }
|
|
139
|
+
if let v = map["adRefreshMax"] as? Int { cfg.adRefreshMax = v }
|
|
140
|
+
if let v = map["adRefreshMaxMobile"] as? Int { cfg.adRefreshMaxMobile = v }
|
|
141
|
+
|
|
142
|
+
// JS bridge passes ms; iOS API is seconds (TimeInterval).
|
|
143
|
+
if let v = map["adRefreshIntervalMs"] as? NSNumber {
|
|
144
|
+
cfg.adRefreshInterval = v.doubleValue / 1000.0
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if let prebid = map["prebidServer"] as? NSDictionary,
|
|
148
|
+
let accountId = prebid["accountId"] as? String,
|
|
149
|
+
let endpoint = prebid["endpoint"] as? String {
|
|
150
|
+
let bidders = (prebid["bidders"] as? [String]) ?? []
|
|
151
|
+
let timeout = (prebid["timeout"] as? Int) ?? 1500
|
|
152
|
+
cfg.prebidServer = PrebidServerConfig(
|
|
153
|
+
accountId: accountId,
|
|
154
|
+
endpoint: endpoint,
|
|
155
|
+
bidders: bidders,
|
|
156
|
+
timeout: timeout,
|
|
157
|
+
syncEndpoint: prebid["syncEndpoint"] as? String
|
|
158
|
+
)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if let remote = map["remote"] as? NSDictionary,
|
|
162
|
+
let data = try? JSONSerialization.data(withJSONObject: remote, options: []) {
|
|
163
|
+
cfg.remoteJSON = data
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return cfg
|
|
167
|
+
}
|
|
168
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, '..', 'package.json')))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = 'SellwildSDK-RN'
|
|
7
|
+
s.version = package['version']
|
|
8
|
+
s.summary = 'React Native bridge for the Sellwild iOS SDK'
|
|
9
|
+
s.description = <<-DESC
|
|
10
|
+
Bridges <SellwildBanner> from @sellwild/react-native-sdk to the
|
|
11
|
+
native iOS SellwildAdView (Prebid Mobile + AdManagerBannerView).
|
|
12
|
+
There is no WebView in the ad path.
|
|
13
|
+
DESC
|
|
14
|
+
|
|
15
|
+
s.homepage = 'https://github.com/Antengo/sellwild-sdk'
|
|
16
|
+
s.license = { :type => 'MIT' }
|
|
17
|
+
s.author = { 'Sellwild' => 'sdk@sellwild.com' }
|
|
18
|
+
s.source = { :git => 'https://github.com/Antengo/sellwild-sdk.git', :tag => s.version.to_s }
|
|
19
|
+
|
|
20
|
+
s.platforms = { :ios => '13.0' }
|
|
21
|
+
s.swift_version = '5.5'
|
|
22
|
+
|
|
23
|
+
s.source_files = '*.{swift,m,h}'
|
|
24
|
+
s.requires_arc = true
|
|
25
|
+
|
|
26
|
+
# The host app must already pull in SellwildSDK (the iOS SDK pod). We
|
|
27
|
+
# depend on it explicitly so `pod install` resolves both with one
|
|
28
|
+
# declaration in the host Podfile.
|
|
29
|
+
s.dependency 'SellwildSDK', '>= 1.3.0'
|
|
30
|
+
s.dependency 'React-Core'
|
|
31
|
+
end
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sellwild/react-native-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Sellwild mobile advertising SDK for React Native",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "src/index.ts",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"react-native-webview": ">=11.0.0"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@sellwild/sdk-core": "^1.
|
|
26
|
+
"@sellwild/sdk-core": "^1.3.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/react": "^18.0.0",
|
package/src/SellwildBanner.tsx
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import { View, StyleSheet,
|
|
3
|
-
import { WebView } from 'react-native-webview'
|
|
4
|
-
import type { WebViewMessageEvent } from 'react-native-webview'
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { Platform, requireNativeComponent, UIManager, ViewStyle, View, Text, StyleSheet, NativeSyntheticEvent } from 'react-native'
|
|
5
3
|
import type { SellwildConfig, AdSize } from '@sellwild/sdk-core'
|
|
6
|
-
import { WIDGET_BASE_URL } from '@sellwild/sdk-core'
|
|
7
|
-
import { buildBannerHtml } from './htmlBuilder'
|
|
8
4
|
|
|
9
|
-
// Standard IAB mobile ad sizes
|
|
5
|
+
// Standard IAB mobile ad sizes — used to lock the host View dimensions.
|
|
6
|
+
// The actual ad size is also propagated to native as the `size` prop label.
|
|
10
7
|
const AD_DIMENSIONS: Record<AdSize, { width: number; height: number }> = {
|
|
11
8
|
'300x250': { width: 300, height: 250 },
|
|
12
9
|
'320x50': { width: 320, height: 50 },
|
|
@@ -16,6 +13,42 @@ const AD_DIMENSIONS: Record<AdSize, { width: number; height: number }> = {
|
|
|
16
13
|
'1x1': { width: 1, height: 1 },
|
|
17
14
|
}
|
|
18
15
|
|
|
16
|
+
// ─── Native component bridge ─────────────────────────────────────────────────
|
|
17
|
+
//
|
|
18
|
+
// As of 1.3.0 the React Native banner is backed by a real native ad view —
|
|
19
|
+
// `com.sellwild.sdk.SellwildAdView` on Android (Prebid Mobile + AdManagerAdView)
|
|
20
|
+
// and `SellwildAdView` on iOS (Prebid Mobile + AdManagerBannerView). There is
|
|
21
|
+
// no WebView in the ad path on either platform.
|
|
22
|
+
//
|
|
23
|
+
// The Android bridge lives in `react-native/android` and is autolinked via
|
|
24
|
+
// the `@sellwild/react-native-sdk` package.
|
|
25
|
+
|
|
26
|
+
const NATIVE_NAME = 'SellwildBannerView'
|
|
27
|
+
|
|
28
|
+
interface NativeBannerProps {
|
|
29
|
+
config: object
|
|
30
|
+
size: string
|
|
31
|
+
zoneId: string
|
|
32
|
+
style?: ViewStyle
|
|
33
|
+
onAdLoaded?: (e: NativeSyntheticEvent<{}>) => void
|
|
34
|
+
onAdImpression?: (e: NativeSyntheticEvent<{ zoneId: string }>) => void
|
|
35
|
+
onAdClicked?: (e: NativeSyntheticEvent<{}>) => void
|
|
36
|
+
onAdFailed?: (e: NativeSyntheticEvent<{ message: string }>) => void
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const NativeBanner = (() => {
|
|
40
|
+
// requireNativeComponent crashes loudly if the view manager isn't
|
|
41
|
+
// registered. Probe first so we can render a friendly fallback on
|
|
42
|
+
// platforms where the bridge isn't in this build yet.
|
|
43
|
+
const config = UIManager.getViewManagerConfig?.(NATIVE_NAME)
|
|
44
|
+
if (!config) {
|
|
45
|
+
return null
|
|
46
|
+
}
|
|
47
|
+
return requireNativeComponent<NativeBannerProps>(NATIVE_NAME)
|
|
48
|
+
})()
|
|
49
|
+
|
|
50
|
+
// ─── Public component ────────────────────────────────────────────────────────
|
|
51
|
+
|
|
19
52
|
export interface SellwildBannerProps {
|
|
20
53
|
config: SellwildConfig
|
|
21
54
|
size: AdSize
|
|
@@ -35,40 +68,73 @@ export function SellwildBanner({
|
|
|
35
68
|
onClick,
|
|
36
69
|
onError,
|
|
37
70
|
}: SellwildBannerProps) {
|
|
38
|
-
const
|
|
39
|
-
const
|
|
71
|
+
const dim = AD_DIMENSIONS[size]
|
|
72
|
+
const containerStyle: ViewStyle = { width: dim.width, height: dim.height }
|
|
40
73
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
74
|
+
if (!NativeBanner) {
|
|
75
|
+
// Native module not registered. Most common cause: iOS bridge not yet
|
|
76
|
+
// wired (1.3.0 ships the Android bridge first; iOS lands in 1.3.x).
|
|
77
|
+
// Render a visible placeholder in dev builds so the gap is obvious;
|
|
78
|
+
// production builds get a transparent slot of the right dimensions.
|
|
79
|
+
return (
|
|
80
|
+
<View style={[containerStyle, style, __DEV__ ? styles.devPlaceholder : undefined]}>
|
|
81
|
+
{__DEV__ ? (
|
|
82
|
+
<Text style={styles.devText}>
|
|
83
|
+
Sellwild native banner not available on {Platform.OS} (yet)
|
|
84
|
+
</Text>
|
|
85
|
+
) : null}
|
|
86
|
+
</View>
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Pass only the fields the native banner path actually reads. The rest
|
|
91
|
+
// of SellwildConfig is ignored on the native side. Note: TS core uses
|
|
92
|
+
// `adRefreshInterval` (millis); the native side reads it as
|
|
93
|
+
// `adRefreshIntervalMs`. The bridge translates.
|
|
94
|
+
const nativeConfig = {
|
|
95
|
+
partnerCode: config.partnerCode,
|
|
96
|
+
appBundleId: config.appBundleId,
|
|
97
|
+
appStoreUrl: config.appStoreUrl,
|
|
98
|
+
gamTag: config.gamTag,
|
|
99
|
+
debug: config.debug,
|
|
100
|
+
adRefreshMax: config.adRefreshMax,
|
|
101
|
+
adRefreshMaxMobile: config.adRefreshMaxMobile,
|
|
102
|
+
adRefreshIntervalMs: config.adRefreshInterval,
|
|
103
|
+
prebidServer: config.prebidServer,
|
|
104
|
+
remote: config.remote,
|
|
105
|
+
}
|
|
53
106
|
|
|
54
107
|
return (
|
|
55
|
-
<
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}}
|
|
71
|
-
/>
|
|
72
|
-
</View>
|
|
108
|
+
<NativeBanner
|
|
109
|
+
style={[containerStyle, style]}
|
|
110
|
+
config={nativeConfig}
|
|
111
|
+
size={size}
|
|
112
|
+
zoneId={String(zoneId)}
|
|
113
|
+
onAdLoaded={() => {
|
|
114
|
+
// No-op event hook today; surfaced for future fill metrics.
|
|
115
|
+
}}
|
|
116
|
+
onAdImpression={() => onImpression?.()}
|
|
117
|
+
onAdClicked={() => onClick?.()}
|
|
118
|
+
onAdFailed={(e: NativeSyntheticEvent<{ message: string }>) => {
|
|
119
|
+
const msg = e.nativeEvent?.message ?? 'Ad failed'
|
|
120
|
+
onError?.(new Error(msg))
|
|
121
|
+
}}
|
|
122
|
+
/>
|
|
73
123
|
)
|
|
74
124
|
}
|
|
125
|
+
|
|
126
|
+
const styles = StyleSheet.create({
|
|
127
|
+
devPlaceholder: {
|
|
128
|
+
backgroundColor: '#FEE2E2',
|
|
129
|
+
borderWidth: 1,
|
|
130
|
+
borderColor: '#FCA5A5',
|
|
131
|
+
alignItems: 'center',
|
|
132
|
+
justifyContent: 'center',
|
|
133
|
+
padding: 4,
|
|
134
|
+
},
|
|
135
|
+
devText: {
|
|
136
|
+
color: '#991B1B',
|
|
137
|
+
fontSize: 11,
|
|
138
|
+
textAlign: 'center',
|
|
139
|
+
},
|
|
140
|
+
})
|
package/src/htmlBuilder.ts
CHANGED
|
@@ -183,7 +183,7 @@ function configToAttributes(config: SellwildConfig): string {
|
|
|
183
183
|
add('consent-management', config.consentManagement)
|
|
184
184
|
add('schain-sid', config.schainSid)
|
|
185
185
|
add('s2s-config', config.s2sConfig)
|
|
186
|
-
add('iab-cats', config.iabCats
|
|
186
|
+
add('iab-cats', Array.isArray(config.iabCats) ? config.iabCats.join(',') : config.iabCats)
|
|
187
187
|
|
|
188
188
|
// Third-party (typed fields with defaults — kept emitted explicitly for
|
|
189
189
|
// backwards compatibility with static buildConfig() callers)
|