bitmovin-player-react-native 0.3.1 → 0.5.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/README.md +486 -24
- package/RNBitmovinPlayer.podspec +5 -1
- package/android/build.gradle +8 -5
- package/android/src/main/java/com/bitmovin/player/reactnative/AnalyticsModule.kt +154 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/DrmModule.kt +4 -5
- package/android/src/main/java/com/bitmovin/player/reactnative/PlayerModule.kt +41 -5
- package/android/src/main/java/com/bitmovin/player/reactnative/RNPlayerView.kt +318 -2
- package/android/src/main/java/com/bitmovin/player/reactnative/RNPlayerViewManager.kt +70 -9
- package/android/src/main/java/com/bitmovin/player/reactnative/RNPlayerViewPackage.kt +3 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/SourceModule.kt +4 -5
- package/android/src/main/java/com/bitmovin/player/reactnative/UuidModule.kt +3 -1
- package/android/src/main/java/com/bitmovin/player/reactnative/converter/JsonConverter.kt +389 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/extensions/Any.kt +27 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/extensions/ReactContextExtension.kt +8 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/extensions/ReadableArray.kt +19 -2
- package/android/src/main/java/com/bitmovin/player/reactnative/extensions/String.kt +8 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/extensions/WritableMap.kt +19 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/ui/FullscreenHandlerBridge.kt +37 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/ui/FullscreenHandlerModule.kt +73 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/ui/RNPictureInPictureHandler.kt +191 -0
- package/ios/AnalyticsModule.m +14 -0
- package/ios/AnalyticsModule.swift +180 -0
- package/ios/AudioSessionModule.m +10 -0
- package/ios/AudioSessionModule.swift +65 -0
- package/ios/Event+JSON.swift +134 -0
- package/ios/FullscreenHandlerBridge.swift +33 -0
- package/ios/FullscreenHandlerModule.m +9 -0
- package/ios/FullscreenHandlerModule.swift +71 -0
- package/ios/PlayerModule.m +6 -0
- package/ios/PlayerModule.swift +44 -0
- package/ios/RCTConvert+BitmovinPlayer.swift +382 -0
- package/ios/RNPlayerView+PlayerListener.swift +56 -0
- package/ios/RNPlayerView+UserInterfaceListener.swift +35 -0
- package/ios/RNPlayerView.swift +22 -0
- package/ios/RNPlayerViewManager.m +24 -1
- package/ios/RNPlayerViewManager.swift +23 -1
- package/lib/index.d.ts +1013 -150
- package/lib/index.js +251 -48
- package/lib/index.mjs +231 -34
- package/package.json +1 -1
- package/src/advertising.ts +155 -0
- package/src/analytics/collector.ts +97 -0
- package/src/analytics/config.ts +218 -0
- package/src/analytics/index.ts +2 -0
- package/src/audioSession.ts +47 -0
- package/src/components/PlayerView/events.ts +49 -3
- package/src/components/PlayerView/index.tsx +68 -11
- package/src/components/PlayerView/native.ts +4 -1
- package/src/events.ts +255 -0
- package/src/index.ts +4 -0
- package/src/media.ts +33 -0
- package/src/player.ts +57 -1
- package/src/source.ts +4 -0
- package/src/styleConfig.ts +87 -0
- package/src/ui/fullscreenhandler.ts +19 -0
- package/src/ui/fullscreenhandlerbridge.ts +59 -0
package/ios/Event+JSON.swift
CHANGED
|
@@ -161,3 +161,137 @@ extension SubtitleChangedEvent {
|
|
|
161
161
|
]
|
|
162
162
|
}
|
|
163
163
|
}
|
|
164
|
+
|
|
165
|
+
extension AdBreakFinishedEvent {
|
|
166
|
+
func toJSON() -> [AnyHashable: Any] {
|
|
167
|
+
[
|
|
168
|
+
"name": name,
|
|
169
|
+
"timestamp": timestamp,
|
|
170
|
+
"adBreak": RCTConvert.toJson(adBreak: adBreak)
|
|
171
|
+
]
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
extension AdBreakStartedEvent {
|
|
176
|
+
func toJSON() -> [AnyHashable: Any] {
|
|
177
|
+
[
|
|
178
|
+
"name": name,
|
|
179
|
+
"timestamp": timestamp,
|
|
180
|
+
"adBreak": RCTConvert.toJson(adBreak: adBreak)
|
|
181
|
+
]
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
extension AdClickedEvent {
|
|
186
|
+
func toJSON() -> [AnyHashable: Any] {
|
|
187
|
+
[
|
|
188
|
+
"name": name,
|
|
189
|
+
"timestamp": timestamp,
|
|
190
|
+
"clickThroughUrl": clickThroughUrl
|
|
191
|
+
]
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
extension AdErrorEvent {
|
|
196
|
+
func toJSON() -> [AnyHashable: Any] {
|
|
197
|
+
[
|
|
198
|
+
"name": name,
|
|
199
|
+
"timestamp": timestamp,
|
|
200
|
+
"adConfig": RCTConvert.toJson(adConfig: adConfig),
|
|
201
|
+
"adItem": RCTConvert.toJson(adItem: adItem),
|
|
202
|
+
"code": code,
|
|
203
|
+
"message": message
|
|
204
|
+
]
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
extension AdFinishedEvent {
|
|
209
|
+
func toJSON() -> [AnyHashable: Any] {
|
|
210
|
+
[
|
|
211
|
+
"name": name,
|
|
212
|
+
"timestamp": timestamp,
|
|
213
|
+
"ad": RCTConvert.toJson(ad: ad)
|
|
214
|
+
]
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
extension AdManifestLoadEvent {
|
|
219
|
+
func toJSON() -> [AnyHashable: Any] {
|
|
220
|
+
[
|
|
221
|
+
"name": name,
|
|
222
|
+
"timestamp": timestamp,
|
|
223
|
+
"adBreak": RCTConvert.toJson(adBreak: adBreak),
|
|
224
|
+
"adConfig": RCTConvert.toJson(adConfig: adConfig)
|
|
225
|
+
]
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
extension AdManifestLoadedEvent {
|
|
230
|
+
func toJSON() -> [AnyHashable: Any] {
|
|
231
|
+
[
|
|
232
|
+
"name": name,
|
|
233
|
+
"timestamp": timestamp,
|
|
234
|
+
"adBreak": RCTConvert.toJson(adBreak: adBreak),
|
|
235
|
+
"adConfig": RCTConvert.toJson(adConfig: adConfig),
|
|
236
|
+
"downloadTime": downloadTime
|
|
237
|
+
]
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
extension AdQuartileEvent {
|
|
242
|
+
func toJSON() -> [AnyHashable: Any] {
|
|
243
|
+
[
|
|
244
|
+
"name": name,
|
|
245
|
+
"timestamp": timestamp,
|
|
246
|
+
"quartile": RCTConvert.toJson(adQuartile: adQuartile)
|
|
247
|
+
]
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
extension AdScheduledEvent {
|
|
252
|
+
func toJSON() -> [AnyHashable: Any] {
|
|
253
|
+
[
|
|
254
|
+
"name": name,
|
|
255
|
+
"timestamp": timestamp,
|
|
256
|
+
"numberOfAds": numberOfAds
|
|
257
|
+
]
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
extension AdSkippedEvent {
|
|
262
|
+
func toJSON() -> [AnyHashable: Any] {
|
|
263
|
+
[
|
|
264
|
+
"name": name,
|
|
265
|
+
"timestamp": timestamp,
|
|
266
|
+
"ad": RCTConvert.toJson(ad: ad)
|
|
267
|
+
]
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
extension AdStartedEvent {
|
|
272
|
+
func toJSON() -> [AnyHashable: Any] {
|
|
273
|
+
[
|
|
274
|
+
"name": name,
|
|
275
|
+
"timestamp": timestamp,
|
|
276
|
+
"ad": RCTConvert.toJson(ad: ad),
|
|
277
|
+
"clickThroughUrl": clickThroughUrl?.absoluteString,
|
|
278
|
+
"clientType": RCTConvert.toJson(adSourceType: clientType),
|
|
279
|
+
"duration": duration,
|
|
280
|
+
"indexInQueue": indexInQueue,
|
|
281
|
+
"position": position,
|
|
282
|
+
"skipOffset": skipOffset,
|
|
283
|
+
"timeOffset": timeOffset
|
|
284
|
+
]
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
extension VideoDownloadQualityChangedEvent {
|
|
289
|
+
func toJSON() -> [AnyHashable: Any] {
|
|
290
|
+
[
|
|
291
|
+
"newVideoQuality": RCTConvert.toJson(videoQuality: videoQualityNew),
|
|
292
|
+
"oldVideoQuality": RCTConvert.toJson(videoQuality: videoQualityOld),
|
|
293
|
+
"name": name,
|
|
294
|
+
"timestamp": timestamp
|
|
295
|
+
]
|
|
296
|
+
}
|
|
297
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import BitmovinPlayer
|
|
2
|
+
|
|
3
|
+
class FullscreenHandlerBridge: NSObject, FullscreenHandler {
|
|
4
|
+
var isFullscreen = false
|
|
5
|
+
|
|
6
|
+
private let nativeId: NativeId
|
|
7
|
+
private let bridge: RCTBridge
|
|
8
|
+
|
|
9
|
+
init(_ nativeId: NativeId, bridge: RCTBridge) {
|
|
10
|
+
self.nativeId = nativeId
|
|
11
|
+
self.bridge = bridge
|
|
12
|
+
super.init()
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
func onFullscreenRequested() {
|
|
16
|
+
guard let fullscreenHandlerModule = getFullscreenHandlerModule() else {
|
|
17
|
+
return
|
|
18
|
+
}
|
|
19
|
+
fullscreenHandlerModule.onFullscreenRequested(nativeId: nativeId)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
func onFullscreenExitRequested() {
|
|
23
|
+
guard let fullscreenHandlerModule = getFullscreenHandlerModule() else {
|
|
24
|
+
return
|
|
25
|
+
}
|
|
26
|
+
fullscreenHandlerModule.onFullscreenExitRequested(nativeId: nativeId)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/// Fetches the initialized `FullscreenHandlerModule` instance on RN's bridge object.
|
|
30
|
+
private func getFullscreenHandlerModule() -> FullscreenHandlerModule? {
|
|
31
|
+
bridge.module(for: FullscreenHandlerModule.self) as? FullscreenHandlerModule
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#import <React/RCTBridgeModule.h>
|
|
2
|
+
|
|
3
|
+
@interface RCT_EXTERN_REMAP_MODULE(FullscreenHandlerModule, FullscreenHandlerModule, NSObject)
|
|
4
|
+
|
|
5
|
+
RCT_EXTERN_METHOD(destroy:(NSString *)nativeId)
|
|
6
|
+
|
|
7
|
+
RCT_EXTERN__BLOCKING_SYNCHRONOUS_METHOD(onFullscreenChanged:(NSString *)nativeId isFullscreenEnabled:(BOOL)isFullscreenEnabled)
|
|
8
|
+
RCT_EXTERN_METHOD(registerHandler:(NSString *)nativeId)
|
|
9
|
+
@end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import BitmovinPlayer
|
|
2
|
+
|
|
3
|
+
@objc(FullscreenHandlerModule)
|
|
4
|
+
class FullscreenHandlerModule: NSObject, RCTBridgeModule {
|
|
5
|
+
/// React bridge reference.
|
|
6
|
+
@objc var bridge: RCTBridge!
|
|
7
|
+
|
|
8
|
+
/// JS module name.
|
|
9
|
+
static func moduleName() -> String! {
|
|
10
|
+
"FullscreenHandlerModule"
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/// Module requires main thread initialization.
|
|
14
|
+
static func requiresMainQueueSetup() -> Bool {
|
|
15
|
+
true
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/// Use `UIManager.addBlock` to enqueue module methods on UI thread.
|
|
19
|
+
var methodQueue: DispatchQueue! {
|
|
20
|
+
bridge.uiManager.methodQueue
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/// In-memory mapping from `nativeId`s to `FullscreenHandler` instances.
|
|
24
|
+
private var fullscreenHandlers: Registry<FullscreenHandlerBridge> = [:]
|
|
25
|
+
|
|
26
|
+
/// Dispatch group used for blocking thread while waiting for state change
|
|
27
|
+
private let fullscreenChangeDispatchGroup = DispatchGroup()
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
Fetches the `FullscreenHandlerBridge` instance associated with `nativeId` from internal fullscreenHandlers.
|
|
31
|
+
- Parameter nativeId: `FullscreenHandlerBridge` instance ID.
|
|
32
|
+
- Returns: The associated `FullscreenHandlerBridge` instance or `nil`.
|
|
33
|
+
*/
|
|
34
|
+
@objc func retrieve(_ nativeId: NativeId) -> FullscreenHandlerBridge? {
|
|
35
|
+
fullscreenHandlers[nativeId]
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
Removes the `FullscreenHandlerBridge` instance associated with `nativeId` from `fullscreenHandlers`.
|
|
40
|
+
- Parameter nativeId Instance to be disposed.
|
|
41
|
+
*/
|
|
42
|
+
@objc(destroy:)
|
|
43
|
+
func destroy(_ nativeId: NativeId) {
|
|
44
|
+
fullscreenHandlers.removeValue(forKey: nativeId)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@objc(onFullscreenChanged:isFullscreenEnabled:)
|
|
48
|
+
func onFullscreenChanged(_ nativeId: NativeId, isFullscreenEnabled: Bool) -> Any? {
|
|
49
|
+
fullscreenHandlers[nativeId]?.isFullscreen = isFullscreenEnabled
|
|
50
|
+
fullscreenChangeDispatchGroup.leave()
|
|
51
|
+
return nil
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@objc(registerHandler:)
|
|
55
|
+
func registerHandler(_ nativeId: NativeId) {
|
|
56
|
+
guard fullscreenHandlers[nativeId] == nil else { return }
|
|
57
|
+
fullscreenHandlers[nativeId] = FullscreenHandlerBridge(nativeId, bridge: bridge)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
func onFullscreenRequested(nativeId: NativeId) {
|
|
61
|
+
fullscreenChangeDispatchGroup.enter()
|
|
62
|
+
bridge.enqueueJSCall("FullscreenBridge-\(nativeId)", method: "enterFullscreen", args: []) {}
|
|
63
|
+
fullscreenChangeDispatchGroup.wait()
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
func onFullscreenExitRequested(nativeId: NativeId) {
|
|
67
|
+
fullscreenChangeDispatchGroup.enter()
|
|
68
|
+
bridge.enqueueJSCall("FullscreenBridge-\(nativeId)", method: "exitFullscreen", args: []) {}
|
|
69
|
+
fullscreenChangeDispatchGroup.wait()
|
|
70
|
+
}
|
|
71
|
+
}
|
package/ios/PlayerModule.m
CHANGED
|
@@ -53,5 +53,11 @@ RCT_EXTERN_METHOD(
|
|
|
53
53
|
getAvailableSubtitles:(NSString *)nativeId
|
|
54
54
|
resolver:(RCTPromiseResolveBlock)resolve
|
|
55
55
|
rejecter:(RCTPromiseRejectBlock)reject)
|
|
56
|
+
RCT_EXTERN_METHOD(scheduleAd:(NSString *)nativeId adItemJson:(nullable id)adItemJson)
|
|
57
|
+
RCT_EXTERN_METHOD(skipAd:(NSString *)nativeId)
|
|
58
|
+
RCT_EXTERN_METHOD(
|
|
59
|
+
isAd:(NSString *)nativeId
|
|
60
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
61
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
56
62
|
|
|
57
63
|
@end
|
package/ios/PlayerModule.swift
CHANGED
|
@@ -346,4 +346,48 @@ class PlayerModule: NSObject, RCTBridgeModule {
|
|
|
346
346
|
resolve(subtitlesJson ?? [])
|
|
347
347
|
}
|
|
348
348
|
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
Schedules an `AdItem` in the `nativeId`'s associated player.
|
|
352
|
+
- Parameter nativeId: Target player id.
|
|
353
|
+
- Parameter adItemJson: Json representation of the `AdItem` to be scheduled.
|
|
354
|
+
*/
|
|
355
|
+
@objc(scheduleAd:adItemJson:)
|
|
356
|
+
func scheduleAd(_ nativeId: NativeId, adItemJson: Any?) {
|
|
357
|
+
guard let adItem = RCTConvert.adItem(adItemJson) else {
|
|
358
|
+
return
|
|
359
|
+
}
|
|
360
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
361
|
+
self?.players[nativeId]?.scheduleAd(adItem: adItem)
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
Skips the current ad in `nativeId`'s associated player.
|
|
367
|
+
Has no effect if the current ad is not skippable or if no ad is being played back.
|
|
368
|
+
- Parameter nativeId: Target player id.
|
|
369
|
+
*/
|
|
370
|
+
@objc(skipAd:)
|
|
371
|
+
func skipAd(_ nativeId: NativeId) {
|
|
372
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
373
|
+
self?.players[nativeId]?.skipAd()
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
Returns `true` while an ad is being played back or when main content playback has been paused for ad playback.
|
|
379
|
+
- Parameter nativeId: Target player id.
|
|
380
|
+
- Parameter resolver: JS promise resolver.
|
|
381
|
+
- Parameter rejecter: JS promise rejecter.
|
|
382
|
+
*/
|
|
383
|
+
@objc(isAd:resolver:rejecter:)
|
|
384
|
+
func isAd(
|
|
385
|
+
_ nativeId: NativeId,
|
|
386
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
387
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
388
|
+
) {
|
|
389
|
+
bridge.uiManager.addUIBlock { [weak self] _, _ in
|
|
390
|
+
resolve(self?.players[nativeId]?.isAd)
|
|
391
|
+
}
|
|
392
|
+
}
|
|
349
393
|
}
|