@ezoic/react-native-sdk 1.1.0 → 1.2.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/EzoicReactNativeSdk.podspec +1 -1
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/ezoic/reactnative/EzoicAdsModule.kt +144 -0
- package/ios/EzoicAdsImpl.swift +200 -44
- package/ios/EzoicReactNativeSdk.mm +18 -1
- package/lib/module/EzoicInterstitialAd.js +108 -0
- package/lib/module/EzoicInterstitialAd.js.map +1 -0
- package/lib/module/EzoicRewardedAd.js +4 -1
- package/lib/module/EzoicRewardedAd.js.map +1 -1
- package/lib/module/NativeEzoicAds.js.map +1 -1
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/EzoicInterstitialAd.d.ts +51 -0
- package/lib/typescript/src/EzoicInterstitialAd.d.ts.map +1 -0
- package/lib/typescript/src/EzoicRewardedAd.d.ts +1 -0
- package/lib/typescript/src/EzoicRewardedAd.d.ts.map +1 -1
- package/lib/typescript/src/NativeEzoicAds.d.ts +2 -0
- package/lib/typescript/src/NativeEzoicAds.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +1 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/EzoicInterstitialAd.ts +126 -0
- package/src/EzoicRewardedAd.ts +8 -2
- package/src/NativeEzoicAds.ts +3 -1
- package/src/index.tsx +4 -0
|
@@ -20,6 +20,6 @@ Pod::Spec.new do |s|
|
|
|
20
20
|
|
|
21
21
|
# Native Ezoic Ads SDK (vends the `EzoicAdsSDKBinary` module). Brings in
|
|
22
22
|
# PrebidMobile + Google-Mobile-Ads-SDK transitively.
|
|
23
|
-
s.dependency "EzoicAdsSDK", "~> 1.
|
|
23
|
+
s.dependency "EzoicAdsSDK", "~> 1.2"
|
|
24
24
|
s.swift_version = "5.9"
|
|
25
25
|
end
|
package/android/build.gradle
CHANGED
|
@@ -68,5 +68,5 @@ dependencies {
|
|
|
68
68
|
// Native Ezoic Ads SDK (resolved from Maven Central). Brings in Google Mobile
|
|
69
69
|
// Ads + Prebid transitively. Requires mavenCentral() + google() in the
|
|
70
70
|
// consuming app's repositories (the RN template provides both).
|
|
71
|
-
implementation "com.ezoic.sdk:ezoic-ads-sdk:1.
|
|
71
|
+
implementation "com.ezoic.sdk:ezoic-ads-sdk:1.2.0"
|
|
72
72
|
}
|
|
@@ -7,6 +7,9 @@ import com.facebook.react.bridge.ReactApplicationContext
|
|
|
7
7
|
import com.facebook.react.bridge.ReadableMap
|
|
8
8
|
import com.facebook.react.bridge.WritableMap
|
|
9
9
|
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
10
|
+
import com.ezoic.ads.sdk.adunits.EzoicInterstitialAd
|
|
11
|
+
import com.ezoic.ads.sdk.adunits.EzoicInterstitialAdListener
|
|
12
|
+
import com.ezoic.ads.sdk.adunits.EzoicInterstitialAdListenerAdapter
|
|
10
13
|
import com.ezoic.ads.sdk.adunits.EzoicReward
|
|
11
14
|
import com.ezoic.ads.sdk.adunits.EzoicRewardedAd
|
|
12
15
|
import com.ezoic.ads.sdk.adunits.EzoicRewardedAdListener
|
|
@@ -32,6 +35,22 @@ class EzoicAdsModule(reactContext: ReactApplicationContext) :
|
|
|
32
35
|
@Volatile var reward: EzoicReward? = null
|
|
33
36
|
}
|
|
34
37
|
|
|
38
|
+
/** Loaded interstitial ads awaiting `show`, keyed by ad unit id. */
|
|
39
|
+
private val interstitialAds = ConcurrentHashMap<Int, EzoicInterstitialAd>()
|
|
40
|
+
|
|
41
|
+
/** In-flight interstitial `show` calls, keyed by ad unit id. */
|
|
42
|
+
private val pendingInterstitialShows = ConcurrentHashMap<Int, InterstitialShow>()
|
|
43
|
+
|
|
44
|
+
private class InterstitialShow(val promise: Promise) {
|
|
45
|
+
@Volatile var settled = false
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Ad unit ids with an in-flight rewarded `load`. */
|
|
49
|
+
private val loadingRewarded = ConcurrentHashMap.newKeySet<Int>()
|
|
50
|
+
|
|
51
|
+
/** Ad unit ids with an in-flight interstitial `load`. */
|
|
52
|
+
private val loadingInterstitial = ConcurrentHashMap.newKeySet<Int>()
|
|
53
|
+
|
|
35
54
|
override fun initialize(config: ReadableMap, promise: Promise) {
|
|
36
55
|
val domain = if (config.hasKey("domain")) config.getString("domain") else null
|
|
37
56
|
if (domain.isNullOrEmpty()) {
|
|
@@ -79,7 +98,12 @@ class EzoicAdsModule(reactContext: ReactApplicationContext) :
|
|
|
79
98
|
promise.reject("EzoicAds", "Invalid adUnitIdentifier: $adUnitIdentifier")
|
|
80
99
|
return
|
|
81
100
|
}
|
|
101
|
+
if (rewardedAds.containsKey(id) || !loadingRewarded.add(id)) {
|
|
102
|
+
promise.reject("EzoicAds", "An ad is already loaded/loading for ad unit $adUnitIdentifier")
|
|
103
|
+
return
|
|
104
|
+
}
|
|
82
105
|
EzoicRewardedAd.load(reactApplicationContext, id) { result ->
|
|
106
|
+
loadingRewarded.remove(id)
|
|
83
107
|
result.onSuccess { ad ->
|
|
84
108
|
ad.listener = makeListener(adUnitIdentifier)
|
|
85
109
|
rewardedAds[id] = ad
|
|
@@ -97,6 +121,10 @@ class EzoicAdsModule(reactContext: ReactApplicationContext) :
|
|
|
97
121
|
promise.reject("EzoicAds", "Rewarded ad not loaded for $adUnitIdentifier")
|
|
98
122
|
return
|
|
99
123
|
}
|
|
124
|
+
if (pendingShows.containsKey(id)) {
|
|
125
|
+
promise.reject("EzoicAds", "A show is already in progress for ad unit $adUnitIdentifier")
|
|
126
|
+
return
|
|
127
|
+
}
|
|
100
128
|
val activity = currentActivity
|
|
101
129
|
if (activity == null) {
|
|
102
130
|
promise.reject("EzoicAds", "No current Activity to present the rewarded ad")
|
|
@@ -138,6 +166,75 @@ class EzoicAdsModule(reactContext: ReactApplicationContext) :
|
|
|
138
166
|
}
|
|
139
167
|
}
|
|
140
168
|
|
|
169
|
+
override fun loadInterstitialAd(adUnitIdentifier: String, promise: Promise) {
|
|
170
|
+
val id = adUnitIdentifier.toIntOrNull()
|
|
171
|
+
if (id == null) {
|
|
172
|
+
promise.reject("EzoicAds", "Invalid adUnitIdentifier: $adUnitIdentifier")
|
|
173
|
+
return
|
|
174
|
+
}
|
|
175
|
+
if (interstitialAds.containsKey(id) || !loadingInterstitial.add(id)) {
|
|
176
|
+
promise.reject("EzoicAds", "An ad is already loaded/loading for ad unit $adUnitIdentifier")
|
|
177
|
+
return
|
|
178
|
+
}
|
|
179
|
+
EzoicInterstitialAd.load(reactApplicationContext, id) { result ->
|
|
180
|
+
loadingInterstitial.remove(id)
|
|
181
|
+
result.onSuccess { ad ->
|
|
182
|
+
ad.listener = makeInterstitialListener(adUnitIdentifier)
|
|
183
|
+
interstitialAds[id] = ad
|
|
184
|
+
promise.resolve(null)
|
|
185
|
+
}.onFailure { e ->
|
|
186
|
+
promise.reject("EzoicAds", e.message ?: "Interstitial ad failed to load", e)
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
override fun showInterstitialAd(adUnitIdentifier: String, promise: Promise) {
|
|
192
|
+
val id = adUnitIdentifier.toIntOrNull()
|
|
193
|
+
val ad = if (id != null) interstitialAds[id] else null
|
|
194
|
+
if (id == null || ad == null) {
|
|
195
|
+
promise.reject("EzoicAds", "Interstitial ad not loaded for $adUnitIdentifier")
|
|
196
|
+
return
|
|
197
|
+
}
|
|
198
|
+
if (pendingInterstitialShows.containsKey(id)) {
|
|
199
|
+
promise.reject("EzoicAds", "A show is already in progress for ad unit $adUnitIdentifier")
|
|
200
|
+
return
|
|
201
|
+
}
|
|
202
|
+
val activity = currentActivity
|
|
203
|
+
if (activity == null) {
|
|
204
|
+
promise.reject("EzoicAds", "No current Activity to present the interstitial ad")
|
|
205
|
+
return
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
pendingInterstitialShows[id] = InterstitialShow(promise)
|
|
209
|
+
|
|
210
|
+
// Native show(activity) has no completion lambda, so replace the load-time
|
|
211
|
+
// listener with one that settles the promise on terminal events
|
|
212
|
+
// (dismiss = resolve, failed-to-show = reject).
|
|
213
|
+
ad.listener = makeInterstitialListener(
|
|
214
|
+
adUnitIdentifier,
|
|
215
|
+
onDismiss = {
|
|
216
|
+
interstitialAds.remove(id)
|
|
217
|
+
val pending = pendingInterstitialShows.remove(id)
|
|
218
|
+
if (pending != null && !pending.settled) {
|
|
219
|
+
pending.settled = true
|
|
220
|
+
pending.promise.resolve(null)
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
onFailedToShow = { message ->
|
|
224
|
+
interstitialAds.remove(id)
|
|
225
|
+
val pending = pendingInterstitialShows.remove(id)
|
|
226
|
+
if (pending != null && !pending.settled) {
|
|
227
|
+
pending.settled = true
|
|
228
|
+
pending.promise.reject("EzoicAds", message)
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
activity.runOnUiThread {
|
|
234
|
+
ad.show(activity)
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
141
238
|
override fun addListener(eventName: String) {
|
|
142
239
|
// No-op: required by the React Native NativeEventEmitter contract.
|
|
143
240
|
}
|
|
@@ -158,6 +255,7 @@ class EzoicAdsModule(reactContext: ReactApplicationContext) :
|
|
|
158
255
|
override fun onRewardedAdFailedToShow(rewardedAd: EzoicRewardedAd, error: EzoicError) {
|
|
159
256
|
emitRewardedEvent(adUnitIdentifier, "failedToShow") {
|
|
160
257
|
putString("message", error.message)
|
|
258
|
+
putInt("code", error.code)
|
|
161
259
|
}
|
|
162
260
|
onFailedToShow?.invoke(error.message)
|
|
163
261
|
}
|
|
@@ -197,11 +295,57 @@ class EzoicAdsModule(reactContext: ReactApplicationContext) :
|
|
|
197
295
|
.emit(REWARDED_EVENT, map)
|
|
198
296
|
}
|
|
199
297
|
|
|
298
|
+
private fun makeInterstitialListener(
|
|
299
|
+
adUnitIdentifier: String,
|
|
300
|
+
onDismiss: (() -> Unit)? = null,
|
|
301
|
+
onFailedToShow: ((String) -> Unit)? = null
|
|
302
|
+
): EzoicInterstitialAdListener = object : EzoicInterstitialAdListenerAdapter() {
|
|
303
|
+
override fun onInterstitialAdShown(interstitialAd: EzoicInterstitialAd) {
|
|
304
|
+
emitInterstitialEvent(adUnitIdentifier, "shown")
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
override fun onInterstitialAdFailedToShow(interstitialAd: EzoicInterstitialAd, error: EzoicError) {
|
|
308
|
+
emitInterstitialEvent(adUnitIdentifier, "failedToShow") {
|
|
309
|
+
putString("message", error.message)
|
|
310
|
+
putInt("code", error.code)
|
|
311
|
+
}
|
|
312
|
+
onFailedToShow?.invoke(error.message)
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
override fun onInterstitialAdImpression(interstitialAd: EzoicInterstitialAd) {
|
|
316
|
+
emitInterstitialEvent(adUnitIdentifier, "impression")
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
override fun onInterstitialAdClicked(interstitialAd: EzoicInterstitialAd) {
|
|
320
|
+
emitInterstitialEvent(adUnitIdentifier, "clicked")
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
override fun onInterstitialAdDismissed(interstitialAd: EzoicInterstitialAd) {
|
|
324
|
+
emitInterstitialEvent(adUnitIdentifier, "dismissed")
|
|
325
|
+
onDismiss?.invoke()
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
private fun emitInterstitialEvent(
|
|
330
|
+
adUnitIdentifier: String,
|
|
331
|
+
type: String,
|
|
332
|
+
extra: (WritableMap.() -> Unit)? = null
|
|
333
|
+
) {
|
|
334
|
+
val map = Arguments.createMap()
|
|
335
|
+
map.putString("adUnitIdentifier", adUnitIdentifier)
|
|
336
|
+
map.putString("type", type)
|
|
337
|
+
extra?.invoke(map)
|
|
338
|
+
reactApplicationContext
|
|
339
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
340
|
+
.emit(INTERSTITIAL_EVENT, map)
|
|
341
|
+
}
|
|
342
|
+
|
|
200
343
|
private fun ReadableMap.optBool(key: String, default: Boolean): Boolean =
|
|
201
344
|
if (hasKey(key) && !isNull(key)) getBoolean(key) else default
|
|
202
345
|
|
|
203
346
|
companion object {
|
|
204
347
|
const val NAME = NativeEzoicAdsSpec.NAME
|
|
205
348
|
private const val REWARDED_EVENT = "EzoicRewardedAdEvent"
|
|
349
|
+
private const val INTERSTITIAL_EVENT = "EzoicInterstitialAdEvent"
|
|
206
350
|
}
|
|
207
351
|
}
|
package/ios/EzoicAdsImpl.swift
CHANGED
|
@@ -22,65 +22,118 @@ import EzoicAdsSDKBinary
|
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
/// Loaded interstitial ads awaiting `show`, keyed by ad unit id.
|
|
26
|
+
private var interstitialAds: [Int: EzoicInterstitialAd] = [:]
|
|
27
|
+
|
|
28
|
+
/// In-flight interstitial `show` calls, keyed by ad unit id.
|
|
29
|
+
private var pendingInterstitialShows: [Int: PendingInterstitialShow] = [:]
|
|
30
|
+
|
|
31
|
+
private final class PendingInterstitialShow {
|
|
32
|
+
let resolve: (Any?) -> Void
|
|
33
|
+
let reject: (String, String, NSError?) -> Void
|
|
34
|
+
init(resolve: @escaping (Any?) -> Void, reject: @escaping (String, String, NSError?) -> Void) {
|
|
35
|
+
self.resolve = resolve
|
|
36
|
+
self.reject = reject
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/// Ad unit ids with an in-flight rewarded `load`.
|
|
41
|
+
private var loadingRewarded: Set<Int> = []
|
|
42
|
+
|
|
43
|
+
/// Ad unit ids with an in-flight interstitial `load`.
|
|
44
|
+
private var loadingInterstitial: Set<Int> = []
|
|
45
|
+
|
|
46
|
+
/// Runs `work` on the main thread. The ad/pending/loading dictionaries and
|
|
47
|
+
/// every native load/show call touch UIKit and this shared state, so they must
|
|
48
|
+
/// only run on main. Delegate callbacks already arrive on main.
|
|
49
|
+
private func onMain(_ work: @escaping () -> Void) {
|
|
50
|
+
if Thread.isMainThread {
|
|
51
|
+
work()
|
|
52
|
+
} else {
|
|
53
|
+
DispatchQueue.main.async(execute: work)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
25
57
|
@objc public func initialize(_ config: NSDictionary,
|
|
26
58
|
resolve: @escaping (Any?) -> Void,
|
|
27
59
|
reject: @escaping (String, String, NSError?) -> Void) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
60
|
+
onMain {
|
|
61
|
+
guard let domain = config["domain"] as? String, !domain.isEmpty else {
|
|
62
|
+
reject("EzoicAds", "initialize requires a non-empty `domain`.", nil)
|
|
63
|
+
return
|
|
64
|
+
}
|
|
65
|
+
let configuration = EzoicConfiguration(
|
|
66
|
+
domain: domain,
|
|
67
|
+
autoReadConsent: (config["autoReadConsent"] as? Bool) ?? true,
|
|
68
|
+
subjectToCOPPA: (config["subjectToCOPPA"] as? Bool) ?? false,
|
|
69
|
+
requestATTBeforeAds: (config["requestATTBeforeAds"] as? Bool) ?? true,
|
|
70
|
+
debugEnabled: (config["debugEnabled"] as? Bool) ?? false,
|
|
71
|
+
testMode: (config["testMode"] as? Bool) ?? false
|
|
72
|
+
)
|
|
73
|
+
EzoicAds.shared.initialize(with: configuration) { result in
|
|
74
|
+
switch result {
|
|
75
|
+
case .success:
|
|
76
|
+
resolve(nil)
|
|
77
|
+
case .failure(let error):
|
|
78
|
+
reject("EzoicAds", error.localizedDescription, error as NSError)
|
|
79
|
+
}
|
|
46
80
|
}
|
|
47
81
|
}
|
|
48
82
|
}
|
|
49
83
|
|
|
50
84
|
@objc public func setGDPRConsent(_ applies: Bool, consentString: String?) {
|
|
51
|
-
|
|
85
|
+
onMain {
|
|
86
|
+
EzoicAds.shared.setGDPRConsent(applies: applies, consentString: consentString)
|
|
87
|
+
}
|
|
52
88
|
}
|
|
53
89
|
|
|
54
90
|
@objc public func setGPPConsent(_ gppString: String?, sectionIds: String?) {
|
|
55
|
-
|
|
91
|
+
onMain {
|
|
92
|
+
EzoicAds.shared.setGPPConsent(gppString: gppString, sectionIds: sectionIds)
|
|
93
|
+
}
|
|
56
94
|
}
|
|
57
95
|
|
|
58
96
|
@objc public func setSubjectToCOPPA(_ value: Bool) {
|
|
59
|
-
|
|
97
|
+
onMain {
|
|
98
|
+
EzoicAds.shared.setSubjectToCOPPA(value)
|
|
99
|
+
}
|
|
60
100
|
}
|
|
61
101
|
|
|
62
102
|
@objc public func trackPageview(_ resolve: @escaping (Any?) -> Void) {
|
|
63
|
-
|
|
64
|
-
|
|
103
|
+
onMain {
|
|
104
|
+
EzoicAds.shared.trackPageview { success in
|
|
105
|
+
resolve(NSNumber(value: success))
|
|
106
|
+
}
|
|
65
107
|
}
|
|
66
108
|
}
|
|
67
109
|
|
|
68
110
|
@objc public func loadRewardedAd(_ adUnitIdentifier: String,
|
|
69
111
|
resolve: @escaping (Any?) -> Void,
|
|
70
112
|
reject: @escaping (String, String, NSError?) -> Void) {
|
|
71
|
-
|
|
72
|
-
reject("EzoicAds", "Invalid adUnitIdentifier: \(adUnitIdentifier)", nil)
|
|
73
|
-
return
|
|
74
|
-
}
|
|
75
|
-
EzoicRewardedAd.load(adUnitIdentifier: id) { [weak self] result in
|
|
113
|
+
onMain { [weak self] in
|
|
76
114
|
guard let self = self else { return }
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
115
|
+
guard let id = Int(adUnitIdentifier) else {
|
|
116
|
+
reject("EzoicAds", "Invalid adUnitIdentifier: \(adUnitIdentifier)", nil)
|
|
117
|
+
return
|
|
118
|
+
}
|
|
119
|
+
if self.rewardedAds[id] != nil || self.loadingRewarded.contains(id) {
|
|
120
|
+
reject("EzoicAds", "An ad is already loaded/loading for ad unit \(adUnitIdentifier)", nil)
|
|
121
|
+
return
|
|
122
|
+
}
|
|
123
|
+
self.loadingRewarded.insert(id)
|
|
124
|
+
EzoicRewardedAd.load(adUnitIdentifier: id) { [weak self] result in
|
|
125
|
+
guard let self = self else { return }
|
|
126
|
+
self.onMain {
|
|
127
|
+
self.loadingRewarded.remove(id)
|
|
128
|
+
switch result {
|
|
129
|
+
case .success(let ad):
|
|
130
|
+
ad.delegate = self
|
|
131
|
+
self.rewardedAds[id] = ad
|
|
132
|
+
resolve(nil)
|
|
133
|
+
case .failure(let error):
|
|
134
|
+
reject("EzoicAds", error.localizedDescription, error as NSError)
|
|
135
|
+
}
|
|
136
|
+
}
|
|
84
137
|
}
|
|
85
138
|
}
|
|
86
139
|
}
|
|
@@ -88,14 +141,21 @@ import EzoicAdsSDKBinary
|
|
|
88
141
|
@objc public func showRewardedAd(_ adUnitIdentifier: String,
|
|
89
142
|
resolve: @escaping (Any?) -> Void,
|
|
90
143
|
reject: @escaping (String, String, NSError?) -> Void) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
144
|
+
onMain { [weak self] in
|
|
145
|
+
guard let self = self else { return }
|
|
146
|
+
guard let id = Int(adUnitIdentifier), let ad = self.rewardedAds[id] else {
|
|
147
|
+
reject("EzoicAds", "Rewarded ad not loaded for \(adUnitIdentifier)", nil)
|
|
148
|
+
return
|
|
149
|
+
}
|
|
150
|
+
if self.pendingShows[id] != nil {
|
|
151
|
+
reject("EzoicAds", "A show is already in progress for ad unit \(adUnitIdentifier)", nil)
|
|
152
|
+
return
|
|
153
|
+
}
|
|
154
|
+
self.pendingShows[id] = PendingRewardShow(resolve: resolve, reject: reject)
|
|
155
|
+
// Presenting from nil lets GMA use the application's top view controller.
|
|
156
|
+
ad.show(from: nil) { [weak self] reward in
|
|
157
|
+
self?.onMain { self?.pendingShows[id]?.reward = reward }
|
|
158
|
+
}
|
|
99
159
|
}
|
|
100
160
|
}
|
|
101
161
|
|
|
@@ -107,6 +167,67 @@ import EzoicAdsSDKBinary
|
|
|
107
167
|
for (key, value) in extra { body[key] = value }
|
|
108
168
|
eventEmitter?("EzoicRewardedAdEvent", body)
|
|
109
169
|
}
|
|
170
|
+
|
|
171
|
+
@objc public func loadInterstitialAd(_ adUnitIdentifier: String,
|
|
172
|
+
resolve: @escaping (Any?) -> Void,
|
|
173
|
+
reject: @escaping (String, String, NSError?) -> Void) {
|
|
174
|
+
onMain { [weak self] in
|
|
175
|
+
guard let self = self else { return }
|
|
176
|
+
guard let id = Int(adUnitIdentifier) else {
|
|
177
|
+
reject("EzoicAds", "Invalid adUnitIdentifier: \(adUnitIdentifier)", nil)
|
|
178
|
+
return
|
|
179
|
+
}
|
|
180
|
+
if self.interstitialAds[id] != nil || self.loadingInterstitial.contains(id) {
|
|
181
|
+
reject("EzoicAds", "An ad is already loaded/loading for ad unit \(adUnitIdentifier)", nil)
|
|
182
|
+
return
|
|
183
|
+
}
|
|
184
|
+
self.loadingInterstitial.insert(id)
|
|
185
|
+
EzoicInterstitialAd.load(adUnitIdentifier: id) { [weak self] result in
|
|
186
|
+
guard let self = self else { return }
|
|
187
|
+
self.onMain {
|
|
188
|
+
self.loadingInterstitial.remove(id)
|
|
189
|
+
switch result {
|
|
190
|
+
case .success(let ad):
|
|
191
|
+
ad.delegate = self
|
|
192
|
+
self.interstitialAds[id] = ad
|
|
193
|
+
resolve(nil)
|
|
194
|
+
case .failure(let error):
|
|
195
|
+
reject("EzoicAds", error.localizedDescription, error as NSError)
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
@objc public func showInterstitialAd(_ adUnitIdentifier: String,
|
|
203
|
+
resolve: @escaping (Any?) -> Void,
|
|
204
|
+
reject: @escaping (String, String, NSError?) -> Void) {
|
|
205
|
+
onMain { [weak self] in
|
|
206
|
+
guard let self = self else { return }
|
|
207
|
+
guard let id = Int(adUnitIdentifier), let ad = self.interstitialAds[id] else {
|
|
208
|
+
reject("EzoicAds", "Interstitial ad not loaded for \(adUnitIdentifier)", nil)
|
|
209
|
+
return
|
|
210
|
+
}
|
|
211
|
+
if self.pendingInterstitialShows[id] != nil {
|
|
212
|
+
reject("EzoicAds", "A show is already in progress for ad unit \(adUnitIdentifier)", nil)
|
|
213
|
+
return
|
|
214
|
+
}
|
|
215
|
+
self.pendingInterstitialShows[id] = PendingInterstitialShow(resolve: resolve, reject: reject)
|
|
216
|
+
// Native show(from:) has no completion handler, so the show promise is
|
|
217
|
+
// settled from the delegate (dismiss = resolve, failed-to-present = reject).
|
|
218
|
+
// Presenting from nil lets GMA use the application's top view controller.
|
|
219
|
+
ad.show(from: nil)
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
private func emitInterstitial(_ ad: EzoicInterstitialAd, _ type: String, _ extra: [String: Any] = [:]) {
|
|
224
|
+
var body: [String: Any] = [
|
|
225
|
+
"adUnitIdentifier": String(ad.adUnitIdentifier),
|
|
226
|
+
"type": type
|
|
227
|
+
]
|
|
228
|
+
for (key, value) in extra { body[key] = value }
|
|
229
|
+
eventEmitter?("EzoicInterstitialAdEvent", body)
|
|
230
|
+
}
|
|
110
231
|
}
|
|
111
232
|
|
|
112
233
|
// MARK: - EzoicRewardedAdDelegate
|
|
@@ -118,7 +239,7 @@ extension EzoicAdsImpl: EzoicRewardedAdDelegate {
|
|
|
118
239
|
}
|
|
119
240
|
|
|
120
241
|
public func rewardedAd(_ rewardedAd: EzoicRewardedAd, didFailToPresentWithError error: EzoicError) {
|
|
121
|
-
emit(rewardedAd, "failedToShow", ["message": error.localizedDescription])
|
|
242
|
+
emit(rewardedAd, "failedToShow", ["message": error.localizedDescription, "code": error.code])
|
|
122
243
|
let id = rewardedAd.adUnitIdentifier
|
|
123
244
|
rewardedAds.removeValue(forKey: id)
|
|
124
245
|
if let pending = pendingShows.removeValue(forKey: id) {
|
|
@@ -154,3 +275,38 @@ extension EzoicAdsImpl: EzoicRewardedAdDelegate {
|
|
|
154
275
|
}
|
|
155
276
|
}
|
|
156
277
|
}
|
|
278
|
+
|
|
279
|
+
// MARK: - EzoicInterstitialAdDelegate
|
|
280
|
+
|
|
281
|
+
extension EzoicAdsImpl: EzoicInterstitialAdDelegate {
|
|
282
|
+
|
|
283
|
+
public func interstitialAdDidPresent(_ interstitialAd: EzoicInterstitialAd) {
|
|
284
|
+
emitInterstitial(interstitialAd, "shown")
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
public func interstitialAd(_ interstitialAd: EzoicInterstitialAd, didFailToPresentWithError error: EzoicError) {
|
|
288
|
+
emitInterstitial(interstitialAd, "failedToShow", ["message": error.localizedDescription, "code": error.code])
|
|
289
|
+
let id = interstitialAd.adUnitIdentifier
|
|
290
|
+
interstitialAds.removeValue(forKey: id)
|
|
291
|
+
if let pending = pendingInterstitialShows.removeValue(forKey: id) {
|
|
292
|
+
pending.reject("EzoicAds", error.localizedDescription, error as NSError)
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
public func interstitialAdDidRecordImpression(_ interstitialAd: EzoicInterstitialAd) {
|
|
297
|
+
emitInterstitial(interstitialAd, "impression")
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
public func interstitialAdDidRecordClick(_ interstitialAd: EzoicInterstitialAd) {
|
|
301
|
+
emitInterstitial(interstitialAd, "clicked")
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
public func interstitialAdDidDismiss(_ interstitialAd: EzoicInterstitialAd) {
|
|
305
|
+
emitInterstitial(interstitialAd, "dismissed")
|
|
306
|
+
let id = interstitialAd.adUnitIdentifier
|
|
307
|
+
interstitialAds.removeValue(forKey: id)
|
|
308
|
+
if let pending = pendingInterstitialShows.removeValue(forKey: id) {
|
|
309
|
+
pending.resolve(nil)
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
#import <EzoicReactNativeSdk/EzoicReactNativeSdk-Swift.h>
|
|
3
3
|
|
|
4
4
|
static NSString *const kEzoicRewardedEvent = @"EzoicRewardedAdEvent";
|
|
5
|
+
static NSString *const kEzoicInterstitialEvent = @"EzoicInterstitialAdEvent";
|
|
5
6
|
|
|
6
7
|
@implementation EzoicReactNativeSdk {
|
|
7
8
|
EzoicAdsImpl *_impl;
|
|
@@ -30,7 +31,7 @@ static NSString *const kEzoicRewardedEvent = @"EzoicRewardedAdEvent";
|
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
- (NSArray<NSString *> *)supportedEvents {
|
|
33
|
-
return @[ kEzoicRewardedEvent ];
|
|
34
|
+
return @[ kEzoicRewardedEvent, kEzoicInterstitialEvent ];
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
- (void)startObserving {
|
|
@@ -88,6 +89,22 @@ static NSString *const kEzoicRewardedEvent = @"EzoicRewardedAdEvent";
|
|
|
88
89
|
reject:^(NSString *code, NSString *msg, NSError *_Nullable e) { reject(code, msg, e); }];
|
|
89
90
|
}
|
|
90
91
|
|
|
92
|
+
- (void)loadInterstitialAd:(NSString *)adUnitIdentifier
|
|
93
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
94
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
95
|
+
[_impl loadInterstitialAd:adUnitIdentifier
|
|
96
|
+
resolve:^(id _Nullable v) { resolve(v); }
|
|
97
|
+
reject:^(NSString *code, NSString *msg, NSError *_Nullable e) { reject(code, msg, e); }];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
- (void)showInterstitialAd:(NSString *)adUnitIdentifier
|
|
101
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
102
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
103
|
+
[_impl showInterstitialAd:adUnitIdentifier
|
|
104
|
+
resolve:^(id _Nullable v) { resolve(v); }
|
|
105
|
+
reject:^(NSString *code, NSString *msg, NSError *_Nullable e) { reject(code, msg, e); }];
|
|
106
|
+
}
|
|
107
|
+
|
|
91
108
|
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
|
92
109
|
(const facebook::react::ObjCTurboModule::InitParams &)params {
|
|
93
110
|
return std::make_shared<facebook::react::NativeEzoicAdsSpecJSI>(params);
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { NativeEventEmitter } from 'react-native';
|
|
4
|
+
import NativeEzoicAds from "./NativeEzoicAds.js";
|
|
5
|
+
import { coerceAdUnitId } from "./helpers.js";
|
|
6
|
+
|
|
7
|
+
/** Lifecycle callbacks for an interstitial ad. All are optional. */
|
|
8
|
+
|
|
9
|
+
/** The single native event name carrying every interstitial lifecycle signal. */
|
|
10
|
+
const INTERSTITIAL_EVENT = 'EzoicInterstitialAdEvent';
|
|
11
|
+
// A single shared emitter is sufficient — events are routed to the right
|
|
12
|
+
// instance by adUnitIdentifier below.
|
|
13
|
+
const emitter = new NativeEventEmitter(NativeEzoicAds);
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* An interstitial ad. Use the static `load` to fetch an ad ahead of time, then
|
|
17
|
+
* call `show()` to present it full-screen at a natural transition point.
|
|
18
|
+
* Interstitials carry no reward.
|
|
19
|
+
*
|
|
20
|
+
* ```ts
|
|
21
|
+
* const ad = await EzoicInterstitialAd.load('12345');
|
|
22
|
+
* ad.setListeners({ onDismissed: () => console.log('closed') });
|
|
23
|
+
* await ad.show();
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* Mirrors the native `EzoicInterstitialAd` load/show lifecycle on both
|
|
27
|
+
* platforms. Interstitial ads are single-use — load a new one for the next
|
|
28
|
+
* opportunity.
|
|
29
|
+
*/
|
|
30
|
+
export class EzoicInterstitialAd {
|
|
31
|
+
/** The Ezoic ad unit identifier this ad was loaded for. */
|
|
32
|
+
|
|
33
|
+
listeners = {};
|
|
34
|
+
subscription = null;
|
|
35
|
+
constructor(adUnitIdentifier) {
|
|
36
|
+
this.adUnitIdentifier = adUnitIdentifier;
|
|
37
|
+
this.subscription = emitter.addListener(INTERSTITIAL_EVENT, raw => {
|
|
38
|
+
const event = raw;
|
|
39
|
+
if (event.adUnitIdentifier !== this.adUnitIdentifier) return;
|
|
40
|
+
this.handleEvent(event);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Loads an interstitial ad for the given Ezoic ad unit identifier. Resolves
|
|
46
|
+
* with a ready-to-show `EzoicInterstitialAd`, or rejects if no ad could be
|
|
47
|
+
* loaded.
|
|
48
|
+
*/
|
|
49
|
+
static async load(adUnitIdentifier) {
|
|
50
|
+
const id = coerceAdUnitId(adUnitIdentifier);
|
|
51
|
+
const ad = new EzoicInterstitialAd(id);
|
|
52
|
+
try {
|
|
53
|
+
await NativeEzoicAds.loadInterstitialAd(id);
|
|
54
|
+
return ad;
|
|
55
|
+
} catch (error) {
|
|
56
|
+
ad.destroy();
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Registers lifecycle callbacks. Replaces any previously set listeners. */
|
|
62
|
+
setListeners(listeners) {
|
|
63
|
+
this.listeners = listeners;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Presents the interstitial ad full-screen. Resolves when the ad is
|
|
68
|
+
* dismissed. Rejects if the ad was not ready (load first) or failed to
|
|
69
|
+
* present.
|
|
70
|
+
*/
|
|
71
|
+
async show() {
|
|
72
|
+
await NativeEzoicAds.showInterstitialAd(this.adUnitIdentifier);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Releases the event subscription. Safe to call multiple times. */
|
|
76
|
+
destroy() {
|
|
77
|
+
this.subscription?.remove();
|
|
78
|
+
this.subscription = null;
|
|
79
|
+
this.listeners = {};
|
|
80
|
+
}
|
|
81
|
+
handleEvent(event) {
|
|
82
|
+
switch (event.type) {
|
|
83
|
+
case 'shown':
|
|
84
|
+
this.listeners.onShown?.();
|
|
85
|
+
break;
|
|
86
|
+
case 'failedToShow':
|
|
87
|
+
this.listeners.onFailedToShow?.({
|
|
88
|
+
message: event.message ?? '',
|
|
89
|
+
code: event.code
|
|
90
|
+
});
|
|
91
|
+
// Failure to show is terminal — the native ad is single-use.
|
|
92
|
+
this.destroy();
|
|
93
|
+
break;
|
|
94
|
+
case 'impression':
|
|
95
|
+
this.listeners.onImpression?.();
|
|
96
|
+
break;
|
|
97
|
+
case 'clicked':
|
|
98
|
+
this.listeners.onClicked?.();
|
|
99
|
+
break;
|
|
100
|
+
case 'dismissed':
|
|
101
|
+
this.listeners.onDismissed?.();
|
|
102
|
+
// Dismissal is terminal — the native ad is single-use.
|
|
103
|
+
this.destroy();
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=EzoicInterstitialAd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["NativeEventEmitter","NativeEzoicAds","coerceAdUnitId","INTERSTITIAL_EVENT","emitter","EzoicInterstitialAd","listeners","subscription","constructor","adUnitIdentifier","addListener","raw","event","handleEvent","load","id","ad","loadInterstitialAd","error","destroy","setListeners","show","showInterstitialAd","remove","type","onShown","onFailedToShow","message","code","onImpression","onClicked","onDismissed"],"sourceRoot":"../../src","sources":["EzoicInterstitialAd.ts"],"mappings":";;AAAA,SAASA,kBAAkB,QAAkC,cAAc;AAC3E,OAAOC,cAAc,MAAM,qBAAkB;AAC7C,SAASC,cAAc,QAAQ,cAAW;;AAE1C;;AASA;AACA,MAAMC,kBAAkB,GAAG,0BAA0B;AASrD;AACA;AACA,MAAMC,OAAO,GAAG,IAAIJ,kBAAkB,CAACC,cAAuB,CAAC;;AAE/D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMI,mBAAmB,CAAC;EAC/B;;EAGQC,SAAS,GAAiC,CAAC,CAAC;EAC5CC,YAAY,GAA+B,IAAI;EAE/CC,WAAWA,CAACC,gBAAwB,EAAE;IAC5C,IAAI,CAACA,gBAAgB,GAAGA,gBAAgB;IACxC,IAAI,CAACF,YAAY,GAAGH,OAAO,CAACM,WAAW,CACrCP,kBAAkB,EACjBQ,GAAY,IAAK;MAChB,MAAMC,KAAK,GAAGD,GAA8B;MAC5C,IAAIC,KAAK,CAACH,gBAAgB,KAAK,IAAI,CAACA,gBAAgB,EAAE;MACtD,IAAI,CAACI,WAAW,CAACD,KAAK,CAAC;IACzB,CACF,CAAC;EACH;;EAEA;AACF;AACA;AACA;AACA;EACE,aAAaE,IAAIA,CAACL,gBAAwB,EAAgC;IACxE,MAAMM,EAAE,GAAGb,cAAc,CAACO,gBAAgB,CAAC;IAC3C,MAAMO,EAAE,GAAG,IAAIX,mBAAmB,CAACU,EAAE,CAAC;IACtC,IAAI;MACF,MAAMd,cAAc,CAACgB,kBAAkB,CAACF,EAAE,CAAC;MAC3C,OAAOC,EAAE;IACX,CAAC,CAAC,OAAOE,KAAK,EAAE;MACdF,EAAE,CAACG,OAAO,CAAC,CAAC;MACZ,MAAMD,KAAK;IACb;EACF;;EAEA;EACAE,YAAYA,CAACd,SAAuC,EAAQ;IAC1D,IAAI,CAACA,SAAS,GAAGA,SAAS;EAC5B;;EAEA;AACF;AACA;AACA;AACA;EACE,MAAMe,IAAIA,CAAA,EAAkB;IAC1B,MAAMpB,cAAc,CAACqB,kBAAkB,CAAC,IAAI,CAACb,gBAAgB,CAAC;EAChE;;EAEA;EACAU,OAAOA,CAAA,EAAS;IACd,IAAI,CAACZ,YAAY,EAAEgB,MAAM,CAAC,CAAC;IAC3B,IAAI,CAAChB,YAAY,GAAG,IAAI;IACxB,IAAI,CAACD,SAAS,GAAG,CAAC,CAAC;EACrB;EAEQO,WAAWA,CAACD,KAA8B,EAAQ;IACxD,QAAQA,KAAK,CAACY,IAAI;MAChB,KAAK,OAAO;QACV,IAAI,CAAClB,SAAS,CAACmB,OAAO,GAAG,CAAC;QAC1B;MACF,KAAK,cAAc;QACjB,IAAI,CAACnB,SAAS,CAACoB,cAAc,GAAG;UAC9BC,OAAO,EAAEf,KAAK,CAACe,OAAO,IAAI,EAAE;UAC5BC,IAAI,EAAEhB,KAAK,CAACgB;QACd,CAAC,CAAC;QACF;QACA,IAAI,CAACT,OAAO,CAAC,CAAC;QACd;MACF,KAAK,YAAY;QACf,IAAI,CAACb,SAAS,CAACuB,YAAY,GAAG,CAAC;QAC/B;MACF,KAAK,SAAS;QACZ,IAAI,CAACvB,SAAS,CAACwB,SAAS,GAAG,CAAC;QAC5B;MACF,KAAK,WAAW;QACd,IAAI,CAACxB,SAAS,CAACyB,WAAW,GAAG,CAAC;QAC9B;QACA,IAAI,CAACZ,OAAO,CAAC,CAAC;QACd;IACJ;EACF;AACF","ignoreList":[]}
|
|
@@ -86,8 +86,11 @@ export class EzoicRewardedAd {
|
|
|
86
86
|
break;
|
|
87
87
|
case 'failedToShow':
|
|
88
88
|
this.listeners.onFailedToShow?.({
|
|
89
|
-
message: event.message ?? ''
|
|
89
|
+
message: event.message ?? '',
|
|
90
|
+
code: event.code
|
|
90
91
|
});
|
|
92
|
+
// Failure to show is terminal — the native ad is single-use.
|
|
93
|
+
this.destroy();
|
|
91
94
|
break;
|
|
92
95
|
case 'impression':
|
|
93
96
|
this.listeners.onImpression?.();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NativeEventEmitter","NativeEzoicAds","coerceAdUnitId","mapRewardResult","REWARDED_EVENT","emitter","EzoicRewardedAd","listeners","subscription","constructor","adUnitIdentifier","addListener","raw","event","handleEvent","load","id","ad","loadRewardedAd","error","destroy","setListeners","show","result","showRewardedAd","remove","type","onShown","onFailedToShow","message","onImpression","onClicked","onUserEarnedReward","rewardType","amount","rewardAmount","onDismissed"],"sourceRoot":"../../src","sources":["EzoicRewardedAd.ts"],"mappings":";;AAAA,SAASA,kBAAkB,QAAkC,cAAc;AAC3E,OAAOC,cAAc,MAAM,qBAAkB;AAC7C,SAASC,cAAc,EAAEC,eAAe,QAAQ,cAAW;;AAE3D;;AAMA;;AAUA;AACA,MAAMC,cAAc,GAAG,sBAAsB;
|
|
1
|
+
{"version":3,"names":["NativeEventEmitter","NativeEzoicAds","coerceAdUnitId","mapRewardResult","REWARDED_EVENT","emitter","EzoicRewardedAd","listeners","subscription","constructor","adUnitIdentifier","addListener","raw","event","handleEvent","load","id","ad","loadRewardedAd","error","destroy","setListeners","show","result","showRewardedAd","remove","type","onShown","onFailedToShow","message","code","onImpression","onClicked","onUserEarnedReward","rewardType","amount","rewardAmount","onDismissed"],"sourceRoot":"../../src","sources":["EzoicRewardedAd.ts"],"mappings":";;AAAA,SAASA,kBAAkB,QAAkC,cAAc;AAC3E,OAAOC,cAAc,MAAM,qBAAkB;AAC7C,SAASC,cAAc,EAAEC,eAAe,QAAQ,cAAW;;AAE3D;;AAMA;;AAUA;AACA,MAAMC,cAAc,GAAG,sBAAsB;AAiB7C;AACA;AACA,MAAMC,OAAO,GAAG,IAAIL,kBAAkB,CAACC,cAAuB,CAAC;;AAE/D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMK,eAAe,CAAC;EAC3B;;EAGQC,SAAS,GAA6B,CAAC,CAAC;EACxCC,YAAY,GAA+B,IAAI;EAE/CC,WAAWA,CAACC,gBAAwB,EAAE;IAC5C,IAAI,CAACA,gBAAgB,GAAGA,gBAAgB;IACxC,IAAI,CAACF,YAAY,GAAGH,OAAO,CAACM,WAAW,CAACP,cAAc,EAAGQ,GAAY,IAAK;MACxE,MAAMC,KAAK,GAAGD,GAA0B;MACxC,IAAIC,KAAK,CAACH,gBAAgB,KAAK,IAAI,CAACA,gBAAgB,EAAE;MACtD,IAAI,CAACI,WAAW,CAACD,KAAK,CAAC;IACzB,CAAC,CAAC;EACJ;;EAEA;AACF;AACA;AACA;EACE,aAAaE,IAAIA,CAACL,gBAAwB,EAA4B;IACpE,MAAMM,EAAE,GAAGd,cAAc,CAACQ,gBAAgB,CAAC;IAC3C,MAAMO,EAAE,GAAG,IAAIX,eAAe,CAACU,EAAE,CAAC;IAClC,IAAI;MACF,MAAMf,cAAc,CAACiB,cAAc,CAACF,EAAE,CAAC;MACvC,OAAOC,EAAE;IACX,CAAC,CAAC,OAAOE,KAAK,EAAE;MACdF,EAAE,CAACG,OAAO,CAAC,CAAC;MACZ,MAAMD,KAAK;IACb;EACF;;EAEA;EACAE,YAAYA,CAACd,SAAmC,EAAQ;IACtD,IAAI,CAACA,SAAS,GAAGA,SAAS;EAC5B;;EAEA;AACF;AACA;AACA;AACA;EACE,MAAMe,IAAIA,CAAA,EAAgC;IACxC,MAAMC,MAAM,GAAG,MAAMtB,cAAc,CAACuB,cAAc,CAAC,IAAI,CAACd,gBAAgB,CAAC;IACzE,OAAOP,eAAe,CAACoB,MAAM,CAAC;EAChC;;EAEA;EACAH,OAAOA,CAAA,EAAS;IACd,IAAI,CAACZ,YAAY,EAAEiB,MAAM,CAAC,CAAC;IAC3B,IAAI,CAACjB,YAAY,GAAG,IAAI;IACxB,IAAI,CAACD,SAAS,GAAG,CAAC,CAAC;EACrB;EAEQO,WAAWA,CAACD,KAA0B,EAAQ;IACpD,QAAQA,KAAK,CAACa,IAAI;MAChB,KAAK,OAAO;QACV,IAAI,CAACnB,SAAS,CAACoB,OAAO,GAAG,CAAC;QAC1B;MACF,KAAK,cAAc;QACjB,IAAI,CAACpB,SAAS,CAACqB,cAAc,GAAG;UAC9BC,OAAO,EAAEhB,KAAK,CAACgB,OAAO,IAAI,EAAE;UAC5BC,IAAI,EAAEjB,KAAK,CAACiB;QACd,CAAC,CAAC;QACF;QACA,IAAI,CAACV,OAAO,CAAC,CAAC;QACd;MACF,KAAK,YAAY;QACf,IAAI,CAACb,SAAS,CAACwB,YAAY,GAAG,CAAC;QAC/B;MACF,KAAK,SAAS;QACZ,IAAI,CAACxB,SAAS,CAACyB,SAAS,GAAG,CAAC;QAC5B;MACF,KAAK,QAAQ;QACX,IAAI,CAACzB,SAAS,CAAC0B,kBAAkB,GAAG;UAClCP,IAAI,EAAEb,KAAK,CAACqB,UAAU,IAAI,EAAE;UAC5BC,MAAM,EAAEtB,KAAK,CAACuB,YAAY,IAAI;QAChC,CAAC,CAAC;QACF;MACF,KAAK,WAAW;QACd,IAAI,CAAC7B,SAAS,CAAC8B,WAAW,GAAG,CAAC;QAC9B;QACA,IAAI,CAACjB,OAAO,CAAC,CAAC;QACd;IACJ;EACF;AACF","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeEzoicAds.ts"],"mappings":";;AACA,SAASA,mBAAmB,QAAQ,cAAc;;AAWlD;AACA;AACA;AACA;AACA;AACA;;
|
|
1
|
+
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeEzoicAds.ts"],"mappings":";;AACA,SAASA,mBAAmB,QAAQ,cAAc;;AAWlD;AACA;AACA;AACA;AACA;AACA;;AAsBA,eAAeA,mBAAmB,CAACC,YAAY,CAAO,qBAAqB,CAAC","ignoreList":[]}
|
package/lib/module/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import EzoicBannerNative from './EzoicBannerViewNativeComponent';
|
|
|
5
5
|
import { coerceAdUnitId, normalizeConfig, normalizeSize } from "./helpers.js";
|
|
6
6
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
7
7
|
export { EzoicRewardedAd } from "./EzoicRewardedAd.js";
|
|
8
|
+
export { EzoicInterstitialAd } from "./EzoicInterstitialAd.js";
|
|
8
9
|
export const EzoicAds = {
|
|
9
10
|
initialize(config) {
|
|
10
11
|
return NativeEzoicAds.initialize(normalizeConfig(config));
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NativeEzoicAds","EzoicBannerNative","coerceAdUnitId","normalizeConfig","normalizeSize","jsx","_jsx","EzoicRewardedAd","EzoicAds","initialize","config","setGDPRConsent","applies","consentString","setGPPConsent","gppString","sectionIds","setSubjectToCOPPA","value","trackPageview","EzoicBannerView","props","adUnitIdentifier","size","onLoad","onError","onImpression","onClick","onOpen","onClose","rest","undefined","e","nativeEvent","onAdClick"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AACA,OAAOA,cAAc,MAA4B,qBAAkB;AACnE,OAAOC,iBAAiB,MAAM,kCAAkC;AAChE,SAASC,cAAc,EAAEC,eAAe,EAAEC,aAAa,QAAQ,cAAW;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAG3E,SACEC,eAAe,QAGV,sBAAmB;
|
|
1
|
+
{"version":3,"names":["NativeEzoicAds","EzoicBannerNative","coerceAdUnitId","normalizeConfig","normalizeSize","jsx","_jsx","EzoicRewardedAd","EzoicInterstitialAd","EzoicAds","initialize","config","setGDPRConsent","applies","consentString","setGPPConsent","gppString","sectionIds","setSubjectToCOPPA","value","trackPageview","EzoicBannerView","props","adUnitIdentifier","size","onLoad","onError","onImpression","onClick","onOpen","onClose","rest","undefined","e","nativeEvent","onAdClick"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AACA,OAAOA,cAAc,MAA4B,qBAAkB;AACnE,OAAOC,iBAAiB,MAAM,kCAAkC;AAChE,SAASC,cAAc,EAAEC,eAAe,EAAEC,aAAa,QAAQ,cAAW;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAG3E,SACEC,eAAe,QAGV,sBAAmB;AAC1B,SACEC,mBAAmB,QAEd,0BAAuB;AAE9B,OAAO,MAAMC,QAAQ,GAAG;EACtBC,UAAUA,CAACC,MAAmB,EAAiB;IAC7C,OAAOX,cAAc,CAACU,UAAU,CAACP,eAAe,CAACQ,MAAM,CAAC,CAAC;EAC3D,CAAC;EACDC,cAAcA,CAACC,OAAgB,EAAEC,aAAsB,EAAQ;IAC7Dd,cAAc,CAACY,cAAc,CAACC,OAAO,EAAEC,aAAa,CAAC;EACvD,CAAC;EACDC,aAAaA,CAACC,SAAkB,EAAEC,UAAmB,EAAQ;IAC3DjB,cAAc,CAACe,aAAa,CAACC,SAAS,EAAEC,UAAU,CAAC;EACrD,CAAC;EACDC,iBAAiBA,CAACC,KAAc,EAAQ;IACtCnB,cAAc,CAACkB,iBAAiB,CAACC,KAAK,CAAC;EACzC,CAAC;EACDC,aAAaA,CAAA,EAAqB;IAChC,OAAOpB,cAAc,CAACoB,aAAa,CAAC,CAAC;EACvC;AACF,CAAC;AAmBD,OAAO,SAASC,eAAeA,CAACC,KAA2B,EAAE;EAC3D,MAAM;IACJC,gBAAgB;IAChBC,IAAI;IACJC,MAAM;IACNC,OAAO;IACPC,YAAY;IACZC,OAAO;IACPC,MAAM;IACNC,OAAO;IACP,GAAGC;EACL,CAAC,GAAGT,KAAK;EACT,oBACEhB,IAAA,CAACL,iBAAiB;IAAA,GACZ8B,IAAI;IACRR,gBAAgB,EAAErB,cAAc,CAACqB,gBAAgB,CAAE;IACnDC,IAAI,EAAEpB,aAAa,CAACoB,IAAI,CAAE;IAC1BC,MAAM,EAAEA,MAAM,GAAG,MAAMA,MAAM,CAAC,CAAC,GAAGO,SAAU;IAC5CN,OAAO,EAAEA,OAAO,GAAIO,CAAC,IAAKP,OAAO,CAACO,CAAC,CAACC,WAAW,CAAC,GAAGF,SAAU;IAC7DL,YAAY,EAAEA,YAAY,GAAG,MAAMA,YAAY,CAAC,CAAC,GAAGK,SAAU;IAC9DG,SAAS,EAAEP,OAAO,GAAG,MAAMA,OAAO,CAAC,CAAC,GAAGI,SAAU;IACjDH,MAAM,EAAEA,MAAM,GAAG,MAAMA,MAAM,CAAC,CAAC,GAAGG,SAAU;IAC5CF,OAAO,EAAEA,OAAO,GAAG,MAAMA,OAAO,CAAC,CAAC,GAAGE;EAAU,CAChD,CAAC;AAEN","ignoreList":[]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/** Lifecycle callbacks for an interstitial ad. All are optional. */
|
|
2
|
+
export interface EzoicInterstitialAdListeners {
|
|
3
|
+
onShown?: () => void;
|
|
4
|
+
onFailedToShow?: (error: {
|
|
5
|
+
message: string;
|
|
6
|
+
code?: number;
|
|
7
|
+
}) => void;
|
|
8
|
+
onImpression?: () => void;
|
|
9
|
+
onClicked?: () => void;
|
|
10
|
+
onDismissed?: () => void;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* An interstitial ad. Use the static `load` to fetch an ad ahead of time, then
|
|
14
|
+
* call `show()` to present it full-screen at a natural transition point.
|
|
15
|
+
* Interstitials carry no reward.
|
|
16
|
+
*
|
|
17
|
+
* ```ts
|
|
18
|
+
* const ad = await EzoicInterstitialAd.load('12345');
|
|
19
|
+
* ad.setListeners({ onDismissed: () => console.log('closed') });
|
|
20
|
+
* await ad.show();
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* Mirrors the native `EzoicInterstitialAd` load/show lifecycle on both
|
|
24
|
+
* platforms. Interstitial ads are single-use — load a new one for the next
|
|
25
|
+
* opportunity.
|
|
26
|
+
*/
|
|
27
|
+
export declare class EzoicInterstitialAd {
|
|
28
|
+
/** The Ezoic ad unit identifier this ad was loaded for. */
|
|
29
|
+
readonly adUnitIdentifier: string;
|
|
30
|
+
private listeners;
|
|
31
|
+
private subscription;
|
|
32
|
+
private constructor();
|
|
33
|
+
/**
|
|
34
|
+
* Loads an interstitial ad for the given Ezoic ad unit identifier. Resolves
|
|
35
|
+
* with a ready-to-show `EzoicInterstitialAd`, or rejects if no ad could be
|
|
36
|
+
* loaded.
|
|
37
|
+
*/
|
|
38
|
+
static load(adUnitIdentifier: string): Promise<EzoicInterstitialAd>;
|
|
39
|
+
/** Registers lifecycle callbacks. Replaces any previously set listeners. */
|
|
40
|
+
setListeners(listeners: EzoicInterstitialAdListeners): void;
|
|
41
|
+
/**
|
|
42
|
+
* Presents the interstitial ad full-screen. Resolves when the ad is
|
|
43
|
+
* dismissed. Rejects if the ad was not ready (load first) or failed to
|
|
44
|
+
* present.
|
|
45
|
+
*/
|
|
46
|
+
show(): Promise<void>;
|
|
47
|
+
/** Releases the event subscription. Safe to call multiple times. */
|
|
48
|
+
destroy(): void;
|
|
49
|
+
private handleEvent;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=EzoicInterstitialAd.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EzoicInterstitialAd.d.ts","sourceRoot":"","sources":["../../../src/EzoicInterstitialAd.ts"],"names":[],"mappings":"AAIA,oEAAoE;AACpE,MAAM,WAAW,4BAA4B;IAC3C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACrE,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAC1B;AAgBD;;;;;;;;;;;;;;GAcG;AACH,qBAAa,mBAAmB;IAC9B,2DAA2D;IAC3D,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAElC,OAAO,CAAC,SAAS,CAAoC;IACrD,OAAO,CAAC,YAAY,CAAoC;IAExD,OAAO;IAYP;;;;OAIG;WACU,IAAI,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAYzE,4EAA4E;IAC5E,YAAY,CAAC,SAAS,EAAE,4BAA4B,GAAG,IAAI;IAI3D;;;;OAIG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,oEAAoE;IACpE,OAAO,IAAI,IAAI;IAMf,OAAO,CAAC,WAAW;CA0BpB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EzoicRewardedAd.d.ts","sourceRoot":"","sources":["../../../src/EzoicRewardedAd.ts"],"names":[],"mappings":"AAIA,gEAAgE;AAChE,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,+DAA+D;AAC/D,MAAM,WAAW,wBAAwB;IACvC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"EzoicRewardedAd.d.ts","sourceRoot":"","sources":["../../../src/EzoicRewardedAd.ts"],"names":[],"mappings":"AAIA,gEAAgE;AAChE,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,+DAA+D;AAC/D,MAAM,WAAW,wBAAwB;IACvC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACrE,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,kBAAkB,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,CAAC;CACpD;AAwBD;;;;;;;;;;;;;GAaG;AACH,qBAAa,eAAe;IAC1B,2DAA2D;IAC3D,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAElC,OAAO,CAAC,SAAS,CAAgC;IACjD,OAAO,CAAC,YAAY,CAAoC;IAExD,OAAO;IASP;;;OAGG;WACU,IAAI,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAYrE,4EAA4E;IAC5E,YAAY,CAAC,SAAS,EAAE,wBAAwB,GAAG,IAAI;IAIvD;;;;OAIG;IACG,IAAI,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAKzC,oEAAoE;IACpE,OAAO,IAAI,IAAI;IAMf,OAAO,CAAC,WAAW;CAgCpB"}
|
|
@@ -26,6 +26,8 @@ export interface Spec extends TurboModule {
|
|
|
26
26
|
trackPageview(): Promise<boolean>;
|
|
27
27
|
loadRewardedAd(adUnitIdentifier: string): Promise<void>;
|
|
28
28
|
showRewardedAd(adUnitIdentifier: string): Promise<EzoicRewardResult>;
|
|
29
|
+
loadInterstitialAd(adUnitIdentifier: string): Promise<void>;
|
|
30
|
+
showInterstitialAd(adUnitIdentifier: string): Promise<void>;
|
|
29
31
|
addListener(eventName: string): void;
|
|
30
32
|
removeListeners(count: number): void;
|
|
31
33
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NativeEzoicAds.d.ts","sourceRoot":"","sources":["../../../src/NativeEzoicAds.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/D,aAAa,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7D,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IACxC,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAClC,cAAc,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,cAAc,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"NativeEzoicAds.d.ts","sourceRoot":"","sources":["../../../src/NativeEzoicAds.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,UAAU,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/D,aAAa,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7D,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IACxC,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAClC,cAAc,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,cAAc,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACrE,kBAAkB,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,kBAAkB,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5D,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;;AAED,wBAA6E"}
|
|
@@ -2,6 +2,7 @@ import type { StyleProp, ViewStyle } from 'react-native';
|
|
|
2
2
|
import { type EzoicConfig } from './NativeEzoicAds.js';
|
|
3
3
|
export type { EzoicConfig };
|
|
4
4
|
export { EzoicRewardedAd, type EzoicReward, type EzoicRewardedAdListeners, } from './EzoicRewardedAd.js';
|
|
5
|
+
export { EzoicInterstitialAd, type EzoicInterstitialAdListeners, } from './EzoicInterstitialAd.js';
|
|
5
6
|
export declare const EzoicAds: {
|
|
6
7
|
initialize(config: EzoicConfig): Promise<void>;
|
|
7
8
|
setGDPRConsent(applies: boolean, consentString?: string): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzD,OAAuB,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAkB,CAAC;AAIpE,YAAY,EAAE,WAAW,EAAE,CAAC;AAC5B,OAAO,EACL,eAAe,EACf,KAAK,WAAW,EAChB,KAAK,wBAAwB,GAC9B,MAAM,sBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzD,OAAuB,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAkB,CAAC;AAIpE,YAAY,EAAE,WAAW,EAAE,CAAC;AAC5B,OAAO,EACL,eAAe,EACf,KAAK,WAAW,EAChB,KAAK,wBAAwB,GAC9B,MAAM,sBAAmB,CAAC;AAC3B,OAAO,EACL,mBAAmB,EACnB,KAAK,4BAA4B,GAClC,MAAM,0BAAuB,CAAC;AAE/B,eAAO,MAAM,QAAQ;uBACA,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;4BAGtB,OAAO,kBAAkB,MAAM,GAAG,IAAI;8BAGpC,MAAM,eAAe,MAAM,GAAG,IAAI;6BAGnC,OAAO,GAAG,IAAI;qBAGtB,OAAO,CAAC,OAAO,CAAC;CAGlC,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,oBAAoB;IACnC,gBAAgB,EAAE,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC5C,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,+BAyB1D"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ezoic/react-native-sdk",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Ezoic Ads SDK for React Native (Prebid + Google Ad Manager banner and rewarded ads).",
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "Ezoic Ads SDK for React Native (Prebid + Google Ad Manager banner, interstitial and rewarded ads).",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|
|
7
7
|
"exports": {
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { NativeEventEmitter, type EmitterSubscription } from 'react-native';
|
|
2
|
+
import NativeEzoicAds from './NativeEzoicAds';
|
|
3
|
+
import { coerceAdUnitId } from './helpers';
|
|
4
|
+
|
|
5
|
+
/** Lifecycle callbacks for an interstitial ad. All are optional. */
|
|
6
|
+
export interface EzoicInterstitialAdListeners {
|
|
7
|
+
onShown?: () => void;
|
|
8
|
+
onFailedToShow?: (error: { message: string; code?: number }) => void;
|
|
9
|
+
onImpression?: () => void;
|
|
10
|
+
onClicked?: () => void;
|
|
11
|
+
onDismissed?: () => void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** The single native event name carrying every interstitial lifecycle signal. */
|
|
15
|
+
const INTERSTITIAL_EVENT = 'EzoicInterstitialAdEvent';
|
|
16
|
+
|
|
17
|
+
interface InterstitialNativeEvent {
|
|
18
|
+
adUnitIdentifier: string;
|
|
19
|
+
type: 'shown' | 'failedToShow' | 'impression' | 'clicked' | 'dismissed';
|
|
20
|
+
message?: string;
|
|
21
|
+
code?: number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// A single shared emitter is sufficient — events are routed to the right
|
|
25
|
+
// instance by adUnitIdentifier below.
|
|
26
|
+
const emitter = new NativeEventEmitter(NativeEzoicAds as never);
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* An interstitial ad. Use the static `load` to fetch an ad ahead of time, then
|
|
30
|
+
* call `show()` to present it full-screen at a natural transition point.
|
|
31
|
+
* Interstitials carry no reward.
|
|
32
|
+
*
|
|
33
|
+
* ```ts
|
|
34
|
+
* const ad = await EzoicInterstitialAd.load('12345');
|
|
35
|
+
* ad.setListeners({ onDismissed: () => console.log('closed') });
|
|
36
|
+
* await ad.show();
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* Mirrors the native `EzoicInterstitialAd` load/show lifecycle on both
|
|
40
|
+
* platforms. Interstitial ads are single-use — load a new one for the next
|
|
41
|
+
* opportunity.
|
|
42
|
+
*/
|
|
43
|
+
export class EzoicInterstitialAd {
|
|
44
|
+
/** The Ezoic ad unit identifier this ad was loaded for. */
|
|
45
|
+
readonly adUnitIdentifier: string;
|
|
46
|
+
|
|
47
|
+
private listeners: EzoicInterstitialAdListeners = {};
|
|
48
|
+
private subscription: EmitterSubscription | null = null;
|
|
49
|
+
|
|
50
|
+
private constructor(adUnitIdentifier: string) {
|
|
51
|
+
this.adUnitIdentifier = adUnitIdentifier;
|
|
52
|
+
this.subscription = emitter.addListener(
|
|
53
|
+
INTERSTITIAL_EVENT,
|
|
54
|
+
(raw: unknown) => {
|
|
55
|
+
const event = raw as InterstitialNativeEvent;
|
|
56
|
+
if (event.adUnitIdentifier !== this.adUnitIdentifier) return;
|
|
57
|
+
this.handleEvent(event);
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Loads an interstitial ad for the given Ezoic ad unit identifier. Resolves
|
|
64
|
+
* with a ready-to-show `EzoicInterstitialAd`, or rejects if no ad could be
|
|
65
|
+
* loaded.
|
|
66
|
+
*/
|
|
67
|
+
static async load(adUnitIdentifier: string): Promise<EzoicInterstitialAd> {
|
|
68
|
+
const id = coerceAdUnitId(adUnitIdentifier);
|
|
69
|
+
const ad = new EzoicInterstitialAd(id);
|
|
70
|
+
try {
|
|
71
|
+
await NativeEzoicAds.loadInterstitialAd(id);
|
|
72
|
+
return ad;
|
|
73
|
+
} catch (error) {
|
|
74
|
+
ad.destroy();
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Registers lifecycle callbacks. Replaces any previously set listeners. */
|
|
80
|
+
setListeners(listeners: EzoicInterstitialAdListeners): void {
|
|
81
|
+
this.listeners = listeners;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Presents the interstitial ad full-screen. Resolves when the ad is
|
|
86
|
+
* dismissed. Rejects if the ad was not ready (load first) or failed to
|
|
87
|
+
* present.
|
|
88
|
+
*/
|
|
89
|
+
async show(): Promise<void> {
|
|
90
|
+
await NativeEzoicAds.showInterstitialAd(this.adUnitIdentifier);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Releases the event subscription. Safe to call multiple times. */
|
|
94
|
+
destroy(): void {
|
|
95
|
+
this.subscription?.remove();
|
|
96
|
+
this.subscription = null;
|
|
97
|
+
this.listeners = {};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
private handleEvent(event: InterstitialNativeEvent): void {
|
|
101
|
+
switch (event.type) {
|
|
102
|
+
case 'shown':
|
|
103
|
+
this.listeners.onShown?.();
|
|
104
|
+
break;
|
|
105
|
+
case 'failedToShow':
|
|
106
|
+
this.listeners.onFailedToShow?.({
|
|
107
|
+
message: event.message ?? '',
|
|
108
|
+
code: event.code,
|
|
109
|
+
});
|
|
110
|
+
// Failure to show is terminal — the native ad is single-use.
|
|
111
|
+
this.destroy();
|
|
112
|
+
break;
|
|
113
|
+
case 'impression':
|
|
114
|
+
this.listeners.onImpression?.();
|
|
115
|
+
break;
|
|
116
|
+
case 'clicked':
|
|
117
|
+
this.listeners.onClicked?.();
|
|
118
|
+
break;
|
|
119
|
+
case 'dismissed':
|
|
120
|
+
this.listeners.onDismissed?.();
|
|
121
|
+
// Dismissal is terminal — the native ad is single-use.
|
|
122
|
+
this.destroy();
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
package/src/EzoicRewardedAd.ts
CHANGED
|
@@ -11,7 +11,7 @@ export interface EzoicReward {
|
|
|
11
11
|
/** Lifecycle callbacks for a rewarded ad. All are optional. */
|
|
12
12
|
export interface EzoicRewardedAdListeners {
|
|
13
13
|
onShown?: () => void;
|
|
14
|
-
onFailedToShow?: (error: { message: string }) => void;
|
|
14
|
+
onFailedToShow?: (error: { message: string; code?: number }) => void;
|
|
15
15
|
onImpression?: () => void;
|
|
16
16
|
onClicked?: () => void;
|
|
17
17
|
onDismissed?: () => void;
|
|
@@ -31,6 +31,7 @@ interface RewardedNativeEvent {
|
|
|
31
31
|
| 'dismissed'
|
|
32
32
|
| 'reward';
|
|
33
33
|
message?: string;
|
|
34
|
+
code?: number;
|
|
34
35
|
rewardType?: string;
|
|
35
36
|
rewardAmount?: number;
|
|
36
37
|
}
|
|
@@ -113,7 +114,12 @@ export class EzoicRewardedAd {
|
|
|
113
114
|
this.listeners.onShown?.();
|
|
114
115
|
break;
|
|
115
116
|
case 'failedToShow':
|
|
116
|
-
this.listeners.onFailedToShow?.({
|
|
117
|
+
this.listeners.onFailedToShow?.({
|
|
118
|
+
message: event.message ?? '',
|
|
119
|
+
code: event.code,
|
|
120
|
+
});
|
|
121
|
+
// Failure to show is terminal — the native ad is single-use.
|
|
122
|
+
this.destroy();
|
|
117
123
|
break;
|
|
118
124
|
case 'impression':
|
|
119
125
|
this.listeners.onImpression?.();
|
package/src/NativeEzoicAds.ts
CHANGED
|
@@ -30,7 +30,9 @@ export interface Spec extends TurboModule {
|
|
|
30
30
|
trackPageview(): Promise<boolean>;
|
|
31
31
|
loadRewardedAd(adUnitIdentifier: string): Promise<void>;
|
|
32
32
|
showRewardedAd(adUnitIdentifier: string): Promise<EzoicRewardResult>;
|
|
33
|
-
|
|
33
|
+
loadInterstitialAd(adUnitIdentifier: string): Promise<void>;
|
|
34
|
+
showInterstitialAd(adUnitIdentifier: string): Promise<void>;
|
|
35
|
+
// Required by NativeEventEmitter for the ad lifecycle events.
|
|
34
36
|
addListener(eventName: string): void;
|
|
35
37
|
removeListeners(count: number): void;
|
|
36
38
|
}
|
package/src/index.tsx
CHANGED
|
@@ -9,6 +9,10 @@ export {
|
|
|
9
9
|
type EzoicReward,
|
|
10
10
|
type EzoicRewardedAdListeners,
|
|
11
11
|
} from './EzoicRewardedAd';
|
|
12
|
+
export {
|
|
13
|
+
EzoicInterstitialAd,
|
|
14
|
+
type EzoicInterstitialAdListeners,
|
|
15
|
+
} from './EzoicInterstitialAd';
|
|
12
16
|
|
|
13
17
|
export const EzoicAds = {
|
|
14
18
|
initialize(config: EzoicConfig): Promise<void> {
|