react-native-theoplayer 11.2.0 → 11.2.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 CHANGED
@@ -5,6 +5,12 @@ 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
+ ## [11.2.1] - 26-06-09
9
+
10
+ ### Fixed
11
+
12
+ - Fixed an issue on iOS where setting the targetVideoQuality uids was causing a crash due to an unsafe bounds-check.
13
+
8
14
  ## [11.2.0] - 26-06-04
9
15
 
10
16
  ### Added
@@ -281,11 +281,13 @@ class THEOplayerRCTPlayerAPI: NSObject, RCTBridgeModule {
281
281
  let player = theView.player {
282
282
  let uidValue = uid.intValue
283
283
  let textTracks: TextTrackList = player.textTracks
284
- guard textTracks.count > 0 else {
284
+ let textTrackCount = textTracks.count
285
+ guard textTrackCount > 0 else {
285
286
  return
286
287
  }
287
288
  if DEBUG_PLAYER_API { PrintUtils.printLog(logText: "[NATIVE] Showing textTrack \(uidValue) on TheoPlayer") }
288
- for i in 0...textTracks.count-1 {
289
+ for i in 0..<textTrackCount {
290
+ guard i < textTracks.count else { break }
289
291
  let textTrack: TextTrack = textTracks.get(i)
290
292
  if textTrack.uid == uidValue {
291
293
  textTrack.mode = TextTrackMode.showing
@@ -304,11 +306,13 @@ class THEOplayerRCTPlayerAPI: NSObject, RCTBridgeModule {
304
306
  let player = theView.player {
305
307
  let uidValue = uid.intValue
306
308
  let audioTracks: AudioTrackList = player.audioTracks
307
- guard audioTracks.count > 0 else {
309
+ let audioTrackCount = audioTracks.count
310
+ guard audioTrackCount > 0 else {
308
311
  return
309
312
  }
310
313
  if DEBUG_PLAYER_API { PrintUtils.printLog(logText: "[NATIVE] Enabling audioTrack \(uidValue) on TheoPlayer") }
311
- for i in 0...audioTracks.count-1 {
314
+ for i in 0..<audioTrackCount {
315
+ guard i < audioTracks.count else { break }
312
316
  let audioTrack: MediaTrack = audioTracks.get(i)
313
317
  audioTrack.enabled = (audioTrack.uid == uidValue)
314
318
  }
@@ -323,11 +327,13 @@ class THEOplayerRCTPlayerAPI: NSObject, RCTBridgeModule {
323
327
  let player = theView.player {
324
328
  let uidValue = uid.intValue
325
329
  let videoTracks: VideoTrackList = player.videoTracks
326
- guard videoTracks.count > 0 else {
330
+ let videoTrackCount = videoTracks.count
331
+ guard videoTrackCount > 0 else {
327
332
  return
328
333
  }
329
334
  if DEBUG_PLAYER_API { PrintUtils.printLog(logText: "[NATIVE] Enabling videoTrack \(uidValue) on TheoPlayer") }
330
- for i in 0...videoTracks.count-1 {
335
+ for i in 0..<videoTrackCount {
336
+ guard i < videoTracks.count else { break }
331
337
  let videoTrack: MediaTrack = videoTracks.get(i)
332
338
  videoTrack.enabled = (videoTrack.uid == uidValue)
333
339
  }
@@ -341,27 +347,37 @@ class THEOplayerRCTPlayerAPI: NSObject, RCTBridgeModule {
341
347
  if let theView = self.bridge.uiManager.view(forReactTag: node) as? THEOplayerRCTView,
342
348
  let player = theView.player {
343
349
  let videoTracks: VideoTrackList = player.videoTracks
344
- guard videoTracks.count > 0 else {
350
+ let videoTrackCount = videoTracks.count
351
+ guard videoTrackCount > 0 else {
345
352
  return
346
353
  }
347
354
  var activeVideoTrack: VideoTrack?
348
- for i in 0...videoTracks.count-1 {
355
+ for i in 0..<videoTrackCount {
356
+ guard i < videoTracks.count else { break }
349
357
  let videoTrack: MediaTrack = videoTracks.get(i)
350
358
  if videoTrack.enabled {
351
359
  activeVideoTrack = videoTrack as? VideoTrack
352
360
  }
353
361
  }
354
362
  if let foundTrack = activeVideoTrack {
355
- let matchingQualities = (0..<foundTrack.qualities.count).compactMap { index in
363
+ let requestedBandwidths = Set(uids.map { $0.intValue })
364
+ let currentBandwidths = Set(foundTrack.targetQualities?.map { $0.bandwidth } ?? [])
365
+ guard requestedBandwidths != currentBandwidths else {
366
+ if DEBUG_PLAYER_API { PrintUtils.printLog(logText: "[NATIVE] targetQualities: \(uids) already set on active videotrack. Skipping update.") }
367
+ return
368
+ }
369
+ let qualityCount = foundTrack.qualities.count
370
+ let matchingQualities = (0..<qualityCount).compactMap { index -> Quality? in
371
+ guard index < foundTrack.qualities.count else { return nil }
356
372
  let quality = foundTrack.qualities.get(index)
357
- return uids.contains { $0.intValue == quality.bandwidth } ? quality : nil
373
+ return uids.contains(where: { $0.intValue == quality.bandwidth }) ? quality : nil
358
374
  }
359
- foundTrack.targetQualities = matchingQualities.count > 0 ? matchingQualities : nil
375
+ foundTrack.targetQualities = matchingQualities.isEmpty ? nil : matchingQualities
360
376
  if DEBUG_PLAYER_API {
361
377
  if matchingQualities.count > 0 {
362
- if DEBUG_PLAYER_API { PrintUtils.printLog(logText: "[NATIVE] targetQualities: \(uids) set on active videotrack. (matching: \(matchingQualities.map(\.bandwidth)))") }
378
+ PrintUtils.printLog(logText: "[NATIVE] targetQualities: \(uids) set on active videotrack. (matching: \(matchingQualities.map(\.bandwidth)))")
363
379
  } else {
364
- if DEBUG_PLAYER_API { PrintUtils.printLog(logText: "[NATIVE] targetQualities: \(uids) set on active videotrack. (no match or empty) => no quality restriction.") }
380
+ PrintUtils.printLog(logText: "[NATIVE] targetQualities: \(uids) set on active videotrack. (no match or empty) => no quality restriction.")
365
381
  }
366
382
  }
367
383
  }
@@ -56,10 +56,12 @@ class THEOplayerRCTTrackMetadataAggregator {
56
56
  // MARK: TEXTTRACKS
57
57
  class func aggregatedTextTrackListInfo(textTracks: TextTrackList, metadataTracks: [[String:Any]], player: THEOplayer) -> [[String:Any]] {
58
58
  var trackEntries:[[String:Any]] = metadataTracks
59
- guard textTracks.count > 0 else {
59
+ let textTrackCount = textTracks.count
60
+ guard textTrackCount > 0 else {
60
61
  return trackEntries
61
62
  }
62
- for i in 0...textTracks.count-1 {
63
+ for i in 0..<textTrackCount {
64
+ guard i < textTracks.count else { break }
63
65
  let textTrack: TextTrack = textTracks.get(i)
64
66
  trackEntries.append(THEOplayerRCTTrackMetadataAggregator.aggregatedTextTrackInfo(textTrack: textTrack, player: player))
65
67
  }
@@ -90,10 +92,12 @@ class THEOplayerRCTTrackMetadataAggregator {
90
92
  }
91
93
 
92
94
  private class func selectedTextTrack(textTracks: TextTrackList) -> Int {
93
- guard textTracks.count > 0 else {
95
+ let textTrackCount = textTracks.count
96
+ guard textTrackCount > 0 else {
94
97
  return 0
95
98
  }
96
- for i in 0...textTracks.count-1 {
99
+ for i in 0..<textTrackCount {
100
+ guard i < textTracks.count else { break }
97
101
  let textTrack: TextTrack = textTracks.get(i)
98
102
  if textTrack.mode == TextTrackMode.showing {
99
103
  return textTrack.uid
@@ -160,10 +164,12 @@ class THEOplayerRCTTrackMetadataAggregator {
160
164
  // MARK: AUDIOTRACKS
161
165
  private class func aggregatedAudioTrackListInfo(audioTracks: AudioTrackList) -> [[String:Any]] {
162
166
  var audioTrackEntries:[[String:Any]] = []
163
- guard audioTracks.count > 0 else {
167
+ let audioTrackCount = audioTracks.count
168
+ guard audioTrackCount > 0 else {
164
169
  return audioTrackEntries
165
170
  }
166
- for i in 0...audioTracks.count-1 {
171
+ for i in 0..<audioTrackCount {
172
+ guard i < audioTracks.count else { break }
167
173
  let audioTrack: MediaTrack = audioTracks.get(i) // should be casted to AudioTrack
168
174
  audioTrackEntries.append(THEOplayerRCTTrackMetadataAggregator.aggregatedAudioTrackInfo(audioTrack: audioTrack))
169
175
  }
@@ -181,7 +187,9 @@ class THEOplayerRCTTrackMetadataAggregator {
181
187
  entry[PROP_ENABLED] = audioTrack.enabled
182
188
 
183
189
  // add known qualities
184
- entry[PROP_QUALITIES] = (0..<audioTrack.qualities.count).map { index in
190
+ let audioQualityCount = audioTrack.qualities.count
191
+ entry[PROP_QUALITIES] = (0..<audioQualityCount).compactMap { index -> [String:Any]? in
192
+ guard index < audioTrack.qualities.count else { return nil }
185
193
  return THEOplayerRCTTrackMetadataAggregator.aggregatedQualityInfo(quality: audioTrack.qualities.get(index))
186
194
  }
187
195
 
@@ -193,10 +201,12 @@ class THEOplayerRCTTrackMetadataAggregator {
193
201
  }
194
202
 
195
203
  private class func selectedAudioTrack(audioTracks: AudioTrackList) -> Int {
196
- guard audioTracks.count > 0 else {
204
+ let audioTrackCount = audioTracks.count
205
+ guard audioTrackCount > 0 else {
197
206
  return 0
198
207
  }
199
- for i in 0...audioTracks.count-1 {
208
+ for i in 0..<audioTrackCount {
209
+ guard i < audioTracks.count else { break }
200
210
  let audioTrack: MediaTrack = audioTracks.get(i)
201
211
  if audioTrack.enabled {
202
212
  return audioTrack.uid
@@ -208,10 +218,12 @@ class THEOplayerRCTTrackMetadataAggregator {
208
218
  // MARK: VIDEOTRACKS
209
219
  private class func aggregatedVideoTrackListInfo(videoTracks: VideoTrackList) -> [[String:Any]] {
210
220
  var videoTrackEntries:[[String:Any]] = []
211
- guard videoTracks.count > 0 else {
221
+ let videoTrackCount = videoTracks.count
222
+ guard videoTrackCount > 0 else {
212
223
  return videoTrackEntries
213
224
  }
214
- for i in 0...videoTracks.count-1 {
225
+ for i in 0..<videoTrackCount {
226
+ guard i < videoTracks.count else { break }
215
227
  if let videoTrack: VideoTrack = videoTracks.get(i) as? VideoTrack {
216
228
  videoTrackEntries.append(THEOplayerRCTTrackMetadataAggregator.aggregatedVideoTrackInfo(videoTrack: videoTrack))
217
229
  }
@@ -230,7 +242,9 @@ class THEOplayerRCTTrackMetadataAggregator {
230
242
  entry[PROP_ENABLED] = videoTrack.enabled
231
243
 
232
244
  // add known qualities
233
- entry[PROP_QUALITIES] = (0..<videoTrack.qualities.count).map { index in
245
+ let videoQualityCount = videoTrack.qualities.count
246
+ entry[PROP_QUALITIES] = (0..<videoQualityCount).compactMap { index -> [String:Any]? in
247
+ guard index < videoTrack.qualities.count else { return nil }
234
248
  return THEOplayerRCTTrackMetadataAggregator.aggregatedQualityInfo(quality: videoTrack.qualities.get(index))
235
249
  }
236
250
 
@@ -243,12 +257,14 @@ class THEOplayerRCTTrackMetadataAggregator {
243
257
  }
244
258
 
245
259
  private class func selectedVideoTrack(videoTracks: VideoTrackList) -> Int {
246
- guard videoTracks.count > 0 else {
260
+ let videoTrackCount = videoTracks.count
261
+ guard videoTrackCount > 0 else {
247
262
  return 0
248
263
  }
249
- for i in 0...videoTracks.count-1 {
264
+ for i in 0..<videoTrackCount {
265
+ guard i < videoTracks.count else { break }
250
266
  let videoTrack: MediaTrack = videoTracks.get(i)
251
- if videoTracks.get(i).enabled {
267
+ if videoTrack.enabled {
252
268
  return videoTrack.uid
253
269
  }
254
270
  }
@@ -274,7 +290,7 @@ class THEOplayerRCTTrackMetadataAggregator {
274
290
  "bandwidth": quality.bandwidth,
275
291
  "codecs": "",
276
292
  "id": identifier,
277
- "uid": identifier,
293
+ "uid": quality.bandwidth,
278
294
  "name": label,
279
295
  "label": label,
280
296
  "available": true,
@@ -1 +1 @@
1
- {"version":"11.2.0","buildDate":"2026-06-04T15:04:43.174Z"}
1
+ {"version":"11.2.1","buildDate":"2026-06-09T13:34:42.726Z"}
@@ -1 +1 @@
1
- {"version":"11.2.0","buildDate":"2026-06-04T15:04:43.174Z"}
1
+ {"version":"11.2.1","buildDate":"2026-06-09T13:34:42.726Z"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-theoplayer",
3
- "version": "11.2.0",
3
+ "version": "11.2.1",
4
4
  "description": "A THEOplayer video component for react-native.",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
package/src/manifest.json CHANGED
@@ -1 +1 @@
1
- {"version":"11.2.0","buildDate":"2026-06-04T15:04:43.174Z"}
1
+ {"version":"11.2.1","buildDate":"2026-06-09T13:34:42.726Z"}