@capgo/capacitor-jw-player 0.0.13 → 0.0.20
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/Package.swift +0 -5
- package/README.md +4 -4
- package/android/src/main/java/ee/forgr/capacitor_jw_player/PlayerActivity.java +16 -10
- package/dist/docs.json +6 -2
- package/dist/esm/definitions.d.ts +101 -0
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.d.ts +21 -9
- package/dist/esm/web.js +307 -28
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +307 -28
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +307 -28
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/JwPlayerPlugin/JwPlayerPlugin.swift +183 -68
- package/ios/Sources/JwPlayerPlugin/VideosToPlay.swift +1 -0
- package/package.json +3 -2
|
@@ -2,7 +2,6 @@ import Foundation
|
|
|
2
2
|
import Capacitor
|
|
3
3
|
import JWPlayerKit
|
|
4
4
|
import AVKit // Import AVKit for AVAudioSession
|
|
5
|
-
import GoogleCast
|
|
6
5
|
/**
|
|
7
6
|
* Please read the Capacitor iOS Plugin Development Guide
|
|
8
7
|
* here: https://capacitorjs.com/docs/plugins/ios
|
|
@@ -16,7 +15,8 @@ protocol CallbackHandler {
|
|
|
16
15
|
}
|
|
17
16
|
|
|
18
17
|
@objc(JwPlayerPlugin)
|
|
19
|
-
public class JwPlayerPlugin: CAPPlugin, CAPBridgedPlugin
|
|
18
|
+
public class JwPlayerPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
19
|
+
// public class JwPlayerPlugin: CAPPlugin, CAPBridgedPlugin, GCKLoggerDelegate {
|
|
20
20
|
public let identifier = "JwPlayerPlugin"
|
|
21
21
|
public let jsName = "JwPlayer"
|
|
22
22
|
public let pluginMethods: [CAPPluginMethod] = [
|
|
@@ -46,8 +46,8 @@ public class JwPlayerPlugin: CAPPlugin, CAPBridgedPlugin, GCKLoggerDelegate {
|
|
|
46
46
|
override public func load() {
|
|
47
47
|
// Configure the audio session when the plugin loads
|
|
48
48
|
setupAudioSession()
|
|
49
|
-
print("[JWPlayer] Plugin loaded. Note: Chromecast is initialized in AppDelegate.")
|
|
50
|
-
initializeChromecast()
|
|
49
|
+
// print("[JWPlayer] Plugin loaded. Note: Chromecast is initialized in AppDelegate.")
|
|
50
|
+
// initializeChromecast()
|
|
51
51
|
super.load()
|
|
52
52
|
}
|
|
53
53
|
|
|
@@ -63,46 +63,46 @@ public class JwPlayerPlugin: CAPPlugin, CAPBridgedPlugin, GCKLoggerDelegate {
|
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
private func initializeChromecast() {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
public func logMessage(_ message: String, at level: GCKLoggerLevel, fromFunction function: String, location: String) {
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
@objc func initialize(_ call: CAPPluginCall) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
66
|
+
// private func initializeChromecast() {
|
|
67
|
+
// print("[ChromecastDebug] Starting Chromecast initialization")
|
|
68
|
+
// let kReceiverAppID = "CC1AD845" // Custom App ID for Chromecast
|
|
69
|
+
// let discoveryCriteria = GCKDiscoveryCriteria(applicationID: kReceiverAppID)
|
|
70
|
+
// let options = GCKCastOptions(discoveryCriteria: discoveryCriteria)
|
|
71
|
+
// options.physicalVolumeButtonsWillControlDeviceVolume = true
|
|
72
|
+
// options.disableDiscoveryAutostart = false
|
|
73
|
+
// print("[ChromecastDebug] Setting custom options for Chromecast")
|
|
74
|
+
// do {
|
|
75
|
+
// GCKCastContext.setSharedInstanceWith(options)
|
|
76
|
+
// print("[ChromecastDebug] Chromecast context initialized with App ID: \(kReceiverAppID)")
|
|
77
|
+
// } catch {
|
|
78
|
+
// print("[ChromecastDebug] Error initializing Chromecast context: \(error.localizedDescription)")
|
|
79
|
+
// }
|
|
80
|
+
|
|
81
|
+
// let filter = GCKLoggerFilter.init()
|
|
82
|
+
// filter.minimumLevel = .verbose
|
|
83
|
+
// GCKLogger.sharedInstance().filter = filter
|
|
84
|
+
// GCKLogger.sharedInstance().delegate = self
|
|
85
|
+
// print("[ChromecastDebug] Logger initialized")
|
|
86
|
+
// }
|
|
87
|
+
|
|
88
|
+
// public func logMessage(_ message: String, at level: GCKLoggerLevel, fromFunction function: String, location: String) {
|
|
89
|
+
// print(function + " - " + message)
|
|
90
|
+
// }
|
|
91
|
+
|
|
92
|
+
// @objc func initialize(_ call: CAPPluginCall) {
|
|
93
|
+
// print("[JWPlayer] initialize called")
|
|
94
|
+
// guard let licenseKey = call.getString("licenseKey") else {
|
|
95
|
+
// print("[JWPlayer] Error: licenseKey is missing")
|
|
96
|
+
// call.reject("licenseKey is required for initialize")
|
|
97
|
+
// return
|
|
98
|
+
// }
|
|
99
|
+
|
|
100
|
+
// print("[JWPlayer] Setting license key")
|
|
101
|
+
// JWPlayerKitLicense.setLicenseKey(licenseKey)
|
|
102
|
+
// print("[JWPlayer] License key set successfully")
|
|
103
|
+
|
|
104
|
+
// call.resolve()
|
|
105
|
+
// }
|
|
106
106
|
|
|
107
107
|
@objc func play(_ call: CAPPluginCall) {
|
|
108
108
|
print("[JWPlayer] play called with options: \(call.options)")
|
|
@@ -114,7 +114,7 @@ public class JwPlayerPlugin: CAPPlugin, CAPBridgedPlugin, GCKLoggerDelegate {
|
|
|
114
114
|
|
|
115
115
|
guard let mediaUrl = URL(string: mediaUrlStr) else {
|
|
116
116
|
print("[JWPlayer] Error: mediaUrl is invalid URL: \(mediaUrlStr)")
|
|
117
|
-
call.reject("mediaUrl is invalid URL")
|
|
117
|
+
call.reject("mediaUrl is invalid URL: \(mediaUrlStr)")
|
|
118
118
|
return
|
|
119
119
|
}
|
|
120
120
|
|
|
@@ -580,6 +580,7 @@ class CustomPlayerViewController: JWPlayerViewController, JWPlayerViewController
|
|
|
580
580
|
private var callbackHandler: CallbackHandler?
|
|
581
581
|
private var playerConfig: JWPlayerConfiguration?
|
|
582
582
|
private var closeButton: UIButton! // Custom close button
|
|
583
|
+
private var timeUpdateTimer: Timer? // Timer for periodic time updates
|
|
583
584
|
|
|
584
585
|
// Standard init is unavailable
|
|
585
586
|
@available(*, unavailable)
|
|
@@ -642,6 +643,9 @@ class CustomPlayerViewController: JWPlayerViewController, JWPlayerViewController
|
|
|
642
643
|
print("[JWPlayer] Configuring player from init config")
|
|
643
644
|
player.configurePlayer(with: config)
|
|
644
645
|
print("[JWPlayer] Player configured successfully from init config")
|
|
646
|
+
|
|
647
|
+
// JWPlayerViewController already has self as delegates
|
|
648
|
+
// We are just implementing the delegate methods
|
|
645
649
|
} else {
|
|
646
650
|
print("[JWPlayer] Error: Player configuration is missing in viewDidLoad")
|
|
647
651
|
self.callbackHandler?.notifyEventListener("error", data: ["message": "Player configuration missing"])
|
|
@@ -649,19 +653,59 @@ class CustomPlayerViewController: JWPlayerViewController, JWPlayerViewController
|
|
|
649
653
|
|
|
650
654
|
// Add the custom close button
|
|
651
655
|
setupCloseButton()
|
|
656
|
+
|
|
657
|
+
// Start time update timer after player is ready
|
|
658
|
+
startTimeUpdateTimer()
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
// Start a timer to emit time updates periodically
|
|
662
|
+
private func startTimeUpdateTimer() {
|
|
663
|
+
// Cancel any existing timer
|
|
664
|
+
timeUpdateTimer?.invalidate()
|
|
665
|
+
|
|
666
|
+
// Create a new timer that fires every second
|
|
667
|
+
timeUpdateTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in
|
|
668
|
+
guard let self = self else { return }
|
|
669
|
+
|
|
670
|
+
if self.player.getState() == .playing {
|
|
671
|
+
let position = self.player.time.position
|
|
672
|
+
let duration = self.player.time.duration
|
|
673
|
+
|
|
674
|
+
let timeData: [String: Any] = [
|
|
675
|
+
"position": position,
|
|
676
|
+
"duration": duration
|
|
677
|
+
]
|
|
678
|
+
|
|
679
|
+
self.callbackHandler?.notifyEventListener("time", data: timeData)
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
// Stop the time update timer
|
|
685
|
+
private func stopTimeUpdateTimer() {
|
|
686
|
+
timeUpdateTimer?.invalidate()
|
|
687
|
+
timeUpdateTimer = nil
|
|
652
688
|
}
|
|
653
689
|
|
|
654
690
|
override func viewDidAppear(_ animated: Bool) {
|
|
655
691
|
print("[JWPlayer] viewDidAppear")
|
|
656
692
|
super.viewDidAppear(animated)
|
|
657
|
-
|
|
658
|
-
// Start playback automatically
|
|
659
|
-
// print("[JWPlayer] Starting playback")
|
|
660
|
-
// player.play()
|
|
661
|
-
// print("[JWPlayer] Playback started")
|
|
662
693
|
print("[JWPlayer] Button exists \(view.viewWithTag(2136) !== nil)")
|
|
663
694
|
}
|
|
664
695
|
|
|
696
|
+
override func viewWillDisappear(_ animated: Bool) {
|
|
697
|
+
super.viewWillDisappear(animated)
|
|
698
|
+
|
|
699
|
+
// Stop the time update timer when view disappears
|
|
700
|
+
stopTimeUpdateTimer()
|
|
701
|
+
|
|
702
|
+
// Only trigger the dismissal callback if it's a manual dismissal
|
|
703
|
+
if self.isBeingDismissed || self.isMovingFromParent {
|
|
704
|
+
print("[JWPlayer] Manual dismissal detected in viewWillDisappear")
|
|
705
|
+
callbackHandler?.onPlayerDismissed(isPiPDismissal: false)
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
|
|
665
709
|
// Setup and add the custom close button
|
|
666
710
|
private func setupCloseButton() {
|
|
667
711
|
closeButton = UIButton(type: .custom)
|
|
@@ -703,6 +747,89 @@ class CustomPlayerViewController: JWPlayerViewController, JWPlayerViewController
|
|
|
703
747
|
}
|
|
704
748
|
}
|
|
705
749
|
|
|
750
|
+
// MARK: - JWPlayerDelegate Methods
|
|
751
|
+
|
|
752
|
+
override func jwplayerIsReady(_ player: JWPlayer) {
|
|
753
|
+
super.jwplayerIsReady(player)
|
|
754
|
+
print("[JWPlayer] Player is ready")
|
|
755
|
+
callbackHandler?.notifyEventListener("ready", data: nil)
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
override func jwplayer(_ player: JWPlayer, failedWithError code: UInt, message: String) {
|
|
759
|
+
super.jwplayer(player, failedWithError: code, message: message)
|
|
760
|
+
print("[JWPlayer] Error: \(message), code: \(code)")
|
|
761
|
+
let errorData: [String: Any] = [
|
|
762
|
+
"message": message,
|
|
763
|
+
"code": code
|
|
764
|
+
]
|
|
765
|
+
callbackHandler?.notifyEventListener("error", data: errorData)
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
override func jwplayer(_ player: JWPlayer, failedWithSetupError code: UInt, message: String) {
|
|
769
|
+
super.jwplayer(player, failedWithSetupError: code, message: message)
|
|
770
|
+
print("[JWPlayer] Setup error: \(message), code: \(code)")
|
|
771
|
+
let errorData: [String: Any] = [
|
|
772
|
+
"message": message,
|
|
773
|
+
"code": code
|
|
774
|
+
]
|
|
775
|
+
callbackHandler?.notifyEventListener("error", data: errorData)
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
// MARK: - JWPlayerStateDelegate Methods
|
|
779
|
+
|
|
780
|
+
override func jwplayer(_ player: JWPlayer, isPlayingWithReason reason: JWPlayReason) {
|
|
781
|
+
super.jwplayer(player, isPlayingWithReason: reason)
|
|
782
|
+
print("[JWPlayer] Playing with reason: \(reason)")
|
|
783
|
+
callbackHandler?.notifyEventListener("play", data: ["reason": reason.rawValue])
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
override func jwplayer(_ player: JWPlayer, didPauseWithReason reason: JWPauseReason) {
|
|
787
|
+
super.jwplayer(player, didPauseWithReason: reason)
|
|
788
|
+
print("[JWPlayer] Paused with reason: \(reason)")
|
|
789
|
+
callbackHandler?.notifyEventListener("pause", data: ["reason": reason.rawValue])
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
override func jwplayerContentDidComplete(_ player: JWPlayer) {
|
|
793
|
+
super.jwplayerContentDidComplete(player)
|
|
794
|
+
print("[JWPlayer] Content completed")
|
|
795
|
+
callbackHandler?.notifyEventListener("complete", data: nil)
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
override func jwplayer(_ player: JWPlayer, seekedFrom position: TimeInterval, to offset: TimeInterval) {
|
|
799
|
+
super.jwplayer(player, seekedFrom: position, to: offset)
|
|
800
|
+
print("[JWPlayer] Seeked from \(position) to \(offset)")
|
|
801
|
+
let seekData: [String: Any] = [
|
|
802
|
+
"position": position,
|
|
803
|
+
"offset": offset
|
|
804
|
+
]
|
|
805
|
+
callbackHandler?.notifyEventListener("seek", data: seekData)
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
override func jwplayerHasSeeked(_ player: JWPlayer) {
|
|
809
|
+
super.jwplayerHasSeeked(player)
|
|
810
|
+
print("[JWPlayer] Seeked")
|
|
811
|
+
callbackHandler?.notifyEventListener("seeked", data: nil)
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
override func jwplayer(_ player: JWPlayer, didLoadPlaylistItem item: JWPlayerItem, at index: UInt) {
|
|
815
|
+
super.jwplayer(player, didLoadPlaylistItem: item, at: index)
|
|
816
|
+
print("[JWPlayer] Playlist item loaded at index: \(index)")
|
|
817
|
+
var itemData: [String: Any] = ["index": index]
|
|
818
|
+
|
|
819
|
+
// Add title if available
|
|
820
|
+
if let title = item.title, !title.isEmpty {
|
|
821
|
+
itemData["title"] = title
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
callbackHandler?.notifyEventListener("playlistItem", data: itemData)
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
override func jwplayerPlaylistHasCompleted(_ player: JWPlayer) {
|
|
828
|
+
super.jwplayerPlaylistHasCompleted(player)
|
|
829
|
+
print("[JWPlayer] Playlist completed")
|
|
830
|
+
callbackHandler?.notifyEventListener("playlistComplete", data: nil)
|
|
831
|
+
}
|
|
832
|
+
|
|
706
833
|
// MARK: - JWPlayerViewControllerUIDelegate Method
|
|
707
834
|
|
|
708
835
|
func playerViewController(_ controller: JWPlayerViewController, controlBarVisibilityChanged isVisible: Bool, frame: CGRect) {
|
|
@@ -713,6 +840,9 @@ class CustomPlayerViewController: JWPlayerViewController, JWPlayerViewController
|
|
|
713
840
|
// Ensure closeButton is not nil before accessing
|
|
714
841
|
guard let button = self.closeButton else { return }
|
|
715
842
|
button.alpha = targetAlpha
|
|
843
|
+
|
|
844
|
+
// Emit controlsChanged event to match other platforms
|
|
845
|
+
callbackHandler?.notifyEventListener("controlsChanged", data: ["visible": isVisible])
|
|
716
846
|
}
|
|
717
847
|
|
|
718
848
|
// MARK: - AVPictureInPictureControllerDelegate Methods
|
|
@@ -729,11 +859,13 @@ class CustomPlayerViewController: JWPlayerViewController, JWPlayerViewController
|
|
|
729
859
|
override func pictureInPictureControllerDidStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
|
|
730
860
|
print("[JWPlayer] Delegate: PiP Did Start")
|
|
731
861
|
super.pictureInPictureControllerDidStartPictureInPicture(pictureInPictureController)
|
|
862
|
+
callbackHandler?.notifyEventListener("pipStarted", data: ["isInPictureInPictureMode": true])
|
|
732
863
|
}
|
|
733
864
|
|
|
734
865
|
override func pictureInPictureController(_ pictureInPictureController: AVPictureInPictureController, failedToStartPictureInPictureWithError error: Error) {
|
|
735
866
|
print("[JWPlayer] Delegate: PiP Failed to Start: \(error.localizedDescription)")
|
|
736
867
|
super.pictureInPictureController(pictureInPictureController, failedToStartPictureInPictureWithError: error)
|
|
868
|
+
callbackHandler?.notifyEventListener("error", data: ["message": "Failed to start PiP: \(error.localizedDescription)"])
|
|
737
869
|
}
|
|
738
870
|
|
|
739
871
|
override func pictureInPictureControllerWillStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
|
|
@@ -744,17 +876,10 @@ class CustomPlayerViewController: JWPlayerViewController, JWPlayerViewController
|
|
|
744
876
|
override func pictureInPictureControllerDidStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
|
|
745
877
|
print("[JWPlayer] Delegate: PiP Did Stop")
|
|
746
878
|
super.pictureInPictureControllerDidStopPictureInPicture(pictureInPictureController)
|
|
747
|
-
|
|
748
|
-
// If PiP is stopped directly by the user without restoration, notify the plugin
|
|
749
|
-
// print("[JWPlayer] PiP stopped, cleaning up plugin reference.")
|
|
750
|
-
// self.callbackHandler?.onPlayerDismissed(isPiPDismissal: false)
|
|
879
|
+
callbackHandler?.notifyEventListener("pipStopped", data: ["isInPictureInPictureMode": false])
|
|
751
880
|
}
|
|
752
881
|
|
|
753
882
|
override func pictureInPictureController(_ pictureInPictureController: AVPictureInPictureController, restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void) {
|
|
754
|
-
// print("[JWPlayer] Delegate: PiP Restore UI Requested")
|
|
755
|
-
// Ask the plugin to re-present this view controller instance
|
|
756
|
-
// callbackHandler?.rePresentPlayerRequested()
|
|
757
|
-
|
|
758
883
|
// Here I will REMOVE the button to close and readd it
|
|
759
884
|
if let closeButton = self.closeButton {
|
|
760
885
|
closeButton.removeFromSuperview()
|
|
@@ -766,16 +891,6 @@ class CustomPlayerViewController: JWPlayerViewController, JWPlayerViewController
|
|
|
766
891
|
super.pictureInPictureController(pictureInPictureController, restoreUserInterfaceForPictureInPictureStopWithCompletionHandler: completionHandler)
|
|
767
892
|
}
|
|
768
893
|
|
|
769
|
-
override func viewWillDisappear(_ animated: Bool) {
|
|
770
|
-
super.viewWillDisappear(animated)
|
|
771
|
-
|
|
772
|
-
// Only trigger the dismissal callback if it's a manual dismissal
|
|
773
|
-
if self.isBeingDismissed || self.isMovingFromParent {
|
|
774
|
-
print("[JWPlayer] Manual dismissal detected in viewWillDisappear")
|
|
775
|
-
callbackHandler?.onPlayerDismissed(isPiPDismissal: false)
|
|
776
|
-
}
|
|
777
|
-
}
|
|
778
|
-
|
|
779
894
|
// MARK: - JWCastDelegate
|
|
780
895
|
// Optionally, override the following methods to receive and respond to events when casting.
|
|
781
896
|
// Always call the superclass's method when overriding these methods.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capgo/capacitor-jw-player",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.20",
|
|
4
4
|
"description": "Playes videos from jwplayer.com",
|
|
5
5
|
"main": "dist/plugin.cjs.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -59,7 +59,8 @@
|
|
|
59
59
|
"rimraf": "^6.0.1",
|
|
60
60
|
"rollup": "^4.30.1",
|
|
61
61
|
"swiftlint": "^2.0.0",
|
|
62
|
-
"typescript": "~4.1.5"
|
|
62
|
+
"typescript": "~4.1.5",
|
|
63
|
+
"@types/jwplayer": "^8.31.3"
|
|
63
64
|
},
|
|
64
65
|
"peerDependencies": {
|
|
65
66
|
"@capacitor/core": ">=7.2.0"
|