bitmovin-player-react-native 0.4.0 → 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 +249 -1
- package/RNBitmovinPlayer.podspec +3 -1
- package/android/build.gradle +3 -2
- package/android/src/main/java/com/bitmovin/player/reactnative/AnalyticsModule.kt +154 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/RNPlayerView.kt +45 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/RNPlayerViewManager.kt +25 -4
- package/android/src/main/java/com/bitmovin/player/reactnative/RNPlayerViewPackage.kt +3 -0
- package/android/src/main/java/com/bitmovin/player/reactnative/converter/JsonConverter.kt +172 -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/String.kt +8 -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/ios/AnalyticsModule.m +14 -0
- package/ios/AnalyticsModule.swift +180 -0
- package/ios/Event+JSON.swift +11 -0
- package/ios/FullscreenHandlerBridge.swift +33 -0
- package/ios/FullscreenHandlerModule.m +9 -0
- package/ios/FullscreenHandlerModule.swift +71 -0
- package/ios/RCTConvert+BitmovinPlayer.swift +174 -0
- package/ios/RNPlayerView+PlayerListener.swift +5 -1
- package/ios/RNPlayerView+UserInterfaceListener.swift +16 -0
- package/ios/RNPlayerView.swift +5 -0
- package/ios/RNPlayerViewManager.m +6 -0
- package/ios/RNPlayerViewManager.swift +21 -0
- package/lib/index.d.ts +498 -51
- package/lib/index.js +186 -42
- package/lib/index.mjs +167 -26
- package/package.json +1 -1
- package/src/analytics/collector.ts +97 -0
- package/src/analytics/config.ts +218 -0
- package/src/analytics/index.ts +2 -0
- package/src/components/PlayerView/events.ts +10 -0
- package/src/components/PlayerView/index.tsx +38 -1
- package/src/components/PlayerView/native.ts +4 -1
- package/src/events.ts +43 -0
- package/src/index.ts +2 -0
- package/src/media.ts +33 -0
- package/src/player.ts +21 -0
- 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
|
@@ -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
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import Foundation
|
|
2
2
|
import BitmovinPlayer
|
|
3
|
+
import BitmovinAnalyticsCollector
|
|
3
4
|
|
|
4
5
|
extension RCTConvert {
|
|
5
6
|
/**
|
|
@@ -18,6 +19,9 @@ extension RCTConvert {
|
|
|
18
19
|
if let playbackConfig = RCTConvert.playbackConfig(json["playbackConfig"]) {
|
|
19
20
|
playerConfig.playbackConfig = playbackConfig
|
|
20
21
|
}
|
|
22
|
+
if let styleConfig = RCTConvert.styleConfig(json["styleConfig"]) {
|
|
23
|
+
playerConfig.styleConfig = styleConfig
|
|
24
|
+
}
|
|
21
25
|
if let tweaksConfig = RCTConvert.tweaksConfig(json["tweaksConfig"]) {
|
|
22
26
|
playerConfig.tweaksConfig = tweaksConfig
|
|
23
27
|
}
|
|
@@ -55,6 +59,46 @@ extension RCTConvert {
|
|
|
55
59
|
return playbackConfig
|
|
56
60
|
}
|
|
57
61
|
|
|
62
|
+
/**
|
|
63
|
+
Utility method to instantiate a `StyleConfig` from a JS object.
|
|
64
|
+
- Parameter json: JS object.
|
|
65
|
+
- Returns: The produced `StyleConfig` object.
|
|
66
|
+
*/
|
|
67
|
+
static func styleConfig(_ json: Any?) -> StyleConfig? {
|
|
68
|
+
guard let json = json as? [String: Any?] else {
|
|
69
|
+
return nil
|
|
70
|
+
}
|
|
71
|
+
let styleConfig = StyleConfig()
|
|
72
|
+
if let isUiEnabled = json["isUiEnabled"] as? Bool {
|
|
73
|
+
styleConfig.isUiEnabled = isUiEnabled
|
|
74
|
+
}
|
|
75
|
+
#if !os(tvOS)
|
|
76
|
+
if let playerUiCss = json["playerUiCss"] as? String {
|
|
77
|
+
styleConfig.playerUiCss = RCTConvert.nsurl(playerUiCss)
|
|
78
|
+
}
|
|
79
|
+
if let supplementalPlayerUiCss = json["supplementalPlayerUiCss"] as? String {
|
|
80
|
+
styleConfig.supplementalPlayerUiCss = RCTConvert.nsurl(supplementalPlayerUiCss)
|
|
81
|
+
}
|
|
82
|
+
if let playerUiJs = json["playerUiJs"] as? String {
|
|
83
|
+
styleConfig.playerUiJs = RCTConvert.nsurl(playerUiJs)
|
|
84
|
+
}
|
|
85
|
+
#endif
|
|
86
|
+
if let scalingMode = json["scalingMode"] as? String {
|
|
87
|
+
switch scalingMode {
|
|
88
|
+
case "Fit":
|
|
89
|
+
styleConfig.scalingMode = .fit
|
|
90
|
+
case "Stretch":
|
|
91
|
+
styleConfig.scalingMode = .stretch
|
|
92
|
+
case "Zoom":
|
|
93
|
+
styleConfig.scalingMode = .zoom
|
|
94
|
+
default:
|
|
95
|
+
styleConfig.scalingMode = .fit
|
|
96
|
+
break
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return styleConfig
|
|
100
|
+
}
|
|
101
|
+
|
|
58
102
|
/**
|
|
59
103
|
Utility method to instantiate a `TweaksConfig` from a JS object.
|
|
60
104
|
- Parameter json: JS object.
|
|
@@ -202,6 +246,9 @@ extension RCTConvert {
|
|
|
202
246
|
}
|
|
203
247
|
}
|
|
204
248
|
}
|
|
249
|
+
if let thumbnailTrack = json["thumbnailTrack"] as? String {
|
|
250
|
+
sourceConfig.thumbnailTrack = RCTConvert.thumbnailTrack(thumbnailTrack)
|
|
251
|
+
}
|
|
205
252
|
return sourceConfig
|
|
206
253
|
}
|
|
207
254
|
|
|
@@ -266,6 +313,25 @@ extension RCTConvert {
|
|
|
266
313
|
return fairplayConfig
|
|
267
314
|
}
|
|
268
315
|
|
|
316
|
+
/**
|
|
317
|
+
Utility method to get a `ThumbnailTrack` instance from a JS object.
|
|
318
|
+
- Parameter url: String.
|
|
319
|
+
- Returns: The generated `ThumbnailTrack`.
|
|
320
|
+
*/
|
|
321
|
+
static func thumbnailTrack(_ url: String?) -> ThumbnailTrack? {
|
|
322
|
+
guard
|
|
323
|
+
let url = RCTConvert.nsurl(url)
|
|
324
|
+
else {
|
|
325
|
+
return nil
|
|
326
|
+
}
|
|
327
|
+
return ThumbnailTrack(
|
|
328
|
+
url: url,
|
|
329
|
+
label: "Thumbnails",
|
|
330
|
+
identifier: UUID().uuidString,
|
|
331
|
+
isDefaultTrack: false
|
|
332
|
+
)
|
|
333
|
+
}
|
|
334
|
+
|
|
269
335
|
/**
|
|
270
336
|
Utility method to get a `SubtitleTrack` instance from a JS object.
|
|
271
337
|
- Parameter json: JS object.
|
|
@@ -482,4 +548,112 @@ extension RCTConvert {
|
|
|
482
548
|
"minBitrate": adData.minBitrate
|
|
483
549
|
]
|
|
484
550
|
}
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
Utility method to get a `BitmovinAnalyticsConfig` value from a JS object.
|
|
554
|
+
- Parameter json: JS object.
|
|
555
|
+
- Returns: The associated `BitmovinAnalyticsConfig` value or nil.
|
|
556
|
+
*/
|
|
557
|
+
static func analyticsConfig(_ json: Any?) -> BitmovinAnalyticsConfig? {
|
|
558
|
+
guard
|
|
559
|
+
let json = json as? [String: Any?],
|
|
560
|
+
let key = json["key"] as? String
|
|
561
|
+
else {
|
|
562
|
+
return nil
|
|
563
|
+
}
|
|
564
|
+
let config: BitmovinAnalyticsConfig
|
|
565
|
+
if let playerKey = json["playerKey"] as? String {
|
|
566
|
+
config = BitmovinAnalyticsConfig(key: key, playerKey: playerKey)
|
|
567
|
+
} else {
|
|
568
|
+
config = BitmovinAnalyticsConfig(key: key)
|
|
569
|
+
}
|
|
570
|
+
if let cdnProvider = json["cdnProvider"] as? String {
|
|
571
|
+
config.cdnProvider = cdnProvider
|
|
572
|
+
}
|
|
573
|
+
if let customerUserId = json["customUserId"] as? String {
|
|
574
|
+
config.customerUserId = customerUserId
|
|
575
|
+
}
|
|
576
|
+
if let experimentName = json["experimentName"] as? String {
|
|
577
|
+
config.experimentName = experimentName
|
|
578
|
+
}
|
|
579
|
+
if let videoId = json["videoId"] as? String {
|
|
580
|
+
config.videoId = videoId
|
|
581
|
+
}
|
|
582
|
+
if let title = json["title"] as? String {
|
|
583
|
+
config.title = title
|
|
584
|
+
}
|
|
585
|
+
if let path = json["path"] as? String {
|
|
586
|
+
config.path = path
|
|
587
|
+
}
|
|
588
|
+
if let isLive = json["isLive"] as? Bool {
|
|
589
|
+
config.isLive = isLive
|
|
590
|
+
}
|
|
591
|
+
if let ads = json["ads"] as? Bool {
|
|
592
|
+
config.ads = ads
|
|
593
|
+
}
|
|
594
|
+
if let randomizeUserId = json["randomizeUserId"] as? Bool {
|
|
595
|
+
config.randomizeUserId = randomizeUserId
|
|
596
|
+
}
|
|
597
|
+
for n in 1..<30 {
|
|
598
|
+
if let customDataN = json["customData\(n)"] as? String {
|
|
599
|
+
config.setValue(customDataN, forKey: "customData\(n)")
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
return config
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
/**
|
|
606
|
+
Utility method to get an analytics `CustomData` value from a JS object.
|
|
607
|
+
- Parameter json: JS object.
|
|
608
|
+
- Returns: The associated `CustomData` value or nil.
|
|
609
|
+
*/
|
|
610
|
+
static func analyticsCustomData(_ json: Any?) -> CustomData? {
|
|
611
|
+
guard let json = json as? [String: Any?] else {
|
|
612
|
+
return nil
|
|
613
|
+
}
|
|
614
|
+
let customData = CustomData()
|
|
615
|
+
for n in 1..<30 {
|
|
616
|
+
if let customDataN = json["customData\(n)"] as? String {
|
|
617
|
+
customData.setValue(customDataN, forKey: "customData\(n)")
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
return customData
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
/**
|
|
624
|
+
Utility method to get a JS value from a `CustomData` object.
|
|
625
|
+
- Parameter analyticsCustomData: Analytics custom data object.
|
|
626
|
+
- Returns: The JS value representing the given object.
|
|
627
|
+
*/
|
|
628
|
+
static func toJson(analyticsCustomData: CustomData?) -> [String: Any?]? {
|
|
629
|
+
guard let analyticsCustomData = analyticsCustomData else {
|
|
630
|
+
return nil
|
|
631
|
+
}
|
|
632
|
+
var json: [String: Any?] = [:]
|
|
633
|
+
for n in 1..<30 {
|
|
634
|
+
if let customDataN = analyticsCustomData.value(forKey: "customData\(n)") {
|
|
635
|
+
json["customData\(n)"] = customDataN
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
return json
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
/**
|
|
642
|
+
Utility method to compute a JS value from a `VideoQuality` object.
|
|
643
|
+
- Parameter videoQuality `VideoQuality` object to be converted.
|
|
644
|
+
- Returns: The produced JS object.
|
|
645
|
+
*/
|
|
646
|
+
static func toJson(videoQuality: VideoQuality?) -> [String: Any?]? {
|
|
647
|
+
guard let videoQuality = videoQuality else {
|
|
648
|
+
return nil
|
|
649
|
+
}
|
|
650
|
+
return [
|
|
651
|
+
"id": videoQuality.identifier,
|
|
652
|
+
"label": videoQuality.label,
|
|
653
|
+
"height": videoQuality.height,
|
|
654
|
+
"width": videoQuality.width,
|
|
655
|
+
"codec": videoQuality.codec,
|
|
656
|
+
"bitrate": videoQuality.bitrate,
|
|
657
|
+
]
|
|
658
|
+
}
|
|
485
659
|
}
|
|
@@ -56,7 +56,7 @@ extension RNPlayerView: PlayerListener {
|
|
|
56
56
|
func onSeeked(_ event: SeekedEvent, player: Player) {
|
|
57
57
|
onSeeked?(event.toJSON())
|
|
58
58
|
}
|
|
59
|
-
|
|
59
|
+
|
|
60
60
|
func onStallStarted(_ event: StallStartedEvent, player: Player) {
|
|
61
61
|
onStallStarted?(event.toJSON())
|
|
62
62
|
}
|
|
@@ -144,4 +144,8 @@ extension RNPlayerView: PlayerListener {
|
|
|
144
144
|
func onAdStarted(_ event: AdStartedEvent, player: Player) {
|
|
145
145
|
onAdStarted?(event.toJSON())
|
|
146
146
|
}
|
|
147
|
+
|
|
148
|
+
func onVideoPlaybackQualityChanged(_ event: VideoDownloadQualityChangedEvent, player: Player) {
|
|
149
|
+
onVideoPlaybackQualityChanged?(event.toJSON())
|
|
150
|
+
}
|
|
147
151
|
}
|
|
@@ -16,4 +16,20 @@ extension RNPlayerView: UserInterfaceListener {
|
|
|
16
16
|
func onPictureInPictureExited(_ event: PictureInPictureExitedEvent, view: PlayerView) {
|
|
17
17
|
onPictureInPictureExited?(event.toJSON())
|
|
18
18
|
}
|
|
19
|
+
|
|
20
|
+
func onFullscreenEnter(_ event: FullscreenEnterEvent, view: PlayerView) {
|
|
21
|
+
onFullscreenEnter?(event.toJSON())
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
func onFullscreenExit(_ event: FullscreenExitEvent, view: PlayerView) {
|
|
25
|
+
onFullscreenExit?(event.toJSON())
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
func onFullscreenEnabled(_ event: FullscreenEnabledEvent, view: PlayerView) {
|
|
29
|
+
onFullscreenEnabled?(event.toJSON())
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
func onFullscreenDisabled(_ event: FullscreenDisabledEvent, view: PlayerView) {
|
|
33
|
+
onFullscreenDisabled?(event.toJSON())
|
|
34
|
+
}
|
|
19
35
|
}
|
package/ios/RNPlayerView.swift
CHANGED
|
@@ -43,6 +43,11 @@ class RNPlayerView: UIView {
|
|
|
43
43
|
@objc var onAdScheduled: RCTBubblingEventBlock?
|
|
44
44
|
@objc var onAdSkipped: RCTBubblingEventBlock?
|
|
45
45
|
@objc var onAdStarted: RCTBubblingEventBlock?
|
|
46
|
+
@objc var onVideoPlaybackQualityChanged: RCTBubblingEventBlock?
|
|
47
|
+
@objc var onFullscreenEnabled: RCTBubblingEventBlock?
|
|
48
|
+
@objc var onFullscreenDisabled: RCTBubblingEventBlock?
|
|
49
|
+
@objc var onFullscreenEnter: RCTBubblingEventBlock?
|
|
50
|
+
@objc var onFullscreenExit: RCTBubblingEventBlock?
|
|
46
51
|
|
|
47
52
|
/// The `PlayerView` subview.
|
|
48
53
|
var playerView: PlayerView? {
|
|
@@ -42,7 +42,13 @@ RCT_EXPORT_VIEW_PROPERTY(onAdQuartile, RCTBubblingEventBlock)
|
|
|
42
42
|
RCT_EXPORT_VIEW_PROPERTY(onAdScheduled, RCTBubblingEventBlock)
|
|
43
43
|
RCT_EXPORT_VIEW_PROPERTY(onAdSkipped, RCTBubblingEventBlock)
|
|
44
44
|
RCT_EXPORT_VIEW_PROPERTY(onAdStarted, RCTBubblingEventBlock)
|
|
45
|
+
RCT_EXPORT_VIEW_PROPERTY(onVideoPlaybackQualityChanged, RCTBubblingEventBlock)
|
|
46
|
+
RCT_EXPORT_VIEW_PROPERTY(onFullscreenEnabled, RCTBubblingEventBlock)
|
|
47
|
+
RCT_EXPORT_VIEW_PROPERTY(onFullscreenDisabled, RCTBubblingEventBlock)
|
|
48
|
+
RCT_EXPORT_VIEW_PROPERTY(onFullscreenEnter, RCTBubblingEventBlock)
|
|
49
|
+
RCT_EXPORT_VIEW_PROPERTY(onFullscreenExit, RCTBubblingEventBlock)
|
|
45
50
|
|
|
46
51
|
RCT_EXTERN_METHOD(attachPlayer:(nonnull NSNumber *)viewId playerId:(NSString *)playerId playerConfig:(nullable NSDictionary *)playerConfig)
|
|
52
|
+
RCT_EXTERN_METHOD(attachFullscreenBridge:(nonnull NSNumber *)viewId fullscreenBridgeId:(NSString *)fullscreenBridgeId)
|
|
47
53
|
|
|
48
54
|
@end
|
|
@@ -37,8 +37,29 @@ class RNPlayerViewManager: RCTViewManager {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
@objc func attachFullscreenBridge(_ viewId: NSNumber, fullscreenBridgeId: NativeId) {
|
|
41
|
+
bridge.uiManager.addUIBlock { [weak self] _, views in
|
|
42
|
+
guard
|
|
43
|
+
let view = views?[viewId] as? RNPlayerView,
|
|
44
|
+
let fullscreenBridge = self?.getFullscreenHandlerModule()?.retrieve(fullscreenBridgeId)
|
|
45
|
+
else {
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
guard let playerView = view.playerView else {
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
playerView.fullscreenHandler = fullscreenBridge
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
40
56
|
/// Fetches the initialized `PlayerModule` instance on RN's bridge object.
|
|
41
57
|
private func getPlayerModule() -> PlayerModule? {
|
|
42
58
|
bridge.module(for: PlayerModule.self) as? PlayerModule
|
|
43
59
|
}
|
|
60
|
+
|
|
61
|
+
/// Fetches the initialized `FullscreenHandlerModule` instance on RN's bridge object.
|
|
62
|
+
private func getFullscreenHandlerModule() -> FullscreenHandlerModule? {
|
|
63
|
+
bridge.module(for: FullscreenHandlerModule.self) as? FullscreenHandlerModule
|
|
64
|
+
}
|
|
44
65
|
}
|