react-native-audio-browser 0.2.0-next.27 → 0.2.0-next.29

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.
Files changed (139) hide show
  1. package/android/src/main/java/com/audiobrowser/ServiceBinding.kt +8 -4
  2. package/android/src/main/java/com/audiobrowser/browser/BrowserUrlResolution.kt +3 -4
  3. package/android/src/test/java/com/audiobrowser/ServiceBindingTest.kt +13 -0
  4. package/android/src/test/java/com/audiobrowser/browser/BrowserUrlResolutionTest.kt +2 -2
  5. package/ios/AVPlayerEngine.swift +334 -0
  6. package/ios/AVPlayerEngineCallbacks.swift +15 -0
  7. package/ios/Browser/BrowseGate.swift +58 -0
  8. package/ios/Browser/BrowserConfig.swift +31 -89
  9. package/ios/Browser/BrowserManager.swift +68 -487
  10. package/ios/Browser/NavigationErrorState.swift +41 -0
  11. package/ios/Browser/PageResolver.swift +227 -0
  12. package/ios/Browser/RequestLayer.swift +90 -0
  13. package/ios/Browser/{BrowserManager+URLResolution.swift → RequestPipeline.swift} +175 -107
  14. package/ios/CarPlay/CPInterfaceController+Safe.swift +11 -24
  15. package/ios/CarPlay/CarPlayArtworkResolver.swift +35 -83
  16. package/ios/CarPlay/CarPlayController.swift +42 -1442
  17. package/ios/CarPlay/CarPlayImageLoader.swift +42 -83
  18. package/ios/CarPlay/CarPlayListItemFactory.swift +9 -23
  19. package/ios/CarPlay/CarPlayNowPlayingManager.swift +119 -129
  20. package/ios/CarPlay/CarPlaySession+Navigator.swift +114 -0
  21. package/ios/CarPlay/CarPlaySession+PageLoader.swift +92 -0
  22. package/ios/CarPlay/CarPlaySession+Refresher.swift +43 -0
  23. package/ios/CarPlay/CarPlaySession+TabBar.swift +193 -0
  24. package/ios/CarPlay/CarPlaySession.swift +209 -0
  25. package/ios/CarPlay/CarPlayTemplates.swift +63 -0
  26. package/ios/CarPlay/HybridAudioBrowser+IntentFavorite.swift +20 -0
  27. package/ios/CarPlay/MediaIntentPlayback.swift +74 -0
  28. package/ios/CarPlay/RNABMediaAddHandler.swift +2 -18
  29. package/ios/CarPlay/RNABMediaAffinityHandler.swift +5 -21
  30. package/ios/CarPlay/RNABMediaIntentHandler.swift +2 -3
  31. package/ios/Extension/NavigationError+Conversion.swift +7 -4
  32. package/ios/Extension/UIImage+Adaptive.swift +12 -0
  33. package/ios/Extension/URLError+Connectivity.swift +15 -0
  34. package/ios/Http/HttpClient.swift +63 -145
  35. package/ios/HybridAudioBrowser+Browser.swift +153 -0
  36. package/ios/HybridAudioBrowser+Options.swift +144 -0
  37. package/ios/HybridAudioBrowser+Player.swift +397 -0
  38. package/ios/HybridAudioBrowser+PlayerCallbacks.swift +190 -0
  39. package/ios/HybridAudioBrowser+Stubs.swift +46 -0
  40. package/ios/HybridAudioBrowser.swift +74 -1687
  41. package/ios/Model/NitroTypeStubs.swift +18 -1
  42. package/ios/Model/PlayerUpdateOptions.swift +1 -1
  43. package/ios/NowPlayingInfo/NowPlayingInfoController.swift +18 -53
  44. package/ios/Observer/ItemObserver.swift +90 -0
  45. package/ios/Observer/PlayerObserver.swift +59 -0
  46. package/ios/Option/SessionCategories.swift +41 -92
  47. package/ios/Player/AudioSessionController.swift +177 -0
  48. package/ios/Player/DeferredSeek.swift +70 -0
  49. package/ios/Player/ErrorStatus.swift +27 -0
  50. package/ios/Player/MediaLoader.swift +24 -11
  51. package/ios/Player/NowPlayingUpdater.swift +157 -58
  52. package/ios/Player/PlaybackFailure.swift +125 -0
  53. package/ios/Player/PlaybackPersistence.swift +73 -0
  54. package/ios/Player/Player.swift +1083 -0
  55. package/ios/Player/{PlaybackCoordinatorCallbacks.swift → PlayerCallbacks.swift} +3 -4
  56. package/ios/Player/PlayerEngine.swift +89 -0
  57. package/ios/Player/PlayerStatusTypes.swift +2 -6
  58. package/ios/Player/QueueManager.swift +52 -59
  59. package/ios/Player/RetryLoop.swift +261 -0
  60. package/ios/Player/SleepTimerManager.swift +1 -1
  61. package/ios/RemoteCommand/RemoteCommandCallbacks.swift +2 -3
  62. package/ios/RemoteCommand/RemoteCommandController.swift +85 -367
  63. package/ios/Tests/CarPlayArtworkResolverTests.swift +60 -356
  64. package/ios/Tests/DeferredSeekTests.swift +70 -0
  65. package/ios/Tests/EmitterTests.swift +29 -0
  66. package/ios/Tests/GenerationMemoTests.swift +121 -0
  67. package/ios/Tests/LRUCacheTests.swift +4 -5
  68. package/ios/Tests/MediaLoaderTests.swift +12 -33
  69. package/ios/Tests/ObserverTests.swift +88 -0
  70. package/ios/Tests/PlaybackErrorTests.swift +76 -0
  71. package/ios/Tests/PlaybackFailureTests.swift +189 -0
  72. package/ios/Tests/PlaybackPersistenceTests.swift +93 -0
  73. package/ios/Tests/PlayerPolicyTests.swift +405 -0
  74. package/ios/Tests/{PlaybackCoordinatorTests.swift → PlayerTests.swift} +298 -248
  75. package/ios/Tests/PlayingStateTests.swift +42 -0
  76. package/ios/Tests/QueueManagerTests.swift +76 -107
  77. package/ios/Tests/ReadyValueTests.swift +73 -0
  78. package/ios/Tests/RemoteCommandControllerTests.swift +10 -30
  79. package/ios/Tests/RemoteCommandTests.swift +2 -4
  80. package/ios/Tests/RequestLayerTests.swift +112 -0
  81. package/ios/Tests/RetryLoopTests.swift +270 -0
  82. package/ios/Tests/Support/TestTypes.swift +111 -112
  83. package/ios/Tests/TrackIdTemplateTests.swift +1 -1
  84. package/ios/Tests/URLErrorConnectivityTests.swift +20 -0
  85. package/ios/TrackSelector.swift +1 -1
  86. package/ios/Util/ArtworkImageFetcher.swift +42 -0
  87. package/ios/Util/Emitter.swift +42 -0
  88. package/ios/Util/GenerationMemo.swift +36 -0
  89. package/ios/Util/LRUCache.swift +23 -162
  90. package/ios/Util/NetworkMonitor.swift +1 -1
  91. package/ios/Util/ReadyValue.swift +56 -0
  92. package/ios/Util/SFSymbolRenderer.swift +35 -29
  93. package/ios/Util/SVGProcessor.swift +0 -10
  94. package/lib/commonjs/web/NativeAudioBrowser.js +1 -1
  95. package/lib/commonjs/web/TrackPlayer/PlayingStateFactory.js +1 -1
  96. package/lib/module/web/NativeAudioBrowser.js +1 -1
  97. package/lib/module/web/TrackPlayer/PlayingStateFactory.js +1 -1
  98. package/lib/typescript/src/types/browser.d.ts +3 -3
  99. package/package.json +1 -1
  100. package/src/types/browser.ts +3 -3
  101. package/src/web/NativeAudioBrowser.ts +1 -1
  102. package/src/web/TrackPlayer/PlayingStateFactory.test.ts +1 -1
  103. package/src/web/TrackPlayer/PlayingStateFactory.ts +1 -1
  104. package/ios/Bridge.h +0 -8
  105. package/ios/Browser/MediaResolveComposer.swift +0 -114
  106. package/ios/NowPlayingInfo/MediaItemProperty.swift +0 -78
  107. package/ios/NowPlayingInfo/NowPlayingInfoKeyValue.swift +0 -6
  108. package/ios/NowPlayingInfo/NowPlayingInfoProperty.swift +0 -220
  109. package/ios/Observer/PlayerItemNotificationObserver.swift +0 -119
  110. package/ios/Observer/PlayerItemPropertyObserver.swift +0 -133
  111. package/ios/Observer/PlayerStateObserver.swift +0 -50
  112. package/ios/Observer/PlayerTimeObserver.swift +0 -55
  113. package/ios/Option/PitchAlgorithms.swift +0 -17
  114. package/ios/Option/TimeEventFrequency.swift +0 -18
  115. package/ios/Player/LoadSeekCoordinator.swift +0 -99
  116. package/ios/Player/MediaLoaderDelegate.swift +0 -11
  117. package/ios/Player/PlaybackCoordinator.swift +0 -761
  118. package/ios/Player/PlaybackEffectHandler.swift +0 -54
  119. package/ios/Player/PlaybackErrorHandler.swift +0 -175
  120. package/ios/Player/PlaybackStateStore.swift +0 -27
  121. package/ios/Player/PlayingStateManager.swift +0 -33
  122. package/ios/Player/RetryManager.swift +0 -384
  123. package/ios/Player/SeekCompletionHandler.swift +0 -5
  124. package/ios/Player/SleepTimerHandling.swift +0 -28
  125. package/ios/Support/RNTrackPlayer-Bridging-Header.h +0 -7
  126. package/ios/Tests/LoadSeekCoordinatorTests.swift +0 -327
  127. package/ios/Tests/MediaResolveTests.swift +0 -126
  128. package/ios/Tests/OnceValueTests.swift +0 -79
  129. package/ios/Tests/PlaybackErrorHandlerTests.swift +0 -549
  130. package/ios/Tests/PlaybackStateStoreTests.swift +0 -49
  131. package/ios/Tests/PlayerTimeObserverTests.swift +0 -37
  132. package/ios/Tests/PlayingStateManagerTests.swift +0 -57
  133. package/ios/Tests/RetryManagerTests.swift +0 -178
  134. package/ios/TrackPlayer.swift +0 -1042
  135. package/ios/TrackPlayerCallbacks.swift +0 -53
  136. package/ios/Util/MetadataAdapter.swift +0 -131
  137. package/ios/Util/OnceValue.swift +0 -104
  138. /package/ios/{Player → CarPlay}/MediaIntentCriteria.swift +0 -0
  139. /package/ios/{Browser → CarPlay}/SectionPresentation.swift +0 -0
@@ -1,50 +0,0 @@
1
- import AVFoundation
2
- import Foundation
3
-
4
- /**
5
- Observes player state changes and invokes callbacks passed at initialization.
6
- Uses modern block-based KVO for type-safe observation with automatic cleanup.
7
- */
8
- @MainActor final class PlayerStateObserver {
9
- private var observations: [NSKeyValueObservation] = []
10
-
11
- weak var avPlayer: AVPlayer? {
12
- willSet {
13
- stopObserving()
14
- }
15
- }
16
-
17
- private let onStatusChange: @MainActor (AVPlayer.Status) -> Void
18
- private let onTimeControlStatusChange: @MainActor (AVPlayer.TimeControlStatus) -> Void
19
-
20
- init(
21
- onStatusChange: @escaping @MainActor (AVPlayer.Status) -> Void,
22
- onTimeControlStatusChange: @escaping @MainActor (AVPlayer.TimeControlStatus) -> Void,
23
- ) {
24
- self.onStatusChange = onStatusChange
25
- self.onTimeControlStatusChange = onTimeControlStatusChange
26
- }
27
-
28
- /**
29
- Start receiving events from this observer.
30
- */
31
- func startObserving() {
32
- guard let avPlayer else { return }
33
- stopObserving()
34
-
35
- observations = [
36
- avPlayer.observe(\.status, options: [.new, .initial]) { [weak self] player, _ in
37
- let status = player.status
38
- Task { @MainActor in self?.onStatusChange(status) }
39
- },
40
- avPlayer.observe(\.timeControlStatus, options: [.new]) { [weak self] player, _ in
41
- let status = player.timeControlStatus
42
- Task { @MainActor in self?.onTimeControlStatusChange(status) }
43
- },
44
- ]
45
- }
46
-
47
- func stopObserving() {
48
- observations.removeAll()
49
- }
50
- }
@@ -1,55 +0,0 @@
1
- import AVFoundation
2
- import Foundation
3
-
4
- /**
5
- Observes the player's audio-start boundary and invokes the callback passed at initialization.
6
- */
7
- @MainActor class PlayerTimeObserver {
8
- /// The time to use as start boundary time. Cannot be zero.
9
- private static let startBoundaryTime: CMTime = .init(value: 1, timescale: 1000)
10
-
11
- var boundaryTimeStartObserverToken: Any?
12
-
13
- weak var avPlayer: AVPlayer? {
14
- willSet {
15
- unregisterForBoundaryTimeEvents()
16
- }
17
- }
18
-
19
- private let onAudioDidStart: @MainActor () -> Void
20
-
21
- init(onAudioDidStart: @escaping @MainActor () -> Void) {
22
- self.onAudioDidStart = onAudioDidStart
23
- }
24
-
25
- /**
26
- Will register for the AVPlayer BoundaryTimeEvents, to trigger the audio-start event.
27
- */
28
- func registerForBoundaryTimeEvents() {
29
- guard let avPlayer else {
30
- return
31
- }
32
- unregisterForBoundaryTimeEvents()
33
- boundaryTimeStartObserverToken = avPlayer.addBoundaryTimeObserver(
34
- forTimes: [PlayerTimeObserver.startBoundaryTime].map {
35
- NSValue(time: $0)
36
- },
37
- queue: nil,
38
- using: { [weak self] in
39
- Task { @MainActor in self?.onAudioDidStart() }
40
- },
41
- )
42
- }
43
-
44
- /**
45
- Unregister from the boundary events of the player.
46
- */
47
- func unregisterForBoundaryTimeEvents() {
48
- guard
49
- let avPlayer,
50
- let boundaryTimeStartObserverToken
51
- else { return }
52
- avPlayer.removeTimeObserver(boundaryTimeStartObserverToken)
53
- self.boundaryTimeStartObserverToken = nil
54
- }
55
- }
@@ -1,17 +0,0 @@
1
- import AVFoundation
2
- import Foundation
3
-
4
- public enum PitchAlgorithm: String {
5
- case linear
6
- case music
7
- case voice
8
-
9
- /// The corresponding AVAudioTimePitchAlgorithm for use with AVPlayer
10
- public var avAlgorithm: AVAudioTimePitchAlgorithm {
11
- switch self {
12
- case .linear: .varispeed
13
- case .music: .spectral
14
- case .voice: .timeDomain
15
- }
16
- }
17
- }
@@ -1,18 +0,0 @@
1
- import AVFoundation
2
- import Foundation
3
-
4
- enum TimeEventFrequency {
5
- case everySecond
6
- case everyHalfSecond
7
- case everyQuarterSecond
8
- case custom(time: CMTime)
9
-
10
- func getTime() -> CMTime {
11
- switch self {
12
- case .everySecond: CMTime(value: 1, timescale: 1)
13
- case .everyHalfSecond: CMTime(value: 1, timescale: 2)
14
- case .everyQuarterSecond: CMTime(value: 1, timescale: 4)
15
- case let .custom(time): time
16
- }
17
- }
18
- }
@@ -1,99 +0,0 @@
1
- import AVFoundation
2
- import os.log
3
-
4
- /// AVPlayer's `seek(to:)` is a no-op when there's no loaded `currentItem`,
5
- /// so we must manually defer seeks that arrive during loading and execute them
6
- /// once the AVPlayerItem is ready. This coordinator encapsulates the three
7
- /// sub-problems (capture, execute, coordinate) that were previously spread
8
- /// across `pendingSeek`, `loadSeekInFlight`, and guards in multiple callbacks.
9
- @MainActor
10
- final class LoadSeekCoordinator {
11
- enum State {
12
- case idle
13
- case pendingSeek(time: TimeInterval)
14
- case seekInFlight(time: TimeInterval)
15
- }
16
-
17
- private let logger = Logger(subsystem: "com.audiobrowser", category: "LoadSeekCoordinator")
18
- private(set) var state: State = .idle
19
-
20
- /// Identifies the item epoch a seek was issued against. `reset()` (called on
21
- /// track/queue changes) bumps it, so the completion of a seek issued against
22
- /// the previous item can recognize itself as stale and be dropped — a
23
- /// cancelled cross-item completion arriving after the new track's start
24
- /// position was captured would otherwise consume or prematurely resolve it.
25
- private(set) var generation = 0
26
-
27
- func isCurrentGeneration(_ generation: Int) -> Bool {
28
- generation == self.generation
29
- }
30
-
31
- /// Used by `seekBy()` to offset from the deferred position.
32
- var pendingTime: TimeInterval? {
33
- switch state {
34
- case let .pendingSeek(time): time
35
- case let .seekInFlight(time): time
36
- case .idle: nil
37
- }
38
- }
39
-
40
- var shouldDeferReadyTransition: Bool {
41
- switch state {
42
- case .idle: false
43
- case .pendingSeek, .seekInFlight: true
44
- }
45
- }
46
-
47
- func capture(position: Double) {
48
- if case .seekInFlight = state {
49
- logger.debug("overriding in-flight seek with new target \(position)s")
50
- }
51
- state = .pendingSeek(time: position)
52
- logger.debug("captured pending seek to \(position)s")
53
- }
54
-
55
- /// Returns `true` if a seek was initiated -- caller should NOT transition to `.ready` yet.
56
- func executeIfPending(on player: AVPlayer, delegate: (any SeekCompletionHandler)?) -> Bool {
57
- guard case let .pendingSeek(time) = state else { return false }
58
-
59
- logger.debug("executing deferred seek to \(time)s")
60
- state = .seekInFlight(time: time)
61
-
62
- let cmTime = CMTime(seconds: time, preferredTimescale: 1000)
63
- let generation = generation
64
- player
65
- .seek(to: cmTime, toleranceBefore: CMTime.zero, toleranceAfter: CMTime.zero) {
66
- [weak self] finished in
67
- Task { @MainActor in
68
- guard let self, self.isCurrentGeneration(generation) else { return }
69
- delegate?.handleSeekCompleted(to: time, didFinish: finished)
70
- }
71
- }
72
-
73
- return true
74
- }
75
-
76
- /// Returns `true` if done (caller should transition `.loading` -> `.ready`).
77
- /// Returns `false` if a new seek was queued while in-flight (re-executes automatically).
78
- func seekDidComplete(on player: AVPlayer, delegate: (any SeekCompletionHandler)?) -> Bool {
79
- switch state {
80
- case .seekInFlight:
81
- logger.debug("seek landed, clearing coordinator")
82
- state = .idle
83
- return true
84
- case .pendingSeek:
85
- // A new seek arrived while the previous one was in-flight.
86
- // Execute it now -- don't transition to .ready yet.
87
- logger.debug("seek landed, but a new seek is pending -- re-executing")
88
- _ = executeIfPending(on: player, delegate: delegate)
89
- return false
90
- case .idle:
91
- return false
92
- }
93
- }
94
-
95
- func reset() {
96
- state = .idle
97
- generation += 1
98
- }
99
- }
@@ -1,11 +0,0 @@
1
- import AVFoundation
2
-
3
- @MainActor protocol MediaLoaderDelegate: AnyObject {
4
- func mediaLoaderDidPrepareItem(_ item: AVPlayerItem)
5
- func mediaLoaderDidFailWithUnplayableTrack()
6
- func mediaLoaderDidFailWithRetryableError(_ error: Error)
7
- func mediaLoaderDidFailWithError(_ error: TrackPlayerError.PlaybackError)
8
- func mediaLoaderDidReceiveCommonMetadata(_ items: [AVMetadataItem])
9
- func mediaLoaderDidReceiveChapterMetadata(_ groups: [AVTimedMetadataGroup])
10
- func mediaLoaderDidReceiveTimedMetadata(_ groups: [AVTimedMetadataGroup])
11
- }