react-native-theoplayer 8.5.0 → 8.7.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 (106) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/android/build.gradle +3 -3
  3. package/android/src/main/java/com/theoplayer/ads/AdEventAdapter.kt +2 -2
  4. package/android/src/main/java/com/theoplayer/ads/AdsModule.kt +52 -0
  5. package/android/src/main/java/com/theoplayer/player/PlayerModule.kt +7 -0
  6. package/android/src/main/java/com/theoplayer/presentation/PresentationManager.kt +22 -8
  7. package/android/src/main/java/com/theoplayer/presentation/PresentationModeChangeContext.kt +4 -1
  8. package/android/src/main/java/com/theoplayer/util/PayloadBuilder.kt +1 -0
  9. package/android/src/main/java/com/theoplayer/util/ViewResolver.kt +6 -5
  10. package/app.plugin.js +3 -2
  11. package/ios/THEOplayerRCTBridge.m +8 -0
  12. package/ios/THEOplayerRCTPlayerAPI.swift +6 -0
  13. package/ios/THEOplayerRCTTypeUtils.swift +16 -0
  14. package/ios/ads/THEOplayerRCTAdsAPI+Omid.swift +55 -0
  15. package/ios/ads/THEOplayerRCTAdsEventHandler.swift +77 -36
  16. package/ios/backgroundAudio/THEOplayerRCTNowPlayingManager.swift +7 -2
  17. package/lib/commonjs/api/ads/Omid.js +17 -0
  18. package/lib/commonjs/api/ads/Omid.js.map +1 -0
  19. package/lib/commonjs/api/ads/barrel.js +11 -0
  20. package/lib/commonjs/api/ads/barrel.js.map +1 -1
  21. package/lib/commonjs/api/barrel.js +11 -0
  22. package/lib/commonjs/api/barrel.js.map +1 -1
  23. package/lib/commonjs/api/event/PlayerEvent.js +1 -0
  24. package/lib/commonjs/api/event/PlayerEvent.js.map +1 -1
  25. package/lib/commonjs/api/version/barrel.js +17 -0
  26. package/lib/commonjs/api/version/barrel.js.map +1 -0
  27. package/lib/commonjs/index.js +9 -1
  28. package/lib/commonjs/index.js.map +1 -1
  29. package/lib/commonjs/internal/adapter/ads/THEOplayerNativeAdsAdapter.js +5 -0
  30. package/lib/commonjs/internal/adapter/ads/THEOplayerNativeAdsAdapter.js.map +1 -1
  31. package/lib/commonjs/internal/adapter/ads/THEOplayerNativeOmid.js +25 -0
  32. package/lib/commonjs/internal/adapter/ads/THEOplayerNativeOmid.js.map +1 -0
  33. package/lib/commonjs/internal/adapter/ads/THEOplayerWebAdsAdapter.js +5 -0
  34. package/lib/commonjs/internal/adapter/ads/THEOplayerWebAdsAdapter.js.map +1 -1
  35. package/lib/commonjs/internal/version/Version.js +20 -0
  36. package/lib/commonjs/internal/version/Version.js.map +1 -0
  37. package/lib/commonjs/internal/version/Version.web.js +18 -0
  38. package/lib/commonjs/internal/version/Version.web.js.map +1 -0
  39. package/lib/commonjs/manifest.json +1 -0
  40. package/lib/module/api/ads/Omid.js +12 -0
  41. package/lib/module/api/ads/Omid.js.map +1 -0
  42. package/lib/module/api/ads/barrel.js +1 -0
  43. package/lib/module/api/ads/barrel.js.map +1 -1
  44. package/lib/module/api/barrel.js +1 -0
  45. package/lib/module/api/barrel.js.map +1 -1
  46. package/lib/module/api/event/PlayerEvent.js +1 -0
  47. package/lib/module/api/event/PlayerEvent.js.map +1 -1
  48. package/lib/module/api/version/barrel.js +2 -0
  49. package/lib/module/api/version/barrel.js.map +1 -0
  50. package/lib/module/index.js +1 -0
  51. package/lib/module/index.js.map +1 -1
  52. package/lib/module/internal/adapter/ads/THEOplayerNativeAdsAdapter.js +5 -0
  53. package/lib/module/internal/adapter/ads/THEOplayerNativeAdsAdapter.js.map +1 -1
  54. package/lib/module/internal/adapter/ads/THEOplayerNativeOmid.js +18 -0
  55. package/lib/module/internal/adapter/ads/THEOplayerNativeOmid.js.map +1 -0
  56. package/lib/module/internal/adapter/ads/THEOplayerWebAdsAdapter.js +5 -0
  57. package/lib/module/internal/adapter/ads/THEOplayerWebAdsAdapter.js.map +1 -1
  58. package/lib/module/internal/version/Version.js +11 -0
  59. package/lib/module/internal/version/Version.js.map +1 -0
  60. package/lib/module/internal/version/Version.web.js +10 -0
  61. package/lib/module/internal/version/Version.web.js.map +1 -0
  62. package/lib/module/manifest.json +1 -0
  63. package/lib/typescript/api/ads/AdsAPI.d.ts +7 -0
  64. package/lib/typescript/api/ads/AdsAPI.d.ts.map +1 -1
  65. package/lib/typescript/api/ads/Omid.d.ts +49 -0
  66. package/lib/typescript/api/ads/Omid.d.ts.map +1 -0
  67. package/lib/typescript/api/ads/barrel.d.ts +1 -0
  68. package/lib/typescript/api/ads/barrel.d.ts.map +1 -1
  69. package/lib/typescript/api/barrel.d.ts +1 -0
  70. package/lib/typescript/api/barrel.d.ts.map +1 -1
  71. package/lib/typescript/api/event/AdEvent.d.ts +2 -2
  72. package/lib/typescript/api/event/PlayerEvent.d.ts +8 -1
  73. package/lib/typescript/api/event/PlayerEvent.d.ts.map +1 -1
  74. package/lib/typescript/api/player/THEOplayer.d.ts +2 -0
  75. package/lib/typescript/api/player/THEOplayer.d.ts.map +1 -1
  76. package/lib/typescript/api/version/barrel.d.ts +2 -0
  77. package/lib/typescript/api/version/barrel.d.ts.map +1 -0
  78. package/lib/typescript/index.d.ts +1 -0
  79. package/lib/typescript/index.d.ts.map +1 -1
  80. package/lib/typescript/internal/adapter/ads/THEOplayerNativeAdsAdapter.d.ts +3 -0
  81. package/lib/typescript/internal/adapter/ads/THEOplayerNativeAdsAdapter.d.ts.map +1 -1
  82. package/lib/typescript/internal/adapter/ads/THEOplayerNativeOmid.d.ts +9 -0
  83. package/lib/typescript/internal/adapter/ads/THEOplayerNativeOmid.d.ts.map +1 -0
  84. package/lib/typescript/internal/adapter/ads/THEOplayerWebAdsAdapter.d.ts +2 -0
  85. package/lib/typescript/internal/adapter/ads/THEOplayerWebAdsAdapter.d.ts.map +1 -1
  86. package/lib/typescript/internal/version/Version.d.ts +3 -0
  87. package/lib/typescript/internal/version/Version.d.ts.map +1 -0
  88. package/lib/typescript/internal/version/Version.web.d.ts +3 -0
  89. package/lib/typescript/internal/version/Version.web.d.ts.map +1 -0
  90. package/package.json +16 -15
  91. package/react-native-theoplayer.podspec +6 -6
  92. package/src/api/ads/AdsAPI.ts +8 -0
  93. package/src/api/ads/Omid.ts +58 -0
  94. package/src/api/ads/barrel.ts +1 -0
  95. package/src/api/barrel.ts +1 -0
  96. package/src/api/event/AdEvent.ts +2 -2
  97. package/src/api/event/PlayerEvent.ts +8 -0
  98. package/src/api/player/THEOplayer.ts +2 -0
  99. package/src/api/version/barrel.ts +1 -0
  100. package/src/index.tsx +1 -0
  101. package/src/internal/adapter/ads/THEOplayerNativeAdsAdapter.ts +8 -0
  102. package/src/internal/adapter/ads/THEOplayerNativeOmid.ts +21 -0
  103. package/src/internal/adapter/ads/THEOplayerWebAdsAdapter.ts +7 -0
  104. package/src/internal/version/Version.ts +12 -0
  105. package/src/internal/version/Version.web.ts +11 -0
  106. package/src/manifest.json +1 -0
package/CHANGELOG.md CHANGED
@@ -5,6 +5,27 @@ 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.7.0] - 24-11-05
9
+
10
+ ### Fixed
11
+
12
+ - Fixed an issue on iOS where the dynamic island (iphone 14 plus and higher) briefly disappeared when updating the nowPlayingInfo on for example backgrounding the app.
13
+ - Fixed an issue on Android when using Expo, where the Expo plugin would not add THEOplayer's Maven repo to the project's repositories list.
14
+
15
+ ### Added
16
+
17
+ - Added the `Omid` API for ads, which can be used to manage friendly video controls overlay obstructions.
18
+
19
+ ## [8.6.0] - 24-10-25
20
+
21
+ ### Added
22
+
23
+ - 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.
24
+
25
+ ### Changed
26
+
27
+ - Upgrade example app to support React Native v0.75.
28
+
8
29
  ## [8.5.0] - 24-10-21
9
30
 
10
31
  ### Added
@@ -40,6 +61,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
40
61
  - Fixed an issue on Android where on some Android SDK versions controlling playback with the notification buttons would not work.
41
62
  - Fixed an issue on Web and Android where a text track with attribute `DEFAULT` was not set as the player's `selectedTextTrack` property.
42
63
 
64
+ ### Added
65
+
66
+ - Added `sdkVersions` to react-native-theoplayer, which contains the current RN SDK version and the version of the underlying native THEOplayer SDK.
67
+
43
68
  ## [8.3.0] - 24-09-30
44
69
 
45
70
  ### Added
@@ -108,9 +108,9 @@ repositories {
108
108
  maven { url "https://maven.theoplayer.com/releases" }
109
109
  }
110
110
 
111
- // The minimum supported THEOplayer version is 8.1.0
112
- def theoplayer_sdk_version = safeExtGet('THEOplayer_sdk', '[8.1.0, 9.0.0)')
113
- 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)')
114
114
 
115
115
  dependencies {
116
116
  //noinspection GradleDynamicVersion
@@ -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"
@@ -3,14 +3,21 @@
3
3
  package com.theoplayer.ads
4
4
 
5
5
  import android.util.Log
6
+ import android.view.View
6
7
  import com.facebook.react.bridge.*
7
8
  import com.theoplayer.source.SourceAdapter
8
9
  import com.theoplayer.util.ViewResolver
9
10
  import com.theoplayer.ReactTHEOplayerView
11
+ import com.theoplayer.android.api.ads.OmidFriendlyObstruction
12
+ import com.theoplayer.android.api.ads.OmidFriendlyObstructionPurpose
10
13
  import com.theoplayer.android.api.error.THEOplayerException
11
14
 
12
15
  private const val TAG = "THEORCTAdsModule"
13
16
 
17
+ private const val PROP_OMID_VIEW = "view"
18
+ private const val PROP_OMID_PURPOSE = "purpose"
19
+ private const val PROP_OMID_REASON = "reason"
20
+
14
21
  class AdsModule(context: ReactApplicationContext) : ReactContextBaseJavaModule(context) {
15
22
  private val sourceHelper = SourceAdapter()
16
23
  private val viewResolver: ViewResolver = ViewResolver(context)
@@ -133,4 +140,49 @@ class AdsModule(context: ReactApplicationContext) : ReactContextBaseJavaModule(c
133
140
  }
134
141
  }
135
142
  }
143
+
144
+ @ReactMethod
145
+ fun addFriendlyObstruction(tag: Int, obstruction: ReadableMap) {
146
+ val obsTag =
147
+ if (obstruction.hasKey(PROP_OMID_VIEW)) obstruction.getInt(PROP_OMID_VIEW) else null
148
+ val purpose = if (obstruction.hasKey(PROP_OMID_PURPOSE)) {
149
+ when (obstruction.getString(PROP_OMID_PURPOSE)) {
150
+ "videoControls" -> OmidFriendlyObstructionPurpose.VIDEO_CONTROLS
151
+ "closeAd" -> OmidFriendlyObstructionPurpose.CLOSE_AD
152
+ "notVisible" -> OmidFriendlyObstructionPurpose.NOT_VISIBLE
153
+ else -> OmidFriendlyObstructionPurpose.OTHER
154
+ }
155
+ } else null
156
+ val reason =
157
+ if (obstruction.hasKey(PROP_OMID_REASON)) obstruction.getString(PROP_OMID_REASON) else null
158
+
159
+ if (obsTag !== null) {
160
+ viewResolver.resolveViewByTag(obsTag) { obsView: View? ->
161
+ addFriendlyObstruction(tag, obsView, purpose, reason)
162
+ }
163
+ }
164
+ }
165
+
166
+ private fun addFriendlyObstruction(
167
+ tag: Int,
168
+ obsView: View?,
169
+ purpose: OmidFriendlyObstructionPurpose?,
170
+ reason: String?
171
+ ) {
172
+ if (obsView == null || purpose == null) {
173
+ return
174
+ }
175
+ viewResolver.resolveViewByTag(tag) { view: ReactTHEOplayerView? ->
176
+ view?.player?.ads?.omid?.addFriendlyObstruction(
177
+ OmidFriendlyObstruction(obsView, purpose, reason)
178
+ )
179
+ }
180
+ }
181
+
182
+ @ReactMethod
183
+ fun removeAllFriendlyObstructions(tag: Int) {
184
+ viewResolver.resolveViewByTag(tag) { view: ReactTHEOplayerView? ->
185
+ view?.player?.ads?.omid?.removeAllFriendlyObstructions()
186
+ }
187
+ }
136
188
  }
@@ -10,6 +10,7 @@ import com.theoplayer.android.api.player.RenderingTarget
10
10
  import com.theoplayer.android.api.player.track.mediatrack.MediaTrack
11
11
  import com.theoplayer.android.api.player.track.mediatrack.quality.VideoQuality
12
12
  import com.theoplayer.android.api.player.track.texttrack.TextTrackMode
13
+ import com.theoplayer.android.api.THEOplayerGlobal
13
14
  import com.theoplayer.audio.BackgroundAudioConfigAdapter
14
15
  import com.theoplayer.presentation.PipConfigAdapter
15
16
  import com.theoplayer.track.TextTrackStyleAdapter
@@ -25,6 +26,12 @@ class PlayerModule(context: ReactApplicationContext) : ReactContextBaseJavaModul
25
26
  return TAG
26
27
  }
27
28
 
29
+ // The native version string of the Android THEOplayer SDK.
30
+ @ReactMethod
31
+ fun version(promise: Promise) {
32
+ promise.resolve(THEOplayerGlobal.getVersion())
33
+ }
34
+
28
35
  @ReactMethod
29
36
  fun setABRConfig(tag: Int, config: ReadableMap?) {
30
37
  viewResolver.resolveViewByTag(tag) { view: ReactTHEOplayerView? ->
@@ -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(
@@ -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
  })
@@ -1,17 +1,18 @@
1
1
  package com.theoplayer.util
2
2
 
3
3
  import android.util.Log
4
+ import android.view.View
4
5
  import com.facebook.react.bridge.ReactApplicationContext
5
6
  import com.facebook.react.uimanager.UIManagerModule
6
- import com.theoplayer.ReactTHEOplayerView
7
7
 
8
8
  private const val TAG = "ViewResolver"
9
9
  private const val INVALID_TAG = -1
10
10
 
11
+ @Suppress("UNCHECKED_CAST")
11
12
  class ViewResolver(private val reactContext: ReactApplicationContext) {
12
13
  private var uiManager: UIManagerModule? = null
13
14
 
14
- fun resolveViewByTag(tag: Int, onResolved: (view: ReactTHEOplayerView?) -> Unit) {
15
+ fun <T: View> resolveViewByTag(tag: Int, onResolved: (view: T?) -> Unit) {
15
16
  if (tag == INVALID_TAG) {
16
17
  // Don't bother trying to resolve an invalid tag.
17
18
  onResolved(null)
@@ -21,10 +22,10 @@ class ViewResolver(private val reactContext: ReactApplicationContext) {
21
22
  }
22
23
  uiManager?.addUIBlock {
23
24
  try {
24
- onResolved(it.resolveView(tag) as ReactTHEOplayerView)
25
+ onResolved(it.resolveView(tag) as? T?)
25
26
  } catch (e: Exception) {
26
- // The ReactTHEOplayerView instance could not be resolved: log but do not forward exception.
27
- Log.e(TAG, "Failed to resolve ReactTHEOplayerView tag $tag: $e")
27
+ // The View instance could not be resolved: log but do not forward exception.
28
+ Log.e(TAG, "Failed to resolve View tag $tag: $e")
28
29
  onResolved(null)
29
30
  }
30
31
  }
package/app.plugin.js CHANGED
@@ -40,10 +40,11 @@ const withAndroidTHEOplayer = (config, props) => {
40
40
  const { extensions } = props | {};
41
41
  config = applyAndroidExtensions(config, extensions);
42
42
 
43
- // Add the localMaven repo to the project's repositories
43
+ // Add THEOplayer and local Maven repos to the project's repositories
44
44
  return withProjectBuildGradle(config, (config) => {
45
45
  const localMaven = 'maven { url("$rootDir/../node_modules/react-native-theoplayer/android/local") }';
46
- config.modResults.contents = config.modResults.contents.replace(/allprojects\s*\{\s*repositories\s*\{/, `$&\n\t\t${localMaven}`);
46
+ const THEOplayerMaven = 'maven { url("https://maven.theoplayer.com/releases") }';
47
+ config.modResults.contents = config.modResults.contents.replace(/allprojects\s*\{\s*repositories\s*\{/, `$&\n\t\t${localMaven}\n\t\t${THEOplayerMaven}`);
47
48
  return config;
48
49
  });
49
50
  };
@@ -60,6 +60,9 @@ RCT_EXTERN_METHOD(destroy:(nonnull NSNumber *)node);
60
60
  // ----------------------------------------------------------------------------
61
61
  @interface RCT_EXTERN_REMAP_MODULE(THEORCTPlayerModule, THEOplayerRCTPlayerAPI, NSObject)
62
62
 
63
+ RCT_EXTERN_METHOD(version:(RCTPromiseResolveBlock)resolve
64
+ rejecter:(RCTPromiseRejectBlock)reject)
65
+
63
66
  RCT_EXTERN_METHOD(setPaused:(nonnull NSNumber *)node
64
67
  paused:(BOOL)paused)
65
68
 
@@ -157,6 +160,11 @@ RCT_EXTERN_METHOD(daiStreamTimeForContentTime:(nonnull NSNumber *)node
157
160
  resolver:(RCTPromiseResolveBlock)resolve
158
161
  rejecter:(RCTPromiseRejectBlock)reject)
159
162
 
163
+ RCT_EXTERN_METHOD(addFriendlyObstruction:(nonnull NSNumber *)node
164
+ obstruction:(NSDictionary)obstruction)
165
+
166
+ RCT_EXTERN_METHOD(removeAllFriendlyObstructions:(nonnull NSNumber *)node)
167
+
160
168
  @end
161
169
 
162
170
  // ----------------------------------------------------------------------------
@@ -35,6 +35,12 @@ class THEOplayerRCTPlayerAPI: NSObject, RCTBridgeModule {
35
35
  static func requiresMainQueueSetup() -> Bool {
36
36
  return false
37
37
  }
38
+
39
+ @objc(version:rejecter:)
40
+ func version(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
41
+ let versionString = THEOplayer.version
42
+ resolve(versionString)
43
+ }
38
44
 
39
45
  @objc(setPaused:paused:)
40
46
  func setPaused(_ node: NSNumber, paused: Bool) -> Void {
@@ -123,6 +123,22 @@ class THEOplayerRCTTypeUtils {
123
123
  return .moviePlayback
124
124
  }
125
125
  }
126
+
127
+ class func omidFriendlyObstructionPurposeFromString(_ purposeString: String) -> OmidFriendlyObstructionPurpose {
128
+ switch purposeString {
129
+ case "videoControls":
130
+ return OmidFriendlyObstructionPurpose.mediaControls
131
+ case "closeAd":
132
+ return OmidFriendlyObstructionPurpose.closeAd
133
+ case "notVisible":
134
+ return OmidFriendlyObstructionPurpose.notVisible
135
+ case "other":
136
+ return OmidFriendlyObstructionPurpose.other
137
+ default:
138
+ return OmidFriendlyObstructionPurpose.other
139
+ }
140
+
141
+ }
126
142
 
127
143
  #if os(iOS)
128
144
  class func cacheStatusToString(_ status: CacheStatus) -> String {
@@ -0,0 +1,55 @@
1
+ // THEOplayerRCTAdsAPI+Omid.swift
2
+
3
+ import Foundation
4
+ import THEOplayerSDK
5
+ import UIKit
6
+
7
+ let PROP_OMID_VIEW: String = "view"
8
+ let PROP_OMID_PURPOSE: String = "purpose"
9
+ let PROP_OMID_REASON: String = "reason"
10
+
11
+ extension THEOplayerRCTAdsAPI {
12
+
13
+ #if canImport(THEOplayerGoogleIMAIntegration)
14
+ @objc(addFriendlyObstruction:obstruction:)
15
+ func addFriendlyObstruction(_ node: NSNumber, obstruction: NSDictionary) {
16
+ DispatchQueue.main.async {
17
+ if let obstructionNode = obstruction[PROP_OMID_VIEW] as? NSNumber,
18
+ let purposeString = obstruction[PROP_OMID_PURPOSE] as? String,
19
+ let theView = self.bridge.uiManager.view(forReactTag: node) as? THEOplayerRCTView,
20
+ let obstructionView = self.bridge.uiManager.view(forReactTag: obstructionNode),
21
+ let ads = theView.ads() {
22
+ let obstruction = OmidFriendlyObstruction(view: obstructionView,
23
+ purpose: THEOplayerRCTTypeUtils.omidFriendlyObstructionPurposeFromString(purposeString),
24
+ detailedReason: obstruction[PROP_OMID_REASON] as? String)
25
+ ads.omid.addFriendlyObstruction(friendlyObstruction: obstruction)
26
+ }
27
+ }
28
+ }
29
+
30
+ @objc(removeAllFriendlyObstructions:)
31
+ func removeAllFriendlyObstructions(_ node: NSNumber) {
32
+ DispatchQueue.main.async {
33
+ if let theView = self.bridge.uiManager.view(forReactTag: node) as? THEOplayerRCTView,
34
+ let ads = theView.ads() {
35
+ ads.omid.removeFriendlyObstructions()
36
+ }
37
+ }
38
+ }
39
+
40
+ #else
41
+
42
+ @objc(addFriendlyObstruction:obstruction:)
43
+ func addFriendlyObstruction(_ node: NSNumber, obstruction: NSDictionary) {
44
+ if DEBUG_ADS_API { print(ERROR_MESSAGE_ADS_UNSUPPORTED_FEATURE) }
45
+ }
46
+
47
+ @objc(removeAllFriendlyObstructions:)
48
+ func removeAllFriendlyObstructions(_ node: NSNumber) {
49
+ if DEBUG_ADS_API { print(ERROR_MESSAGE_ADS_UNSUPPORTED_FEATURE) }
50
+ }
51
+
52
+ #endif
53
+ }
54
+
55
+