react-native-audio-browser 0.2.0-next.3 → 0.2.0-next.31

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 (989) hide show
  1. package/README.md +36 -22
  2. package/android/build.gradle +35 -12
  3. package/android/gradle.properties +2 -2
  4. package/android/src/main/AndroidManifest.xml +3 -1
  5. package/android/src/main/java/com/audiobrowser/AudioBrowser.kt +541 -278
  6. package/android/src/main/java/com/audiobrowser/AudioBrowserLifecycleModule.kt +38 -0
  7. package/android/src/main/java/com/audiobrowser/AudioBrowserPackage.kt +18 -2
  8. package/android/src/main/java/com/audiobrowser/ServiceBinding.kt +52 -0
  9. package/android/src/main/java/com/audiobrowser/browser/BrowserManager.kt +315 -213
  10. package/android/src/main/java/com/audiobrowser/browser/BrowserUrlResolution.kt +27 -9
  11. package/android/src/main/java/com/audiobrowser/browser/InertStyleDiagnostic.kt +288 -0
  12. package/android/src/main/java/com/audiobrowser/browser/JsonModels.kt +97 -58
  13. package/android/src/main/java/com/audiobrowser/browser/SectionScope.kt +70 -29
  14. package/android/src/main/java/com/audiobrowser/browser/StyleResolver.kt +60 -0
  15. package/android/src/main/java/com/audiobrowser/extension/ResolvedTrackExt.kt +20 -7
  16. package/android/src/main/java/com/audiobrowser/extension/TappedTrack.kt +20 -0
  17. package/android/src/main/java/com/audiobrowser/extension/TrackIdentity.kt +15 -0
  18. package/android/src/main/java/com/audiobrowser/http/HttpClient.kt +20 -3
  19. package/android/src/main/java/com/audiobrowser/model/IcyTitle.kt +24 -0
  20. package/android/src/main/java/com/audiobrowser/model/PlaybackMetadata.kt +10 -6
  21. package/android/src/main/java/com/audiobrowser/model/PlayerUpdateOptions.kt +12 -12
  22. package/android/src/main/java/com/audiobrowser/player/CapabilityControls.kt +111 -58
  23. package/android/src/main/java/com/audiobrowser/player/CrossOriginHeaderStripper.kt +77 -0
  24. package/android/src/main/java/com/audiobrowser/player/MediaFactory.kt +28 -10
  25. package/android/src/main/java/com/audiobrowser/player/MediaSessionCallback.kt +509 -230
  26. package/android/src/main/java/com/audiobrowser/player/MediaSessionCommandManager.kt +218 -252
  27. package/android/src/main/java/com/audiobrowser/player/NowPlayingUpdater.kt +21 -25
  28. package/android/src/main/java/com/audiobrowser/player/PlaybackStateStore.kt +113 -78
  29. package/android/src/main/java/com/audiobrowser/player/Player.kt +81 -38
  30. package/android/src/main/java/com/audiobrowser/player/PlayerCapabilitiesExt.kt +2 -15
  31. package/android/src/main/java/com/audiobrowser/player/PlayerListener.kt +1 -1
  32. package/android/src/main/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicy.kt +2 -1
  33. package/android/src/main/java/com/audiobrowser/player/ShuffleOrderLedBy.kt +30 -0
  34. package/android/src/main/java/com/audiobrowser/tls/AiaCertChaser.kt +67 -11
  35. package/android/src/main/java/com/audiobrowser/tls/AiaChasingExtendedTrustManager.kt +168 -0
  36. package/android/src/main/java/com/audiobrowser/tls/AiaChasingTrustManager.kt +58 -14
  37. package/android/src/main/java/com/audiobrowser/tls/AiaTls.kt +35 -7
  38. package/android/src/main/java/com/audiobrowser/tls/CachingCertificateFetcher.kt +278 -59
  39. package/android/src/main/java/com/audiobrowser/util/ArtworkVariant.kt +7 -9
  40. package/android/src/main/java/com/audiobrowser/util/BrowserPathHelper.kt +62 -40
  41. package/android/src/main/java/com/audiobrowser/util/MediaExtrasBuilder.kt +28 -23
  42. package/android/src/main/java/com/audiobrowser/util/StyleWire.kt +110 -0
  43. package/android/src/main/java/com/audiobrowser/util/TrackFactory.kt +56 -52
  44. package/android/src/main/res/values/strings.xml +25 -5
  45. package/android/src/test/java/com/audiobrowser/ServiceBindingTest.kt +100 -0
  46. package/android/src/test/java/com/audiobrowser/TestFixtures.kt +119 -33
  47. package/android/src/test/java/com/audiobrowser/browser/BrowserManagerFavoritesTest.kt +153 -0
  48. package/android/src/test/java/com/audiobrowser/browser/BrowserManagerLayerResolutionTest.kt +15 -0
  49. package/android/src/test/java/com/audiobrowser/browser/BrowserManagerTest.kt +346 -8
  50. package/android/src/test/java/com/audiobrowser/browser/BrowserUrlResolutionTest.kt +40 -2
  51. package/android/src/test/java/com/audiobrowser/browser/InertStyleDiagnosticTest.kt +301 -0
  52. package/android/src/test/java/com/audiobrowser/browser/JsonArtworkTest.kt +3 -2
  53. package/android/src/test/java/com/audiobrowser/browser/JsonStyleTest.kt +168 -0
  54. package/android/src/test/java/com/audiobrowser/browser/SectionScopeTest.kt +128 -55
  55. package/android/src/test/java/com/audiobrowser/browser/StyleResolverTest.kt +160 -0
  56. package/android/src/test/java/com/audiobrowser/extension/TappedTrackTest.kt +43 -0
  57. package/android/src/test/java/com/audiobrowser/extension/TrackIdentityTest.kt +41 -0
  58. package/android/src/test/java/com/audiobrowser/model/IcyTitleTest.kt +49 -0
  59. package/android/src/test/java/com/audiobrowser/player/BrowseTilesTest.kt +385 -0
  60. package/android/src/test/java/com/audiobrowser/player/CapabilityControlsTest.kt +101 -58
  61. package/android/src/test/java/com/audiobrowser/player/CrossOriginHeaderStripperTest.kt +94 -0
  62. package/android/src/test/java/com/audiobrowser/player/MediaSessionSlotMappingTest.kt +45 -0
  63. package/android/src/test/java/com/audiobrowser/player/NowPlayingUpdaterTest.kt +42 -2
  64. package/android/src/test/java/com/audiobrowser/player/PlaybackErrorClassifierTest.kt +3 -4
  65. package/android/src/test/java/com/audiobrowser/player/PlaybackStateStoreTrackJsonTest.kt +55 -0
  66. package/android/src/test/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicyTest.kt +3 -3
  67. package/android/src/test/java/com/audiobrowser/player/ShuffleOrderLedByTest.kt +79 -0
  68. package/android/src/test/java/com/audiobrowser/tls/AiaCertChaserTest.kt +197 -7
  69. package/android/src/test/java/com/audiobrowser/tls/AiaChasingTrustManagerTest.kt +325 -4
  70. package/android/src/test/java/com/audiobrowser/tls/CachingCertificateFetcherCallSiteTest.kt +322 -0
  71. package/android/src/test/java/com/audiobrowser/tls/CachingCertificateFetcherTest.kt +83 -0
  72. package/android/src/test/java/com/audiobrowser/util/BrowserPathHelperTest.kt +55 -16
  73. package/android/src/test/java/com/audiobrowser/util/MediaExtrasBuilderTest.kt +162 -0
  74. package/android/src/test/java/com/audiobrowser/util/TrackFactoryMediaIdTest.kt +7 -7
  75. package/ios/AVPlayerEngine.swift +330 -0
  76. package/ios/AVPlayerEngineCallbacks.swift +15 -0
  77. package/ios/Browser/BrowseGate.swift +58 -0
  78. package/ios/Browser/BrowserConfig.swift +117 -78
  79. package/ios/Browser/BrowserManager.swift +209 -603
  80. package/ios/Browser/BrowserPathHelper.swift +50 -46
  81. package/ios/Browser/InertStyleDiagnostic.swift +296 -0
  82. package/ios/Browser/JsonModels.swift +264 -106
  83. package/ios/Browser/NavigationErrorState.swift +41 -0
  84. package/ios/Browser/PageResolver.swift +227 -0
  85. package/ios/Browser/RequestLayer.swift +90 -0
  86. package/ios/Browser/{BrowserManager+URLResolution.swift → RequestPipeline.swift} +193 -121
  87. package/ios/Browser/SearchDrillIn.swift +7 -7
  88. package/ios/Browser/SectionScope.swift +58 -24
  89. package/ios/Browser/StyleResolver.swift +58 -0
  90. package/ios/Browser/TabBarEntries.swift +9 -3
  91. package/ios/Browser/TrackIdTemplate.swift +37 -0
  92. package/ios/CarPlay/CPInterfaceController+Safe.swift +100 -43
  93. package/ios/CarPlay/CarPlayArtworkResolver.swift +36 -83
  94. package/ios/CarPlay/CarPlayController.swift +42 -1296
  95. package/ios/CarPlay/CarPlayImageLoader.swift +78 -97
  96. package/ios/CarPlay/CarPlayListItemFactory.swift +303 -92
  97. package/ios/CarPlay/CarPlayNowPlayingManager.swift +129 -136
  98. package/ios/CarPlay/CarPlaySession+Navigator.swift +114 -0
  99. package/ios/CarPlay/CarPlaySession+PageLoader.swift +92 -0
  100. package/ios/CarPlay/CarPlaySession+Refresher.swift +43 -0
  101. package/ios/CarPlay/CarPlaySession+TabBar.swift +193 -0
  102. package/ios/CarPlay/CarPlaySession.swift +209 -0
  103. package/ios/CarPlay/CarPlayTemplates.swift +63 -0
  104. package/ios/CarPlay/HybridAudioBrowser+IntentFavorite.swift +20 -0
  105. package/ios/{Player → CarPlay}/MediaIntentCriteria.swift +17 -9
  106. package/ios/CarPlay/MediaIntentPlayback.swift +74 -0
  107. package/ios/CarPlay/RNABMediaAddHandler.swift +8 -24
  108. package/ios/CarPlay/RNABMediaAffinityHandler.swift +7 -23
  109. package/ios/CarPlay/RNABMediaIntentHandler.swift +18 -19
  110. package/ios/CarPlay/SectionPresentation.swift +77 -0
  111. package/ios/CarPlay/TopTemplateReplacer.swift +96 -0
  112. package/ios/Extension/Capability+RemoteCommand.swift +1 -1
  113. package/ios/Extension/NavigationError+Conversion.swift +14 -4
  114. package/ios/Extension/PlayerCapabilities+Favorite.swift +1 -15
  115. package/ios/Extension/ResolvedTrack+Copying.swift +13 -15
  116. package/ios/Extension/Section+Copying.swift +29 -0
  117. package/ios/Extension/String+IcyCharset.swift +21 -0
  118. package/ios/Extension/TimedMetadata+AVFoundation.swift +6 -4
  119. package/ios/Extension/Track+Copying.swift +8 -12
  120. package/ios/Extension/Track+Identity.swift +18 -0
  121. package/ios/Extension/UIApplication+ActiveScene.swift +27 -0
  122. package/ios/Extension/UIImage+Adaptive.swift +12 -0
  123. package/ios/Extension/URLError+Connectivity.swift +15 -0
  124. package/ios/Http/HttpClient.swift +66 -142
  125. package/ios/HybridAudioBrowser+Browser.swift +153 -0
  126. package/ios/HybridAudioBrowser+Options.swift +144 -0
  127. package/ios/HybridAudioBrowser+Player.swift +397 -0
  128. package/ios/HybridAudioBrowser+PlayerCallbacks.swift +189 -0
  129. package/ios/HybridAudioBrowser+Stubs.swift +46 -0
  130. package/ios/HybridAudioBrowser.swift +153 -1610
  131. package/ios/Model/NitroTypeStubs.swift +146 -24
  132. package/ios/Model/PlayerUpdateOptions.swift +8 -1
  133. package/ios/Model/RemoteCommand.swift +18 -0
  134. package/ios/Model/TrackPlayerError.swift +2 -2
  135. package/ios/NowPlayingInfo/NowPlayingInfoController.swift +18 -53
  136. package/ios/Observer/ItemObserver.swift +90 -0
  137. package/ios/Observer/PlayerObserver.swift +59 -0
  138. package/ios/Option/SessionCategories.swift +42 -92
  139. package/ios/Player/AudioSessionController.swift +189 -0
  140. package/ios/Player/DeferredSeek.swift +70 -0
  141. package/ios/Player/ErrorStatus.swift +27 -0
  142. package/ios/Player/MediaLoader.swift +62 -35
  143. package/ios/Player/NowPlayingUpdater.swift +197 -50
  144. package/ios/Player/PlaybackFailure.swift +125 -0
  145. package/ios/Player/PlaybackPersistence.swift +73 -0
  146. package/ios/Player/PlaybackTimer.swift +8 -2
  147. package/ios/Player/Player.swift +1078 -0
  148. package/ios/Player/{PlaybackCoordinatorCallbacks.swift → PlayerCallbacks.swift} +3 -4
  149. package/ios/Player/PlayerEngine.swift +87 -0
  150. package/ios/Player/PlayerStatusTypes.swift +2 -6
  151. package/ios/Player/QueueManager.swift +93 -67
  152. package/ios/Player/RetryLoop.swift +261 -0
  153. package/ios/Player/ShuffleOrder.swift +33 -0
  154. package/ios/Player/SleepTimerManager.swift +1 -1
  155. package/ios/RemoteCommand/RemoteCommandCallbacks.swift +46 -0
  156. package/ios/RemoteCommand/RemoteCommandController.swift +87 -331
  157. package/ios/Tests/BrowserPathHelperTests.swift +56 -15
  158. package/ios/Tests/CarPlayArtworkResolverTests.swift +60 -373
  159. package/ios/Tests/DeferredSeekTests.swift +70 -0
  160. package/ios/Tests/EmitterTests.swift +29 -0
  161. package/ios/Tests/GenerationMemoTests.swift +121 -0
  162. package/ios/Tests/InertStyleDiagnosticTests.swift +209 -0
  163. package/ios/Tests/JsonModelsTests.swift +164 -1
  164. package/ios/Tests/LRUCacheTests.swift +110 -0
  165. package/ios/Tests/MediaIntentCriteriaTests.swift +2 -2
  166. package/ios/Tests/MediaLoaderTests.swift +12 -48
  167. package/ios/Tests/ObserverTests.swift +88 -0
  168. package/ios/Tests/PlaybackErrorTests.swift +76 -0
  169. package/ios/Tests/PlaybackFailureTests.swift +189 -0
  170. package/ios/Tests/PlaybackPersistenceTests.swift +93 -0
  171. package/ios/Tests/PlayerPolicyTests.swift +420 -0
  172. package/ios/Tests/{PlaybackCoordinatorTests.swift → PlayerTests.swift} +300 -248
  173. package/ios/Tests/PlayingStateTests.swift +42 -0
  174. package/ios/Tests/QueueManagerTests.swift +196 -115
  175. package/ios/Tests/ReadyValueTests.swift +73 -0
  176. package/ios/Tests/RemoteCommandControllerTests.swift +152 -0
  177. package/ios/Tests/RemoteCommandTests.swift +65 -0
  178. package/ios/Tests/RequestLayerTests.swift +112 -0
  179. package/ios/Tests/ResolvedTrackCopyingTests.swift +39 -35
  180. package/ios/Tests/RetryLoopTests.swift +270 -0
  181. package/ios/Tests/SearchDrillInTests.swift +16 -16
  182. package/ios/Tests/SectionPresentationTests.swift +98 -0
  183. package/ios/Tests/SectionScopeTests.swift +87 -55
  184. package/ios/Tests/StyleResolverTests.swift +132 -0
  185. package/ios/Tests/Support/TestTypes.swift +108 -104
  186. package/ios/Tests/TabBarEntriesTests.swift +19 -19
  187. package/ios/Tests/TimedMetadataAVFoundationTests.swift +42 -0
  188. package/ios/Tests/TopTemplateReplacerTests.swift +172 -0
  189. package/ios/Tests/TrackIdTemplateTests.swift +67 -0
  190. package/ios/Tests/TrackIdentityTests.swift +20 -0
  191. package/ios/Tests/TrackSelectorTests.swift +168 -33
  192. package/ios/Tests/URLErrorConnectivityTests.swift +20 -0
  193. package/ios/TrackSelector.swift +46 -31
  194. package/ios/Util/ArtworkImageFetcher.swift +58 -1
  195. package/ios/Util/Emitter.swift +42 -0
  196. package/ios/Util/GenerationMemo.swift +36 -0
  197. package/ios/Util/LRUCache.swift +23 -159
  198. package/ios/Util/NetworkMonitor.swift +43 -26
  199. package/ios/Util/ReadyValue.swift +56 -0
  200. package/ios/Util/SFSymbolRenderer.swift +59 -31
  201. package/ios/Util/SVGProcessor.swift +9 -12
  202. package/lib/commonjs/AudioBrowser.js +8 -8
  203. package/lib/commonjs/AudioBrowser.js.map +1 -1
  204. package/lib/commonjs/CLAUDE.md +52 -0
  205. package/lib/commonjs/features/browser-config.js +12 -8
  206. package/lib/commonjs/features/browser-config.js.map +1 -1
  207. package/lib/commonjs/features/browser.js +11 -3
  208. package/lib/commonjs/features/browser.js.map +1 -1
  209. package/lib/commonjs/features/carConnection.js +1 -1
  210. package/lib/commonjs/features/equalizer.js +1 -1
  211. package/lib/commonjs/features/errors.js +3 -3
  212. package/lib/commonjs/features/favorites.js +14 -11
  213. package/lib/commonjs/features/favorites.js.map +1 -1
  214. package/lib/commonjs/features/gate.js +16 -1
  215. package/lib/commonjs/features/gate.js.map +1 -1
  216. package/lib/commonjs/features/metadata.js +20 -3
  217. package/lib/commonjs/features/metadata.js.map +1 -1
  218. package/lib/commonjs/features/network.js +1 -1
  219. package/lib/commonjs/features/nowPlaying.js +1 -1
  220. package/lib/commonjs/features/output.js +1 -1
  221. package/lib/commonjs/features/playback/controls.js +4 -2
  222. package/lib/commonjs/features/playback/controls.js.map +1 -1
  223. package/lib/commonjs/features/playback/playWhenReady.js +1 -1
  224. package/lib/commonjs/features/playback/playing.js +1 -1
  225. package/lib/commonjs/features/playback/progress.js +3 -2
  226. package/lib/commonjs/features/playback/progress.js.map +1 -1
  227. package/lib/commonjs/features/playback/rate.js +8 -1
  228. package/lib/commonjs/features/playback/rate.js.map +1 -1
  229. package/lib/commonjs/features/playback/state.js +3 -4
  230. package/lib/commonjs/features/playback/state.js.map +1 -1
  231. package/lib/commonjs/features/playback/trackPlaybackTime.js +0 -6
  232. package/lib/commonjs/features/playback/trackPlaybackTime.js.map +1 -1
  233. package/lib/commonjs/features/playback/volume.js +1 -1
  234. package/lib/commonjs/features/player/options.js +48 -34
  235. package/lib/commonjs/features/player/options.js.map +1 -1
  236. package/lib/commonjs/features/player/setup.js +18 -9
  237. package/lib/commonjs/features/player/setup.js.map +1 -1
  238. package/lib/commonjs/features/player/validateOptions.js +23 -0
  239. package/lib/commonjs/features/player/validateOptions.js.map +1 -0
  240. package/lib/commonjs/features/queue/activeTrack.js +15 -4
  241. package/lib/commonjs/features/queue/activeTrack.js.map +1 -1
  242. package/lib/commonjs/features/queue/queue.js +13 -6
  243. package/lib/commonjs/features/queue/queue.js.map +1 -1
  244. package/lib/commonjs/features/queue/repeatMode.js +1 -1
  245. package/lib/commonjs/features/queue/shuffle.js +1 -1
  246. package/lib/commonjs/features/remoteControls.js +13 -92
  247. package/lib/commonjs/features/remoteControls.js.map +1 -1
  248. package/lib/commonjs/features/sleepTimer.js +13 -1
  249. package/lib/commonjs/features/sleepTimer.js.map +1 -1
  250. package/lib/commonjs/test-utils/reactNativeStub.js +65 -0
  251. package/lib/commonjs/test-utils/reactNativeStub.js.map +1 -0
  252. package/lib/commonjs/utils/LazyNativeEmitter.js +28 -14
  253. package/lib/commonjs/utils/LazyNativeEmitter.js.map +1 -1
  254. package/lib/commonjs/utils/NativeUpdatedValue.js +31 -13
  255. package/lib/commonjs/utils/NativeUpdatedValue.js.map +1 -1
  256. package/lib/commonjs/utils/getTrackIdentity.js +24 -0
  257. package/lib/commonjs/utils/getTrackIdentity.js.map +1 -0
  258. package/lib/commonjs/utils/useNativeValueRefreshedBy.js +33 -0
  259. package/lib/commonjs/utils/useNativeValueRefreshedBy.js.map +1 -0
  260. package/lib/commonjs/web/NativeAudioBrowser.js +201 -76
  261. package/lib/commonjs/web/NativeAudioBrowser.js.map +1 -1
  262. package/lib/commonjs/web/TrackPlayer/LoadAttempt.js +37 -0
  263. package/lib/commonjs/web/TrackPlayer/LoadAttempt.js.map +1 -0
  264. package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js +18 -2
  265. package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js.map +1 -1
  266. package/lib/commonjs/web/TrackPlayer/Player.js +254 -39
  267. package/lib/commonjs/web/TrackPlayer/Player.js.map +1 -1
  268. package/lib/commonjs/web/TrackPlayer/PlayingStateFactory.js +1 -1
  269. package/lib/commonjs/web/TrackPlayer/QueueManager.js +14 -0
  270. package/lib/commonjs/web/TrackPlayer/QueueManager.js.map +1 -1
  271. package/lib/commonjs/web/TrackPlayer/QueuePlayer.js +33 -12
  272. package/lib/commonjs/web/TrackPlayer/QueuePlayer.js.map +1 -1
  273. package/lib/commonjs/web/browser/BrowserManager.js +175 -100
  274. package/lib/commonjs/web/browser/BrowserManager.js.map +1 -1
  275. package/lib/commonjs/web/browser/FavoriteManager.js +30 -21
  276. package/lib/commonjs/web/browser/FavoriteManager.js.map +1 -1
  277. package/lib/commonjs/web/browser/NavigationErrorManager.js +3 -1
  278. package/lib/commonjs/web/browser/NavigationErrorManager.js.map +1 -1
  279. package/lib/commonjs/web/browser/SearchManager.js +18 -23
  280. package/lib/commonjs/web/browser/SearchManager.js.map +1 -1
  281. package/lib/commonjs/web/browser/assertBrowsePageShape.js +2 -2
  282. package/lib/commonjs/web/browser/assertBrowsePageShape.js.map +1 -1
  283. package/lib/commonjs/web/browser/classifyTrackNavigation.js +9 -9
  284. package/lib/commonjs/web/browser/classifyTrackNavigation.js.map +1 -1
  285. package/lib/commonjs/web/browser/sections.js +89 -0
  286. package/lib/commonjs/web/browser/sections.js.map +1 -0
  287. package/lib/commonjs/web/http/RequestConfigBuilder.js +110 -27
  288. package/lib/commonjs/web/http/RequestConfigBuilder.js.map +1 -1
  289. package/lib/commonjs/web/http/followMediaRedirect.js +219 -0
  290. package/lib/commonjs/web/http/followMediaRedirect.js.map +1 -0
  291. package/lib/commonjs/web/player/NowPlayingManager.js +4 -3
  292. package/lib/commonjs/web/player/NowPlayingManager.js.map +1 -1
  293. package/lib/commonjs/web/util/BrowserPathHelper.js +62 -11
  294. package/lib/commonjs/web/util/BrowserPathHelper.js.map +1 -1
  295. package/lib/module/AudioBrowser.js +2 -1
  296. package/lib/module/AudioBrowser.js.map +1 -1
  297. package/lib/module/CLAUDE.md +52 -0
  298. package/lib/module/features/browser-config.js +12 -8
  299. package/lib/module/features/browser-config.js.map +1 -1
  300. package/lib/module/features/browser.js +11 -3
  301. package/lib/module/features/browser.js.map +1 -1
  302. package/lib/module/features/carConnection.js +1 -1
  303. package/lib/module/features/equalizer.js +1 -1
  304. package/lib/module/features/errors.js +3 -3
  305. package/lib/module/features/favorites.js +14 -11
  306. package/lib/module/features/favorites.js.map +1 -1
  307. package/lib/module/features/gate.js +16 -1
  308. package/lib/module/features/gate.js.map +1 -1
  309. package/lib/module/features/metadata.js +20 -3
  310. package/lib/module/features/metadata.js.map +1 -1
  311. package/lib/module/features/network.js +1 -1
  312. package/lib/module/features/nowPlaying.js +1 -1
  313. package/lib/module/features/output.js +1 -1
  314. package/lib/module/features/playback/controls.js +4 -2
  315. package/lib/module/features/playback/controls.js.map +1 -1
  316. package/lib/module/features/playback/playWhenReady.js +1 -1
  317. package/lib/module/features/playback/playing.js +1 -1
  318. package/lib/module/features/playback/progress.js +3 -2
  319. package/lib/module/features/playback/progress.js.map +1 -1
  320. package/lib/module/features/playback/rate.js +8 -1
  321. package/lib/module/features/playback/rate.js.map +1 -1
  322. package/lib/module/features/playback/state.js +3 -4
  323. package/lib/module/features/playback/state.js.map +1 -1
  324. package/lib/module/features/playback/trackPlaybackTime.js +0 -5
  325. package/lib/module/features/playback/trackPlaybackTime.js.map +1 -1
  326. package/lib/module/features/playback/volume.js +1 -1
  327. package/lib/module/features/player/options.js +47 -32
  328. package/lib/module/features/player/options.js.map +1 -1
  329. package/lib/module/features/player/setup.js +17 -8
  330. package/lib/module/features/player/setup.js.map +1 -1
  331. package/lib/module/features/player/validateOptions.js +19 -0
  332. package/lib/module/features/player/validateOptions.js.map +1 -0
  333. package/lib/module/features/queue/activeTrack.js +15 -4
  334. package/lib/module/features/queue/activeTrack.js.map +1 -1
  335. package/lib/module/features/queue/queue.js +13 -6
  336. package/lib/module/features/queue/queue.js.map +1 -1
  337. package/lib/module/features/queue/repeatMode.js +1 -1
  338. package/lib/module/features/queue/shuffle.js +1 -1
  339. package/lib/module/features/remoteControls.js +13 -92
  340. package/lib/module/features/remoteControls.js.map +1 -1
  341. package/lib/module/features/sleepTimer.js +13 -1
  342. package/lib/module/features/sleepTimer.js.map +1 -1
  343. package/lib/module/test-utils/reactNativeStub.js +58 -0
  344. package/lib/module/test-utils/reactNativeStub.js.map +1 -0
  345. package/lib/module/utils/LazyNativeEmitter.js +28 -14
  346. package/lib/module/utils/LazyNativeEmitter.js.map +1 -1
  347. package/lib/module/utils/NativeUpdatedValue.js +31 -13
  348. package/lib/module/utils/NativeUpdatedValue.js.map +1 -1
  349. package/lib/module/utils/getTrackIdentity.js +20 -0
  350. package/lib/module/utils/getTrackIdentity.js.map +1 -0
  351. package/lib/module/utils/useNativeValueRefreshedBy.js +29 -0
  352. package/lib/module/utils/useNativeValueRefreshedBy.js.map +1 -0
  353. package/lib/module/web/NativeAudioBrowser.js +201 -76
  354. package/lib/module/web/NativeAudioBrowser.js.map +1 -1
  355. package/lib/module/web/TrackPlayer/LoadAttempt.js +32 -0
  356. package/lib/module/web/TrackPlayer/LoadAttempt.js.map +1 -0
  357. package/lib/module/web/TrackPlayer/PlaybackStateMachine.js +18 -2
  358. package/lib/module/web/TrackPlayer/PlaybackStateMachine.js.map +1 -1
  359. package/lib/module/web/TrackPlayer/Player.js +254 -39
  360. package/lib/module/web/TrackPlayer/Player.js.map +1 -1
  361. package/lib/module/web/TrackPlayer/PlayingStateFactory.js +1 -1
  362. package/lib/module/web/TrackPlayer/QueueManager.js +14 -0
  363. package/lib/module/web/TrackPlayer/QueueManager.js.map +1 -1
  364. package/lib/module/web/TrackPlayer/QueuePlayer.js +33 -12
  365. package/lib/module/web/TrackPlayer/QueuePlayer.js.map +1 -1
  366. package/lib/module/web/browser/BrowserManager.js +175 -100
  367. package/lib/module/web/browser/BrowserManager.js.map +1 -1
  368. package/lib/module/web/browser/FavoriteManager.js +31 -21
  369. package/lib/module/web/browser/FavoriteManager.js.map +1 -1
  370. package/lib/module/web/browser/NavigationErrorManager.js +3 -1
  371. package/lib/module/web/browser/NavigationErrorManager.js.map +1 -1
  372. package/lib/module/web/browser/SearchManager.js +18 -23
  373. package/lib/module/web/browser/SearchManager.js.map +1 -1
  374. package/lib/module/web/browser/assertBrowsePageShape.js +2 -2
  375. package/lib/module/web/browser/assertBrowsePageShape.js.map +1 -1
  376. package/lib/module/web/browser/classifyTrackNavigation.js +9 -9
  377. package/lib/module/web/browser/classifyTrackNavigation.js.map +1 -1
  378. package/lib/module/web/browser/sections.js +83 -0
  379. package/lib/module/web/browser/sections.js.map +1 -0
  380. package/lib/module/web/http/RequestConfigBuilder.js +110 -27
  381. package/lib/module/web/http/RequestConfigBuilder.js.map +1 -1
  382. package/lib/module/web/http/followMediaRedirect.js +215 -0
  383. package/lib/module/web/http/followMediaRedirect.js.map +1 -0
  384. package/lib/module/web/player/NowPlayingManager.js +4 -3
  385. package/lib/module/web/player/NowPlayingManager.js.map +1 -1
  386. package/lib/module/web/util/BrowserPathHelper.js +62 -11
  387. package/lib/module/web/util/BrowserPathHelper.js.map +1 -1
  388. package/lib/typescript/package.json +1 -0
  389. package/lib/typescript/src/AudioBrowser.d.ts +1 -1
  390. package/lib/typescript/src/AudioBrowser.d.ts.map +1 -1
  391. package/lib/typescript/src/features/browser-config.d.ts.map +1 -1
  392. package/lib/typescript/src/features/browser.d.ts +10 -2
  393. package/lib/typescript/src/features/browser.d.ts.map +1 -1
  394. package/lib/typescript/src/features/carConnection.d.ts +1 -1
  395. package/lib/typescript/src/features/equalizer.d.ts +1 -1
  396. package/lib/typescript/src/features/errors.d.ts +3 -3
  397. package/lib/typescript/src/features/favorites.d.ts +14 -11
  398. package/lib/typescript/src/features/favorites.d.ts.map +1 -1
  399. package/lib/typescript/src/features/gate.d.ts +18 -2
  400. package/lib/typescript/src/features/gate.d.ts.map +1 -1
  401. package/lib/typescript/src/features/metadata.d.ts +20 -3
  402. package/lib/typescript/src/features/metadata.d.ts.map +1 -1
  403. package/lib/typescript/src/features/network.d.ts +1 -1
  404. package/lib/typescript/src/features/nowPlaying.d.ts +1 -1
  405. package/lib/typescript/src/features/output.d.ts +1 -1
  406. package/lib/typescript/src/features/playback/controls.d.ts +4 -2
  407. package/lib/typescript/src/features/playback/controls.d.ts.map +1 -1
  408. package/lib/typescript/src/features/playback/playWhenReady.d.ts +1 -1
  409. package/lib/typescript/src/features/playback/playing.d.ts +1 -1
  410. package/lib/typescript/src/features/playback/progress.d.ts +1 -1
  411. package/lib/typescript/src/features/playback/progress.d.ts.map +1 -1
  412. package/lib/typescript/src/features/playback/rate.d.ts +8 -1
  413. package/lib/typescript/src/features/playback/rate.d.ts.map +1 -1
  414. package/lib/typescript/src/features/playback/state.d.ts +3 -4
  415. package/lib/typescript/src/features/playback/state.d.ts.map +1 -1
  416. package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts +1 -1
  417. package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts.map +1 -1
  418. package/lib/typescript/src/features/playback/volume.d.ts +1 -1
  419. package/lib/typescript/src/features/player/options.d.ts +108 -56
  420. package/lib/typescript/src/features/player/options.d.ts.map +1 -1
  421. package/lib/typescript/src/features/player/setup.d.ts +14 -4
  422. package/lib/typescript/src/features/player/setup.d.ts.map +1 -1
  423. package/lib/typescript/src/features/player/validateOptions.d.ts +2 -0
  424. package/lib/typescript/src/features/player/validateOptions.d.ts.map +1 -0
  425. package/lib/typescript/src/features/queue/activeTrack.d.ts +9 -2
  426. package/lib/typescript/src/features/queue/activeTrack.d.ts.map +1 -1
  427. package/lib/typescript/src/features/queue/queue.d.ts +7 -4
  428. package/lib/typescript/src/features/queue/queue.d.ts.map +1 -1
  429. package/lib/typescript/src/features/queue/repeatMode.d.ts +1 -1
  430. package/lib/typescript/src/features/queue/shuffle.d.ts +1 -1
  431. package/lib/typescript/src/features/remoteControls.d.ts +23 -22
  432. package/lib/typescript/src/features/remoteControls.d.ts.map +1 -1
  433. package/lib/typescript/src/features/sleepTimer.d.ts +1 -1
  434. package/lib/typescript/src/features/sleepTimer.d.ts.map +1 -1
  435. package/lib/typescript/src/test-utils/reactNativeStub.d.ts +36 -0
  436. package/lib/typescript/src/test-utils/reactNativeStub.d.ts.map +1 -0
  437. package/lib/typescript/src/types/browser-native.d.ts +3 -2
  438. package/lib/typescript/src/types/browser-native.d.ts.map +1 -1
  439. package/lib/typescript/src/types/browser-nodes.d.ts +387 -126
  440. package/lib/typescript/src/types/browser-nodes.d.ts.map +1 -1
  441. package/lib/typescript/src/types/browser.d.ts +93 -61
  442. package/lib/typescript/src/types/browser.d.ts.map +1 -1
  443. package/lib/typescript/src/utils/LazyNativeEmitter.d.ts +19 -16
  444. package/lib/typescript/src/utils/LazyNativeEmitter.d.ts.map +1 -1
  445. package/lib/typescript/src/utils/NativeUpdatedValue.d.ts +24 -19
  446. package/lib/typescript/src/utils/NativeUpdatedValue.d.ts.map +1 -1
  447. package/lib/typescript/src/utils/getTrackIdentity.d.ts +18 -0
  448. package/lib/typescript/src/utils/getTrackIdentity.d.ts.map +1 -0
  449. package/lib/typescript/src/utils/resolveAssetSource.d.ts +1 -2
  450. package/lib/typescript/src/utils/resolveAssetSource.d.ts.map +1 -1
  451. package/lib/typescript/src/utils/useNativeValueRefreshedBy.d.ts +21 -0
  452. package/lib/typescript/src/utils/useNativeValueRefreshedBy.d.ts.map +1 -0
  453. package/nitrogen/generated/android/AudioBrowser+autolinking.cmake +1 -2
  454. package/nitrogen/generated/android/AudioBrowserOnLoad.cpp +4 -2
  455. package/nitrogen/generated/android/c++/JAndroidAudioContentType.hpp +2 -2
  456. package/nitrogen/generated/android/c++/JAndroidAudioOffloadSettings.hpp +2 -2
  457. package/nitrogen/generated/android/c++/JAndroidOptions.hpp +12 -12
  458. package/nitrogen/generated/android/c++/JAndroidPlayerWakeMode.hpp +2 -2
  459. package/nitrogen/generated/android/c++/JAppKilledPlaybackBehavior.hpp +2 -2
  460. package/nitrogen/generated/android/c++/JArtworkRendering.hpp +58 -0
  461. package/nitrogen/generated/android/c++/JArtworkRequestConfig.hpp +10 -5
  462. package/nitrogen/generated/android/c++/JArtworkVariants.hpp +2 -2
  463. package/nitrogen/generated/android/c++/JBatteryOptimizationStatus.hpp +2 -2
  464. package/nitrogen/generated/android/c++/JBatteryOptimizationStatusChangedEvent.hpp +2 -2
  465. package/nitrogen/generated/android/c++/JBatteryWarningPendingChangedEvent.hpp +2 -2
  466. package/nitrogen/generated/android/c++/JBrowseError.hpp +2 -2
  467. package/nitrogen/generated/android/c++/JBrowseResult.hpp +19 -7
  468. package/nitrogen/generated/android/c++/JBrowserSourceCallbackParam.hpp +2 -2
  469. package/nitrogen/generated/android/c++/JCarPlayNowPlayingButton.hpp +2 -2
  470. package/nitrogen/generated/android/c++/JCarPlayPlayingIndicatorLocation.hpp +58 -0
  471. package/nitrogen/generated/android/c++/JCarPlaySiriListButtonPosition.hpp +2 -2
  472. package/nitrogen/generated/android/c++/JCardImage.hpp +58 -0
  473. package/nitrogen/generated/android/c++/JChapterMetadata.hpp +2 -2
  474. package/nitrogen/generated/android/c++/JEqualizerSettings.hpp +10 -10
  475. package/nitrogen/generated/android/c++/JFavoriteChangedEvent.hpp +10 -5
  476. package/nitrogen/generated/android/c++/JFormatNavigationErrorParams.hpp +11 -5
  477. package/nitrogen/generated/android/c++/JFormatNowPlayingParams.hpp +10 -5
  478. package/nitrogen/generated/android/c++/JFormattedNavigationError.hpp +2 -2
  479. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.hpp +2 -2
  480. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___RequestConfig_std__optional_std__unordered_map_std__string__std__string__.hpp +9 -9
  481. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___Track.hpp +10 -5
  482. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_FormattedNavigationError____FormatNavigationErrorParams.hpp +4 -2
  483. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.hpp +10 -5
  484. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_std__string____Track.hpp +10 -5
  485. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.hpp +2 -2
  486. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____MediaTransformParams.hpp +2 -2
  487. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____RequestConfig_std__optional_std__unordered_map_std__string__std__string__.hpp +9 -9
  488. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____Track.hpp +10 -5
  489. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.hpp +2 -2
  490. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_Track______SearchParams.hpp +18 -12
  491. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_void_____TrackLoadEvent.hpp +10 -4
  492. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__string__.hpp +102 -0
  493. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.hpp +18 -6
  494. package/nitrogen/generated/android/c++/JFunc_void.hpp +2 -2
  495. package/nitrogen/generated/android/c++/JFunc_void_BatteryOptimizationStatusChangedEvent.hpp +2 -2
  496. package/nitrogen/generated/android/c++/JFunc_void_BatteryWarningPendingChangedEvent.hpp +2 -2
  497. package/nitrogen/generated/android/c++/JFunc_void_EqualizerSettings.hpp +2 -2
  498. package/nitrogen/generated/android/c++/JFunc_void_FavoriteChangedEvent.hpp +10 -5
  499. package/nitrogen/generated/android/c++/JFunc_void_GateEvent.hpp +2 -2
  500. package/nitrogen/generated/android/c++/JFunc_void_NavigationErrorEvent.hpp +2 -2
  501. package/nitrogen/generated/android/c++/JFunc_void_NowPlayingMetadata.hpp +2 -2
  502. package/nitrogen/generated/android/c++/JFunc_void_Options.hpp +9 -12
  503. package/nitrogen/generated/android/c++/JFunc_void_Output.hpp +2 -2
  504. package/nitrogen/generated/android/c++/JFunc_void_Playback.hpp +2 -2
  505. package/nitrogen/generated/android/c++/JFunc_void_PlaybackActiveTrackChangedEvent.hpp +10 -5
  506. package/nitrogen/generated/android/c++/JFunc_void_PlaybackErrorEvent.hpp +2 -2
  507. package/nitrogen/generated/android/c++/JFunc_void_PlaybackPlayWhenReadyChangedEvent.hpp +2 -2
  508. package/nitrogen/generated/android/c++/JFunc_void_PlaybackProgressUpdatedEvent.hpp +2 -2
  509. package/nitrogen/generated/android/c++/JFunc_void_PlaybackQueueEndedEvent.hpp +2 -2
  510. package/nitrogen/generated/android/c++/JFunc_void_PlayingState.hpp +2 -2
  511. package/nitrogen/generated/android/c++/JFunc_void_RemoteJumpBackwardEvent.hpp +2 -2
  512. package/nitrogen/generated/android/c++/JFunc_void_RemoteJumpForwardEvent.hpp +2 -2
  513. package/nitrogen/generated/android/c++/JFunc_void_RemotePlayIdEvent.hpp +2 -2
  514. package/nitrogen/generated/android/c++/JFunc_void_RemotePlaySearchEvent.hpp +2 -2
  515. package/nitrogen/generated/android/c++/JFunc_void_RemoteSeekEvent.hpp +2 -2
  516. package/nitrogen/generated/android/c++/JFunc_void_RemoteSkipEvent.hpp +2 -2
  517. package/nitrogen/generated/android/c++/JFunc_void_RepeatModeChangedEvent.hpp +2 -2
  518. package/nitrogen/generated/android/c++/JFunc_void_TimedMetadata.hpp +2 -2
  519. package/nitrogen/generated/android/c++/JFunc_void_TrackMetadata.hpp +2 -2
  520. package/nitrogen/generated/android/c++/JFunc_void_bool.hpp +2 -2
  521. package/nitrogen/generated/android/c++/JFunc_void_double.hpp +2 -2
  522. package/nitrogen/generated/android/c++/JFunc_void_std__optional_FormattedNavigationError_.hpp +2 -2
  523. package/nitrogen/generated/android/c++/JFunc_void_std__optional_ResolvedTrack_.hpp +17 -5
  524. package/nitrogen/generated/android/c++/JFunc_void_std__optional_std__variant_nitro__NullType__SleepTimerTime__SleepTimerEndOfTrack__.hpp +2 -2
  525. package/nitrogen/generated/android/c++/JFunc_void_std__string.hpp +2 -2
  526. package/nitrogen/generated/android/c++/JFunc_void_std__vector_ChapterMetadata_.hpp +16 -16
  527. package/nitrogen/generated/android/c++/JFunc_void_std__vector_Track_.hpp +24 -18
  528. package/nitrogen/generated/android/c++/JGate.hpp +2 -2
  529. package/nitrogen/generated/android/c++/JGateDecision.hpp +2 -2
  530. package/nitrogen/generated/android/c++/JGateEvent.hpp +2 -2
  531. package/nitrogen/generated/android/c++/JGateReason.hpp +2 -2
  532. package/nitrogen/generated/android/c++/JGridTile.hpp +64 -0
  533. package/nitrogen/generated/android/c++/JHttpMethod.hpp +2 -2
  534. package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.cpp +77 -53
  535. package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.hpp +3 -3
  536. package/nitrogen/generated/android/c++/JIOSCategory.hpp +2 -2
  537. package/nitrogen/generated/android/c++/JIOSCategoryMode.hpp +2 -2
  538. package/nitrogen/generated/android/c++/JIOSCategoryOptions.hpp +2 -2
  539. package/nitrogen/generated/android/c++/JIOSCategoryPolicy.hpp +2 -2
  540. package/nitrogen/generated/android/c++/JIOSOptions.hpp +17 -11
  541. package/nitrogen/generated/android/c++/JImageContext.hpp +2 -2
  542. package/nitrogen/generated/android/c++/JImageQueryParams.hpp +2 -2
  543. package/nitrogen/generated/android/c++/JImageShape.hpp +58 -0
  544. package/nitrogen/generated/android/c++/JImageSource.hpp +2 -2
  545. package/nitrogen/generated/android/c++/JMediaReference.hpp +2 -2
  546. package/nitrogen/generated/android/c++/JMediaRequestConfig.hpp +10 -5
  547. package/nitrogen/generated/android/c++/JMediaTransformParams.hpp +2 -2
  548. package/nitrogen/generated/android/c++/JNativeAndroidSetupOptions.hpp +2 -2
  549. package/nitrogen/generated/android/c++/JNativeBrowserConfiguration.hpp +48 -21
  550. package/nitrogen/generated/android/c++/JNativeGateRequest.hpp +2 -2
  551. package/nitrogen/generated/android/c++/JNativeIOSSetupOptions.hpp +10 -10
  552. package/nitrogen/generated/android/c++/JNativeRouteEntry.hpp +16 -4
  553. package/nitrogen/generated/android/c++/JNativeSetupPlayerOptions.hpp +17 -14
  554. package/nitrogen/generated/android/c++/JNativeUpdateOptions.hpp +9 -12
  555. package/nitrogen/generated/android/c++/JNavigationError.hpp +2 -2
  556. package/nitrogen/generated/android/c++/JNavigationErrorEvent.hpp +2 -2
  557. package/nitrogen/generated/android/c++/JNavigationErrorKind.hpp +58 -0
  558. package/nitrogen/generated/android/c++/JNavigationErrorType.hpp +2 -2
  559. package/nitrogen/generated/android/c++/JNitroAndroidUpdateOptions.hpp +12 -12
  560. package/nitrogen/generated/android/c++/JNitroIOSUpdateOptions.hpp +17 -11
  561. package/nitrogen/generated/android/c++/JNowPlayingMetadata.hpp +2 -2
  562. package/nitrogen/generated/android/c++/JNowPlayingUpdate.hpp +2 -2
  563. package/nitrogen/generated/android/c++/JOptions.hpp +9 -12
  564. package/nitrogen/generated/android/c++/JOutput.hpp +2 -2
  565. package/nitrogen/generated/android/c++/JOutputType.hpp +2 -2
  566. package/nitrogen/generated/android/c++/JPlayback.hpp +2 -2
  567. package/nitrogen/generated/android/c++/JPlaybackActiveTrackChangedEvent.hpp +10 -5
  568. package/nitrogen/generated/android/c++/JPlaybackError.hpp +2 -2
  569. package/nitrogen/generated/android/c++/JPlaybackErrorEvent.hpp +2 -2
  570. package/nitrogen/generated/android/c++/JPlaybackErrorKind.hpp +2 -2
  571. package/nitrogen/generated/android/c++/JPlaybackPlayWhenReadyChangedEvent.hpp +2 -2
  572. package/nitrogen/generated/android/c++/JPlaybackProgressUpdatedEvent.hpp +2 -2
  573. package/nitrogen/generated/android/c++/JPlaybackQueueEndedEvent.hpp +2 -2
  574. package/nitrogen/generated/android/c++/JPlaybackState.hpp +2 -2
  575. package/nitrogen/generated/android/c++/JPlayerCapabilities.hpp +7 -13
  576. package/nitrogen/generated/android/c++/JPlayingState.hpp +2 -2
  577. package/nitrogen/generated/android/c++/JProgress.hpp +2 -2
  578. package/nitrogen/generated/android/c++/{JNotificationButton.hpp → JRemoteButton.hpp} +19 -19
  579. package/nitrogen/generated/android/c++/JRemoteButtonLayout.hpp +86 -0
  580. package/nitrogen/generated/android/c++/JRemoteJumpBackwardEvent.hpp +2 -2
  581. package/nitrogen/generated/android/c++/JRemoteJumpForwardEvent.hpp +2 -2
  582. package/nitrogen/generated/android/c++/JRemotePlayIdEvent.hpp +2 -2
  583. package/nitrogen/generated/android/c++/JRemotePlaySearchEvent.hpp +2 -2
  584. package/nitrogen/generated/android/c++/JRemoteSeekEvent.hpp +2 -2
  585. package/nitrogen/generated/android/c++/JRemoteSkipEvent.hpp +2 -2
  586. package/nitrogen/generated/android/c++/JRepeatMode.hpp +2 -2
  587. package/nitrogen/generated/android/c++/JRepeatModeChangedEvent.hpp +2 -2
  588. package/nitrogen/generated/android/c++/JRequestConfig.hpp +2 -2
  589. package/nitrogen/generated/android/c++/JResolvedTrack.hpp +67 -59
  590. package/nitrogen/generated/android/c++/JRetryConfig.hpp +2 -2
  591. package/nitrogen/generated/android/c++/JSearchMode.hpp +2 -2
  592. package/nitrogen/generated/android/c++/JSearchParams.hpp +2 -2
  593. package/nitrogen/generated/android/c++/JSection.hpp +116 -0
  594. package/nitrogen/generated/android/c++/JSectionStyle.hpp +96 -0
  595. package/nitrogen/generated/android/c++/JSleepTimer.hpp +4 -4
  596. package/nitrogen/generated/android/c++/JSleepTimerEndOfTrack.hpp +2 -2
  597. package/nitrogen/generated/android/c++/JSleepTimerTime.hpp +2 -2
  598. package/nitrogen/generated/android/c++/JStallReason.hpp +2 -2
  599. package/nitrogen/generated/android/c++/JStyleDisplay.hpp +58 -0
  600. package/nitrogen/generated/android/c++/JTimedMetadata.hpp +2 -2
  601. package/nitrogen/generated/android/c++/JTrack.hpp +27 -48
  602. package/nitrogen/generated/android/c++/JTrackLoadEvent.hpp +18 -12
  603. package/nitrogen/generated/android/c++/JTrackMetadata.hpp +2 -2
  604. package/nitrogen/generated/android/c++/JTrackRequest.hpp +2 -2
  605. package/nitrogen/generated/android/c++/JTrackStyle.hpp +47 -19
  606. package/nitrogen/generated/android/c++/JTransformableRequestConfig.hpp +2 -2
  607. package/nitrogen/generated/android/c++/JVariant_Boolean_AndroidAudioOffloadSettings.hpp +3 -3
  608. package/nitrogen/generated/android/c++/JVariant_Boolean_RetryConfig.hpp +3 -3
  609. package/nitrogen/generated/android/c++/JVariant_NullType_Double.hpp +3 -3
  610. package/nitrogen/generated/android/c++/JVariant_NullType_RemoteButtonLayout.cpp +26 -0
  611. package/nitrogen/generated/android/c++/JVariant_NullType_RemoteButtonLayout.hpp +75 -0
  612. package/nitrogen/generated/android/c++/JVariant_ResolvedTrack_BrowseError_Promise_BrowseResult_.hpp +20 -8
  613. package/nitrogen/generated/android/c++/JVariant_String_ArtworkVariants.hpp +3 -3
  614. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidAudioOffloadSettings.kt +15 -0
  615. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidOptions.kt +20 -3
  616. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{FavoritesMatchMode.kt → ArtworkRendering.kt} +5 -5
  617. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ArtworkRequestConfig.kt +37 -0
  618. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ArtworkVariants.kt +15 -0
  619. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BatteryOptimizationStatusChangedEvent.kt +13 -0
  620. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BatteryWarningPendingChangedEvent.kt +13 -0
  621. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BrowseError.kt +13 -0
  622. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BrowseResult.kt +16 -7
  623. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BrowserSourceCallbackParam.kt +15 -0
  624. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/CarPlayPlayingIndicatorLocation.kt +23 -0
  625. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/CardImage.kt +23 -0
  626. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ChapterMetadata.kt +19 -0
  627. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/EqualizerSettings.kt +27 -0
  628. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FavoriteChangedEvent.kt +15 -0
  629. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormatNavigationErrorParams.kt +25 -3
  630. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormatNowPlayingParams.kt +21 -0
  631. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormattedNavigationError.kt +15 -0
  632. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.kt +0 -2
  633. 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 -2
  634. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___Track.kt +0 -2
  635. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_FormattedNavigationError____FormatNavigationErrorParams.kt +0 -2
  636. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.kt +0 -2
  637. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_std__string____Track.kt +0 -2
  638. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.kt +0 -2
  639. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____MediaTransformParams.kt +0 -2
  640. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____RequestConfig_std__optional_std__unordered_map_std__string__std__string__.kt +0 -2
  641. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____Track.kt +0 -2
  642. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.kt +0 -2
  643. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_Track______SearchParams.kt +0 -2
  644. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_void_____TrackLoadEvent.kt +0 -2
  645. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__string__.kt +78 -0
  646. 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 +0 -2
  647. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void.kt +0 -2
  648. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_BatteryOptimizationStatusChangedEvent.kt +0 -2
  649. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_BatteryWarningPendingChangedEvent.kt +0 -2
  650. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_EqualizerSettings.kt +0 -2
  651. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_FavoriteChangedEvent.kt +0 -2
  652. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_GateEvent.kt +0 -2
  653. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_NavigationErrorEvent.kt +0 -2
  654. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_NowPlayingMetadata.kt +0 -2
  655. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_Options.kt +0 -2
  656. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_Output.kt +0 -2
  657. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_Playback.kt +0 -2
  658. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackActiveTrackChangedEvent.kt +0 -2
  659. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackErrorEvent.kt +0 -2
  660. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackPlayWhenReadyChangedEvent.kt +0 -2
  661. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackProgressUpdatedEvent.kt +0 -2
  662. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackQueueEndedEvent.kt +0 -2
  663. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlayingState.kt +0 -2
  664. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemoteJumpBackwardEvent.kt +0 -2
  665. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemoteJumpForwardEvent.kt +0 -2
  666. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemotePlayIdEvent.kt +0 -2
  667. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemotePlaySearchEvent.kt +0 -2
  668. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemoteSeekEvent.kt +0 -2
  669. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemoteSkipEvent.kt +0 -2
  670. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RepeatModeChangedEvent.kt +0 -2
  671. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_TimedMetadata.kt +0 -2
  672. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_TrackMetadata.kt +0 -2
  673. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_bool.kt +0 -2
  674. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_double.kt +0 -2
  675. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__optional_FormattedNavigationError_.kt +0 -2
  676. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__optional_ResolvedTrack_.kt +0 -2
  677. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__optional_std__variant_nitro__NullType__SleepTimerTime__SleepTimerEndOfTrack__.kt +0 -2
  678. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__string.kt +0 -2
  679. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__vector_ChapterMetadata_.kt +0 -2
  680. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__vector_Track_.kt +0 -2
  681. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Gate.kt +15 -0
  682. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/GateDecision.kt +15 -0
  683. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/GateEvent.kt +13 -0
  684. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/GridTile.kt +25 -0
  685. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/HybridAudioBrowserSpec.kt +3 -1
  686. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IOSOptions.kt +25 -3
  687. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageContext.kt +15 -0
  688. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageQueryParams.kt +15 -0
  689. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageShape.kt +23 -0
  690. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageSource.kt +19 -0
  691. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaRequestConfig.kt +35 -0
  692. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaTransformParams.kt +15 -0
  693. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeAndroidSetupOptions.kt +31 -0
  694. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeBrowserConfiguration.kt +51 -5
  695. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeGateRequest.kt +17 -0
  696. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeIOSSetupOptions.kt +21 -0
  697. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeRouteEntry.kt +27 -0
  698. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeSetupPlayerOptions.kt +29 -0
  699. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeUpdateOptions.kt +23 -0
  700. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NavigationError.kt +19 -0
  701. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NavigationErrorEvent.kt +13 -0
  702. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NavigationErrorKind.kt +23 -0
  703. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroAndroidUpdateOptions.kt +20 -3
  704. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroIOSUpdateOptions.kt +25 -3
  705. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingMetadata.kt +29 -0
  706. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingUpdate.kt +17 -0
  707. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Options.kt +23 -0
  708. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Output.kt +17 -0
  709. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Playback.kt +15 -0
  710. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackActiveTrackChangedEvent.kt +21 -0
  711. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackError.kt +21 -0
  712. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackErrorEvent.kt +13 -0
  713. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackPlayWhenReadyChangedEvent.kt +13 -0
  714. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackProgressUpdatedEvent.kt +19 -0
  715. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackQueueEndedEvent.kt +15 -0
  716. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlayerCapabilities.kt +37 -2
  717. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlayingState.kt +15 -0
  718. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Progress.kt +17 -0
  719. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{NotificationButton.kt → RemoteButton.kt} +3 -3
  720. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteButtonLayout.kt +61 -0
  721. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteJumpBackwardEvent.kt +13 -0
  722. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteJumpForwardEvent.kt +13 -0
  723. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemotePlayIdEvent.kt +15 -0
  724. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemotePlaySearchEvent.kt +13 -0
  725. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteSeekEvent.kt +13 -0
  726. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteSkipEvent.kt +13 -0
  727. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RepeatModeChangedEvent.kt +13 -0
  728. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RequestConfig.kt +27 -0
  729. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ResolvedTrack.kt +67 -15
  730. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RetryConfig.kt +17 -0
  731. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SearchParams.kt +27 -0
  732. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Section.kt +66 -0
  733. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SectionStyle.kt +86 -0
  734. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SleepTimer.kt +18 -8
  735. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SleepTimerEndOfTrack.kt +13 -0
  736. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SleepTimerTime.kt +13 -0
  737. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/StyleDisplay.kt +23 -0
  738. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TimedMetadata.kt +21 -0
  739. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Track.kt +55 -12
  740. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackLoadEvent.kt +17 -0
  741. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackMetadata.kt +43 -0
  742. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackRequest.kt +17 -0
  743. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackStyle.kt +58 -5
  744. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TransformableRequestConfig.kt +31 -0
  745. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_Boolean_AndroidAudioOffloadSettings.kt +16 -7
  746. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_Boolean_RetryConfig.kt +16 -7
  747. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_NullType_Double.kt +16 -7
  748. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Variant_NullType_NotificationButtonLayout.kt → Variant_NullType_RemoteButtonLayout.kt} +24 -15
  749. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_ResolvedTrack_BrowseError_Promise_BrowseResult_.kt +18 -8
  750. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_String_ArtworkVariants.kt +16 -7
  751. package/nitrogen/generated/ios/AudioBrowser+autolinking.rb +2 -0
  752. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.cpp +38 -29
  753. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.hpp +779 -665
  754. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Umbrella.hpp +34 -16
  755. package/nitrogen/generated/ios/c++/HybridAudioBrowserSpecSwift.hpp +36 -18
  756. package/nitrogen/generated/ios/swift/AndroidOptions.swift +12 -12
  757. package/nitrogen/generated/ios/swift/ArtworkRendering.swift +40 -0
  758. package/nitrogen/generated/ios/swift/BrowseResult.swift +12 -0
  759. package/nitrogen/generated/ios/swift/CarPlayPlayingIndicatorLocation.swift +40 -0
  760. package/nitrogen/generated/ios/swift/CardImage.swift +40 -0
  761. package/nitrogen/generated/ios/swift/FormatNavigationErrorParams.swift +7 -2
  762. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__string__.swift +54 -0
  763. package/nitrogen/generated/ios/swift/GridTile.swift +48 -0
  764. package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec.swift +1 -1
  765. package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec_cxx.swift +2 -2
  766. package/nitrogen/generated/ios/swift/IOSOptions.swift +7 -2
  767. package/nitrogen/generated/ios/swift/ImageShape.swift +40 -0
  768. package/nitrogen/generated/ios/swift/NativeBrowserConfiguration.swift +52 -5
  769. package/nitrogen/generated/ios/swift/NavigationErrorKind.swift +40 -0
  770. package/nitrogen/generated/ios/swift/NitroAndroidUpdateOptions.swift +12 -12
  771. package/nitrogen/generated/ios/swift/NitroIOSUpdateOptions.swift +12 -1
  772. package/nitrogen/generated/ios/swift/PlayerCapabilities.swift +8 -27
  773. package/nitrogen/generated/ios/swift/{NotificationButton.swift → RemoteButton.swift} +6 -6
  774. package/nitrogen/generated/ios/swift/RemoteButtonLayout.swift +57 -0
  775. package/nitrogen/generated/ios/swift/ResolvedTrack.swift +62 -73
  776. package/nitrogen/generated/ios/swift/Section.swift +82 -0
  777. package/nitrogen/generated/ios/swift/SectionStyle.swift +133 -0
  778. package/nitrogen/generated/ios/swift/SleepTimer.swift +13 -0
  779. package/nitrogen/generated/ios/swift/StyleDisplay.swift +40 -0
  780. package/nitrogen/generated/ios/swift/Track.swift +28 -63
  781. package/nitrogen/generated/ios/swift/TrackStyle.swift +86 -22
  782. package/nitrogen/generated/ios/swift/Variant_Bool_AndroidAudioOffloadSettings.swift +12 -0
  783. package/nitrogen/generated/ios/swift/Variant_Bool_RetryConfig.swift +12 -0
  784. package/nitrogen/generated/ios/swift/Variant_NullType_Double.swift +12 -0
  785. package/nitrogen/generated/ios/swift/Variant_NullType_RemoteButtonLayout.swift +30 -0
  786. package/nitrogen/generated/ios/swift/Variant_ResolvedTrack_BrowseError_Promise_BrowseResult_.swift +13 -0
  787. package/nitrogen/generated/ios/swift/Variant_String_ArtworkVariants.swift +12 -0
  788. package/nitrogen/generated/shared/c++/AndroidOptions.hpp +8 -8
  789. package/nitrogen/generated/shared/c++/{FavoritesMatchMode.hpp → ArtworkRendering.hpp} +17 -17
  790. package/nitrogen/generated/shared/c++/CarPlayPlayingIndicatorLocation.hpp +76 -0
  791. package/nitrogen/generated/shared/c++/CardImage.hpp +76 -0
  792. package/nitrogen/generated/shared/c++/FormatNavigationErrorParams.hpp +9 -2
  793. package/nitrogen/generated/shared/c++/GridTile.hpp +84 -0
  794. package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.cpp +1 -1
  795. package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.hpp +1 -1
  796. package/nitrogen/generated/shared/c++/IOSOptions.hpp +9 -2
  797. package/nitrogen/generated/shared/c++/ImageShape.hpp +76 -0
  798. package/nitrogen/generated/shared/c++/NativeBrowserConfiguration.hpp +10 -6
  799. package/nitrogen/generated/shared/c++/NavigationErrorKind.hpp +76 -0
  800. package/nitrogen/generated/shared/c++/NitroAndroidUpdateOptions.hpp +8 -8
  801. package/nitrogen/generated/shared/c++/NitroIOSUpdateOptions.hpp +9 -2
  802. package/nitrogen/generated/shared/c++/PlayerCapabilities.hpp +6 -9
  803. package/nitrogen/generated/shared/c++/{NotificationButton.hpp → RemoteButton.hpp} +19 -19
  804. package/nitrogen/generated/shared/c++/RemoteButtonLayout.hpp +94 -0
  805. package/nitrogen/generated/shared/c++/ResolvedTrack.hpp +33 -37
  806. package/nitrogen/generated/shared/c++/Section.hpp +102 -0
  807. package/nitrogen/generated/shared/c++/SectionStyle.hpp +126 -0
  808. package/nitrogen/generated/shared/c++/StyleDisplay.hpp +76 -0
  809. package/nitrogen/generated/shared/c++/Track.hpp +18 -30
  810. package/nitrogen/generated/shared/c++/TrackStyle.hpp +73 -34
  811. package/package.json +24 -11
  812. package/src/AudioBrowser.ts +2 -1
  813. package/src/CLAUDE.md +52 -0
  814. package/src/features/battery.test.ts +79 -0
  815. package/src/features/browser-config.test.ts +21 -6
  816. package/src/features/browser-config.ts +12 -8
  817. package/src/features/browser.test.ts +1 -1
  818. package/src/features/browser.ts +11 -3
  819. package/src/features/carConnection.ts +1 -1
  820. package/src/features/equalizer.ts +1 -1
  821. package/src/features/errors.ts +3 -3
  822. package/src/features/favorites.ts +14 -11
  823. package/src/features/gate.ts +16 -1
  824. package/src/features/hook-wiring.test.ts +302 -0
  825. package/src/features/metadata.ts +20 -3
  826. package/src/features/network.ts +1 -1
  827. package/src/features/nowPlaying.ts +1 -1
  828. package/src/features/output.ts +1 -1
  829. package/src/features/playback/controls.ts +4 -2
  830. package/src/features/playback/playWhenReady.ts +1 -1
  831. package/src/features/playback/playing.ts +1 -1
  832. package/src/features/playback/progress.test.ts +169 -0
  833. package/src/features/playback/progress.ts +3 -2
  834. package/src/features/playback/rate.ts +8 -1
  835. package/src/features/playback/state.ts +3 -4
  836. package/src/features/playback/trackPlaybackTime.test.ts +16 -6
  837. package/src/features/playback/trackPlaybackTime.ts +1 -6
  838. package/src/features/playback/volume.ts +1 -1
  839. package/src/features/player/options.ts +126 -76
  840. package/src/features/player/setup.test.ts +24 -7
  841. package/src/features/player/setup.ts +22 -10
  842. package/src/features/player/validateOptions.ts +21 -0
  843. package/src/features/queue/activeTrack.ts +15 -4
  844. package/src/features/queue/queue.ts +13 -6
  845. package/src/features/queue/repeatMode.ts +1 -1
  846. package/src/features/queue/shuffle.ts +1 -1
  847. package/src/features/remoteControls.ts +13 -92
  848. package/src/features/sleepTimer.test.ts +172 -0
  849. package/src/features/sleepTimer.ts +9 -1
  850. package/src/nitro-stub-drift.test.ts +277 -0
  851. package/src/public-surface.test.ts +147 -0
  852. package/src/specs/audio-browser.nitro.ts +5 -4
  853. package/src/style-resolution.test.ts +210 -0
  854. package/src/test-utils/reactNativeStub.ts +60 -0
  855. package/src/types/browser-native.ts +7 -3
  856. package/src/types/browser-nodes.ts +403 -134
  857. package/src/types/browser.ts +97 -63
  858. package/src/utils/LazyNativeEmitter.ts +28 -15
  859. package/src/utils/NativeUpdatedValue.ts +29 -13
  860. package/src/utils/getTrackIdentity.ts +20 -0
  861. package/src/utils/useDebug.test.ts +182 -0
  862. package/src/utils/useNativeUpdatedValue.test.ts +103 -0
  863. package/src/utils/useNativeValueRefreshedBy.ts +38 -0
  864. package/src/web/NativeAudioBrowser.playWhenReady.test.ts +232 -2
  865. package/src/web/NativeAudioBrowser.ts +240 -83
  866. package/src/web/TrackPlayer/LoadAttempt.ts +29 -0
  867. package/src/web/TrackPlayer/PlaybackStateMachine.test.ts +60 -13
  868. package/src/web/TrackPlayer/PlaybackStateMachine.ts +22 -6
  869. package/src/web/TrackPlayer/Player.dispatch.test.ts +5 -3
  870. package/src/web/TrackPlayer/Player.load.test.ts +137 -1
  871. package/src/web/TrackPlayer/Player.ts +284 -37
  872. package/src/web/TrackPlayer/PlayingStateFactory.test.ts +1 -1
  873. package/src/web/TrackPlayer/PlayingStateFactory.ts +1 -1
  874. package/src/web/TrackPlayer/QueueManager.test.ts +29 -0
  875. package/src/web/TrackPlayer/QueueManager.ts +14 -0
  876. package/src/web/TrackPlayer/QueuePlayer.ts +33 -14
  877. package/src/web/__tests__/lifecycle.test.ts +345 -0
  878. package/src/web/__tests__/lifecycleHarness.ts +351 -0
  879. package/src/web/__tests__/loadEdgeCases.test.ts +246 -0
  880. package/src/web/__tests__/loadSupersession.test.ts +175 -0
  881. package/src/web/__tests__/retry.test.ts +169 -0
  882. package/src/web/browser/BrowserManager.ts +209 -111
  883. package/src/web/browser/FavoriteManager.test.ts +84 -0
  884. package/src/web/browser/FavoriteManager.ts +28 -23
  885. package/src/web/browser/NavigationErrorManager.ts +3 -1
  886. package/src/web/browser/SearchManager.test.ts +75 -0
  887. package/src/web/browser/SearchManager.ts +25 -28
  888. package/src/web/browser/__tests__/artwork-resolution.test.ts +117 -0
  889. package/src/web/browser/__tests__/layer-resolver.test.ts +35 -0
  890. package/src/web/browser/__tests__/search-artwork.test.ts +46 -0
  891. package/src/web/browser/__tests__/search-navigation.test.ts +76 -0
  892. package/src/web/browser/assertBrowsePageShape.test.ts +1 -1
  893. package/src/web/browser/assertBrowsePageShape.ts +5 -3
  894. package/src/web/browser/classifyTrackNavigation.test.ts +10 -8
  895. package/src/web/browser/classifyTrackNavigation.ts +9 -9
  896. package/src/web/browser/parseSearchResponse.test.ts +8 -2
  897. package/src/web/browser/sections.test.ts +91 -0
  898. package/src/web/browser/sections.ts +72 -0
  899. package/src/web/http/RequestConfigBuilder.test.ts +241 -1
  900. package/src/web/http/RequestConfigBuilder.ts +140 -33
  901. package/src/web/http/followMediaRedirect.test.ts +289 -0
  902. package/src/web/http/followMediaRedirect.ts +253 -0
  903. package/src/web/player/NowPlayingManager.ts +4 -3
  904. package/src/web/util/BrowserPathHelper.test.ts +68 -0
  905. package/src/web/util/BrowserPathHelper.ts +70 -13
  906. package/website/guide/android-auto.md +114 -0
  907. package/website/guide/android-certificates.md +409 -0
  908. package/website/guide/artwork.md +255 -0
  909. package/website/guide/audio-output.md +135 -0
  910. package/website/guide/automotive.md +86 -0
  911. package/website/guide/basic-usage.md +151 -0
  912. package/website/guide/battery.md +115 -0
  913. package/website/guide/browser.md +587 -0
  914. package/website/guide/carplay.md +650 -0
  915. package/website/guide/configuration.md +173 -0
  916. package/website/guide/equalizer.md +231 -0
  917. package/website/guide/errors.md +310 -0
  918. package/website/guide/favorites.md +154 -0
  919. package/website/guide/gate.md +143 -0
  920. package/website/guide/getting-started.md +46 -0
  921. package/website/guide/hooks.md +238 -0
  922. package/website/guide/live-streams.md +125 -0
  923. package/website/guide/metadata.md +239 -0
  924. package/website/guide/migrating-from-track-player.md +244 -0
  925. package/website/guide/native-callback-fetch.md +127 -0
  926. package/website/guide/network.md +86 -0
  927. package/website/guide/now-playing.md +175 -0
  928. package/website/guide/playback.md +328 -0
  929. package/website/guide/queue.md +300 -0
  930. package/website/guide/remote-controls.md +256 -0
  931. package/website/guide/search.md +255 -0
  932. package/website/guide/sleep-timer.md +268 -0
  933. package/website/guide/track.md +247 -0
  934. package/ios/Bridge.h +0 -8
  935. package/ios/Browser/MediaResolveComposer.swift +0 -114
  936. package/ios/CarPlay/ImageRowItem+CarPlay.swift +0 -19
  937. package/ios/Model/MediaURL.swift +0 -67
  938. package/ios/NowPlayingInfo/MediaItemProperty.swift +0 -78
  939. package/ios/NowPlayingInfo/NowPlayingInfoKeyValue.swift +0 -6
  940. package/ios/NowPlayingInfo/NowPlayingInfoProperty.swift +0 -220
  941. package/ios/Observer/PlayerItemNotificationObserver.swift +0 -119
  942. package/ios/Observer/PlayerItemPropertyObserver.swift +0 -133
  943. package/ios/Observer/PlayerStateObserver.swift +0 -50
  944. package/ios/Observer/PlayerTimeObserver.swift +0 -55
  945. package/ios/Option/PitchAlgorithms.swift +0 -17
  946. package/ios/Option/TimeEventFrequency.swift +0 -18
  947. package/ios/Player/LoadSeekCoordinator.swift +0 -99
  948. package/ios/Player/MediaLoaderDelegate.swift +0 -11
  949. package/ios/Player/PlaybackCoordinator.swift +0 -754
  950. package/ios/Player/PlaybackEffectHandler.swift +0 -54
  951. package/ios/Player/PlaybackErrorHandler.swift +0 -175
  952. package/ios/Player/PlaybackStateStore.swift +0 -27
  953. package/ios/Player/PlayingStateManager.swift +0 -33
  954. package/ios/Player/RetryManager.swift +0 -322
  955. package/ios/Player/SeekCompletionHandler.swift +0 -3
  956. package/ios/Player/SleepTimerHandling.swift +0 -15
  957. package/ios/Support/RNTrackPlayer-Bridging-Header.h +0 -7
  958. package/ios/Tests/LoadSeekCoordinatorTests.swift +0 -325
  959. package/ios/Tests/MediaResolveTests.swift +0 -126
  960. package/ios/Tests/OnceValueTests.swift +0 -79
  961. package/ios/Tests/PlaybackErrorHandlerTests.swift +0 -547
  962. package/ios/Tests/PlaybackStateStoreTests.swift +0 -48
  963. package/ios/Tests/PlayingStateManagerTests.swift +0 -57
  964. package/ios/Tests/RetryManagerTests.swift +0 -89
  965. package/ios/TrackPlayer.swift +0 -1014
  966. package/ios/TrackPlayerCallbacks.swift +0 -86
  967. package/ios/Util/MetadataAdapter.swift +0 -131
  968. package/ios/Util/OnceValue.swift +0 -104
  969. package/nitrogen/generated/android/c++/JFavoriteConfig.hpp +0 -58
  970. package/nitrogen/generated/android/c++/JFavoritesMatchMode.hpp +0 -58
  971. package/nitrogen/generated/android/c++/JImageRowItem.hpp +0 -105
  972. package/nitrogen/generated/android/c++/JNotificationButtonLayout.hpp +0 -94
  973. package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.cpp +0 -26
  974. package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.hpp +0 -71
  975. package/nitrogen/generated/android/c++/JVariant_NullType_NotificationButtonLayout.cpp +0 -26
  976. package/nitrogen/generated/android/c++/JVariant_NullType_NotificationButtonLayout.hpp +0 -75
  977. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FavoriteConfig.kt +0 -38
  978. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageRowItem.kt +0 -68
  979. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NotificationButtonLayout.kt +0 -50
  980. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_Boolean_FavoriteConfig.kt +0 -53
  981. package/nitrogen/generated/ios/swift/FavoriteConfig.swift +0 -29
  982. package/nitrogen/generated/ios/swift/FavoritesMatchMode.swift +0 -40
  983. package/nitrogen/generated/ios/swift/ImageRowItem.swift +0 -195
  984. package/nitrogen/generated/ios/swift/NotificationButtonLayout.swift +0 -92
  985. package/nitrogen/generated/ios/swift/Variant_Bool_FavoriteConfig.swift +0 -18
  986. package/nitrogen/generated/ios/swift/Variant_NullType_NotificationButtonLayout.swift +0 -18
  987. package/nitrogen/generated/shared/c++/FavoriteConfig.hpp +0 -84
  988. package/nitrogen/generated/shared/c++/ImageRowItem.hpp +0 -129
  989. package/nitrogen/generated/shared/c++/NotificationButtonLayout.hpp +0 -102
@@ -41,6 +41,11 @@ function applyImageQueryParams(config, imgParams, context) {
41
41
  };
42
42
  }
43
43
 
44
+ /** Whether `after` carries a header `before` had not already set identically. */
45
+ function addsHeaders(before, after) {
46
+ if (!after) return false;
47
+ return Object.entries(after).some(([key, value]) => before?.[key] !== value);
48
+ }
44
49
  /**
45
50
  * Builds and merges request configurations.
46
51
  * Mirrors Android's RequestConfigBuilder.kt
@@ -81,7 +86,9 @@ export const RequestConfigBuilder = {
81
86
  * A layer with a transform wins completely — it receives the base (plus route
82
87
  * params) and its result replaces the base; the layer's own static fields are
83
88
  * ignored. A layer without a transform merges its static fields over the base.
84
- * `path` is carried from the base — only a transform may change it.
89
+ * `path` is carried from the base — only a transform may change it. A
90
+ * throwing transform falls back to the base, so the layer is skipped and the
91
+ * ladder continues.
85
92
  *
86
93
  * Mirrors native's BrowserManager.applyLayer so web resolves the shared
87
94
  * `request` → `<kind>` → route chain identically across platforms.
@@ -92,10 +99,21 @@ export const RequestConfigBuilder = {
92
99
  // its result replaces it. When both are set they run as a pipeline — async
93
100
  // first, then sync (mirrors native applyLayer).
94
101
  if (layer.transform || layer.transformSync) {
95
- let cfg = base;
96
- if (layer.transform) cfg = await layer.transform(cfg, params);
97
- if (layer.transformSync) cfg = layer.transformSync(cfg, params);
98
- return cfg;
102
+ try {
103
+ let cfg = base;
104
+ if (layer.transform) cfg = await layer.transform(cfg, params);
105
+ if (layer.transformSync) cfg = layer.transformSync(cfg, params);
106
+ return cfg;
107
+ } catch (e) {
108
+ // A throwing transform costs its own layer, not the ladder: the layers
109
+ // under it stand, so a relative path still gets the shared `baseUrl`
110
+ // and a media request keeps the shared credential. One catch around
111
+ // the pair, as native has it, so a sync stage that throws after a
112
+ // successful async one also falls back to the layer's input rather
113
+ // than to a half-applied config.
114
+ console.error('Failed to apply transform function, using base config', e);
115
+ return base;
116
+ }
99
117
  }
100
118
  return {
101
119
  method: layer.method ?? base.method,
@@ -138,31 +156,103 @@ export const RequestConfigBuilder = {
138
156
  };
139
157
  },
140
158
  /**
141
- * Resolves a media URL using the media configuration.
142
- * Creates a RequestConfig with the track's src as the path, then builds the URL.
143
- * Supports the transform callback for URL manipulation.
159
+ * Resolves a media request from the layered configuration, returning the
160
+ * whole request rather than just its URL.
161
+ *
162
+ * The layers resolve headers (and a user agent) alongside the URL, and the
163
+ * media request needs all of them: native applies them to the AVURLAsset /
164
+ * ExoPlayer DataSpec, so web has to apply them to Shaka's requests or the
165
+ * same configuration authenticates on iOS and Android but 401s here.
144
166
  *
145
- * The shared `request` layer is applied first (its transform runs for media
146
- * too, per the documented contract — e.g. a dynamic baseUrl), then the media
147
- * transform / static fields on top. Mirrors native's resolveMediaUrl,
148
- * including its best-effort behaviour: if a transform throws, fall back to the
149
- * original `src` rather than failing the load.
167
+ * The resolved URL is returned in `path`, with `baseUrl` already folded into
168
+ * it. Best-effort throughout, but at two levels: a throwing transform or
169
+ * resolver costs only its own layer (see {@link applyLayer}), and the catch
170
+ * here is the backstop for anything left — a malformed `baseUrl` reaching
171
+ * `buildUrl`, say — which falls back to the bare `src`.
172
+ *
173
+ * The chain is `request` → `media` → `media.resolve(track)`, matching
174
+ * native's. See {@link applyMediaResolve} for why the per-track resolver goes
175
+ * last.
150
176
  *
151
177
  * @param src The track's src value (may be relative or absolute)
152
178
  * @param requestConfig The shared request configuration (applied first)
153
179
  * @param mediaConfig The media request configuration
154
- * @returns The resolved absolute URL
180
+ * @param track The track being loaded, for `media.resolve`; without it the
181
+ * per-track layer is skipped and the static layers stand
182
+ * @returns The resolved request, its URL in `path`
155
183
  */
156
- async resolveMediaUrl(src, requestConfig, mediaConfig) {
184
+ async resolveMediaRequest(src, requestConfig, mediaConfig, track) {
157
185
  try {
158
- const config = await this.applyLayers({
186
+ // The layers are applied one at a time rather than through `applyLayers`
187
+ // so the media layer's own header contribution stays visible; each
188
+ // transform still runs exactly once.
189
+ const shared = await this.applyLayer({
159
190
  path: src
160
- }, [requestConfig, mediaConfig]);
161
- return BrowserPathHelper.buildUrl(config.baseUrl, config.path ?? src);
191
+ }, requestConfig);
192
+ const layered = await this.applyLayer(shared, mediaConfig);
193
+ const config = await this.applyMediaResolve(layered, mediaConfig, track);
194
+ // buildUrl folds in baseUrl *and* appends `query`; both are cleared on
195
+ // the way out so the resolved url can't be rebuilt and double-applied.
196
+ return {
197
+ ...config,
198
+ baseUrl: undefined,
199
+ query: undefined,
200
+ path: this.buildUrl({
201
+ ...config,
202
+ path: config.path ?? src
203
+ }),
204
+ mediaLayerHeaders: addsHeaders(shared.headers, config.headers)
205
+ };
162
206
  } catch (e) {
163
207
  console.error('Failed to resolve media URL, using original src', e);
164
- return BrowserPathHelper.buildUrl(undefined, src);
208
+ return {
209
+ path: BrowserPathHelper.buildUrl(undefined, src),
210
+ mediaLayerHeaders: false
211
+ };
212
+ }
213
+ },
214
+ /**
215
+ * Applies `media.resolve(track)` / `media.resolveSync(track)` as the final,
216
+ * most-specific layer over an already request+media-layered config. A no-op
217
+ * without a track or a resolver, so the layers stand on their own.
218
+ *
219
+ * Last, not first: native runs the media layer's transform and then lets the
220
+ * per-track resolver win over the result (Android `applyMediaResolve`, iOS
221
+ * `applyMediaResolveLayer`), so a resolver minting a signed URL is not
222
+ * overwritten by the static layer that shaped the unsigned one. Override-wins
223
+ * on every field, `path` included — replacing the URL outright is the point.
224
+ *
225
+ * A throwing resolver falls back to the layered config, as native does: the
226
+ * per-track shaping is lost, the layers under it are not.
227
+ */
228
+ async applyMediaResolve(layered, mediaConfig, track) {
229
+ if (!track || !mediaConfig) return layered;
230
+ if (!mediaConfig.resolve && !mediaConfig.resolveSync) return layered;
231
+ try {
232
+ const resolved = await this.composeResolved(mediaConfig, track);
233
+ return resolved ? this.mergeConfig(layered, resolved) : layered;
234
+ } catch (e) {
235
+ console.error('Failed to apply media.resolve, using layered config', e);
236
+ return layered;
237
+ }
238
+ },
239
+ /**
240
+ * Runs a config's per-track resolvers and composes their output: async
241
+ * `resolve` first, then `resolveSync` merged over it, sync winning.
242
+ * `undefined` when neither is set or neither produced a config.
243
+ *
244
+ * Media and artwork share the pairing, so it lives here rather than in both
245
+ * — the same reason native has `composeResolved`. Errors are the callers' to
246
+ * handle: the two paths differ on what a throwing resolver costs.
247
+ */
248
+ async composeResolved(config, track) {
249
+ let resolved;
250
+ if (config.resolve) resolved = await config.resolve(track);
251
+ if (config.resolveSync) {
252
+ const sync = config.resolveSync(track);
253
+ resolved = resolved ? this.mergeConfig(resolved, sync) : sync;
165
254
  }
255
+ return resolved;
166
256
  },
167
257
  /**
168
258
  * Resolves an artwork URL and creates an ImageSource.
@@ -246,14 +336,7 @@ export const RequestConfigBuilder = {
246
336
 
247
337
  // Step 1: Per-track resolution — async `resolve` first, then `resolveSync`
248
338
  // merged over it (mirrors native).
249
- let resolvedConfig;
250
- if (artworkConfig.resolve) {
251
- resolvedConfig = await artworkConfig.resolve(track);
252
- }
253
- if (artworkConfig.resolveSync) {
254
- const r = artworkConfig.resolveSync(track);
255
- resolvedConfig = resolvedConfig ? this.mergeConfig(resolvedConfig, r) : r;
256
- }
339
+ const resolvedConfig = await this.composeResolved(artworkConfig, track);
257
340
  // If a resolver ran but produced nothing and there's no artwork URL, no artwork
258
341
  if ((artworkConfig.resolve || artworkConfig.resolveSync) && !resolvedConfig && artworkUrl === undefined) {
259
342
  return undefined;
@@ -1 +1 @@
1
- {"version":3,"names":["artworkUrl","resolveArtworkUrl","BrowserPathHelper","appendQueryParams","url","query","Object","keys","length","params","URLSearchParams","key","value","entries","undefined","append","String","queryString","toString","separator","includes","applyImageQueryParams","config","imgParams","context","width","height","RequestConfigBuilder","buildUrl","path","baseUrl","mergeConfig","base","override","method","headers","mergeHeaders","mergeQuery","body","contentType","userAgent","applyLayer","layer","transform","transformSync","cfg","applyLayers","layers","merged","toRequestConfig","resolveMediaUrl","src","requestConfig","mediaConfig","e","console","error","resolveArtworkSource","artworkConfig","resolvedUri","uri","resolveArtworkSourceAsync","track","imageContext","artwork","baseConfig","resolvedConfig","resolve","resolveSync","r","mergedConfig","imageQueryParams","request","finalUri","transformTrackArtwork","artworkSource"],"sourceRoot":"../../../../src","sources":["web/http/RequestConfigBuilder.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["artworkUrl","resolveArtworkUrl","BrowserPathHelper","appendQueryParams","url","query","Object","keys","length","params","URLSearchParams","key","value","entries","undefined","append","String","queryString","toString","separator","includes","applyImageQueryParams","config","imgParams","context","width","height","addsHeaders","before","after","some","RequestConfigBuilder","buildUrl","path","baseUrl","mergeConfig","base","override","method","headers","mergeHeaders","mergeQuery","body","contentType","userAgent","applyLayer","layer","transform","transformSync","cfg","e","console","error","applyLayers","layers","merged","toRequestConfig","resolveMediaRequest","src","requestConfig","mediaConfig","track","shared","layered","applyMediaResolve","mediaLayerHeaders","resolve","resolveSync","resolved","composeResolved","sync","resolveArtworkSource","artworkConfig","resolvedUri","uri","resolveArtworkSourceAsync","imageContext","artwork","baseConfig","resolvedConfig","mergedConfig","imageQueryParams","request","finalUri","transformTrackArtwork","artworkSource"],"sourceRoot":"../../../../src","sources":["web/http/RequestConfigBuilder.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,215 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Resolves a media URL that is authenticated by a header.
5
+ *
6
+ * Shaka only routes manifest requests through its networking engine, where a
7
+ * request filter can attach headers. A progressive file is played by assigning
8
+ * `mediaElement.src`, and a media element cannot send custom headers — so such
9
+ * a URL is unplayable that way. Following the redirect here yields the signed,
10
+ * public URL these endpoints hand back, which needs no auth of its own.
11
+ *
12
+ * Best effort and bounded: anything that fails — including taking too long, see
13
+ * {@link PROBE_TIMEOUT_MS} — falls back to the original URL, so the load fails
14
+ * or succeeds on its own terms rather than ours. It must never be the reason a
15
+ * load hangs: `load()` awaits this before Shaka sees the URL at all.
16
+ *
17
+ * Gated, because the probe is not free: a HEAD at a third-party stream host
18
+ * costs a CORS preflight, and most will refuse it, so an app that never
19
+ * authenticates its media would pay a round trip on every play for a result it
20
+ * always discards. It runs only for headers that look like media credentials
21
+ * ({@link isMediaAuth}), on media a media element actually has to play
22
+ * ({@link isManifestUrl}), and never on a URL the browser resolves locally.
23
+ */
24
+
25
+ /** URLs the browser resolves locally; there is no redirect to follow. */
26
+ const isLocalUrl = url => /^(file|blob|data|mediasource):/i.test(url);
27
+
28
+ /**
29
+ * Extensions Shaka types as a manifest, from its own `EXTENSIONS_TO_MIME_TYPES_`
30
+ * map: HLS, DASH and Smooth Streaming.
31
+ */
32
+ const MANIFEST_EXTENSIONS = new Set(['m3u8', 'mpd', 'ism']);
33
+
34
+ /**
35
+ * Whether Shaka will parse this as a manifest rather than hand it to the media
36
+ * element — in which case the probe has nothing to offer and something to cost.
37
+ *
38
+ * A manifest goes through Shaka's networking engine, where the request filter
39
+ * attaches the headers to the manifest, its segments and any key requests. The
40
+ * probe cannot improve on that, and it actively breaks it: on a cross-origin
41
+ * redirect the probe clears the headers, so the segments that Android still
42
+ * authenticates would go out bare and 401. So this is a correctness fix as much
43
+ * as it is one fewer round trip.
44
+ *
45
+ * Extension-based, and therefore partial — Shaka guesses the same way
46
+ * (`NetworkingUtils.getExtension`), but plenty of HLS endpoints have no
47
+ * extension at all. Those still get probed, which is the status quo rather than
48
+ * a regression. Nothing on `Track` carries a MIME type to do better with.
49
+ */
50
+ const isManifestUrl = url => {
51
+ const path = url.split(/[?#]/)[0] ?? '';
52
+ const filename = path.slice(path.lastIndexOf('/') + 1);
53
+ const pieces = filename.split('.');
54
+ return pieces.length > 1 && MANIFEST_EXTENSIONS.has(pieces[pieces.length - 1].toLowerCase());
55
+ };
56
+ /**
57
+ * How long the probe may take before the original URL is played instead.
58
+ *
59
+ * The same 8s the Android media client allows a connect or a read
60
+ * (`MediaFactory.mediaHttpClient`), which is generous for a HEAD but errs the
61
+ * safe way: a slow-but-working auth endpoint should not be abandoned, since
62
+ * giving up means playing a URL that will 401.
63
+ */
64
+ const PROBE_TIMEOUT_MS = 8_000;
65
+
66
+ /**
67
+ * `AbortSignal.timeout` where it exists (Safari 16+, Chrome 103+, Node 17.3+),
68
+ * else a hand-rolled equivalent, else nothing — an environment with neither
69
+ * still gets the deadline below, just without cancelling the request.
70
+ */
71
+ const timeoutSignal = ms => {
72
+ if (typeof AbortSignal === 'undefined') return undefined;
73
+ if (typeof AbortSignal.timeout === 'function') return AbortSignal.timeout(ms);
74
+ if (typeof AbortController === 'undefined') return undefined;
75
+ const controller = new AbortController();
76
+ setTimeout(() => controller.abort(), ms);
77
+ return controller.signal;
78
+ };
79
+
80
+ /**
81
+ * The probe, with a deadline. `load()` awaits this before Shaka is asked to
82
+ * play anything, so an unreachable host would otherwise stall the load
83
+ * indefinitely — no audio, and no error to show for it.
84
+ *
85
+ * Two mechanisms, each with its own job: the signal cancels the request, so a
86
+ * dead host does not hold a connection open behind us, and the race bounds *us*
87
+ * even where the fetch implementation ignores the signal. Whichever fires, the
88
+ * caller treats it as any other probe failure and plays the original URL.
89
+ */
90
+ const fetchWithDeadline = async (doFetch, url, headers, timeoutMs) => {
91
+ let timer;
92
+ try {
93
+ return await Promise.race([doFetch(url, {
94
+ method: 'HEAD',
95
+ headers,
96
+ redirect: 'follow',
97
+ signal: timeoutSignal(timeoutMs)
98
+ }), new Promise((_resolve, reject) => {
99
+ timer = setTimeout(() => reject(new Error(`Media redirect probe timed out (${timeoutMs}ms)`)), timeoutMs);
100
+ })]);
101
+ } finally {
102
+ if (timer !== undefined) clearTimeout(timer);
103
+ }
104
+ };
105
+
106
+ /**
107
+ * Whether these headers look like a media credential — the only thing the
108
+ * probe can fix, and the only thing worth a preflight.
109
+ *
110
+ * A header the `media` layer set is media-specific by construction. Otherwise
111
+ * only `Authorization` counts: an app authenticating one API for browse and
112
+ * media alike puts it on the shared `request` layer, and that is the common
113
+ * shape. Shared plumbing that also rides browse requests — an `X-Client-Version`
114
+ * — is not a credential and must not trigger the probe.
115
+ *
116
+ * The residual case is a shared layer carrying a custom auth header, say
117
+ * `X-Api-Key`, for media that needs it: move it to the `media` layer and the
118
+ * probe runs.
119
+ */
120
+ const isMediaAuth = (headers, mediaLayerHeaders) => mediaLayerHeaders || Object.keys(headers).some(key => key.toLowerCase() === 'authorization');
121
+ /**
122
+ * Origin of an http(s) URL, or undefined when it cannot be determined.
123
+ *
124
+ * Relative URLs are resolved against the document, because that is what the
125
+ * probe's own `fetch` does — a `src` of `/api/authed/7` is a request to the
126
+ * page's origin, so the credential went there. Without this a relative `src`
127
+ * has no origin, never matches the absolute URL the response reports, and the
128
+ * headers are dropped from every load that uses one.
129
+ *
130
+ * Parsed rather than pattern-matched so the comparison normalizes the way
131
+ * Android's `CrossOriginHeaderStripper.sameOrigin` does: `URL.host` omits a
132
+ * default port, so `https://a.com` and `https://a.com:443` are one origin, and
133
+ * it excludes userinfo, so `https://user@a.com` is not a third.
134
+ */
135
+ const originOf = url => {
136
+ try {
137
+ const base = typeof location === 'undefined' ? undefined : location.href;
138
+ const {
139
+ protocol,
140
+ host
141
+ } = new URL(url, base);
142
+ if (protocol !== 'http:' && protocol !== 'https:') return undefined;
143
+ return `${protocol}//${host}`;
144
+ } catch {
145
+ return undefined;
146
+ }
147
+ };
148
+
149
+ /**
150
+ * Whether the redirect left the origin the credential was addressed to.
151
+ *
152
+ * Only when both origins are known and differ. An origin we could not work out
153
+ * — a relative URL with no document base, outside a browser — is not evidence
154
+ * of a hop, and treating it as one is how the headers went missing before.
155
+ */
156
+ const leftTheOrigin = (from, to) => {
157
+ const origin = originOf(from);
158
+ return origin !== undefined && originOf(to) !== origin;
159
+ };
160
+ export async function followMediaRedirect(url, headers, {
161
+ fetchImpl,
162
+ mediaLayerHeaders = false,
163
+ timeoutMs = PROBE_TIMEOUT_MS
164
+ } = {}) {
165
+ if (!headers || Object.keys(headers).length === 0) return {
166
+ src: url,
167
+ headers
168
+ };
169
+ if (!isMediaAuth(headers, mediaLayerHeaders)) return {
170
+ src: url,
171
+ headers
172
+ };
173
+ if (isManifestUrl(url)) return {
174
+ src: url,
175
+ headers
176
+ };
177
+ if (isLocalUrl(url)) return {
178
+ src: url,
179
+ headers
180
+ };
181
+ const doFetch = fetchImpl ?? globalThis.fetch;
182
+ if (typeof doFetch !== 'function') return {
183
+ src: url,
184
+ headers
185
+ };
186
+ try {
187
+ // HEAD walks the chain without tripping download counting, which keys off
188
+ // ranged GETs. Deadlined, because the load waits on it.
189
+ const response = await fetchWithDeadline(doFetch, url, headers, timeoutMs);
190
+ const src = response.url || url;
191
+
192
+ // The status belongs to the *last* hop, so it only speaks for the
193
+ // authenticating endpoint when there was no redirect. Once one has
194
+ // happened, hop one authenticated and handed us its target, and a refusal
195
+ // past that is routinely about the method rather than the credential:
196
+ // presigned S3 and GCS URLs sign it — SigV4's canonical request opens with
197
+ // HTTPMethod, GCS V4's with HTTP_VERB — so a URL signed for GET answers a
198
+ // HEAD with 403. Keep the signed URL, which is the whole point of the walk,
199
+ // and let a real error surface through the player.
200
+ if (!response.ok && src === url) return {
201
+ src: url,
202
+ headers
203
+ };
204
+ return {
205
+ src,
206
+ headers: leftTheOrigin(url, src) ? undefined : headers
207
+ };
208
+ } catch {
209
+ return {
210
+ src: url,
211
+ headers
212
+ };
213
+ }
214
+ }
215
+ //# sourceMappingURL=followMediaRedirect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["isLocalUrl","url","test","MANIFEST_EXTENSIONS","Set","isManifestUrl","path","split","filename","slice","lastIndexOf","pieces","length","has","toLowerCase","PROBE_TIMEOUT_MS","timeoutSignal","ms","AbortSignal","undefined","timeout","AbortController","controller","setTimeout","abort","signal","fetchWithDeadline","doFetch","headers","timeoutMs","timer","Promise","race","method","redirect","_resolve","reject","Error","clearTimeout","isMediaAuth","mediaLayerHeaders","Object","keys","some","key","originOf","base","location","href","protocol","host","URL","leftTheOrigin","from","to","origin","followMediaRedirect","fetchImpl","src","globalThis","fetch","response","ok"],"sourceRoot":"../../../../src","sources":["web/http/followMediaRedirect.ts"],"mappings":"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","ignoreList":[]}
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
 
3
3
  import { artworkUrl } from '../../utils/artwork';
4
+ import { getTrackIdentity } from '../../utils/getTrackIdentity';
4
5
 
5
6
  /**
6
7
  * Manages now playing metadata overrides.
@@ -28,7 +29,7 @@ export class NowPlayingManager {
28
29
  album: update.album ?? currentTrack.album,
29
30
  artwork: artworkUrl(currentTrack.artwork),
30
31
  description: currentTrack.description,
31
- mediaId: currentTrack.src ?? currentTrack.url,
32
+ mediaId: getTrackIdentity(currentTrack) ?? currentTrack.path,
32
33
  genre: currentTrack.genre,
33
34
  duration
34
35
  } : {
@@ -37,7 +38,7 @@ export class NowPlayingManager {
37
38
  album: currentTrack.album,
38
39
  artwork: artworkUrl(currentTrack.artwork),
39
40
  description: currentTrack.description,
40
- mediaId: currentTrack.src ?? currentTrack.url,
41
+ mediaId: getTrackIdentity(currentTrack) ?? currentTrack.path,
41
42
  genre: currentTrack.genre,
42
43
  duration
43
44
  };
@@ -59,7 +60,7 @@ export class NowPlayingManager {
59
60
  album: this.override?.album ?? currentTrack.album,
60
61
  artwork: artworkUrl(currentTrack.artwork),
61
62
  description: currentTrack.description,
62
- mediaId: currentTrack.src ?? currentTrack.url,
63
+ mediaId: getTrackIdentity(currentTrack) ?? currentTrack.path,
63
64
  genre: currentTrack.genre,
64
65
  duration
65
66
  };
@@ -1 +1 @@
1
- {"version":3,"names":["artworkUrl","NowPlayingManager","onNowPlayingChanged","updateNowPlaying","update","currentTrack","duration","override","metadata","title","artist","album","artwork","description","mediaId","src","url","genre","getNowPlaying","undefined","clearNowPlayingOverride"],"sourceRoot":"../../../../src","sources":["web/player/NowPlayingManager.ts"],"mappings":";;AAEA,SAASA,UAAU,QAAQ,qBAAqB;;AAEhD;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,iBAAiB,CAAC;EAG7B;EACAC,mBAAmB,GAA2CA,CAAA,KAAM,CAAC,CAAC;;EAEtE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;EACEC,gBAAgBA,CACdC,MAAoC,EACpCC,YAA+B,EAC/BC,QAAgB,EACV;IACN,IAAI,CAACC,QAAQ,GAAGH,MAAM;IAEtB,IAAI,CAACC,YAAY,EAAE;IAEnB,MAAMG,QAA4B,GAAGJ,MAAM,GACvC;MACEK,KAAK,EAAEL,MAAM,CAACK,KAAK,IAAIJ,YAAY,CAACI,KAAK;MACzCC,MAAM,EAAEN,MAAM,CAACM,MAAM,IAAIL,YAAY,CAACK,MAAM;MAC5CC,KAAK,EAAEP,MAAM,CAACO,KAAK,IAAIN,YAAY,CAACM,KAAK;MACzCC,OAAO,EAAEZ,UAAU,CAACK,YAAY,CAACO,OAAO,CAAC;MACzCC,WAAW,EAAER,YAAY,CAACQ,WAAW;MACrCC,OAAO,EAAET,YAAY,CAACU,GAAG,IAAIV,YAAY,CAACW,GAAG;MAC7CC,KAAK,EAAEZ,YAAY,CAACY,KAAK;MACzBX;IACF,CAAC,GACD;MACEG,KAAK,EAAEJ,YAAY,CAACI,KAAK;MACzBC,MAAM,EAAEL,YAAY,CAACK,MAAM;MAC3BC,KAAK,EAAEN,YAAY,CAACM,KAAK;MACzBC,OAAO,EAAEZ,UAAU,CAACK,YAAY,CAACO,OAAO,CAAC;MACzCC,WAAW,EAAER,YAAY,CAACQ,WAAW;MACrCC,OAAO,EAAET,YAAY,CAACU,GAAG,IAAIV,YAAY,CAACW,GAAG;MAC7CC,KAAK,EAAEZ,YAAY,CAACY,KAAK;MACzBX;IACF,CAAC;IAEL,IAAI,CAACJ,mBAAmB,CAACM,QAAQ,CAAC;EACpC;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;EACEU,aAAaA,CACXb,YAA+B,EAC/BC,QAAgB,EACgB;IAChC,IAAI,CAACD,YAAY,EAAE,OAAOc,SAAS;IAEnC,OAAO;MACLV,KAAK,EAAE,IAAI,CAACF,QAAQ,EAAEE,KAAK,IAAIJ,YAAY,CAACI,KAAK;MACjDC,MAAM,EAAE,IAAI,CAACH,QAAQ,EAAEG,MAAM,IAAIL,YAAY,CAACK,MAAM;MACpDC,KAAK,EAAE,IAAI,CAACJ,QAAQ,EAAEI,KAAK,IAAIN,YAAY,CAACM,KAAK;MACjDC,OAAO,EAAEZ,UAAU,CAACK,YAAY,CAACO,OAAO,CAAC;MACzCC,WAAW,EAAER,YAAY,CAACQ,WAAW;MACrCC,OAAO,EAAET,YAAY,CAACU,GAAG,IAAIV,YAAY,CAACW,GAAG;MAC7CC,KAAK,EAAEZ,YAAY,CAACY,KAAK;MACzBX;IACF,CAAC;EACH;;EAEA;AACF;AACA;AACA;EACEc,uBAAuBA,CAAA,EAAS;IAC9B,IAAI,CAACb,QAAQ,GAAGY,SAAS;EAC3B;AACF","ignoreList":[]}
1
+ {"version":3,"names":["artworkUrl","getTrackIdentity","NowPlayingManager","onNowPlayingChanged","updateNowPlaying","update","currentTrack","duration","override","metadata","title","artist","album","artwork","description","mediaId","path","genre","getNowPlaying","undefined","clearNowPlayingOverride"],"sourceRoot":"../../../../src","sources":["web/player/NowPlayingManager.ts"],"mappings":";;AAEA,SAASA,UAAU,QAAQ,qBAAqB;AAChD,SAASC,gBAAgB,QAAQ,8BAA8B;;AAE/D;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,iBAAiB,CAAC;EAG7B;EACAC,mBAAmB,GAA2CA,CAAA,KAAM,CAAC,CAAC;;EAEtE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;EACEC,gBAAgBA,CACdC,MAAoC,EACpCC,YAA+B,EAC/BC,QAAgB,EACV;IACN,IAAI,CAACC,QAAQ,GAAGH,MAAM;IAEtB,IAAI,CAACC,YAAY,EAAE;IAEnB,MAAMG,QAA4B,GAAGJ,MAAM,GACvC;MACEK,KAAK,EAAEL,MAAM,CAACK,KAAK,IAAIJ,YAAY,CAACI,KAAK;MACzCC,MAAM,EAAEN,MAAM,CAACM,MAAM,IAAIL,YAAY,CAACK,MAAM;MAC5CC,KAAK,EAAEP,MAAM,CAACO,KAAK,IAAIN,YAAY,CAACM,KAAK;MACzCC,OAAO,EAAEb,UAAU,CAACM,YAAY,CAACO,OAAO,CAAC;MACzCC,WAAW,EAAER,YAAY,CAACQ,WAAW;MACrCC,OAAO,EAAEd,gBAAgB,CAACK,YAAY,CAAC,IAAIA,YAAY,CAACU,IAAI;MAC5DC,KAAK,EAAEX,YAAY,CAACW,KAAK;MACzBV;IACF,CAAC,GACD;MACEG,KAAK,EAAEJ,YAAY,CAACI,KAAK;MACzBC,MAAM,EAAEL,YAAY,CAACK,MAAM;MAC3BC,KAAK,EAAEN,YAAY,CAACM,KAAK;MACzBC,OAAO,EAAEb,UAAU,CAACM,YAAY,CAACO,OAAO,CAAC;MACzCC,WAAW,EAAER,YAAY,CAACQ,WAAW;MACrCC,OAAO,EAAEd,gBAAgB,CAACK,YAAY,CAAC,IAAIA,YAAY,CAACU,IAAI;MAC5DC,KAAK,EAAEX,YAAY,CAACW,KAAK;MACzBV;IACF,CAAC;IAEL,IAAI,CAACJ,mBAAmB,CAACM,QAAQ,CAAC;EACpC;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;EACES,aAAaA,CACXZ,YAA+B,EAC/BC,QAAgB,EACgB;IAChC,IAAI,CAACD,YAAY,EAAE,OAAOa,SAAS;IAEnC,OAAO;MACLT,KAAK,EAAE,IAAI,CAACF,QAAQ,EAAEE,KAAK,IAAIJ,YAAY,CAACI,KAAK;MACjDC,MAAM,EAAE,IAAI,CAACH,QAAQ,EAAEG,MAAM,IAAIL,YAAY,CAACK,MAAM;MACpDC,KAAK,EAAE,IAAI,CAACJ,QAAQ,EAAEI,KAAK,IAAIN,YAAY,CAACM,KAAK;MACjDC,OAAO,EAAEb,UAAU,CAACM,YAAY,CAACO,OAAO,CAAC;MACzCC,WAAW,EAAER,YAAY,CAACQ,WAAW;MACrCC,OAAO,EAAEd,gBAAgB,CAACK,YAAY,CAAC,IAAIA,YAAY,CAACU,IAAI;MAC5DC,KAAK,EAAEX,YAAY,CAACW,KAAK;MACzBV;IACF,CAAC;EACH;;EAEA;AACF;AACA;AACA;EACEa,uBAAuBA,CAAA,EAAS;IAC9B,IAAI,CAACZ,QAAQ,GAAGW,SAAS;EAC3B;AACF","ignoreList":[]}
@@ -8,8 +8,12 @@
8
8
  * 1. System paths (prefixed with `/__`): Root, recent, and search paths
9
9
  * 2. Contextual URLs: Embed parent context in track identifiers for Media3 integration
10
10
  *
11
- * Contextual URL format: `{parentPath}?__trackId={trackSrc}`
12
- * Example: "/library/radio?__trackId=song.mp3"
11
+ * Contextual URL format: `{parentPath}?__trackId={trackIdentity}&__index={childIndex}`
12
+ * Example: "/library/radio?__trackId=song.mp3&__index=2"
13
+ *
14
+ * `__trackId` is the identity check; `__index` (the child's position on the
15
+ * page at stamp time) is only a tie-breaker between surfaces that carry the
16
+ * same identity — a stale index never selects a different track.
13
17
  *
14
18
  * This allows:
15
19
  * - Media3 to reference playable-only tracks (tracks with `src` but no `url`)
@@ -21,6 +25,14 @@ export const BrowserPathHelper = {
21
25
  SEARCH_PATH_PREFIX: '/__search',
22
26
  /** Query parameter name for contextual track identifiers */
23
27
  CONTEXTUAL_TRACK_PARAM: '__trackId',
28
+ /** Query parameter name for the tapped child's page position (tie-breaker) */
29
+ CONTEXTUAL_INDEX_PARAM: '__index',
30
+ /**
31
+ * Whether a navigation error on this path came from a browse or a search
32
+ */
33
+ navigationErrorKind(path) {
34
+ return path.startsWith(`${this.SEARCH_PATH_PREFIX}?`) ? 'search' : 'browse';
35
+ },
24
36
  /**
25
37
  * Create a search path for a given query
26
38
  */
@@ -38,13 +50,13 @@ export const BrowserPathHelper = {
38
50
  return path.includes(`?${this.CONTEXTUAL_TRACK_PARAM}=`) || path.includes(`&${this.CONTEXTUAL_TRACK_PARAM}=`);
39
51
  },
40
52
  /**
41
- * Strips the __trackId parameter from a contextual URL to get the parent path.
42
- * If the URL is not contextual, returns it unchanged.
53
+ * Strips the contextual parameters (__trackId and __index) from a contextual
54
+ * URL to get the parent path. If the URL is not contextual, returns it unchanged.
43
55
  *
44
56
  * @param url The URL to process
45
- * @returns The URL without the __trackId parameter
57
+ * @returns The URL without the contextual parameters
46
58
  *
47
- * Example: "/library/radio?__trackId=song.mp3" → "/library/radio"
59
+ * Example: "/library/radio?__trackId=song.mp3&__index=2" → "/library/radio"
48
60
  * Example: "/search?q=jazz&__trackId=song.mp3" → "/search?q=jazz"
49
61
  */
50
62
  stripTrackId(url) {
@@ -56,8 +68,9 @@ export const BrowserPathHelper = {
56
68
  const isFullUrl = url.startsWith('http://') || url.startsWith('https://');
57
69
  const urlObj = new URL(url, isFullUrl ? undefined : 'http://placeholder');
58
70
 
59
- // Remove the __trackId parameter
71
+ // Remove the contextual parameters
60
72
  urlObj.searchParams.delete(this.CONTEXTUAL_TRACK_PARAM);
73
+ urlObj.searchParams.delete(this.CONTEXTUAL_INDEX_PARAM);
61
74
 
62
75
  // Return the appropriate format
63
76
  if (isFullUrl) {
@@ -68,7 +81,7 @@ export const BrowserPathHelper = {
68
81
  }
69
82
  } catch {
70
83
  // Fallback: simple string manipulation
71
- const paramPattern = new RegExp(`[?&]${this.CONTEXTUAL_TRACK_PARAM}=[^&]*`, 'g');
84
+ const paramPattern = new RegExp(`[?&](?:${this.CONTEXTUAL_TRACK_PARAM}|${this.CONTEXTUAL_INDEX_PARAM})=[^&]*`, 'g');
72
85
  let result = url.replace(paramPattern, '');
73
86
  // Clean up any trailing ? or &
74
87
  result = result.replace(/[?&]$/, '');
@@ -77,6 +90,22 @@ export const BrowserPathHelper = {
77
90
  return result;
78
91
  }
79
92
  },
93
+ /**
94
+ * Builds a contextual URL by appending a track identifier — and optionally
95
+ * the tapped child's page position — to a parent path.
96
+ *
97
+ * @param parentPath The parent container path
98
+ * @param trackId The track identity (`id` when non-blank, else `src`)
99
+ * @param index The child's position on the page at stamp time (tie-breaker)
100
+ * @returns A contextual URL combining parent path, track ID, and index
101
+ *
102
+ * Example: build("/library", "song.mp3", 2) → "/library?__trackId=song.mp3&__index=2"
103
+ */
104
+ build(parentPath, trackId, index) {
105
+ const separator = parentPath.includes('?') ? '&' : '?';
106
+ const indexParam = index === undefined ? '' : `&${this.CONTEXTUAL_INDEX_PARAM}=${index}`;
107
+ return `${parentPath}${separator}${this.CONTEXTUAL_TRACK_PARAM}=${encodeURIComponent(trackId)}${indexParam}`;
108
+ },
80
109
  /**
81
110
  * Extracts the track ID from a contextual URL.
82
111
  * Returns undefined if the URL is not contextual or doesn't contain the track ID parameter.
@@ -90,14 +119,36 @@ export const BrowserPathHelper = {
90
119
  if (!this.isContextual(path)) {
91
120
  return undefined;
92
121
  }
122
+ return this.extractParam(path, this.CONTEXTUAL_TRACK_PARAM);
123
+ },
124
+ /**
125
+ * Extracts the stamped page index from a contextual URL, or undefined when
126
+ * the URL is not contextual or carries no (valid, non-negative) index.
127
+ *
128
+ * Example: "/library/radio?__trackId=song.mp3&__index=2" → 2
129
+ */
130
+ extractIndex(path) {
131
+ if (!this.isContextual(path)) {
132
+ return undefined;
133
+ }
134
+ const raw = this.extractParam(path, this.CONTEXTUAL_INDEX_PARAM);
135
+ if (raw === undefined || !/^\d+$/.test(raw)) {
136
+ return undefined;
137
+ }
138
+ return Number.parseInt(raw, 10);
139
+ },
140
+ /**
141
+ * Extracts a single query parameter, handling both full URLs and paths,
142
+ * with a regex fallback for input the URL parser rejects.
143
+ */
144
+ extractParam(path, param) {
93
145
  try {
94
- // Parse the URL - handle both full URLs and paths
95
146
  const isFullUrl = path.startsWith('http://') || path.startsWith('https://');
96
147
  const urlObj = new URL(path, isFullUrl ? undefined : 'http://placeholder');
97
- return urlObj.searchParams.get(this.CONTEXTUAL_TRACK_PARAM) ?? undefined;
148
+ return urlObj.searchParams.get(param) ?? undefined;
98
149
  } catch {
99
150
  // Fallback: regex extraction
100
- const match = path.match(new RegExp(`[?&]${this.CONTEXTUAL_TRACK_PARAM}=([^&]*)`));
151
+ const match = path.match(new RegExp(`[?&]${param}=([^&]*)`));
101
152
  return match?.[1] ? decodeURIComponent(match[1]) : undefined;
102
153
  }
103
154
  },