novvy-ads-react-native 1.0.0-beta.1
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/LICENSE +21 -0
- package/README.md +210 -0
- package/android/build.gradle +84 -0
- package/android/gradle.properties +4 -0
- package/android/src/main/AndroidManifest.xml +4 -0
- package/android/src/main/java/ai/novvy/reactnative/NovvyAdContainerView.kt +63 -0
- package/android/src/main/java/ai/novvy/reactnative/NovvyAdsModule.kt +390 -0
- package/android/src/main/java/ai/novvy/reactnative/NovvyAdsPackage.kt +46 -0
- package/android/src/main/java/ai/novvy/reactnative/NovvyPauseAdViewManager.kt +68 -0
- package/android/src/main/java/ai/novvy/reactnative/NovvyScrollAdViewManager.kt +72 -0
- package/android/src/main/java/ai/novvy/reactnative/RnPlayerAdapter.kt +18 -0
- package/android/src/main/java/ai/novvy/reactnative/ViewReadyEvent.kt +26 -0
- package/app.plugin.js +4 -0
- package/ios/NovvyAds.mm +168 -0
- package/ios/NovvyAdsImpl.swift +409 -0
- package/ios/NovvyPauseAdView.mm +79 -0
- package/ios/NovvyScrollAdView.mm +80 -0
- package/ios/RnPlayerAdapter.swift +14 -0
- package/lib/commonjs/NovvyAds.js +87 -0
- package/lib/commonjs/NovvyAds.js.map +1 -0
- package/lib/commonjs/ads/NovvyAd.js +121 -0
- package/lib/commonjs/ads/NovvyAd.js.map +1 -0
- package/lib/commonjs/ads/NovvyEndAd.js +19 -0
- package/lib/commonjs/ads/NovvyEndAd.js.map +1 -0
- package/lib/commonjs/ads/NovvyFullScreenAd.js +49 -0
- package/lib/commonjs/ads/NovvyFullScreenAd.js.map +1 -0
- package/lib/commonjs/ads/NovvyInterstitialAd.js +19 -0
- package/lib/commonjs/ads/NovvyInterstitialAd.js.map +1 -0
- package/lib/commonjs/ads/NovvyMidAd.js +19 -0
- package/lib/commonjs/ads/NovvyMidAd.js.map +1 -0
- package/lib/commonjs/ads/NovvyPauseAd.js +116 -0
- package/lib/commonjs/ads/NovvyPauseAd.js.map +1 -0
- package/lib/commonjs/ads/NovvyRewardedAd.js +53 -0
- package/lib/commonjs/ads/NovvyRewardedAd.js.map +1 -0
- package/lib/commonjs/ads/NovvyScrollAd.js +136 -0
- package/lib/commonjs/ads/NovvyScrollAd.js.map +1 -0
- package/lib/commonjs/eventBus.js +60 -0
- package/lib/commonjs/eventBus.js.map +1 -0
- package/lib/commonjs/index.js +90 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/spec/NativeNovvyAds.js +27 -0
- package/lib/commonjs/spec/NativeNovvyAds.js.map +1 -0
- package/lib/commonjs/spec/NovvyPauseAdViewNativeComponent.js +16 -0
- package/lib/commonjs/spec/NovvyPauseAdViewNativeComponent.js.map +1 -0
- package/lib/commonjs/spec/NovvyScrollAdViewNativeComponent.js +17 -0
- package/lib/commonjs/spec/NovvyScrollAdViewNativeComponent.js.map +1 -0
- package/lib/commonjs/spec/codegen-event-emitter.d.js +2 -0
- package/lib/commonjs/spec/codegen-event-emitter.d.js.map +1 -0
- package/lib/commonjs/types.js +54 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/commonjs/views/NovvyPauseAdView.js +76 -0
- package/lib/commonjs/views/NovvyPauseAdView.js.map +1 -0
- package/lib/commonjs/views/NovvyScrollAdView.js +63 -0
- package/lib/commonjs/views/NovvyScrollAdView.js.map +1 -0
- package/lib/module/NovvyAds.js +83 -0
- package/lib/module/NovvyAds.js.map +1 -0
- package/lib/module/ads/NovvyAd.js +117 -0
- package/lib/module/ads/NovvyAd.js.map +1 -0
- package/lib/module/ads/NovvyEndAd.js +15 -0
- package/lib/module/ads/NovvyEndAd.js.map +1 -0
- package/lib/module/ads/NovvyFullScreenAd.js +45 -0
- package/lib/module/ads/NovvyFullScreenAd.js.map +1 -0
- package/lib/module/ads/NovvyInterstitialAd.js +15 -0
- package/lib/module/ads/NovvyInterstitialAd.js.map +1 -0
- package/lib/module/ads/NovvyMidAd.js +15 -0
- package/lib/module/ads/NovvyMidAd.js.map +1 -0
- package/lib/module/ads/NovvyPauseAd.js +112 -0
- package/lib/module/ads/NovvyPauseAd.js.map +1 -0
- package/lib/module/ads/NovvyRewardedAd.js +49 -0
- package/lib/module/ads/NovvyRewardedAd.js.map +1 -0
- package/lib/module/ads/NovvyScrollAd.js +132 -0
- package/lib/module/ads/NovvyScrollAd.js.map +1 -0
- package/lib/module/eventBus.js +55 -0
- package/lib/module/eventBus.js.map +1 -0
- package/lib/module/index.js +22 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/spec/NativeNovvyAds.js +28 -0
- package/lib/module/spec/NativeNovvyAds.js.map +1 -0
- package/lib/module/spec/NovvyPauseAdViewNativeComponent.js +13 -0
- package/lib/module/spec/NovvyPauseAdViewNativeComponent.js.map +1 -0
- package/lib/module/spec/NovvyScrollAdViewNativeComponent.js +14 -0
- package/lib/module/spec/NovvyScrollAdViewNativeComponent.js.map +1 -0
- package/lib/module/spec/codegen-event-emitter.d.js +2 -0
- package/lib/module/spec/codegen-event-emitter.d.js.map +1 -0
- package/lib/module/types.js +56 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/views/NovvyPauseAdView.js +70 -0
- package/lib/module/views/NovvyPauseAdView.js.map +1 -0
- package/lib/module/views/NovvyScrollAdView.js +57 -0
- package/lib/module/views/NovvyScrollAdView.js.map +1 -0
- package/lib/typescript/NovvyAds.d.ts +69 -0
- package/lib/typescript/NovvyAds.d.ts.map +1 -0
- package/lib/typescript/ads/NovvyAd.d.ts +57 -0
- package/lib/typescript/ads/NovvyAd.d.ts.map +1 -0
- package/lib/typescript/ads/NovvyEndAd.d.ts +7 -0
- package/lib/typescript/ads/NovvyEndAd.d.ts.map +1 -0
- package/lib/typescript/ads/NovvyFullScreenAd.d.ts +19 -0
- package/lib/typescript/ads/NovvyFullScreenAd.d.ts.map +1 -0
- package/lib/typescript/ads/NovvyInterstitialAd.d.ts +7 -0
- package/lib/typescript/ads/NovvyInterstitialAd.d.ts.map +1 -0
- package/lib/typescript/ads/NovvyMidAd.d.ts +7 -0
- package/lib/typescript/ads/NovvyMidAd.d.ts.map +1 -0
- package/lib/typescript/ads/NovvyPauseAd.d.ts +45 -0
- package/lib/typescript/ads/NovvyPauseAd.d.ts.map +1 -0
- package/lib/typescript/ads/NovvyRewardedAd.d.ts +19 -0
- package/lib/typescript/ads/NovvyRewardedAd.d.ts.map +1 -0
- package/lib/typescript/ads/NovvyScrollAd.d.ts +57 -0
- package/lib/typescript/ads/NovvyScrollAd.d.ts.map +1 -0
- package/lib/typescript/eventBus.d.ts +15 -0
- package/lib/typescript/eventBus.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +15 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/spec/NativeNovvyAds.d.ts +73 -0
- package/lib/typescript/spec/NativeNovvyAds.d.ts.map +1 -0
- package/lib/typescript/spec/NovvyPauseAdViewNativeComponent.d.ts +18 -0
- package/lib/typescript/spec/NovvyPauseAdViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/spec/NovvyScrollAdViewNativeComponent.d.ts +19 -0
- package/lib/typescript/spec/NovvyScrollAdViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/types.d.ts +77 -0
- package/lib/typescript/types.d.ts.map +1 -0
- package/lib/typescript/views/NovvyPauseAdView.d.ts +21 -0
- package/lib/typescript/views/NovvyPauseAdView.d.ts.map +1 -0
- package/lib/typescript/views/NovvyScrollAdView.d.ts +22 -0
- package/lib/typescript/views/NovvyScrollAdView.d.ts.map +1 -0
- package/novvy-ads-react-native.podspec +71 -0
- package/package.json +84 -0
- package/plugin/build/index.d.ts +11 -0
- package/plugin/build/index.js +53 -0
- package/react-native.config.js +7 -0
- package/src/NovvyAds.ts +98 -0
- package/src/ads/NovvyAd.ts +125 -0
- package/src/ads/NovvyEndAd.ts +13 -0
- package/src/ads/NovvyFullScreenAd.ts +46 -0
- package/src/ads/NovvyInterstitialAd.ts +13 -0
- package/src/ads/NovvyMidAd.ts +13 -0
- package/src/ads/NovvyPauseAd.ts +125 -0
- package/src/ads/NovvyRewardedAd.ts +49 -0
- package/src/ads/NovvyScrollAd.ts +138 -0
- package/src/eventBus.ts +59 -0
- package/src/index.tsx +29 -0
- package/src/spec/NativeNovvyAds.ts +134 -0
- package/src/spec/NovvyPauseAdViewNativeComponent.ts +20 -0
- package/src/spec/NovvyScrollAdViewNativeComponent.ts +21 -0
- package/src/spec/codegen-event-emitter.d.ts +10 -0
- package/src/types.ts +82 -0
- package/src/views/NovvyPauseAdView.tsx +80 -0
- package/src/views/NovvyScrollAdView.tsx +71 -0
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
package ai.novvy.reactnative
|
|
2
|
+
|
|
3
|
+
import android.app.Activity
|
|
4
|
+
import android.view.ViewGroup
|
|
5
|
+
import ai.novvy.android.sdk.*
|
|
6
|
+
import com.facebook.react.bridge.Arguments
|
|
7
|
+
import com.facebook.react.bridge.Promise
|
|
8
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
9
|
+
import com.facebook.react.bridge.ReadableArray
|
|
10
|
+
import com.facebook.react.bridge.ReadableMap
|
|
11
|
+
import com.facebook.react.bridge.UiThreadUtil
|
|
12
|
+
import com.facebook.react.bridge.WritableMap
|
|
13
|
+
import java.util.concurrent.ConcurrentHashMap
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* TurboModule bridging the Novvy Android ad SDK to React Native.
|
|
17
|
+
*
|
|
18
|
+
* Mirrors the Flutter plugin's `NovvyAdsApiImpl.kt` one-to-one:
|
|
19
|
+
* - SDK init + user/content context
|
|
20
|
+
* - Interstitial / Rewarded / Mid / End full-screen ads (load → show)
|
|
21
|
+
* - Scroll (inline feed) ads (load → attach → setPlaying → detach)
|
|
22
|
+
* - Pause (realtime pause card) ads (attach → detach, no load)
|
|
23
|
+
*
|
|
24
|
+
* A single `onAdEvent` emitter multiplexes every ad's lifecycle events to JS;
|
|
25
|
+
* each JS ad object filters by its own `adObjectId`.
|
|
26
|
+
*/
|
|
27
|
+
class NovvyAdsModule(reactContext: ReactApplicationContext) :
|
|
28
|
+
NativeNovvyAdsSpec(reactContext) {
|
|
29
|
+
|
|
30
|
+
private val appContext = reactContext.applicationContext
|
|
31
|
+
// Accessed from both the native-modules thread (load*) and the main thread
|
|
32
|
+
// (attach/show/dispose, marshaled via runOnMain) — must be concurrency-safe.
|
|
33
|
+
private val adMap = ConcurrentHashMap<String, Any>()
|
|
34
|
+
private val scrollContainerMap = ConcurrentHashMap<String, ViewGroup>()
|
|
35
|
+
private val pauseContainerMap = ConcurrentHashMap<String, ViewGroup>()
|
|
36
|
+
private val pauseAdapterMap = ConcurrentHashMap<String, RnPlayerAdapter>()
|
|
37
|
+
|
|
38
|
+
init {
|
|
39
|
+
instance = this
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
override fun invalidate() {
|
|
43
|
+
super.invalidate()
|
|
44
|
+
if (instance === this) {
|
|
45
|
+
instance = null
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// ── Event emission ──────────────────────────────────────────────────────
|
|
50
|
+
|
|
51
|
+
private fun runOnMain(block: () -> Unit) {
|
|
52
|
+
if (UiThreadUtil.isOnUiThread()) block() else UiThreadUtil.runOnUiThread(block)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private fun emit(
|
|
56
|
+
adObjectId: String,
|
|
57
|
+
adUnitId: String,
|
|
58
|
+
event: String,
|
|
59
|
+
error: String? = null,
|
|
60
|
+
remainingSeconds: Int? = null,
|
|
61
|
+
) {
|
|
62
|
+
val map: WritableMap = Arguments.createMap().apply {
|
|
63
|
+
putString("adObjectId", adObjectId)
|
|
64
|
+
putString("adUnitId", adUnitId)
|
|
65
|
+
putString("event", event)
|
|
66
|
+
if (error != null) putString("error", error)
|
|
67
|
+
if (remainingSeconds != null) putInt("remainingSeconds", remainingSeconds)
|
|
68
|
+
}
|
|
69
|
+
runOnMain { emitOnAdEvent(map) }
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
private fun errorText(error: NovvyError): String = when (error) {
|
|
73
|
+
is NovvyError.InternalError -> "InternalError: ${error.details}"
|
|
74
|
+
else -> error.message ?: error::class.simpleName ?: "UnknownError"
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// ── Initialization & context ──────────────────────────────────────────────
|
|
78
|
+
|
|
79
|
+
override fun initialize(
|
|
80
|
+
appId: String,
|
|
81
|
+
endpoint: String,
|
|
82
|
+
apiKey: String,
|
|
83
|
+
userContext: ReadableMap?,
|
|
84
|
+
promise: Promise,
|
|
85
|
+
) {
|
|
86
|
+
NovvySDK.initialize(
|
|
87
|
+
context = appContext,
|
|
88
|
+
appId = appId,
|
|
89
|
+
endpoint = endpoint,
|
|
90
|
+
apiKey = apiKey,
|
|
91
|
+
userContext = userContext?.toSdkUserContext(),
|
|
92
|
+
onComplete = { success -> runOnMain { promise.resolve(success) } },
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
override fun setUserContext(context: ReadableMap) {
|
|
97
|
+
NovvySDK.setUserContext(context.toSdkUserContext())
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
override fun updateUserContext(partial: ReadableMap) {
|
|
101
|
+
NovvySDK.updateUserContext(
|
|
102
|
+
userId = partial.optString("userId"),
|
|
103
|
+
hashedEmail = partial.optString("hashedEmail"),
|
|
104
|
+
isPaidUser = partial.optBoolean("isPaidUser"),
|
|
105
|
+
age = partial.optInt("age"),
|
|
106
|
+
gender = partial.optString("gender"),
|
|
107
|
+
dramaWatchHistory = partial.optArray("dramaWatchHistory")?.toSdkRecords(),
|
|
108
|
+
maximumAdsInOneDrama = partial.optInt("maximumAdsInOneDrama"),
|
|
109
|
+
)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
override fun setContentContext(context: ReadableMap) {
|
|
113
|
+
NovvySDK.setContentContext(
|
|
114
|
+
NovvyContentContext(
|
|
115
|
+
seriesName = context.optString("seriesName"),
|
|
116
|
+
episodeNumber = context.optInt("episodeNumber"),
|
|
117
|
+
url = context.optString("url"),
|
|
118
|
+
)
|
|
119
|
+
)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
override fun updateContentContext(partial: ReadableMap) {
|
|
123
|
+
NovvySDK.updateContentContext(
|
|
124
|
+
seriesName = partial.optString("seriesName"),
|
|
125
|
+
episodeNumber = partial.optInt("episodeNumber"),
|
|
126
|
+
url = partial.optString("url"),
|
|
127
|
+
)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private fun ReadableMap.toSdkUserContext(): NovvyUserContext = NovvyUserContext(
|
|
131
|
+
userId = optString("userId"),
|
|
132
|
+
hashedEmail = optString("hashedEmail"),
|
|
133
|
+
isPaidUser = optBoolean("isPaidUser"),
|
|
134
|
+
age = optInt("age"),
|
|
135
|
+
gender = optString("gender"),
|
|
136
|
+
dramaWatchHistory = optArray("dramaWatchHistory")?.toSdkRecords(),
|
|
137
|
+
maximumAdsInOneDrama = optInt("maximumAdsInOneDrama"),
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
private fun ReadableArray.toSdkRecords(): List<NovvyDramaRecord> {
|
|
141
|
+
val out = mutableListOf<NovvyDramaRecord>()
|
|
142
|
+
for (i in 0 until size()) {
|
|
143
|
+
val record = getMap(i) ?: continue
|
|
144
|
+
out.add(
|
|
145
|
+
NovvyDramaRecord(
|
|
146
|
+
seriesId = record.optString("seriesId") ?: "",
|
|
147
|
+
lastWatchedEpisode = record.optInt("lastWatchedEpisode") ?: 0,
|
|
148
|
+
unlockedEpisode = record.optInt("unlockedEpisode") ?: 0,
|
|
149
|
+
dramaTitle = record.optString("dramaTitle"),
|
|
150
|
+
)
|
|
151
|
+
)
|
|
152
|
+
}
|
|
153
|
+
return out
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// ── Interstitial ───────────────────────────────────────────────────────────
|
|
157
|
+
|
|
158
|
+
override fun loadInterstitialAd(adUnitId: String, adObjectId: String) {
|
|
159
|
+
val ad = NovvyInterstitialAd(adUnitId)
|
|
160
|
+
adMap[adObjectId] = ad
|
|
161
|
+
ad.load(object : NovvyInterstitialAdListener {
|
|
162
|
+
override fun onAdLoaded(ad: NovvyInterstitialAd) = emit(adObjectId, adUnitId, EV_LOADED)
|
|
163
|
+
override fun onAdFailedToLoad(ad: NovvyInterstitialAd, error: NovvyError) =
|
|
164
|
+
emit(adObjectId, adUnitId, EV_FAILED, errorText(error))
|
|
165
|
+
override fun onAdShown(ad: NovvyInterstitialAd) = emit(adObjectId, adUnitId, EV_SHOWED)
|
|
166
|
+
override fun onAdClosed(ad: NovvyInterstitialAd) = emit(adObjectId, adUnitId, EV_DISMISSED)
|
|
167
|
+
})
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
override fun showInterstitialAd(adObjectId: String) = runOnMain {
|
|
171
|
+
val ad = adMap[adObjectId] as? NovvyInterstitialAd ?: return@runOnMain
|
|
172
|
+
val activity = requireActivity(adObjectId) ?: return@runOnMain
|
|
173
|
+
ad.show(activity)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// ── Rewarded ─────────────────────────────────────────────────────────────
|
|
177
|
+
|
|
178
|
+
override fun loadRewardedAd(adUnitId: String, adObjectId: String) {
|
|
179
|
+
val ad = NovvyRewardedAd(adUnitId)
|
|
180
|
+
adMap[adObjectId] = ad
|
|
181
|
+
ad.load(object : NovvyRewardedAdListener {
|
|
182
|
+
override fun onAdLoaded(ad: NovvyRewardedAd) = emit(adObjectId, adUnitId, EV_LOADED)
|
|
183
|
+
override fun onAdFailedToLoad(ad: NovvyRewardedAd, error: NovvyError) =
|
|
184
|
+
emit(adObjectId, adUnitId, EV_FAILED, errorText(error))
|
|
185
|
+
override fun onAdShown(ad: NovvyRewardedAd) = emit(adObjectId, adUnitId, EV_SHOWED)
|
|
186
|
+
override fun onUserEarnedReward(ad: NovvyRewardedAd) =
|
|
187
|
+
emit(adObjectId, adUnitId, EV_EARNED_REWARD)
|
|
188
|
+
override fun onAdClosed(ad: NovvyRewardedAd) = emit(adObjectId, adUnitId, EV_DISMISSED)
|
|
189
|
+
})
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
override fun showRewardedAd(adObjectId: String) = runOnMain {
|
|
193
|
+
val ad = adMap[adObjectId] as? NovvyRewardedAd ?: return@runOnMain
|
|
194
|
+
val activity = requireActivity(adObjectId) ?: return@runOnMain
|
|
195
|
+
ad.show(activity)
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// ── Mid-roll ───────────────────────────────────────────────────────────────
|
|
199
|
+
|
|
200
|
+
override fun loadMidAd(adUnitId: String, adObjectId: String) {
|
|
201
|
+
val ad = NovvyMidAd(adUnitId)
|
|
202
|
+
adMap[adObjectId] = ad
|
|
203
|
+
ad.load(object : NovvyMidAdListener {
|
|
204
|
+
override fun onAdLoaded(ad: NovvyMidAd) = emit(adObjectId, adUnitId, EV_LOADED)
|
|
205
|
+
override fun onAdFailedToLoad(ad: NovvyMidAd, error: NovvyError) =
|
|
206
|
+
emit(adObjectId, adUnitId, EV_FAILED, errorText(error))
|
|
207
|
+
override fun onAdShown(ad: NovvyMidAd) = emit(adObjectId, adUnitId, EV_SHOWED)
|
|
208
|
+
override fun onAdClosed(ad: NovvyMidAd) = emit(adObjectId, adUnitId, EV_DISMISSED)
|
|
209
|
+
})
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
override fun showMidAd(adObjectId: String) = runOnMain {
|
|
213
|
+
val ad = adMap[adObjectId] as? NovvyMidAd ?: return@runOnMain
|
|
214
|
+
val activity = requireActivity(adObjectId) ?: return@runOnMain
|
|
215
|
+
ad.show(activity)
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// ── End-roll ─────────────────────────────────────────────────────────────
|
|
219
|
+
|
|
220
|
+
override fun loadEndAd(adUnitId: String, adObjectId: String) {
|
|
221
|
+
val ad = NovvyEndAd(adUnitId)
|
|
222
|
+
adMap[adObjectId] = ad
|
|
223
|
+
ad.load(object : NovvyEndAdListener {
|
|
224
|
+
override fun onAdLoaded(ad: NovvyEndAd) = emit(adObjectId, adUnitId, EV_LOADED)
|
|
225
|
+
override fun onAdFailedToLoad(ad: NovvyEndAd, error: NovvyError) =
|
|
226
|
+
emit(adObjectId, adUnitId, EV_FAILED, errorText(error))
|
|
227
|
+
override fun onAdShown(ad: NovvyEndAd) = emit(adObjectId, adUnitId, EV_SHOWED)
|
|
228
|
+
override fun onAdClosed(ad: NovvyEndAd) = emit(adObjectId, adUnitId, EV_DISMISSED)
|
|
229
|
+
})
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
override fun showEndAd(adObjectId: String) = runOnMain {
|
|
233
|
+
val ad = adMap[adObjectId] as? NovvyEndAd ?: return@runOnMain
|
|
234
|
+
val activity = requireActivity(adObjectId) ?: return@runOnMain
|
|
235
|
+
ad.show(activity)
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// ── Scroll (inline feed) ─────────────────────────────────────────────────
|
|
239
|
+
|
|
240
|
+
override fun loadScrollAd(adUnitId: String, adObjectId: String, episodeNumber: Double?) {
|
|
241
|
+
val ad = NovvyScrollAd(adUnitId = adUnitId, episode = episodeNumber?.toInt())
|
|
242
|
+
adMap[adObjectId] = ad
|
|
243
|
+
ad.load(object : NovvyScrollAdListener {
|
|
244
|
+
override fun onAdLoaded(ad: NovvyScrollAd) = emit(adObjectId, adUnitId, EV_LOADED)
|
|
245
|
+
override fun onAdFailedToLoad(ad: NovvyScrollAd, error: NovvyError) =
|
|
246
|
+
emit(adObjectId, adUnitId, EV_FAILED, errorText(error))
|
|
247
|
+
override fun onAdShown(ad: NovvyScrollAd) = emit(adObjectId, adUnitId, EV_SHOWED)
|
|
248
|
+
override fun onAdHidden(ad: NovvyScrollAd) = emit(adObjectId, adUnitId, EV_HIDDEN)
|
|
249
|
+
})
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
override fun attachScrollAd(
|
|
253
|
+
adObjectId: String,
|
|
254
|
+
durationSeconds: Double?,
|
|
255
|
+
useDefaultSwipeOverlay: Boolean,
|
|
256
|
+
) = runOnMain {
|
|
257
|
+
val ad = adMap[adObjectId] as? NovvyScrollAd ?: return@runOnMain
|
|
258
|
+
val container = scrollContainerMap[adObjectId] ?: return@runOnMain
|
|
259
|
+
ad.attach(
|
|
260
|
+
container = container,
|
|
261
|
+
durationSeconds = durationSeconds?.toInt(),
|
|
262
|
+
useDefaultSwipeOverlay = useDefaultSwipeOverlay,
|
|
263
|
+
onAdPlaybackTick = { remaining -> emit(adObjectId, "", EV_PLAYBACK_TICK, remainingSeconds = remaining) },
|
|
264
|
+
)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
override fun setScrollAdPlaying(adObjectId: String, playing: Boolean) = runOnMain {
|
|
268
|
+
(adMap[adObjectId] as? NovvyScrollAd)?.setPlaying(playing)
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
override fun detachScrollAd(adObjectId: String) = runOnMain {
|
|
272
|
+
(adMap[adObjectId] as? NovvyScrollAd)?.detach()
|
|
273
|
+
scrollContainerMap.remove(adObjectId)
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// ── Pause (realtime pause card) ─────────────────────────────────────────
|
|
277
|
+
|
|
278
|
+
override fun attachPauseAd(
|
|
279
|
+
adUnitId: String,
|
|
280
|
+
adObjectId: String,
|
|
281
|
+
positionMs: Double,
|
|
282
|
+
isPlaying: Boolean,
|
|
283
|
+
) = runOnMain {
|
|
284
|
+
val container = pauseContainerMap[adObjectId] ?: return@runOnMain
|
|
285
|
+
val adapter = RnPlayerAdapter().apply {
|
|
286
|
+
currentPositionMs = positionMs.toLong()
|
|
287
|
+
this.isPlaying = isPlaying
|
|
288
|
+
}
|
|
289
|
+
pauseAdapterMap[adObjectId] = adapter
|
|
290
|
+
val ad = NovvyPauseAd(adUnitId)
|
|
291
|
+
adMap[adObjectId] = ad
|
|
292
|
+
ad.attach(container, adapter, object : NovvyPauseAdListener {
|
|
293
|
+
override fun onAdFailedToLoad(ad: NovvyPauseAd, error: NovvyError) =
|
|
294
|
+
emit(adObjectId, adUnitId, EV_FAILED, errorText(error))
|
|
295
|
+
override fun onAdShown(ad: NovvyPauseAd) = emit(adObjectId, adUnitId, EV_SHOWED)
|
|
296
|
+
override fun onAdHidden(ad: NovvyPauseAd) = emit(adObjectId, adUnitId, EV_HIDDEN)
|
|
297
|
+
})
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
override fun updatePauseAdPlayerState(
|
|
301
|
+
adObjectId: String,
|
|
302
|
+
positionMs: Double,
|
|
303
|
+
isPlaying: Boolean,
|
|
304
|
+
) {
|
|
305
|
+
val adapter = pauseAdapterMap[adObjectId] ?: return
|
|
306
|
+
adapter.currentPositionMs = positionMs.toLong()
|
|
307
|
+
adapter.isPlaying = isPlaying
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
override fun detachPauseAd(adObjectId: String) = runOnMain {
|
|
311
|
+
(adMap[adObjectId] as? NovvyPauseAd)?.detach()
|
|
312
|
+
pauseContainerMap.remove(adObjectId)
|
|
313
|
+
pauseAdapterMap.remove(adObjectId)
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// ── Common ────────────────────────────────────────────────────────────────
|
|
317
|
+
|
|
318
|
+
override fun disposeAd(adObjectId: String) = runOnMain {
|
|
319
|
+
when (val ad = adMap[adObjectId]) {
|
|
320
|
+
is NovvyPauseAd -> {
|
|
321
|
+
ad.detach(); ad.destroy()
|
|
322
|
+
pauseContainerMap.remove(adObjectId)
|
|
323
|
+
pauseAdapterMap.remove(adObjectId)
|
|
324
|
+
}
|
|
325
|
+
is NovvyScrollAd -> {
|
|
326
|
+
ad.detach(); ad.destroy()
|
|
327
|
+
scrollContainerMap.remove(adObjectId)
|
|
328
|
+
}
|
|
329
|
+
is NovvyRewardedAd -> ad.destroy()
|
|
330
|
+
is NovvyInterstitialAd -> ad.destroy()
|
|
331
|
+
is NovvyMidAd -> ad.destroy()
|
|
332
|
+
is NovvyEndAd -> ad.destroy()
|
|
333
|
+
}
|
|
334
|
+
adMap.remove(adObjectId)
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// ── Platform view helpers (called by view managers) ───────────────────────
|
|
338
|
+
|
|
339
|
+
fun registerScrollContainer(adObjectId: String, container: ViewGroup) {
|
|
340
|
+
scrollContainerMap[adObjectId] = container
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
fun registerPauseContainer(adObjectId: String, container: ViewGroup) {
|
|
344
|
+
pauseContainerMap[adObjectId] = container
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
fun onScrollViewDisposed(adObjectId: String) = detachScrollAd(adObjectId)
|
|
348
|
+
fun onPauseViewDisposed(adObjectId: String) = detachPauseAd(adObjectId)
|
|
349
|
+
|
|
350
|
+
private fun requireActivity(adObjectId: String): Activity? {
|
|
351
|
+
val activity = currentActivity
|
|
352
|
+
if (activity == null) {
|
|
353
|
+
emit(adObjectId, "", EV_FAILED, "No active Activity available")
|
|
354
|
+
}
|
|
355
|
+
return activity
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
companion object {
|
|
359
|
+
const val NAME = NativeNovvyAdsSpec.NAME
|
|
360
|
+
|
|
361
|
+
/** The live module instance, used by the view managers to register containers. */
|
|
362
|
+
@Volatile
|
|
363
|
+
@JvmStatic
|
|
364
|
+
var instance: NovvyAdsModule? = null
|
|
365
|
+
private set
|
|
366
|
+
|
|
367
|
+
// Event names — must match the NovvyAdEvent string union in the TS layer.
|
|
368
|
+
private const val EV_LOADED = "loaded"
|
|
369
|
+
private const val EV_FAILED = "failedToLoad"
|
|
370
|
+
private const val EV_SHOWED = "showed"
|
|
371
|
+
private const val EV_DISMISSED = "dismissed"
|
|
372
|
+
private const val EV_HIDDEN = "hidden"
|
|
373
|
+
private const val EV_EARNED_REWARD = "earnedReward"
|
|
374
|
+
private const val EV_PLAYBACK_TICK = "playbackTick"
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// ── ReadableMap helpers ───────────────────────────────────────────────────────
|
|
379
|
+
|
|
380
|
+
private fun ReadableMap.optString(key: String): String? =
|
|
381
|
+
if (hasKey(key) && !isNull(key)) getString(key) else null
|
|
382
|
+
|
|
383
|
+
private fun ReadableMap.optBoolean(key: String): Boolean? =
|
|
384
|
+
if (hasKey(key) && !isNull(key)) getBoolean(key) else null
|
|
385
|
+
|
|
386
|
+
private fun ReadableMap.optInt(key: String): Int? =
|
|
387
|
+
if (hasKey(key) && !isNull(key)) getDouble(key).toInt() else null
|
|
388
|
+
|
|
389
|
+
private fun ReadableMap.optArray(key: String): ReadableArray? =
|
|
390
|
+
if (hasKey(key) && !isNull(key)) getArray(key) else null
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
package ai.novvy.reactnative
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.BaseReactPackage
|
|
4
|
+
import com.facebook.react.bridge.NativeModule
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.module.model.ReactModuleInfo
|
|
7
|
+
import com.facebook.react.module.model.ReactModuleInfoProvider
|
|
8
|
+
import com.facebook.react.uimanager.ViewManager
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* React Native package exposing the Novvy Ads TurboModule and the two inline
|
|
12
|
+
* ad view managers (scroll + pause). Mirrors the Flutter plugin's
|
|
13
|
+
* `NovvyAdsPlugin` registration.
|
|
14
|
+
*/
|
|
15
|
+
class NovvyAdsPackage : BaseReactPackage() {
|
|
16
|
+
|
|
17
|
+
override fun getModule(
|
|
18
|
+
name: String,
|
|
19
|
+
reactContext: ReactApplicationContext,
|
|
20
|
+
): NativeModule? = if (name == NovvyAdsModule.NAME) {
|
|
21
|
+
NovvyAdsModule(reactContext)
|
|
22
|
+
} else {
|
|
23
|
+
null
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
override fun getReactModuleInfoProvider(): ReactModuleInfoProvider =
|
|
27
|
+
ReactModuleInfoProvider {
|
|
28
|
+
mapOf(
|
|
29
|
+
NovvyAdsModule.NAME to ReactModuleInfo(
|
|
30
|
+
NovvyAdsModule.NAME,
|
|
31
|
+
NovvyAdsModule.NAME,
|
|
32
|
+
false, // canOverrideExistingModule
|
|
33
|
+
false, // needsEagerInit
|
|
34
|
+
false, // isCxxModule
|
|
35
|
+
true, // isTurboModule
|
|
36
|
+
),
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
override fun createViewManagers(
|
|
41
|
+
reactContext: ReactApplicationContext,
|
|
42
|
+
): List<ViewManager<*, *>> = listOf(
|
|
43
|
+
NovvyScrollAdViewManager(),
|
|
44
|
+
NovvyPauseAdViewManager(),
|
|
45
|
+
)
|
|
46
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
package ai.novvy.reactnative
|
|
2
|
+
|
|
3
|
+
import android.view.ViewGroup
|
|
4
|
+
import android.widget.FrameLayout
|
|
5
|
+
import com.facebook.react.module.annotations.ReactModule
|
|
6
|
+
import com.facebook.react.uimanager.SimpleViewManager
|
|
7
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
8
|
+
import com.facebook.react.uimanager.UIManagerHelper
|
|
9
|
+
import com.facebook.react.uimanager.ViewManagerDelegate
|
|
10
|
+
import com.facebook.react.viewmanagers.NovvyPauseAdViewManagerDelegate
|
|
11
|
+
import com.facebook.react.viewmanagers.NovvyPauseAdViewManagerInterface
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Fabric ViewManager for the inline realtime pause-card ad container.
|
|
15
|
+
*
|
|
16
|
+
* Registers a transparent [FrameLayout] with [NovvyAdsModule] keyed by
|
|
17
|
+
* `adObjectId`, then fires `onViewReady` so JS issues `attachPauseAd` (there is
|
|
18
|
+
* no load step for pause ads). Mirrors the Flutter plugin's `NovvyPauseViewFactory`.
|
|
19
|
+
*/
|
|
20
|
+
@ReactModule(name = NovvyPauseAdViewManager.NAME)
|
|
21
|
+
class NovvyPauseAdViewManager :
|
|
22
|
+
SimpleViewManager<FrameLayout>(),
|
|
23
|
+
NovvyPauseAdViewManagerInterface<FrameLayout> {
|
|
24
|
+
|
|
25
|
+
private val delegate = NovvyPauseAdViewManagerDelegate(this)
|
|
26
|
+
private val adObjectIds = HashMap<FrameLayout, String>()
|
|
27
|
+
|
|
28
|
+
override fun getName(): String = NAME
|
|
29
|
+
|
|
30
|
+
override fun getDelegate(): ViewManagerDelegate<FrameLayout> = delegate
|
|
31
|
+
|
|
32
|
+
override fun createViewInstance(context: ThemedReactContext): FrameLayout =
|
|
33
|
+
NovvyAdContainerView(context).apply {
|
|
34
|
+
layoutParams = ViewGroup.LayoutParams(
|
|
35
|
+
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
36
|
+
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
override fun setAdObjectId(view: FrameLayout, value: String?) {
|
|
41
|
+
if (value.isNullOrEmpty()) return
|
|
42
|
+
adObjectIds[view] = value
|
|
43
|
+
NovvyAdsModule.instance?.registerPauseContainer(value, view)
|
|
44
|
+
dispatchViewReady(view, value)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private fun dispatchViewReady(view: FrameLayout, adObjectId: String) {
|
|
48
|
+
val context = (view as? NovvyAdContainerView)?.reactContext ?: return
|
|
49
|
+
val dispatcher =
|
|
50
|
+
UIManagerHelper.getEventDispatcherForReactTag(context, view.id) ?: return
|
|
51
|
+
val surfaceId = UIManagerHelper.getSurfaceId(view)
|
|
52
|
+
dispatcher.dispatchEvent(ViewReadyEvent(surfaceId, view.id, adObjectId))
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
override fun onDropViewInstance(view: FrameLayout) {
|
|
56
|
+
super.onDropViewInstance(view)
|
|
57
|
+
adObjectIds.remove(view)?.let { NovvyAdsModule.instance?.onPauseViewDisposed(it) }
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> =
|
|
61
|
+
mutableMapOf(
|
|
62
|
+
ViewReadyEvent.EVENT_NAME to mapOf("registrationName" to "onViewReady"),
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
companion object {
|
|
66
|
+
const val NAME = "NovvyPauseAdView"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
package ai.novvy.reactnative
|
|
2
|
+
|
|
3
|
+
import android.graphics.Color
|
|
4
|
+
import android.view.ViewGroup
|
|
5
|
+
import android.widget.FrameLayout
|
|
6
|
+
import com.facebook.react.module.annotations.ReactModule
|
|
7
|
+
import com.facebook.react.uimanager.SimpleViewManager
|
|
8
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
9
|
+
import com.facebook.react.uimanager.UIManagerHelper
|
|
10
|
+
import com.facebook.react.uimanager.ViewManagerDelegate
|
|
11
|
+
import com.facebook.react.viewmanagers.NovvyScrollAdViewManagerDelegate
|
|
12
|
+
import com.facebook.react.viewmanagers.NovvyScrollAdViewManagerInterface
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Fabric ViewManager for the inline scroll (feed) ad container.
|
|
16
|
+
*
|
|
17
|
+
* Creates a black-backed [FrameLayout], registers it with [NovvyAdsModule]
|
|
18
|
+
* keyed by `adObjectId`, then fires `onViewReady` so JS issues `attachScrollAd`.
|
|
19
|
+
* Mirrors the Flutter plugin's `NovvyScrollViewFactory` / `NovvyScrollPlatformView`.
|
|
20
|
+
*/
|
|
21
|
+
@ReactModule(name = NovvyScrollAdViewManager.NAME)
|
|
22
|
+
class NovvyScrollAdViewManager :
|
|
23
|
+
SimpleViewManager<FrameLayout>(),
|
|
24
|
+
NovvyScrollAdViewManagerInterface<FrameLayout> {
|
|
25
|
+
|
|
26
|
+
private val delegate = NovvyScrollAdViewManagerDelegate(this)
|
|
27
|
+
private val adObjectIds = HashMap<FrameLayout, String>()
|
|
28
|
+
|
|
29
|
+
override fun getName(): String = NAME
|
|
30
|
+
|
|
31
|
+
override fun getDelegate(): ViewManagerDelegate<FrameLayout> = delegate
|
|
32
|
+
|
|
33
|
+
override fun createViewInstance(context: ThemedReactContext): FrameLayout =
|
|
34
|
+
NovvyAdContainerView(context).apply {
|
|
35
|
+
layoutParams = ViewGroup.LayoutParams(
|
|
36
|
+
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
37
|
+
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
38
|
+
)
|
|
39
|
+
// Opaque black backdrop: the ad view is transparent until the video
|
|
40
|
+
// decodes its first frame; black reads as a clean loading state.
|
|
41
|
+
setBackgroundColor(Color.BLACK)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
override fun setAdObjectId(view: FrameLayout, value: String?) {
|
|
45
|
+
if (value.isNullOrEmpty()) return
|
|
46
|
+
adObjectIds[view] = value
|
|
47
|
+
NovvyAdsModule.instance?.registerScrollContainer(value, view)
|
|
48
|
+
dispatchViewReady(view, value)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private fun dispatchViewReady(view: FrameLayout, adObjectId: String) {
|
|
52
|
+
val context = (view as? NovvyAdContainerView)?.reactContext ?: return
|
|
53
|
+
val dispatcher =
|
|
54
|
+
UIManagerHelper.getEventDispatcherForReactTag(context, view.id) ?: return
|
|
55
|
+
val surfaceId = UIManagerHelper.getSurfaceId(view)
|
|
56
|
+
dispatcher.dispatchEvent(ViewReadyEvent(surfaceId, view.id, adObjectId))
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
override fun onDropViewInstance(view: FrameLayout) {
|
|
60
|
+
super.onDropViewInstance(view)
|
|
61
|
+
adObjectIds.remove(view)?.let { NovvyAdsModule.instance?.onScrollViewDisposed(it) }
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> =
|
|
65
|
+
mutableMapOf(
|
|
66
|
+
ViewReadyEvent.EVENT_NAME to mapOf("registrationName" to "onViewReady"),
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
companion object {
|
|
70
|
+
const val NAME = "NovvyScrollAdView"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
package ai.novvy.reactnative
|
|
2
|
+
|
|
3
|
+
import ai.novvy.android.sdk.NovvyPlayerAdapter
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A [NovvyPlayerAdapter] whose state is pushed from JS via TurboModule calls.
|
|
7
|
+
*
|
|
8
|
+
* The SDK's PlaybackMonitor polls this adapter; JS pushes updated values at
|
|
9
|
+
* ~500ms cadence via `updatePauseAdPlayerState`. Mirrors the Flutter plugin's
|
|
10
|
+
* `FlutterPlayerAdapter`.
|
|
11
|
+
*/
|
|
12
|
+
internal class RnPlayerAdapter : NovvyPlayerAdapter {
|
|
13
|
+
@Volatile
|
|
14
|
+
override var currentPositionMs: Long = 0L
|
|
15
|
+
|
|
16
|
+
@Volatile
|
|
17
|
+
override var isPlaying: Boolean = false
|
|
18
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
package ai.novvy.reactnative
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Arguments
|
|
4
|
+
import com.facebook.react.bridge.WritableMap
|
|
5
|
+
import com.facebook.react.uimanager.events.Event
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Direct event fired once the native ad container is registered with
|
|
9
|
+
* [NovvyAdsModule], signalling JS to issue attach (mirrors the Flutter
|
|
10
|
+
* plugin's `onPlatformViewCreated`).
|
|
11
|
+
*/
|
|
12
|
+
internal class ViewReadyEvent(
|
|
13
|
+
surfaceId: Int,
|
|
14
|
+
viewTag: Int,
|
|
15
|
+
private val adObjectId: String,
|
|
16
|
+
) : Event<ViewReadyEvent>(surfaceId, viewTag) {
|
|
17
|
+
|
|
18
|
+
override fun getEventName(): String = EVENT_NAME
|
|
19
|
+
|
|
20
|
+
override fun getEventData(): WritableMap =
|
|
21
|
+
Arguments.createMap().apply { putString("adObjectId", adObjectId) }
|
|
22
|
+
|
|
23
|
+
companion object {
|
|
24
|
+
const val EVENT_NAME = "topViewReady"
|
|
25
|
+
}
|
|
26
|
+
}
|
package/app.plugin.js
ADDED