react-native-audio-browser 0.2.0-next.9 → 0.2.0

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 (975) hide show
  1. package/AudioBrowser.podspec +1 -1
  2. package/README.md +2 -180
  3. package/android/build.gradle +1 -17
  4. package/android/gradle.properties +1 -1
  5. package/android/src/main/AndroidManifest.xml +0 -15
  6. package/android/src/main/java/com/audiobrowser/AudioBrowser.kt +148 -433
  7. package/android/src/main/java/com/audiobrowser/Callbacks.kt +6 -4
  8. package/android/src/main/java/com/audiobrowser/Service.kt +18 -67
  9. package/android/src/main/java/com/audiobrowser/browser/BrowserManager.kt +178 -442
  10. package/android/src/main/java/com/audiobrowser/browser/JsonModels.kt +4 -41
  11. package/android/src/main/java/com/audiobrowser/browser/TrackLoadHandler.kt +4 -4
  12. package/android/src/main/java/com/audiobrowser/http/RequestConfigBuilder.kt +97 -109
  13. package/android/src/main/java/com/audiobrowser/model/PlaybackMetadata.kt +10 -6
  14. package/android/src/main/java/com/audiobrowser/model/PlayerSetupOptions.kt +8 -40
  15. package/android/src/main/java/com/audiobrowser/model/PlayerUpdateOptions.kt +46 -40
  16. package/android/src/main/java/com/audiobrowser/player/AutomaticBufferManager.kt +1 -4
  17. package/android/src/main/java/com/audiobrowser/player/DynamicLoadControl.kt +1 -18
  18. package/android/src/main/java/com/audiobrowser/player/MediaFactory.kt +3 -15
  19. package/android/src/main/java/com/audiobrowser/player/MediaSessionCallback.kt +134 -422
  20. package/android/src/main/java/com/audiobrowser/player/MediaSessionCommandManager.kt +404 -248
  21. package/android/src/main/java/com/audiobrowser/player/PlaybackProgressUpdateManager.kt +59 -0
  22. package/android/src/main/java/com/audiobrowser/player/PlaybackStateStore.kt +5 -25
  23. package/android/src/main/java/com/audiobrowser/player/Player.kt +582 -469
  24. package/android/src/main/java/com/audiobrowser/player/PlayerListener.kt +67 -190
  25. package/android/src/main/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicy.kt +53 -118
  26. package/android/src/main/java/com/audiobrowser/player/SleepTimer.kt +3 -37
  27. package/android/src/main/java/com/audiobrowser/player/TransformingDataSource.kt +40 -85
  28. package/android/src/main/java/com/audiobrowser/util/BrowserPathHelper.kt +0 -24
  29. package/android/src/main/java/com/audiobrowser/util/CoilBitmapLoader.kt +300 -23
  30. package/android/src/main/java/com/audiobrowser/util/EqualizerManager.kt +23 -13
  31. package/android/src/main/java/com/audiobrowser/util/MediaExtrasBuilder.kt +2 -2
  32. package/android/src/main/java/com/audiobrowser/util/MetadataAdapter.kt +3 -4
  33. package/android/src/main/java/com/audiobrowser/util/PlayingStateFactory.kt +1 -2
  34. package/android/src/main/java/com/audiobrowser/util/RatingFactory.kt +72 -0
  35. package/android/src/main/java/com/audiobrowser/util/ResolvedTrackFactory.kt +36 -0
  36. package/android/src/main/java/com/audiobrowser/util/SvgArtworkRenderer.kt +111 -6
  37. package/android/src/main/java/com/audiobrowser/util/SystemVolumeMonitor.kt +8 -22
  38. package/android/src/main/java/com/audiobrowser/util/TrackFactory.kt +80 -112
  39. package/android/src/main/res/values/strings.xml +0 -4
  40. package/android/src/test/java/com/audiobrowser/browser/BrowserManagerTest.kt +0 -4
  41. package/android/src/test/java/com/audiobrowser/browser/SimpleRouterTest.kt +2 -1
  42. package/android/src/test/java/com/audiobrowser/http/RequestConfigBuilderTest.kt +0 -72
  43. package/android/src/test/java/com/audiobrowser/player/PlaybackProgressUpdateManagerTest.kt +146 -0
  44. package/ios/Browser/BrowserConfig.swift +11 -41
  45. package/ios/Browser/BrowserManager+URLResolution.swift +93 -213
  46. package/ios/Browser/BrowserManager.swift +110 -303
  47. package/ios/Browser/BrowserPathHelper.swift +3 -32
  48. package/ios/Browser/JsonModels.swift +66 -287
  49. package/ios/CarPlay/CarPlayArtworkResolver.swift +6 -6
  50. package/ios/CarPlay/CarPlayController.swift +149 -739
  51. package/ios/CarPlay/CarPlayImageLoader.swift +8 -57
  52. package/ios/CarPlay/CarPlayListItemFactory.swift +35 -44
  53. package/ios/CarPlay/CarPlayNowPlayingManager.swift +36 -180
  54. package/ios/CarPlay/RNABAudioBrowser.h +10 -15
  55. package/ios/CarPlay/RNABAudioBrowser.m +14 -15
  56. package/ios/CarPlay/RNABCarPlaySceneDelegate.m +0 -2
  57. package/ios/CarPlay/RNABMediaIntentHandler.swift +43 -53
  58. package/ios/CarPlay/Track+CarPlay.swift +63 -0
  59. package/ios/Extension/Capability+RemoteCommand.swift +9 -7
  60. package/ios/Extension/ChapterMetadata+AVFoundation.swift +1 -1
  61. package/ios/Extension/NavigationError+Conversion.swift +1 -8
  62. package/ios/Extension/ResolvedTrack+Copying.swift +4 -10
  63. package/ios/Extension/TimedMetadata+AVFoundation.swift +1 -1
  64. package/ios/Extension/Track+AVPlayer.swift +4 -4
  65. package/ios/Extension/Track+Copying.swift +3 -9
  66. package/ios/Extension/TrackMetadata+AVFoundation.swift +1 -1
  67. package/ios/HybridAudioBrowser.swift +196 -804
  68. package/ios/Model/NitroTypeStubs.swift +224 -299
  69. package/ios/Model/PlayerUpdateOptions.swift +23 -23
  70. package/ios/Model/RemoteCommand.swift +6 -24
  71. package/ios/Model/TrackPlayerError.swift +18 -82
  72. package/ios/NowPlayingInfo/NowPlayingInfoCenter.swift +9 -0
  73. package/ios/NowPlayingInfo/NowPlayingInfoController.swift +121 -99
  74. package/ios/Observer/PlayerItemNotificationObserver.swift +5 -45
  75. package/ios/Observer/PlayerItemPropertyObserver.swift +4 -27
  76. package/ios/Observer/PlayerTimeObserver.swift +53 -3
  77. package/ios/Option/SessionCategories.swift +11 -34
  78. package/ios/Player/LoadSeekCoordinator.swift +1 -16
  79. package/ios/Player/MediaLoader.swift +11 -31
  80. package/ios/Player/NowPlayingUpdater.swift +26 -119
  81. package/ios/Player/PlaybackCoordinator.swift +51 -285
  82. package/ios/Player/PlaybackCoordinatorCallbacks.swift +1 -6
  83. package/ios/Player/PlaybackEffectHandler.swift +9 -19
  84. package/ios/Player/PlaybackErrorHandler.swift +13 -97
  85. package/ios/Player/PlaybackProgressUpdateManager.swift +68 -0
  86. package/ios/Player/PlaybackStateMachine.swift +13 -18
  87. package/ios/Player/PlayingStateManager.swift +2 -3
  88. package/ios/Player/QueueManager.swift +61 -67
  89. package/ios/Player/RetryManager.swift +21 -98
  90. package/ios/Player/SleepTimerHandling.swift +0 -8
  91. package/ios/Player/SleepTimerManager.swift +11 -72
  92. package/ios/RemoteCommand/RemoteCommandController.swift +21 -40
  93. package/ios/Tests/BrowserPathHelperTests.swift +0 -28
  94. package/ios/Tests/CarPlayArtworkResolverTests.swift +39 -39
  95. package/ios/Tests/ChapterMetadataAVFoundationTests.swift +2 -2
  96. package/ios/Tests/LoadSeekCoordinatorTests.swift +7 -40
  97. package/ios/Tests/MediaLoaderTests.swift +20 -32
  98. package/ios/Tests/PlaybackCoordinatorTests.swift +13 -787
  99. package/ios/Tests/PlaybackErrorHandlerTests.swift +46 -380
  100. package/ios/Tests/PlaybackProgressUpdateManagerTests.swift +166 -0
  101. package/ios/Tests/PlaybackStateMachineTests.swift +8 -33
  102. package/ios/Tests/QueueManagerTests.swift +18 -149
  103. package/ios/Tests/ResolvedTrackCopyingTests.swift +8 -15
  104. package/ios/Tests/Support/TestTypes.swift +20 -61
  105. package/ios/Tests/TrackSelectorTests.swift +15 -15
  106. package/ios/TrackPlayer.swift +58 -380
  107. package/ios/TrackPlayerCallbacks.swift +44 -5
  108. package/ios/TrackSelector.swift +5 -5
  109. package/ios/Util/ArtworkImageFetcher.swift +2 -4
  110. package/ios/Util/NetworkMonitor.swift +3 -7
  111. package/ios/Util/OnceValue.swift +0 -34
  112. package/lib/commonjs/AudioBrowser.js +11 -0
  113. package/lib/commonjs/AudioBrowser.js.map +1 -1
  114. package/lib/commonjs/features/browser.js +158 -59
  115. package/lib/commonjs/features/browser.js.map +1 -1
  116. package/lib/commonjs/features/equalizer.js +1 -1
  117. package/lib/commonjs/features/errors.js +5 -37
  118. package/lib/commonjs/features/errors.js.map +1 -1
  119. package/lib/commonjs/features/favorites.js +1 -1
  120. package/lib/commonjs/features/index.js +0 -22
  121. package/lib/commonjs/features/index.js.map +1 -1
  122. package/lib/commonjs/features/metadata.js +3 -3
  123. package/lib/commonjs/features/metadata.js.map +1 -1
  124. package/lib/commonjs/features/network.js +1 -1
  125. package/lib/commonjs/features/nowPlaying.js +1 -36
  126. package/lib/commonjs/features/nowPlaying.js.map +1 -1
  127. package/lib/commonjs/features/output.js +23 -37
  128. package/lib/commonjs/features/output.js.map +1 -1
  129. package/lib/commonjs/features/playback/controls.js +0 -9
  130. package/lib/commonjs/features/playback/controls.js.map +1 -1
  131. package/lib/commonjs/features/playback/index.js +0 -11
  132. package/lib/commonjs/features/playback/index.js.map +1 -1
  133. package/lib/commonjs/features/playback/playWhenReady.js +1 -1
  134. package/lib/commonjs/features/playback/playing.js +1 -1
  135. package/lib/commonjs/features/playback/progress.js +13 -29
  136. package/lib/commonjs/features/playback/progress.js.map +1 -1
  137. package/lib/commonjs/features/playback/state.js +1 -1
  138. package/lib/commonjs/features/playback/volume.js +2 -2
  139. package/lib/commonjs/features/player/options.js +29 -79
  140. package/lib/commonjs/features/player/options.js.map +1 -1
  141. package/lib/commonjs/features/player/setup.js +3 -256
  142. package/lib/commonjs/features/player/setup.js.map +1 -1
  143. package/lib/commonjs/features/queue/activeTrack.js +1 -1
  144. package/lib/commonjs/features/queue/queue.js +5 -12
  145. package/lib/commonjs/features/queue/queue.js.map +1 -1
  146. package/lib/commonjs/features/queue/repeatMode.js +1 -1
  147. package/lib/commonjs/features/queue/shuffle.js +1 -1
  148. package/lib/commonjs/features/rating.js +2 -0
  149. package/lib/commonjs/features/rating.js.map +1 -0
  150. package/lib/commonjs/features/remoteControls.js +104 -14
  151. package/lib/commonjs/features/remoteControls.js.map +1 -1
  152. package/lib/commonjs/features/sleepTimer.js +5 -10
  153. package/lib/commonjs/features/sleepTimer.js.map +1 -1
  154. package/lib/commonjs/native.js +0 -5
  155. package/lib/commonjs/native.js.map +1 -1
  156. package/lib/commonjs/native.web.js +1 -4
  157. package/lib/commonjs/native.web.js.map +1 -1
  158. package/lib/commonjs/types/player.js +2 -0
  159. package/lib/commonjs/types/player.js.map +1 -0
  160. package/lib/commonjs/utils/LazyNativeEmitter.js +8 -8
  161. package/lib/commonjs/utils/LazyNativeEmitter.js.map +1 -1
  162. package/lib/commonjs/utils/NativeUpdatedValue.js +3 -0
  163. package/lib/commonjs/utils/NativeUpdatedValue.js.map +1 -1
  164. package/lib/commonjs/web/NativeAudioBrowser.js +124 -301
  165. package/lib/commonjs/web/NativeAudioBrowser.js.map +1 -1
  166. package/lib/commonjs/web/SimpleRouter.test.js +174 -0
  167. package/lib/commonjs/web/SimpleRouter.test.js.map +1 -0
  168. package/lib/commonjs/web/TrackPlayer/Player.js +26 -90
  169. package/lib/commonjs/web/TrackPlayer/Player.js.map +1 -1
  170. package/lib/commonjs/web/TrackPlayer/PlaylistPlayer.js +293 -0
  171. package/lib/commonjs/web/TrackPlayer/PlaylistPlayer.js.map +1 -0
  172. package/lib/commonjs/web/TrackPlayer/RepeatMode.js +1 -1
  173. package/lib/commonjs/web/TrackPlayer/RepeatMode.js.map +1 -1
  174. package/lib/commonjs/web/TrackPlayer/SleepTimer.js +3 -34
  175. package/lib/commonjs/web/TrackPlayer/SleepTimer.js.map +1 -1
  176. package/lib/commonjs/web/TrackPlayer/index.js +5 -13
  177. package/lib/commonjs/web/TrackPlayer/index.js.map +1 -1
  178. package/lib/commonjs/web/browser/BrowserManager.js +50 -176
  179. package/lib/commonjs/web/browser/BrowserManager.js.map +1 -1
  180. package/lib/commonjs/web/browser/NavigationErrorManager.js +1 -3
  181. package/lib/commonjs/web/browser/NavigationErrorManager.js.map +1 -1
  182. package/lib/commonjs/web/browser/SearchManager.js +9 -11
  183. package/lib/commonjs/web/browser/SearchManager.js.map +1 -1
  184. package/lib/commonjs/web/http/HttpClient.js +23 -4
  185. package/lib/commonjs/web/http/HttpClient.js.map +1 -1
  186. package/lib/commonjs/web/http/RequestConfigBuilder.js +58 -107
  187. package/lib/commonjs/web/http/RequestConfigBuilder.js.map +1 -1
  188. package/lib/commonjs/web/player/NowPlayingManager.js +5 -6
  189. package/lib/commonjs/web/player/NowPlayingManager.js.map +1 -1
  190. package/lib/commonjs/web/player/OptionsManager.js +17 -9
  191. package/lib/commonjs/web/player/OptionsManager.js.map +1 -1
  192. package/lib/module/AudioBrowser.js +1 -4
  193. package/lib/module/AudioBrowser.js.map +1 -1
  194. package/lib/module/features/browser.js +156 -53
  195. package/lib/module/features/browser.js.map +1 -1
  196. package/lib/module/features/equalizer.js +1 -1
  197. package/lib/module/features/errors.js +5 -37
  198. package/lib/module/features/errors.js.map +1 -1
  199. package/lib/module/features/favorites.js +1 -1
  200. package/lib/module/features/index.js +0 -2
  201. package/lib/module/features/index.js.map +1 -1
  202. package/lib/module/features/metadata.js +3 -3
  203. package/lib/module/features/metadata.js.map +1 -1
  204. package/lib/module/features/network.js +1 -1
  205. package/lib/module/features/nowPlaying.js +1 -34
  206. package/lib/module/features/nowPlaying.js.map +1 -1
  207. package/lib/module/features/output.js +19 -32
  208. package/lib/module/features/output.js.map +1 -1
  209. package/lib/module/features/playback/controls.js +0 -8
  210. package/lib/module/features/playback/controls.js.map +1 -1
  211. package/lib/module/features/playback/index.js +0 -1
  212. package/lib/module/features/playback/index.js.map +1 -1
  213. package/lib/module/features/playback/playWhenReady.js +1 -1
  214. package/lib/module/features/playback/playing.js +1 -1
  215. package/lib/module/features/playback/progress.js +13 -29
  216. package/lib/module/features/playback/progress.js.map +1 -1
  217. package/lib/module/features/playback/state.js +1 -1
  218. package/lib/module/features/playback/volume.js +2 -2
  219. package/lib/module/features/player/options.js +29 -79
  220. package/lib/module/features/player/options.js.map +1 -1
  221. package/lib/module/features/player/setup.js +3 -256
  222. package/lib/module/features/player/setup.js.map +1 -1
  223. package/lib/module/features/queue/activeTrack.js +1 -1
  224. package/lib/module/features/queue/queue.js +5 -12
  225. package/lib/module/features/queue/queue.js.map +1 -1
  226. package/lib/module/features/queue/repeatMode.js +1 -1
  227. package/lib/module/features/queue/shuffle.js +1 -1
  228. package/lib/module/features/rating.js +2 -0
  229. package/lib/module/features/rating.js.map +1 -0
  230. package/lib/module/features/remoteControls.js +103 -13
  231. package/lib/module/features/remoteControls.js.map +1 -1
  232. package/lib/module/features/sleepTimer.js +5 -10
  233. package/lib/module/features/sleepTimer.js.map +1 -1
  234. package/lib/module/native.js +0 -5
  235. package/lib/module/native.js.map +1 -1
  236. package/lib/module/native.web.js +1 -4
  237. package/lib/module/native.web.js.map +1 -1
  238. package/lib/module/types/player.js +2 -0
  239. package/lib/module/types/player.js.map +1 -0
  240. package/lib/module/utils/LazyNativeEmitter.js +8 -8
  241. package/lib/module/utils/LazyNativeEmitter.js.map +1 -1
  242. package/lib/module/utils/NativeUpdatedValue.js +3 -0
  243. package/lib/module/utils/NativeUpdatedValue.js.map +1 -1
  244. package/lib/module/web/NativeAudioBrowser.js +125 -302
  245. package/lib/module/web/NativeAudioBrowser.js.map +1 -1
  246. package/lib/module/web/SimpleRouter.test.js +174 -0
  247. package/lib/module/web/SimpleRouter.test.js.map +1 -0
  248. package/lib/module/web/TrackPlayer/Player.js +26 -90
  249. package/lib/module/web/TrackPlayer/Player.js.map +1 -1
  250. package/lib/module/web/TrackPlayer/PlaylistPlayer.js +288 -0
  251. package/lib/module/web/TrackPlayer/PlaylistPlayer.js.map +1 -0
  252. package/lib/module/web/TrackPlayer/RepeatMode.js +1 -1
  253. package/lib/module/web/TrackPlayer/RepeatMode.js.map +1 -1
  254. package/lib/module/web/TrackPlayer/SleepTimer.js +3 -34
  255. package/lib/module/web/TrackPlayer/SleepTimer.js.map +1 -1
  256. package/lib/module/web/TrackPlayer/index.js +1 -2
  257. package/lib/module/web/TrackPlayer/index.js.map +1 -1
  258. package/lib/module/web/browser/BrowserManager.js +50 -176
  259. package/lib/module/web/browser/BrowserManager.js.map +1 -1
  260. package/lib/module/web/browser/NavigationErrorManager.js +1 -3
  261. package/lib/module/web/browser/NavigationErrorManager.js.map +1 -1
  262. package/lib/module/web/browser/SearchManager.js +9 -11
  263. package/lib/module/web/browser/SearchManager.js.map +1 -1
  264. package/lib/module/web/http/HttpClient.js +23 -4
  265. package/lib/module/web/http/HttpClient.js.map +1 -1
  266. package/lib/module/web/http/RequestConfigBuilder.js +58 -107
  267. package/lib/module/web/http/RequestConfigBuilder.js.map +1 -1
  268. package/lib/module/web/player/NowPlayingManager.js +5 -7
  269. package/lib/module/web/player/NowPlayingManager.js.map +1 -1
  270. package/lib/module/web/player/OptionsManager.js +17 -9
  271. package/lib/module/web/player/OptionsManager.js.map +1 -1
  272. package/lib/typescript/src/AudioBrowser.d.ts +1 -0
  273. package/lib/typescript/src/AudioBrowser.d.ts.map +1 -1
  274. package/lib/typescript/src/features/browser.d.ts +1 -40
  275. package/lib/typescript/src/features/browser.d.ts.map +1 -1
  276. package/lib/typescript/src/features/equalizer.d.ts +1 -1
  277. package/lib/typescript/src/features/errors.d.ts +6 -61
  278. package/lib/typescript/src/features/errors.d.ts.map +1 -1
  279. package/lib/typescript/src/features/favorites.d.ts +1 -1
  280. package/lib/typescript/src/features/index.d.ts +0 -2
  281. package/lib/typescript/src/features/index.d.ts.map +1 -1
  282. package/lib/typescript/src/features/metadata.d.ts +7 -9
  283. package/lib/typescript/src/features/metadata.d.ts.map +1 -1
  284. package/lib/typescript/src/features/network.d.ts +1 -1
  285. package/lib/typescript/src/features/nowPlaying.d.ts +1 -28
  286. package/lib/typescript/src/features/nowPlaying.d.ts.map +1 -1
  287. package/lib/typescript/src/features/output.d.ts +18 -28
  288. package/lib/typescript/src/features/output.d.ts.map +1 -1
  289. package/lib/typescript/src/features/playback/controls.d.ts +0 -5
  290. package/lib/typescript/src/features/playback/controls.d.ts.map +1 -1
  291. package/lib/typescript/src/features/playback/index.d.ts +0 -1
  292. package/lib/typescript/src/features/playback/index.d.ts.map +1 -1
  293. package/lib/typescript/src/features/playback/playWhenReady.d.ts +1 -1
  294. package/lib/typescript/src/features/playback/playing.d.ts +1 -1
  295. package/lib/typescript/src/features/playback/progress.d.ts +1 -4
  296. package/lib/typescript/src/features/playback/progress.d.ts.map +1 -1
  297. package/lib/typescript/src/features/playback/state.d.ts +1 -1
  298. package/lib/typescript/src/features/playback/volume.d.ts +2 -2
  299. package/lib/typescript/src/features/player/options.d.ts +127 -176
  300. package/lib/typescript/src/features/player/options.d.ts.map +1 -1
  301. package/lib/typescript/src/features/player/setup.d.ts +167 -213
  302. package/lib/typescript/src/features/player/setup.d.ts.map +1 -1
  303. package/lib/typescript/src/features/queue/activeTrack.d.ts +1 -1
  304. package/lib/typescript/src/features/queue/queue.d.ts +4 -11
  305. package/lib/typescript/src/features/queue/queue.d.ts.map +1 -1
  306. package/lib/typescript/src/features/queue/repeatMode.d.ts +1 -1
  307. package/lib/typescript/src/features/queue/shuffle.d.ts +1 -1
  308. package/lib/typescript/src/features/rating.d.ts +14 -0
  309. package/lib/typescript/src/features/rating.d.ts.map +1 -0
  310. package/lib/typescript/src/features/remoteControls.d.ts +35 -23
  311. package/lib/typescript/src/features/remoteControls.d.ts.map +1 -1
  312. package/lib/typescript/src/features/sleepTimer.d.ts +4 -19
  313. package/lib/typescript/src/features/sleepTimer.d.ts.map +1 -1
  314. package/lib/typescript/src/index.d.ts.map +1 -1
  315. package/lib/typescript/src/native.d.ts +2 -1
  316. package/lib/typescript/src/native.d.ts.map +1 -1
  317. package/lib/typescript/src/native.web.d.ts +3 -0
  318. package/lib/typescript/src/native.web.d.ts.map +1 -0
  319. package/lib/typescript/src/specs/audio-browser.nitro.d.ts +225 -17
  320. package/lib/typescript/src/specs/audio-browser.nitro.d.ts.map +1 -1
  321. package/lib/typescript/src/types/browser-native.d.ts +3 -9
  322. package/lib/typescript/src/types/browser-native.d.ts.map +1 -1
  323. package/lib/typescript/src/types/browser-nodes.d.ts +13 -145
  324. package/lib/typescript/src/types/browser-nodes.d.ts.map +1 -1
  325. package/lib/typescript/src/types/browser.d.ts +85 -349
  326. package/lib/typescript/src/types/browser.d.ts.map +1 -1
  327. package/lib/typescript/src/types/player.d.ts +64 -0
  328. package/lib/typescript/src/types/player.d.ts.map +1 -0
  329. package/lib/typescript/src/utils/LazyNativeEmitter.d.ts +6 -8
  330. package/lib/typescript/src/utils/LazyNativeEmitter.d.ts.map +1 -1
  331. package/lib/typescript/src/utils/NativeUpdatedValue.d.ts +2 -0
  332. package/lib/typescript/src/utils/NativeUpdatedValue.d.ts.map +1 -1
  333. package/lib/typescript/src/utils/resolveAssetSource.d.ts.map +1 -1
  334. package/lib/typescript/src/web/NativeAudioBrowser.d.ts +188 -0
  335. package/lib/typescript/src/web/NativeAudioBrowser.d.ts.map +1 -0
  336. package/lib/typescript/src/web/SimpleRouter.d.ts +40 -0
  337. package/lib/typescript/src/web/SimpleRouter.d.ts.map +1 -0
  338. package/lib/typescript/src/web/SimpleRouter.test.d.ts +2 -0
  339. package/lib/typescript/src/web/SimpleRouter.test.d.ts.map +1 -0
  340. package/lib/typescript/src/web/TrackPlayer/Event.d.ts +11 -0
  341. package/lib/typescript/src/web/TrackPlayer/Event.d.ts.map +1 -0
  342. package/lib/typescript/src/web/TrackPlayer/Player.d.ts +59 -0
  343. package/lib/typescript/src/web/TrackPlayer/Player.d.ts.map +1 -0
  344. package/lib/typescript/src/web/TrackPlayer/PlaylistPlayer.d.ts +39 -0
  345. package/lib/typescript/src/web/TrackPlayer/PlaylistPlayer.d.ts.map +1 -0
  346. package/lib/typescript/src/web/TrackPlayer/RepeatMode.d.ts +6 -0
  347. package/lib/typescript/src/web/TrackPlayer/RepeatMode.d.ts.map +1 -0
  348. package/lib/typescript/src/web/TrackPlayer/SetupNotCalledError.d.ts +4 -0
  349. package/lib/typescript/src/web/TrackPlayer/SetupNotCalledError.d.ts.map +1 -0
  350. package/lib/typescript/src/web/TrackPlayer/SleepTimer.d.ts +34 -0
  351. package/lib/typescript/src/web/TrackPlayer/SleepTimer.d.ts.map +1 -0
  352. package/lib/typescript/src/web/TrackPlayer/State.d.ts +13 -0
  353. package/lib/typescript/src/web/TrackPlayer/State.d.ts.map +1 -0
  354. package/lib/typescript/src/web/TrackPlayer/index.d.ts +5 -0
  355. package/lib/typescript/src/web/TrackPlayer/index.d.ts.map +1 -0
  356. package/lib/typescript/src/web/browser/BrowserManager.d.ts +154 -0
  357. package/lib/typescript/src/web/browser/BrowserManager.d.ts.map +1 -0
  358. package/lib/typescript/src/web/browser/FavoriteManager.d.ts +42 -0
  359. package/lib/typescript/src/web/browser/FavoriteManager.d.ts.map +1 -0
  360. package/lib/typescript/src/web/browser/NavigationErrorManager.d.ts +40 -0
  361. package/lib/typescript/src/web/browser/NavigationErrorManager.d.ts.map +1 -0
  362. package/lib/typescript/src/web/browser/SearchManager.d.ts +22 -0
  363. package/lib/typescript/src/web/browser/SearchManager.d.ts.map +1 -0
  364. package/lib/typescript/src/web/http/HttpClient.d.ts +25 -0
  365. package/lib/typescript/src/web/http/HttpClient.d.ts.map +1 -0
  366. package/lib/typescript/src/web/http/RequestConfigBuilder.d.ts +98 -0
  367. package/lib/typescript/src/web/http/RequestConfigBuilder.d.ts.map +1 -0
  368. package/lib/typescript/src/web/player/NowPlayingManager.d.ts +34 -0
  369. package/lib/typescript/src/web/player/NowPlayingManager.d.ts.map +1 -0
  370. package/lib/typescript/src/web/player/OptionsManager.d.ts +32 -0
  371. package/lib/typescript/src/web/player/OptionsManager.d.ts.map +1 -0
  372. package/lib/typescript/src/web/util/BrowserPathHelper.d.ts +69 -0
  373. package/lib/typescript/src/web/util/BrowserPathHelper.d.ts.map +1 -0
  374. package/lib/typescript/src/web/util/shuffle.d.ts +8 -0
  375. package/lib/typescript/src/web/util/shuffle.d.ts.map +1 -0
  376. package/nitrogen/generated/android/AudioBrowser+autolinking.cmake +2 -4
  377. package/nitrogen/generated/android/AudioBrowserOnLoad.cpp +10 -24
  378. package/nitrogen/generated/android/c++/JAndroidAudioContentType.hpp +6 -6
  379. package/nitrogen/generated/android/c++/JAndroidOptions.hpp +20 -10
  380. package/nitrogen/generated/android/c++/JAndroidUpdateOptions.hpp +86 -0
  381. package/nitrogen/generated/android/c++/JArtworkRequestConfig.hpp +1 -33
  382. package/nitrogen/generated/android/c++/JBrowseResult.hpp +0 -5
  383. package/nitrogen/generated/android/c++/JCarPlayNowPlayingButton.hpp +3 -3
  384. package/nitrogen/generated/android/c++/JFavoriteChangedEvent.hpp +0 -6
  385. package/nitrogen/generated/android/c++/JFormattedNavigationError.hpp +2 -3
  386. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____Track.hpp +0 -6
  387. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.hpp +147 -0
  388. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_Track______SearchParams.hpp +0 -8
  389. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_void_____TrackLoadEvent.hpp +0 -6
  390. package/nitrogen/generated/android/c++/JFunc_void_FavoriteChangedEvent.hpp +0 -6
  391. package/nitrogen/generated/android/c++/JFunc_void_IosOutput.hpp +80 -0
  392. package/nitrogen/generated/android/c++/JFunc_void_NowPlayingMetadata.hpp +10 -0
  393. package/nitrogen/generated/android/c++/JFunc_void_Options.hpp +9 -14
  394. package/nitrogen/generated/android/c++/JFunc_void_Playback.hpp +0 -2
  395. package/nitrogen/generated/android/c++/JFunc_void_PlaybackActiveTrackChangedEvent.hpp +0 -6
  396. package/nitrogen/generated/android/c++/JFunc_void_PlaybackErrorEvent.hpp +0 -2
  397. package/nitrogen/generated/android/c++/JFunc_void_RemoteSetRatingEvent.hpp +87 -0
  398. package/nitrogen/generated/android/c++/JFunc_void_bool.hpp +10 -10
  399. package/nitrogen/generated/android/c++/JFunc_void_std__optional_ResolvedTrack_.hpp +0 -6
  400. package/nitrogen/generated/android/c++/JFunc_void_std__vector_Track_.hpp +0 -6
  401. package/nitrogen/generated/android/c++/JHeartRating.hpp +57 -0
  402. package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.cpp +221 -245
  403. package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.hpp +22 -25
  404. package/nitrogen/generated/android/c++/JImageRowItem.hpp +3 -33
  405. package/nitrogen/generated/android/c++/{JOutput.hpp → JIosOutput.hpp} +15 -15
  406. package/nitrogen/generated/android/c++/JIosOutputType.hpp +85 -0
  407. package/nitrogen/generated/android/c++/JMediaRequestConfig.hpp +1 -33
  408. package/nitrogen/generated/android/c++/JNativeBrowserConfiguration.hpp +28 -61
  409. package/nitrogen/generated/android/c++/JNativeRouteEntry.hpp +9 -20
  410. package/nitrogen/generated/android/c++/JNativeUpdateOptions.hpp +24 -21
  411. package/nitrogen/generated/android/c++/JNavigationErrorType.hpp +0 -6
  412. package/nitrogen/generated/android/c++/JNitroAndroidUpdateOptions.hpp +20 -10
  413. package/nitrogen/generated/android/c++/{JRemoteButton.hpp → JNotificationButton.hpp} +20 -20
  414. package/nitrogen/generated/android/c++/JNotificationButtonLayout.hpp +94 -0
  415. package/nitrogen/generated/android/c++/JNowPlayingMetadata.hpp +17 -3
  416. package/nitrogen/generated/android/c++/JNowPlayingUpdate.hpp +3 -7
  417. package/nitrogen/generated/android/c++/JOptions.hpp +14 -19
  418. package/nitrogen/generated/android/c++/{JNativeAndroidSetupOptions.hpp → JPartialAndroidSetupPlayerOptions.hpp} +10 -10
  419. package/nitrogen/generated/android/c++/{JNativeIOSSetupOptions.hpp → JPartialIOSSetupPlayerOptions.hpp} +10 -10
  420. package/nitrogen/generated/android/c++/JPartialSetupPlayerOptions.hpp +96 -0
  421. package/nitrogen/generated/android/c++/JPercentageRating.hpp +57 -0
  422. package/nitrogen/generated/android/c++/JPlayback.hpp +0 -2
  423. package/nitrogen/generated/android/c++/JPlaybackActiveTrackChangedEvent.hpp +0 -6
  424. package/nitrogen/generated/android/c++/JPlaybackError.hpp +3 -18
  425. package/nitrogen/generated/android/c++/JPlaybackErrorEvent.hpp +0 -2
  426. package/nitrogen/generated/android/c++/JPlaybackState.hpp +3 -3
  427. package/nitrogen/generated/android/c++/JPlayerCapabilities.hpp +5 -11
  428. package/nitrogen/generated/android/c++/JRatingType.hpp +73 -0
  429. package/nitrogen/generated/android/c++/JRemoteSetRatingEvent.hpp +66 -0
  430. package/nitrogen/generated/android/c++/JResolvedTrack.hpp +5 -23
  431. package/nitrogen/generated/android/c++/JRetryConfig.hpp +7 -11
  432. package/nitrogen/generated/android/c++/JSearchMode.hpp +9 -27
  433. package/nitrogen/generated/android/c++/JSearchParams.hpp +3 -9
  434. package/nitrogen/generated/android/c++/JStarRating.hpp +57 -0
  435. package/nitrogen/generated/android/c++/{JGateEvent.hpp → JThumbsRating.hpp} +15 -16
  436. package/nitrogen/generated/android/c++/JTrack.hpp +5 -23
  437. package/nitrogen/generated/android/c++/JTrackLoadEvent.hpp +0 -6
  438. package/nitrogen/generated/android/c++/JTransformableRequestConfig.hpp +1 -14
  439. package/nitrogen/generated/android/c++/JUpdateOptions.hpp +105 -0
  440. package/nitrogen/generated/android/c++/JVariant_HeartRating_ThumbsRating_StarRating_PercentageRating.cpp +34 -0
  441. package/nitrogen/generated/android/c++/JVariant_HeartRating_ThumbsRating_StarRating_PercentageRating.hpp +105 -0
  442. package/nitrogen/generated/android/c++/JVariant_NullType_NotificationButtonLayout.cpp +26 -0
  443. package/nitrogen/generated/android/c++/JVariant_NullType_NotificationButtonLayout.hpp +75 -0
  444. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidAudioContentType.kt +4 -4
  445. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidOptions.kt +9 -3
  446. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidUpdateOptions.kt +50 -0
  447. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ArtworkRequestConfig.kt +4 -10
  448. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/CarPlayNowPlayingButton.kt +3 -3
  449. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormattedNavigationError.kt +2 -2
  450. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Func_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.kt → Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.kt} +12 -12
  451. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Func_void_Output.kt → Func_void_IosOutput.kt} +9 -9
  452. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Func_void_GateEvent.kt → Func_void_RemoteSetRatingEvent.kt} +9 -9
  453. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_bool.kt +9 -9
  454. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Gate.kt → HeartRating.kt} +6 -9
  455. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/HybridAudioBrowserSpec.kt +109 -103
  456. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageRowItem.kt +3 -24
  457. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Output.kt → IosOutput.kt} +6 -6
  458. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IosOutputType.kt +32 -0
  459. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaRequestConfig.kt +4 -10
  460. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeBrowserConfiguration.kt +6 -18
  461. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeRouteEntry.kt +4 -4
  462. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeUpdateOptions.kt +6 -6
  463. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NavigationErrorType.kt +1 -3
  464. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroAndroidUpdateOptions.kt +9 -3
  465. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{FavoritesMatchMode.kt → NotificationButton.kt} +8 -5
  466. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NotificationButtonLayout.kt +50 -0
  467. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingMetadata.kt +6 -3
  468. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingUpdate.kt +3 -6
  469. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Options.kt +3 -3
  470. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{NativeAndroidSetupOptions.kt → PartialAndroidSetupPlayerOptions.kt} +5 -5
  471. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{NativeIOSSetupOptions.kt → PartialIOSSetupPlayerOptions.kt} +5 -5
  472. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PartialSetupPlayerOptions.kt +47 -0
  473. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{GateDecision.kt → PercentageRating.kt} +6 -9
  474. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackError.kt +3 -12
  475. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackState.kt +6 -6
  476. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlayerCapabilities.kt +2 -2
  477. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{GateReason.kt → RatingType.kt} +10 -5
  478. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{ArtworkVariants.kt → RemoteSetRatingEvent.kt} +6 -9
  479. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ResolvedTrack.kt +3 -12
  480. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RetryConfig.kt +4 -7
  481. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SearchMode.kt +6 -12
  482. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SearchParams.kt +3 -6
  483. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{GateEvent.kt → StarRating.kt} +6 -6
  484. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{FavoriteConfig.kt → ThumbsRating.kt} +6 -6
  485. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Track.kt +3 -12
  486. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TransformableRequestConfig.kt +4 -7
  487. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/UpdateOptions.kt +53 -0
  488. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_HeartRating_ThumbsRating_StarRating_PercentageRating.kt +77 -0
  489. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Variant_NullType_RemoteButtonLayout.kt → Variant_NullType_NotificationButtonLayout.kt} +9 -9
  490. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.cpp +28 -139
  491. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.hpp +489 -1125
  492. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Umbrella.hpp +45 -66
  493. package/nitrogen/generated/ios/c++/HybridAudioBrowserSpecSwift.hpp +118 -176
  494. package/nitrogen/generated/ios/swift/AndroidAudioContentType.swift +8 -8
  495. package/nitrogen/generated/ios/swift/AndroidOptions.swift +22 -12
  496. package/nitrogen/generated/ios/swift/AndroidUpdateOptions.swift +119 -0
  497. package/nitrogen/generated/ios/swift/ArtworkRequestConfig.swift +1 -95
  498. package/nitrogen/generated/ios/swift/CarPlayNowPlayingButton.swift +4 -4
  499. package/nitrogen/generated/ios/swift/FormattedNavigationError.swift +4 -17
  500. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.swift +68 -0
  501. package/nitrogen/generated/ios/swift/{Func_void_Output.swift → Func_void_IosOutput.swift} +10 -10
  502. package/nitrogen/generated/ios/swift/{Func_void_GateEvent.swift → Func_void_RemoteSetRatingEvent.swift} +10 -10
  503. package/nitrogen/generated/ios/swift/Func_void_bool.swift +5 -5
  504. package/nitrogen/generated/ios/swift/{Func_void_std__shared_ptr_Promise_GateDecision__.swift → Func_void_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError___.swift} +17 -17
  505. package/nitrogen/generated/ios/swift/HeartRating.swift +29 -0
  506. package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec.swift +14 -20
  507. package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec_cxx.swift +197 -230
  508. package/nitrogen/generated/ios/swift/ImageRowItem.swift +2 -121
  509. package/nitrogen/generated/ios/swift/{Output.swift → IosOutput.swift} +7 -7
  510. package/nitrogen/generated/ios/swift/IosOutputType.swift +76 -0
  511. package/nitrogen/generated/ios/swift/MediaRequestConfig.swift +1 -107
  512. package/nitrogen/generated/ios/swift/NativeBrowserConfiguration.swift +22 -161
  513. package/nitrogen/generated/ios/swift/NativeRouteEntry.swift +19 -19
  514. package/nitrogen/generated/ios/swift/NativeUpdateOptions.swift +25 -12
  515. package/nitrogen/generated/ios/swift/NavigationErrorType.swift +0 -8
  516. package/nitrogen/generated/ios/swift/NitroAndroidUpdateOptions.swift +41 -12
  517. package/nitrogen/generated/ios/swift/{RemoteButton.swift → NotificationButton.swift} +10 -10
  518. package/nitrogen/generated/ios/swift/NotificationButtonLayout.swift +92 -0
  519. package/nitrogen/generated/ios/swift/NowPlayingMetadata.swift +48 -1
  520. package/nitrogen/generated/ios/swift/NowPlayingUpdate.swift +1 -19
  521. package/nitrogen/generated/ios/swift/Options.swift +4 -10
  522. package/nitrogen/generated/ios/swift/{NativeAndroidSetupOptions.swift → PartialAndroidSetupPlayerOptions.swift} +5 -5
  523. package/nitrogen/generated/ios/swift/{NativeIOSSetupOptions.swift → PartialIOSSetupPlayerOptions.swift} +5 -5
  524. package/nitrogen/generated/ios/swift/PartialSetupPlayerOptions.swift +101 -0
  525. package/nitrogen/generated/ios/swift/PercentageRating.swift +29 -0
  526. package/nitrogen/generated/ios/swift/PlaybackError.swift +2 -43
  527. package/nitrogen/generated/ios/swift/PlaybackState.swift +4 -4
  528. package/nitrogen/generated/ios/swift/PlayerCapabilities.swift +8 -27
  529. package/nitrogen/generated/ios/swift/RatingType.swift +60 -0
  530. package/nitrogen/generated/ios/swift/RemoteSetRatingEvent.swift +58 -0
  531. package/nitrogen/generated/ios/swift/ResolvedTrack.swift +8 -74
  532. package/nitrogen/generated/ios/swift/RetryConfig.swift +4 -35
  533. package/nitrogen/generated/ios/swift/SearchMode.swift +12 -36
  534. package/nitrogen/generated/ios/swift/SearchParams.swift +2 -7
  535. package/nitrogen/generated/ios/swift/StarRating.swift +29 -0
  536. package/nitrogen/generated/ios/swift/ThumbsRating.swift +29 -0
  537. package/nitrogen/generated/ios/swift/Track.swift +8 -74
  538. package/nitrogen/generated/ios/swift/TransformableRequestConfig.swift +1 -60
  539. package/nitrogen/generated/ios/swift/UpdateOptions.swift +143 -0
  540. package/nitrogen/generated/ios/swift/Variant_HeartRating_ThumbsRating_StarRating_PercentageRating.swift +20 -0
  541. package/nitrogen/generated/ios/swift/{Variant_NullType_RemoteButtonLayout.swift → Variant_NullType_NotificationButtonLayout.swift} +3 -3
  542. package/nitrogen/generated/shared/c++/AndroidAudioContentType.hpp +10 -10
  543. package/nitrogen/generated/shared/c++/AndroidOptions.hpp +19 -8
  544. package/nitrogen/generated/shared/c++/AndroidUpdateOptions.hpp +109 -0
  545. package/nitrogen/generated/shared/c++/ArtworkRequestConfig.hpp +2 -10
  546. package/nitrogen/generated/shared/c++/CarPlayNowPlayingButton.hpp +6 -6
  547. package/nitrogen/generated/shared/c++/EqualizerSettings.hpp +2 -0
  548. package/nitrogen/generated/shared/c++/FormattedNavigationError.hpp +5 -6
  549. package/nitrogen/generated/shared/c++/{GateEvent.hpp → HeartRating.hpp} +17 -18
  550. package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.cpp +18 -21
  551. package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.hpp +35 -44
  552. package/nitrogen/generated/shared/c++/ImageRowItem.hpp +2 -33
  553. package/nitrogen/generated/shared/c++/{Output.hpp → IosOutput.hpp} +18 -18
  554. package/nitrogen/generated/shared/c++/IosOutputType.hpp +112 -0
  555. package/nitrogen/generated/shared/c++/MediaRequestConfig.hpp +2 -10
  556. package/nitrogen/generated/shared/c++/NativeBrowserConfiguration.hpp +15 -31
  557. package/nitrogen/generated/shared/c++/NativeRouteEntry.hpp +5 -5
  558. package/nitrogen/generated/shared/c++/NativeUpdateOptions.hpp +7 -9
  559. package/nitrogen/generated/shared/c++/NavigationErrorType.hpp +0 -8
  560. package/nitrogen/generated/shared/c++/NitroAndroidUpdateOptions.hpp +19 -8
  561. package/nitrogen/generated/shared/c++/{RemoteButton.hpp → NotificationButton.hpp} +25 -25
  562. package/nitrogen/generated/shared/c++/NotificationButtonLayout.hpp +102 -0
  563. package/nitrogen/generated/shared/c++/NowPlayingMetadata.hpp +19 -3
  564. package/nitrogen/generated/shared/c++/NowPlayingUpdate.hpp +2 -6
  565. package/nitrogen/generated/shared/c++/Options.hpp +8 -8
  566. package/nitrogen/generated/shared/c++/{NativeAndroidSetupOptions.hpp → PartialAndroidSetupPlayerOptions.hpp} +11 -11
  567. package/nitrogen/generated/shared/c++/{NativeIOSSetupOptions.hpp → PartialIOSSetupPlayerOptions.hpp} +11 -11
  568. package/nitrogen/generated/shared/c++/PartialSetupPlayerOptions.hpp +104 -0
  569. package/nitrogen/generated/shared/c++/{FavoriteConfig.hpp → PercentageRating.hpp} +17 -18
  570. package/nitrogen/generated/shared/c++/PlaybackError.hpp +3 -18
  571. package/nitrogen/generated/shared/c++/PlaybackState.hpp +9 -9
  572. package/nitrogen/generated/shared/c++/PlayerCapabilities.hpp +6 -9
  573. package/nitrogen/generated/shared/c++/RatingType.hpp +96 -0
  574. package/nitrogen/generated/shared/c++/RemoteSetRatingEvent.hpp +94 -0
  575. package/nitrogen/generated/shared/c++/ResolvedTrack.hpp +5 -24
  576. package/nitrogen/generated/shared/c++/RetryConfig.hpp +6 -10
  577. package/nitrogen/generated/shared/c++/SearchMode.hpp +15 -39
  578. package/nitrogen/generated/shared/c++/SearchParams.hpp +2 -9
  579. package/nitrogen/generated/shared/c++/{Gate.hpp → StarRating.hpp} +16 -21
  580. package/nitrogen/generated/shared/c++/{GateDecision.hpp → ThumbsRating.hpp} +17 -23
  581. package/nitrogen/generated/shared/c++/Track.hpp +5 -24
  582. package/nitrogen/generated/shared/c++/TransformableRequestConfig.hpp +2 -6
  583. package/nitrogen/generated/shared/c++/UpdateOptions.hpp +111 -0
  584. package/package.json +5 -12
  585. package/src/AudioBrowser.ts +1 -4
  586. package/src/features/browser.ts +201 -58
  587. package/src/features/equalizer.ts +1 -1
  588. package/src/features/errors.ts +5 -71
  589. package/src/features/favorites.ts +1 -1
  590. package/src/features/index.ts +0 -2
  591. package/src/features/metadata.ts +15 -9
  592. package/src/features/network.ts +1 -1
  593. package/src/features/nowPlaying.ts +1 -37
  594. package/src/features/output.ts +22 -35
  595. package/src/features/playback/controls.ts +0 -8
  596. package/src/features/playback/index.ts +0 -1
  597. package/src/features/playback/playWhenReady.ts +1 -1
  598. package/src/features/playback/playing.ts +1 -1
  599. package/src/features/playback/progress.ts +13 -32
  600. package/src/features/playback/state.ts +1 -1
  601. package/src/features/playback/volume.ts +2 -2
  602. package/src/features/player/options.ts +110 -217
  603. package/src/features/player/setup.ts +175 -397
  604. package/src/features/queue/activeTrack.ts +1 -1
  605. package/src/features/queue/queue.ts +6 -17
  606. package/src/features/queue/repeatMode.ts +1 -1
  607. package/src/features/queue/shuffle.ts +1 -1
  608. package/src/features/rating.ts +17 -0
  609. package/src/features/remoteControls.ts +115 -13
  610. package/src/features/sleepTimer.ts +5 -24
  611. package/src/native.ts +0 -5
  612. package/src/native.web.ts +1 -4
  613. package/src/specs/audio-browser.nitro.ts +41 -131
  614. package/src/types/browser-native.ts +6 -19
  615. package/src/types/browser-nodes.ts +13 -160
  616. package/src/types/browser.ts +89 -377
  617. package/src/types/player.ts +69 -0
  618. package/src/utils/LazyNativeEmitter.ts +8 -9
  619. package/src/utils/NativeUpdatedValue.ts +2 -0
  620. package/src/web/NativeAudioBrowser.ts +158 -365
  621. package/src/web/TrackPlayer/Player.ts +39 -113
  622. package/src/web/TrackPlayer/PlaylistPlayer.ts +346 -0
  623. package/src/web/TrackPlayer/RepeatMode.ts +1 -1
  624. package/src/web/TrackPlayer/SleepTimer.ts +3 -38
  625. package/src/web/TrackPlayer/index.ts +1 -2
  626. package/src/web/browser/BrowserManager.ts +62 -231
  627. package/src/web/browser/NavigationErrorManager.ts +1 -3
  628. package/src/web/browser/SearchManager.ts +15 -11
  629. package/src/web/http/HttpClient.ts +35 -5
  630. package/src/web/http/RequestConfigBuilder.ts +63 -120
  631. package/src/web/player/NowPlayingManager.ts +5 -6
  632. package/src/web/player/OptionsManager.ts +18 -12
  633. package/android/src/main/java/com/audiobrowser/ServiceBinding.kt +0 -46
  634. package/android/src/main/java/com/audiobrowser/browser/ArtworkResolutionRegistry.kt +0 -37
  635. package/android/src/main/java/com/audiobrowser/browser/BrowseArtworkRegistry.kt +0 -34
  636. package/android/src/main/java/com/audiobrowser/browser/BrowserUrlResolution.kt +0 -299
  637. package/android/src/main/java/com/audiobrowser/browser/JsonArtwork.kt +0 -79
  638. package/android/src/main/java/com/audiobrowser/browser/SectionScope.kt +0 -42
  639. package/android/src/main/java/com/audiobrowser/extension/ResolvedTrackExt.kt +0 -35
  640. package/android/src/main/java/com/audiobrowser/player/CapabilityControls.kt +0 -172
  641. package/android/src/main/java/com/audiobrowser/player/EqualizerController.kt +0 -153
  642. package/android/src/main/java/com/audiobrowser/player/InterceptingPlayer.kt +0 -141
  643. package/android/src/main/java/com/audiobrowser/player/NowPlayingUpdater.kt +0 -347
  644. package/android/src/main/java/com/audiobrowser/player/PlaybackErrorClassifier.kt +0 -129
  645. package/android/src/main/java/com/audiobrowser/player/PlaybackStateMachine.kt +0 -85
  646. package/android/src/main/java/com/audiobrowser/player/PlaybackTimer.kt +0 -56
  647. package/android/src/main/java/com/audiobrowser/player/PlayerCapabilitiesExt.kt +0 -20
  648. package/android/src/main/java/com/audiobrowser/player/PlayerEngineFactory.kt +0 -130
  649. package/android/src/main/java/com/audiobrowser/player/SleepTimerManager.kt +0 -80
  650. package/android/src/main/java/com/audiobrowser/player/StuckRecoveryPolicy.kt +0 -50
  651. package/android/src/main/java/com/audiobrowser/player/VolumeFader.kt +0 -81
  652. package/android/src/main/java/com/audiobrowser/tls/AiaCertChaser.kt +0 -141
  653. package/android/src/main/java/com/audiobrowser/tls/AiaChasingTrustManager.kt +0 -37
  654. package/android/src/main/java/com/audiobrowser/tls/AiaTls.kt +0 -41
  655. package/android/src/main/java/com/audiobrowser/tls/CachingCertificateFetcher.kt +0 -209
  656. package/android/src/main/java/com/audiobrowser/util/ArtworkContentProvider.kt +0 -161
  657. package/android/src/main/java/com/audiobrowser/util/ArtworkUris.kt +0 -28
  658. package/android/src/main/java/com/audiobrowser/util/ArtworkVariant.kt +0 -24
  659. package/android/src/main/java/com/audiobrowser/util/CoilArtworkLoader.kt +0 -49
  660. package/android/src/main/java/com/audiobrowser/util/CoilArtworkLoaderHolder.kt +0 -36
  661. package/android/src/main/java/com/audiobrowser/util/OutputMonitor.kt +0 -211
  662. package/android/src/main/java/com/audiobrowser/util/OutputSwitcher.kt +0 -58
  663. package/android/src/main/java/com/audiobrowser/util/RatingFavorites.kt +0 -14
  664. package/android/src/test/java/com/audiobrowser/ServiceBindingTest.kt +0 -68
  665. package/android/src/test/java/com/audiobrowser/TestFixtures.kt +0 -165
  666. package/android/src/test/java/com/audiobrowser/browser/ArtworkResolutionRegistryTest.kt +0 -46
  667. package/android/src/test/java/com/audiobrowser/browser/BrowseArtworkRegistryTest.kt +0 -39
  668. package/android/src/test/java/com/audiobrowser/browser/BrowserManagerBuildApiRequestTest.kt +0 -114
  669. package/android/src/test/java/com/audiobrowser/browser/BrowserManagerLayerResolutionTest.kt +0 -141
  670. package/android/src/test/java/com/audiobrowser/browser/BrowserUrlResolutionTest.kt +0 -177
  671. package/android/src/test/java/com/audiobrowser/browser/JsonArtworkTest.kt +0 -55
  672. package/android/src/test/java/com/audiobrowser/browser/SectionScopeTest.kt +0 -94
  673. package/android/src/test/java/com/audiobrowser/player/CapabilityControlsTest.kt +0 -203
  674. package/android/src/test/java/com/audiobrowser/player/DynamicLoadControlTest.kt +0 -56
  675. package/android/src/test/java/com/audiobrowser/player/EqualizerControllerTest.kt +0 -216
  676. package/android/src/test/java/com/audiobrowser/player/MediaSessionSlotMappingTest.kt +0 -45
  677. package/android/src/test/java/com/audiobrowser/player/NowPlayingUpdaterTest.kt +0 -442
  678. package/android/src/test/java/com/audiobrowser/player/PlaybackErrorClassifierTest.kt +0 -190
  679. package/android/src/test/java/com/audiobrowser/player/PlaybackStateMachineTest.kt +0 -198
  680. package/android/src/test/java/com/audiobrowser/player/PlaybackTimerTest.kt +0 -137
  681. package/android/src/test/java/com/audiobrowser/player/PlayerEngineFactoryTest.kt +0 -36
  682. package/android/src/test/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicyTest.kt +0 -268
  683. package/android/src/test/java/com/audiobrowser/player/SessionErrorMaskTest.kt +0 -68
  684. package/android/src/test/java/com/audiobrowser/player/StuckRecoveryPolicyTest.kt +0 -40
  685. package/android/src/test/java/com/audiobrowser/player/TransformingDataSourceTest.kt +0 -193
  686. package/android/src/test/java/com/audiobrowser/tls/AiaCertChaserTest.kt +0 -107
  687. package/android/src/test/java/com/audiobrowser/tls/AiaChasingTrustManagerTest.kt +0 -73
  688. package/android/src/test/java/com/audiobrowser/tls/CachingCertificateFetcherTest.kt +0 -75
  689. package/android/src/test/java/com/audiobrowser/tls/CertFixtures.kt +0 -18
  690. package/android/src/test/java/com/audiobrowser/util/ArtworkContentProviderTest.kt +0 -163
  691. package/android/src/test/java/com/audiobrowser/util/ArtworkUrisTest.kt +0 -34
  692. package/android/src/test/java/com/audiobrowser/util/BrowserPathHelperTest.kt +0 -28
  693. package/android/src/test/java/com/audiobrowser/util/CoilArtworkLoaderHolderTest.kt +0 -53
  694. package/android/src/test/java/com/audiobrowser/util/CoilArtworkLoaderTest.kt +0 -58
  695. package/android/src/test/java/com/audiobrowser/util/FakeImageLoader.kt +0 -57
  696. package/android/src/test/java/com/audiobrowser/util/PlayingStateFactoryTest.kt +0 -40
  697. package/android/src/test/java/com/audiobrowser/util/RatingFavoritesTest.kt +0 -34
  698. package/android/src/test/java/com/audiobrowser/util/TrackFactoryBrowseTest.kt +0 -50
  699. package/android/src/test/java/com/audiobrowser/util/TrackFactoryMediaIdTest.kt +0 -63
  700. package/android/src/test/java/com/audiobrowser/util/TrackFactoryRatingTest.kt +0 -35
  701. package/android/src/test/resources/certs/isrg-root-x1.pem +0 -31
  702. package/android/src/test/resources/certs/letsencrypt-r13.der +0 -0
  703. package/android/src/test/resources/certs/letsencrypt-r13.pem +0 -29
  704. package/android/src/test/resources/certs/stationplaylist-leaf.pem +0 -34
  705. package/ios/Browser/MediaResolveComposer.swift +0 -114
  706. package/ios/Browser/SearchDrillIn.swift +0 -44
  707. package/ios/Browser/SectionScope.swift +0 -35
  708. package/ios/Browser/TabBarEntries.swift +0 -15
  709. package/ios/CarPlay/CPInterfaceController+Safe.swift +0 -126
  710. package/ios/CarPlay/ImageRowItem+CarPlay.swift +0 -19
  711. package/ios/CarPlay/RNABMediaAddHandler.swift +0 -75
  712. package/ios/CarPlay/RNABMediaAffinityHandler.swift +0 -69
  713. package/ios/Extension/PlayerCapabilities+Favorite.swift +0 -20
  714. package/ios/Extension/RequestConfig+Copying.swift +0 -31
  715. package/ios/Extension/Variant+Artwork.swift +0 -49
  716. package/ios/NowPlayingInfo/SilentAudioPrimer.swift +0 -73
  717. package/ios/Player/AirPlayStallJudgement.swift +0 -25
  718. package/ios/Player/EndOfTrackJudgement.swift +0 -32
  719. package/ios/Player/MediaIntentCriteria.swift +0 -139
  720. package/ios/Player/PersistedPlaybackState.swift +0 -11
  721. package/ios/Player/PlaybackStateStore.swift +0 -27
  722. package/ios/Player/PlaybackTimer.swift +0 -61
  723. package/ios/Player/VolumeFader.swift +0 -77
  724. package/ios/RemoteCommand/RemoteCommandCallbacks.swift +0 -47
  725. package/ios/Tests/AirPlayStallJudgementTests.swift +0 -52
  726. package/ios/Tests/EndOfTrackJudgementTests.swift +0 -35
  727. package/ios/Tests/JsonModelsTests.swift +0 -58
  728. package/ios/Tests/MediaIntentCriteriaTests.swift +0 -170
  729. package/ios/Tests/MediaLoaderAssetOptionsTests.swift +0 -46
  730. package/ios/Tests/MediaResolveTests.swift +0 -126
  731. package/ios/Tests/OnceValueTests.swift +0 -79
  732. package/ios/Tests/PlaybackStateStoreTests.swift +0 -48
  733. package/ios/Tests/PlaybackTimerTests.swift +0 -55
  734. package/ios/Tests/PlayingStateManagerTests.swift +0 -57
  735. package/ios/Tests/RemoteCommandControllerTests.swift +0 -156
  736. package/ios/Tests/RemoteCommandTests.swift +0 -67
  737. package/ios/Tests/RetryManagerTests.swift +0 -89
  738. package/ios/Tests/SearchDrillInTests.swift +0 -63
  739. package/ios/Tests/SectionScopeTests.swift +0 -82
  740. package/ios/Tests/SleepTimerManagerTests.swift +0 -107
  741. package/ios/Tests/Support/ManualSleepTimerScheduler.swift +0 -47
  742. package/ios/Tests/TabBarEntriesTests.swift +0 -71
  743. package/lib/commonjs/features/browser-config.js +0 -227
  744. package/lib/commonjs/features/browser-config.js.map +0 -1
  745. package/lib/commonjs/features/carConnection.js +0 -42
  746. package/lib/commonjs/features/carConnection.js.map +0 -1
  747. package/lib/commonjs/features/gate.js +0 -149
  748. package/lib/commonjs/features/gate.js.map +0 -1
  749. package/lib/commonjs/features/playback/trackPlaybackTime.js +0 -86
  750. package/lib/commonjs/features/playback/trackPlaybackTime.js.map +0 -1
  751. package/lib/commonjs/features/player/validateOptions.js +0 -24
  752. package/lib/commonjs/features/player/validateOptions.js.map +0 -1
  753. package/lib/commonjs/utils/artwork.js +0 -31
  754. package/lib/commonjs/utils/artwork.js.map +0 -1
  755. package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js +0 -71
  756. package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js.map +0 -1
  757. package/lib/commonjs/web/TrackPlayer/PlaybackTimer.js +0 -34
  758. package/lib/commonjs/web/TrackPlayer/PlaybackTimer.js.map +0 -1
  759. package/lib/commonjs/web/TrackPlayer/PlayingStateFactory.js +0 -21
  760. package/lib/commonjs/web/TrackPlayer/PlayingStateFactory.js.map +0 -1
  761. package/lib/commonjs/web/TrackPlayer/QueueManager.js +0 -273
  762. package/lib/commonjs/web/TrackPlayer/QueueManager.js.map +0 -1
  763. package/lib/commonjs/web/TrackPlayer/QueuePlayer.js +0 -158
  764. package/lib/commonjs/web/TrackPlayer/QueuePlayer.js.map +0 -1
  765. package/lib/commonjs/web/TrackPlayer/VolumeFader.js +0 -75
  766. package/lib/commonjs/web/TrackPlayer/VolumeFader.js.map +0 -1
  767. package/lib/commonjs/web/browser/assertBrowsePageShape.js +0 -22
  768. package/lib/commonjs/web/browser/assertBrowsePageShape.js.map +0 -1
  769. package/lib/commonjs/web/browser/classifyTrackNavigation.js +0 -41
  770. package/lib/commonjs/web/browser/classifyTrackNavigation.js.map +0 -1
  771. package/lib/commonjs/web/browser/parseSearchResponse.js +0 -20
  772. package/lib/commonjs/web/browser/parseSearchResponse.js.map +0 -1
  773. package/lib/commonjs/web/playbackErrorKind.js +0 -57
  774. package/lib/commonjs/web/playbackErrorKind.js.map +0 -1
  775. package/lib/commonjs/web/player/MediaSessionManager.js +0 -121
  776. package/lib/commonjs/web/player/MediaSessionManager.js.map +0 -1
  777. package/lib/commonjs/web/player/RemoteCommandController.js +0 -96
  778. package/lib/commonjs/web/player/RemoteCommandController.js.map +0 -1
  779. package/lib/module/features/browser-config.js +0 -221
  780. package/lib/module/features/browser-config.js.map +0 -1
  781. package/lib/module/features/carConnection.js +0 -37
  782. package/lib/module/features/carConnection.js.map +0 -1
  783. package/lib/module/features/gate.js +0 -144
  784. package/lib/module/features/gate.js.map +0 -1
  785. package/lib/module/features/playback/trackPlaybackTime.js +0 -83
  786. package/lib/module/features/playback/trackPlaybackTime.js.map +0 -1
  787. package/lib/module/features/player/validateOptions.js +0 -20
  788. package/lib/module/features/player/validateOptions.js.map +0 -1
  789. package/lib/module/utils/artwork.js +0 -26
  790. package/lib/module/utils/artwork.js.map +0 -1
  791. package/lib/module/web/TrackPlayer/PlaybackStateMachine.js +0 -67
  792. package/lib/module/web/TrackPlayer/PlaybackStateMachine.js.map +0 -1
  793. package/lib/module/web/TrackPlayer/PlaybackTimer.js +0 -29
  794. package/lib/module/web/TrackPlayer/PlaybackTimer.js.map +0 -1
  795. package/lib/module/web/TrackPlayer/PlayingStateFactory.js +0 -17
  796. package/lib/module/web/TrackPlayer/PlayingStateFactory.js.map +0 -1
  797. package/lib/module/web/TrackPlayer/QueueManager.js +0 -269
  798. package/lib/module/web/TrackPlayer/QueueManager.js.map +0 -1
  799. package/lib/module/web/TrackPlayer/QueuePlayer.js +0 -154
  800. package/lib/module/web/TrackPlayer/QueuePlayer.js.map +0 -1
  801. package/lib/module/web/TrackPlayer/VolumeFader.js +0 -70
  802. package/lib/module/web/TrackPlayer/VolumeFader.js.map +0 -1
  803. package/lib/module/web/browser/assertBrowsePageShape.js +0 -18
  804. package/lib/module/web/browser/assertBrowsePageShape.js.map +0 -1
  805. package/lib/module/web/browser/classifyTrackNavigation.js +0 -38
  806. package/lib/module/web/browser/classifyTrackNavigation.js.map +0 -1
  807. package/lib/module/web/browser/parseSearchResponse.js +0 -16
  808. package/lib/module/web/browser/parseSearchResponse.js.map +0 -1
  809. package/lib/module/web/playbackErrorKind.js +0 -52
  810. package/lib/module/web/playbackErrorKind.js.map +0 -1
  811. package/lib/module/web/player/MediaSessionManager.js +0 -116
  812. package/lib/module/web/player/MediaSessionManager.js.map +0 -1
  813. package/lib/module/web/player/RemoteCommandController.js +0 -92
  814. package/lib/module/web/player/RemoteCommandController.js.map +0 -1
  815. package/lib/typescript/src/features/browser-config.d.ts +0 -12
  816. package/lib/typescript/src/features/browser-config.d.ts.map +0 -1
  817. package/lib/typescript/src/features/carConnection.d.ts +0 -20
  818. package/lib/typescript/src/features/carConnection.d.ts.map +0 -1
  819. package/lib/typescript/src/features/gate.d.ts +0 -78
  820. package/lib/typescript/src/features/gate.d.ts.map +0 -1
  821. package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts +0 -34
  822. package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts.map +0 -1
  823. package/lib/typescript/src/features/player/validateOptions.d.ts +0 -2
  824. package/lib/typescript/src/features/player/validateOptions.d.ts.map +0 -1
  825. package/lib/typescript/src/utils/artwork.d.ts +0 -19
  826. package/lib/typescript/src/utils/artwork.d.ts.map +0 -1
  827. package/nitrogen/generated/android/c++/JArtworkVariants.hpp +0 -61
  828. package/nitrogen/generated/android/c++/JFavoriteConfig.hpp +0 -58
  829. package/nitrogen/generated/android/c++/JFavoritesMatchMode.hpp +0 -58
  830. package/nitrogen/generated/android/c++/JFormatNowPlayingParams.hpp +0 -100
  831. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.hpp +0 -112
  832. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___RequestConfig_std__optional_std__unordered_map_std__string__std__string__.hpp +0 -121
  833. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___Track.hpp +0 -123
  834. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.hpp +0 -133
  835. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_std__string____Track.hpp +0 -121
  836. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.hpp +0 -139
  837. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.hpp +0 -134
  838. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.hpp +0 -131
  839. package/nitrogen/generated/android/c++/JFunc_void_GateEvent.hpp +0 -79
  840. package/nitrogen/generated/android/c++/JFunc_void_Output.hpp +0 -80
  841. package/nitrogen/generated/android/c++/JGate.hpp +0 -62
  842. package/nitrogen/generated/android/c++/JGateDecision.hpp +0 -64
  843. package/nitrogen/generated/android/c++/JGateReason.hpp +0 -58
  844. package/nitrogen/generated/android/c++/JIOSOptions.hpp +0 -95
  845. package/nitrogen/generated/android/c++/JMediaReference.hpp +0 -58
  846. package/nitrogen/generated/android/c++/JNativeGateRequest.hpp +0 -74
  847. package/nitrogen/generated/android/c++/JNativeSetupPlayerOptions.hpp +0 -182
  848. package/nitrogen/generated/android/c++/JNitroIOSUpdateOptions.hpp +0 -96
  849. package/nitrogen/generated/android/c++/JOutputType.hpp +0 -82
  850. package/nitrogen/generated/android/c++/JPlaybackErrorKind.hpp +0 -76
  851. package/nitrogen/generated/android/c++/JRemoteButtonLayout.hpp +0 -86
  852. package/nitrogen/generated/android/c++/JStallReason.hpp +0 -58
  853. package/nitrogen/generated/android/c++/JTrackRequest.hpp +0 -93
  854. package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.cpp +0 -26
  855. package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.hpp +0 -71
  856. package/nitrogen/generated/android/c++/JVariant_NullType_RemoteButtonLayout.cpp +0 -26
  857. package/nitrogen/generated/android/c++/JVariant_NullType_RemoteButtonLayout.hpp +0 -75
  858. package/nitrogen/generated/android/c++/JVariant_ResolvedTrack_BrowseError_Promise_BrowseResult_.cpp +0 -41
  859. package/nitrogen/generated/android/c++/JVariant_ResolvedTrack_BrowseError_Promise_BrowseResult_.hpp +0 -121
  860. package/nitrogen/generated/android/c++/JVariant_String_ArtworkVariants.cpp +0 -26
  861. package/nitrogen/generated/android/c++/JVariant_String_ArtworkVariants.hpp +0 -70
  862. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormatNowPlayingParams.kt +0 -50
  863. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.kt +0 -80
  864. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___RequestConfig_std__optional_std__unordered_map_std__string__std__string__.kt +0 -80
  865. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___Track.kt +0 -80
  866. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.kt +0 -80
  867. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_std__string____Track.kt +0 -80
  868. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.kt +0 -80
  869. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.kt +0 -80
  870. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IOSOptions.kt +0 -44
  871. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaReference.kt +0 -23
  872. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeGateRequest.kt +0 -44
  873. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeSetupPlayerOptions.kt +0 -66
  874. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroIOSUpdateOptions.kt +0 -44
  875. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/OutputType.kt +0 -31
  876. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackErrorKind.kt +0 -29
  877. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteButton.kt +0 -26
  878. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteButtonLayout.kt +0 -44
  879. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/StallReason.kt +0 -23
  880. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackRequest.kt +0 -44
  881. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_Boolean_FavoriteConfig.kt +0 -53
  882. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_ResolvedTrack_BrowseError_Promise_BrowseResult_.kt +0 -65
  883. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_String_ArtworkVariants.kt +0 -53
  884. package/nitrogen/generated/ios/swift/ArtworkVariants.swift +0 -34
  885. package/nitrogen/generated/ios/swift/FavoriteConfig.swift +0 -29
  886. package/nitrogen/generated/ios/swift/FavoritesMatchMode.swift +0 -40
  887. package/nitrogen/generated/ios/swift/FormatNowPlayingParams.swift +0 -67
  888. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.swift +0 -54
  889. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_RequestConfig___RequestConfig_std__optional_std__unordered_map_std__string__std__string__.swift +0 -69
  890. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_RequestConfig___Track.swift +0 -54
  891. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.swift +0 -60
  892. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__optional_std__string____Track.swift +0 -60
  893. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.swift +0 -61
  894. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.swift +0 -61
  895. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.swift +0 -77
  896. package/nitrogen/generated/ios/swift/Func_void_GateDecision.swift +0 -46
  897. package/nitrogen/generated/ios/swift/Func_void_TransformableRequestConfig.swift +0 -46
  898. package/nitrogen/generated/ios/swift/Func_void_std__optional_NowPlayingUpdate_.swift +0 -46
  899. package/nitrogen/generated/ios/swift/Func_void_std__optional_std__string_.swift +0 -53
  900. package/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_TransformableRequestConfig__.swift +0 -66
  901. package/nitrogen/generated/ios/swift/Func_void_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError____.swift +0 -81
  902. package/nitrogen/generated/ios/swift/Gate.swift +0 -47
  903. package/nitrogen/generated/ios/swift/GateDecision.swift +0 -40
  904. package/nitrogen/generated/ios/swift/GateEvent.swift +0 -29
  905. package/nitrogen/generated/ios/swift/GateReason.swift +0 -40
  906. package/nitrogen/generated/ios/swift/IOSOptions.swift +0 -51
  907. package/nitrogen/generated/ios/swift/MediaReference.swift +0 -40
  908. package/nitrogen/generated/ios/swift/NativeGateRequest.swift +0 -58
  909. package/nitrogen/generated/ios/swift/NativeSetupPlayerOptions.swift +0 -206
  910. package/nitrogen/generated/ios/swift/NitroIOSUpdateOptions.swift +0 -90
  911. package/nitrogen/generated/ios/swift/OutputType.swift +0 -72
  912. package/nitrogen/generated/ios/swift/PlaybackErrorKind.swift +0 -64
  913. package/nitrogen/generated/ios/swift/RemoteButtonLayout.swift +0 -57
  914. package/nitrogen/generated/ios/swift/StallReason.swift +0 -40
  915. package/nitrogen/generated/ios/swift/TrackRequest.swift +0 -106
  916. package/nitrogen/generated/ios/swift/Variant_Bool_FavoriteConfig.swift +0 -18
  917. package/nitrogen/generated/ios/swift/Variant_ResolvedTrack_BrowseError_Promise_BrowseResult_.swift +0 -19
  918. package/nitrogen/generated/ios/swift/Variant_String_ArtworkVariants.swift +0 -18
  919. package/nitrogen/generated/shared/c++/ArtworkVariants.hpp +0 -87
  920. package/nitrogen/generated/shared/c++/FavoritesMatchMode.hpp +0 -76
  921. package/nitrogen/generated/shared/c++/FormatNowPlayingParams.hpp +0 -110
  922. package/nitrogen/generated/shared/c++/GateReason.hpp +0 -76
  923. package/nitrogen/generated/shared/c++/IOSOptions.hpp +0 -91
  924. package/nitrogen/generated/shared/c++/MediaReference.hpp +0 -76
  925. package/nitrogen/generated/shared/c++/NativeGateRequest.hpp +0 -97
  926. package/nitrogen/generated/shared/c++/NativeSetupPlayerOptions.hpp +0 -138
  927. package/nitrogen/generated/shared/c++/NitroIOSUpdateOptions.hpp +0 -92
  928. package/nitrogen/generated/shared/c++/OutputType.hpp +0 -108
  929. package/nitrogen/generated/shared/c++/PlaybackErrorKind.hpp +0 -100
  930. package/nitrogen/generated/shared/c++/RemoteButtonLayout.hpp +0 -94
  931. package/nitrogen/generated/shared/c++/StallReason.hpp +0 -76
  932. package/nitrogen/generated/shared/c++/TrackRequest.hpp +0 -93
  933. package/src/codegen-no-config-variant.test.ts +0 -70
  934. package/src/features/browser-config.test.ts +0 -110
  935. package/src/features/browser-config.ts +0 -293
  936. package/src/features/browser.test.ts +0 -19
  937. package/src/features/carConnection.ts +0 -36
  938. package/src/features/gate.test.ts +0 -72
  939. package/src/features/gate.ts +0 -155
  940. package/src/features/playback/trackPlaybackTime.test.ts +0 -80
  941. package/src/features/playback/trackPlaybackTime.ts +0 -101
  942. package/src/features/player/options.test.ts +0 -38
  943. package/src/features/player/setup.test.ts +0 -125
  944. package/src/features/player/validateOptions.ts +0 -22
  945. package/src/features/queue/queue.test.ts +0 -36
  946. package/src/public-surface.test.ts +0 -123
  947. package/src/utils/artwork.ts +0 -30
  948. package/src/web/NativeAudioBrowser.playWhenReady.test.ts +0 -301
  949. package/src/web/TrackPlayer/PlaybackStateMachine.test.ts +0 -139
  950. package/src/web/TrackPlayer/PlaybackStateMachine.ts +0 -82
  951. package/src/web/TrackPlayer/PlaybackTimer.test.ts +0 -67
  952. package/src/web/TrackPlayer/PlaybackTimer.ts +0 -33
  953. package/src/web/TrackPlayer/Player.dispatch.test.ts +0 -229
  954. package/src/web/TrackPlayer/Player.load.test.ts +0 -86
  955. package/src/web/TrackPlayer/PlayingStateFactory.test.ts +0 -51
  956. package/src/web/TrackPlayer/PlayingStateFactory.ts +0 -24
  957. package/src/web/TrackPlayer/QueueManager.test.ts +0 -289
  958. package/src/web/TrackPlayer/QueueManager.ts +0 -302
  959. package/src/web/TrackPlayer/QueuePlayer.ts +0 -188
  960. package/src/web/TrackPlayer/VolumeFader.ts +0 -74
  961. package/src/web/browser/__tests__/layer-resolver.test.ts +0 -69
  962. package/src/web/browser/assertBrowsePageShape.test.ts +0 -27
  963. package/src/web/browser/assertBrowsePageShape.ts +0 -27
  964. package/src/web/browser/classifyTrackNavigation.test.ts +0 -41
  965. package/src/web/browser/classifyTrackNavigation.ts +0 -35
  966. package/src/web/browser/parseSearchResponse.test.ts +0 -25
  967. package/src/web/browser/parseSearchResponse.ts +0 -15
  968. package/src/web/http/RequestConfigBuilder.test.ts +0 -59
  969. package/src/web/playbackErrorKind.test.ts +0 -55
  970. package/src/web/playbackErrorKind.ts +0 -56
  971. package/src/web/player/MediaSessionManager.test.ts +0 -220
  972. package/src/web/player/MediaSessionManager.ts +0 -151
  973. package/src/web/player/NowPlayingManager.test.ts +0 -46
  974. package/src/web/player/RemoteCommandController.test.ts +0 -171
  975. package/src/web/player/RemoteCommandController.ts +0 -166
@@ -7,13 +7,10 @@ import com.audiobrowser.http.HttpClient
7
7
  import com.audiobrowser.http.RequestConfigBuilder
8
8
  import com.audiobrowser.util.BrowserPathHelper
9
9
  import com.audiobrowser.util.TrackFactory
10
- import com.audiobrowser.util.artworkOf
11
10
  import com.margelo.nitro.audiobrowser.ArtworkRequestConfig
12
11
  import com.margelo.nitro.audiobrowser.BrowserSourceCallbackParam
13
- import com.margelo.nitro.audiobrowser.FavoritesMatchMode
14
- import com.margelo.nitro.audiobrowser.Func_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____
15
12
  import com.margelo.nitro.audiobrowser.ImageContext
16
- import com.margelo.nitro.audiobrowser.MediaReference
13
+ import com.margelo.nitro.audiobrowser.ImageSource
17
14
  import com.margelo.nitro.audiobrowser.MediaRequestConfig
18
15
  import com.margelo.nitro.audiobrowser.NativeRouteEntry
19
16
  import com.margelo.nitro.audiobrowser.RequestConfig
@@ -49,7 +46,6 @@ class BrowserManager {
49
46
  private var onPathChanged: ((String) -> Unit)? = null
50
47
  private var onContentChanged: ((ResolvedTrack?) -> Unit)? = null
51
48
  private var onTabsChanged: ((Array<Track>) -> Unit)? = null
52
- private var onArtworkRegistriesCleared: (() -> Unit)? = null
53
49
 
54
50
  private var path: String = "/"
55
51
  set(value) {
@@ -90,64 +86,28 @@ class BrowserManager {
90
86
  // Invalidated via invalidateContentCache() when content changes
91
87
  private val contentCache = LruCache<String, ResolvedTrack>(20)
92
88
 
93
- // Cache for the most recent search - the query string and its results stored as one pair, so a
94
- // concurrent reader never sees one query matched with another query's results.
95
- @Volatile private var lastSearch: Pair<String, Array<Track>>? = null
89
+ // Cache for search results - keyed by query string
90
+ private var lastSearchQuery: String? = null
91
+ private var lastSearchResults: Array<Track>? = null
96
92
 
97
93
  // Set of favorited track identifiers (src)
98
94
  private var favoriteIds = setOf<String>()
99
95
 
100
- // Favorite match mode, propagated from the player's `favorite` capability.
101
- // null = favoriting disabled (no row hearts). Set via setFavoriteMatch.
102
- private var favoriteMatch: FavoritesMatchMode? = null
103
-
104
96
  // Navigation tracking to prevent race conditions
105
97
  @Volatile private var currentNavigationId = 0
106
98
 
107
99
  /**
108
100
  * Browser configuration containing routes, search, tabs, and request settings. This can be
109
101
  * updated dynamically when the configuration changes.
110
- *
111
- * Setting a new config bumps [layerGeneration] so the cached request/browse resolver layers are
112
- * re-resolved on the next request (the resolvers may close over config-derived state).
113
102
  */
114
103
  var config: BrowserConfig = BrowserConfig()
115
- set(value) {
116
- field = value
117
- layerGeneration += 1
118
- // Registered artwork resolutions pin configs (and their JS callback handles)
119
- // from the previous configuration — never resolve through them again.
120
- artworkResolutions.clear()
121
- onArtworkRegistriesCleared?.invoke()
122
- }
123
-
124
- // Resolver-layer caching. The request/browse layers may be resolver thunks
125
- // (config.requestResolver / config.browseResolver) resolved once per *content generation*:
126
- // re-resolved when content is invalidated (clearContentCache, from invalidateAllContent) or when
127
- // a new config is set, cached, and merged per request.
128
- private var layerGeneration = 0
129
- private var resolvedLayerGeneration = -1
130
- private var resolvedRequestLayer: TransformableRequestConfig? = null
131
- private var resolvedBrowseLayer: TransformableRequestConfig? = null
132
-
133
- /** Test-only accessors for the resolver-layer cache state (see ensureLayersResolved). */
134
- internal val layerGenerationForTest: Int
135
- get() = layerGeneration
136
-
137
- internal val resolvedLayerGenerationForTest: Int
138
- get() = resolvedLayerGeneration
139
-
140
- internal val resolvedRequestLayerForTest: TransformableRequestConfig?
141
- get() = resolvedRequestLayer
142
-
143
- internal val resolvedBrowseLayerForTest: TransformableRequestConfig?
144
- get() = resolvedBrowseLayer
145
104
 
146
105
  /**
147
- * Maps produced artwork URIs back to (Track, artwork-config kind) so display-time bitmap loading
148
- * can re-resolve Track-first. See [ArtworkResolutionRegistry].
106
+ * Callback to transform artwork URLs for tracks. Takes a track and optional per-route artwork
107
+ * config, returns ImageSource or null. Injected by AudioBrowser when artwork config is set.
108
+ * The ImageContext parameter provides size hints for CDN URL generation.
149
109
  */
150
- val artworkResolutions = ArtworkResolutionRegistry()
110
+ var artworkUrlResolver: (suspend (Track, ArtworkRequestConfig?, ImageContext?) -> ImageSource?)? = null
151
111
 
152
112
  /**
153
113
  * Sets the favorited track identifiers. Tracks will have their favorited field hydrated based on
@@ -158,14 +118,6 @@ class BrowserManager {
158
118
  Timber.d("Set ${favoriteIds.size} favorite IDs")
159
119
  }
160
120
 
161
- /**
162
- * Sets the favorite match mode (propagated from the `favorite` capability). null disables
163
- * row-heart hydration.
164
- */
165
- fun setFavoriteMatch(match: FavoritesMatchMode?) {
166
- favoriteMatch = match
167
- }
168
-
169
121
  /**
170
122
  * Updates the favorite state for a single track identifier. Called when the heart button is
171
123
  * tapped in media controllers.
@@ -181,30 +133,40 @@ class BrowserManager {
181
133
  }
182
134
 
183
135
  /**
184
- * Hydrates the favorited field on a track based on the favoriteIds set. No-op unless favoriting
185
- * is enabled (the `favorite` capability). Only playable (src-bearing) tracks are favoritable; the
186
- * flag is set to true OR false so non-favorited tracks still show an (empty) heart. Doesn't
187
- * overwrite API-provided values.
136
+ * Hydrates the favorited field on a track based on the favoriteIds set. Only hydrates if
137
+ * track.favorited is null (doesn't overwrite API-provided values). Only tracks with src can be
138
+ * favorited.
188
139
  */
189
140
  private fun hydrateFavorite(track: Track): Track {
190
- val match = favoriteMatch ?: return track
191
141
  // Don't overwrite API-provided favorites
192
142
  if (track.favorited != null) return track
193
- // Only playable tracks are favoritable
194
- val src = track.src ?: return track
195
-
196
- val isFavorited = isFavorite(src, match)
197
-
198
- return track.copy(favorited = isFavorited)
143
+ if (favoriteIds.isEmpty()) return track
144
+
145
+ val isFavorited = track.src?.let { favoriteIds.contains(it) } ?: false
146
+ if (!isFavorited) return track
147
+
148
+ return Track(
149
+ url = track.url,
150
+ src = track.src,
151
+ artwork = track.artwork,
152
+ artworkSource = track.artworkSource,
153
+ artworkCarPlayTinted = track.artworkCarPlayTinted,
154
+ title = track.title,
155
+ subtitle = track.subtitle,
156
+ artist = track.artist,
157
+ album = track.album,
158
+ description = track.description,
159
+ genre = track.genre,
160
+ duration = track.duration,
161
+ style = track.style,
162
+ childrenStyle = track.childrenStyle,
163
+ favorited = true,
164
+ groupTitle = track.groupTitle,
165
+ live = track.live,
166
+ imageRow = track.imageRow,
167
+ )
199
168
  }
200
169
 
201
- /** Whether [src] is favorited under the given match mode. */
202
- private fun isFavorite(src: String, match: FavoritesMatchMode): Boolean =
203
- when (match) {
204
- FavoritesMatchMode.EXACT -> favoriteIds.contains(src)
205
- FavoritesMatchMode.PARTIAL -> favoriteIds.any { BrowserPathHelper.containsSegment(src, it) }
206
- }
207
-
208
170
  /** Hydrates favorites on all children of a ResolvedTrack. */
209
171
  private fun hydrateChildren(resolvedTrack: ResolvedTrack): ResolvedTrack {
210
172
  val children = resolvedTrack.children ?: return resolvedTrack
@@ -212,29 +174,20 @@ class BrowserManager {
212
174
  return resolvedTrack.copy(children = hydratedChildren)
213
175
  }
214
176
 
215
- /** Cache a track by id, url, and src for O(1) lookup from any mediaId form. */
177
+ /** Cache a track by both url and src for O(1) lookup from either key. */
216
178
  private fun cacheTrack(track: Track) {
217
- track.id?.takeUnless { it.isBlank() }?.let { trackCache.put(it, track) }
218
179
  track.url?.let { trackCache.put(it, track) }
219
180
  track.src?.let { trackCache.put(it, track) }
220
181
  }
221
182
 
222
183
  private fun cacheChildren(resolvedTrack: ResolvedTrack) {
223
- resolvedTrack.children?.forEach { track ->
224
- cacheTrack(track)
225
- // Image-row items are playable surfaces of their own: cache them (with
226
- // their stamped contextual urls) so an id-keyed mediaId from an
227
- // expanded Android Auto tile can find its way back to queue expansion.
228
- track.imageRow?.forEach { item ->
229
- cacheTrack(with(TrackFactory) { item.toTrack(groupTitle = track.title) })
230
- }
231
- }
184
+ resolvedTrack.children?.forEach { track -> cacheTrack(track) }
232
185
  }
233
186
 
234
187
  /**
235
- * Get a cached Track by mediaId (stable id, url, or src), or null if not cached. Used by Media3
236
- * to rehydrate MediaItem shells with full track metadata. Re-hydrates favorites in case
237
- * setFavoriteStates was called after caching.
188
+ * Get a cached Track by mediaId (url or src), or null if not cached. Used by Media3 to rehydrate
189
+ * MediaItem shells with full track metadata. Re-hydrates favorites in case setFavoriteStates was
190
+ * called after caching.
238
191
  */
239
192
  fun getCachedTrack(mediaId: String): Track? {
240
193
  // Try direct lookup first (matches url or src)
@@ -259,76 +212,27 @@ class BrowserManager {
259
212
  }
260
213
 
261
214
  /**
262
- * Resolves a tapped mediaId to the contextual url to expand a queue from, or null when there is
263
- * none. A contextual mediaId is its own; a stable-id mediaId (see TrackFactory.buildMediaItem)
264
- * resolves through the track cache to the contextual url of the container it was most recently
265
- * browsed in — a legacy car controller round-trips only the mediaId, so the cache is what
266
- * remembers which list the row came from.
267
- */
268
- fun contextualUrlFor(mediaId: String): String? {
269
- if (BrowserPathHelper.isContextual(mediaId)) return mediaId
270
- return getCachedTrack(mediaId)?.url?.takeIf { BrowserPathHelper.isContextual(it) }
271
- }
272
-
273
- /**
274
- * Resolves a single Media3 MediaItem to a Track. Prefers the track cache (keyed by id, url, and
275
- * src).
215
+ * Resolves multiple media IDs from cache. Throws IllegalStateException if any mediaId is not
216
+ * found in cache.
276
217
  *
277
- * A cache miss is legitimately reachable: a controller can replay a mediaId this process never
278
- * browsed — e.g. a search-result track after process death. When the mediaId is a playable URL,
279
- * or the item's requestMetadata carries the playable uri (stamped by TrackFactory for stable-id
280
- * mediaIds, and round-tripped by Media3 controllers), fall back to a minimal track built from the
281
- * item's own metadata instead of failing playback.
282
- *
283
- * @throws IllegalStateException if the mediaId is not cached and no playable URL is available
218
+ * @param mediaIds The media IDs to resolve
219
+ * @return List of Track objects
284
220
  */
285
- private fun resolveMediaItemToTrack(mediaItem: MediaItem): Track {
286
- val mediaId = mediaItem.mediaId
287
-
288
- getCachedTrack(mediaId)?.let { cachedTrack ->
289
- Timber.d("Resolved mediaId='$mediaId' from cache: '${cachedTrack.title}'")
290
- return cachedTrack
291
- }
221
+ fun resolveMediaIdsFromCache(mediaIds: List<String>): List<Track> {
222
+ return mediaIds.map { mediaId ->
223
+ Timber.d("=== Resolving from cache: mediaId='$mediaId' ===")
292
224
 
293
- val fallbackSrc =
294
- if (mediaId.startsWith("http://") || mediaId.startsWith("https://")) {
295
- mediaId
296
- } else {
297
- mediaItem.requestMetadata.mediaUri?.toString()
225
+ getCachedTrack(mediaId)?.let { cachedTrack ->
226
+ Timber.d("→ Found cached Track: '${cachedTrack.title}'")
227
+ return@map cachedTrack
298
228
  }
299
- if (fallbackSrc != null) {
300
- Timber.w("Cache MISS for mediaId='$mediaId' - building minimal track from media item")
301
- val metadata = mediaItem.mediaMetadata
302
- return hydrateFavorite(
303
- Track(
304
- // A mediaId distinct from the playable uri is the track's stable id —
305
- // keep it so the item's identity (car now-playing row match) survives.
306
- id = mediaId.takeIf { it != fallbackSrc },
307
- url = null,
308
- src = fallbackSrc,
309
- artwork = artworkOf(metadata.artworkUri?.toString()),
310
- artworkSource = null,
311
- request = null,
312
- artworkCarPlayTinted = null,
313
- title = metadata.title?.toString() ?: mediaId,
314
- subtitle = metadata.artist?.toString(),
315
- artist = null,
316
- albumUrl = null,
317
- album = metadata.albumTitle?.toString(),
318
- description = metadata.description?.toString(),
319
- genre = metadata.genre?.toString(),
320
- duration = null,
321
- style = null,
322
- childrenStyle = null,
323
- favorited = null,
324
- groupTitle = null,
325
- live = null,
326
- imageRow = null,
327
- )
229
+
230
+ // Cache miss - this indicates a bug in our caching system
231
+ Timber.e("→ Cache MISS for mediaId='$mediaId' - this should not happen")
232
+ throw IllegalStateException(
233
+ "MediaItem not found in cache: $mediaId. This indicates a bug in the caching system."
328
234
  )
329
235
  }
330
-
331
- throw IllegalStateException("MediaItem not found in cache: $mediaId")
332
236
  }
333
237
 
334
238
  /**
@@ -345,7 +249,7 @@ class BrowserManager {
345
249
  * @param startIndex Index of the item to start playing
346
250
  * @param startPositionMs Position within the start item to begin playback
347
251
  * @return MediaSession.MediaItemsWithStartPosition ready for Media3
348
- * @throws IllegalStateException if a mediaId is neither cached nor a playable URL
252
+ * @throws IllegalStateException if any mediaId is not found in cache
349
253
  */
350
254
  suspend fun resolveMediaItemsForPlayback(
351
255
  mediaItems: List<MediaItem>,
@@ -366,13 +270,10 @@ class BrowserManager {
366
270
  val searchTracks = searchResults.children
367
271
 
368
272
  if (searchTracks != null && searchTracks.isNotEmpty()) {
369
- // Find the selected track in search results (mediaId is the stable id
370
- // when the track has one, else url/src — see TrackFactory)
273
+ // Find the selected track in search results
371
274
  val mediaId = mediaItem.mediaId
372
275
  val selectedIndex =
373
- searchTracks.indexOfFirst { track ->
374
- track.id == mediaId || track.url == mediaId || track.src == mediaId
375
- }
276
+ searchTracks.indexOfFirst { track -> track.url == mediaId || track.src == mediaId }
376
277
 
377
278
  if (selectedIndex >= 0) {
378
279
  Timber.d(
@@ -396,14 +297,11 @@ class BrowserManager {
396
297
  }
397
298
 
398
299
  val mediaId = mediaItems[0].mediaId
399
- // A failed search match falls through to plain resolution, never to browse
400
- // expansion — the user asked for that one result, not a browsed list.
401
- val contextualUrl = if (searchQuery == null) contextualUrlFor(mediaId) else null
402
300
 
403
- if (contextualUrl != null) {
404
- Timber.d("Attempting queue expansion for mediaId='$mediaId' via '$contextualUrl'")
301
+ if (BrowserPathHelper.isContextual(mediaId)) {
302
+ Timber.d("Attempting queue expansion for mediaId='$mediaId'")
405
303
 
406
- val expanded = expandQueueFromContextualUrl(contextualUrl)
304
+ val expanded = expandQueueFromContextualUrl(mediaId)
407
305
 
408
306
  if (expanded != null) {
409
307
  val (tracks, selectedIndex) = expanded
@@ -420,11 +318,12 @@ class BrowserManager {
420
318
  }
421
319
  }
422
320
 
423
- // No expansion - resolve from cache (with a minimal-track fallback for replayed mediaIds)
424
- val resolvedTracks = mediaItems.map { resolveMediaItemToTrack(it) }
321
+ // No expansion - resolve from cache
322
+ val mediaIds = mediaItems.map { it.mediaId }
323
+ val cachedTracks = resolveMediaIdsFromCache(mediaIds)
425
324
 
426
325
  // Convert to Media3 MediaItems
427
- val resolvedMediaItems = resolvedTracks.map { track -> TrackFactory.toMedia3(track) }
326
+ val resolvedMediaItems = cachedTracks.map { track -> TrackFactory.toMedia3(track) }
428
327
 
429
328
  return MediaSession.MediaItemsWithStartPosition(resolvedMediaItems, startIndex, startPositionMs)
430
329
  }
@@ -456,11 +355,6 @@ class BrowserManager {
456
355
  if (useCache) {
457
356
  contentCache.get(normalizedPath)?.let { cached ->
458
357
  Timber.d("Content cache HIT for path='$normalizedPath'")
459
- // Re-key the track cache even on a hit: an id-keyed lookup (stable-id
460
- // mediaId → contextual url, see contextualUrlFor) must reflect the
461
- // most recently *browsed* container, which a cached re-display
462
- // otherwise wouldn't re-register.
463
- cacheChildren(cached)
464
358
  // Re-hydrate favorites in case they changed since caching
465
359
  return hydrateChildren(cached)
466
360
  }
@@ -493,37 +387,35 @@ class BrowserManager {
493
387
  Timber.d("Invalidated content cache for path='$path'")
494
388
  }
495
389
 
496
- /** Clears all cached content. */
390
+ /** Clears all cached content. Used when artwork resolver is wired up to force re-fetch. */
497
391
  fun clearContentCache() {
498
392
  contentCache.evictAll()
499
- // Bump the layer generation so request/browse resolver thunks are re-resolved on the next
500
- // request (invalidateAllContent → clearContentCache is the documented re-resolve trigger).
501
- layerGeneration += 1
502
- // Invalidated content's artwork resolutions go with it (same staleness rule as the
503
- // config setter).
504
- artworkResolutions.clear()
505
- onArtworkRegistriesCleared?.invoke()
506
393
  Timber.d("Cleared all content cache")
507
394
  }
508
395
 
509
396
  private suspend fun resolveUncached(path: String): ResolvedTrack {
510
- // Match an explicit route (or the '*' default). With no match, fall back to
511
- // the implicit default: fetch the path via the request + browse config.
512
- val match = config.routes?.let { findBestRouteMatch(path, it) }
513
-
514
- val resolvedTrack: ResolvedTrack
515
- val effectiveArtworkConfig: ArtworkRequestConfig?
516
- if (match != null) {
517
- val (routeEntry, routeParams) = match
518
- Timber.d("Matched route: ${routeEntry.path} with params: $routeParams")
519
- resolvedTrack = resolveRouteEntry(routeEntry, path, routeParams)
520
- effectiveArtworkConfig = routeEntry.artwork ?: config.artwork
521
- } else {
522
- Timber.d("No route matched for path: $path — using implicit default")
523
- resolvedTrack = executeApiRequest(null, path, mapOf("path" to path))
524
- effectiveArtworkConfig = config.artwork
397
+ val routes = config.routes
398
+ if (routes.isNullOrEmpty()) {
399
+ Timber.e("No routes configured for path: $path")
400
+ throw ContentNotFoundException(path)
525
401
  }
526
402
 
403
+ // Find best matching route
404
+ val (routeEntry, routeParams) =
405
+ findBestRouteMatch(path, routes)
406
+ ?: run {
407
+ Timber.e("No route matched for path: $path")
408
+ throw ContentNotFoundException(path)
409
+ }
410
+
411
+ Timber.d("Matched route: ${routeEntry.path} with params: $routeParams")
412
+
413
+ // Resolve the track from the route
414
+ val resolvedTrack = resolveRouteEntry(routeEntry, path, routeParams)
415
+
416
+ // Get effective artwork config: per-route overrides global
417
+ val effectiveArtworkConfig = routeEntry.artwork ?: config.artwork
418
+
527
419
  // Transform children: generate contextual URLs and transform artwork URLs
528
420
  val transformedChildren =
529
421
  resolvedTrack.children?.let { children ->
@@ -531,11 +423,8 @@ class BrowserManager {
531
423
  children
532
424
  .mapIndexed { index, track ->
533
425
  async {
534
- // Validate that track has stable identifier. A track carrying an
535
- // imageRow is exempt: a url-less row is a pure preview — never
536
- // selected, navigated to, or cached (its items carry their own
537
- // identity; on Android Auto it expands into them).
538
- if (track.imageRow.isNullOrEmpty()) validateTrack(track, "Child track")
426
+ // Validate that track has stable identifier
427
+ validateTrack(track, "Child track")
539
428
 
540
429
  var transformedTrack = track
541
430
 
@@ -557,35 +446,22 @@ class BrowserManager {
557
446
  )
558
447
  }
559
448
 
560
- // Playable image-row items get contextual URLs like any list
561
- // row, so a tile tap expands into its section's queue instead
562
- // of a queue of one (ADR 0006).
563
- transformedTrack.imageRow?.let { items ->
449
+ // Transform artwork URL if resolver is configured
450
+ // At browse-time, we don't have display size info
451
+ val resolver = artworkUrlResolver
452
+ if (resolver != null) {
453
+ val browseContext = ImageContext(null, null)
564
454
  transformedTrack =
565
- transformedTrack.copy(
566
- imageRow =
567
- items
568
- .map { item ->
569
- if (item.url == null && item.src != null) {
570
- item.copy(url = BrowserPathHelper.build(path, item.src))
571
- } else {
572
- item
573
- }
574
- }
575
- .toTypedArray()
455
+ transformArtworkUrl(
456
+ transformedTrack,
457
+ effectiveArtworkConfig,
458
+ resolver,
459
+ path,
460
+ index,
461
+ browseContext,
576
462
  )
577
463
  }
578
464
 
579
- // Transform artwork URL. At browse-time there is no display size info.
580
- transformedTrack =
581
- transformArtworkUrl(
582
- transformedTrack,
583
- effectiveArtworkConfig,
584
- path,
585
- index,
586
- ImageContext(null, null),
587
- )
588
-
589
465
  transformedTrack
590
466
  }
591
467
  }
@@ -602,7 +478,7 @@ class BrowserManager {
602
478
  }
603
479
 
604
480
  /**
605
- * Transforms a track's artwork via [resolveArtworkUrl]. Populates artworkSource with the
481
+ * Transforms a track's artwork using the configured resolver. Populates artworkSource with the
606
482
  * transformed ImageSource, keeping artwork unchanged. Handles all edge cases: undefined returns,
607
483
  * errors, missing artwork.
608
484
  *
@@ -611,6 +487,7 @@ class BrowserManager {
611
487
  private suspend fun transformArtworkUrl(
612
488
  track: Track,
613
489
  artworkConfig: ArtworkRequestConfig?,
490
+ resolver: suspend (Track, ArtworkRequestConfig?, ImageContext?) -> ImageSource?,
614
491
  path: String,
615
492
  index: Int,
616
493
  imageContext: ImageContext? = null,
@@ -621,7 +498,7 @@ class BrowserManager {
621
498
  }
622
499
 
623
500
  return try {
624
- val imageSource = resolveArtworkUrl(track, artworkConfig, imageContext)
501
+ val imageSource = resolver(track, artworkConfig, imageContext)
625
502
 
626
503
  when {
627
504
  // resolve returned null → no artwork source
@@ -634,15 +511,6 @@ class BrowserManager {
634
511
  // resolve returned ImageSource → set artworkSource
635
512
  else -> {
636
513
  Timber.d("[$path] Child[$index] '${track.title}': artworkSource set: ${imageSource.uri}")
637
- // Remember how this URI was produced so display-time loading (which only
638
- // gets a URI from Media3) can re-resolve Track-first with a size hint.
639
- // Register the per-route config only when it isn't the global fallback,
640
- // so display-time resolution reads the *current* config.artwork.
641
- artworkResolutions.register(
642
- imageSource.uri,
643
- track,
644
- artworkConfig?.takeIf { it !== config.artwork },
645
- )
646
514
  track.copy(artworkSource = imageSource)
647
515
  }
648
516
  }
@@ -681,20 +549,8 @@ class BrowserManager {
681
549
  return null
682
550
  }
683
551
 
684
- // Queue scope is the tapped section, not the whole page (ADR 0006). An
685
- // id that no longer appears on the page aborts the expansion — the
686
- // caller falls back to the stored single track; silently queueing the
687
- // changed list would resume the wrong station.
688
- val sectionTracks =
689
- when (val section = SectionScope.section(children.toList(), trackId)) {
690
- is SectionScope.Section.ImageRow ->
691
- with(TrackFactory) { section.items.map { it.toTrack(groupTitle = null) } }
692
- is SectionScope.Section.Run -> section.tracks
693
- null -> return null
694
- }
695
-
696
552
  // Filter to only playable tracks (tracks with src)
697
- val playableTracks = sectionTracks.filter { track -> track.src != null }
553
+ val playableTracks = children.filter { track -> track.src != null }
698
554
 
699
555
  if (playableTracks.isEmpty()) {
700
556
  Timber.w("Parent has no playable tracks, cannot expand queue")
@@ -786,9 +642,8 @@ class BrowserManager {
786
642
  * @return Array of Track results, or null if not found
787
643
  */
788
644
  fun getCachedSearchResults(query: String): Array<Track>? {
789
- val (cachedQuery, cachedResults) = lastSearch ?: return null
790
- if (query != cachedQuery) return null
791
- return cachedResults.map { hydrateFavorite(it) }.toTypedArray()
645
+ if (query != lastSearchQuery) return null
646
+ return lastSearchResults?.map { hydrateFavorite(it) }?.toTypedArray()
792
647
  }
793
648
 
794
649
  /**
@@ -807,7 +662,6 @@ class BrowserManager {
807
662
  album = null,
808
663
  title = null,
809
664
  playlist = null,
810
- reference = MediaReference.UNKNOWN,
811
665
  )
812
666
  )
813
667
  }
@@ -832,11 +686,10 @@ class BrowserManager {
832
686
 
833
687
  // Check if result is browsable-only (container/route) vs playable
834
688
  // If it's browsable but also playable (has src or playable=true), treat it as playable
835
- val firstResultUrl = firstResult.url
836
689
  val tracksToFilter =
837
- if (firstResult.src == null && firstResultUrl != null) {
838
- Timber.d("First search result is browsable-only, resolving: $firstResultUrl")
839
- val resolvedTrack = resolve(firstResultUrl)
690
+ if (firstResult.src == null) {
691
+ Timber.d("First search result is browsable-only, resolving: ${firstResult.url}")
692
+ val resolvedTrack = resolve(firstResult.url!!)
840
693
  resolvedTrack.children
841
694
  ?.filter { it.src != null }
842
695
  ?.takeIf { it.isNotEmpty() }
@@ -864,7 +717,6 @@ class BrowserManager {
864
717
  album = null,
865
718
  title = null,
866
719
  playlist = null,
867
- reference = MediaReference.UNKNOWN,
868
720
  )
869
721
  )
870
722
  }
@@ -883,34 +735,20 @@ class BrowserManager {
883
735
  val searchPath = BrowserPathHelper.createSearchPath(params.query)
884
736
 
885
737
  try {
886
- // Execute search. Drop results without a stable identifier (url or src): search results come
887
- // from server/JS data that doesn't pass through validateTrack like browse children do, and
888
- // downstream conversion (TrackFactory.toMedia3) and browsable-result resolution require one.
889
- val searchResults =
890
- resolveSearch(params)
891
- .filter { track ->
892
- val valid = track.url != null || track.src != null
893
- if (!valid) {
894
- Timber.w("Dropping search result without url or src: '${track.title}'")
895
- }
896
- valid
897
- }
898
- .toTypedArray()
738
+ // Execute search
739
+ val searchResults = resolveSearch(params)
899
740
 
900
741
  // Create ResolvedTrack
901
742
  val searchResolvedTrack =
902
743
  ResolvedTrack(
903
- id = null,
904
744
  url = searchPath,
905
745
  title = "Search: ${params.query}",
906
746
  children = searchResults,
907
747
  carPlaySiriListButton = null,
908
748
  artwork = null,
909
749
  artworkSource = null,
910
- request = null,
911
750
  artworkCarPlayTinted = null,
912
751
  artist = null,
913
- albumUrl = null,
914
752
  description = null,
915
753
  subtitle = null,
916
754
  album = null,
@@ -926,7 +764,8 @@ class BrowserManager {
926
764
  )
927
765
 
928
766
  // Cache search results for getCachedSearchResults()
929
- lastSearch = params.query to searchResults
767
+ lastSearchQuery = params.query
768
+ lastSearchResults = searchResults
930
769
 
931
770
  // Cache individual tracks for Media3 lookups
932
771
  cacheChildren(searchResolvedTrack)
@@ -941,17 +780,14 @@ class BrowserManager {
941
780
  // Return empty search result on error
942
781
  val emptySearchResult =
943
782
  ResolvedTrack(
944
- id = null,
945
783
  url = searchPath,
946
784
  title = "Search: ${params.query}",
947
785
  children = emptyArray(),
948
786
  carPlaySiriListButton = null,
949
787
  artwork = null,
950
788
  artworkSource = null,
951
- request = null,
952
789
  artworkCarPlayTinted = null,
953
790
  artist = null,
954
- albumUrl = null,
955
791
  description = null,
956
792
  subtitle = null,
957
793
  album = null,
@@ -1012,15 +848,6 @@ class BrowserManager {
1012
848
  onTabsChanged = callback
1013
849
  }
1014
850
 
1015
- /**
1016
- * Set callback invoked whenever both [artworkResolutions] and the browse-artwork registry are
1017
- * cleared (config swap or content invalidation). The caller should clear any parallel
1018
- * [com.audiobrowser.browser.BrowseArtworkRegistry] instance it owns.
1019
- */
1020
- fun setOnArtworkRegistriesCleared(callback: () -> Unit) {
1021
- onArtworkRegistriesCleared = callback
1022
- }
1023
-
1024
851
  /**
1025
852
  * Query navigation tabs from the configured tabs source. This is an async operation that resolves
1026
853
  * the tabs configuration.
@@ -1098,25 +925,15 @@ class BrowserManager {
1098
925
  entry.browseCallback?.let { callback ->
1099
926
  Timber.d("Resolving route via callback")
1100
927
  val param = BrowserSourceCallbackParam(path, routeParams)
1101
- // BrowserSourceCallback may return a BrowseResult synchronously or via a
1102
- // Promise. Nitro flattens (ResolvedTrack | BrowseError) | Promise<BrowseResult>
1103
- // into a 3-arm variant: sync track, sync error, or a Promise resolving to a
1104
- // BrowseResult (which is itself a ResolvedTrack | BrowseError variant).
1105
- return callback
1106
- .invoke(param)
1107
- .await()
1108
- .match(
1109
- first = { resolvedTrack -> resolvedTrack },
1110
- second = { browseError -> throw CallbackException(browseError.error) },
1111
- third = { promise ->
1112
- promise
1113
- .await()
1114
- .match(
1115
- first = { resolvedTrack -> resolvedTrack },
1116
- second = { browseError -> throw CallbackException(browseError.error) },
1117
- )
1118
- },
1119
- )
928
+ val promise = callback.invoke(param)
929
+ val innerPromise = promise.await()
930
+ val result = innerPromise.await()
931
+
932
+ // Handle BrowseResult variant: either ResolvedTrack or BrowseError
933
+ return result.match(
934
+ first = { resolvedTrack -> resolvedTrack },
935
+ second = { browseError -> throw CallbackException(browseError.error) }
936
+ )
1120
937
  }
1121
938
 
1122
939
  entry.browseConfig?.let { apiConfig ->
@@ -1182,119 +999,34 @@ class BrowserManager {
1182
999
  }
1183
1000
 
1184
1001
  /**
1185
- * Resolves a single request/browse layer. When a resolver thunk is present it is invoked and its
1186
- * result awaited. The resolver is Promise-only (the TS layer normalizes a sync-or-async thunk via
1187
- * Promise.resolve), so its native shape is `Promise<Promise<TransformableRequestConfig>>` — a
1188
- * double await. When there is no resolver the static layer config is returned as-is.
1189
- */
1190
- private suspend fun resolveLayer(
1191
- staticConfig: TransformableRequestConfig?,
1192
- resolver: Func_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____?,
1193
- ): TransformableRequestConfig? {
1194
- if (resolver == null) return staticConfig
1195
- // Promise-only resolver (the TS layer wraps a sync-or-async thunk in
1196
- // Promise.resolve) → double await: the bridge promise, then the JS promise.
1197
- return resolver.invoke().await().await()
1198
- }
1199
-
1200
- /**
1201
- * Ensures the request/browse resolver layers are resolved for the current [layerGeneration],
1202
- * caching the result. Re-resolves when the generation changes (config set or content
1203
- * invalidation). Uses a simple generation guard with no in-flight cache: a benign idempotent
1204
- * double-resolve under concurrent first-requests is acceptable, and on a thrown resolver nothing
1205
- * is cached so the next request retries naturally.
1206
- */
1207
- internal suspend fun ensureLayersResolved() {
1208
- if (resolvedLayerGeneration == layerGeneration) return
1209
- val generation = layerGeneration
1210
- val req = resolveLayer(config.request, config.requestResolver)
1211
- val brw = resolveLayer(config.browse, config.browseResolver)
1212
- // A newer generation started while we were awaiting — drop this stale result.
1213
- if (generation != layerGeneration) return
1214
- resolvedRequestLayer = req
1215
- resolvedBrowseLayer = brw
1216
- resolvedLayerGeneration = generation
1217
- }
1218
-
1219
- /**
1220
- * Ensures the request layer is resolved for the current generation and returns it (the resolver
1221
- * result when a [BrowserConfig.requestResolver] is configured, else the static
1222
- * [BrowserConfig.request]).
1223
- *
1224
- * Consumers outside the browse path (media URL building, artwork) must obtain the request layer
1225
- * through this accessor rather than reading the static `config.request`, so a resolver-only
1226
- * consumer still gets a baseUrl/headers/transform for media, artwork, and now-playing artwork.
1227
- */
1228
- internal suspend fun resolvedRequestConfig(): TransformableRequestConfig? {
1229
- ensureLayersResolved()
1230
- return resolvedRequestLayer
1231
- }
1232
-
1233
- /**
1234
- * Builds the HTTP request for an API-backed path by layering request (shared) → kind
1235
- * (browse/search) → route configs. Each layer's transform receives the previous layer's output; a
1236
- * layer with no transform merges its static fields.
1237
- *
1238
- * `initialQuery` seeds query params onto the BASE the kind layer receives (e.g. search q/mode/…):
1239
- * a layer with a transform "wins completely" and is handed only the base, so params placed on a
1240
- * layer's own static query would be dropped before the transform runs. The same goes for `path`:
1241
- * it is carried from the base through every layer (only a transform may change it), so a kind
1242
- * whose config supplies the path (search) must seed it via the `path` parameter. Mirrors iOS
1243
- * `buildApiRequest`.
1244
- *
1245
- * @throws ContentNotFoundException when no layer supplies a baseUrl — there is nothing to fetch,
1246
- * so the path is genuinely "not found" rather than a network error (mirrors iOS's `guard let
1247
- * baseUrl`).
1248
- */
1249
- internal suspend fun buildApiRequest(
1250
- kindConfig: TransformableRequestConfig?,
1251
- routeConfig: TransformableRequestConfig?,
1252
- path: String?,
1253
- params: Map<String, String>,
1254
- initialQuery: Map<String, String>? = null,
1255
- ): HttpClient.HttpRequest {
1256
- // Resolve the request/browse resolver thunks once per content generation (cached).
1257
- ensureLayersResolved()
1258
-
1259
- var merged =
1260
- RequestConfig(
1261
- method = null,
1262
- path = path,
1263
- baseUrl = null,
1264
- headers = null,
1265
- query = null,
1266
- body = null,
1267
- contentType = null,
1268
- userAgent = null,
1269
- )
1270
- resolvedRequestLayer?.let { merged = RequestConfigBuilder.mergeConfig(merged, it, params) }
1271
- if (!initialQuery.isNullOrEmpty()) {
1272
- merged = merged.copy(query = (merged.query ?: emptyMap()) + initialQuery)
1273
- }
1274
- kindConfig?.let { merged = RequestConfigBuilder.mergeConfig(merged, it, params) }
1275
- routeConfig?.let { merged = RequestConfigBuilder.mergeConfig(merged, it, params) }
1276
-
1277
- if (merged.baseUrl.isNullOrBlank()) {
1278
- throw ContentNotFoundException(path ?: "")
1279
- }
1280
- return RequestConfigBuilder.buildHttpRequest(merged)
1281
- }
1282
-
1283
- /**
1284
- * Execute an API request for browser content. Request building (layering + transforms + baseUrl
1285
- * guard) lives in [buildApiRequest]; this adds the browse-specific response shape (a
1286
- * ResolvedTrack page object).
1002
+ * Execute an API request for browser content. Handles URL parameter substitution, config merging,
1003
+ * and transforms.
1287
1004
  */
1288
1005
  private suspend fun executeApiRequest(
1289
- apiConfig: TransformableRequestConfig?,
1006
+ apiConfig: TransformableRequestConfig,
1290
1007
  path: String,
1291
1008
  routeParams: Map<String, String>,
1292
1009
  ): ResolvedTrack {
1293
1010
  return withContext(Dispatchers.IO) {
1294
- // request (shared) → browse (kind) → route. apiConfig is null for the
1295
- // implicit default (an unmatched browse path → fetch via request + browse + path).
1296
- ensureLayersResolved()
1297
- val httpRequest = buildApiRequest(resolvedBrowseLayer, apiConfig, path, routeParams)
1011
+ // 1. Start with base config, using the navigation path as default
1012
+ val baseConfig =
1013
+ config.request?.let { req ->
1014
+ RequestConfigBuilder.toRequestConfig(req).copy(path = req.path ?: path)
1015
+ }
1016
+ ?: RequestConfig(
1017
+ path = path,
1018
+ method = null,
1019
+ baseUrl = null,
1020
+ headers = null,
1021
+ query = null,
1022
+ body = null,
1023
+ contentType = null,
1024
+ userAgent = null,
1025
+ )
1026
+ val mergedConfig = RequestConfigBuilder.mergeConfig(baseConfig, apiConfig, routeParams)
1027
+
1028
+ // 2. Build and execute HTTP request
1029
+ val httpRequest = RequestConfigBuilder.buildHttpRequest(mergedConfig)
1298
1030
  val response = httpClient.request(httpRequest)
1299
1031
 
1300
1032
  response.fold(
@@ -1334,10 +1066,24 @@ class BrowserManager {
1334
1066
  ): Array<Track> {
1335
1067
  return withContext(Dispatchers.IO) {
1336
1068
  try {
1069
+ // 1. Start with base config
1070
+ val baseConfig =
1071
+ config.request?.let { RequestConfigBuilder.toRequestConfig(it) }
1072
+ ?: RequestConfig(
1073
+ method = null,
1074
+ path = null,
1075
+ baseUrl = null,
1076
+ headers = null,
1077
+ query = null,
1078
+ body = null,
1079
+ contentType = null,
1080
+ userAgent = null,
1081
+ )
1082
+
1083
+ // 2. Build query parameters from SearchParams
1337
1084
  val searchQueryParams = buildMap {
1338
1085
  put("q", params.query)
1339
1086
  params.mode?.let { put("mode", it.toString().lowercase()) }
1340
- if (params.reference == MediaReference.MY) put("reference", "my")
1341
1087
  params.genre?.let { put("genre", it) }
1342
1088
  params.artist?.let { put("artist", it) }
1343
1089
  params.album?.let { put("album", it) }
@@ -1345,26 +1091,31 @@ class BrowserManager {
1345
1091
  params.playlist?.let { put("playlist", it) }
1346
1092
  }
1347
1093
 
1348
- // request (shared) → search (kind); no browse layer and no route — search
1349
- // is its own kind. The search params seed the base (see buildApiRequest
1350
- // docs), and so does the search config's path: a layer's static path
1351
- // never applies (the path is carried from the base), so the caller
1352
- // seeds it — mirrors the web stub's fetchSearchResults.
1353
- val httpRequest =
1354
- buildApiRequest(
1355
- kindConfig = apiConfig,
1356
- routeConfig = null,
1094
+ // 3. Create a copy of API config with added search parameters
1095
+ val searchConfig =
1096
+ TransformableRequestConfig(
1097
+ transform = apiConfig.transform,
1098
+ method = apiConfig.method,
1357
1099
  path = apiConfig.path,
1358
- params = emptyMap(),
1359
- initialQuery = searchQueryParams,
1100
+ baseUrl = apiConfig.baseUrl,
1101
+ headers = apiConfig.headers,
1102
+ query = (apiConfig.query ?: emptyMap()) + searchQueryParams,
1103
+ body = apiConfig.body,
1104
+ contentType = apiConfig.contentType,
1105
+ userAgent = apiConfig.userAgent,
1360
1106
  )
1107
+
1108
+ // 3. Merge configs and apply transform if provided
1109
+ var mergedConfig = RequestConfigBuilder.mergeConfig(baseConfig, searchConfig, emptyMap())
1110
+
1111
+ // 4. Build and execute HTTP request
1112
+ val httpRequest = RequestConfigBuilder.buildHttpRequest(mergedConfig)
1361
1113
  val response = httpClient.request(httpRequest)
1362
1114
 
1363
1115
  response.fold(
1364
1116
  onSuccess = { httpResponse ->
1365
1117
  if (httpResponse.isSuccessful) {
1366
- // The search endpoint returns a bare Track array (unlike browse,
1367
- // which returns a page object). iOS parses it the same way.
1118
+ // 4. Parse response as Track array
1368
1119
  val jsonTracks = json.decodeFromString<List<JsonTrack>>(httpResponse.body)
1369
1120
  jsonTracks.map { it.toNitro() }.toTypedArray()
1370
1121
  } else {
@@ -1405,23 +1156,8 @@ class CallbackException(message: String) : Exception(message)
1405
1156
  */
1406
1157
  data class BrowserConfig(
1407
1158
  val request: TransformableRequestConfig? = null,
1408
- // Resolver thunk for the shared request layer. When set, it is resolved once per content
1409
- // generation (re-resolved after invalidateAllContent), cached, and merged per request — instead
1410
- // of carrying a static `request`. `request` and `requestResolver` are mutually exclusive in
1411
- // practice (the consumer sets one or the other), but both are merged if present.
1412
- val requestResolver:
1413
- Func_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____? =
1414
- null,
1415
- val browse: TransformableRequestConfig? = null,
1416
- // Resolver thunk for the browse layer. See `requestResolver`.
1417
- val browseResolver:
1418
- Func_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____? =
1419
- null,
1420
1159
  val media: MediaRequestConfig? = null,
1421
1160
  val artwork: ArtworkRequestConfig? = null,
1422
- // Now-playing-only artwork configuration (lock screen / notification / Android Auto now-playing).
1423
- // A distinct kind from `artwork`; the now-playing path falls back to `artwork` when this is null.
1424
- val nowPlayingArtwork: ArtworkRequestConfig? = null,
1425
1161
  // Routes as array with flattened entries (includes __tabs__, __search__, and __default__ special
1426
1162
  // routes)
1427
1163
  val routes: Array<NativeRouteEntry>? = null,