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
@@ -0,0 +1,190 @@
1
+ import AVFoundation
2
+ import AVKit
3
+ import Foundation
4
+ import MediaPlayer
5
+ import NitroModules
6
+ import os.log
7
+
8
+ // MARK: - PlayerCallbacks, AVPlayerEngineCallbacks
9
+
10
+ extension HybridAudioBrowser: PlayerCallbacks, AVPlayerEngineCallbacks {
11
+ public func playerDidChangePlayback(_ playback: Playback) {
12
+ onPlaybackChanged(playback)
13
+ // The Player sets the error before this fires, so the error line renders.
14
+ engine?.nowPlayingUpdater.render()
15
+ }
16
+
17
+ public func playerDidChangeActiveTrack(_ event: PlaybackActiveTrackChangedEvent) {
18
+ // Hydrate the active track's `favorited` from the authoritative set so JS
19
+ // consumers (useActiveTrack) match getActiveTrack()'s hydrated value — the
20
+ // Player emits the raw queue track, whose flag isn't kept in sync.
21
+ let hydrated = PlaybackActiveTrackChangedEvent(
22
+ lastIndex: event.lastIndex,
23
+ lastTrack: event.lastTrack,
24
+ lastPosition: event.lastPosition,
25
+ index: event.index,
26
+ track: event.track.map(browserManager.hydrateFavorite),
27
+ )
28
+ activeTrackChangedEmitter.emit(hydrated)
29
+ engine?.nowPlayingUpdater.trackChanged()
30
+ }
31
+
32
+ public func playerDidUpdateProgress(_ event: PlaybackProgressUpdatedEvent) {
33
+ onPlaybackProgressUpdated(event)
34
+ }
35
+
36
+ public func playerDidFirePlaybackInterval() {
37
+ onPlaybackInterval()
38
+ }
39
+
40
+ public func playerDidChangePlayWhenReady(_ playWhenReady: Bool) {
41
+ // Intent to play again is the earliest cancel signal for a pending session release.
42
+ if playWhenReady { audioSession.cancelRelease() }
43
+ onPlaybackPlayWhenReadyChanged(PlaybackPlayWhenReadyChangedEvent(playWhenReady: playWhenReady))
44
+ }
45
+
46
+ public func playerDidChangePlayingState(_ state: PlayingState) {
47
+ onPlaybackPlayingState(state)
48
+ // Lazily activate the audio session the moment playback actually produces — or is buffering to
49
+ // produce — output. This (not setup) is where we grab the session, so launching the app never
50
+ // interrupts other apps' audio; the interruption only happens when the user truly starts
51
+ // playback, which is correct. Keyed off play *state*, not `playWhenReady`, because the intent
52
+ // can be set at setup (before any track) while output only begins here. Idempotent:
53
+ // `setActive(true)` is a no-op when the session is already active.
54
+ if state.playing || state.buffering {
55
+ audioSession.activate()
56
+ // The now-playing session's activation request at link time predates this
57
+ // (the audio session was still inactive, and the system may have declined);
58
+ // re-request now so the surface can appear even if playback never produces
59
+ // audio (first-ever load failing on a dead stream).
60
+ engine?.reactivateNowPlayingSession()
61
+ }
62
+ // A stall starting or recovering may not change the Player state.
63
+ engine?.nowPlayingUpdater.render()
64
+ }
65
+
66
+ public func playerShouldReleaseSession() {
67
+ audioSession.scheduleRelease()
68
+ }
69
+
70
+ public func playerDidEndQueue(_ event: PlaybackQueueEndedEvent) {
71
+ onPlaybackQueueEnded(event)
72
+ }
73
+
74
+ public func playerDidChangeQueue(_ tracks: [Track]) {
75
+ queueChangedEmitter.emit(tracks)
76
+ }
77
+
78
+ public func playerDidChangeRepeatMode(_ event: RepeatModeChangedEvent) {
79
+ repeatModeChangedEmitter.emit(event)
80
+ }
81
+
82
+ public func playerDidChangeShuffleEnabled(_ enabled: Bool) {
83
+ shuffleChangedEmitter.emit(enabled)
84
+ onPlaybackShuffleModeChanged(enabled)
85
+ }
86
+
87
+ public func playerDidError(_ event: PlaybackErrorEvent) {
88
+ onPlaybackError(event)
89
+ }
90
+
91
+ public func playerDidChangeSleepTimer(_ state: SleepTimer?) {
92
+ onSleepTimerChanged(state)
93
+ }
94
+
95
+ public func playerDidChangeNowPlaying(_ metadata: NowPlayingMetadata) {
96
+ onNowPlayingChanged(metadata)
97
+ }
98
+
99
+ public func playerDidReceiveCommonMetadata(_ items: [AVMetadataItem]) {
100
+ let metadata = TrackMetadata.from(items: items)
101
+ onTrackMetadata(metadata)
102
+ }
103
+
104
+ public func playerDidReceiveTimedMetadata(_ groups: [AVTimedMetadataGroup]) {
105
+ for group in groups {
106
+ if let metadata = TimedMetadata.from(items: group.items, icyCharset: player?.currentTrack?.icyCharset) {
107
+ onTimedMetadata(metadata)
108
+ engine?.nowPlayingUpdater.receivedTimedMetadata(metadata)
109
+ }
110
+ }
111
+ }
112
+
113
+ public func playerDidReceiveChapterMetadata(_ groups: [AVTimedMetadataGroup]) {
114
+ let chapters = ChapterMetadata.from(groups: groups)
115
+ onChapterMetadata(chapters)
116
+ }
117
+
118
+ public func remotePlay() {
119
+ dispatchRemote(handler: handleRemotePlay, report: onRemotePlay) { player?.play() }
120
+ }
121
+
122
+ public func remotePause() {
123
+ dispatchRemote(handler: handleRemotePause, report: onRemotePause) { player?.pause() }
124
+ }
125
+
126
+ public func remoteStop() {
127
+ dispatchRemote(handler: handleRemoteStop, report: onRemoteStop) { player?.stop() }
128
+ }
129
+
130
+ public func remotePlayPause() {
131
+ if player?.playWhenReady == true { remotePause() } else { remotePlay() }
132
+ }
133
+
134
+ public func remoteNext() {
135
+ dispatchRemote(handler: handleRemoteNext, report: onRemoteNext) { player?.next() }
136
+ }
137
+
138
+ public func remotePrevious() {
139
+ dispatchRemote(handler: handleRemotePrevious, report: onRemotePrevious) { player?.previous() }
140
+ }
141
+
142
+ public func remoteJumpForward(interval: Double) {
143
+ dispatchRemote(
144
+ RemoteJumpForwardEvent(interval: interval), handler: handleRemoteJumpForward, report: onRemoteJumpForward,
145
+ ) { player?.seek(by: interval) }
146
+ }
147
+
148
+ public func remoteJumpBackward(interval: Double) {
149
+ dispatchRemote(
150
+ RemoteJumpBackwardEvent(interval: interval), handler: handleRemoteJumpBackward, report: onRemoteJumpBackward,
151
+ ) { player?.seek(by: -interval) }
152
+ }
153
+
154
+ public func remoteSeek(position: Double) {
155
+ dispatchRemote(RemoteSeekEvent(position: position), handler: handleRemoteSeek, report: onRemoteSeek) {
156
+ player?.seek(to: position)
157
+ }
158
+ }
159
+
160
+ /// Runs JS's override for a remote command when it set one, else `fallback`, then reports
161
+ /// the command to JS.
162
+ private func dispatchRemote(handler: (() -> Void)?, report: () -> Void, fallback: () -> Void) {
163
+ if let handler { handler() } else { fallback() }
164
+ report()
165
+ }
166
+
167
+ private func dispatchRemote<Event>(
168
+ _ event: Event,
169
+ handler: ((Event) -> Void)?,
170
+ report: (Event) -> Void,
171
+ fallback: () -> Void,
172
+ ) {
173
+ if let handler { handler(event) } else { fallback() }
174
+ report(event)
175
+ }
176
+
177
+ public func remoteChangeRepeatMode(mode: RepeatMode) {
178
+ // Apply the repeat mode change from CarPlay/lock screen
179
+ try? setRepeatMode(mode: mode)
180
+ }
181
+
182
+ public func remoteChangeShuffleMode(enabled: Bool) {
183
+ // Apply the shuffle mode change from CarPlay/lock screen
184
+ try? setShuffleEnabled(enabled: enabled)
185
+ }
186
+
187
+ public func remoteChangePlaybackRate(rate: Float) {
188
+ player?.rate = rate
189
+ }
190
+ }
@@ -0,0 +1,46 @@
1
+ import AVFoundation
2
+ import AVKit
3
+ import Foundation
4
+ import MediaPlayer
5
+ import NitroModules
6
+ import os.log
7
+
8
+ public extension HybridAudioBrowser {
9
+ // MARK: - Equalizer (unsupported on iOS)
10
+
11
+ func getEqualizerSettings() throws -> EqualizerSettings? {
12
+ // No-op: equalizer unsupported on iOS
13
+ nil
14
+ }
15
+
16
+ func setEqualizerEnabled(enabled _: Bool) throws {
17
+ // No-op: equalizer unsupported on iOS
18
+ }
19
+
20
+ func setEqualizerPreset(preset _: String) throws {
21
+ // No-op: equalizer unsupported on iOS
22
+ }
23
+
24
+ func setEqualizerLevels(levels _: [Double]) throws {
25
+ // No-op: equalizer unsupported on iOS
26
+ }
27
+
28
+ // MARK: - Battery (Android-only, stub implementations)
29
+
30
+ func getBatteryWarningPending() throws -> Bool {
31
+ false
32
+ }
33
+
34
+ func getBatteryOptimizationStatus() throws -> BatteryOptimizationStatus {
35
+ // iOS doesn't have battery optimization restrictions like Android
36
+ .unrestricted
37
+ }
38
+
39
+ func dismissBatteryWarning() throws {
40
+ // No-op on iOS
41
+ }
42
+
43
+ func openBatterySettings() throws {
44
+ // No-op on iOS
45
+ }
46
+ }