react-native-audio-browser 0.1.1 → 0.2.0-next.1

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 (901) hide show
  1. package/AudioBrowser.podspec +1 -1
  2. package/README.md +180 -2
  3. package/android/build.gradle +10 -0
  4. package/android/gradle.properties +1 -1
  5. package/android/src/main/AndroidManifest.xml +15 -0
  6. package/android/src/main/java/com/audiobrowser/AudioBrowser.kt +401 -141
  7. package/android/src/main/java/com/audiobrowser/Callbacks.kt +4 -6
  8. package/android/src/main/java/com/audiobrowser/Service.kt +67 -18
  9. package/android/src/main/java/com/audiobrowser/browser/ArtworkResolutionRegistry.kt +37 -0
  10. package/android/src/main/java/com/audiobrowser/browser/BrowseArtworkRegistry.kt +34 -0
  11. package/android/src/main/java/com/audiobrowser/browser/BrowserManager.kt +443 -178
  12. package/android/src/main/java/com/audiobrowser/browser/BrowserUrlResolution.kt +300 -0
  13. package/android/src/main/java/com/audiobrowser/browser/JsonArtwork.kt +79 -0
  14. package/android/src/main/java/com/audiobrowser/browser/JsonModels.kt +41 -4
  15. package/android/src/main/java/com/audiobrowser/browser/SectionScope.kt +43 -0
  16. package/android/src/main/java/com/audiobrowser/browser/TrackLoadHandler.kt +4 -4
  17. package/android/src/main/java/com/audiobrowser/extension/ResolvedTrackExt.kt +35 -0
  18. package/android/src/main/java/com/audiobrowser/http/RequestConfigBuilder.kt +109 -97
  19. package/android/src/main/java/com/audiobrowser/model/PlaybackMetadata.kt +6 -10
  20. package/android/src/main/java/com/audiobrowser/model/PlayerSetupOptions.kt +40 -8
  21. package/android/src/main/java/com/audiobrowser/model/PlayerUpdateOptions.kt +31 -37
  22. package/android/src/main/java/com/audiobrowser/player/AutomaticBufferManager.kt +4 -1
  23. package/android/src/main/java/com/audiobrowser/player/CapabilityControls.kt +119 -0
  24. package/android/src/main/java/com/audiobrowser/player/DynamicLoadControl.kt +18 -1
  25. package/android/src/main/java/com/audiobrowser/player/EqualizerController.kt +153 -0
  26. package/android/src/main/java/com/audiobrowser/player/InterceptingPlayer.kt +141 -0
  27. package/android/src/main/java/com/audiobrowser/player/MediaFactory.kt +15 -3
  28. package/android/src/main/java/com/audiobrowser/player/MediaSessionCallback.kt +415 -131
  29. package/android/src/main/java/com/audiobrowser/player/MediaSessionCommandManager.kt +154 -276
  30. package/android/src/main/java/com/audiobrowser/player/NowPlayingUpdater.kt +348 -0
  31. package/android/src/main/java/com/audiobrowser/player/PlaybackErrorClassifier.kt +129 -0
  32. package/android/src/main/java/com/audiobrowser/player/PlaybackStateMachine.kt +85 -0
  33. package/android/src/main/java/com/audiobrowser/player/PlaybackStateStore.kt +27 -5
  34. package/android/src/main/java/com/audiobrowser/player/PlaybackTimer.kt +56 -0
  35. package/android/src/main/java/com/audiobrowser/player/Player.kt +452 -576
  36. package/android/src/main/java/com/audiobrowser/player/PlayerCapabilitiesExt.kt +20 -0
  37. package/android/src/main/java/com/audiobrowser/player/PlayerEngineFactory.kt +130 -0
  38. package/android/src/main/java/com/audiobrowser/player/PlayerListener.kt +190 -67
  39. package/android/src/main/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicy.kt +117 -53
  40. package/android/src/main/java/com/audiobrowser/player/SleepTimer.kt +37 -3
  41. package/android/src/main/java/com/audiobrowser/player/SleepTimerManager.kt +80 -0
  42. package/android/src/main/java/com/audiobrowser/player/StuckRecoveryPolicy.kt +50 -0
  43. package/android/src/main/java/com/audiobrowser/player/TransformingDataSource.kt +84 -40
  44. package/android/src/main/java/com/audiobrowser/player/VolumeFader.kt +81 -0
  45. package/android/src/main/java/com/audiobrowser/tls/AiaCertChaser.kt +141 -0
  46. package/android/src/main/java/com/audiobrowser/tls/AiaChasingTrustManager.kt +37 -0
  47. package/android/src/main/java/com/audiobrowser/tls/AiaTls.kt +41 -0
  48. package/android/src/main/java/com/audiobrowser/tls/CachingCertificateFetcher.kt +209 -0
  49. package/android/src/main/java/com/audiobrowser/util/ArtworkContentProvider.kt +161 -0
  50. package/android/src/main/java/com/audiobrowser/util/ArtworkUris.kt +28 -0
  51. package/android/src/main/java/com/audiobrowser/util/ArtworkVariant.kt +26 -0
  52. package/android/src/main/java/com/audiobrowser/util/BrowserPathHelper.kt +24 -0
  53. package/android/src/main/java/com/audiobrowser/util/CoilArtworkLoader.kt +49 -0
  54. package/android/src/main/java/com/audiobrowser/util/CoilArtworkLoaderHolder.kt +36 -0
  55. package/android/src/main/java/com/audiobrowser/util/CoilBitmapLoader.kt +23 -300
  56. package/android/src/main/java/com/audiobrowser/util/EqualizerManager.kt +13 -23
  57. package/android/src/main/java/com/audiobrowser/util/MediaExtrasBuilder.kt +2 -2
  58. package/android/src/main/java/com/audiobrowser/util/MetadataAdapter.kt +4 -3
  59. package/android/src/main/java/com/audiobrowser/util/OutputMonitor.kt +211 -0
  60. package/android/src/main/java/com/audiobrowser/util/OutputSwitcher.kt +58 -0
  61. package/android/src/main/java/com/audiobrowser/util/PlayingStateFactory.kt +2 -1
  62. package/android/src/main/java/com/audiobrowser/util/RatingFavorites.kt +14 -0
  63. package/android/src/main/java/com/audiobrowser/util/SvgArtworkRenderer.kt +6 -111
  64. package/android/src/main/java/com/audiobrowser/util/SystemVolumeMonitor.kt +22 -8
  65. package/android/src/main/java/com/audiobrowser/util/TrackFactory.kt +111 -80
  66. package/android/src/main/res/values/strings.xml +4 -0
  67. package/android/src/test/java/com/audiobrowser/TestFixtures.kt +166 -0
  68. package/android/src/test/java/com/audiobrowser/browser/ArtworkResolutionRegistryTest.kt +46 -0
  69. package/android/src/test/java/com/audiobrowser/browser/BrowseArtworkRegistryTest.kt +39 -0
  70. package/android/src/test/java/com/audiobrowser/browser/BrowserManagerBuildApiRequestTest.kt +114 -0
  71. package/android/src/test/java/com/audiobrowser/browser/BrowserManagerLayerResolutionTest.kt +141 -0
  72. package/android/src/test/java/com/audiobrowser/browser/BrowserManagerTest.kt +4 -0
  73. package/android/src/test/java/com/audiobrowser/browser/BrowserUrlResolutionTest.kt +177 -0
  74. package/android/src/test/java/com/audiobrowser/browser/JsonArtworkTest.kt +54 -0
  75. package/android/src/test/java/com/audiobrowser/browser/SectionScopeTest.kt +96 -0
  76. package/android/src/test/java/com/audiobrowser/browser/SimpleRouterTest.kt +1 -2
  77. package/android/src/test/java/com/audiobrowser/http/RequestConfigBuilderTest.kt +72 -0
  78. package/android/src/test/java/com/audiobrowser/player/CapabilityControlsTest.kt +159 -0
  79. package/android/src/test/java/com/audiobrowser/player/DynamicLoadControlTest.kt +56 -0
  80. package/android/src/test/java/com/audiobrowser/player/EqualizerControllerTest.kt +216 -0
  81. package/android/src/test/java/com/audiobrowser/player/NowPlayingUpdaterTest.kt +442 -0
  82. package/android/src/test/java/com/audiobrowser/player/PlaybackErrorClassifierTest.kt +191 -0
  83. package/android/src/test/java/com/audiobrowser/player/PlaybackStateMachineTest.kt +198 -0
  84. package/android/src/test/java/com/audiobrowser/player/PlaybackTimerTest.kt +137 -0
  85. package/android/src/test/java/com/audiobrowser/player/PlayerEngineFactoryTest.kt +36 -0
  86. package/android/src/test/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicyTest.kt +268 -0
  87. package/android/src/test/java/com/audiobrowser/player/SessionErrorMaskTest.kt +68 -0
  88. package/android/src/test/java/com/audiobrowser/player/StuckRecoveryPolicyTest.kt +40 -0
  89. package/android/src/test/java/com/audiobrowser/player/TransformingDataSourceTest.kt +193 -0
  90. package/android/src/test/java/com/audiobrowser/tls/AiaCertChaserTest.kt +107 -0
  91. package/android/src/test/java/com/audiobrowser/tls/AiaChasingTrustManagerTest.kt +73 -0
  92. package/android/src/test/java/com/audiobrowser/tls/CachingCertificateFetcherTest.kt +75 -0
  93. package/android/src/test/java/com/audiobrowser/tls/CertFixtures.kt +18 -0
  94. package/android/src/test/java/com/audiobrowser/util/ArtworkContentProviderTest.kt +163 -0
  95. package/android/src/test/java/com/audiobrowser/util/ArtworkUrisTest.kt +34 -0
  96. package/android/src/test/java/com/audiobrowser/util/BrowserPathHelperTest.kt +28 -0
  97. package/android/src/test/java/com/audiobrowser/util/CoilArtworkLoaderHolderTest.kt +53 -0
  98. package/android/src/test/java/com/audiobrowser/util/CoilArtworkLoaderTest.kt +58 -0
  99. package/android/src/test/java/com/audiobrowser/util/FakeImageLoader.kt +57 -0
  100. package/android/src/test/java/com/audiobrowser/util/PlayingStateFactoryTest.kt +40 -0
  101. package/android/src/test/java/com/audiobrowser/util/RatingFavoritesTest.kt +34 -0
  102. package/android/src/test/java/com/audiobrowser/util/TrackFactoryBrowseTest.kt +50 -0
  103. package/android/src/test/java/com/audiobrowser/util/TrackFactoryMediaIdTest.kt +63 -0
  104. package/android/src/test/java/com/audiobrowser/util/TrackFactoryRatingTest.kt +35 -0
  105. package/android/src/test/resources/certs/isrg-root-x1.pem +31 -0
  106. package/android/src/test/resources/certs/letsencrypt-r13.der +0 -0
  107. package/android/src/test/resources/certs/letsencrypt-r13.pem +29 -0
  108. package/android/src/test/resources/certs/stationplaylist-leaf.pem +34 -0
  109. package/ios/Browser/BrowserConfig.swift +41 -11
  110. package/ios/Browser/BrowserManager+URLResolution.swift +213 -93
  111. package/ios/Browser/BrowserManager.swift +303 -110
  112. package/ios/Browser/BrowserPathHelper.swift +32 -3
  113. package/ios/Browser/JsonModels.swift +287 -66
  114. package/ios/Browser/MediaResolveComposer.swift +114 -0
  115. package/ios/Browser/SearchDrillIn.swift +44 -0
  116. package/ios/Browser/SectionScope.swift +35 -0
  117. package/ios/Browser/TabBarEntries.swift +15 -0
  118. package/ios/CarPlay/CPInterfaceController+Safe.swift +126 -0
  119. package/ios/CarPlay/CarPlayArtworkResolver.swift +6 -6
  120. package/ios/CarPlay/CarPlayController.swift +739 -149
  121. package/ios/CarPlay/CarPlayImageLoader.swift +57 -8
  122. package/ios/CarPlay/CarPlayListItemFactory.swift +44 -35
  123. package/ios/CarPlay/CarPlayNowPlayingManager.swift +180 -36
  124. package/ios/CarPlay/ImageRowItem+CarPlay.swift +19 -0
  125. package/ios/CarPlay/RNABAudioBrowser.h +15 -10
  126. package/ios/CarPlay/RNABAudioBrowser.m +15 -14
  127. package/ios/CarPlay/RNABCarPlaySceneDelegate.m +2 -0
  128. package/ios/CarPlay/RNABMediaAddHandler.swift +75 -0
  129. package/ios/CarPlay/RNABMediaAffinityHandler.swift +69 -0
  130. package/ios/CarPlay/RNABMediaIntentHandler.swift +53 -43
  131. package/ios/Extension/Capability+RemoteCommand.swift +7 -9
  132. package/ios/Extension/ChapterMetadata+AVFoundation.swift +1 -1
  133. package/ios/Extension/NavigationError+Conversion.swift +8 -1
  134. package/ios/Extension/PlayerCapabilities+Favorite.swift +20 -0
  135. package/ios/Extension/RequestConfig+Copying.swift +31 -0
  136. package/ios/Extension/ResolvedTrack+Copying.swift +10 -4
  137. package/ios/Extension/TimedMetadata+AVFoundation.swift +1 -1
  138. package/ios/Extension/Track+AVPlayer.swift +4 -4
  139. package/ios/Extension/Track+Copying.swift +9 -3
  140. package/ios/Extension/TrackMetadata+AVFoundation.swift +1 -1
  141. package/ios/Extension/Variant+Artwork.swift +49 -0
  142. package/ios/HybridAudioBrowser.swift +750 -173
  143. package/ios/Model/NitroTypeStubs.swift +299 -224
  144. package/ios/Model/PlayerUpdateOptions.swift +23 -23
  145. package/ios/Model/RemoteCommand.swift +6 -6
  146. package/ios/Model/TrackPlayerError.swift +82 -18
  147. package/ios/NowPlayingInfo/NowPlayingInfoController.swift +99 -121
  148. package/ios/NowPlayingInfo/SilentAudioPrimer.swift +73 -0
  149. package/ios/Observer/PlayerItemNotificationObserver.swift +45 -5
  150. package/ios/Observer/PlayerItemPropertyObserver.swift +27 -4
  151. package/ios/Observer/PlayerTimeObserver.swift +3 -53
  152. package/ios/Option/SessionCategories.swift +33 -11
  153. package/ios/Player/AirPlayStallJudgement.swift +25 -0
  154. package/ios/Player/EndOfTrackJudgement.swift +32 -0
  155. package/ios/Player/LoadSeekCoordinator.swift +16 -1
  156. package/ios/Player/MediaIntentCriteria.swift +139 -0
  157. package/ios/Player/MediaLoader.swift +28 -10
  158. package/ios/Player/NowPlayingUpdater.swift +119 -26
  159. package/ios/Player/PersistedPlaybackState.swift +11 -0
  160. package/ios/Player/PlaybackCoordinator.swift +282 -51
  161. package/ios/Player/PlaybackCoordinatorCallbacks.swift +6 -1
  162. package/ios/Player/PlaybackEffectHandler.swift +19 -9
  163. package/ios/Player/PlaybackErrorHandler.swift +97 -13
  164. package/ios/Player/PlaybackStateMachine.swift +18 -13
  165. package/ios/Player/PlaybackStateStore.swift +27 -0
  166. package/ios/Player/PlaybackTimer.swift +61 -0
  167. package/ios/Player/PlayingStateManager.swift +3 -2
  168. package/ios/Player/QueueManager.swift +67 -61
  169. package/ios/Player/RetryManager.swift +97 -21
  170. package/ios/Player/SleepTimerHandling.swift +8 -0
  171. package/ios/Player/SleepTimerManager.swift +38 -5
  172. package/ios/Player/VolumeFader.swift +77 -0
  173. package/ios/RemoteCommand/RemoteCommandController.swift +31 -15
  174. package/ios/Tests/AirPlayStallJudgementTests.swift +52 -0
  175. package/ios/Tests/BrowserPathHelperTests.swift +28 -0
  176. package/ios/Tests/CarPlayArtworkResolverTests.swift +39 -39
  177. package/ios/Tests/ChapterMetadataAVFoundationTests.swift +2 -2
  178. package/ios/Tests/EndOfTrackJudgementTests.swift +35 -0
  179. package/ios/Tests/JsonModelsTests.swift +58 -0
  180. package/ios/Tests/LoadSeekCoordinatorTests.swift +38 -7
  181. package/ios/Tests/MediaIntentCriteriaTests.swift +170 -0
  182. package/ios/Tests/MediaLoaderAssetOptionsTests.swift +46 -0
  183. package/ios/Tests/MediaLoaderTests.swift +23 -8
  184. package/ios/Tests/MediaResolveTests.swift +126 -0
  185. package/ios/Tests/OnceValueTests.swift +79 -0
  186. package/ios/Tests/PlaybackCoordinatorTests.swift +784 -13
  187. package/ios/Tests/PlaybackErrorHandlerTests.swift +380 -46
  188. package/ios/Tests/PlaybackStateMachineTests.swift +33 -8
  189. package/ios/Tests/PlaybackStateStoreTests.swift +48 -0
  190. package/ios/Tests/PlaybackTimerTests.swift +55 -0
  191. package/ios/Tests/PlayingStateManagerTests.swift +57 -0
  192. package/ios/Tests/QueueManagerTests.swift +149 -18
  193. package/ios/Tests/ResolvedTrackCopyingTests.swift +15 -8
  194. package/ios/Tests/RetryManagerTests.swift +89 -0
  195. package/ios/Tests/SearchDrillInTests.swift +63 -0
  196. package/ios/Tests/SectionScopeTests.swift +82 -0
  197. package/ios/Tests/SleepTimerManagerTests.swift +104 -0
  198. package/ios/Tests/Support/TestTypes.swift +61 -20
  199. package/ios/Tests/TabBarEntriesTests.swift +71 -0
  200. package/ios/Tests/TrackSelectorTests.swift +15 -15
  201. package/ios/TrackPlayer.swift +380 -58
  202. package/ios/TrackPlayerCallbacks.swift +0 -6
  203. package/ios/TrackSelector.swift +5 -5
  204. package/ios/Util/ArtworkImageFetcher.swift +4 -2
  205. package/ios/Util/NetworkMonitor.swift +7 -3
  206. package/ios/Util/OnceValue.swift +34 -0
  207. package/lib/commonjs/features/browser-config.js +227 -0
  208. package/lib/commonjs/features/browser-config.js.map +1 -0
  209. package/lib/commonjs/features/browser.js +59 -158
  210. package/lib/commonjs/features/browser.js.map +1 -1
  211. package/lib/commonjs/features/carConnection.js +42 -0
  212. package/lib/commonjs/features/carConnection.js.map +1 -0
  213. package/lib/commonjs/features/errors.js +34 -2
  214. package/lib/commonjs/features/errors.js.map +1 -1
  215. package/lib/commonjs/features/gate.js +149 -0
  216. package/lib/commonjs/features/gate.js.map +1 -0
  217. package/lib/commonjs/features/index.js +22 -0
  218. package/lib/commonjs/features/index.js.map +1 -1
  219. package/lib/commonjs/features/metadata.js.map +1 -1
  220. package/lib/commonjs/features/nowPlaying.js +35 -0
  221. package/lib/commonjs/features/nowPlaying.js.map +1 -1
  222. package/lib/commonjs/features/output.js +37 -23
  223. package/lib/commonjs/features/output.js.map +1 -1
  224. package/lib/commonjs/features/playback/controls.js +9 -0
  225. package/lib/commonjs/features/playback/controls.js.map +1 -1
  226. package/lib/commonjs/features/playback/index.js +11 -0
  227. package/lib/commonjs/features/playback/index.js.map +1 -1
  228. package/lib/commonjs/features/playback/progress.js +28 -12
  229. package/lib/commonjs/features/playback/progress.js.map +1 -1
  230. package/lib/commonjs/features/playback/trackPlaybackTime.js +92 -0
  231. package/lib/commonjs/features/playback/trackPlaybackTime.js.map +1 -0
  232. package/lib/commonjs/features/playback/volume.js +1 -1
  233. package/lib/commonjs/features/player/options.js +49 -13
  234. package/lib/commonjs/features/player/options.js.map +1 -1
  235. package/lib/commonjs/features/player/setup.js +249 -3
  236. package/lib/commonjs/features/player/setup.js.map +1 -1
  237. package/lib/commonjs/features/queue/queue.js +10 -3
  238. package/lib/commonjs/features/queue/queue.js.map +1 -1
  239. package/lib/commonjs/features/remoteControls.js +1 -12
  240. package/lib/commonjs/features/remoteControls.js.map +1 -1
  241. package/lib/commonjs/features/sleepTimer.js +9 -4
  242. package/lib/commonjs/features/sleepTimer.js.map +1 -1
  243. package/lib/commonjs/native.js +5 -0
  244. package/lib/commonjs/native.js.map +1 -1
  245. package/lib/commonjs/native.web.js +4 -1
  246. package/lib/commonjs/native.web.js.map +1 -1
  247. package/lib/commonjs/utils/LazyNativeEmitter.js +0 -3
  248. package/lib/commonjs/utils/LazyNativeEmitter.js.map +1 -1
  249. package/lib/commonjs/utils/NativeUpdatedValue.js +0 -3
  250. package/lib/commonjs/utils/NativeUpdatedValue.js.map +1 -1
  251. package/lib/commonjs/utils/artwork.js +31 -0
  252. package/lib/commonjs/utils/artwork.js.map +1 -0
  253. package/lib/commonjs/web/NativeAudioBrowser.js +301 -124
  254. package/lib/commonjs/web/NativeAudioBrowser.js.map +1 -1
  255. package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js +71 -0
  256. package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js.map +1 -0
  257. package/lib/commonjs/web/TrackPlayer/PlaybackTimer.js +34 -0
  258. package/lib/commonjs/web/TrackPlayer/PlaybackTimer.js.map +1 -0
  259. package/lib/commonjs/web/TrackPlayer/Player.js +90 -26
  260. package/lib/commonjs/web/TrackPlayer/Player.js.map +1 -1
  261. package/lib/commonjs/web/TrackPlayer/PlayingStateFactory.js +21 -0
  262. package/lib/commonjs/web/TrackPlayer/PlayingStateFactory.js.map +1 -0
  263. package/lib/commonjs/web/TrackPlayer/QueueManager.js +273 -0
  264. package/lib/commonjs/web/TrackPlayer/QueueManager.js.map +1 -0
  265. package/lib/commonjs/web/TrackPlayer/QueuePlayer.js +158 -0
  266. package/lib/commonjs/web/TrackPlayer/QueuePlayer.js.map +1 -0
  267. package/lib/commonjs/web/TrackPlayer/RepeatMode.js +1 -1
  268. package/lib/commonjs/web/TrackPlayer/RepeatMode.js.map +1 -1
  269. package/lib/commonjs/web/TrackPlayer/SleepTimer.js +34 -3
  270. package/lib/commonjs/web/TrackPlayer/SleepTimer.js.map +1 -1
  271. package/lib/commonjs/web/TrackPlayer/VolumeFader.js +75 -0
  272. package/lib/commonjs/web/TrackPlayer/VolumeFader.js.map +1 -0
  273. package/lib/commonjs/web/TrackPlayer/index.js +13 -5
  274. package/lib/commonjs/web/TrackPlayer/index.js.map +1 -1
  275. package/lib/commonjs/web/browser/BrowserManager.js +176 -50
  276. package/lib/commonjs/web/browser/BrowserManager.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 +11 -9
  280. package/lib/commonjs/web/browser/SearchManager.js.map +1 -1
  281. package/lib/commonjs/web/browser/assertBrowsePageShape.js +22 -0
  282. package/lib/commonjs/web/browser/assertBrowsePageShape.js.map +1 -0
  283. package/lib/commonjs/web/browser/classifyTrackNavigation.js +41 -0
  284. package/lib/commonjs/web/browser/classifyTrackNavigation.js.map +1 -0
  285. package/lib/commonjs/web/browser/parseSearchResponse.js +20 -0
  286. package/lib/commonjs/web/browser/parseSearchResponse.js.map +1 -0
  287. package/lib/commonjs/web/http/HttpClient.js +4 -23
  288. package/lib/commonjs/web/http/HttpClient.js.map +1 -1
  289. package/lib/commonjs/web/http/RequestConfigBuilder.js +107 -58
  290. package/lib/commonjs/web/http/RequestConfigBuilder.js.map +1 -1
  291. package/lib/commonjs/web/playbackErrorKind.js +57 -0
  292. package/lib/commonjs/web/playbackErrorKind.js.map +1 -0
  293. package/lib/commonjs/web/player/MediaSessionManager.js +121 -0
  294. package/lib/commonjs/web/player/MediaSessionManager.js.map +1 -0
  295. package/lib/commonjs/web/player/NowPlayingManager.js +6 -5
  296. package/lib/commonjs/web/player/NowPlayingManager.js.map +1 -1
  297. package/lib/commonjs/web/player/OptionsManager.js +9 -17
  298. package/lib/commonjs/web/player/OptionsManager.js.map +1 -1
  299. package/lib/commonjs/web/player/RemoteCommandController.js +96 -0
  300. package/lib/commonjs/web/player/RemoteCommandController.js.map +1 -0
  301. package/lib/module/features/browser-config.js +221 -0
  302. package/lib/module/features/browser-config.js.map +1 -0
  303. package/lib/module/features/browser.js +53 -156
  304. package/lib/module/features/browser.js.map +1 -1
  305. package/lib/module/features/carConnection.js +37 -0
  306. package/lib/module/features/carConnection.js.map +1 -0
  307. package/lib/module/features/errors.js +34 -2
  308. package/lib/module/features/errors.js.map +1 -1
  309. package/lib/module/features/gate.js +144 -0
  310. package/lib/module/features/gate.js.map +1 -0
  311. package/lib/module/features/index.js +2 -0
  312. package/lib/module/features/index.js.map +1 -1
  313. package/lib/module/features/metadata.js.map +1 -1
  314. package/lib/module/features/nowPlaying.js +33 -0
  315. package/lib/module/features/nowPlaying.js.map +1 -1
  316. package/lib/module/features/output.js +32 -19
  317. package/lib/module/features/output.js.map +1 -1
  318. package/lib/module/features/playback/controls.js +8 -0
  319. package/lib/module/features/playback/controls.js.map +1 -1
  320. package/lib/module/features/playback/index.js +1 -0
  321. package/lib/module/features/playback/index.js.map +1 -1
  322. package/lib/module/features/playback/progress.js +28 -12
  323. package/lib/module/features/playback/progress.js.map +1 -1
  324. package/lib/module/features/playback/trackPlaybackTime.js +88 -0
  325. package/lib/module/features/playback/trackPlaybackTime.js.map +1 -0
  326. package/lib/module/features/playback/volume.js +1 -1
  327. package/lib/module/features/player/options.js +48 -13
  328. package/lib/module/features/player/options.js.map +1 -1
  329. package/lib/module/features/player/setup.js +249 -3
  330. package/lib/module/features/player/setup.js.map +1 -1
  331. package/lib/module/features/queue/queue.js +10 -3
  332. package/lib/module/features/queue/queue.js.map +1 -1
  333. package/lib/module/features/remoteControls.js +0 -11
  334. package/lib/module/features/remoteControls.js.map +1 -1
  335. package/lib/module/features/sleepTimer.js +9 -4
  336. package/lib/module/features/sleepTimer.js.map +1 -1
  337. package/lib/module/native.js +5 -0
  338. package/lib/module/native.js.map +1 -1
  339. package/lib/module/native.web.js +4 -1
  340. package/lib/module/native.web.js.map +1 -1
  341. package/lib/module/utils/LazyNativeEmitter.js +0 -3
  342. package/lib/module/utils/LazyNativeEmitter.js.map +1 -1
  343. package/lib/module/utils/NativeUpdatedValue.js +0 -3
  344. package/lib/module/utils/NativeUpdatedValue.js.map +1 -1
  345. package/lib/module/utils/artwork.js +26 -0
  346. package/lib/module/utils/artwork.js.map +1 -0
  347. package/lib/module/web/NativeAudioBrowser.js +302 -125
  348. package/lib/module/web/NativeAudioBrowser.js.map +1 -1
  349. package/lib/module/web/TrackPlayer/PlaybackStateMachine.js +67 -0
  350. package/lib/module/web/TrackPlayer/PlaybackStateMachine.js.map +1 -0
  351. package/lib/module/web/TrackPlayer/PlaybackTimer.js +29 -0
  352. package/lib/module/web/TrackPlayer/PlaybackTimer.js.map +1 -0
  353. package/lib/module/web/TrackPlayer/Player.js +90 -26
  354. package/lib/module/web/TrackPlayer/Player.js.map +1 -1
  355. package/lib/module/web/TrackPlayer/PlayingStateFactory.js +17 -0
  356. package/lib/module/web/TrackPlayer/PlayingStateFactory.js.map +1 -0
  357. package/lib/module/web/TrackPlayer/QueueManager.js +269 -0
  358. package/lib/module/web/TrackPlayer/QueueManager.js.map +1 -0
  359. package/lib/module/web/TrackPlayer/QueuePlayer.js +154 -0
  360. package/lib/module/web/TrackPlayer/QueuePlayer.js.map +1 -0
  361. package/lib/module/web/TrackPlayer/RepeatMode.js +1 -1
  362. package/lib/module/web/TrackPlayer/RepeatMode.js.map +1 -1
  363. package/lib/module/web/TrackPlayer/SleepTimer.js +34 -3
  364. package/lib/module/web/TrackPlayer/SleepTimer.js.map +1 -1
  365. package/lib/module/web/TrackPlayer/VolumeFader.js +70 -0
  366. package/lib/module/web/TrackPlayer/VolumeFader.js.map +1 -0
  367. package/lib/module/web/TrackPlayer/index.js +2 -1
  368. package/lib/module/web/TrackPlayer/index.js.map +1 -1
  369. package/lib/module/web/browser/BrowserManager.js +176 -50
  370. package/lib/module/web/browser/BrowserManager.js.map +1 -1
  371. package/lib/module/web/browser/NavigationErrorManager.js +3 -1
  372. package/lib/module/web/browser/NavigationErrorManager.js.map +1 -1
  373. package/lib/module/web/browser/SearchManager.js +11 -9
  374. package/lib/module/web/browser/SearchManager.js.map +1 -1
  375. package/lib/module/web/browser/assertBrowsePageShape.js +18 -0
  376. package/lib/module/web/browser/assertBrowsePageShape.js.map +1 -0
  377. package/lib/module/web/browser/classifyTrackNavigation.js +38 -0
  378. package/lib/module/web/browser/classifyTrackNavigation.js.map +1 -0
  379. package/lib/module/web/browser/parseSearchResponse.js +16 -0
  380. package/lib/module/web/browser/parseSearchResponse.js.map +1 -0
  381. package/lib/module/web/http/HttpClient.js +4 -23
  382. package/lib/module/web/http/HttpClient.js.map +1 -1
  383. package/lib/module/web/http/RequestConfigBuilder.js +107 -58
  384. package/lib/module/web/http/RequestConfigBuilder.js.map +1 -1
  385. package/lib/module/web/playbackErrorKind.js +52 -0
  386. package/lib/module/web/playbackErrorKind.js.map +1 -0
  387. package/lib/module/web/player/MediaSessionManager.js +116 -0
  388. package/lib/module/web/player/MediaSessionManager.js.map +1 -0
  389. package/lib/module/web/player/NowPlayingManager.js +7 -5
  390. package/lib/module/web/player/NowPlayingManager.js.map +1 -1
  391. package/lib/module/web/player/OptionsManager.js +9 -17
  392. package/lib/module/web/player/OptionsManager.js.map +1 -1
  393. package/lib/module/web/player/RemoteCommandController.js +92 -0
  394. package/lib/module/web/player/RemoteCommandController.js.map +1 -0
  395. package/lib/typescript/src/features/browser-config.d.ts +12 -0
  396. package/lib/typescript/src/features/browser-config.d.ts.map +1 -0
  397. package/lib/typescript/src/features/browser.d.ts +40 -1
  398. package/lib/typescript/src/features/browser.d.ts.map +1 -1
  399. package/lib/typescript/src/features/carConnection.d.ts +20 -0
  400. package/lib/typescript/src/features/carConnection.d.ts.map +1 -0
  401. package/lib/typescript/src/features/errors.d.ts +58 -3
  402. package/lib/typescript/src/features/errors.d.ts.map +1 -1
  403. package/lib/typescript/src/features/gate.d.ts +77 -0
  404. package/lib/typescript/src/features/gate.d.ts.map +1 -0
  405. package/lib/typescript/src/features/index.d.ts +2 -0
  406. package/lib/typescript/src/features/index.d.ts.map +1 -1
  407. package/lib/typescript/src/features/metadata.d.ts +6 -4
  408. package/lib/typescript/src/features/metadata.d.ts.map +1 -1
  409. package/lib/typescript/src/features/nowPlaying.d.ts +27 -0
  410. package/lib/typescript/src/features/nowPlaying.d.ts.map +1 -1
  411. package/lib/typescript/src/features/output.d.ts +28 -18
  412. package/lib/typescript/src/features/output.d.ts.map +1 -1
  413. package/lib/typescript/src/features/playback/controls.d.ts +5 -0
  414. package/lib/typescript/src/features/playback/controls.d.ts.map +1 -1
  415. package/lib/typescript/src/features/playback/index.d.ts +1 -0
  416. package/lib/typescript/src/features/playback/index.d.ts.map +1 -1
  417. package/lib/typescript/src/features/playback/progress.d.ts +3 -0
  418. package/lib/typescript/src/features/playback/progress.d.ts.map +1 -1
  419. package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts +34 -0
  420. package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts.map +1 -0
  421. package/lib/typescript/src/features/playback/volume.d.ts +1 -1
  422. package/lib/typescript/src/features/player/options.d.ts +92 -93
  423. package/lib/typescript/src/features/player/options.d.ts.map +1 -1
  424. package/lib/typescript/src/features/player/setup.d.ts +206 -167
  425. package/lib/typescript/src/features/player/setup.d.ts.map +1 -1
  426. package/lib/typescript/src/features/queue/queue.d.ts +9 -2
  427. package/lib/typescript/src/features/queue/queue.d.ts.map +1 -1
  428. package/lib/typescript/src/features/remoteControls.d.ts +0 -13
  429. package/lib/typescript/src/features/remoteControls.d.ts.map +1 -1
  430. package/lib/typescript/src/features/sleepTimer.d.ts +18 -3
  431. package/lib/typescript/src/features/sleepTimer.d.ts.map +1 -1
  432. package/lib/typescript/src/index.d.ts.map +1 -1
  433. package/lib/typescript/src/native.d.ts +1 -2
  434. package/lib/typescript/src/native.d.ts.map +1 -1
  435. package/lib/typescript/src/specs/audio-browser.nitro.d.ts +17 -225
  436. package/lib/typescript/src/specs/audio-browser.nitro.d.ts.map +1 -1
  437. package/lib/typescript/src/types/browser-native.d.ts +9 -3
  438. package/lib/typescript/src/types/browser-native.d.ts.map +1 -1
  439. package/lib/typescript/src/types/browser-nodes.d.ts +145 -13
  440. package/lib/typescript/src/types/browser-nodes.d.ts.map +1 -1
  441. package/lib/typescript/src/types/browser.d.ts +349 -85
  442. package/lib/typescript/src/types/browser.d.ts.map +1 -1
  443. package/lib/typescript/src/utils/LazyNativeEmitter.d.ts +0 -2
  444. package/lib/typescript/src/utils/LazyNativeEmitter.d.ts.map +1 -1
  445. package/lib/typescript/src/utils/NativeUpdatedValue.d.ts +0 -2
  446. package/lib/typescript/src/utils/NativeUpdatedValue.d.ts.map +1 -1
  447. package/lib/typescript/src/utils/artwork.d.ts +19 -0
  448. package/lib/typescript/src/utils/artwork.d.ts.map +1 -0
  449. package/lib/typescript/src/utils/resolveAssetSource.d.ts.map +1 -1
  450. package/nitrogen/generated/android/AudioBrowser+autolinking.cmake +3 -1
  451. package/nitrogen/generated/android/AudioBrowserOnLoad.cpp +24 -10
  452. package/nitrogen/generated/android/c++/JAndroidAudioContentType.hpp +6 -6
  453. package/nitrogen/generated/android/c++/JAndroidOptions.hpp +1 -11
  454. package/nitrogen/generated/android/c++/JArtworkRequestConfig.hpp +33 -1
  455. package/nitrogen/generated/android/c++/JArtworkVariants.hpp +61 -0
  456. package/nitrogen/generated/android/c++/JBrowseResult.hpp +5 -0
  457. package/nitrogen/generated/android/c++/JCarPlayNowPlayingButton.hpp +3 -3
  458. package/nitrogen/generated/android/c++/JFavoriteChangedEvent.hpp +6 -0
  459. package/nitrogen/generated/android/c++/JFavoriteConfig.hpp +58 -0
  460. package/nitrogen/generated/android/c++/JFavoritesMatchMode.hpp +58 -0
  461. package/nitrogen/generated/android/c++/JFormatNowPlayingParams.hpp +100 -0
  462. package/nitrogen/generated/android/c++/JFormattedNavigationError.hpp +3 -2
  463. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.hpp +112 -0
  464. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___RequestConfig_std__optional_std__unordered_map_std__string__std__string__.hpp +121 -0
  465. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___Track.hpp +123 -0
  466. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.hpp +133 -0
  467. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_std__string____Track.hpp +121 -0
  468. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.hpp +139 -0
  469. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____Track.hpp +6 -0
  470. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.hpp +134 -0
  471. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_Track______SearchParams.hpp +8 -0
  472. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_void_____TrackLoadEvent.hpp +6 -0
  473. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.hpp +131 -0
  474. package/nitrogen/generated/android/c++/JFunc_void_FavoriteChangedEvent.hpp +6 -0
  475. package/nitrogen/generated/android/c++/JFunc_void_GateEvent.hpp +79 -0
  476. package/nitrogen/generated/android/c++/JFunc_void_NowPlayingMetadata.hpp +0 -10
  477. package/nitrogen/generated/android/c++/JFunc_void_Options.hpp +9 -4
  478. package/nitrogen/generated/android/c++/JFunc_void_Output.hpp +80 -0
  479. package/nitrogen/generated/android/c++/JFunc_void_Playback.hpp +2 -0
  480. package/nitrogen/generated/android/c++/JFunc_void_PlaybackActiveTrackChangedEvent.hpp +6 -0
  481. package/nitrogen/generated/android/c++/JFunc_void_PlaybackErrorEvent.hpp +2 -0
  482. package/nitrogen/generated/android/c++/JFunc_void_bool.hpp +10 -10
  483. package/nitrogen/generated/android/c++/JFunc_void_std__optional_ResolvedTrack_.hpp +6 -0
  484. package/nitrogen/generated/android/c++/JFunc_void_std__vector_Track_.hpp +6 -0
  485. package/nitrogen/generated/android/c++/JGate.hpp +62 -0
  486. package/nitrogen/generated/android/c++/JGateDecision.hpp +64 -0
  487. package/nitrogen/generated/android/c++/{JThumbsRating.hpp → JGateEvent.hpp} +16 -15
  488. package/nitrogen/generated/android/c++/JGateReason.hpp +58 -0
  489. package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.cpp +236 -212
  490. package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.hpp +25 -22
  491. package/nitrogen/generated/android/c++/JIOSOptions.hpp +95 -0
  492. package/nitrogen/generated/android/c++/JImageRowItem.hpp +33 -3
  493. package/nitrogen/generated/android/c++/JMediaReference.hpp +58 -0
  494. package/nitrogen/generated/android/c++/JMediaRequestConfig.hpp +33 -1
  495. package/nitrogen/generated/android/c++/{JPartialAndroidSetupPlayerOptions.hpp → JNativeAndroidSetupOptions.hpp} +10 -10
  496. package/nitrogen/generated/android/c++/JNativeBrowserConfiguration.hpp +61 -28
  497. package/nitrogen/generated/android/c++/JNativeGateRequest.hpp +74 -0
  498. package/nitrogen/generated/android/c++/{JPartialIOSSetupPlayerOptions.hpp → JNativeIOSSetupOptions.hpp} +10 -10
  499. package/nitrogen/generated/android/c++/JNativeRouteEntry.hpp +20 -9
  500. package/nitrogen/generated/android/c++/JNativeSetupPlayerOptions.hpp +182 -0
  501. package/nitrogen/generated/android/c++/JNativeUpdateOptions.hpp +16 -19
  502. package/nitrogen/generated/android/c++/JNavigationErrorType.hpp +6 -0
  503. package/nitrogen/generated/android/c++/JNitroAndroidUpdateOptions.hpp +1 -11
  504. package/nitrogen/generated/android/c++/JNitroIOSUpdateOptions.hpp +96 -0
  505. package/nitrogen/generated/android/c++/JNotificationButton.hpp +3 -3
  506. package/nitrogen/generated/android/c++/JNowPlayingMetadata.hpp +3 -17
  507. package/nitrogen/generated/android/c++/JNowPlayingUpdate.hpp +7 -3
  508. package/nitrogen/generated/android/c++/JOptions.hpp +14 -9
  509. package/nitrogen/generated/android/c++/{JIosOutput.hpp → JOutput.hpp} +15 -15
  510. package/nitrogen/generated/android/c++/JOutputType.hpp +82 -0
  511. package/nitrogen/generated/android/c++/JPlayback.hpp +2 -0
  512. package/nitrogen/generated/android/c++/JPlaybackActiveTrackChangedEvent.hpp +6 -0
  513. package/nitrogen/generated/android/c++/JPlaybackError.hpp +18 -3
  514. package/nitrogen/generated/android/c++/JPlaybackErrorEvent.hpp +2 -0
  515. package/nitrogen/generated/android/c++/JPlaybackErrorKind.hpp +76 -0
  516. package/nitrogen/generated/android/c++/JPlaybackState.hpp +3 -3
  517. package/nitrogen/generated/android/c++/JPlayerCapabilities.hpp +11 -5
  518. package/nitrogen/generated/android/c++/JResolvedTrack.hpp +23 -5
  519. package/nitrogen/generated/android/c++/JRetryConfig.hpp +11 -7
  520. package/nitrogen/generated/android/c++/JSearchMode.hpp +27 -9
  521. package/nitrogen/generated/android/c++/JSearchParams.hpp +9 -3
  522. package/nitrogen/generated/android/c++/JStallReason.hpp +58 -0
  523. package/nitrogen/generated/android/c++/JTrack.hpp +23 -5
  524. package/nitrogen/generated/android/c++/JTrackLoadEvent.hpp +6 -0
  525. package/nitrogen/generated/android/c++/JTrackRequest.hpp +93 -0
  526. package/nitrogen/generated/android/c++/JTransformableRequestConfig.hpp +14 -1
  527. package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.cpp +26 -0
  528. package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.hpp +71 -0
  529. package/nitrogen/generated/android/c++/JVariant_ResolvedTrack_BrowseError_Promise_BrowseResult_.cpp +41 -0
  530. package/nitrogen/generated/android/c++/JVariant_ResolvedTrack_BrowseError_Promise_BrowseResult_.hpp +121 -0
  531. package/nitrogen/generated/android/c++/JVariant_String_ArtworkVariants.cpp +26 -0
  532. package/nitrogen/generated/android/c++/JVariant_String_ArtworkVariants.hpp +70 -0
  533. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidAudioContentType.kt +4 -4
  534. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidOptions.kt +2 -8
  535. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ArtworkRequestConfig.kt +10 -4
  536. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ArtworkVariants.kt +41 -0
  537. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/CarPlayNowPlayingButton.kt +3 -3
  538. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{ThumbsRating.kt → FavoriteConfig.kt} +6 -6
  539. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{RatingType.kt → FavoritesMatchMode.kt} +5 -10
  540. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormatNowPlayingParams.kt +50 -0
  541. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormattedNavigationError.kt +2 -2
  542. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.kt +80 -0
  543. 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 +80 -0
  544. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___Track.kt +80 -0
  545. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.kt +80 -0
  546. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_std__string____Track.kt +80 -0
  547. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.kt +80 -0
  548. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.kt +80 -0
  549. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.kt → Func_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.kt} +12 -12
  550. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Func_void_RemoteSetRatingEvent.kt → Func_void_GateEvent.kt} +9 -9
  551. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Func_void_IosOutput.kt → Func_void_Output.kt} +9 -9
  552. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_bool.kt +9 -9
  553. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{HeartRating.kt → Gate.kt} +9 -6
  554. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{PercentageRating.kt → GateDecision.kt} +9 -6
  555. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{StarRating.kt → GateEvent.kt} +6 -6
  556. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/GateReason.kt +23 -0
  557. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/HybridAudioBrowserSpec.kt +103 -109
  558. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IOSOptions.kt +44 -0
  559. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageRowItem.kt +24 -3
  560. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaReference.kt +23 -0
  561. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaRequestConfig.kt +10 -4
  562. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{PartialAndroidSetupPlayerOptions.kt → NativeAndroidSetupOptions.kt} +5 -5
  563. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeBrowserConfiguration.kt +18 -6
  564. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{RemoteSetRatingEvent.kt → NativeGateRequest.kt} +12 -6
  565. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{PartialIOSSetupPlayerOptions.kt → NativeIOSSetupOptions.kt} +5 -5
  566. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeRouteEntry.kt +4 -4
  567. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeSetupPlayerOptions.kt +66 -0
  568. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeUpdateOptions.kt +6 -6
  569. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NavigationErrorType.kt +3 -1
  570. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroAndroidUpdateOptions.kt +2 -8
  571. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroIOSUpdateOptions.kt +44 -0
  572. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NotificationButton.kt +5 -5
  573. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingMetadata.kt +3 -6
  574. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingUpdate.kt +6 -3
  575. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Options.kt +3 -3
  576. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{IosOutput.kt → Output.kt} +6 -6
  577. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/OutputType.kt +31 -0
  578. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackError.kt +12 -3
  579. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackErrorKind.kt +29 -0
  580. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackState.kt +6 -6
  581. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlayerCapabilities.kt +2 -2
  582. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ResolvedTrack.kt +12 -3
  583. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RetryConfig.kt +7 -4
  584. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SearchMode.kt +12 -6
  585. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SearchParams.kt +6 -3
  586. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/StallReason.kt +23 -0
  587. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Track.kt +12 -3
  588. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackRequest.kt +44 -0
  589. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TransformableRequestConfig.kt +7 -4
  590. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_Boolean_FavoriteConfig.kt +53 -0
  591. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_ResolvedTrack_BrowseError_Promise_BrowseResult_.kt +65 -0
  592. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_String_ArtworkVariants.kt +53 -0
  593. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.cpp +139 -28
  594. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.hpp +1098 -447
  595. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Umbrella.hpp +60 -39
  596. package/nitrogen/generated/ios/c++/HybridAudioBrowserSpecSwift.hpp +170 -112
  597. package/nitrogen/generated/ios/swift/AndroidAudioContentType.swift +8 -8
  598. package/nitrogen/generated/ios/swift/AndroidOptions.swift +2 -12
  599. package/nitrogen/generated/ios/swift/ArtworkRequestConfig.swift +95 -1
  600. package/nitrogen/generated/ios/swift/ArtworkVariants.swift +34 -0
  601. package/nitrogen/generated/ios/swift/CarPlayNowPlayingButton.swift +4 -4
  602. package/nitrogen/generated/ios/swift/FavoriteConfig.swift +29 -0
  603. package/nitrogen/generated/ios/swift/FavoritesMatchMode.swift +40 -0
  604. package/nitrogen/generated/ios/swift/FormatNowPlayingParams.swift +67 -0
  605. package/nitrogen/generated/ios/swift/FormattedNavigationError.swift +17 -4
  606. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.swift +54 -0
  607. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_RequestConfig___RequestConfig_std__optional_std__unordered_map_std__string__std__string__.swift +69 -0
  608. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_RequestConfig___Track.swift +54 -0
  609. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.swift +60 -0
  610. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__optional_std__string____Track.swift +60 -0
  611. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.swift +61 -0
  612. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.swift +61 -0
  613. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.swift +77 -0
  614. package/nitrogen/generated/ios/swift/Func_void_GateDecision.swift +46 -0
  615. package/nitrogen/generated/ios/swift/{Func_void_RemoteSetRatingEvent.swift → Func_void_GateEvent.swift} +10 -10
  616. package/nitrogen/generated/ios/swift/{Func_void_IosOutput.swift → Func_void_Output.swift} +10 -10
  617. package/nitrogen/generated/ios/swift/Func_void_TransformableRequestConfig.swift +46 -0
  618. package/nitrogen/generated/ios/swift/Func_void_bool.swift +5 -5
  619. package/nitrogen/generated/ios/swift/Func_void_std__optional_NowPlayingUpdate_.swift +46 -0
  620. package/nitrogen/generated/ios/swift/Func_void_std__optional_std__string_.swift +53 -0
  621. package/nitrogen/generated/ios/swift/{Func_void_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError___.swift → Func_void_std__shared_ptr_Promise_GateDecision__.swift} +17 -17
  622. package/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_TransformableRequestConfig__.swift +66 -0
  623. package/nitrogen/generated/ios/swift/Func_void_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError____.swift +81 -0
  624. package/nitrogen/generated/ios/swift/Gate.swift +47 -0
  625. package/nitrogen/generated/ios/swift/GateDecision.swift +40 -0
  626. package/nitrogen/generated/ios/swift/GateEvent.swift +29 -0
  627. package/nitrogen/generated/ios/swift/GateReason.swift +40 -0
  628. package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec.swift +20 -14
  629. package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec_cxx.swift +230 -197
  630. package/nitrogen/generated/ios/swift/IOSOptions.swift +51 -0
  631. package/nitrogen/generated/ios/swift/ImageRowItem.swift +121 -2
  632. package/nitrogen/generated/ios/swift/MediaReference.swift +40 -0
  633. package/nitrogen/generated/ios/swift/MediaRequestConfig.swift +107 -1
  634. package/nitrogen/generated/ios/swift/{PartialAndroidSetupPlayerOptions.swift → NativeAndroidSetupOptions.swift} +5 -5
  635. package/nitrogen/generated/ios/swift/NativeBrowserConfiguration.swift +161 -22
  636. package/nitrogen/generated/ios/swift/NativeGateRequest.swift +58 -0
  637. package/nitrogen/generated/ios/swift/{PartialIOSSetupPlayerOptions.swift → NativeIOSSetupOptions.swift} +5 -5
  638. package/nitrogen/generated/ios/swift/NativeRouteEntry.swift +19 -19
  639. package/nitrogen/generated/ios/swift/NativeSetupPlayerOptions.swift +206 -0
  640. package/nitrogen/generated/ios/swift/NativeUpdateOptions.swift +12 -25
  641. package/nitrogen/generated/ios/swift/NavigationErrorType.swift +8 -0
  642. package/nitrogen/generated/ios/swift/NitroAndroidUpdateOptions.swift +1 -30
  643. package/nitrogen/generated/ios/swift/NitroIOSUpdateOptions.swift +90 -0
  644. package/nitrogen/generated/ios/swift/NotificationButton.swift +4 -4
  645. package/nitrogen/generated/ios/swift/NowPlayingMetadata.swift +1 -48
  646. package/nitrogen/generated/ios/swift/NowPlayingUpdate.swift +19 -1
  647. package/nitrogen/generated/ios/swift/Options.swift +10 -4
  648. package/nitrogen/generated/ios/swift/{IosOutput.swift → Output.swift} +7 -7
  649. package/nitrogen/generated/ios/swift/OutputType.swift +72 -0
  650. package/nitrogen/generated/ios/swift/PlaybackError.swift +43 -2
  651. package/nitrogen/generated/ios/swift/PlaybackErrorKind.swift +64 -0
  652. package/nitrogen/generated/ios/swift/PlaybackState.swift +4 -4
  653. package/nitrogen/generated/ios/swift/PlayerCapabilities.swift +27 -8
  654. package/nitrogen/generated/ios/swift/ResolvedTrack.swift +74 -8
  655. package/nitrogen/generated/ios/swift/RetryConfig.swift +35 -4
  656. package/nitrogen/generated/ios/swift/SearchMode.swift +36 -12
  657. package/nitrogen/generated/ios/swift/SearchParams.swift +7 -2
  658. package/nitrogen/generated/ios/swift/StallReason.swift +40 -0
  659. package/nitrogen/generated/ios/swift/Track.swift +74 -8
  660. package/nitrogen/generated/ios/swift/TrackRequest.swift +106 -0
  661. package/nitrogen/generated/ios/swift/TransformableRequestConfig.swift +60 -1
  662. package/nitrogen/generated/ios/swift/Variant_Bool_FavoriteConfig.swift +18 -0
  663. package/nitrogen/generated/ios/swift/Variant_ResolvedTrack_BrowseError_Promise_BrowseResult_.swift +19 -0
  664. package/nitrogen/generated/ios/swift/Variant_String_ArtworkVariants.swift +18 -0
  665. package/nitrogen/generated/shared/c++/AndroidAudioContentType.hpp +10 -10
  666. package/nitrogen/generated/shared/c++/AndroidOptions.hpp +1 -12
  667. package/nitrogen/generated/shared/c++/ArtworkRequestConfig.hpp +10 -2
  668. package/nitrogen/generated/shared/c++/ArtworkVariants.hpp +87 -0
  669. package/nitrogen/generated/shared/c++/CarPlayNowPlayingButton.hpp +6 -6
  670. package/nitrogen/generated/shared/c++/EqualizerSettings.hpp +0 -2
  671. package/nitrogen/generated/shared/c++/{StarRating.hpp → FavoriteConfig.hpp} +18 -17
  672. package/nitrogen/generated/shared/c++/FavoritesMatchMode.hpp +76 -0
  673. package/nitrogen/generated/shared/c++/FormatNowPlayingParams.hpp +110 -0
  674. package/nitrogen/generated/shared/c++/FormattedNavigationError.hpp +6 -5
  675. package/nitrogen/generated/shared/c++/{HeartRating.hpp → Gate.hpp} +21 -16
  676. package/nitrogen/generated/shared/c++/{ThumbsRating.hpp → GateDecision.hpp} +23 -17
  677. package/nitrogen/generated/shared/c++/{PercentageRating.hpp → GateEvent.hpp} +18 -17
  678. package/nitrogen/generated/shared/c++/GateReason.hpp +76 -0
  679. package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.cpp +21 -18
  680. package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.hpp +44 -35
  681. package/nitrogen/generated/shared/c++/IOSOptions.hpp +91 -0
  682. package/nitrogen/generated/shared/c++/ImageRowItem.hpp +33 -2
  683. package/nitrogen/generated/shared/c++/MediaReference.hpp +76 -0
  684. package/nitrogen/generated/shared/c++/MediaRequestConfig.hpp +10 -2
  685. package/nitrogen/generated/shared/c++/{PartialAndroidSetupPlayerOptions.hpp → NativeAndroidSetupOptions.hpp} +11 -11
  686. package/nitrogen/generated/shared/c++/NativeBrowserConfiguration.hpp +31 -15
  687. package/nitrogen/generated/shared/c++/NativeGateRequest.hpp +97 -0
  688. package/nitrogen/generated/shared/c++/{PartialIOSSetupPlayerOptions.hpp → NativeIOSSetupOptions.hpp} +11 -11
  689. package/nitrogen/generated/shared/c++/NativeRouteEntry.hpp +5 -5
  690. package/nitrogen/generated/shared/c++/NativeSetupPlayerOptions.hpp +138 -0
  691. package/nitrogen/generated/shared/c++/NativeUpdateOptions.hpp +9 -7
  692. package/nitrogen/generated/shared/c++/NavigationErrorType.hpp +8 -0
  693. package/nitrogen/generated/shared/c++/NitroAndroidUpdateOptions.hpp +1 -12
  694. package/nitrogen/generated/shared/c++/NitroIOSUpdateOptions.hpp +92 -0
  695. package/nitrogen/generated/shared/c++/NotificationButton.hpp +8 -8
  696. package/nitrogen/generated/shared/c++/NowPlayingMetadata.hpp +3 -19
  697. package/nitrogen/generated/shared/c++/NowPlayingUpdate.hpp +6 -2
  698. package/nitrogen/generated/shared/c++/Options.hpp +8 -8
  699. package/nitrogen/generated/shared/c++/{IosOutput.hpp → Output.hpp} +18 -18
  700. package/nitrogen/generated/shared/c++/OutputType.hpp +108 -0
  701. package/nitrogen/generated/shared/c++/PlaybackError.hpp +18 -3
  702. package/nitrogen/generated/shared/c++/PlaybackErrorKind.hpp +100 -0
  703. package/nitrogen/generated/shared/c++/PlaybackState.hpp +9 -9
  704. package/nitrogen/generated/shared/c++/PlayerCapabilities.hpp +9 -6
  705. package/nitrogen/generated/shared/c++/ResolvedTrack.hpp +24 -5
  706. package/nitrogen/generated/shared/c++/RetryConfig.hpp +10 -6
  707. package/nitrogen/generated/shared/c++/SearchMode.hpp +39 -15
  708. package/nitrogen/generated/shared/c++/SearchParams.hpp +9 -2
  709. package/nitrogen/generated/shared/c++/StallReason.hpp +76 -0
  710. package/nitrogen/generated/shared/c++/Track.hpp +24 -5
  711. package/nitrogen/generated/shared/c++/TrackRequest.hpp +93 -0
  712. package/nitrogen/generated/shared/c++/TransformableRequestConfig.hpp +6 -2
  713. package/package.json +11 -6
  714. package/src/codegen-no-config-variant.test.ts +70 -0
  715. package/src/features/browser-config.test.ts +110 -0
  716. package/src/features/browser-config.ts +293 -0
  717. package/src/features/browser.test.ts +19 -0
  718. package/src/features/browser.ts +58 -201
  719. package/src/features/carConnection.ts +36 -0
  720. package/src/features/errors.ts +68 -2
  721. package/src/features/gate.test.ts +72 -0
  722. package/src/features/gate.ts +155 -0
  723. package/src/features/index.ts +2 -0
  724. package/src/features/metadata.ts +6 -12
  725. package/src/features/nowPlaying.ts +36 -0
  726. package/src/features/output.ts +35 -22
  727. package/src/features/playback/controls.ts +8 -0
  728. package/src/features/playback/index.ts +1 -0
  729. package/src/features/playback/progress.ts +31 -12
  730. package/src/features/playback/trackPlaybackTime.test.ts +66 -0
  731. package/src/features/playback/trackPlaybackTime.ts +106 -0
  732. package/src/features/playback/volume.ts +1 -1
  733. package/src/features/player/options.test.ts +38 -0
  734. package/src/features/player/options.ts +140 -75
  735. package/src/features/player/setup.test.ts +117 -0
  736. package/src/features/player/setup.ts +390 -175
  737. package/src/features/queue/queue.test.ts +36 -0
  738. package/src/features/queue/queue.ts +15 -4
  739. package/src/features/remoteControls.ts +0 -23
  740. package/src/features/sleepTimer.ts +23 -4
  741. package/src/native.ts +5 -0
  742. package/src/native.web.ts +4 -1
  743. package/src/specs/audio-browser.nitro.ts +131 -41
  744. package/src/types/browser-native.ts +19 -6
  745. package/src/types/browser-nodes.ts +160 -13
  746. package/src/types/browser.ts +377 -89
  747. package/src/utils/LazyNativeEmitter.ts +0 -2
  748. package/src/utils/NativeUpdatedValue.ts +0 -2
  749. package/src/utils/artwork.ts +30 -0
  750. package/src/web/NativeAudioBrowser.playWhenReady.test.ts +301 -0
  751. package/src/web/NativeAudioBrowser.ts +365 -158
  752. package/src/web/TrackPlayer/PlaybackStateMachine.test.ts +139 -0
  753. package/src/web/TrackPlayer/PlaybackStateMachine.ts +82 -0
  754. package/src/web/TrackPlayer/PlaybackTimer.test.ts +67 -0
  755. package/src/web/TrackPlayer/PlaybackTimer.ts +33 -0
  756. package/src/web/TrackPlayer/Player.dispatch.test.ts +229 -0
  757. package/src/web/TrackPlayer/Player.load.test.ts +86 -0
  758. package/src/web/TrackPlayer/Player.ts +113 -39
  759. package/src/web/TrackPlayer/PlayingStateFactory.test.ts +51 -0
  760. package/src/web/TrackPlayer/PlayingStateFactory.ts +24 -0
  761. package/src/web/TrackPlayer/QueueManager.test.ts +289 -0
  762. package/src/web/TrackPlayer/QueueManager.ts +302 -0
  763. package/src/web/TrackPlayer/QueuePlayer.ts +188 -0
  764. package/src/web/TrackPlayer/RepeatMode.ts +1 -1
  765. package/src/web/TrackPlayer/SleepTimer.ts +38 -3
  766. package/src/web/TrackPlayer/VolumeFader.ts +74 -0
  767. package/src/web/TrackPlayer/index.ts +2 -1
  768. package/src/web/browser/BrowserManager.ts +231 -62
  769. package/src/web/browser/NavigationErrorManager.ts +3 -1
  770. package/src/web/browser/SearchManager.ts +11 -15
  771. package/src/web/browser/__tests__/layer-resolver.test.ts +69 -0
  772. package/src/web/browser/assertBrowsePageShape.test.ts +27 -0
  773. package/src/web/browser/assertBrowsePageShape.ts +27 -0
  774. package/src/web/browser/classifyTrackNavigation.test.ts +41 -0
  775. package/src/web/browser/classifyTrackNavigation.ts +35 -0
  776. package/src/web/browser/parseSearchResponse.test.ts +25 -0
  777. package/src/web/browser/parseSearchResponse.ts +15 -0
  778. package/src/web/http/HttpClient.ts +5 -35
  779. package/src/web/http/RequestConfigBuilder.test.ts +59 -0
  780. package/src/web/http/RequestConfigBuilder.ts +120 -63
  781. package/src/web/playbackErrorKind.test.ts +55 -0
  782. package/src/web/playbackErrorKind.ts +56 -0
  783. package/src/web/player/MediaSessionManager.test.ts +220 -0
  784. package/src/web/player/MediaSessionManager.ts +151 -0
  785. package/src/web/player/NowPlayingManager.test.ts +46 -0
  786. package/src/web/player/NowPlayingManager.ts +6 -5
  787. package/src/web/player/OptionsManager.ts +12 -18
  788. package/src/web/player/RemoteCommandController.test.ts +171 -0
  789. package/src/web/player/RemoteCommandController.ts +166 -0
  790. package/android/src/main/java/com/audiobrowser/player/PlaybackProgressUpdateManager.kt +0 -59
  791. package/android/src/main/java/com/audiobrowser/util/RatingFactory.kt +0 -72
  792. package/android/src/main/java/com/audiobrowser/util/ResolvedTrackFactory.kt +0 -36
  793. package/android/src/test/java/com/audiobrowser/player/PlaybackProgressUpdateManagerTest.kt +0 -146
  794. package/ios/CarPlay/Track+CarPlay.swift +0 -63
  795. package/ios/NowPlayingInfo/NowPlayingInfoCenter.swift +0 -9
  796. package/ios/Player/PlaybackProgressUpdateManager.swift +0 -68
  797. package/ios/Tests/PlaybackProgressUpdateManagerTests.swift +0 -166
  798. package/lib/commonjs/features/rating.js +0 -2
  799. package/lib/commonjs/features/rating.js.map +0 -1
  800. package/lib/commonjs/types/player.js +0 -2
  801. package/lib/commonjs/types/player.js.map +0 -1
  802. package/lib/commonjs/web/SimpleRouter.test.js +0 -174
  803. package/lib/commonjs/web/SimpleRouter.test.js.map +0 -1
  804. package/lib/commonjs/web/TrackPlayer/PlaylistPlayer.js +0 -293
  805. package/lib/commonjs/web/TrackPlayer/PlaylistPlayer.js.map +0 -1
  806. package/lib/module/features/rating.js +0 -2
  807. package/lib/module/features/rating.js.map +0 -1
  808. package/lib/module/types/player.js +0 -2
  809. package/lib/module/types/player.js.map +0 -1
  810. package/lib/module/web/SimpleRouter.test.js +0 -174
  811. package/lib/module/web/SimpleRouter.test.js.map +0 -1
  812. package/lib/module/web/TrackPlayer/PlaylistPlayer.js +0 -288
  813. package/lib/module/web/TrackPlayer/PlaylistPlayer.js.map +0 -1
  814. package/lib/typescript/src/features/rating.d.ts +0 -14
  815. package/lib/typescript/src/features/rating.d.ts.map +0 -1
  816. package/lib/typescript/src/native.web.d.ts +0 -3
  817. package/lib/typescript/src/native.web.d.ts.map +0 -1
  818. package/lib/typescript/src/types/player.d.ts +0 -64
  819. package/lib/typescript/src/types/player.d.ts.map +0 -1
  820. package/lib/typescript/src/web/NativeAudioBrowser.d.ts +0 -188
  821. package/lib/typescript/src/web/NativeAudioBrowser.d.ts.map +0 -1
  822. package/lib/typescript/src/web/SimpleRouter.d.ts +0 -40
  823. package/lib/typescript/src/web/SimpleRouter.d.ts.map +0 -1
  824. package/lib/typescript/src/web/SimpleRouter.test.d.ts +0 -2
  825. package/lib/typescript/src/web/SimpleRouter.test.d.ts.map +0 -1
  826. package/lib/typescript/src/web/TrackPlayer/Event.d.ts +0 -11
  827. package/lib/typescript/src/web/TrackPlayer/Event.d.ts.map +0 -1
  828. package/lib/typescript/src/web/TrackPlayer/Player.d.ts +0 -59
  829. package/lib/typescript/src/web/TrackPlayer/Player.d.ts.map +0 -1
  830. package/lib/typescript/src/web/TrackPlayer/PlaylistPlayer.d.ts +0 -39
  831. package/lib/typescript/src/web/TrackPlayer/PlaylistPlayer.d.ts.map +0 -1
  832. package/lib/typescript/src/web/TrackPlayer/RepeatMode.d.ts +0 -6
  833. package/lib/typescript/src/web/TrackPlayer/RepeatMode.d.ts.map +0 -1
  834. package/lib/typescript/src/web/TrackPlayer/SetupNotCalledError.d.ts +0 -4
  835. package/lib/typescript/src/web/TrackPlayer/SetupNotCalledError.d.ts.map +0 -1
  836. package/lib/typescript/src/web/TrackPlayer/SleepTimer.d.ts +0 -34
  837. package/lib/typescript/src/web/TrackPlayer/SleepTimer.d.ts.map +0 -1
  838. package/lib/typescript/src/web/TrackPlayer/State.d.ts +0 -13
  839. package/lib/typescript/src/web/TrackPlayer/State.d.ts.map +0 -1
  840. package/lib/typescript/src/web/TrackPlayer/index.d.ts +0 -5
  841. package/lib/typescript/src/web/TrackPlayer/index.d.ts.map +0 -1
  842. package/lib/typescript/src/web/browser/BrowserManager.d.ts +0 -154
  843. package/lib/typescript/src/web/browser/BrowserManager.d.ts.map +0 -1
  844. package/lib/typescript/src/web/browser/FavoriteManager.d.ts +0 -42
  845. package/lib/typescript/src/web/browser/FavoriteManager.d.ts.map +0 -1
  846. package/lib/typescript/src/web/browser/NavigationErrorManager.d.ts +0 -40
  847. package/lib/typescript/src/web/browser/NavigationErrorManager.d.ts.map +0 -1
  848. package/lib/typescript/src/web/browser/SearchManager.d.ts +0 -22
  849. package/lib/typescript/src/web/browser/SearchManager.d.ts.map +0 -1
  850. package/lib/typescript/src/web/http/HttpClient.d.ts +0 -25
  851. package/lib/typescript/src/web/http/HttpClient.d.ts.map +0 -1
  852. package/lib/typescript/src/web/http/RequestConfigBuilder.d.ts +0 -98
  853. package/lib/typescript/src/web/http/RequestConfigBuilder.d.ts.map +0 -1
  854. package/lib/typescript/src/web/player/NowPlayingManager.d.ts +0 -34
  855. package/lib/typescript/src/web/player/NowPlayingManager.d.ts.map +0 -1
  856. package/lib/typescript/src/web/player/OptionsManager.d.ts +0 -32
  857. package/lib/typescript/src/web/player/OptionsManager.d.ts.map +0 -1
  858. package/lib/typescript/src/web/util/BrowserPathHelper.d.ts +0 -69
  859. package/lib/typescript/src/web/util/BrowserPathHelper.d.ts.map +0 -1
  860. package/lib/typescript/src/web/util/shuffle.d.ts +0 -8
  861. package/lib/typescript/src/web/util/shuffle.d.ts.map +0 -1
  862. package/nitrogen/generated/android/c++/JAndroidUpdateOptions.hpp +0 -86
  863. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.hpp +0 -147
  864. package/nitrogen/generated/android/c++/JFunc_void_IosOutput.hpp +0 -80
  865. package/nitrogen/generated/android/c++/JFunc_void_RemoteSetRatingEvent.hpp +0 -87
  866. package/nitrogen/generated/android/c++/JHeartRating.hpp +0 -57
  867. package/nitrogen/generated/android/c++/JIosOutputType.hpp +0 -85
  868. package/nitrogen/generated/android/c++/JPartialSetupPlayerOptions.hpp +0 -96
  869. package/nitrogen/generated/android/c++/JPercentageRating.hpp +0 -57
  870. package/nitrogen/generated/android/c++/JRatingType.hpp +0 -73
  871. package/nitrogen/generated/android/c++/JRemoteSetRatingEvent.hpp +0 -66
  872. package/nitrogen/generated/android/c++/JStarRating.hpp +0 -57
  873. package/nitrogen/generated/android/c++/JUpdateOptions.hpp +0 -105
  874. package/nitrogen/generated/android/c++/JVariant_HeartRating_ThumbsRating_StarRating_PercentageRating.cpp +0 -34
  875. package/nitrogen/generated/android/c++/JVariant_HeartRating_ThumbsRating_StarRating_PercentageRating.hpp +0 -105
  876. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidUpdateOptions.kt +0 -50
  877. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IosOutputType.kt +0 -32
  878. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PartialSetupPlayerOptions.kt +0 -47
  879. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/UpdateOptions.kt +0 -53
  880. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_HeartRating_ThumbsRating_StarRating_PercentageRating.kt +0 -77
  881. package/nitrogen/generated/ios/swift/AndroidUpdateOptions.swift +0 -119
  882. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.swift +0 -68
  883. package/nitrogen/generated/ios/swift/HeartRating.swift +0 -29
  884. package/nitrogen/generated/ios/swift/IosOutputType.swift +0 -76
  885. package/nitrogen/generated/ios/swift/PartialSetupPlayerOptions.swift +0 -101
  886. package/nitrogen/generated/ios/swift/PercentageRating.swift +0 -29
  887. package/nitrogen/generated/ios/swift/RatingType.swift +0 -60
  888. package/nitrogen/generated/ios/swift/RemoteSetRatingEvent.swift +0 -58
  889. package/nitrogen/generated/ios/swift/StarRating.swift +0 -29
  890. package/nitrogen/generated/ios/swift/ThumbsRating.swift +0 -29
  891. package/nitrogen/generated/ios/swift/UpdateOptions.swift +0 -143
  892. package/nitrogen/generated/ios/swift/Variant_HeartRating_ThumbsRating_StarRating_PercentageRating.swift +0 -20
  893. package/nitrogen/generated/shared/c++/AndroidUpdateOptions.hpp +0 -109
  894. package/nitrogen/generated/shared/c++/IosOutputType.hpp +0 -112
  895. package/nitrogen/generated/shared/c++/PartialSetupPlayerOptions.hpp +0 -104
  896. package/nitrogen/generated/shared/c++/RatingType.hpp +0 -96
  897. package/nitrogen/generated/shared/c++/RemoteSetRatingEvent.hpp +0 -94
  898. package/nitrogen/generated/shared/c++/UpdateOptions.hpp +0 -111
  899. package/src/features/rating.ts +0 -17
  900. package/src/types/player.ts +0 -69
  901. package/src/web/TrackPlayer/PlaylistPlayer.ts +0 -346
@@ -0,0 +1,55 @@
1
+ import XCTest
2
+
3
+ @testable import AudioBrowserTestable
4
+
5
+ @MainActor
6
+ final class PlaybackTimerTests: XCTestCase {
7
+ func testNoTicksUntilIntervalSetAndActive() async throws {
8
+ var ticks = 0
9
+ let timer = PlaybackTimer(isActive: { $0 == .playing }) { ticks += 1 }
10
+ timer.onPlaybackStateChanged(.playing) // no interval yet
11
+ try await Task.sleep(nanoseconds: 1_200_000_000)
12
+ XCTAssertEqual(ticks, 0)
13
+ }
14
+
15
+ func testTicksWhenIntervalSetAndActive() async throws {
16
+ var ticks = 0
17
+ let timer = PlaybackTimer(isActive: { $0 == .playing }) { ticks += 1 }
18
+ timer.setInterval(1)
19
+ timer.onPlaybackStateChanged(.playing)
20
+ try await Task.sleep(nanoseconds: 2_200_000_000)
21
+ XCTAssertGreaterThanOrEqual(ticks, 1)
22
+ }
23
+
24
+ func testStopsWhenStateLeavesActive() async throws {
25
+ var ticks = 0
26
+ let timer = PlaybackTimer(isActive: { $0 == .playing }) { ticks += 1 }
27
+ timer.setInterval(1)
28
+ timer.onPlaybackStateChanged(.playing)
29
+ timer.onPlaybackStateChanged(.paused)
30
+ let after = ticks
31
+ try await Task.sleep(nanoseconds: 1_200_000_000)
32
+ XCTAssertEqual(ticks, after)
33
+ }
34
+
35
+ func testNilIntervalStops() async throws {
36
+ var ticks = 0
37
+ let timer = PlaybackTimer(isActive: { $0 == .playing }) { ticks += 1 }
38
+ timer.setInterval(1)
39
+ timer.onPlaybackStateChanged(.playing)
40
+ timer.setInterval(nil) // off-switch
41
+ let after = ticks
42
+ try await Task.sleep(nanoseconds: 1_200_000_000)
43
+ XCTAssertEqual(ticks, after)
44
+ }
45
+
46
+ func testIsActivePredicateGatesState() async throws {
47
+ // A "playing-only" predicate must not tick while buffering.
48
+ var ticks = 0
49
+ let timer = PlaybackTimer(isActive: { $0 == .playing }) { ticks += 1 }
50
+ timer.setInterval(1)
51
+ timer.onPlaybackStateChanged(.buffering)
52
+ try await Task.sleep(nanoseconds: 1_200_000_000)
53
+ XCTAssertEqual(ticks, 0)
54
+ }
55
+ }
@@ -0,0 +1,57 @@
1
+ import Foundation
2
+ import Testing
3
+
4
+ @testable import AudioBrowserTestable
5
+
6
+ @Suite("PlayingStateManager")
7
+ struct PlayingStateManagerTests {
8
+ @MainActor
9
+ private func makeManager() -> (manager: PlayingStateManager, changes: () -> [PlayingState]) {
10
+ var recorded: [PlayingState] = []
11
+ let manager = PlayingStateManager { recorded.append($0) }
12
+ return (manager, { recorded })
13
+ }
14
+
15
+ @Test @MainActor
16
+ func playing_whenIntentAndActiveState() {
17
+ let (m, _) = makeManager()
18
+ m.update(playWhenReady: true, state: .playing)
19
+ #expect(m.playing == true)
20
+ #expect(m.buffering == false)
21
+ }
22
+
23
+ @Test @MainActor
24
+ func buffering_whenIntentAndLoading() {
25
+ let (m, _) = makeManager()
26
+ m.update(playWhenReady: true, state: .loading)
27
+ #expect(m.playing == true)
28
+ #expect(m.buffering == true)
29
+ }
30
+
31
+ @Test @MainActor
32
+ func notPlaying_withoutIntent() {
33
+ let (m, _) = makeManager()
34
+ m.update(playWhenReady: false, state: .playing)
35
+ #expect(m.playing == false)
36
+ }
37
+
38
+ /// Terminal states are not playable regardless of intent. .stopped was
39
+ /// missing from the exclusion list — masked only by stop() clearing
40
+ /// playWhenReady right after transitioning, which made the gap latent.
41
+ @Test @MainActor
42
+ func notPlaying_inTerminalStates_evenWithIntent() {
43
+ for state in [PlaybackState.none, .stopped, .ended, .error] {
44
+ let (m, _) = makeManager()
45
+ m.update(playWhenReady: true, state: state)
46
+ #expect(m.playing == false, "Expected not playing in \(state) despite intent")
47
+ }
48
+ }
49
+
50
+ @Test @MainActor
51
+ func onChange_firesOnlyOnActualChange() {
52
+ let (m, changes) = makeManager()
53
+ m.update(playWhenReady: true, state: .playing)
54
+ m.update(playWhenReady: true, state: .playing)
55
+ #expect(changes().count == 1)
56
+ }
57
+ }
@@ -390,16 +390,16 @@ struct AddAtTests {
390
390
  #expect(try q.addAt([], at: 0) == false)
391
391
  }
392
392
 
393
- @Test func singleExistingTrack_insertBeforeCurrent_doesNotShift() throws {
393
+ @Test func singleExistingTrack_insertBeforeCurrent_shifts() throws {
394
394
  let q = QueueManager()
395
395
  q.setQueue(tracks("a"))
396
- // guard `tracks.count > 1` is false (count is 1), so currentIndex is NOT shifted.
397
- // The original track moves to index 1 but currentIndex stays 0.
398
396
  let changed = try q.addAt(tracks("x"), at: 0)
399
397
  #expect(changed == false)
400
- #expect(q.currentIndex == 0)
401
- // currentTrack is now "x" (the inserted track), not "a"
402
- #expect(q.currentTrack?.id == "x")
398
+ // The pointer follows the playing track — the old `tracks.count > 1`
399
+ // guard silently swapped currentTrack to the inserted track while the
400
+ // player kept playing the old one.
401
+ #expect(q.currentIndex == 1)
402
+ #expect(q.currentTrack?.id == "a")
403
403
  }
404
404
 
405
405
  @Test func atExactCurrentIndex_shiftsCurrentIndex() throws {
@@ -524,13 +524,17 @@ struct RemoveTests {
524
524
  @Suite("move()")
525
525
  @MainActor
526
526
  struct MoveTests {
527
- @Test func currentTrack_returnsTrue_updatesIndex() throws {
527
+ // A move never changes which track is current — the pointer follows the
528
+ // track, and no move returns true (true triggers a reload at the caller,
529
+ // which would restart playback on a reorder).
530
+
531
+ @Test func currentTrack_pointerFollows() throws {
528
532
  let q = QueueManager()
529
533
  q.setQueue(tracks("a", "b", "c"), initialIndex: 0)
530
534
  let changed = try q.move(fromIndex: 0, toIndex: 2)
531
- #expect(changed == true)
535
+ #expect(changed == false)
532
536
  #expect(q.currentIndex == 2)
533
- #expect(q.tracks[2].id == "a")
537
+ #expect(q.currentTrack?.id == "a")
534
538
  }
535
539
 
536
540
  @Test func nonCurrent_returnsFalse() throws {
@@ -548,26 +552,37 @@ struct MoveTests {
548
552
  }
549
553
  }
550
554
 
551
- @Test func nonCurrent_acrossCurrent_doesNotAdjustIndex() throws {
555
+ @Test func nonCurrent_acrossCurrent_keepsPointerOnSameTrack() throws {
552
556
  let q = QueueManager()
553
557
  q.setQueue(tracks("a", "b", "c"), initialIndex: 1)
554
- // Move track from before current to after current.
555
- // currentIndex is NOT adjusted (only adjusted when fromIndex == currentIndex).
556
558
  let changed = try q.move(fromIndex: 0, toIndex: 2)
557
559
  #expect(changed == false)
558
- #expect(q.currentIndex == 1)
559
- // After remove(0): [b, c], insert at min(2,2)=2: [b, c, a]
560
- // currentIndex 1 now points to "c", not "b"
561
- #expect(q.currentTrack?.id == "c")
560
+ // [a,b,c] → [b,c,a]; "b" is now index 0.
561
+ #expect(q.currentTrack?.id == "b")
562
+ #expect(q.currentIndex == 0)
563
+ }
564
+
565
+ @Test func nonCurrent_acrossCurrentBackwards_keepsPointerOnSameTrack() throws {
566
+ let q = QueueManager()
567
+ q.setQueue(tracks("a", "b", "c"), initialIndex: 1)
568
+ let changed = try q.move(fromIndex: 2, toIndex: 0)
569
+ #expect(changed == false)
570
+ // [a,b,c] → [c,a,b]; "b" is now index 2.
571
+ #expect(q.currentTrack?.id == "b")
572
+ #expect(q.currentIndex == 2)
562
573
  }
563
574
 
564
- @Test func toIndexBeyondCount_clampsToEnd() throws {
575
+ @Test func toIndexBeyondCount_clampsPointerToo() throws {
565
576
  let q = QueueManager()
566
577
  q.setQueue(tracks("a", "b", "c"), initialIndex: 0)
567
578
  let changed = try q.move(fromIndex: 0, toIndex: 99)
568
- #expect(changed == true)
579
+ #expect(changed == false)
569
580
  // remove(0): [b, c], insert at min(2, 99)=2: [b, c, a]
570
581
  #expect(q.tracks[2].id == "a")
582
+ // The unclamped assignment left currentIndex at 99 → currentTrack nil →
583
+ // a reorder unloaded playback.
584
+ #expect(q.currentIndex == 2)
585
+ #expect(q.currentTrack?.id == "a")
571
586
  }
572
587
 
573
588
  @Test func invalidFromIndex_throws() {
@@ -606,6 +621,23 @@ struct ClearTests {
606
621
  let q = QueueManager()
607
622
  #expect(q.clear() == false)
608
623
  }
624
+
625
+ /// clear() and removeUpcomingTracks() were the only mutations not
626
+ /// maintaining the shuffle order — a stale order over a rebuilt queue
627
+ /// navigates to phantom indices, nil-ing currentTrack and unloading
628
+ /// playback mid-session.
629
+ @Test func clear_alsoClearsShuffleOrder() {
630
+ let q = QueueManager()
631
+ q.shuffleEnabled = true
632
+ q.setQueue(tracks("a", "b", "c", "d", "e"))
633
+
634
+ q.clear()
635
+
636
+ #expect(q.shuffleOrder.shuffled.isEmpty)
637
+
638
+ _ = try? q.addAt(tracks("x", "y"), at: 0)
639
+ #expect(q.shuffleOrder.shuffled.count == q.tracks.count)
640
+ }
609
641
  }
610
642
 
611
643
  // MARK: - Other: replace, removeUpcomingTracks
@@ -620,6 +652,16 @@ struct OtherMutationTests {
620
652
  #expect(q.tracks[1].id == "B")
621
653
  }
622
654
 
655
+ @Test func removeUpcomingTracks_alsoTrimsShuffleOrder() {
656
+ let q = QueueManager()
657
+ q.shuffleEnabled = true
658
+ q.setQueue(tracks("a", "b", "c", "d", "e"), initialIndex: 1)
659
+
660
+ q.removeUpcomingTracks()
661
+
662
+ #expect(q.shuffleOrder.shuffled.count == q.tracks.count)
663
+ }
664
+
623
665
  @Test func removeUpcomingTracks_keepsCurrentAndBefore() {
624
666
  let q = QueueManager()
625
667
  q.setQueue(tracks("a", "b", "c", "d"), initialIndex: 1)
@@ -878,3 +920,92 @@ struct DelegateTests {
878
920
  #expect(spy.calls.isEmpty)
879
921
  }
880
922
  }
923
+
924
+ // MARK: - canNext / canPrevious
925
+
926
+ @Suite("canNext / canPrevious")
927
+ @MainActor
928
+ struct SkipAvailabilityTests {
929
+ @Test func emptyQueue_bothFalse() {
930
+ let q = QueueManager()
931
+ #expect(q.canNext == false)
932
+ #expect(q.canPrevious == false)
933
+ }
934
+
935
+ @Test func singleTrack_repeatOff_bothFalse() {
936
+ let q = QueueManager()
937
+ q.setQueue(tracks("a"))
938
+ #expect(q.canNext == false)
939
+ #expect(q.canPrevious == false)
940
+ }
941
+
942
+ @Test func singleTrack_repeatQueue_bothFalse() {
943
+ let q = QueueManager()
944
+ q.setQueue(tracks("a"))
945
+ q.repeatMode = .queue
946
+ #expect(q.canNext == false)
947
+ #expect(q.canPrevious == false)
948
+ }
949
+
950
+ @Test func firstOfMany_nextOnly() {
951
+ let q = QueueManager()
952
+ q.setQueue(tracks("a", "b", "c"), initialIndex: 0)
953
+ #expect(q.canNext == true)
954
+ #expect(q.canPrevious == false)
955
+ }
956
+
957
+ @Test func middleOfMany_both() {
958
+ let q = QueueManager()
959
+ q.setQueue(tracks("a", "b", "c"), initialIndex: 1)
960
+ #expect(q.canNext == true)
961
+ #expect(q.canPrevious == true)
962
+ }
963
+
964
+ @Test func lastOfMany_repeatOff_previousOnly() {
965
+ let q = QueueManager()
966
+ q.setQueue(tracks("a", "b", "c"), initialIndex: 2)
967
+ #expect(q.canNext == false)
968
+ #expect(q.canPrevious == true)
969
+ }
970
+
971
+ @Test func lastOfMany_repeatQueue_bothTrue() {
972
+ let q = QueueManager()
973
+ q.setQueue(tracks("a", "b", "c"), initialIndex: 2)
974
+ q.repeatMode = .queue
975
+ #expect(q.canNext == true) // wraps to first
976
+ #expect(q.canPrevious == true)
977
+ }
978
+
979
+ @Test func firstOfMany_repeatQueue_bothTrue() {
980
+ let q = QueueManager()
981
+ q.setQueue(tracks("a", "b", "c"), initialIndex: 0)
982
+ q.repeatMode = .queue
983
+ #expect(q.canNext == true)
984
+ #expect(q.canPrevious == true) // wraps to last
985
+ }
986
+
987
+ // Shuffle wraps the playback order unconditionally (even with repeat off), so
988
+ // next()/previous() always move when count > 1 — canNext/canPrevious must
989
+ // agree at the shuffle-order boundaries, not grey out.
990
+ @Test func shuffleEnd_repeatOff_canNextTrue() {
991
+ let q = QueueManager()
992
+ q.setQueue(tracks("a", "b", "c", "d"))
993
+ q.shuffleEnabled = true
994
+ q.repeatMode = .off
995
+ while !q.isLastInPlaybackOrder {
996
+ _ = q.next()
997
+ } // advance to last in shuffle order
998
+ #expect(q.canNext == true) // next() wraps to the first shuffle position
999
+ }
1000
+
1001
+ @Test func shuffleStart_repeatOff_canPreviousTrue() {
1002
+ let q = QueueManager()
1003
+ q.setQueue(tracks("a", "b", "c", "d"))
1004
+ q.shuffleEnabled = true
1005
+ q.repeatMode = .off
1006
+ while !q.previousTracks.isEmpty {
1007
+ _ = q.previous()
1008
+ } // back to first in shuffle order
1009
+ #expect(q.canPrevious == true) // previous() wraps to the last shuffle position
1010
+ }
1011
+ }
@@ -4,7 +4,7 @@ import Testing
4
4
 
5
5
  private func makeResolvedTrack(
6
6
  url: String = "/test",
7
- title: String = "Test Track"
7
+ title: String = "Test Track",
8
8
  ) -> ResolvedTrack {
9
9
  ResolvedTrack(
10
10
  url: url,
@@ -26,7 +26,7 @@ private func makeResolvedTrack(
26
26
  favorited: nil,
27
27
  groupTitle: nil,
28
28
  live: nil,
29
- imageRow: nil
29
+ imageRow: nil,
30
30
  )
31
31
  }
32
32
 
@@ -35,8 +35,9 @@ private func makeFullResolvedTrack() -> ResolvedTrack {
35
35
  url: "/original",
36
36
  children: [Track(id: "t1", url: "/t1")],
37
37
  carPlaySiriListButton: .top,
38
+ id: "original-id",
38
39
  src: "src.mp3",
39
- artwork: "art.jpg",
40
+ artwork: .first("art.jpg"),
40
41
  artworkSource: ImageSource(uri: "resolved-art.jpg"),
41
42
  artworkCarPlayTinted: true,
42
43
  title: "Original Title",
@@ -51,7 +52,7 @@ private func makeFullResolvedTrack() -> ResolvedTrack {
51
52
  favorited: true,
52
53
  groupTitle: "Group A",
53
54
  live: false,
54
- imageRow: [ImageRowItem(title: "Row 1")]
55
+ imageRow: [ImageRowItem(title: "Row 1")],
55
56
  )
56
57
  }
57
58
 
@@ -95,10 +96,16 @@ private func makeFullResolvedTrack() -> ResolvedTrack {
95
96
  #expect(copy.src == "new-src.mp3")
96
97
  }
97
98
 
99
+ @Test func copyingOverridesId() {
100
+ let original = makeResolvedTrack()
101
+ let copy = original.copying(id: "new-id")
102
+ #expect(copy.id == "new-id")
103
+ }
104
+
98
105
  @Test func copyingOverridesArtwork() {
99
106
  let original = makeResolvedTrack()
100
- let copy = original.copying(artwork: "new-art.jpg")
101
- #expect(copy.artwork == "new-art.jpg")
107
+ let copy = original.copying(artwork: .some(.first("new-art.jpg")))
108
+ #expect(copy.artwork?.url == "new-art.jpg")
102
109
  }
103
110
 
104
111
  @Test func copyingOverridesArtworkSource() {
@@ -203,7 +210,7 @@ private func makeFullResolvedTrack() -> ResolvedTrack {
203
210
  title: "Updated Title",
204
211
  artist: "New Artist",
205
212
  duration: 240.0,
206
- favorited: true
213
+ favorited: true,
207
214
  )
208
215
  #expect(copy.url == "/updated")
209
216
  #expect(copy.title == "Updated Title")
@@ -227,7 +234,7 @@ private func makeFullResolvedTrack() -> ResolvedTrack {
227
234
  #expect(copy.children?.count == 1)
228
235
  #expect(copy.carPlaySiriListButton == .top)
229
236
  #expect(copy.src == "src.mp3")
230
- #expect(copy.artwork == "art.jpg")
237
+ #expect(copy.artwork?.url == "art.jpg")
231
238
  #expect(copy.artworkSource == ImageSource(uri: "resolved-art.jpg"))
232
239
  #expect(copy.artworkCarPlayTinted == true)
233
240
  #expect(copy.subtitle == "Original Subtitle")
@@ -0,0 +1,89 @@
1
+ import Foundation
2
+ import Testing
3
+
4
+ @testable import AudioBrowserTestable
5
+
6
+ private final class MockNetworkStatus: NetworkStatusProviding, @unchecked Sendable {
7
+ var isOnline: Bool
8
+ init(isOnline: Bool) { self.isOnline = isOnline }
9
+ }
10
+
11
+ /// The two duration budgets: a never-played load gives up fast while online; a
12
+ /// load that produced audio — or a device that is offline — keeps the full
13
+ /// recovery budget. Timing-based: budgets are configured in single-digit
14
+ /// milliseconds so one executed backoff (~1s) exhausts them.
15
+ @Suite("RetryManager budgets")
16
+ @MainActor
17
+ struct RetryManagerBudgetTests {
18
+ /// Returns the mock too — `networkMonitor` is weak, the test must keep it alive.
19
+ private func makeManager(
20
+ firstConnectMs: Double,
21
+ maxMs: Double = 120_000,
22
+ online: Bool,
23
+ ) -> (RetryManager, MockNetworkStatus) {
24
+ let manager = RetryManager()
25
+ manager.updatePolicy(from: .second(RetryConfig(
26
+ maxRetries: nil,
27
+ maxRetryDurationMs: maxMs,
28
+ firstConnectMaxRetryDurationMs: firstConnectMs,
29
+ )))
30
+ let network = MockNetworkStatus(isOnline: online)
31
+ manager.networkMonitor = network
32
+ return (manager, network)
33
+ }
34
+
35
+ /// A dead-on-arrival stream: the first attempt runs, and the budget refuses
36
+ /// a later one. Budgets are checked before AND after each backoff wait, so
37
+ /// the test budget must exceed the first backoff (~1s) for attempt one to
38
+ /// execute, and be exceeded by the cumulative ~2.5s before attempt two ends.
39
+ /// 1800ms sits ~800ms clear of the first backoff (sleep overshoot on a loaded
40
+ /// machine only widens the passing margins, never shrinks them into failure).
41
+ @Test func neverPlayedLoad_givesUpAfterFirstConnectBudget() async {
42
+ let (manager, network) = makeManager(firstConnectMs: 1800, online: true)
43
+ _ = network
44
+
45
+ #expect(await manager.attemptRetry(startFromCurrentTime: false) == true)
46
+ #expect(await manager.attemptRetry(startFromCurrentTime: false) == false)
47
+ }
48
+
49
+ /// The same failure timeline on a load that has produced audio keeps
50
+ /// retrying: only the recovery budget applies.
51
+ @Test func playedLoad_ignoresTheFirstConnectBudget() async {
52
+ let (manager, network) = makeManager(firstConnectMs: 500, online: true)
53
+ _ = network
54
+ manager.hasPlayed = true
55
+
56
+ #expect(await manager.attemptRetry(startFromCurrentTime: false) == true)
57
+ #expect(await manager.attemptRetry(startFromCurrentTime: false) == true)
58
+ }
59
+
60
+ /// Offline failures must not burn the first-connect budget (a station tapped
61
+ /// in a tunnel parks for connectivity); the budget's clock starts at the
62
+ /// first failure observed online, so a dead station still gets a fast
63
+ /// verdict after restoration.
64
+ @Test func offlineTime_doesNotBurnTheFirstConnectBudget() async {
65
+ // 4s: well above the ~2.3s backoff of the first online attempt (the ladder
66
+ // kept climbing while offline), well below the ~5.6s cumulative after it.
67
+ let (manager, network) = makeManager(firstConnectMs: 4000, online: false)
68
+
69
+ // Offline: the short budget never engages, attempts keep running.
70
+ #expect(await manager.attemptRetry(startFromCurrentTime: false) == true)
71
+ #expect(await manager.attemptRetry(startFromCurrentTime: false) == true)
72
+
73
+ // Connectivity returns: the short clock starts now — one more attempt
74
+ // runs, then the budget is spent.
75
+ network.isOnline = true
76
+ #expect(await manager.attemptRetry(startFromCurrentTime: false) == true)
77
+ #expect(await manager.attemptRetry(startFromCurrentTime: false) == false)
78
+ }
79
+
80
+ /// `reset()` (track change / budget refill) restarts the clocks but must NOT
81
+ /// touch `hasPlayed` — the refill runs mid-play, and clearing the flag there
82
+ /// would hand a playing stream the short budget on its next drop.
83
+ @Test func reset_keepsHasPlayed() {
84
+ let manager = RetryManager()
85
+ manager.hasPlayed = true
86
+ manager.reset()
87
+ #expect(manager.hasPlayed == true)
88
+ }
89
+ }
@@ -0,0 +1,63 @@
1
+ import Testing
2
+
3
+ @testable import AudioBrowserTestable
4
+
5
+ private struct Item: PlayableSearchItem {
6
+ let src: String?
7
+ let url: String?
8
+ }
9
+
10
+ @Suite("SearchDrillIn.playable")
11
+ struct SearchDrillInTests {
12
+ /// A resolver that fails the test if the drill-in path calls it.
13
+ private func unusedResolver(_ url: String) async throws -> [Item] {
14
+ Issue.record("resolveChildren should not have been called (url: \(url))")
15
+ return []
16
+ }
17
+
18
+ @Test func noResults_returnsNil() async throws {
19
+ let result = try await SearchDrillIn.playable(from: [Item](), resolveChildren: unusedResolver)
20
+ #expect(result == nil)
21
+ }
22
+
23
+ @Test func firstPlayable_returnsFlatPlayable_inOrder_withoutResolving() async throws {
24
+ let items = [
25
+ Item(src: "/a.mp3", url: nil),
26
+ Item(src: nil, url: "/page/x"), // browsable, filtered out
27
+ Item(src: "/b.mp3", url: nil),
28
+ ]
29
+ let result = try await SearchDrillIn.playable(from: items, resolveChildren: unusedResolver)
30
+ #expect(result?.compactMap(\.src) == ["/a.mp3", "/b.mp3"])
31
+ }
32
+
33
+ @Test func firstBrowsable_drillsIntoIt_andPlaysItsChildren() async throws {
34
+ let items = [
35
+ Item(src: nil, url: "/page/place"), // browsable first result
36
+ Item(src: "/later.mp3", url: nil), // would win without drill-in
37
+ ]
38
+ let result = try await SearchDrillIn.playable(from: items) { url in
39
+ #expect(url == "/page/place")
40
+ return [Item(src: "/station1.mp3", url: nil), Item(src: "/station2.mp3", url: nil)]
41
+ }
42
+ #expect(result?.compactMap(\.src) == ["/station1.mp3", "/station2.mp3"])
43
+ }
44
+
45
+ @Test func browsableDrillYieldsNothing_fallsBackToFlat() async throws {
46
+ let items = [
47
+ Item(src: nil, url: "/page/empty"),
48
+ Item(src: "/fallback.mp3", url: nil),
49
+ ]
50
+ let result = try await SearchDrillIn.playable(from: items) { _ in
51
+ [Item(src: nil, url: "/page/nested")] // nothing playable inside
52
+ }
53
+ #expect(result?.compactMap(\.src) == ["/fallback.mp3"])
54
+ }
55
+
56
+ @Test func nothingPlayableAnywhere_returnsNil() async throws {
57
+ let items = [Item(src: nil, url: "/page/a"), Item(src: nil, url: "/page/b")]
58
+ let result = try await SearchDrillIn.playable(from: items) { _ in
59
+ [Item(src: nil, url: "/page/nested")]
60
+ }
61
+ #expect(result == nil)
62
+ }
63
+ }
@@ -0,0 +1,82 @@
1
+ @testable import AudioBrowserTestable
2
+ import Testing
3
+
4
+ struct SectionScopeTests {
5
+ private func track(_ src: String, group: String? = nil) -> Track {
6
+ Track(id: src, src: src, groupTitle: group)
7
+ }
8
+
9
+ private func runSrcs(_ section: SectionScope.Section?) -> [String?]? {
10
+ guard case .run(let tracks) = section else { return nil }
11
+ return tracks.map(\.src)
12
+ }
13
+
14
+ private func imageRowSrcs(_ section: SectionScope.Section?) -> [String?]? {
15
+ guard case .imageRow(let items) = section else { return nil }
16
+ return items.map(\.src)
17
+ }
18
+
19
+ @Test func scopesToTheContiguousGroupTitleRun() {
20
+ let children = [
21
+ track("a", group: "First"),
22
+ track("b", group: "First"),
23
+ track("c", group: "Second"),
24
+ track("d", group: "Second"),
25
+ track("e"),
26
+ ]
27
+ #expect(runSrcs(SectionScope.section(of: children, containing: "c")) == ["c", "d"])
28
+ #expect(runSrcs(SectionScope.section(of: children, containing: "a")) == ["a", "b"])
29
+ }
30
+
31
+ @Test func ungroupedItemsFormTheirOwnRun() {
32
+ let children = [
33
+ track("a", group: "First"),
34
+ track("b"),
35
+ track("c"),
36
+ track("d", group: "Second"),
37
+ ]
38
+ #expect(runSrcs(SectionScope.section(of: children, containing: "b")) == ["b", "c"])
39
+ }
40
+
41
+ @Test func identicalTitlesInSeparateRunsStaySeparate() {
42
+ let children = [
43
+ track("a", group: "Same"),
44
+ track("x", group: "Other"),
45
+ track("b", group: "Same"),
46
+ ]
47
+ #expect(runSrcs(SectionScope.section(of: children, containing: "a")) == ["a"])
48
+ }
49
+
50
+ @Test func findsTheIdInsideAnImageRow() {
51
+ let items = [
52
+ ImageRowItem(src: "s1", title: "One"),
53
+ ImageRowItem(src: "s2", title: "Two"),
54
+ ]
55
+ var row = Track(id: "row", title: "Most Played")
56
+ row.imageRow = items
57
+ let children = [row, track("a")]
58
+ #expect(imageRowSrcs(SectionScope.section(of: children, containing: "s2")) == ["s1", "s2"])
59
+ }
60
+
61
+ @Test func unknownIdReturnsNil() {
62
+ #expect(SectionScope.section(of: [track("a")], containing: "zz") == nil)
63
+ }
64
+
65
+ // Pins the documented precedence: sections are located by src, and an id
66
+ // present in both an image row and the flat list resolves to the row.
67
+ @Test func imageRowWinsOverAFlatListDuplicate() {
68
+ var row = Track(id: "row", title: "Row")
69
+ row.imageRow = [ImageRowItem(src: "dup", title: "Dup")]
70
+ let children = [row, track("dup"), track("b")]
71
+ #expect(imageRowSrcs(SectionScope.section(of: children, containing: "dup")) == ["dup"])
72
+ }
73
+
74
+ @Test func duplicateSrcAcrossRunsResolvesToTheEarlierRun() {
75
+ let children = [
76
+ track("dup", group: "First"),
77
+ track("x", group: "Second"),
78
+ track("dup", group: "Second"),
79
+ ]
80
+ #expect(runSrcs(SectionScope.section(of: children, containing: "dup")) == ["dup"])
81
+ }
82
+ }