react-native-audio-browser 0.2.0-next.28 → 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 (137) hide show
  1. package/android/src/main/java/com/audiobrowser/browser/BrowserUrlResolution.kt +3 -4
  2. package/android/src/test/java/com/audiobrowser/browser/BrowserUrlResolutionTest.kt +2 -2
  3. package/ios/AVPlayerEngine.swift +334 -0
  4. package/ios/AVPlayerEngineCallbacks.swift +15 -0
  5. package/ios/Browser/BrowseGate.swift +58 -0
  6. package/ios/Browser/BrowserConfig.swift +31 -89
  7. package/ios/Browser/BrowserManager.swift +68 -487
  8. package/ios/Browser/NavigationErrorState.swift +41 -0
  9. package/ios/Browser/PageResolver.swift +227 -0
  10. package/ios/Browser/RequestLayer.swift +90 -0
  11. package/ios/Browser/{BrowserManager+URLResolution.swift → RequestPipeline.swift} +175 -107
  12. package/ios/CarPlay/CPInterfaceController+Safe.swift +11 -24
  13. package/ios/CarPlay/CarPlayArtworkResolver.swift +35 -83
  14. package/ios/CarPlay/CarPlayController.swift +42 -1442
  15. package/ios/CarPlay/CarPlayImageLoader.swift +42 -83
  16. package/ios/CarPlay/CarPlayListItemFactory.swift +9 -23
  17. package/ios/CarPlay/CarPlayNowPlayingManager.swift +119 -129
  18. package/ios/CarPlay/CarPlaySession+Navigator.swift +114 -0
  19. package/ios/CarPlay/CarPlaySession+PageLoader.swift +92 -0
  20. package/ios/CarPlay/CarPlaySession+Refresher.swift +43 -0
  21. package/ios/CarPlay/CarPlaySession+TabBar.swift +193 -0
  22. package/ios/CarPlay/CarPlaySession.swift +209 -0
  23. package/ios/CarPlay/CarPlayTemplates.swift +63 -0
  24. package/ios/CarPlay/HybridAudioBrowser+IntentFavorite.swift +20 -0
  25. package/ios/CarPlay/MediaIntentPlayback.swift +74 -0
  26. package/ios/CarPlay/RNABMediaAddHandler.swift +2 -18
  27. package/ios/CarPlay/RNABMediaAffinityHandler.swift +5 -21
  28. package/ios/CarPlay/RNABMediaIntentHandler.swift +2 -3
  29. package/ios/Extension/NavigationError+Conversion.swift +7 -4
  30. package/ios/Extension/UIImage+Adaptive.swift +12 -0
  31. package/ios/Extension/URLError+Connectivity.swift +15 -0
  32. package/ios/Http/HttpClient.swift +63 -145
  33. package/ios/HybridAudioBrowser+Browser.swift +153 -0
  34. package/ios/HybridAudioBrowser+Options.swift +144 -0
  35. package/ios/HybridAudioBrowser+Player.swift +397 -0
  36. package/ios/HybridAudioBrowser+PlayerCallbacks.swift +190 -0
  37. package/ios/HybridAudioBrowser+Stubs.swift +46 -0
  38. package/ios/HybridAudioBrowser.swift +74 -1687
  39. package/ios/Model/NitroTypeStubs.swift +18 -1
  40. package/ios/Model/PlayerUpdateOptions.swift +1 -1
  41. package/ios/NowPlayingInfo/NowPlayingInfoController.swift +18 -53
  42. package/ios/Observer/ItemObserver.swift +90 -0
  43. package/ios/Observer/PlayerObserver.swift +59 -0
  44. package/ios/Option/SessionCategories.swift +41 -92
  45. package/ios/Player/AudioSessionController.swift +177 -0
  46. package/ios/Player/DeferredSeek.swift +70 -0
  47. package/ios/Player/ErrorStatus.swift +27 -0
  48. package/ios/Player/MediaLoader.swift +24 -11
  49. package/ios/Player/NowPlayingUpdater.swift +157 -58
  50. package/ios/Player/PlaybackFailure.swift +125 -0
  51. package/ios/Player/PlaybackPersistence.swift +73 -0
  52. package/ios/Player/Player.swift +1083 -0
  53. package/ios/Player/{PlaybackCoordinatorCallbacks.swift → PlayerCallbacks.swift} +3 -4
  54. package/ios/Player/PlayerEngine.swift +89 -0
  55. package/ios/Player/PlayerStatusTypes.swift +2 -6
  56. package/ios/Player/QueueManager.swift +52 -59
  57. package/ios/Player/RetryLoop.swift +261 -0
  58. package/ios/Player/SleepTimerManager.swift +1 -1
  59. package/ios/RemoteCommand/RemoteCommandCallbacks.swift +2 -3
  60. package/ios/RemoteCommand/RemoteCommandController.swift +85 -367
  61. package/ios/Tests/CarPlayArtworkResolverTests.swift +60 -356
  62. package/ios/Tests/DeferredSeekTests.swift +70 -0
  63. package/ios/Tests/EmitterTests.swift +29 -0
  64. package/ios/Tests/GenerationMemoTests.swift +121 -0
  65. package/ios/Tests/LRUCacheTests.swift +4 -5
  66. package/ios/Tests/MediaLoaderTests.swift +12 -33
  67. package/ios/Tests/ObserverTests.swift +88 -0
  68. package/ios/Tests/PlaybackErrorTests.swift +76 -0
  69. package/ios/Tests/PlaybackFailureTests.swift +189 -0
  70. package/ios/Tests/PlaybackPersistenceTests.swift +93 -0
  71. package/ios/Tests/PlayerPolicyTests.swift +405 -0
  72. package/ios/Tests/{PlaybackCoordinatorTests.swift → PlayerTests.swift} +298 -248
  73. package/ios/Tests/PlayingStateTests.swift +42 -0
  74. package/ios/Tests/QueueManagerTests.swift +76 -107
  75. package/ios/Tests/ReadyValueTests.swift +73 -0
  76. package/ios/Tests/RemoteCommandControllerTests.swift +10 -30
  77. package/ios/Tests/RemoteCommandTests.swift +2 -4
  78. package/ios/Tests/RequestLayerTests.swift +112 -0
  79. package/ios/Tests/RetryLoopTests.swift +270 -0
  80. package/ios/Tests/Support/TestTypes.swift +111 -112
  81. package/ios/Tests/TrackIdTemplateTests.swift +1 -1
  82. package/ios/Tests/URLErrorConnectivityTests.swift +20 -0
  83. package/ios/TrackSelector.swift +1 -1
  84. package/ios/Util/ArtworkImageFetcher.swift +42 -0
  85. package/ios/Util/Emitter.swift +42 -0
  86. package/ios/Util/GenerationMemo.swift +36 -0
  87. package/ios/Util/LRUCache.swift +23 -162
  88. package/ios/Util/NetworkMonitor.swift +1 -1
  89. package/ios/Util/ReadyValue.swift +56 -0
  90. package/ios/Util/SFSymbolRenderer.swift +35 -29
  91. package/ios/Util/SVGProcessor.swift +0 -10
  92. package/lib/commonjs/web/NativeAudioBrowser.js +1 -1
  93. package/lib/commonjs/web/TrackPlayer/PlayingStateFactory.js +1 -1
  94. package/lib/module/web/NativeAudioBrowser.js +1 -1
  95. package/lib/module/web/TrackPlayer/PlayingStateFactory.js +1 -1
  96. package/lib/typescript/src/types/browser.d.ts +3 -3
  97. package/package.json +1 -1
  98. package/src/types/browser.ts +3 -3
  99. package/src/web/NativeAudioBrowser.ts +1 -1
  100. package/src/web/TrackPlayer/PlayingStateFactory.test.ts +1 -1
  101. package/src/web/TrackPlayer/PlayingStateFactory.ts +1 -1
  102. package/ios/Bridge.h +0 -8
  103. package/ios/Browser/MediaResolveComposer.swift +0 -114
  104. package/ios/NowPlayingInfo/MediaItemProperty.swift +0 -78
  105. package/ios/NowPlayingInfo/NowPlayingInfoKeyValue.swift +0 -6
  106. package/ios/NowPlayingInfo/NowPlayingInfoProperty.swift +0 -220
  107. package/ios/Observer/PlayerItemNotificationObserver.swift +0 -119
  108. package/ios/Observer/PlayerItemPropertyObserver.swift +0 -133
  109. package/ios/Observer/PlayerStateObserver.swift +0 -50
  110. package/ios/Observer/PlayerTimeObserver.swift +0 -55
  111. package/ios/Option/PitchAlgorithms.swift +0 -17
  112. package/ios/Option/TimeEventFrequency.swift +0 -18
  113. package/ios/Player/LoadSeekCoordinator.swift +0 -99
  114. package/ios/Player/MediaLoaderDelegate.swift +0 -11
  115. package/ios/Player/PlaybackCoordinator.swift +0 -761
  116. package/ios/Player/PlaybackEffectHandler.swift +0 -54
  117. package/ios/Player/PlaybackErrorHandler.swift +0 -175
  118. package/ios/Player/PlaybackStateStore.swift +0 -27
  119. package/ios/Player/PlayingStateManager.swift +0 -33
  120. package/ios/Player/RetryManager.swift +0 -384
  121. package/ios/Player/SeekCompletionHandler.swift +0 -5
  122. package/ios/Player/SleepTimerHandling.swift +0 -28
  123. package/ios/Support/RNTrackPlayer-Bridging-Header.h +0 -7
  124. package/ios/Tests/LoadSeekCoordinatorTests.swift +0 -327
  125. package/ios/Tests/MediaResolveTests.swift +0 -126
  126. package/ios/Tests/OnceValueTests.swift +0 -79
  127. package/ios/Tests/PlaybackErrorHandlerTests.swift +0 -549
  128. package/ios/Tests/PlaybackStateStoreTests.swift +0 -49
  129. package/ios/Tests/PlayerTimeObserverTests.swift +0 -37
  130. package/ios/Tests/PlayingStateManagerTests.swift +0 -57
  131. package/ios/Tests/RetryManagerTests.swift +0 -178
  132. package/ios/TrackPlayer.swift +0 -1042
  133. package/ios/TrackPlayerCallbacks.swift +0 -53
  134. package/ios/Util/MetadataAdapter.swift +0 -131
  135. package/ios/Util/OnceValue.swift +0 -104
  136. /package/ios/{Player → CarPlay}/MediaIntentCriteria.swift +0 -0
  137. /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
- }