react-native-theoplayer 8.4.0 → 8.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/android/build.gradle +15 -4
  3. package/android/src/main/java/com/theoplayer/ReactTHEOplayerContext.kt +14 -0
  4. package/android/src/main/java/com/theoplayer/ads/AdEventAdapter.kt +2 -2
  5. package/android/src/main/java/com/theoplayer/presentation/PresentationManager.kt +22 -8
  6. package/android/src/main/java/com/theoplayer/presentation/PresentationModeChangeContext.kt +4 -1
  7. package/android/src/main/java/com/theoplayer/source/SourceAdapter.kt +48 -0
  8. package/android/src/main/java/com/theoplayer/util/PayloadBuilder.kt +1 -0
  9. package/ios/ads/THEOplayerRCTAdsEventHandler.swift +77 -36
  10. package/ios/presentationMode/THEOplayerRCTPresentationModeManager.swift +46 -25
  11. package/ios/presentationMode/THEOplayerRCTView+PresentationMode.swift +1 -1
  12. package/lib/commonjs/api/event/PlayerEvent.js +1 -0
  13. package/lib/commonjs/api/event/PlayerEvent.js.map +1 -1
  14. package/lib/commonjs/api/source/SourceDescription.js.map +1 -1
  15. package/lib/commonjs/api/version/SdkVersions.js +2 -0
  16. package/lib/commonjs/api/version/SdkVersions.js.map +1 -0
  17. package/lib/commonjs/internal/adapter/THEOplayerWebAdapter.js +5 -1
  18. package/lib/commonjs/internal/adapter/THEOplayerWebAdapter.js.map +1 -1
  19. package/lib/module/api/event/PlayerEvent.js +1 -0
  20. package/lib/module/api/event/PlayerEvent.js.map +1 -1
  21. package/lib/module/api/source/SourceDescription.js.map +1 -1
  22. package/lib/module/api/version/SdkVersions.js +2 -0
  23. package/lib/module/api/version/SdkVersions.js.map +1 -0
  24. package/lib/module/internal/adapter/THEOplayerWebAdapter.js +5 -1
  25. package/lib/module/internal/adapter/THEOplayerWebAdapter.js.map +1 -1
  26. package/lib/typescript/api/ads/AdsConfiguration.d.ts +13 -0
  27. package/lib/typescript/api/ads/AdsConfiguration.d.ts.map +1 -1
  28. package/lib/typescript/api/event/AdEvent.d.ts +2 -2
  29. package/lib/typescript/api/event/PlayerEvent.d.ts +8 -1
  30. package/lib/typescript/api/event/PlayerEvent.d.ts.map +1 -1
  31. package/lib/typescript/api/source/SourceDescription.d.ts +6 -0
  32. package/lib/typescript/api/source/SourceDescription.d.ts.map +1 -1
  33. package/lib/typescript/api/version/SdkVersions.d.ts +15 -0
  34. package/lib/typescript/api/version/SdkVersions.d.ts.map +1 -0
  35. package/lib/typescript/internal/adapter/THEOplayerWebAdapter.d.ts.map +1 -1
  36. package/package.json +15 -15
  37. package/react-native-theoplayer.podspec +6 -6
  38. package/src/api/ads/AdsConfiguration.ts +14 -0
  39. package/src/api/event/AdEvent.ts +2 -2
  40. package/src/api/event/PlayerEvent.ts +8 -0
  41. package/src/api/source/SourceDescription.ts +7 -0
  42. package/src/api/version/SdkVersions.ts +15 -0
  43. package/src/internal/adapter/THEOplayerWebAdapter.ts +5 -1
package/CHANGELOG.md CHANGED
@@ -5,11 +5,39 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.1.0/)
6
6
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [8.6.0] - 24-10-25
9
+
10
+ ### Added
11
+
12
+ - Added `AdEvent.AD_CLICKED` and `AdEvent.AD_TAPPED` ad events for iOS and Android. The events are dispatched when a user taps or clicks on an ad that has a `clickThrough` link.
13
+
14
+ ### Changed
15
+
16
+ - Upgrade example app to support React Native v0.75.
17
+
18
+ ## [8.5.0] - 24-10-21
19
+
20
+ ### Added
21
+
22
+ - Added `SdkVersion` interface to be used by the sdk and its connectors to report version info.
23
+ - Added the `THEOads` SGAI ad integration for Android. See [THEOads](https://www.theoplayer.com/product/theoads) for more details.
24
+
25
+ ### Fixed
26
+
27
+ - Fixed an issue on Web where all text tracks other than the selected would be set to `disabled` when enabling a text track.
28
+ - Fixed an issue on iOS where the player would crash when changing the presentationMode from fullscreen to picture-in-picture during ad playout.
29
+
30
+ ### Changed
31
+
32
+ - On iOS, after closing picture-in-picture the player returns back to the previous presentationMode instead of always returning to inline.
33
+
8
34
  ## [8.4.0] - 24-10-10
9
35
 
10
36
  ### Added
11
37
 
12
38
  - Added a `posterStyle` property on `THEOplayerView` to allow overriding the default 16:9 poster style.
39
+ - Added a `theoads` property on `PlayerConfiguration.ads` to allow play-out of THEOads sources on Web platforms.
40
+ - Added a `hlsDateRange` property on `SourceDescription` to enable parsing and exposing date ranges from HLS playlists. This flag was already available on `PlayerConfiguration`, which applies for all HLS sources.
13
41
 
14
42
  ### Fixed
15
43
 
@@ -28,7 +28,8 @@ static def versionString(version) {
28
28
  // Extensions
29
29
  def enabledGoogleIMA = safeExtGet("THEOplayer_extensionGoogleIMA", 'false').toBoolean()
30
30
  def enabledGoogleDAI = safeExtGet("THEOplayer_extensionGoogleDAI", 'false').toBoolean()
31
- def enabledAds = enabledGoogleIMA || enabledGoogleDAI
31
+ def enabledTHEOads = safeExtGet("THEOplayer_extensionTHEOads", 'false').toBoolean()
32
+ def enabledAds = enabledGoogleIMA || enabledGoogleDAI || enabledTHEOads
32
33
  def enabledCast = safeExtGet("THEOplayer_extensionCast", 'false').toBoolean()
33
34
  def enabledMediaSession = safeExtGet("THEOplayer_extensionMediaSession", 'true').toBoolean()
34
35
 
@@ -61,6 +62,7 @@ android {
61
62
  // Extension buildConfig fields
62
63
  buildConfigField "boolean", "EXTENSION_GOOGLE_IMA", "${enabledGoogleIMA}"
63
64
  buildConfigField "boolean", "EXTENSION_GOOGLE_DAI", "${enabledGoogleDAI}"
65
+ buildConfigField "boolean", "EXTENSION_THEOADS", "${enabledTHEOads}"
64
66
  buildConfigField "boolean", "EXTENSION_ADS", "${enabledAds}"
65
67
  buildConfigField "boolean", "EXTENSION_CAST", "${enabledCast}"
66
68
  buildConfigField "boolean", "EXTENSION_MEDIASESSION", "${enabledMediaSession}"
@@ -106,9 +108,9 @@ repositories {
106
108
  maven { url "https://maven.theoplayer.com/releases" }
107
109
  }
108
110
 
109
- // The minimum supported THEOplayer version is 8.1.0
110
- def theoplayer_sdk_version = safeExtGet('THEOplayer_sdk', '[8.1.0, 9.0.0)')
111
- def theoplayer_mediasession_version = safeExtGet('THEOplayer_mediasession', '[8.1.0, 9.0.0)')
111
+ // The minimum supported THEOplayer version is 8.3.0
112
+ def theoplayer_sdk_version = safeExtGet('THEOplayer_sdk', '[8.3.0, 9.0.0)')
113
+ def theoplayer_mediasession_version = safeExtGet('THEOplayer_mediasession', '[8.0.0, 9.0.0)')
112
114
 
113
115
  dependencies {
114
116
  //noinspection GradleDynamicVersion
@@ -139,6 +141,14 @@ dependencies {
139
141
  compileOnly "com.theoplayer.theoplayer-sdk-android:integration-ads-dai:${theoplayer_sdk_version}"
140
142
  }
141
143
 
144
+ if (enabledTHEOads) {
145
+ println('Enable THEOplayer THEOads extension.')
146
+ implementation "com.theoplayer.theoplayer-sdk-android:integration-ads-theoads:${theoplayer_sdk_version}"
147
+ } else {
148
+ println('Disable THEOplayer THEOads extension.')
149
+ compileOnly "com.theoplayer.theoplayer-sdk-android:integration-ads-theoads:${theoplayer_sdk_version}"
150
+ }
151
+
142
152
  if (enabledCast) {
143
153
  println('Enable THEOplayer cast extension.')
144
154
  implementation "com.theoplayer.theoplayer-sdk-android:integration-cast:${theoplayer_sdk_version}"
@@ -153,6 +163,7 @@ configurations.configureEach {
153
163
  resolutionStrategy {
154
164
  force "com.theoplayer.theoplayer-sdk-android:integration-ads-ima:${theoplayer_sdk_version}"
155
165
  force "com.theoplayer.theoplayer-sdk-android:integration-ads-dai:${theoplayer_sdk_version}"
166
+ force "com.theoplayer.theoplayer-sdk-android:integration-ads-theoads:${theoplayer_sdk_version}"
156
167
  }
157
168
  }
158
169
 
@@ -18,6 +18,8 @@ import com.theoplayer.android.api.ads.dai.GoogleDaiIntegration
18
18
  import com.theoplayer.android.api.ads.dai.GoogleDaiIntegrationFactory
19
19
  import com.theoplayer.android.api.ads.ima.GoogleImaIntegration
20
20
  import com.theoplayer.android.api.ads.ima.GoogleImaIntegrationFactory
21
+ import com.theoplayer.android.api.ads.theoads.TheoAdsIntegration
22
+ import com.theoplayer.android.api.ads.theoads.TheoAdsIntegrationFactory
21
23
  import com.theoplayer.android.api.cast.CastIntegration
22
24
  import com.theoplayer.android.api.cast.CastIntegrationFactory
23
25
  import com.theoplayer.android.api.event.EventListener
@@ -80,6 +82,7 @@ class ReactTHEOplayerContext private constructor(
80
82
 
81
83
  var daiIntegration: GoogleDaiIntegration? = null
82
84
  var imaIntegration: GoogleImaIntegration? = null
85
+ private var theoAdsIntegration: TheoAdsIntegration? = null
83
86
  var castIntegration: CastIntegration? = null
84
87
  var wasPlayingOnHostPause: Boolean = false
85
88
  private var isHostPaused: Boolean = false
@@ -295,6 +298,17 @@ class ReactTHEOplayerContext private constructor(
295
298
  } catch (e: Exception) {
296
299
  Log.w(TAG, "Failed to configure Google DAI integration ${e.message}")
297
300
  }
301
+ try {
302
+ if (BuildConfig.EXTENSION_THEOADS) {
303
+ theoAdsIntegration = TheoAdsIntegrationFactory.createTheoAdsIntegration(
304
+ playerView
305
+ ).also {
306
+ playerView.player.addIntegration(it)
307
+ }
308
+ }
309
+ } catch (e: Exception) {
310
+ Log.w(TAG, "Failed to configure THEOAds integration ${e.message}")
311
+ }
298
312
  try {
299
313
  if (BuildConfig.EXTENSION_CAST) {
300
314
  castIntegration = CastIntegrationFactory.createCastIntegration(
@@ -115,8 +115,8 @@ class AdEventAdapter(private val adsApi: AdsApiWrapper, eventEmitter: AdEventEmi
115
115
  GoogleImaAdEventType.AD_BREAK_STARTED, AdsEventTypes.AD_BREAK_BEGIN -> "adbreakbegin"
116
116
  GoogleImaAdEventType.AD_BREAK_ENDED, AdsEventTypes.AD_BREAK_END -> "adbreakend"
117
117
  GoogleImaAdEventType.AD_BREAK_FETCH_ERROR -> "aderror"
118
- GoogleImaAdEventType.CLICKED -> "adclicked"
119
- GoogleImaAdEventType.TAPPED -> "adtapped"
118
+ GoogleImaAdEventType.CLICKED, AdsEventTypes.AD_CLICKED -> "adclicked"
119
+ GoogleImaAdEventType.TAPPED, AdsEventTypes.AD_TAPPED -> "adtapped"
120
120
  GoogleImaAdEventType.ICON_TAPPED -> "adicontapped"
121
121
  GoogleImaAdEventType.ICON_FALLBACK_IMAGE_CLOSED -> "adiconfallbackimageclosed"
122
122
  AdsEventTypes.ADD_AD -> "addad"
@@ -40,6 +40,8 @@ class PresentationManager(
40
40
 
41
41
  var currentPresentationMode: PresentationMode = PresentationMode.INLINE
42
42
  private set
43
+ var currentPresentationModeChangeContext: PresentationModeChangeContext? = null
44
+ private set
43
45
 
44
46
  var pipConfig: PipConfig = PipConfig()
45
47
 
@@ -54,12 +56,14 @@ class PresentationManager(
54
56
  }
55
57
  onPictureInPictureModeChanged = object : BroadcastReceiver() {
56
58
  override fun onReceive(context: Context?, intent: Intent?) {
57
- // Dispatch event on every PiP mode change
59
+ val transitioningToPip = intent
60
+ ?.getBooleanExtra("isTransitioningToPip", false) ?: false
58
61
  val inPip = intent?.getBooleanExtra("isInPictureInPictureMode", false) ?: false
59
- if (inPip) {
60
- onEnterPip()
61
- } else {
62
- onExitPip()
62
+ // Dispatch event on every PiP mode change
63
+ when {
64
+ transitioningToPip -> onEnterPip(true)
65
+ inPip -> onEnterPip()
66
+ else -> onExitPip()
63
67
  }
64
68
  }
65
69
  }
@@ -104,9 +108,11 @@ class PresentationManager(
104
108
  PresentationMode.INLINE -> {
105
109
  setFullscreen(false)
106
110
  }
111
+
107
112
  PresentationMode.FULLSCREEN -> {
108
113
  setFullscreen(true)
109
114
  }
115
+
110
116
  PresentationMode.PICTURE_IN_PICTURE -> {
111
117
  setFullscreen(false)
112
118
  enterPip()
@@ -144,8 +150,13 @@ class PresentationManager(
144
150
  }
145
151
  }
146
152
 
147
- private fun onEnterPip() {
148
- updatePresentationMode(PresentationMode.PICTURE_IN_PICTURE)
153
+ private fun onEnterPip(transitioningToPip: Boolean = false) {
154
+ updatePresentationMode(
155
+ PresentationMode.PICTURE_IN_PICTURE,
156
+ if (transitioningToPip)
157
+ PresentationModeChangeContext(PresentationModeChangePipContext.TRANSITIONING_TO_PIP)
158
+ else null
159
+ )
149
160
  }
150
161
 
151
162
  private fun onExitPip() {
@@ -241,11 +252,14 @@ class PresentationManager(
241
252
  presentationMode: PresentationMode,
242
253
  context: PresentationModeChangeContext? = null
243
254
  ) {
244
- if (presentationMode == currentPresentationMode) {
255
+ if (presentationMode == currentPresentationMode &&
256
+ context == currentPresentationModeChangeContext
257
+ ) {
245
258
  return
246
259
  }
247
260
  val prevPresentationMode = currentPresentationMode
248
261
  currentPresentationMode = presentationMode
262
+ currentPresentationModeChangeContext = context
249
263
  eventEmitter.emitPresentationModeChange(presentationMode, prevPresentationMode, context)
250
264
 
251
265
  // Resume playing when going to PiP and player was playing
@@ -9,7 +9,10 @@ enum class PresentationModeChangePipContext {
9
9
  CLOSED,
10
10
 
11
11
  // The PiP window transitioned back into the app.
12
- RESTORED
12
+ RESTORED,
13
+
14
+ // The app transitioning to PiP frame
15
+ TRANSITIONING_TO_PIP
13
16
  }
14
17
 
15
18
  data class PresentationModeChangeContext(
@@ -3,6 +3,7 @@ package com.theoplayer.source
3
3
  import android.text.TextUtils
4
4
  import android.util.Log
5
5
  import com.google.gson.Gson
6
+ import com.theoplayer.android.api.ads.theoads.TheoAdDescription
6
7
  import com.theoplayer.android.api.error.THEOplayerException
7
8
  import com.facebook.react.bridge.ReadableMap
8
9
  import com.facebook.react.bridge.WritableMap
@@ -17,6 +18,7 @@ import com.theoplayer.android.api.source.addescription.GoogleImaAdDescription
17
18
  import com.theoplayer.android.api.player.track.texttrack.TextTrackKind
18
19
  import com.theoplayer.android.api.source.metadata.ChromecastMetadataImage
19
20
  import com.theoplayer.BuildConfig
21
+ import com.theoplayer.android.api.ads.theoads.TheoAdsLayoutOverride
20
22
  import com.theoplayer.android.api.error.ErrorCode
21
23
  import com.theoplayer.android.api.source.AdIntegration
22
24
  import com.theoplayer.android.api.source.dash.DashPlaybackConfiguration
@@ -52,7 +54,16 @@ private const val PROP_ADS = "ads"
52
54
  private const val PROP_DASH = "dash"
53
55
  private const val PROP_DASH_IGNORE_AVAILABILITYWINDOW = "ignoreAvailabilityWindow"
54
56
  private const val PROP_HEADERS = "headers"
57
+ private const val PROP_AD_TAG_PARAMETERS = "adTagParameters"
58
+ private const val PROP_BACKDROP_DOUBLE_BOX = "backdropDoubleBox"
59
+ private const val PROP_BACKDROP_LSHAPE = "backdropLShape"
60
+ private const val PROP_CUSTOM_ASSET_KEY = "customAssetKey"
61
+ private const val PROP_OVERRIDE_LAYOUT = "overrideLayout"
62
+ private const val PROP_NETWORK_CODE = "networkCode"
63
+ private const val PROP_USE_ID3 = "useId3"
64
+
55
65
  private const val ERROR_IMA_NOT_ENABLED = "Google IMA support not enabled."
66
+ private const val ERROR_THEOADS_NOT_ENABLED = "THEOads support not enabled."
56
67
  private const val ERROR_UNSUPPORTED_CSAI_INTEGRATION = "Unsupported CSAI integration"
57
68
  private const val ERROR_MISSING_CSAI_INTEGRATION = "Missing CSAI integration"
58
69
 
@@ -252,6 +263,9 @@ class SourceAdapter {
252
263
  AdIntegration.GOOGLE_IMA.adIntegration -> parseImaAdFromJS(
253
264
  jsonAdDescription
254
265
  )
266
+ AdIntegration.THEO_ADS.adIntegration -> parseTheoAdFromJS(
267
+ jsonAdDescription
268
+ )
255
269
  else -> {
256
270
  throw THEOplayerException(
257
271
  ErrorCode.AD_ERROR,
@@ -285,6 +299,40 @@ class SourceAdapter {
285
299
  .build()
286
300
  }
287
301
 
302
+ @Throws(JSONException::class)
303
+ private fun parseTheoAdFromJS(jsonAdDescription: JSONObject): TheoAdDescription {
304
+ if (!BuildConfig.EXTENSION_THEOADS) {
305
+ throw THEOplayerException(ErrorCode.AD_ERROR, ERROR_THEOADS_NOT_ENABLED)
306
+ }
307
+ return TheoAdDescription(
308
+ adTagParameters = parseAdTagParameters(jsonAdDescription.optJSONObject(PROP_AD_TAG_PARAMETERS)),
309
+ backdropDoubleBox = jsonAdDescription.optString(PROP_BACKDROP_DOUBLE_BOX),
310
+ backdropLShape = jsonAdDescription.optString(PROP_BACKDROP_LSHAPE),
311
+ customAssetKey = jsonAdDescription.optString(PROP_CUSTOM_ASSET_KEY),
312
+ networkCode = jsonAdDescription.optString(PROP_NETWORK_CODE),
313
+ overrideLayout = parseOverrideLayout(jsonAdDescription.optString(PROP_OVERRIDE_LAYOUT)),
314
+ useId3 = jsonAdDescription.optBoolean(PROP_USE_ID3),
315
+ )
316
+ }
317
+
318
+ private fun parseAdTagParameters(params: JSONObject?): Map<String, String> =
319
+ params?.keys()?.asSequence()
320
+ ?.mapNotNull { key -> key to params.optString(key) }
321
+ ?.toMap() ?: emptyMap()
322
+
323
+ private fun parseOverrideLayout(override: String?): TheoAdsLayoutOverride? {
324
+ if (override == null) {
325
+ return null
326
+ }
327
+ when (override) {
328
+ "single" -> return TheoAdsLayoutOverride.SINGLE
329
+ "single-if-mobile" -> return TheoAdsLayoutOverride.SINGLE
330
+ "l-shape" -> return TheoAdsLayoutOverride.LSHAPE
331
+ "double" -> return TheoAdsLayoutOverride.DOUBLE
332
+ }
333
+ return null
334
+ }
335
+
288
336
  @Throws(JSONException::class)
289
337
  private fun parseTextTrackFromJS(jsonTextTrack: JSONObject): TextTrackDescription {
290
338
  val builder = TextTrackDescription.Builder(jsonTextTrack.optString(PROP_SRC))
@@ -109,6 +109,7 @@ class PayloadBuilder {
109
109
  val contextPayload = Arguments.createMap()
110
110
  context.pip?.let { pipCtx ->
111
111
  contextPayload.putString(EVENT_PROP_PIP, when (pipCtx) {
112
+ PresentationModeChangePipContext.TRANSITIONING_TO_PIP -> "transitioning-to-pip"
112
113
  PresentationModeChangePipContext.RESTORED -> "restored"
113
114
  else -> "closed"
114
115
  })
@@ -15,14 +15,16 @@ let EVENT_TYPE_AD_FIRST_QUARTILE: String = "adfirstquartile"
15
15
  let EVENT_TYPE_AD_THIRD_QUARTILE: String = "adthirdquartile"
16
16
  let EVENT_TYPE_AD_MIDPOINT: String = "admidpoint"
17
17
  let EVENT_TYPE_AD_LOADED: String = "adloaded"
18
+ let EVENT_TYPE_AD_TAPPED: String = "adtapped"
19
+ let EVENT_TYPE_AD_CLICKED: String = "adclicked"
18
20
 
19
21
  class THEOplayerRCTAdsEventHandler {
20
22
  // MARK: Members
21
23
  private weak var player: THEOplayer?
22
-
24
+
23
25
  // MARK: Events
24
26
  var onNativeAdEvent: RCTDirectEventBlock?
25
-
27
+
26
28
  // MARK: Ad Listeners
27
29
  private var adBeginListener: EventListener?
28
30
  private var adEndListener: EventListener?
@@ -33,27 +35,29 @@ class THEOplayerRCTAdsEventHandler {
33
35
  private var adMidpointListener: EventListener?
34
36
  private var adThirdQuartileListener: EventListener?
35
37
  private var adLoadedListener: EventListener?
36
-
38
+ private var adTappedListener: EventListener?
39
+ private var adClickedListener: EventListener?
40
+
37
41
  // MARK: - destruction
38
42
  func destroy() {
39
43
  // dettach listeners
40
44
  self.dettachListeners()
41
45
  }
42
-
46
+
43
47
  // MARK: - player setup / breakdown
44
48
  func setPlayer(_ player: THEOplayer) {
45
49
  self.player = player;
46
-
50
+
47
51
  // attach listeners
48
52
  self.attachListeners()
49
53
  }
50
-
54
+
51
55
  // MARK: - attach/dettach Listeners
52
56
  private func attachListeners() {
53
57
  guard let player = self.player else {
54
58
  return
55
59
  }
56
-
60
+
57
61
  #if canImport(THEOplayerGoogleIMAIntegration)
58
62
  // AD_BEGIN
59
63
  self.adBeginListener = player.ads.addEventListener(type: AdsEventTypes.AD_BEGIN) { [weak self] event in
@@ -67,7 +71,7 @@ class THEOplayerRCTAdsEventHandler {
67
71
  }
68
72
  }
69
73
  if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdBegin listener attached to THEOplayer.ads") }
70
-
74
+
71
75
  // AD_END
72
76
  self.adEndListener = player.ads.addEventListener(type: AdsEventTypes.AD_END) { [weak self] event in
73
77
  if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received AD_END event from THEOplayer Ads") }
@@ -80,7 +84,7 @@ class THEOplayerRCTAdsEventHandler {
80
84
  }
81
85
  }
82
86
  if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdEnd listener attached to THEOplayer.ads") }
83
-
87
+
84
88
  // AD_BREAK_BEGIN
85
89
  self.adBreakBeginListener = player.ads.addEventListener(type: AdsEventTypes.AD_BREAK_BEGIN) { [weak self] event in
86
90
  if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received AD_BREAK_BEGIN event from THEOplayer Ads") }
@@ -93,7 +97,7 @@ class THEOplayerRCTAdsEventHandler {
93
97
  }
94
98
  }
95
99
  if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdBreakBegin listener attached to THEOplayer.ads") }
96
-
100
+
97
101
  // AD_BREAK_END
98
102
  self.adBreakEndListener = player.ads.addEventListener(type: AdsEventTypes.AD_BREAK_END) { [weak self] event in
99
103
  if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received AD_BREAK_END event from THEOplayer Ads") }
@@ -106,7 +110,7 @@ class THEOplayerRCTAdsEventHandler {
106
110
  }
107
111
  }
108
112
  if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdBreakEnd listener attached to THEOplayer.ads") }
109
-
113
+
110
114
  // AD_ERROR
111
115
  self.adErrorListener = player.ads.addEventListener(type: AdsEventTypes.AD_ERROR) { [weak self] event in
112
116
  if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received AD_ERROR event from THEOplayer Ads") }
@@ -119,7 +123,7 @@ class THEOplayerRCTAdsEventHandler {
119
123
  }
120
124
  }
121
125
  if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdError listener attached to THEOplayer.ads") }
122
-
126
+
123
127
  // AD_FIRST_QUARTILE
124
128
  self.adFirstQuartileListener = player.ads.addEventListener(type: AdsEventTypes.AD_FIRST_QUARTILE) { [weak self] event in
125
129
  if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received AD_FIRST_QUARTILE event from THEOplayer Ads") }
@@ -132,7 +136,7 @@ class THEOplayerRCTAdsEventHandler {
132
136
  }
133
137
  }
134
138
  if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdFirstQuartile listener attached to THEOplayer.ads") }
135
-
139
+
136
140
  // AD_MIDPOINT
137
141
  self.adMidpointListener = player.ads.addEventListener(type: AdsEventTypes.AD_MIDPOINT) { [weak self] event in
138
142
  if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received AD_MIDPOINT event from THEOplayer Ads") }
@@ -145,7 +149,7 @@ class THEOplayerRCTAdsEventHandler {
145
149
  }
146
150
  }
147
151
  if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdMidpoint listener attached to THEOplayer.ads") }
148
-
152
+
149
153
  // AD_THIRD_QUARTILE
150
154
  self.adThirdQuartileListener = player.ads.addEventListener(type: AdsEventTypes.AD_THIRD_QUARTILE) { [weak self] event in
151
155
  if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received AD_THIRD_QUARTILE event from THEOplayer Ads") }
@@ -158,7 +162,7 @@ class THEOplayerRCTAdsEventHandler {
158
162
  }
159
163
  }
160
164
  if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdThirdQuartile listener attached to THEOplayer.ads") }
161
-
165
+
162
166
  // AD_LOADED
163
167
  self.adLoadedListener = player.ads.addEventListener(type: AdsEventTypes.AD_LOADED) { [weak self] event in
164
168
  if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received AD_LOADED event from THEOplayer Ads") }
@@ -170,69 +174,106 @@ class THEOplayerRCTAdsEventHandler {
170
174
  ])
171
175
  }
172
176
  }
173
- if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdThirdQuartile listener attached to THEOplayer.ads") }
177
+ if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdLoaded listener attached to THEOplayer.ads") }
178
+
179
+ // AD_TAPPED
180
+ self.adTappedListener = player.ads.addEventListener(type: AdsEventTypes.AD_TAPPED) { [weak self] event in
181
+ if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received AD_TAPPED event from THEOplayer Ads") }
182
+ if let forwardedAdEvent = self?.onNativeAdEvent,
183
+ let ad = event.ad {
184
+ forwardedAdEvent([
185
+ AD_EVENT_PROP_TYPE: EVENT_TYPE_AD_TAPPED,
186
+ AD_EVENT_PROP_AD: THEOplayerRCTAdAdapter.fromAd(ad: ad)
187
+ ])
188
+ }
189
+ }
190
+ if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdTapped listener attached to THEOplayer.ads") }
191
+
192
+ // AD_CLICKED
193
+ self.adClickedListener = player.ads.addEventListener(type: AdsEventTypes.AD_CLICKED) { [weak self] event in
194
+ if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received AD_CLICKED event from THEOplayer Ads") }
195
+ if let forwardedAdEvent = self?.onNativeAdEvent,
196
+ let ad = event.ad {
197
+ forwardedAdEvent([
198
+ AD_EVENT_PROP_TYPE: EVENT_TYPE_AD_CLICKED,
199
+ AD_EVENT_PROP_AD: THEOplayerRCTAdAdapter.fromAd(ad: ad)
200
+ ])
201
+ }
202
+ }
203
+ if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdClicked listener attached to THEOplayer.ads") }
174
204
  #endif
175
-
176
205
  }
177
-
206
+
178
207
  private func dettachListeners() {
179
208
  guard let player = self.player else {
180
209
  return
181
210
  }
182
-
211
+
183
212
  #if canImport(THEOplayerGoogleIMAIntegration)
184
213
  // AD_BEGIN
185
214
  if let adBeginListener = self.adBeginListener {
186
215
  player.ads.removeEventListener(type: AdsEventTypes.AD_BEGIN, listener: adBeginListener)
187
- if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdBegin listener dettached from THEOplayer.ads") }
216
+ if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdBegin listener detached from THEOplayer.ads") }
188
217
  }
189
-
218
+
190
219
  // AD_END
191
220
  if let adEndListener = self.adEndListener {
192
221
  player.ads.removeEventListener(type: AdsEventTypes.AD_END, listener: adEndListener)
193
- if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdEnd listener dettached from THEOplayer.ads") }
222
+ if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdEnd listener detached from THEOplayer.ads") }
194
223
  }
195
-
224
+
196
225
  // AD_BREAK_BEGIN
197
226
  if let adBreakBeginListener = self.adBreakBeginListener {
198
227
  player.ads.removeEventListener(type: AdsEventTypes.AD_BREAK_BEGIN, listener: adBreakBeginListener)
199
- if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdBreakBegin listener dettached from THEOplayer.ads") }
228
+ if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdBreakBegin listener detached from THEOplayer.ads") }
200
229
  }
201
-
230
+
202
231
  // AD_BREAK_END
203
232
  if let adBreakEndListener = self.adBreakEndListener {
204
233
  player.ads.removeEventListener(type: AdsEventTypes.AD_BREAK_END, listener: adBreakEndListener)
205
- if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdBreakEnd listener dettached from THEOplayer.ads") }
234
+ if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdBreakEnd listener detached from THEOplayer.ads") }
206
235
  }
207
-
236
+
208
237
  // AD_ERROR
209
238
  if let adErrorListener = self.adErrorListener {
210
239
  player.ads.removeEventListener(type: AdsEventTypes.AD_ERROR, listener: adErrorListener)
211
- if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdError listener dettached from THEOplayer.ads") }
240
+ if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AdError listener detached from THEOplayer.ads") }
212
241
  }
213
-
242
+
214
243
  // AD_FIRST_QUARTILE
215
244
  if let adFirstQuartileListener = self.adFirstQuartileListener {
216
245
  player.ads.removeEventListener(type: AdsEventTypes.AD_FIRST_QUARTILE, listener: adFirstQuartileListener)
217
- if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] adFirstQuartileListener listener dettached from THEOplayer.ads") }
246
+ if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] adFirstQuartileListener listener detached from THEOplayer.ads") }
218
247
  }
219
-
248
+
220
249
  // AD_MIDPOINT
221
250
  if let adMidpointListener = self.adMidpointListener {
222
251
  player.ads.removeEventListener(type: AdsEventTypes.AD_MIDPOINT, listener: adMidpointListener)
223
- if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] adMidpointListener listener dettached from THEOplayer.ads") }
252
+ if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] adMidpointListener listener detached from THEOplayer.ads") }
224
253
  }
225
-
254
+
226
255
  // AD_THIRD_QUARTILE
227
256
  if let adThirdQuartileListener = self.adThirdQuartileListener {
228
257
  player.ads.removeEventListener(type: AdsEventTypes.AD_THIRD_QUARTILE, listener: adThirdQuartileListener)
229
- if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] adThirdQuartileListener listener dettached from THEOplayer.ads") }
258
+ if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] adThirdQuartileListener listener detached from THEOplayer.ads") }
230
259
  }
231
-
260
+
232
261
  // AD_LOADED
233
262
  if let adLoadedListener = self.adLoadedListener {
234
263
  player.ads.removeEventListener(type: AdsEventTypes.AD_LOADED, listener: adLoadedListener)
235
- if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] adLoadedListener listener dettached from THEOplayer.ads") }
264
+ if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] adLoadedListener listener detached from THEOplayer.ads") }
265
+ }
266
+
267
+ // AD_TAPPED
268
+ if let adTappedListener = self.adLoadedListener {
269
+ player.ads.removeEventListener(type: AdsEventTypes.AD_TAPPED, listener: adTappedListener)
270
+ if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] adTapped listener detached from THEOplayer.ads") }
271
+ }
272
+
273
+ // AD_CLICKED
274
+ if let adClickedListener = self.adLoadedListener {
275
+ player.ads.removeEventListener(type: AdsEventTypes.AD_CLICKED, listener: adClickedListener)
276
+ if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] adClicked listener detached from THEOplayer.ads") }
236
277
  }
237
278
  #endif
238
279