react-native-tpstreams 1.0.6 → 1.0.7

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.
@@ -21,7 +21,7 @@ Pod::Spec.new do |s|
21
21
  'DEFINES_MODULE' => 'YES',
22
22
  'CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES' => 'YES'
23
23
  }
24
- s.dependency "TPStreamsSDK" , "1.2.10"
24
+ s.dependency "TPStreamsSDK" , "1.2.11"
25
25
 
26
26
 
27
27
  # Ensure the module is not built as a framework to avoid bridging header conflicts
@@ -6,6 +6,8 @@ import AVFoundation
6
6
 
7
7
  @objc(TPStreamsRNPlayerView)
8
8
  class TPStreamsRNPlayerView: UIView {
9
+
10
+ private static let errorCodeDRMLicenseExpired = 5100
9
11
 
10
12
  private enum PlaybackState: Int {
11
13
  case idle = 1
@@ -21,6 +23,7 @@ class TPStreamsRNPlayerView: UIView {
21
23
  private var timeControlStatusObserver: NSKeyValueObservation?
22
24
  private var playerStateObserver: NSKeyValueObservation?
23
25
  private var setupScheduled = false
26
+ private var pendingOfflineCredentialsCompletion: ((String?, Double) -> Void)?
24
27
 
25
28
  @objc var videoId: NSString = ""
26
29
  @objc var accessToken: NSString = ""
@@ -142,6 +145,15 @@ class TPStreamsRNPlayerView: UIView {
142
145
 
143
146
  private func configurePlayerView() {
144
147
  guard let player = player else { return }
148
+ player.onRequestOfflineLicenseRenewal = { [weak self] assetId, completion in
149
+ guard let self = self else {
150
+ completion(nil, 0)
151
+ return
152
+ }
153
+ self.sendErrorEvent("Playback error", Self.errorCodeDRMLicenseExpired, "Offline DRM license expired")
154
+ self.pendingOfflineCredentialsCompletion = completion
155
+ self.onAccessTokenExpired?(["videoId": assetId])
156
+ }
145
157
 
146
158
  let configBuilder = createPlayerConfigBuilder()
147
159
  let playerVC = TPStreamPlayerViewController()
@@ -162,6 +174,10 @@ class TPStreamsRNPlayerView: UIView {
162
174
  .setprogressBarThumbColor(.systemBlue)
163
175
  .setwatchedProgressTrackColor(.systemBlue)
164
176
  .setDownloadMetadata(metadataDict)
177
+
178
+ if offlineLicenseExpireTime > 0 {
179
+ configBuilder.setLicenseDurationSeconds(offlineLicenseExpireTime)
180
+ }
165
181
 
166
182
  if enableDownload {
167
183
  configBuilder.showDownloadOption()
@@ -184,9 +200,9 @@ class TPStreamsRNPlayerView: UIView {
184
200
 
185
201
  private func observePlayerChanges() {
186
202
  setupSeekObserver()
203
+ setupPlayerStateObserver()
187
204
  setupPlaybackSpeedObserver()
188
205
  setupPlayingStateObserver()
189
- setupPlayerStateObserver()
190
206
  }
191
207
 
192
208
  private func setupSeekObserver() {
@@ -203,7 +219,7 @@ class TPStreamsRNPlayerView: UIView {
203
219
  private func setupPlaybackSpeedObserver() {
204
220
  guard let player = player else { return }
205
221
 
206
- playbackSpeedObserver = player.observe(\.rate, options: [.new, .initial]) { [weak self] player, _ in
222
+ playbackSpeedObserver = player.observe(\.rate, options: [.new]) { [weak self] player, _ in
207
223
  DispatchQueue.main.async {
208
224
  self?.onPlaybackSpeedChanged?(["speed": player.rate])
209
225
  }
@@ -230,13 +246,31 @@ class TPStreamsRNPlayerView: UIView {
230
246
  self?.onPlayerStateChanged?(["playbackState": state])
231
247
  }
232
248
  }
249
+
250
+ timeControlStatusObserver = player.observe(\.timeControlStatus, options: [.new, .initial]) { [weak self] player, _ in
251
+ DispatchQueue.main.async {
252
+ let state = self?.mapPlayerStateToAndroid(player.status, timeControlStatus: player.timeControlStatus) ?? PlaybackState.idle.rawValue
253
+ self?.onPlayerStateChanged?(["playbackState": state])
254
+ }
255
+ }
256
+ }
257
+
258
+ private func sendErrorEvent(_ message: String, _ code: Int, _ details: String) {
259
+ onError?([
260
+ "message": message,
261
+ "code": code,
262
+ "details": details
263
+ ])
233
264
  }
234
265
 
235
- private func mapPlayerStateToAndroid(_ status: AVPlayer.Status) -> Int {
266
+ private func mapPlayerStateToAndroid(_ status: AVPlayer.Status, timeControlStatus: AVPlayer.TimeControlStatus? = nil) -> Int {
236
267
  switch status {
237
268
  case .unknown:
238
269
  return PlaybackState.idle.rawValue
239
270
  case .readyToPlay:
271
+ if timeControlStatus == .waitingToPlayAtSpecifiedRate {
272
+ return PlaybackState.buffering.rawValue
273
+ }
240
274
  return PlaybackState.ready.rawValue
241
275
  case .failed:
242
276
  return PlaybackState.idle.rawValue
@@ -308,6 +342,12 @@ class TPStreamsRNPlayerView: UIView {
308
342
  @objc func setNewAccessToken(_ newToken: String) {
309
343
  pendingTokenCompletion?(newToken)
310
344
  pendingTokenCompletion = nil
345
+
346
+ if let offlineLicenseRenewalCompletion = pendingOfflineCredentialsCompletion {
347
+ let duration = offlineLicenseExpireTime
348
+ offlineLicenseRenewalCompletion(newToken, duration)
349
+ pendingOfflineCredentialsCompletion = nil
350
+ }
311
351
  }
312
352
 
313
353
  override func willMove(toSuperview newSuperview: UIView?) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-tpstreams",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "description": "Video component for TPStreams",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",