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
@@ -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
+ }