react-native-theoplayer 7.6.0 → 7.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/android/src/main/java/com/theoplayer/cache/CacheModule.kt +27 -25
- package/ios/THEOplayerRCTBridge.m +3 -1
- package/ios/THEOplayerRCTMainEventHandler.swift +2 -2
- package/ios/THEOplayerRCTMediaTrackEventHandler.swift +129 -2
- package/ios/THEOplayerRCTSourceDescriptionAggregator.swift +15 -2
- package/ios/THEOplayerRCTSourceDescriptionBuilder.swift +14 -0
- package/ios/THEOplayerRCTTrackEventTypes.swift +4 -0
- package/ios/ads/THEOplayerRCTAdAdapter.swift +19 -15
- package/ios/ads/THEOplayerRCTAdsNative.swift +25 -8
- package/ios/cache/THEOplayerRCTCacheAPI.swift +7 -3
- package/ios/cache/THEOplayerRCTCacheAggregator.swift +1 -1
- package/package.json +1 -1
- package/react-native-theoplayer.podspec +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,25 @@ 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
|
+
## [7.7.1] - 24-07-29
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- Fixed an issue on tvOS where native cache functionality was not excluded correctly resulting in build errors.
|
|
13
|
+
|
|
14
|
+
## [7.7.0] - 24-07-25
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- Added ActiveQualityChanged event support for iOS.
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- Fixed an issue where on iOS a cached asset would not play when setting the tasks's source on the player.
|
|
23
|
+
- Fixed an issue where on iOS the createTask method (CacheAPI) was not returning the created task.
|
|
24
|
+
- Fixed an issue where on iOS the Ad and AdBreak protocols where extended in the underlying native SDK and required some modifications.
|
|
25
|
+
- Fixed an issue where on Android the native module preparation would fail due to a change in the Android SDK 7.8.0 on eventDispatching.
|
|
26
|
+
|
|
8
27
|
## [7.6.0] - 24-07-01
|
|
9
28
|
|
|
10
29
|
### Added
|
|
@@ -52,34 +52,36 @@ class CacheModule(private val context: ReactApplicationContext) :
|
|
|
52
52
|
|
|
53
53
|
init {
|
|
54
54
|
// Add cache event listeners
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
// Listen for add task events
|
|
63
|
-
tasks.addEventListener(CachingTaskListEventTypes.ADD_TASK) { event ->
|
|
64
|
-
event.task?.let { task ->
|
|
65
|
-
// Notify AddCachingTaskEvent event
|
|
66
|
-
emit("onAddCachingTaskEvent", Arguments.createMap().apply {
|
|
67
|
-
putMap(PROP_TASK, CacheAdapter.fromCachingTask(task))
|
|
55
|
+
handler.post {
|
|
56
|
+
cache?.apply {
|
|
57
|
+
// Listen for cache state changes
|
|
58
|
+
addEventListener(CacheEventTypes.CACHE_STATE_CHANGE) { event ->
|
|
59
|
+
emit("onCacheStatusChange", Arguments.createMap().apply {
|
|
60
|
+
putString(PROP_STATUS, CacheAdapter.fromCacheStatus(event.status))
|
|
68
61
|
})
|
|
69
|
-
|
|
70
|
-
|
|
62
|
+
}
|
|
63
|
+
// Listen for add task events
|
|
64
|
+
tasks.addEventListener(CachingTaskListEventTypes.ADD_TASK) { event ->
|
|
65
|
+
event.task?.let { task ->
|
|
66
|
+
// Notify AddCachingTaskEvent event
|
|
67
|
+
emit("onAddCachingTaskEvent", Arguments.createMap().apply {
|
|
68
|
+
putMap(PROP_TASK, CacheAdapter.fromCachingTask(task))
|
|
69
|
+
})
|
|
70
|
+
// Add CachingTask listeners
|
|
71
|
+
addCachingTaskListeners(task)
|
|
72
|
+
}
|
|
71
73
|
}
|
|
72
|
-
}
|
|
73
74
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
75
|
+
// Listen for task removal
|
|
76
|
+
tasks.addEventListener(CachingTaskListEventTypes.REMOVE_TASK) { event ->
|
|
77
|
+
event.task?.let { task ->
|
|
78
|
+
// Notify RemoveCachingTaskEvent event
|
|
79
|
+
emit("onRemoveCachingTaskEvent", Arguments.createMap().apply {
|
|
80
|
+
putMap(PROP_TASK, CacheAdapter.fromCachingTask(event.task))
|
|
81
|
+
})
|
|
82
|
+
// Remove CachingTask listeners
|
|
83
|
+
removeCachingTaskListeners(task)
|
|
84
|
+
}
|
|
83
85
|
}
|
|
84
86
|
}
|
|
85
87
|
}
|
|
@@ -228,7 +228,9 @@ RCT_EXTERN_METHOD(getInitialState:(RCTPromiseResolveBlock)resolve
|
|
|
228
228
|
rejecter:(RCTPromiseRejectBlock)reject)
|
|
229
229
|
|
|
230
230
|
RCT_EXTERN_METHOD(createTask:(NSDictionary)src
|
|
231
|
-
params:(NSDictionary)params
|
|
231
|
+
params:(NSDictionary)params
|
|
232
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
233
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
232
234
|
|
|
233
235
|
RCT_EXTERN_METHOD(startCachingTask:(nonnull NSString *)id)
|
|
234
236
|
|
|
@@ -317,8 +317,8 @@ public class THEOplayerRCTMainEventHandler {
|
|
|
317
317
|
let forwardedResizeEvent = self?.onNativeResize {
|
|
318
318
|
forwardedResizeEvent(
|
|
319
319
|
[
|
|
320
|
-
"width": wplayer.
|
|
321
|
-
"height": wplayer.
|
|
320
|
+
"width": wplayer.frame.width,
|
|
321
|
+
"height": wplayer.frame.height,
|
|
322
322
|
]
|
|
323
323
|
)
|
|
324
324
|
}
|
|
@@ -20,8 +20,8 @@ class THEOplayerRCTMediaTrackEventHandler {
|
|
|
20
20
|
private var videoChangeTrackListener: EventListener?
|
|
21
21
|
|
|
22
22
|
// MARK: mediaTrack listeners (attached dynamically to new mediatracks)
|
|
23
|
-
private var
|
|
24
|
-
private var
|
|
23
|
+
private var videoQualityChangeListeners: [Int:EventListener] = [:]
|
|
24
|
+
private var audioQualityChangeListeners: [Int:EventListener] = [:]
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
// MARK: - destruction
|
|
@@ -56,6 +56,10 @@ class THEOplayerRCTMediaTrackEventHandler {
|
|
|
56
56
|
"type" : TrackListEventType.ADD_TRACK.rawValue,
|
|
57
57
|
"trackType": MediaTrackType.AUDIO.rawValue
|
|
58
58
|
])
|
|
59
|
+
|
|
60
|
+
// start listening for qualityChange events on this track
|
|
61
|
+
welf.audioQualityChangeListeners[audioTrack.uid] = audioTrack.addEventListener(type: MediaTrackEventTypes.ACTIVE_QUALITY_CHANGED, listener: welf.addAudioQualityChangeListener(_:))
|
|
62
|
+
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] QualityChange listener attached to THEOplayer audioTrack with uid \(audioTrack.uid)") }
|
|
59
63
|
}
|
|
60
64
|
}
|
|
61
65
|
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AddTrack listener attached to THEOplayer audioTrack list") }
|
|
@@ -72,6 +76,12 @@ class THEOplayerRCTMediaTrackEventHandler {
|
|
|
72
76
|
"type" : TrackListEventType.REMOVE_TRACK.rawValue,
|
|
73
77
|
"trackType": MediaTrackType.AUDIO.rawValue
|
|
74
78
|
])
|
|
79
|
+
|
|
80
|
+
// stop listening for qualityChange events on this track
|
|
81
|
+
if let audioQualityChangeListener = welf.audioQualityChangeListeners.removeValue(forKey: audioTrack.uid) {
|
|
82
|
+
audioTrack.removeEventListener(type: MediaTrackEventTypes.ACTIVE_QUALITY_CHANGED, listener: audioQualityChangeListener)
|
|
83
|
+
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] ActiveQuality listener removed from THEOplayer audioTrack with uid \(audioTrack.uid)") }
|
|
84
|
+
}
|
|
75
85
|
}
|
|
76
86
|
}
|
|
77
87
|
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] RemoveTrack listener attached to THEOplayer audioTrack list") }
|
|
@@ -104,6 +114,10 @@ class THEOplayerRCTMediaTrackEventHandler {
|
|
|
104
114
|
"type" : TrackListEventType.ADD_TRACK.rawValue,
|
|
105
115
|
"trackType": MediaTrackType.VIDEO.rawValue
|
|
106
116
|
])
|
|
117
|
+
|
|
118
|
+
// start listening for qualityChange events on this track
|
|
119
|
+
welf.videoQualityChangeListeners[videoTrack.uid] = videoTrack.addEventListener(type: MediaTrackEventTypes.ACTIVE_QUALITY_CHANGED, listener: welf.addVideoQualityChangeListener(_:))
|
|
120
|
+
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] QualityChange listener attached to THEOplayer videoTrack with uid \(videoTrack.uid)") }
|
|
107
121
|
}
|
|
108
122
|
}
|
|
109
123
|
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] AddTrack listener attached to THEOplayer videoTrack list") }
|
|
@@ -120,6 +134,12 @@ class THEOplayerRCTMediaTrackEventHandler {
|
|
|
120
134
|
"type" : TrackListEventType.REMOVE_TRACK.rawValue,
|
|
121
135
|
"trackType": MediaTrackType.VIDEO.rawValue
|
|
122
136
|
])
|
|
137
|
+
|
|
138
|
+
// stop listening for qualityChange events on this track
|
|
139
|
+
if let videoQualityChangeListener = welf.videoQualityChangeListeners.removeValue(forKey: videoTrack.uid) {
|
|
140
|
+
videoTrack.removeEventListener(type: MediaTrackEventTypes.ACTIVE_QUALITY_CHANGED, listener: videoQualityChangeListener)
|
|
141
|
+
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] ActiveQuality listener removed from THEOplayer videoTrack with uid \(videoTrack.uid)") }
|
|
142
|
+
}
|
|
123
143
|
}
|
|
124
144
|
}
|
|
125
145
|
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] RemoveTrack listener attached to THEOplayer videoTrack list") }
|
|
@@ -181,5 +201,112 @@ class THEOplayerRCTMediaTrackEventHandler {
|
|
|
181
201
|
player.videoTracks.removeEventListener(type: VideoTrackListEventTypes.CHANGE, listener: videoChangeTrackListener)
|
|
182
202
|
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] ChangeTrack listener dettached from THEOplayer videoTrack list") }
|
|
183
203
|
}
|
|
204
|
+
|
|
205
|
+
// QUALITY CHANGE - AUDIO
|
|
206
|
+
let audioTrackCount = player.audioTracks.count
|
|
207
|
+
if audioTrackCount > 0 {
|
|
208
|
+
for i in 0..<audioTrackCount {
|
|
209
|
+
let audioTrack = player.audioTracks[i]
|
|
210
|
+
// stop listening for quality change events on this track
|
|
211
|
+
if let audioQualityChangeListener = self.audioQualityChangeListeners.removeValue(forKey: audioTrack.uid) {
|
|
212
|
+
audioTrack.removeEventListener(type: MediaTrackEventTypes.ACTIVE_QUALITY_CHANGED, listener: audioQualityChangeListener)
|
|
213
|
+
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] ActiveQuality listener removed from THEOplayer audioTrack with uid \(audioTrack.uid)") }
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// QUALITY CHANGE - VIDEO
|
|
219
|
+
let videoTrackCount = player.videoTracks.count
|
|
220
|
+
if videoTrackCount > 0 {
|
|
221
|
+
for i in 0..<videoTrackCount {
|
|
222
|
+
let videoTrack = player.videoTracks[i]
|
|
223
|
+
// stop listening for quality change events on this track
|
|
224
|
+
if let videoQualityChangeListener = self.videoQualityChangeListeners.removeValue(forKey: videoTrack.uid) {
|
|
225
|
+
videoTrack.removeEventListener(type: MediaTrackEventTypes.ACTIVE_QUALITY_CHANGED, listener: videoQualityChangeListener)
|
|
226
|
+
if DEBUG_EVENTHANDLER { PrintUtils.printLog(logText: "[NATIVE] ActiveQuality listener removed from THEOplayer videoTrack with uid \(videoTrack.uid)") }
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// MARK: - dynamic mediaTrack Listeners
|
|
233
|
+
private func addVideoQualityChangeListener(_ event: ActiveQualityChangedEvent) {
|
|
234
|
+
if let forwardedMediaTrackEvent = self.onNativeMediaTrackEvent,
|
|
235
|
+
let player = self.player,
|
|
236
|
+
let track = self.activeTrack(tracks: player.videoTracks) {
|
|
237
|
+
if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received ACTIVE_QUALITY_CHANGED event for videoTrack") }
|
|
238
|
+
let identifier = String(track.activeQualityBandwidth)
|
|
239
|
+
let label = self.labelFromBandWidth(track.activeQualityBandwidth)
|
|
240
|
+
forwardedMediaTrackEvent([
|
|
241
|
+
"trackUid" : track.uid,
|
|
242
|
+
"type" : MediaTrackEventType.ACTIVE_QUALITY_CHANGED.rawValue,
|
|
243
|
+
"trackType": MediaTrackType.VIDEO.rawValue,
|
|
244
|
+
"qualities": [
|
|
245
|
+
"bandwidth": track.activeQualityBandwidth,
|
|
246
|
+
"codecs": "",
|
|
247
|
+
"id": identifier,
|
|
248
|
+
"uid": identifier,
|
|
249
|
+
"name": label,
|
|
250
|
+
"label": label,
|
|
251
|
+
"available": true,
|
|
252
|
+
"width": player.videoWidth,
|
|
253
|
+
"height": player.videoHeight,
|
|
254
|
+
//"frameRate": 0, // not available on iOS SDK
|
|
255
|
+
//"firstFrame": 0 // not available on iOS SDK
|
|
256
|
+
|
|
257
|
+
]
|
|
258
|
+
])
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
private func addAudioQualityChangeListener(_ event: ActiveQualityChangedEvent) {
|
|
263
|
+
if let forwardedMediaTrackEvent = self.onNativeMediaTrackEvent,
|
|
264
|
+
let player = self.player,
|
|
265
|
+
let track = self.activeTrack(tracks: player.audioTracks) {
|
|
266
|
+
if DEBUG_THEOPLAYER_EVENTS { PrintUtils.printLog(logText: "[NATIVE] Received ACTIVE_QUALITY_CHANGED event for audioTrack") }
|
|
267
|
+
let identifier = String(track.activeQualityBandwidth)
|
|
268
|
+
let label = self.labelFromBandWidth(track.activeQualityBandwidth)
|
|
269
|
+
|
|
270
|
+
forwardedMediaTrackEvent([
|
|
271
|
+
"trackUid" : track.uid,
|
|
272
|
+
"type" : MediaTrackEventType.ACTIVE_QUALITY_CHANGED.rawValue,
|
|
273
|
+
"trackType": MediaTrackType.AUDIO.rawValue,
|
|
274
|
+
"qualities": [
|
|
275
|
+
"bandwidth": track.activeQualityBandwidth,
|
|
276
|
+
"codecs": "",
|
|
277
|
+
"id": identifier,
|
|
278
|
+
"uid": identifier,
|
|
279
|
+
"name": label,
|
|
280
|
+
"label": label,
|
|
281
|
+
"available": true,
|
|
282
|
+
//"audioSamplingRate": 0 // not available on iOS SDK
|
|
283
|
+
]
|
|
284
|
+
])
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// MARK: - Helpers
|
|
289
|
+
private func activeTrack(tracks: THEOplayerSDK.MediaTrackList) -> MediaTrack? {
|
|
290
|
+
guard tracks.count > 0 else {
|
|
291
|
+
return nil;
|
|
292
|
+
}
|
|
293
|
+
var track: MediaTrack?
|
|
294
|
+
for i in 0...tracks.count-1 {
|
|
295
|
+
track = tracks.get(i)
|
|
296
|
+
if (track != nil && track!.enabled) {
|
|
297
|
+
return track
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return nil;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
private func labelFromBandWidth(_ bandWidth: Int) -> String {
|
|
304
|
+
if bandWidth > 1000000 {
|
|
305
|
+
return "\(Double(bandWidth / 1000) / 1000) Mbps"
|
|
306
|
+
} else if bandWidth > 1000 {
|
|
307
|
+
return "\(bandWidth / 1000) kbps"
|
|
308
|
+
} else {
|
|
309
|
+
return "No Label"
|
|
310
|
+
}
|
|
184
311
|
}
|
|
185
312
|
}
|
|
@@ -6,12 +6,14 @@ import UIKit
|
|
|
6
6
|
|
|
7
7
|
#if os(iOS)
|
|
8
8
|
class THEOplayerRCTSourceDescriptionAggregator {
|
|
9
|
-
class func aggregateCacheTaskSourceDescription(sourceDescription: SourceDescription) -> [String:Any]? {
|
|
9
|
+
class func aggregateCacheTaskSourceDescription(sourceDescription: SourceDescription, cachingTaskId: String) -> [String:Any]? {
|
|
10
10
|
do {
|
|
11
11
|
let jsonEncoder = JSONEncoder()
|
|
12
12
|
let data = try jsonEncoder.encode(sourceDescription)
|
|
13
13
|
if let result = try? JSONSerialization.jsonObject(with: data, options: []) as? [String:Any] {
|
|
14
|
-
|
|
14
|
+
let srcDescription = THEOplayerRCTSourceDescriptionAggregator.sanitiseSourceDescriptionMetadata(input: result)
|
|
15
|
+
let extendedSrcDescription = THEOplayerRCTSourceDescriptionAggregator.addCachingTaskIdToMetadata(input: srcDescription, cachingTaskId: cachingTaskId)
|
|
16
|
+
return extendedSrcDescription
|
|
15
17
|
}
|
|
16
18
|
} catch {
|
|
17
19
|
if DEBUG { PrintUtils.printLog(logText: "[NATIVE] Could not aggregate sourceDescription for caching task: \(error.localizedDescription)")}
|
|
@@ -39,5 +41,16 @@ class THEOplayerRCTSourceDescriptionAggregator {
|
|
|
39
41
|
}
|
|
40
42
|
return output
|
|
41
43
|
}
|
|
44
|
+
|
|
45
|
+
private class func addCachingTaskIdToMetadata(input: [String:Any], cachingTaskId: String) -> [String:Any] {
|
|
46
|
+
var output: [String:Any] = input
|
|
47
|
+
if var metadata = output[SD_PROP_METADATA] as? [String:Any] {
|
|
48
|
+
metadata[SD_PROP_METADATA_CACHINGTASK_ID] = cachingTaskId
|
|
49
|
+
output[SD_PROP_METADATA] = metadata
|
|
50
|
+
} else {
|
|
51
|
+
output[SD_PROP_METADATA] = [SD_PROP_METADATA_CACHINGTASK_ID: cachingTaskId]
|
|
52
|
+
}
|
|
53
|
+
return output
|
|
54
|
+
}
|
|
42
55
|
}
|
|
43
56
|
#endif
|
|
@@ -12,6 +12,7 @@ let SD_PROP_SOURCES: String = "sources"
|
|
|
12
12
|
let SD_PROP_POSTER: String = "poster"
|
|
13
13
|
let SD_PROP_TEXTTRACKS: String = "textTracks"
|
|
14
14
|
let SD_PROP_METADATA: String = "metadata"
|
|
15
|
+
let SD_PROP_METADATA_CACHINGTASK_ID: String = "cachingTaskId"
|
|
15
16
|
let SD_PROP_METADATAKEYS: String = "metadataKeys"
|
|
16
17
|
let SD_PROP_SRC: String = "src"
|
|
17
18
|
let SD_PROP_TYPE: String = "type"
|
|
@@ -73,6 +74,19 @@ class THEOplayerRCTSourceDescriptionBuilder {
|
|
|
73
74
|
guard let sourcesData = sourceData[SD_PROP_SOURCES] else {
|
|
74
75
|
return (nil, nil)
|
|
75
76
|
}
|
|
77
|
+
|
|
78
|
+
#if os(iOS)
|
|
79
|
+
if let metadataData = sourceData[SD_PROP_METADATA] as? [String:Any],
|
|
80
|
+
let cachingTaskId = metadataData[SD_PROP_METADATA_CACHINGTASK_ID] as? String {
|
|
81
|
+
// this is a MediaCache src, so fetch the original SourceDescription from the MediaCache
|
|
82
|
+
let cachingTaskWithId = THEOplayer.cache.tasks.first { cachingTask in
|
|
83
|
+
cachingTask.id == cachingTaskId
|
|
84
|
+
}
|
|
85
|
+
if let foundTask = cachingTaskWithId {
|
|
86
|
+
return (foundTask.source, nil)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
#endif
|
|
76
90
|
|
|
77
91
|
var typedSources: [TypedSource] = []
|
|
78
92
|
// case: array of source objects
|
|
@@ -4,6 +4,7 @@ import Foundation
|
|
|
4
4
|
import THEOplayerSDK
|
|
5
5
|
|
|
6
6
|
let PROP_AD_INTEGRATION: String = "integration"
|
|
7
|
+
let PROP_AD_CUSTOM_INTEGRATION: String = "customIntegration"
|
|
7
8
|
let PROP_AD_TYPE: String = "type"
|
|
8
9
|
let PROP_AD_ID: String = "id"
|
|
9
10
|
let PROP_AD_BREAK: String = "adBreak"
|
|
@@ -31,6 +32,7 @@ let PROP_ADBREAK_TIME_OFFSET: String = "timeOffset"
|
|
|
31
32
|
let PROP_ADBREAK_MAX_REMAINING_DURATION: String = "maxRemainingDuration"
|
|
32
33
|
let PROP_ADBREAK_ADS: String = "ads"
|
|
33
34
|
let PROP_ADBREAK_INTEGRATION: String = "integration"
|
|
35
|
+
let PROP_ADBREAK_CUSTOM_INTEGRATION: String = "customIntegration"
|
|
34
36
|
let PROP_COMPANION_AD_SLOT_ID: String = "adSlotId"
|
|
35
37
|
let PROP_COMPANION_ALT_TEXT: String = "altText"
|
|
36
38
|
let PROP_COMPANION_CLICK_THROUGH: String = "clickThrough"
|
|
@@ -43,6 +45,9 @@ class THEOplayerRCTAdAdapter {
|
|
|
43
45
|
class func fromAd(ad: Ad, processAdBreak: Bool = true) -> [String:Any] {
|
|
44
46
|
var adData: [String:Any] = [:]
|
|
45
47
|
adData[PROP_AD_INTEGRATION] = ad.integration._rawValue
|
|
48
|
+
if let customIntegration = ad.customIntegration {
|
|
49
|
+
adData[PROP_AD_CUSTOM_INTEGRATION] = customIntegration
|
|
50
|
+
}
|
|
46
51
|
adData[PROP_AD_TYPE] = ad.type
|
|
47
52
|
if let adId = ad.id {
|
|
48
53
|
adData[PROP_AD_ID] = adId
|
|
@@ -50,6 +55,9 @@ class THEOplayerRCTAdAdapter {
|
|
|
50
55
|
if let resourceURI = ad.resourceURI {
|
|
51
56
|
adData[PROP_AD_RESOURCE_URI] = resourceURI
|
|
52
57
|
}
|
|
58
|
+
if let clickThrough = ad.clickThrough {
|
|
59
|
+
adData[PROP_AD_CLICK_THROUGH] = clickThrough
|
|
60
|
+
}
|
|
53
61
|
if let skipOffset = ad.skipOffset {
|
|
54
62
|
adData[PROP_AD_SKIP_OFFSET] = (skipOffset == -1) ? skipOffset : skipOffset
|
|
55
63
|
}
|
|
@@ -65,20 +73,14 @@ class THEOplayerRCTAdAdapter {
|
|
|
65
73
|
adData[PROP_AD_UNIVERSAL_AD_IDS] = []
|
|
66
74
|
|
|
67
75
|
// Add additional properties for Linear Ads
|
|
68
|
-
if let
|
|
69
|
-
|
|
70
|
-
adData[PROP_AD_DURATION] = adDuration
|
|
71
|
-
}
|
|
76
|
+
if let adDuration = ad.duration {
|
|
77
|
+
adData[PROP_AD_DURATION] = adDuration
|
|
72
78
|
}
|
|
73
79
|
|
|
74
80
|
// Add additional properties for NonLinear Ads
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if let adClickThrough = nonLinearAd.clickThrough {
|
|
78
|
-
adData[PROP_AD_CLICK_THROUGH] = adClickThrough
|
|
79
|
-
}
|
|
81
|
+
if let adClickThrough = ad.clickThrough {
|
|
82
|
+
adData[PROP_AD_CLICK_THROUGH] = adClickThrough
|
|
80
83
|
}
|
|
81
|
-
#endif
|
|
82
84
|
|
|
83
85
|
// Add additional properties for GoogleIma Ads
|
|
84
86
|
if let googleImaAd = ad as? GoogleImaAd {
|
|
@@ -142,6 +144,8 @@ class THEOplayerRCTAdAdapter {
|
|
|
142
144
|
height: adData[PROP_GOOGLE_AD_HEIGHT] as? Int,
|
|
143
145
|
integration: THEOplayerRCTTypeUtils.adIntegrationKind((adData[PROP_AD_INTEGRATION] as? String) ?? ""),
|
|
144
146
|
duration: lround((adData[PROP_AD_DURATION] as? Double) ?? 0.0),
|
|
147
|
+
clickThrough: adData[PROP_AD_CLICK_THROUGH] as? String,
|
|
148
|
+
customIntegration: adData[PROP_AD_CUSTOM_INTEGRATION] as? String,
|
|
145
149
|
mediaFiles: [], // TODO
|
|
146
150
|
adSystem: adData[PROP_GOOGLE_AD_AD_SYSTEM] as? String,
|
|
147
151
|
creativeId: adData[PROP_GOOGLE_AD_CREATIVE_ID] as? String,
|
|
@@ -173,6 +177,8 @@ class THEOplayerRCTAdAdapter {
|
|
|
173
177
|
adBreakData[PROP_ADBREAK_MAX_DURATION] = adBreak.maxDuration
|
|
174
178
|
adBreakData[PROP_ADBREAK_TIME_OFFSET] = adBreak.timeOffset
|
|
175
179
|
adBreakData[PROP_ADBREAK_MAX_REMAINING_DURATION] = adBreak.maxRemainingDuration
|
|
180
|
+
adBreakData[PROP_ADBREAK_INTEGRATION] = adBreak.integration
|
|
181
|
+
adBreakData[PROP_ADBREAK_CUSTOM_INTEGRATION] = adBreak.customIntegration
|
|
176
182
|
// process adds when adbreak contains them
|
|
177
183
|
if !adBreak.ads.isEmpty {
|
|
178
184
|
var adList: [[String:Any]] = []
|
|
@@ -180,10 +186,6 @@ class THEOplayerRCTAdAdapter {
|
|
|
180
186
|
adList.append(THEOplayerRCTAdAdapter.fromAd(ad: ad, processAdBreak: false))
|
|
181
187
|
}
|
|
182
188
|
adBreakData[PROP_ADBREAK_ADS] = adList
|
|
183
|
-
if adList.count > 0,
|
|
184
|
-
let integration = adList[0][PROP_AD_INTEGRATION] {
|
|
185
|
-
adBreakData[PROP_ADBREAK_INTEGRATION] = integration
|
|
186
|
-
}
|
|
187
189
|
}
|
|
188
190
|
return adBreakData
|
|
189
191
|
}
|
|
@@ -205,7 +207,9 @@ class THEOplayerRCTAdAdapter {
|
|
|
205
207
|
return NativeAdBreak(ads: ads,
|
|
206
208
|
maxDuration: lround((adBreakData[PROP_ADBREAK_MAX_DURATION] as? Double) ?? 0),
|
|
207
209
|
maxRemainingDuration: (adBreakData[PROP_ADBREAK_MAX_REMAINING_DURATION] as? Double) ?? 0,
|
|
208
|
-
timeOffset: lround((adBreakData[PROP_ADBREAK_TIME_OFFSET] as? Double) ?? 0)
|
|
210
|
+
timeOffset: lround((adBreakData[PROP_ADBREAK_TIME_OFFSET] as? Double) ?? 0),
|
|
211
|
+
integration: THEOplayerRCTTypeUtils.adIntegrationKind((adBreakData[PROP_ADBREAK_INTEGRATION] as? String) ?? ""),
|
|
212
|
+
customIntegration: adBreakData[PROP_ADBREAK_CUSTOM_INTEGRATION] as? String)
|
|
209
213
|
}
|
|
210
214
|
|
|
211
215
|
class private func fromCompanionAds(companionAds: [CompanionAd?]) -> [[String:Any]] {
|
|
@@ -22,8 +22,14 @@ class NativeAd: THEOplayerSDK.Ad {
|
|
|
22
22
|
var height: Int? = nil
|
|
23
23
|
/** The kind of the ad integration.*/
|
|
24
24
|
var integration: THEOplayerSDK.AdIntegrationKind = THEOplayerSDK.AdIntegrationKind.defaultKind
|
|
25
|
+
/** The duration of the LinearAd, as provided by the VAST file, in seconds.*/
|
|
26
|
+
var duration: Int? = 0
|
|
27
|
+
/** The url that redirects to the website of the advertiser.*/
|
|
28
|
+
var clickThrough: String? = nil
|
|
29
|
+
/**The type of custom ad integration.*/
|
|
30
|
+
var customIntegration: String? = nil
|
|
25
31
|
|
|
26
|
-
init(adBreak: AdBreak? = nil, companions: [THEOplayerSDK.CompanionAd?], type: String, id: String? = nil, skipOffset: Int? = nil, resourceURI: String? = nil, width: Int? = nil, height: Int? = nil, integration: THEOplayerSDK.AdIntegrationKind) {
|
|
32
|
+
init(adBreak: AdBreak? = nil, companions: [THEOplayerSDK.CompanionAd?], type: String, id: String? = nil, skipOffset: Int? = nil, resourceURI: String? = nil, width: Int? = nil, height: Int? = nil, integration: THEOplayerSDK.AdIntegrationKind, duration: Int? = 0, clickThrough: String?, customIntegration: String?) {
|
|
27
33
|
self.adBreak = adBreak
|
|
28
34
|
self.companions = companions
|
|
29
35
|
self.type = type
|
|
@@ -33,18 +39,18 @@ class NativeAd: THEOplayerSDK.Ad {
|
|
|
33
39
|
self.width = width
|
|
34
40
|
self.height = height
|
|
35
41
|
self.integration = integration
|
|
42
|
+
self.duration = duration
|
|
43
|
+
self.clickThrough = clickThrough
|
|
44
|
+
self.customIntegration = customIntegration
|
|
36
45
|
}
|
|
37
46
|
}
|
|
38
47
|
|
|
39
48
|
class NativeLinearAd: NativeAd, THEOplayerSDK.LinearAd {
|
|
40
|
-
/** The duration of the LinearAd, as provided by the VAST file, in seconds.*/
|
|
41
|
-
var duration: Int? = 0
|
|
42
49
|
/** An array of mediafiles, which provides some meta data retrieved from the VAST file.*/
|
|
43
50
|
var mediaFiles: [THEOplayerSDK.MediaFile] = []
|
|
44
51
|
|
|
45
|
-
init(adBreak: AdBreak? = nil, companions: [THEOplayerSDK.CompanionAd?], type: String, id: String? = nil, skipOffset: Int? = nil, resourceURI: String? = nil, width: Int? = nil, height: Int? = nil, integration: THEOplayerSDK.AdIntegrationKind, duration: Int? = 0, mediaFiles: [THEOplayerSDK.MediaFile] = []) {
|
|
52
|
+
init(adBreak: AdBreak? = nil, companions: [THEOplayerSDK.CompanionAd?], type: String, id: String? = nil, skipOffset: Int? = nil, resourceURI: String? = nil, width: Int? = nil, height: Int? = nil, integration: THEOplayerSDK.AdIntegrationKind, duration: Int? = 0, clickThrough: String? = nil, customIntegration: String? = nil, mediaFiles: [THEOplayerSDK.MediaFile] = []) {
|
|
46
53
|
|
|
47
|
-
self.duration = duration
|
|
48
54
|
self.mediaFiles = mediaFiles
|
|
49
55
|
|
|
50
56
|
super.init(adBreak:adBreak,
|
|
@@ -55,7 +61,10 @@ class NativeLinearAd: NativeAd, THEOplayerSDK.LinearAd {
|
|
|
55
61
|
resourceURI: resourceURI,
|
|
56
62
|
width: width,
|
|
57
63
|
height: height,
|
|
58
|
-
integration: integration
|
|
64
|
+
integration: integration,
|
|
65
|
+
duration: duration,
|
|
66
|
+
clickThrough: clickThrough,
|
|
67
|
+
customIntegration: customIntegration)
|
|
59
68
|
}
|
|
60
69
|
}
|
|
61
70
|
|
|
@@ -77,7 +86,7 @@ class NativeLinearGoogleImaAd: NativeLinearAd, THEOplayerSDK.GoogleImaAd {
|
|
|
77
86
|
/** The String representing custom trafficking parameters from the VAST response.*/
|
|
78
87
|
var traffickingParameters: String = ""
|
|
79
88
|
|
|
80
|
-
init(adBreak: AdBreak? = nil, companions: [THEOplayerSDK.CompanionAd?], type: String, id: String? = nil, skipOffset: Int? = nil, resourceURI: String? = nil, width: Int? = nil, height: Int? = nil, integration: THEOplayerSDK.AdIntegrationKind, duration: Int? = 0, mediaFiles: [THEOplayerSDK.MediaFile] = [], adSystem: String? = nil, creativeId: String? = nil, wrapperAdIds: [String], wrapperAdSystems: [String], wrapperCreativeIds: [String], vastMediaBitrate: Int, universalAdIds: [UniversalAdId], traffickingParameters: String) {
|
|
89
|
+
init(adBreak: AdBreak? = nil, companions: [THEOplayerSDK.CompanionAd?], type: String, id: String? = nil, skipOffset: Int? = nil, resourceURI: String? = nil, width: Int? = nil, height: Int? = nil, integration: THEOplayerSDK.AdIntegrationKind, duration: Int? = 0, clickThrough: String? = nil, customIntegration: String? = nil, mediaFiles: [THEOplayerSDK.MediaFile] = [], adSystem: String? = nil, creativeId: String? = nil, wrapperAdIds: [String], wrapperAdSystems: [String], wrapperCreativeIds: [String], vastMediaBitrate: Int, universalAdIds: [UniversalAdId], traffickingParameters: String) {
|
|
81
90
|
self.adSystem = adSystem
|
|
82
91
|
self.creativeId = creativeId
|
|
83
92
|
self.wrapperAdIds = wrapperAdIds
|
|
@@ -97,6 +106,8 @@ class NativeLinearGoogleImaAd: NativeLinearAd, THEOplayerSDK.GoogleImaAd {
|
|
|
97
106
|
height: height,
|
|
98
107
|
integration:integration,
|
|
99
108
|
duration: duration,
|
|
109
|
+
clickThrough: clickThrough,
|
|
110
|
+
customIntegration: customIntegration,
|
|
100
111
|
mediaFiles: mediaFiles)
|
|
101
112
|
}
|
|
102
113
|
}
|
|
@@ -110,12 +121,18 @@ class NativeAdBreak: THEOplayerSDK.AdBreak {
|
|
|
110
121
|
var maxRemainingDuration: Double = -1
|
|
111
122
|
/** The time offset at which point the content will be paused to play the ad break, in seconds.*/
|
|
112
123
|
var timeOffset: Int = 0
|
|
124
|
+
/** The kind of the ad integration.*/
|
|
125
|
+
var integration: THEOplayerSDK.AdIntegrationKind = THEOplayerSDK.AdIntegrationKind.defaultKind
|
|
126
|
+
/**The type of custom ad integration.*/
|
|
127
|
+
var customIntegration: String? = nil
|
|
113
128
|
|
|
114
|
-
init(ads: [Ad], maxDuration: Int, maxRemainingDuration: Double, timeOffset: Int) {
|
|
129
|
+
init(ads: [Ad], maxDuration: Int, maxRemainingDuration: Double, timeOffset: Int, integration: THEOplayerSDK.AdIntegrationKind, customIntegration: String? = nil) {
|
|
115
130
|
self.ads = ads
|
|
116
131
|
self.maxDuration = maxDuration
|
|
117
132
|
self.maxRemainingDuration = maxRemainingDuration
|
|
118
133
|
self.timeOffset = timeOffset
|
|
134
|
+
self.integration = integration
|
|
135
|
+
self.customIntegration = customIntegration
|
|
119
136
|
}
|
|
120
137
|
}
|
|
121
138
|
|
|
@@ -17,6 +17,8 @@ let CACHE_EVENT_PROP_TASKS: String = "tasks"
|
|
|
17
17
|
let CACHE_TAG: String = "[CacheAPI]"
|
|
18
18
|
|
|
19
19
|
let ERROR_MESSAGE_CACHE_API_UNSUPPORTED_FEATURE = "Cache API is not supported for tvOS"
|
|
20
|
+
let ERROR_CODE_CREATE_CACHINGTASK_FAILED = "create_cachingtask_failure"
|
|
21
|
+
let ERROR_MESSAGE_CREATE_CACHINGTASK_FAILURE = "Creating a new cachingTask failed."
|
|
20
22
|
|
|
21
23
|
@objc(THEOplayerRCTCacheAPI)
|
|
22
24
|
class THEOplayerRCTCacheAPI: RCTEventEmitter {
|
|
@@ -140,15 +142,15 @@ class THEOplayerRCTCacheAPI: RCTEventEmitter {
|
|
|
140
142
|
] as [String : Any])
|
|
141
143
|
}
|
|
142
144
|
|
|
143
|
-
@objc(createTask:params:)
|
|
144
|
-
func createTask(_ src: NSDictionary, params: NSDictionary) -> Void {
|
|
145
|
+
@objc(createTask:params:resolver:rejecter:)
|
|
146
|
+
func createTask(_ src: NSDictionary, params: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
|
|
145
147
|
if DEBUG_CACHE_API { PrintUtils.printLog(logText: "[NATIVE] createTask triggered on Cache API.") }
|
|
146
148
|
let params = THEOplayerRCTCachingParametersBuilder.buildCachingParameters(params)
|
|
147
149
|
let (sourceDescription, _) = THEOplayerRCTSourceDescriptionBuilder.buildSourceDescription(src)
|
|
148
150
|
if let srcDescription = sourceDescription,
|
|
149
151
|
let newTask = THEOplayer.cache.createTask(source: srcDescription, parameters: params) {
|
|
150
152
|
if DEBUG_CACHE_API { PrintUtils.printLog(logText: "[NATIVE] New cache task created with id \(newTask.id)") }
|
|
151
|
-
|
|
153
|
+
resolve(THEOplayerRCTCacheAggregator.aggregateCacheTask(task: newTask))
|
|
152
154
|
// emit onAddCachingTaskEvent
|
|
153
155
|
self.sendEvent(withName: "onAddCachingTaskEvent", body: [
|
|
154
156
|
CACHE_EVENT_PROP_TASK: THEOplayerRCTCacheAggregator.aggregateCacheTask(task: newTask)
|
|
@@ -156,6 +158,8 @@ class THEOplayerRCTCacheAPI: RCTEventEmitter {
|
|
|
156
158
|
|
|
157
159
|
// attach the state and progress listeners to the new task
|
|
158
160
|
self.attachTaskListenersToTask(newTask)
|
|
161
|
+
} else {
|
|
162
|
+
reject(ERROR_CODE_CREATE_CACHINGTASK_FAILED, ERROR_MESSAGE_CREATE_CACHINGTASK_FAILURE, nil)
|
|
159
163
|
}
|
|
160
164
|
}
|
|
161
165
|
|
|
@@ -41,7 +41,7 @@ class THEOplayerRCTCacheAggregator {
|
|
|
41
41
|
aggregatedData[CACHETASK_PROP_ID] = task.id
|
|
42
42
|
aggregatedData[CACHETASK_PROP_STATUS] = THEOplayerRCTTypeUtils.cachingTaskStatusToString(task.status)
|
|
43
43
|
aggregatedData[CACHETASK_PROP_PARAMETERS] = THEOplayerRCTCacheAggregator.aggregateCacheTaskParameters(params: task.parameters)
|
|
44
|
-
aggregatedData[CACHETASK_PROP_SOURCE] = THEOplayerRCTSourceDescriptionAggregator.aggregateCacheTaskSourceDescription(sourceDescription: task.source)
|
|
44
|
+
aggregatedData[CACHETASK_PROP_SOURCE] = THEOplayerRCTSourceDescriptionAggregator.aggregateCacheTaskSourceDescription(sourceDescription: task.source, cachingTaskId: task.id)
|
|
45
45
|
for (key, value) in THEOplayerRCTCacheAggregator.aggregateCacheTaskProgress(task: task) {
|
|
46
46
|
aggregatedData[key] = value
|
|
47
47
|
}
|
package/package.json
CHANGED
|
@@ -32,23 +32,23 @@ Pod::Spec.new do |s|
|
|
|
32
32
|
s.dependency "React-Core"
|
|
33
33
|
|
|
34
34
|
# THEOplayer core Dependency
|
|
35
|
-
s.dependency "THEOplayerSDK-core", "~> 7.
|
|
35
|
+
s.dependency "THEOplayerSDK-core", "~> 7.8"
|
|
36
36
|
|
|
37
37
|
if theofeatures.include?("GOOGLE_IMA")
|
|
38
38
|
puts "Adding THEOplayer-Integration-GoogleIMA"
|
|
39
|
-
s.dependency "THEOplayer-Integration-GoogleIMA/Base", "~> 7.
|
|
40
|
-
s.dependency "THEOplayer-Integration-GoogleIMA/Dependencies", "~> 7.
|
|
39
|
+
s.dependency "THEOplayer-Integration-GoogleIMA/Base", "~> 7.8"
|
|
40
|
+
s.dependency "THEOplayer-Integration-GoogleIMA/Dependencies", "~> 7.8"
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
if theofeatures.include?("CHROMECAST")
|
|
44
44
|
puts "Adding THEOplayer-Integration-GoogleCast"
|
|
45
|
-
s.ios.dependency "THEOplayer-Integration-GoogleCast/Base", "~> 7.
|
|
45
|
+
s.ios.dependency "THEOplayer-Integration-GoogleCast/Base", "~> 7.8"
|
|
46
46
|
s.ios.dependency "google-cast-sdk-dynamic-xcframework", "~> 4.8"
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
if theofeatures.include?("SIDELOADED_TEXTTRACKS")
|
|
50
50
|
puts "Adding THEOplayer-Connector-SideloadedSubtitle"
|
|
51
|
-
s.dependency "THEOplayer-Connector-SideloadedSubtitle", "~> 7.
|
|
51
|
+
s.dependency "THEOplayer-Connector-SideloadedSubtitle", "~> 7.8"
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
end
|