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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (975) hide show
  1. package/AudioBrowser.podspec +1 -1
  2. package/README.md +2 -180
  3. package/android/build.gradle +1 -17
  4. package/android/gradle.properties +1 -1
  5. package/android/src/main/AndroidManifest.xml +0 -15
  6. package/android/src/main/java/com/audiobrowser/AudioBrowser.kt +148 -433
  7. package/android/src/main/java/com/audiobrowser/Callbacks.kt +6 -4
  8. package/android/src/main/java/com/audiobrowser/Service.kt +18 -67
  9. package/android/src/main/java/com/audiobrowser/browser/BrowserManager.kt +178 -442
  10. package/android/src/main/java/com/audiobrowser/browser/JsonModels.kt +4 -41
  11. package/android/src/main/java/com/audiobrowser/browser/TrackLoadHandler.kt +4 -4
  12. package/android/src/main/java/com/audiobrowser/http/RequestConfigBuilder.kt +97 -109
  13. package/android/src/main/java/com/audiobrowser/model/PlaybackMetadata.kt +10 -6
  14. package/android/src/main/java/com/audiobrowser/model/PlayerSetupOptions.kt +8 -40
  15. package/android/src/main/java/com/audiobrowser/model/PlayerUpdateOptions.kt +46 -40
  16. package/android/src/main/java/com/audiobrowser/player/AutomaticBufferManager.kt +1 -4
  17. package/android/src/main/java/com/audiobrowser/player/DynamicLoadControl.kt +1 -18
  18. package/android/src/main/java/com/audiobrowser/player/MediaFactory.kt +3 -15
  19. package/android/src/main/java/com/audiobrowser/player/MediaSessionCallback.kt +134 -422
  20. package/android/src/main/java/com/audiobrowser/player/MediaSessionCommandManager.kt +404 -248
  21. package/android/src/main/java/com/audiobrowser/player/PlaybackProgressUpdateManager.kt +59 -0
  22. package/android/src/main/java/com/audiobrowser/player/PlaybackStateStore.kt +5 -25
  23. package/android/src/main/java/com/audiobrowser/player/Player.kt +582 -469
  24. package/android/src/main/java/com/audiobrowser/player/PlayerListener.kt +67 -190
  25. package/android/src/main/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicy.kt +53 -118
  26. package/android/src/main/java/com/audiobrowser/player/SleepTimer.kt +3 -37
  27. package/android/src/main/java/com/audiobrowser/player/TransformingDataSource.kt +40 -85
  28. package/android/src/main/java/com/audiobrowser/util/BrowserPathHelper.kt +0 -24
  29. package/android/src/main/java/com/audiobrowser/util/CoilBitmapLoader.kt +300 -23
  30. package/android/src/main/java/com/audiobrowser/util/EqualizerManager.kt +23 -13
  31. package/android/src/main/java/com/audiobrowser/util/MediaExtrasBuilder.kt +2 -2
  32. package/android/src/main/java/com/audiobrowser/util/MetadataAdapter.kt +3 -4
  33. package/android/src/main/java/com/audiobrowser/util/PlayingStateFactory.kt +1 -2
  34. package/android/src/main/java/com/audiobrowser/util/RatingFactory.kt +72 -0
  35. package/android/src/main/java/com/audiobrowser/util/ResolvedTrackFactory.kt +36 -0
  36. package/android/src/main/java/com/audiobrowser/util/SvgArtworkRenderer.kt +111 -6
  37. package/android/src/main/java/com/audiobrowser/util/SystemVolumeMonitor.kt +8 -22
  38. package/android/src/main/java/com/audiobrowser/util/TrackFactory.kt +80 -112
  39. package/android/src/main/res/values/strings.xml +0 -4
  40. package/android/src/test/java/com/audiobrowser/browser/BrowserManagerTest.kt +0 -4
  41. package/android/src/test/java/com/audiobrowser/browser/SimpleRouterTest.kt +2 -1
  42. package/android/src/test/java/com/audiobrowser/http/RequestConfigBuilderTest.kt +0 -72
  43. package/android/src/test/java/com/audiobrowser/player/PlaybackProgressUpdateManagerTest.kt +146 -0
  44. package/ios/Browser/BrowserConfig.swift +11 -41
  45. package/ios/Browser/BrowserManager+URLResolution.swift +93 -213
  46. package/ios/Browser/BrowserManager.swift +110 -303
  47. package/ios/Browser/BrowserPathHelper.swift +3 -32
  48. package/ios/Browser/JsonModels.swift +66 -287
  49. package/ios/CarPlay/CarPlayArtworkResolver.swift +6 -6
  50. package/ios/CarPlay/CarPlayController.swift +149 -739
  51. package/ios/CarPlay/CarPlayImageLoader.swift +8 -57
  52. package/ios/CarPlay/CarPlayListItemFactory.swift +35 -44
  53. package/ios/CarPlay/CarPlayNowPlayingManager.swift +36 -180
  54. package/ios/CarPlay/RNABAudioBrowser.h +10 -15
  55. package/ios/CarPlay/RNABAudioBrowser.m +14 -15
  56. package/ios/CarPlay/RNABCarPlaySceneDelegate.m +0 -2
  57. package/ios/CarPlay/RNABMediaIntentHandler.swift +43 -53
  58. package/ios/CarPlay/Track+CarPlay.swift +63 -0
  59. package/ios/Extension/Capability+RemoteCommand.swift +9 -7
  60. package/ios/Extension/ChapterMetadata+AVFoundation.swift +1 -1
  61. package/ios/Extension/NavigationError+Conversion.swift +1 -8
  62. package/ios/Extension/ResolvedTrack+Copying.swift +4 -10
  63. package/ios/Extension/TimedMetadata+AVFoundation.swift +1 -1
  64. package/ios/Extension/Track+AVPlayer.swift +4 -4
  65. package/ios/Extension/Track+Copying.swift +3 -9
  66. package/ios/Extension/TrackMetadata+AVFoundation.swift +1 -1
  67. package/ios/HybridAudioBrowser.swift +196 -804
  68. package/ios/Model/NitroTypeStubs.swift +224 -299
  69. package/ios/Model/PlayerUpdateOptions.swift +23 -23
  70. package/ios/Model/RemoteCommand.swift +6 -24
  71. package/ios/Model/TrackPlayerError.swift +18 -82
  72. package/ios/NowPlayingInfo/NowPlayingInfoCenter.swift +9 -0
  73. package/ios/NowPlayingInfo/NowPlayingInfoController.swift +121 -99
  74. package/ios/Observer/PlayerItemNotificationObserver.swift +5 -45
  75. package/ios/Observer/PlayerItemPropertyObserver.swift +4 -27
  76. package/ios/Observer/PlayerTimeObserver.swift +53 -3
  77. package/ios/Option/SessionCategories.swift +11 -34
  78. package/ios/Player/LoadSeekCoordinator.swift +1 -16
  79. package/ios/Player/MediaLoader.swift +11 -31
  80. package/ios/Player/NowPlayingUpdater.swift +26 -119
  81. package/ios/Player/PlaybackCoordinator.swift +51 -285
  82. package/ios/Player/PlaybackCoordinatorCallbacks.swift +1 -6
  83. package/ios/Player/PlaybackEffectHandler.swift +9 -19
  84. package/ios/Player/PlaybackErrorHandler.swift +13 -97
  85. package/ios/Player/PlaybackProgressUpdateManager.swift +68 -0
  86. package/ios/Player/PlaybackStateMachine.swift +13 -18
  87. package/ios/Player/PlayingStateManager.swift +2 -3
  88. package/ios/Player/QueueManager.swift +61 -67
  89. package/ios/Player/RetryManager.swift +21 -98
  90. package/ios/Player/SleepTimerHandling.swift +0 -8
  91. package/ios/Player/SleepTimerManager.swift +11 -72
  92. package/ios/RemoteCommand/RemoteCommandController.swift +21 -40
  93. package/ios/Tests/BrowserPathHelperTests.swift +0 -28
  94. package/ios/Tests/CarPlayArtworkResolverTests.swift +39 -39
  95. package/ios/Tests/ChapterMetadataAVFoundationTests.swift +2 -2
  96. package/ios/Tests/LoadSeekCoordinatorTests.swift +7 -40
  97. package/ios/Tests/MediaLoaderTests.swift +20 -32
  98. package/ios/Tests/PlaybackCoordinatorTests.swift +13 -787
  99. package/ios/Tests/PlaybackErrorHandlerTests.swift +46 -380
  100. package/ios/Tests/PlaybackProgressUpdateManagerTests.swift +166 -0
  101. package/ios/Tests/PlaybackStateMachineTests.swift +8 -33
  102. package/ios/Tests/QueueManagerTests.swift +18 -149
  103. package/ios/Tests/ResolvedTrackCopyingTests.swift +8 -15
  104. package/ios/Tests/Support/TestTypes.swift +20 -61
  105. package/ios/Tests/TrackSelectorTests.swift +15 -15
  106. package/ios/TrackPlayer.swift +58 -380
  107. package/ios/TrackPlayerCallbacks.swift +44 -5
  108. package/ios/TrackSelector.swift +5 -5
  109. package/ios/Util/ArtworkImageFetcher.swift +2 -4
  110. package/ios/Util/NetworkMonitor.swift +3 -7
  111. package/ios/Util/OnceValue.swift +0 -34
  112. package/lib/commonjs/AudioBrowser.js +11 -0
  113. package/lib/commonjs/AudioBrowser.js.map +1 -1
  114. package/lib/commonjs/features/browser.js +158 -59
  115. package/lib/commonjs/features/browser.js.map +1 -1
  116. package/lib/commonjs/features/equalizer.js +1 -1
  117. package/lib/commonjs/features/errors.js +5 -37
  118. package/lib/commonjs/features/errors.js.map +1 -1
  119. package/lib/commonjs/features/favorites.js +1 -1
  120. package/lib/commonjs/features/index.js +0 -22
  121. package/lib/commonjs/features/index.js.map +1 -1
  122. package/lib/commonjs/features/metadata.js +3 -3
  123. package/lib/commonjs/features/metadata.js.map +1 -1
  124. package/lib/commonjs/features/network.js +1 -1
  125. package/lib/commonjs/features/nowPlaying.js +1 -36
  126. package/lib/commonjs/features/nowPlaying.js.map +1 -1
  127. package/lib/commonjs/features/output.js +23 -37
  128. package/lib/commonjs/features/output.js.map +1 -1
  129. package/lib/commonjs/features/playback/controls.js +0 -9
  130. package/lib/commonjs/features/playback/controls.js.map +1 -1
  131. package/lib/commonjs/features/playback/index.js +0 -11
  132. package/lib/commonjs/features/playback/index.js.map +1 -1
  133. package/lib/commonjs/features/playback/playWhenReady.js +1 -1
  134. package/lib/commonjs/features/playback/playing.js +1 -1
  135. package/lib/commonjs/features/playback/progress.js +13 -29
  136. package/lib/commonjs/features/playback/progress.js.map +1 -1
  137. package/lib/commonjs/features/playback/state.js +1 -1
  138. package/lib/commonjs/features/playback/volume.js +2 -2
  139. package/lib/commonjs/features/player/options.js +29 -79
  140. package/lib/commonjs/features/player/options.js.map +1 -1
  141. package/lib/commonjs/features/player/setup.js +3 -256
  142. package/lib/commonjs/features/player/setup.js.map +1 -1
  143. package/lib/commonjs/features/queue/activeTrack.js +1 -1
  144. package/lib/commonjs/features/queue/queue.js +5 -12
  145. package/lib/commonjs/features/queue/queue.js.map +1 -1
  146. package/lib/commonjs/features/queue/repeatMode.js +1 -1
  147. package/lib/commonjs/features/queue/shuffle.js +1 -1
  148. package/lib/commonjs/features/rating.js +2 -0
  149. package/lib/commonjs/features/rating.js.map +1 -0
  150. package/lib/commonjs/features/remoteControls.js +104 -14
  151. package/lib/commonjs/features/remoteControls.js.map +1 -1
  152. package/lib/commonjs/features/sleepTimer.js +5 -10
  153. package/lib/commonjs/features/sleepTimer.js.map +1 -1
  154. package/lib/commonjs/native.js +0 -5
  155. package/lib/commonjs/native.js.map +1 -1
  156. package/lib/commonjs/native.web.js +1 -4
  157. package/lib/commonjs/native.web.js.map +1 -1
  158. package/lib/commonjs/types/player.js +2 -0
  159. package/lib/commonjs/types/player.js.map +1 -0
  160. package/lib/commonjs/utils/LazyNativeEmitter.js +8 -8
  161. package/lib/commonjs/utils/LazyNativeEmitter.js.map +1 -1
  162. package/lib/commonjs/utils/NativeUpdatedValue.js +3 -0
  163. package/lib/commonjs/utils/NativeUpdatedValue.js.map +1 -1
  164. package/lib/commonjs/web/NativeAudioBrowser.js +124 -301
  165. package/lib/commonjs/web/NativeAudioBrowser.js.map +1 -1
  166. package/lib/commonjs/web/SimpleRouter.test.js +174 -0
  167. package/lib/commonjs/web/SimpleRouter.test.js.map +1 -0
  168. package/lib/commonjs/web/TrackPlayer/Player.js +26 -90
  169. package/lib/commonjs/web/TrackPlayer/Player.js.map +1 -1
  170. package/lib/commonjs/web/TrackPlayer/PlaylistPlayer.js +293 -0
  171. package/lib/commonjs/web/TrackPlayer/PlaylistPlayer.js.map +1 -0
  172. package/lib/commonjs/web/TrackPlayer/RepeatMode.js +1 -1
  173. package/lib/commonjs/web/TrackPlayer/RepeatMode.js.map +1 -1
  174. package/lib/commonjs/web/TrackPlayer/SleepTimer.js +3 -34
  175. package/lib/commonjs/web/TrackPlayer/SleepTimer.js.map +1 -1
  176. package/lib/commonjs/web/TrackPlayer/index.js +5 -13
  177. package/lib/commonjs/web/TrackPlayer/index.js.map +1 -1
  178. package/lib/commonjs/web/browser/BrowserManager.js +50 -176
  179. package/lib/commonjs/web/browser/BrowserManager.js.map +1 -1
  180. package/lib/commonjs/web/browser/NavigationErrorManager.js +1 -3
  181. package/lib/commonjs/web/browser/NavigationErrorManager.js.map +1 -1
  182. package/lib/commonjs/web/browser/SearchManager.js +9 -11
  183. package/lib/commonjs/web/browser/SearchManager.js.map +1 -1
  184. package/lib/commonjs/web/http/HttpClient.js +23 -4
  185. package/lib/commonjs/web/http/HttpClient.js.map +1 -1
  186. package/lib/commonjs/web/http/RequestConfigBuilder.js +58 -107
  187. package/lib/commonjs/web/http/RequestConfigBuilder.js.map +1 -1
  188. package/lib/commonjs/web/player/NowPlayingManager.js +5 -6
  189. package/lib/commonjs/web/player/NowPlayingManager.js.map +1 -1
  190. package/lib/commonjs/web/player/OptionsManager.js +17 -9
  191. package/lib/commonjs/web/player/OptionsManager.js.map +1 -1
  192. package/lib/module/AudioBrowser.js +1 -4
  193. package/lib/module/AudioBrowser.js.map +1 -1
  194. package/lib/module/features/browser.js +156 -53
  195. package/lib/module/features/browser.js.map +1 -1
  196. package/lib/module/features/equalizer.js +1 -1
  197. package/lib/module/features/errors.js +5 -37
  198. package/lib/module/features/errors.js.map +1 -1
  199. package/lib/module/features/favorites.js +1 -1
  200. package/lib/module/features/index.js +0 -2
  201. package/lib/module/features/index.js.map +1 -1
  202. package/lib/module/features/metadata.js +3 -3
  203. package/lib/module/features/metadata.js.map +1 -1
  204. package/lib/module/features/network.js +1 -1
  205. package/lib/module/features/nowPlaying.js +1 -34
  206. package/lib/module/features/nowPlaying.js.map +1 -1
  207. package/lib/module/features/output.js +19 -32
  208. package/lib/module/features/output.js.map +1 -1
  209. package/lib/module/features/playback/controls.js +0 -8
  210. package/lib/module/features/playback/controls.js.map +1 -1
  211. package/lib/module/features/playback/index.js +0 -1
  212. package/lib/module/features/playback/index.js.map +1 -1
  213. package/lib/module/features/playback/playWhenReady.js +1 -1
  214. package/lib/module/features/playback/playing.js +1 -1
  215. package/lib/module/features/playback/progress.js +13 -29
  216. package/lib/module/features/playback/progress.js.map +1 -1
  217. package/lib/module/features/playback/state.js +1 -1
  218. package/lib/module/features/playback/volume.js +2 -2
  219. package/lib/module/features/player/options.js +29 -79
  220. package/lib/module/features/player/options.js.map +1 -1
  221. package/lib/module/features/player/setup.js +3 -256
  222. package/lib/module/features/player/setup.js.map +1 -1
  223. package/lib/module/features/queue/activeTrack.js +1 -1
  224. package/lib/module/features/queue/queue.js +5 -12
  225. package/lib/module/features/queue/queue.js.map +1 -1
  226. package/lib/module/features/queue/repeatMode.js +1 -1
  227. package/lib/module/features/queue/shuffle.js +1 -1
  228. package/lib/module/features/rating.js +2 -0
  229. package/lib/module/features/rating.js.map +1 -0
  230. package/lib/module/features/remoteControls.js +103 -13
  231. package/lib/module/features/remoteControls.js.map +1 -1
  232. package/lib/module/features/sleepTimer.js +5 -10
  233. package/lib/module/features/sleepTimer.js.map +1 -1
  234. package/lib/module/native.js +0 -5
  235. package/lib/module/native.js.map +1 -1
  236. package/lib/module/native.web.js +1 -4
  237. package/lib/module/native.web.js.map +1 -1
  238. package/lib/module/types/player.js +2 -0
  239. package/lib/module/types/player.js.map +1 -0
  240. package/lib/module/utils/LazyNativeEmitter.js +8 -8
  241. package/lib/module/utils/LazyNativeEmitter.js.map +1 -1
  242. package/lib/module/utils/NativeUpdatedValue.js +3 -0
  243. package/lib/module/utils/NativeUpdatedValue.js.map +1 -1
  244. package/lib/module/web/NativeAudioBrowser.js +125 -302
  245. package/lib/module/web/NativeAudioBrowser.js.map +1 -1
  246. package/lib/module/web/SimpleRouter.test.js +174 -0
  247. package/lib/module/web/SimpleRouter.test.js.map +1 -0
  248. package/lib/module/web/TrackPlayer/Player.js +26 -90
  249. package/lib/module/web/TrackPlayer/Player.js.map +1 -1
  250. package/lib/module/web/TrackPlayer/PlaylistPlayer.js +288 -0
  251. package/lib/module/web/TrackPlayer/PlaylistPlayer.js.map +1 -0
  252. package/lib/module/web/TrackPlayer/RepeatMode.js +1 -1
  253. package/lib/module/web/TrackPlayer/RepeatMode.js.map +1 -1
  254. package/lib/module/web/TrackPlayer/SleepTimer.js +3 -34
  255. package/lib/module/web/TrackPlayer/SleepTimer.js.map +1 -1
  256. package/lib/module/web/TrackPlayer/index.js +1 -2
  257. package/lib/module/web/TrackPlayer/index.js.map +1 -1
  258. package/lib/module/web/browser/BrowserManager.js +50 -176
  259. package/lib/module/web/browser/BrowserManager.js.map +1 -1
  260. package/lib/module/web/browser/NavigationErrorManager.js +1 -3
  261. package/lib/module/web/browser/NavigationErrorManager.js.map +1 -1
  262. package/lib/module/web/browser/SearchManager.js +9 -11
  263. package/lib/module/web/browser/SearchManager.js.map +1 -1
  264. package/lib/module/web/http/HttpClient.js +23 -4
  265. package/lib/module/web/http/HttpClient.js.map +1 -1
  266. package/lib/module/web/http/RequestConfigBuilder.js +58 -107
  267. package/lib/module/web/http/RequestConfigBuilder.js.map +1 -1
  268. package/lib/module/web/player/NowPlayingManager.js +5 -7
  269. package/lib/module/web/player/NowPlayingManager.js.map +1 -1
  270. package/lib/module/web/player/OptionsManager.js +17 -9
  271. package/lib/module/web/player/OptionsManager.js.map +1 -1
  272. package/lib/typescript/src/AudioBrowser.d.ts +1 -0
  273. package/lib/typescript/src/AudioBrowser.d.ts.map +1 -1
  274. package/lib/typescript/src/features/browser.d.ts +1 -40
  275. package/lib/typescript/src/features/browser.d.ts.map +1 -1
  276. package/lib/typescript/src/features/equalizer.d.ts +1 -1
  277. package/lib/typescript/src/features/errors.d.ts +6 -61
  278. package/lib/typescript/src/features/errors.d.ts.map +1 -1
  279. package/lib/typescript/src/features/favorites.d.ts +1 -1
  280. package/lib/typescript/src/features/index.d.ts +0 -2
  281. package/lib/typescript/src/features/index.d.ts.map +1 -1
  282. package/lib/typescript/src/features/metadata.d.ts +7 -9
  283. package/lib/typescript/src/features/metadata.d.ts.map +1 -1
  284. package/lib/typescript/src/features/network.d.ts +1 -1
  285. package/lib/typescript/src/features/nowPlaying.d.ts +1 -28
  286. package/lib/typescript/src/features/nowPlaying.d.ts.map +1 -1
  287. package/lib/typescript/src/features/output.d.ts +18 -28
  288. package/lib/typescript/src/features/output.d.ts.map +1 -1
  289. package/lib/typescript/src/features/playback/controls.d.ts +0 -5
  290. package/lib/typescript/src/features/playback/controls.d.ts.map +1 -1
  291. package/lib/typescript/src/features/playback/index.d.ts +0 -1
  292. package/lib/typescript/src/features/playback/index.d.ts.map +1 -1
  293. package/lib/typescript/src/features/playback/playWhenReady.d.ts +1 -1
  294. package/lib/typescript/src/features/playback/playing.d.ts +1 -1
  295. package/lib/typescript/src/features/playback/progress.d.ts +1 -4
  296. package/lib/typescript/src/features/playback/progress.d.ts.map +1 -1
  297. package/lib/typescript/src/features/playback/state.d.ts +1 -1
  298. package/lib/typescript/src/features/playback/volume.d.ts +2 -2
  299. package/lib/typescript/src/features/player/options.d.ts +127 -176
  300. package/lib/typescript/src/features/player/options.d.ts.map +1 -1
  301. package/lib/typescript/src/features/player/setup.d.ts +167 -213
  302. package/lib/typescript/src/features/player/setup.d.ts.map +1 -1
  303. package/lib/typescript/src/features/queue/activeTrack.d.ts +1 -1
  304. package/lib/typescript/src/features/queue/queue.d.ts +4 -11
  305. package/lib/typescript/src/features/queue/queue.d.ts.map +1 -1
  306. package/lib/typescript/src/features/queue/repeatMode.d.ts +1 -1
  307. package/lib/typescript/src/features/queue/shuffle.d.ts +1 -1
  308. package/lib/typescript/src/features/rating.d.ts +14 -0
  309. package/lib/typescript/src/features/rating.d.ts.map +1 -0
  310. package/lib/typescript/src/features/remoteControls.d.ts +35 -23
  311. package/lib/typescript/src/features/remoteControls.d.ts.map +1 -1
  312. package/lib/typescript/src/features/sleepTimer.d.ts +4 -19
  313. package/lib/typescript/src/features/sleepTimer.d.ts.map +1 -1
  314. package/lib/typescript/src/index.d.ts.map +1 -1
  315. package/lib/typescript/src/native.d.ts +2 -1
  316. package/lib/typescript/src/native.d.ts.map +1 -1
  317. package/lib/typescript/src/native.web.d.ts +3 -0
  318. package/lib/typescript/src/native.web.d.ts.map +1 -0
  319. package/lib/typescript/src/specs/audio-browser.nitro.d.ts +225 -17
  320. package/lib/typescript/src/specs/audio-browser.nitro.d.ts.map +1 -1
  321. package/lib/typescript/src/types/browser-native.d.ts +3 -9
  322. package/lib/typescript/src/types/browser-native.d.ts.map +1 -1
  323. package/lib/typescript/src/types/browser-nodes.d.ts +13 -145
  324. package/lib/typescript/src/types/browser-nodes.d.ts.map +1 -1
  325. package/lib/typescript/src/types/browser.d.ts +85 -349
  326. package/lib/typescript/src/types/browser.d.ts.map +1 -1
  327. package/lib/typescript/src/types/player.d.ts +64 -0
  328. package/lib/typescript/src/types/player.d.ts.map +1 -0
  329. package/lib/typescript/src/utils/LazyNativeEmitter.d.ts +6 -8
  330. package/lib/typescript/src/utils/LazyNativeEmitter.d.ts.map +1 -1
  331. package/lib/typescript/src/utils/NativeUpdatedValue.d.ts +2 -0
  332. package/lib/typescript/src/utils/NativeUpdatedValue.d.ts.map +1 -1
  333. package/lib/typescript/src/utils/resolveAssetSource.d.ts.map +1 -1
  334. package/lib/typescript/src/web/NativeAudioBrowser.d.ts +188 -0
  335. package/lib/typescript/src/web/NativeAudioBrowser.d.ts.map +1 -0
  336. package/lib/typescript/src/web/SimpleRouter.d.ts +40 -0
  337. package/lib/typescript/src/web/SimpleRouter.d.ts.map +1 -0
  338. package/lib/typescript/src/web/SimpleRouter.test.d.ts +2 -0
  339. package/lib/typescript/src/web/SimpleRouter.test.d.ts.map +1 -0
  340. package/lib/typescript/src/web/TrackPlayer/Event.d.ts +11 -0
  341. package/lib/typescript/src/web/TrackPlayer/Event.d.ts.map +1 -0
  342. package/lib/typescript/src/web/TrackPlayer/Player.d.ts +59 -0
  343. package/lib/typescript/src/web/TrackPlayer/Player.d.ts.map +1 -0
  344. package/lib/typescript/src/web/TrackPlayer/PlaylistPlayer.d.ts +39 -0
  345. package/lib/typescript/src/web/TrackPlayer/PlaylistPlayer.d.ts.map +1 -0
  346. package/lib/typescript/src/web/TrackPlayer/RepeatMode.d.ts +6 -0
  347. package/lib/typescript/src/web/TrackPlayer/RepeatMode.d.ts.map +1 -0
  348. package/lib/typescript/src/web/TrackPlayer/SetupNotCalledError.d.ts +4 -0
  349. package/lib/typescript/src/web/TrackPlayer/SetupNotCalledError.d.ts.map +1 -0
  350. package/lib/typescript/src/web/TrackPlayer/SleepTimer.d.ts +34 -0
  351. package/lib/typescript/src/web/TrackPlayer/SleepTimer.d.ts.map +1 -0
  352. package/lib/typescript/src/web/TrackPlayer/State.d.ts +13 -0
  353. package/lib/typescript/src/web/TrackPlayer/State.d.ts.map +1 -0
  354. package/lib/typescript/src/web/TrackPlayer/index.d.ts +5 -0
  355. package/lib/typescript/src/web/TrackPlayer/index.d.ts.map +1 -0
  356. package/lib/typescript/src/web/browser/BrowserManager.d.ts +154 -0
  357. package/lib/typescript/src/web/browser/BrowserManager.d.ts.map +1 -0
  358. package/lib/typescript/src/web/browser/FavoriteManager.d.ts +42 -0
  359. package/lib/typescript/src/web/browser/FavoriteManager.d.ts.map +1 -0
  360. package/lib/typescript/src/web/browser/NavigationErrorManager.d.ts +40 -0
  361. package/lib/typescript/src/web/browser/NavigationErrorManager.d.ts.map +1 -0
  362. package/lib/typescript/src/web/browser/SearchManager.d.ts +22 -0
  363. package/lib/typescript/src/web/browser/SearchManager.d.ts.map +1 -0
  364. package/lib/typescript/src/web/http/HttpClient.d.ts +25 -0
  365. package/lib/typescript/src/web/http/HttpClient.d.ts.map +1 -0
  366. package/lib/typescript/src/web/http/RequestConfigBuilder.d.ts +98 -0
  367. package/lib/typescript/src/web/http/RequestConfigBuilder.d.ts.map +1 -0
  368. package/lib/typescript/src/web/player/NowPlayingManager.d.ts +34 -0
  369. package/lib/typescript/src/web/player/NowPlayingManager.d.ts.map +1 -0
  370. package/lib/typescript/src/web/player/OptionsManager.d.ts +32 -0
  371. package/lib/typescript/src/web/player/OptionsManager.d.ts.map +1 -0
  372. package/lib/typescript/src/web/util/BrowserPathHelper.d.ts +69 -0
  373. package/lib/typescript/src/web/util/BrowserPathHelper.d.ts.map +1 -0
  374. package/lib/typescript/src/web/util/shuffle.d.ts +8 -0
  375. package/lib/typescript/src/web/util/shuffle.d.ts.map +1 -0
  376. package/nitrogen/generated/android/AudioBrowser+autolinking.cmake +2 -4
  377. package/nitrogen/generated/android/AudioBrowserOnLoad.cpp +10 -24
  378. package/nitrogen/generated/android/c++/JAndroidAudioContentType.hpp +6 -6
  379. package/nitrogen/generated/android/c++/JAndroidOptions.hpp +20 -10
  380. package/nitrogen/generated/android/c++/JAndroidUpdateOptions.hpp +86 -0
  381. package/nitrogen/generated/android/c++/JArtworkRequestConfig.hpp +1 -33
  382. package/nitrogen/generated/android/c++/JBrowseResult.hpp +0 -5
  383. package/nitrogen/generated/android/c++/JCarPlayNowPlayingButton.hpp +3 -3
  384. package/nitrogen/generated/android/c++/JFavoriteChangedEvent.hpp +0 -6
  385. package/nitrogen/generated/android/c++/JFormattedNavigationError.hpp +2 -3
  386. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____Track.hpp +0 -6
  387. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.hpp +147 -0
  388. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_Track______SearchParams.hpp +0 -8
  389. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_void_____TrackLoadEvent.hpp +0 -6
  390. package/nitrogen/generated/android/c++/JFunc_void_FavoriteChangedEvent.hpp +0 -6
  391. package/nitrogen/generated/android/c++/JFunc_void_IosOutput.hpp +80 -0
  392. package/nitrogen/generated/android/c++/JFunc_void_NowPlayingMetadata.hpp +10 -0
  393. package/nitrogen/generated/android/c++/JFunc_void_Options.hpp +9 -14
  394. package/nitrogen/generated/android/c++/JFunc_void_Playback.hpp +0 -2
  395. package/nitrogen/generated/android/c++/JFunc_void_PlaybackActiveTrackChangedEvent.hpp +0 -6
  396. package/nitrogen/generated/android/c++/JFunc_void_PlaybackErrorEvent.hpp +0 -2
  397. package/nitrogen/generated/android/c++/JFunc_void_RemoteSetRatingEvent.hpp +87 -0
  398. package/nitrogen/generated/android/c++/JFunc_void_bool.hpp +10 -10
  399. package/nitrogen/generated/android/c++/JFunc_void_std__optional_ResolvedTrack_.hpp +0 -6
  400. package/nitrogen/generated/android/c++/JFunc_void_std__vector_Track_.hpp +0 -6
  401. package/nitrogen/generated/android/c++/JHeartRating.hpp +57 -0
  402. package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.cpp +221 -245
  403. package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.hpp +22 -25
  404. package/nitrogen/generated/android/c++/JImageRowItem.hpp +3 -33
  405. package/nitrogen/generated/android/c++/{JOutput.hpp → JIosOutput.hpp} +15 -15
  406. package/nitrogen/generated/android/c++/JIosOutputType.hpp +85 -0
  407. package/nitrogen/generated/android/c++/JMediaRequestConfig.hpp +1 -33
  408. package/nitrogen/generated/android/c++/JNativeBrowserConfiguration.hpp +28 -61
  409. package/nitrogen/generated/android/c++/JNativeRouteEntry.hpp +9 -20
  410. package/nitrogen/generated/android/c++/JNativeUpdateOptions.hpp +24 -21
  411. package/nitrogen/generated/android/c++/JNavigationErrorType.hpp +0 -6
  412. package/nitrogen/generated/android/c++/JNitroAndroidUpdateOptions.hpp +20 -10
  413. package/nitrogen/generated/android/c++/{JRemoteButton.hpp → JNotificationButton.hpp} +20 -20
  414. package/nitrogen/generated/android/c++/JNotificationButtonLayout.hpp +94 -0
  415. package/nitrogen/generated/android/c++/JNowPlayingMetadata.hpp +17 -3
  416. package/nitrogen/generated/android/c++/JNowPlayingUpdate.hpp +3 -7
  417. package/nitrogen/generated/android/c++/JOptions.hpp +14 -19
  418. package/nitrogen/generated/android/c++/{JNativeAndroidSetupOptions.hpp → JPartialAndroidSetupPlayerOptions.hpp} +10 -10
  419. package/nitrogen/generated/android/c++/{JNativeIOSSetupOptions.hpp → JPartialIOSSetupPlayerOptions.hpp} +10 -10
  420. package/nitrogen/generated/android/c++/JPartialSetupPlayerOptions.hpp +96 -0
  421. package/nitrogen/generated/android/c++/JPercentageRating.hpp +57 -0
  422. package/nitrogen/generated/android/c++/JPlayback.hpp +0 -2
  423. package/nitrogen/generated/android/c++/JPlaybackActiveTrackChangedEvent.hpp +0 -6
  424. package/nitrogen/generated/android/c++/JPlaybackError.hpp +3 -18
  425. package/nitrogen/generated/android/c++/JPlaybackErrorEvent.hpp +0 -2
  426. package/nitrogen/generated/android/c++/JPlaybackState.hpp +3 -3
  427. package/nitrogen/generated/android/c++/JPlayerCapabilities.hpp +5 -11
  428. package/nitrogen/generated/android/c++/JRatingType.hpp +73 -0
  429. package/nitrogen/generated/android/c++/JRemoteSetRatingEvent.hpp +66 -0
  430. package/nitrogen/generated/android/c++/JResolvedTrack.hpp +5 -23
  431. package/nitrogen/generated/android/c++/JRetryConfig.hpp +7 -11
  432. package/nitrogen/generated/android/c++/JSearchMode.hpp +9 -27
  433. package/nitrogen/generated/android/c++/JSearchParams.hpp +3 -9
  434. package/nitrogen/generated/android/c++/JStarRating.hpp +57 -0
  435. package/nitrogen/generated/android/c++/{JGateEvent.hpp → JThumbsRating.hpp} +15 -16
  436. package/nitrogen/generated/android/c++/JTrack.hpp +5 -23
  437. package/nitrogen/generated/android/c++/JTrackLoadEvent.hpp +0 -6
  438. package/nitrogen/generated/android/c++/JTransformableRequestConfig.hpp +1 -14
  439. package/nitrogen/generated/android/c++/JUpdateOptions.hpp +105 -0
  440. package/nitrogen/generated/android/c++/JVariant_HeartRating_ThumbsRating_StarRating_PercentageRating.cpp +34 -0
  441. package/nitrogen/generated/android/c++/JVariant_HeartRating_ThumbsRating_StarRating_PercentageRating.hpp +105 -0
  442. package/nitrogen/generated/android/c++/JVariant_NullType_NotificationButtonLayout.cpp +26 -0
  443. package/nitrogen/generated/android/c++/JVariant_NullType_NotificationButtonLayout.hpp +75 -0
  444. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidAudioContentType.kt +4 -4
  445. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidOptions.kt +9 -3
  446. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidUpdateOptions.kt +50 -0
  447. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ArtworkRequestConfig.kt +4 -10
  448. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/CarPlayNowPlayingButton.kt +3 -3
  449. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormattedNavigationError.kt +2 -2
  450. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Func_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.kt → Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.kt} +12 -12
  451. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Func_void_Output.kt → Func_void_IosOutput.kt} +9 -9
  452. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Func_void_GateEvent.kt → Func_void_RemoteSetRatingEvent.kt} +9 -9
  453. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_bool.kt +9 -9
  454. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Gate.kt → HeartRating.kt} +6 -9
  455. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/HybridAudioBrowserSpec.kt +109 -103
  456. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageRowItem.kt +3 -24
  457. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Output.kt → IosOutput.kt} +6 -6
  458. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IosOutputType.kt +32 -0
  459. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaRequestConfig.kt +4 -10
  460. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeBrowserConfiguration.kt +6 -18
  461. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeRouteEntry.kt +4 -4
  462. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeUpdateOptions.kt +6 -6
  463. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NavigationErrorType.kt +1 -3
  464. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroAndroidUpdateOptions.kt +9 -3
  465. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{FavoritesMatchMode.kt → NotificationButton.kt} +8 -5
  466. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NotificationButtonLayout.kt +50 -0
  467. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingMetadata.kt +6 -3
  468. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingUpdate.kt +3 -6
  469. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Options.kt +3 -3
  470. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{NativeAndroidSetupOptions.kt → PartialAndroidSetupPlayerOptions.kt} +5 -5
  471. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{NativeIOSSetupOptions.kt → PartialIOSSetupPlayerOptions.kt} +5 -5
  472. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PartialSetupPlayerOptions.kt +47 -0
  473. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{GateDecision.kt → PercentageRating.kt} +6 -9
  474. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackError.kt +3 -12
  475. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackState.kt +6 -6
  476. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlayerCapabilities.kt +2 -2
  477. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{GateReason.kt → RatingType.kt} +10 -5
  478. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{ArtworkVariants.kt → RemoteSetRatingEvent.kt} +6 -9
  479. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ResolvedTrack.kt +3 -12
  480. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RetryConfig.kt +4 -7
  481. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SearchMode.kt +6 -12
  482. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SearchParams.kt +3 -6
  483. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{GateEvent.kt → StarRating.kt} +6 -6
  484. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{FavoriteConfig.kt → ThumbsRating.kt} +6 -6
  485. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Track.kt +3 -12
  486. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TransformableRequestConfig.kt +4 -7
  487. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/UpdateOptions.kt +53 -0
  488. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_HeartRating_ThumbsRating_StarRating_PercentageRating.kt +77 -0
  489. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Variant_NullType_RemoteButtonLayout.kt → Variant_NullType_NotificationButtonLayout.kt} +9 -9
  490. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.cpp +28 -139
  491. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.hpp +489 -1125
  492. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Umbrella.hpp +45 -66
  493. package/nitrogen/generated/ios/c++/HybridAudioBrowserSpecSwift.hpp +118 -176
  494. package/nitrogen/generated/ios/swift/AndroidAudioContentType.swift +8 -8
  495. package/nitrogen/generated/ios/swift/AndroidOptions.swift +22 -12
  496. package/nitrogen/generated/ios/swift/AndroidUpdateOptions.swift +119 -0
  497. package/nitrogen/generated/ios/swift/ArtworkRequestConfig.swift +1 -95
  498. package/nitrogen/generated/ios/swift/CarPlayNowPlayingButton.swift +4 -4
  499. package/nitrogen/generated/ios/swift/FormattedNavigationError.swift +4 -17
  500. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.swift +68 -0
  501. package/nitrogen/generated/ios/swift/{Func_void_Output.swift → Func_void_IosOutput.swift} +10 -10
  502. package/nitrogen/generated/ios/swift/{Func_void_GateEvent.swift → Func_void_RemoteSetRatingEvent.swift} +10 -10
  503. package/nitrogen/generated/ios/swift/Func_void_bool.swift +5 -5
  504. package/nitrogen/generated/ios/swift/{Func_void_std__shared_ptr_Promise_GateDecision__.swift → Func_void_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError___.swift} +17 -17
  505. package/nitrogen/generated/ios/swift/HeartRating.swift +29 -0
  506. package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec.swift +14 -20
  507. package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec_cxx.swift +197 -230
  508. package/nitrogen/generated/ios/swift/ImageRowItem.swift +2 -121
  509. package/nitrogen/generated/ios/swift/{Output.swift → IosOutput.swift} +7 -7
  510. package/nitrogen/generated/ios/swift/IosOutputType.swift +76 -0
  511. package/nitrogen/generated/ios/swift/MediaRequestConfig.swift +1 -107
  512. package/nitrogen/generated/ios/swift/NativeBrowserConfiguration.swift +22 -161
  513. package/nitrogen/generated/ios/swift/NativeRouteEntry.swift +19 -19
  514. package/nitrogen/generated/ios/swift/NativeUpdateOptions.swift +25 -12
  515. package/nitrogen/generated/ios/swift/NavigationErrorType.swift +0 -8
  516. package/nitrogen/generated/ios/swift/NitroAndroidUpdateOptions.swift +41 -12
  517. package/nitrogen/generated/ios/swift/{RemoteButton.swift → NotificationButton.swift} +10 -10
  518. package/nitrogen/generated/ios/swift/NotificationButtonLayout.swift +92 -0
  519. package/nitrogen/generated/ios/swift/NowPlayingMetadata.swift +48 -1
  520. package/nitrogen/generated/ios/swift/NowPlayingUpdate.swift +1 -19
  521. package/nitrogen/generated/ios/swift/Options.swift +4 -10
  522. package/nitrogen/generated/ios/swift/{NativeAndroidSetupOptions.swift → PartialAndroidSetupPlayerOptions.swift} +5 -5
  523. package/nitrogen/generated/ios/swift/{NativeIOSSetupOptions.swift → PartialIOSSetupPlayerOptions.swift} +5 -5
  524. package/nitrogen/generated/ios/swift/PartialSetupPlayerOptions.swift +101 -0
  525. package/nitrogen/generated/ios/swift/PercentageRating.swift +29 -0
  526. package/nitrogen/generated/ios/swift/PlaybackError.swift +2 -43
  527. package/nitrogen/generated/ios/swift/PlaybackState.swift +4 -4
  528. package/nitrogen/generated/ios/swift/PlayerCapabilities.swift +8 -27
  529. package/nitrogen/generated/ios/swift/RatingType.swift +60 -0
  530. package/nitrogen/generated/ios/swift/RemoteSetRatingEvent.swift +58 -0
  531. package/nitrogen/generated/ios/swift/ResolvedTrack.swift +8 -74
  532. package/nitrogen/generated/ios/swift/RetryConfig.swift +4 -35
  533. package/nitrogen/generated/ios/swift/SearchMode.swift +12 -36
  534. package/nitrogen/generated/ios/swift/SearchParams.swift +2 -7
  535. package/nitrogen/generated/ios/swift/StarRating.swift +29 -0
  536. package/nitrogen/generated/ios/swift/ThumbsRating.swift +29 -0
  537. package/nitrogen/generated/ios/swift/Track.swift +8 -74
  538. package/nitrogen/generated/ios/swift/TransformableRequestConfig.swift +1 -60
  539. package/nitrogen/generated/ios/swift/UpdateOptions.swift +143 -0
  540. package/nitrogen/generated/ios/swift/Variant_HeartRating_ThumbsRating_StarRating_PercentageRating.swift +20 -0
  541. package/nitrogen/generated/ios/swift/{Variant_NullType_RemoteButtonLayout.swift → Variant_NullType_NotificationButtonLayout.swift} +3 -3
  542. package/nitrogen/generated/shared/c++/AndroidAudioContentType.hpp +10 -10
  543. package/nitrogen/generated/shared/c++/AndroidOptions.hpp +19 -8
  544. package/nitrogen/generated/shared/c++/AndroidUpdateOptions.hpp +109 -0
  545. package/nitrogen/generated/shared/c++/ArtworkRequestConfig.hpp +2 -10
  546. package/nitrogen/generated/shared/c++/CarPlayNowPlayingButton.hpp +6 -6
  547. package/nitrogen/generated/shared/c++/EqualizerSettings.hpp +2 -0
  548. package/nitrogen/generated/shared/c++/FormattedNavigationError.hpp +5 -6
  549. package/nitrogen/generated/shared/c++/{GateEvent.hpp → HeartRating.hpp} +17 -18
  550. package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.cpp +18 -21
  551. package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.hpp +35 -44
  552. package/nitrogen/generated/shared/c++/ImageRowItem.hpp +2 -33
  553. package/nitrogen/generated/shared/c++/{Output.hpp → IosOutput.hpp} +18 -18
  554. package/nitrogen/generated/shared/c++/IosOutputType.hpp +112 -0
  555. package/nitrogen/generated/shared/c++/MediaRequestConfig.hpp +2 -10
  556. package/nitrogen/generated/shared/c++/NativeBrowserConfiguration.hpp +15 -31
  557. package/nitrogen/generated/shared/c++/NativeRouteEntry.hpp +5 -5
  558. package/nitrogen/generated/shared/c++/NativeUpdateOptions.hpp +7 -9
  559. package/nitrogen/generated/shared/c++/NavigationErrorType.hpp +0 -8
  560. package/nitrogen/generated/shared/c++/NitroAndroidUpdateOptions.hpp +19 -8
  561. package/nitrogen/generated/shared/c++/{RemoteButton.hpp → NotificationButton.hpp} +25 -25
  562. package/nitrogen/generated/shared/c++/NotificationButtonLayout.hpp +102 -0
  563. package/nitrogen/generated/shared/c++/NowPlayingMetadata.hpp +19 -3
  564. package/nitrogen/generated/shared/c++/NowPlayingUpdate.hpp +2 -6
  565. package/nitrogen/generated/shared/c++/Options.hpp +8 -8
  566. package/nitrogen/generated/shared/c++/{NativeAndroidSetupOptions.hpp → PartialAndroidSetupPlayerOptions.hpp} +11 -11
  567. package/nitrogen/generated/shared/c++/{NativeIOSSetupOptions.hpp → PartialIOSSetupPlayerOptions.hpp} +11 -11
  568. package/nitrogen/generated/shared/c++/PartialSetupPlayerOptions.hpp +104 -0
  569. package/nitrogen/generated/shared/c++/{FavoriteConfig.hpp → PercentageRating.hpp} +17 -18
  570. package/nitrogen/generated/shared/c++/PlaybackError.hpp +3 -18
  571. package/nitrogen/generated/shared/c++/PlaybackState.hpp +9 -9
  572. package/nitrogen/generated/shared/c++/PlayerCapabilities.hpp +6 -9
  573. package/nitrogen/generated/shared/c++/RatingType.hpp +96 -0
  574. package/nitrogen/generated/shared/c++/RemoteSetRatingEvent.hpp +94 -0
  575. package/nitrogen/generated/shared/c++/ResolvedTrack.hpp +5 -24
  576. package/nitrogen/generated/shared/c++/RetryConfig.hpp +6 -10
  577. package/nitrogen/generated/shared/c++/SearchMode.hpp +15 -39
  578. package/nitrogen/generated/shared/c++/SearchParams.hpp +2 -9
  579. package/nitrogen/generated/shared/c++/{Gate.hpp → StarRating.hpp} +16 -21
  580. package/nitrogen/generated/shared/c++/{GateDecision.hpp → ThumbsRating.hpp} +17 -23
  581. package/nitrogen/generated/shared/c++/Track.hpp +5 -24
  582. package/nitrogen/generated/shared/c++/TransformableRequestConfig.hpp +2 -6
  583. package/nitrogen/generated/shared/c++/UpdateOptions.hpp +111 -0
  584. package/package.json +5 -12
  585. package/src/AudioBrowser.ts +1 -4
  586. package/src/features/browser.ts +201 -58
  587. package/src/features/equalizer.ts +1 -1
  588. package/src/features/errors.ts +5 -71
  589. package/src/features/favorites.ts +1 -1
  590. package/src/features/index.ts +0 -2
  591. package/src/features/metadata.ts +15 -9
  592. package/src/features/network.ts +1 -1
  593. package/src/features/nowPlaying.ts +1 -37
  594. package/src/features/output.ts +22 -35
  595. package/src/features/playback/controls.ts +0 -8
  596. package/src/features/playback/index.ts +0 -1
  597. package/src/features/playback/playWhenReady.ts +1 -1
  598. package/src/features/playback/playing.ts +1 -1
  599. package/src/features/playback/progress.ts +13 -32
  600. package/src/features/playback/state.ts +1 -1
  601. package/src/features/playback/volume.ts +2 -2
  602. package/src/features/player/options.ts +110 -217
  603. package/src/features/player/setup.ts +175 -397
  604. package/src/features/queue/activeTrack.ts +1 -1
  605. package/src/features/queue/queue.ts +6 -17
  606. package/src/features/queue/repeatMode.ts +1 -1
  607. package/src/features/queue/shuffle.ts +1 -1
  608. package/src/features/rating.ts +17 -0
  609. package/src/features/remoteControls.ts +115 -13
  610. package/src/features/sleepTimer.ts +5 -24
  611. package/src/native.ts +0 -5
  612. package/src/native.web.ts +1 -4
  613. package/src/specs/audio-browser.nitro.ts +41 -131
  614. package/src/types/browser-native.ts +6 -19
  615. package/src/types/browser-nodes.ts +13 -160
  616. package/src/types/browser.ts +89 -377
  617. package/src/types/player.ts +69 -0
  618. package/src/utils/LazyNativeEmitter.ts +8 -9
  619. package/src/utils/NativeUpdatedValue.ts +2 -0
  620. package/src/web/NativeAudioBrowser.ts +158 -365
  621. package/src/web/TrackPlayer/Player.ts +39 -113
  622. package/src/web/TrackPlayer/PlaylistPlayer.ts +346 -0
  623. package/src/web/TrackPlayer/RepeatMode.ts +1 -1
  624. package/src/web/TrackPlayer/SleepTimer.ts +3 -38
  625. package/src/web/TrackPlayer/index.ts +1 -2
  626. package/src/web/browser/BrowserManager.ts +62 -231
  627. package/src/web/browser/NavigationErrorManager.ts +1 -3
  628. package/src/web/browser/SearchManager.ts +15 -11
  629. package/src/web/http/HttpClient.ts +35 -5
  630. package/src/web/http/RequestConfigBuilder.ts +63 -120
  631. package/src/web/player/NowPlayingManager.ts +5 -6
  632. package/src/web/player/OptionsManager.ts +18 -12
  633. package/android/src/main/java/com/audiobrowser/ServiceBinding.kt +0 -46
  634. package/android/src/main/java/com/audiobrowser/browser/ArtworkResolutionRegistry.kt +0 -37
  635. package/android/src/main/java/com/audiobrowser/browser/BrowseArtworkRegistry.kt +0 -34
  636. package/android/src/main/java/com/audiobrowser/browser/BrowserUrlResolution.kt +0 -299
  637. package/android/src/main/java/com/audiobrowser/browser/JsonArtwork.kt +0 -79
  638. package/android/src/main/java/com/audiobrowser/browser/SectionScope.kt +0 -42
  639. package/android/src/main/java/com/audiobrowser/extension/ResolvedTrackExt.kt +0 -35
  640. package/android/src/main/java/com/audiobrowser/player/CapabilityControls.kt +0 -172
  641. package/android/src/main/java/com/audiobrowser/player/EqualizerController.kt +0 -153
  642. package/android/src/main/java/com/audiobrowser/player/InterceptingPlayer.kt +0 -141
  643. package/android/src/main/java/com/audiobrowser/player/NowPlayingUpdater.kt +0 -347
  644. package/android/src/main/java/com/audiobrowser/player/PlaybackErrorClassifier.kt +0 -129
  645. package/android/src/main/java/com/audiobrowser/player/PlaybackStateMachine.kt +0 -85
  646. package/android/src/main/java/com/audiobrowser/player/PlaybackTimer.kt +0 -56
  647. package/android/src/main/java/com/audiobrowser/player/PlayerCapabilitiesExt.kt +0 -20
  648. package/android/src/main/java/com/audiobrowser/player/PlayerEngineFactory.kt +0 -130
  649. package/android/src/main/java/com/audiobrowser/player/SleepTimerManager.kt +0 -80
  650. package/android/src/main/java/com/audiobrowser/player/StuckRecoveryPolicy.kt +0 -50
  651. package/android/src/main/java/com/audiobrowser/player/VolumeFader.kt +0 -81
  652. package/android/src/main/java/com/audiobrowser/tls/AiaCertChaser.kt +0 -141
  653. package/android/src/main/java/com/audiobrowser/tls/AiaChasingTrustManager.kt +0 -37
  654. package/android/src/main/java/com/audiobrowser/tls/AiaTls.kt +0 -41
  655. package/android/src/main/java/com/audiobrowser/tls/CachingCertificateFetcher.kt +0 -209
  656. package/android/src/main/java/com/audiobrowser/util/ArtworkContentProvider.kt +0 -161
  657. package/android/src/main/java/com/audiobrowser/util/ArtworkUris.kt +0 -28
  658. package/android/src/main/java/com/audiobrowser/util/ArtworkVariant.kt +0 -24
  659. package/android/src/main/java/com/audiobrowser/util/CoilArtworkLoader.kt +0 -49
  660. package/android/src/main/java/com/audiobrowser/util/CoilArtworkLoaderHolder.kt +0 -36
  661. package/android/src/main/java/com/audiobrowser/util/OutputMonitor.kt +0 -211
  662. package/android/src/main/java/com/audiobrowser/util/OutputSwitcher.kt +0 -58
  663. package/android/src/main/java/com/audiobrowser/util/RatingFavorites.kt +0 -14
  664. package/android/src/test/java/com/audiobrowser/ServiceBindingTest.kt +0 -68
  665. package/android/src/test/java/com/audiobrowser/TestFixtures.kt +0 -165
  666. package/android/src/test/java/com/audiobrowser/browser/ArtworkResolutionRegistryTest.kt +0 -46
  667. package/android/src/test/java/com/audiobrowser/browser/BrowseArtworkRegistryTest.kt +0 -39
  668. package/android/src/test/java/com/audiobrowser/browser/BrowserManagerBuildApiRequestTest.kt +0 -114
  669. package/android/src/test/java/com/audiobrowser/browser/BrowserManagerLayerResolutionTest.kt +0 -141
  670. package/android/src/test/java/com/audiobrowser/browser/BrowserUrlResolutionTest.kt +0 -177
  671. package/android/src/test/java/com/audiobrowser/browser/JsonArtworkTest.kt +0 -55
  672. package/android/src/test/java/com/audiobrowser/browser/SectionScopeTest.kt +0 -94
  673. package/android/src/test/java/com/audiobrowser/player/CapabilityControlsTest.kt +0 -203
  674. package/android/src/test/java/com/audiobrowser/player/DynamicLoadControlTest.kt +0 -56
  675. package/android/src/test/java/com/audiobrowser/player/EqualizerControllerTest.kt +0 -216
  676. package/android/src/test/java/com/audiobrowser/player/MediaSessionSlotMappingTest.kt +0 -45
  677. package/android/src/test/java/com/audiobrowser/player/NowPlayingUpdaterTest.kt +0 -442
  678. package/android/src/test/java/com/audiobrowser/player/PlaybackErrorClassifierTest.kt +0 -190
  679. package/android/src/test/java/com/audiobrowser/player/PlaybackStateMachineTest.kt +0 -198
  680. package/android/src/test/java/com/audiobrowser/player/PlaybackTimerTest.kt +0 -137
  681. package/android/src/test/java/com/audiobrowser/player/PlayerEngineFactoryTest.kt +0 -36
  682. package/android/src/test/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicyTest.kt +0 -268
  683. package/android/src/test/java/com/audiobrowser/player/SessionErrorMaskTest.kt +0 -68
  684. package/android/src/test/java/com/audiobrowser/player/StuckRecoveryPolicyTest.kt +0 -40
  685. package/android/src/test/java/com/audiobrowser/player/TransformingDataSourceTest.kt +0 -193
  686. package/android/src/test/java/com/audiobrowser/tls/AiaCertChaserTest.kt +0 -107
  687. package/android/src/test/java/com/audiobrowser/tls/AiaChasingTrustManagerTest.kt +0 -73
  688. package/android/src/test/java/com/audiobrowser/tls/CachingCertificateFetcherTest.kt +0 -75
  689. package/android/src/test/java/com/audiobrowser/tls/CertFixtures.kt +0 -18
  690. package/android/src/test/java/com/audiobrowser/util/ArtworkContentProviderTest.kt +0 -163
  691. package/android/src/test/java/com/audiobrowser/util/ArtworkUrisTest.kt +0 -34
  692. package/android/src/test/java/com/audiobrowser/util/BrowserPathHelperTest.kt +0 -28
  693. package/android/src/test/java/com/audiobrowser/util/CoilArtworkLoaderHolderTest.kt +0 -53
  694. package/android/src/test/java/com/audiobrowser/util/CoilArtworkLoaderTest.kt +0 -58
  695. package/android/src/test/java/com/audiobrowser/util/FakeImageLoader.kt +0 -57
  696. package/android/src/test/java/com/audiobrowser/util/PlayingStateFactoryTest.kt +0 -40
  697. package/android/src/test/java/com/audiobrowser/util/RatingFavoritesTest.kt +0 -34
  698. package/android/src/test/java/com/audiobrowser/util/TrackFactoryBrowseTest.kt +0 -50
  699. package/android/src/test/java/com/audiobrowser/util/TrackFactoryMediaIdTest.kt +0 -63
  700. package/android/src/test/java/com/audiobrowser/util/TrackFactoryRatingTest.kt +0 -35
  701. package/android/src/test/resources/certs/isrg-root-x1.pem +0 -31
  702. package/android/src/test/resources/certs/letsencrypt-r13.der +0 -0
  703. package/android/src/test/resources/certs/letsencrypt-r13.pem +0 -29
  704. package/android/src/test/resources/certs/stationplaylist-leaf.pem +0 -34
  705. package/ios/Browser/MediaResolveComposer.swift +0 -114
  706. package/ios/Browser/SearchDrillIn.swift +0 -44
  707. package/ios/Browser/SectionScope.swift +0 -35
  708. package/ios/Browser/TabBarEntries.swift +0 -15
  709. package/ios/CarPlay/CPInterfaceController+Safe.swift +0 -126
  710. package/ios/CarPlay/ImageRowItem+CarPlay.swift +0 -19
  711. package/ios/CarPlay/RNABMediaAddHandler.swift +0 -75
  712. package/ios/CarPlay/RNABMediaAffinityHandler.swift +0 -69
  713. package/ios/Extension/PlayerCapabilities+Favorite.swift +0 -20
  714. package/ios/Extension/RequestConfig+Copying.swift +0 -31
  715. package/ios/Extension/Variant+Artwork.swift +0 -49
  716. package/ios/NowPlayingInfo/SilentAudioPrimer.swift +0 -73
  717. package/ios/Player/AirPlayStallJudgement.swift +0 -25
  718. package/ios/Player/EndOfTrackJudgement.swift +0 -32
  719. package/ios/Player/MediaIntentCriteria.swift +0 -139
  720. package/ios/Player/PersistedPlaybackState.swift +0 -11
  721. package/ios/Player/PlaybackStateStore.swift +0 -27
  722. package/ios/Player/PlaybackTimer.swift +0 -61
  723. package/ios/Player/VolumeFader.swift +0 -77
  724. package/ios/RemoteCommand/RemoteCommandCallbacks.swift +0 -47
  725. package/ios/Tests/AirPlayStallJudgementTests.swift +0 -52
  726. package/ios/Tests/EndOfTrackJudgementTests.swift +0 -35
  727. package/ios/Tests/JsonModelsTests.swift +0 -58
  728. package/ios/Tests/MediaIntentCriteriaTests.swift +0 -170
  729. package/ios/Tests/MediaLoaderAssetOptionsTests.swift +0 -46
  730. package/ios/Tests/MediaResolveTests.swift +0 -126
  731. package/ios/Tests/OnceValueTests.swift +0 -79
  732. package/ios/Tests/PlaybackStateStoreTests.swift +0 -48
  733. package/ios/Tests/PlaybackTimerTests.swift +0 -55
  734. package/ios/Tests/PlayingStateManagerTests.swift +0 -57
  735. package/ios/Tests/RemoteCommandControllerTests.swift +0 -156
  736. package/ios/Tests/RemoteCommandTests.swift +0 -67
  737. package/ios/Tests/RetryManagerTests.swift +0 -89
  738. package/ios/Tests/SearchDrillInTests.swift +0 -63
  739. package/ios/Tests/SectionScopeTests.swift +0 -82
  740. package/ios/Tests/SleepTimerManagerTests.swift +0 -107
  741. package/ios/Tests/Support/ManualSleepTimerScheduler.swift +0 -47
  742. package/ios/Tests/TabBarEntriesTests.swift +0 -71
  743. package/lib/commonjs/features/browser-config.js +0 -227
  744. package/lib/commonjs/features/browser-config.js.map +0 -1
  745. package/lib/commonjs/features/carConnection.js +0 -42
  746. package/lib/commonjs/features/carConnection.js.map +0 -1
  747. package/lib/commonjs/features/gate.js +0 -149
  748. package/lib/commonjs/features/gate.js.map +0 -1
  749. package/lib/commonjs/features/playback/trackPlaybackTime.js +0 -86
  750. package/lib/commonjs/features/playback/trackPlaybackTime.js.map +0 -1
  751. package/lib/commonjs/features/player/validateOptions.js +0 -24
  752. package/lib/commonjs/features/player/validateOptions.js.map +0 -1
  753. package/lib/commonjs/utils/artwork.js +0 -31
  754. package/lib/commonjs/utils/artwork.js.map +0 -1
  755. package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js +0 -71
  756. package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js.map +0 -1
  757. package/lib/commonjs/web/TrackPlayer/PlaybackTimer.js +0 -34
  758. package/lib/commonjs/web/TrackPlayer/PlaybackTimer.js.map +0 -1
  759. package/lib/commonjs/web/TrackPlayer/PlayingStateFactory.js +0 -21
  760. package/lib/commonjs/web/TrackPlayer/PlayingStateFactory.js.map +0 -1
  761. package/lib/commonjs/web/TrackPlayer/QueueManager.js +0 -273
  762. package/lib/commonjs/web/TrackPlayer/QueueManager.js.map +0 -1
  763. package/lib/commonjs/web/TrackPlayer/QueuePlayer.js +0 -158
  764. package/lib/commonjs/web/TrackPlayer/QueuePlayer.js.map +0 -1
  765. package/lib/commonjs/web/TrackPlayer/VolumeFader.js +0 -75
  766. package/lib/commonjs/web/TrackPlayer/VolumeFader.js.map +0 -1
  767. package/lib/commonjs/web/browser/assertBrowsePageShape.js +0 -22
  768. package/lib/commonjs/web/browser/assertBrowsePageShape.js.map +0 -1
  769. package/lib/commonjs/web/browser/classifyTrackNavigation.js +0 -41
  770. package/lib/commonjs/web/browser/classifyTrackNavigation.js.map +0 -1
  771. package/lib/commonjs/web/browser/parseSearchResponse.js +0 -20
  772. package/lib/commonjs/web/browser/parseSearchResponse.js.map +0 -1
  773. package/lib/commonjs/web/playbackErrorKind.js +0 -57
  774. package/lib/commonjs/web/playbackErrorKind.js.map +0 -1
  775. package/lib/commonjs/web/player/MediaSessionManager.js +0 -121
  776. package/lib/commonjs/web/player/MediaSessionManager.js.map +0 -1
  777. package/lib/commonjs/web/player/RemoteCommandController.js +0 -96
  778. package/lib/commonjs/web/player/RemoteCommandController.js.map +0 -1
  779. package/lib/module/features/browser-config.js +0 -221
  780. package/lib/module/features/browser-config.js.map +0 -1
  781. package/lib/module/features/carConnection.js +0 -37
  782. package/lib/module/features/carConnection.js.map +0 -1
  783. package/lib/module/features/gate.js +0 -144
  784. package/lib/module/features/gate.js.map +0 -1
  785. package/lib/module/features/playback/trackPlaybackTime.js +0 -83
  786. package/lib/module/features/playback/trackPlaybackTime.js.map +0 -1
  787. package/lib/module/features/player/validateOptions.js +0 -20
  788. package/lib/module/features/player/validateOptions.js.map +0 -1
  789. package/lib/module/utils/artwork.js +0 -26
  790. package/lib/module/utils/artwork.js.map +0 -1
  791. package/lib/module/web/TrackPlayer/PlaybackStateMachine.js +0 -67
  792. package/lib/module/web/TrackPlayer/PlaybackStateMachine.js.map +0 -1
  793. package/lib/module/web/TrackPlayer/PlaybackTimer.js +0 -29
  794. package/lib/module/web/TrackPlayer/PlaybackTimer.js.map +0 -1
  795. package/lib/module/web/TrackPlayer/PlayingStateFactory.js +0 -17
  796. package/lib/module/web/TrackPlayer/PlayingStateFactory.js.map +0 -1
  797. package/lib/module/web/TrackPlayer/QueueManager.js +0 -269
  798. package/lib/module/web/TrackPlayer/QueueManager.js.map +0 -1
  799. package/lib/module/web/TrackPlayer/QueuePlayer.js +0 -154
  800. package/lib/module/web/TrackPlayer/QueuePlayer.js.map +0 -1
  801. package/lib/module/web/TrackPlayer/VolumeFader.js +0 -70
  802. package/lib/module/web/TrackPlayer/VolumeFader.js.map +0 -1
  803. package/lib/module/web/browser/assertBrowsePageShape.js +0 -18
  804. package/lib/module/web/browser/assertBrowsePageShape.js.map +0 -1
  805. package/lib/module/web/browser/classifyTrackNavigation.js +0 -38
  806. package/lib/module/web/browser/classifyTrackNavigation.js.map +0 -1
  807. package/lib/module/web/browser/parseSearchResponse.js +0 -16
  808. package/lib/module/web/browser/parseSearchResponse.js.map +0 -1
  809. package/lib/module/web/playbackErrorKind.js +0 -52
  810. package/lib/module/web/playbackErrorKind.js.map +0 -1
  811. package/lib/module/web/player/MediaSessionManager.js +0 -116
  812. package/lib/module/web/player/MediaSessionManager.js.map +0 -1
  813. package/lib/module/web/player/RemoteCommandController.js +0 -92
  814. package/lib/module/web/player/RemoteCommandController.js.map +0 -1
  815. package/lib/typescript/src/features/browser-config.d.ts +0 -12
  816. package/lib/typescript/src/features/browser-config.d.ts.map +0 -1
  817. package/lib/typescript/src/features/carConnection.d.ts +0 -20
  818. package/lib/typescript/src/features/carConnection.d.ts.map +0 -1
  819. package/lib/typescript/src/features/gate.d.ts +0 -78
  820. package/lib/typescript/src/features/gate.d.ts.map +0 -1
  821. package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts +0 -34
  822. package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts.map +0 -1
  823. package/lib/typescript/src/features/player/validateOptions.d.ts +0 -2
  824. package/lib/typescript/src/features/player/validateOptions.d.ts.map +0 -1
  825. package/lib/typescript/src/utils/artwork.d.ts +0 -19
  826. package/lib/typescript/src/utils/artwork.d.ts.map +0 -1
  827. package/nitrogen/generated/android/c++/JArtworkVariants.hpp +0 -61
  828. package/nitrogen/generated/android/c++/JFavoriteConfig.hpp +0 -58
  829. package/nitrogen/generated/android/c++/JFavoritesMatchMode.hpp +0 -58
  830. package/nitrogen/generated/android/c++/JFormatNowPlayingParams.hpp +0 -100
  831. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.hpp +0 -112
  832. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___RequestConfig_std__optional_std__unordered_map_std__string__std__string__.hpp +0 -121
  833. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___Track.hpp +0 -123
  834. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.hpp +0 -133
  835. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_std__string____Track.hpp +0 -121
  836. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.hpp +0 -139
  837. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.hpp +0 -134
  838. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.hpp +0 -131
  839. package/nitrogen/generated/android/c++/JFunc_void_GateEvent.hpp +0 -79
  840. package/nitrogen/generated/android/c++/JFunc_void_Output.hpp +0 -80
  841. package/nitrogen/generated/android/c++/JGate.hpp +0 -62
  842. package/nitrogen/generated/android/c++/JGateDecision.hpp +0 -64
  843. package/nitrogen/generated/android/c++/JGateReason.hpp +0 -58
  844. package/nitrogen/generated/android/c++/JIOSOptions.hpp +0 -95
  845. package/nitrogen/generated/android/c++/JMediaReference.hpp +0 -58
  846. package/nitrogen/generated/android/c++/JNativeGateRequest.hpp +0 -74
  847. package/nitrogen/generated/android/c++/JNativeSetupPlayerOptions.hpp +0 -182
  848. package/nitrogen/generated/android/c++/JNitroIOSUpdateOptions.hpp +0 -96
  849. package/nitrogen/generated/android/c++/JOutputType.hpp +0 -82
  850. package/nitrogen/generated/android/c++/JPlaybackErrorKind.hpp +0 -76
  851. package/nitrogen/generated/android/c++/JRemoteButtonLayout.hpp +0 -86
  852. package/nitrogen/generated/android/c++/JStallReason.hpp +0 -58
  853. package/nitrogen/generated/android/c++/JTrackRequest.hpp +0 -93
  854. package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.cpp +0 -26
  855. package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.hpp +0 -71
  856. package/nitrogen/generated/android/c++/JVariant_NullType_RemoteButtonLayout.cpp +0 -26
  857. package/nitrogen/generated/android/c++/JVariant_NullType_RemoteButtonLayout.hpp +0 -75
  858. package/nitrogen/generated/android/c++/JVariant_ResolvedTrack_BrowseError_Promise_BrowseResult_.cpp +0 -41
  859. package/nitrogen/generated/android/c++/JVariant_ResolvedTrack_BrowseError_Promise_BrowseResult_.hpp +0 -121
  860. package/nitrogen/generated/android/c++/JVariant_String_ArtworkVariants.cpp +0 -26
  861. package/nitrogen/generated/android/c++/JVariant_String_ArtworkVariants.hpp +0 -70
  862. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormatNowPlayingParams.kt +0 -50
  863. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.kt +0 -80
  864. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___RequestConfig_std__optional_std__unordered_map_std__string__std__string__.kt +0 -80
  865. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___Track.kt +0 -80
  866. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.kt +0 -80
  867. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_std__string____Track.kt +0 -80
  868. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.kt +0 -80
  869. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.kt +0 -80
  870. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IOSOptions.kt +0 -44
  871. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaReference.kt +0 -23
  872. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeGateRequest.kt +0 -44
  873. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeSetupPlayerOptions.kt +0 -66
  874. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroIOSUpdateOptions.kt +0 -44
  875. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/OutputType.kt +0 -31
  876. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackErrorKind.kt +0 -29
  877. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteButton.kt +0 -26
  878. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteButtonLayout.kt +0 -44
  879. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/StallReason.kt +0 -23
  880. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackRequest.kt +0 -44
  881. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_Boolean_FavoriteConfig.kt +0 -53
  882. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_ResolvedTrack_BrowseError_Promise_BrowseResult_.kt +0 -65
  883. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_String_ArtworkVariants.kt +0 -53
  884. package/nitrogen/generated/ios/swift/ArtworkVariants.swift +0 -34
  885. package/nitrogen/generated/ios/swift/FavoriteConfig.swift +0 -29
  886. package/nitrogen/generated/ios/swift/FavoritesMatchMode.swift +0 -40
  887. package/nitrogen/generated/ios/swift/FormatNowPlayingParams.swift +0 -67
  888. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.swift +0 -54
  889. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_RequestConfig___RequestConfig_std__optional_std__unordered_map_std__string__std__string__.swift +0 -69
  890. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_RequestConfig___Track.swift +0 -54
  891. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.swift +0 -60
  892. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__optional_std__string____Track.swift +0 -60
  893. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.swift +0 -61
  894. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.swift +0 -61
  895. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.swift +0 -77
  896. package/nitrogen/generated/ios/swift/Func_void_GateDecision.swift +0 -46
  897. package/nitrogen/generated/ios/swift/Func_void_TransformableRequestConfig.swift +0 -46
  898. package/nitrogen/generated/ios/swift/Func_void_std__optional_NowPlayingUpdate_.swift +0 -46
  899. package/nitrogen/generated/ios/swift/Func_void_std__optional_std__string_.swift +0 -53
  900. package/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_TransformableRequestConfig__.swift +0 -66
  901. package/nitrogen/generated/ios/swift/Func_void_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError____.swift +0 -81
  902. package/nitrogen/generated/ios/swift/Gate.swift +0 -47
  903. package/nitrogen/generated/ios/swift/GateDecision.swift +0 -40
  904. package/nitrogen/generated/ios/swift/GateEvent.swift +0 -29
  905. package/nitrogen/generated/ios/swift/GateReason.swift +0 -40
  906. package/nitrogen/generated/ios/swift/IOSOptions.swift +0 -51
  907. package/nitrogen/generated/ios/swift/MediaReference.swift +0 -40
  908. package/nitrogen/generated/ios/swift/NativeGateRequest.swift +0 -58
  909. package/nitrogen/generated/ios/swift/NativeSetupPlayerOptions.swift +0 -206
  910. package/nitrogen/generated/ios/swift/NitroIOSUpdateOptions.swift +0 -90
  911. package/nitrogen/generated/ios/swift/OutputType.swift +0 -72
  912. package/nitrogen/generated/ios/swift/PlaybackErrorKind.swift +0 -64
  913. package/nitrogen/generated/ios/swift/RemoteButtonLayout.swift +0 -57
  914. package/nitrogen/generated/ios/swift/StallReason.swift +0 -40
  915. package/nitrogen/generated/ios/swift/TrackRequest.swift +0 -106
  916. package/nitrogen/generated/ios/swift/Variant_Bool_FavoriteConfig.swift +0 -18
  917. package/nitrogen/generated/ios/swift/Variant_ResolvedTrack_BrowseError_Promise_BrowseResult_.swift +0 -19
  918. package/nitrogen/generated/ios/swift/Variant_String_ArtworkVariants.swift +0 -18
  919. package/nitrogen/generated/shared/c++/ArtworkVariants.hpp +0 -87
  920. package/nitrogen/generated/shared/c++/FavoritesMatchMode.hpp +0 -76
  921. package/nitrogen/generated/shared/c++/FormatNowPlayingParams.hpp +0 -110
  922. package/nitrogen/generated/shared/c++/GateReason.hpp +0 -76
  923. package/nitrogen/generated/shared/c++/IOSOptions.hpp +0 -91
  924. package/nitrogen/generated/shared/c++/MediaReference.hpp +0 -76
  925. package/nitrogen/generated/shared/c++/NativeGateRequest.hpp +0 -97
  926. package/nitrogen/generated/shared/c++/NativeSetupPlayerOptions.hpp +0 -138
  927. package/nitrogen/generated/shared/c++/NitroIOSUpdateOptions.hpp +0 -92
  928. package/nitrogen/generated/shared/c++/OutputType.hpp +0 -108
  929. package/nitrogen/generated/shared/c++/PlaybackErrorKind.hpp +0 -100
  930. package/nitrogen/generated/shared/c++/RemoteButtonLayout.hpp +0 -94
  931. package/nitrogen/generated/shared/c++/StallReason.hpp +0 -76
  932. package/nitrogen/generated/shared/c++/TrackRequest.hpp +0 -93
  933. package/src/codegen-no-config-variant.test.ts +0 -70
  934. package/src/features/browser-config.test.ts +0 -110
  935. package/src/features/browser-config.ts +0 -293
  936. package/src/features/browser.test.ts +0 -19
  937. package/src/features/carConnection.ts +0 -36
  938. package/src/features/gate.test.ts +0 -72
  939. package/src/features/gate.ts +0 -155
  940. package/src/features/playback/trackPlaybackTime.test.ts +0 -80
  941. package/src/features/playback/trackPlaybackTime.ts +0 -101
  942. package/src/features/player/options.test.ts +0 -38
  943. package/src/features/player/setup.test.ts +0 -125
  944. package/src/features/player/validateOptions.ts +0 -22
  945. package/src/features/queue/queue.test.ts +0 -36
  946. package/src/public-surface.test.ts +0 -123
  947. package/src/utils/artwork.ts +0 -30
  948. package/src/web/NativeAudioBrowser.playWhenReady.test.ts +0 -301
  949. package/src/web/TrackPlayer/PlaybackStateMachine.test.ts +0 -139
  950. package/src/web/TrackPlayer/PlaybackStateMachine.ts +0 -82
  951. package/src/web/TrackPlayer/PlaybackTimer.test.ts +0 -67
  952. package/src/web/TrackPlayer/PlaybackTimer.ts +0 -33
  953. package/src/web/TrackPlayer/Player.dispatch.test.ts +0 -229
  954. package/src/web/TrackPlayer/Player.load.test.ts +0 -86
  955. package/src/web/TrackPlayer/PlayingStateFactory.test.ts +0 -51
  956. package/src/web/TrackPlayer/PlayingStateFactory.ts +0 -24
  957. package/src/web/TrackPlayer/QueueManager.test.ts +0 -289
  958. package/src/web/TrackPlayer/QueueManager.ts +0 -302
  959. package/src/web/TrackPlayer/QueuePlayer.ts +0 -188
  960. package/src/web/TrackPlayer/VolumeFader.ts +0 -74
  961. package/src/web/browser/__tests__/layer-resolver.test.ts +0 -69
  962. package/src/web/browser/assertBrowsePageShape.test.ts +0 -27
  963. package/src/web/browser/assertBrowsePageShape.ts +0 -27
  964. package/src/web/browser/classifyTrackNavigation.test.ts +0 -41
  965. package/src/web/browser/classifyTrackNavigation.ts +0 -35
  966. package/src/web/browser/parseSearchResponse.test.ts +0 -25
  967. package/src/web/browser/parseSearchResponse.ts +0 -15
  968. package/src/web/http/RequestConfigBuilder.test.ts +0 -59
  969. package/src/web/playbackErrorKind.test.ts +0 -55
  970. package/src/web/playbackErrorKind.ts +0 -56
  971. package/src/web/player/MediaSessionManager.test.ts +0 -220
  972. package/src/web/player/MediaSessionManager.ts +0 -151
  973. package/src/web/player/NowPlayingManager.test.ts +0 -46
  974. package/src/web/player/RemoteCommandController.test.ts +0 -171
  975. package/src/web/player/RemoteCommandController.ts +0 -166
@@ -1,6 +1,5 @@
1
- @testable import AudioBrowserTestable
2
- import Foundation
3
1
  import Testing
2
+ @testable import AudioBrowserTestable
4
3
 
5
4
  /// Helper to build a coordinator with mocks for testing.
6
5
  @MainActor
@@ -8,7 +7,7 @@ private func makeCoordinator() -> (
8
7
  coordinator: PlaybackCoordinator,
9
8
  effectHandler: MockPlaybackEffectHandler,
10
9
  callbacks: MockPlaybackCoordinatorCallbacks,
11
- sleepTimer: MockSleepTimerHandling,
10
+ sleepTimer: MockSleepTimerHandling
12
11
  ) {
13
12
  let retryHandler = MockRetryHandling()
14
13
  let errorHandler = PlaybackErrorHandler(retryHandler: retryHandler)
@@ -27,7 +26,7 @@ private func loadTrack(
27
26
  _ coordinator: PlaybackCoordinator,
28
27
  id: String = "t1",
29
28
  src: String? = "https://example.com/audio.mp3",
30
- title: String = "Test Track",
29
+ title: String = "Test Track"
31
30
  ) {
32
31
  let track = Track(id: id, src: src, title: title)
33
32
  coordinator.setQueue([track])
@@ -42,7 +41,7 @@ struct TransitionTests {
42
41
  let (c, eh, _, _) = makeCoordinator()
43
42
  loadTrack(c)
44
43
  c.playWhenReady = true
45
- eh.startPlaybackCallCount = 0 // reset from playWhenReady setter
44
+ eh.startPlaybackCallCount = 0 // reset from playWhenReady setter
46
45
 
47
46
  c.transition(.bufferingSufficient)
48
47
 
@@ -107,119 +106,19 @@ struct TransitionTests {
107
106
  #expect(cb.playbackChanges.count == 1)
108
107
  #expect(cb.errorEvents.count == 1)
109
108
  }
110
- }
111
-
112
- // MARK: - Retrying Errors
113
-
114
- /// Advisory errors from the retry loop: attached to the current non-terminal
115
- /// state via `playerDidChangePlayback`, never a state transition and never a
116
- /// `playerDidError`.
117
- /// Builds a coordinator whose retry handler will accept the error and
118
- /// pretend the (instant) retry succeeded, so only the advisory path runs.
119
- /// The effect handler is returned solely to keep the weak reference alive.
120
- @MainActor
121
- private func makeRetrying() -> (
122
- PlaybackCoordinator, MockRetryHandling, MockPlaybackCoordinatorCallbacks,
123
- MockPlaybackEffectHandler,
124
- ) {
125
- let retryHandler = MockRetryHandling()
126
- retryHandler.isRetryableResult = true
127
- retryHandler.attemptRetryResult = true
128
- let errorHandler = PlaybackErrorHandler(retryHandler: retryHandler)
129
- let coordinator = PlaybackCoordinator(
130
- errorHandler: errorHandler, sleepTimerManager: MockSleepTimerHandling(),
131
- )
132
- let effectHandler = MockPlaybackEffectHandler()
133
- coordinator.effectHandler = effectHandler
134
- let callbacks = MockPlaybackCoordinatorCallbacks()
135
- coordinator.callbacks = callbacks
136
- return (coordinator, retryHandler, callbacks, effectHandler)
137
- }
138
109
 
139
- @Suite("PlaybackCoordinator - retrying errors")
140
- struct RetryingErrorTests {
141
110
  @Test @MainActor
142
- func retryingError_attachesToCurrentState() async {
143
- let (c, _, cb, _) = makeRetrying()
144
- c.transition(.trackLoading)
145
- cb.playbackChanges.removeAll()
146
-
147
- c.errorHandler.handleError(URLError(.cannotConnectToHost), context: .mediaLoad)
148
-
149
- #expect(c.state == .loading)
150
- #expect(c.playbackError == .hostUnreachable)
151
- #expect(cb.playbackChanges.count == 1)
152
- #expect(cb.playbackChanges.last?.state == .loading)
153
- #expect(cb.playbackChanges.last?.error?.retrying == true)
154
- // Advisory, not terminal: the error event is reserved for .error.
155
- #expect(cb.errorEvents.isEmpty)
156
- await c.errorHandler.pendingRetryTask?.value
157
- }
158
-
159
- /// Every failed attempt re-reports through `handleError`; identical repeats
160
- /// must not re-emit (they'd re-render now-playing every backoff tick).
161
- @Test @MainActor
162
- func repeatedIdenticalFailure_emitsOnce() async {
163
- let (c, _, cb, _) = makeRetrying()
164
- c.transition(.trackLoading)
165
- cb.playbackChanges.removeAll()
166
-
167
- c.errorHandler.handleError(URLError(.cannotConnectToHost), context: .mediaLoad)
168
- await c.errorHandler.pendingRetryTask?.value
169
- c.errorHandler.handleError(URLError(.cannotConnectToHost), context: .mediaLoad)
170
- await c.errorHandler.pendingRetryTask?.value
171
-
172
- #expect(cb.playbackChanges.count == 1)
173
- }
174
-
175
- /// While .playing, buffered audio is still audibly fine — the advisory must
176
- /// not replace the song line over working sound (matches Android's guard).
177
- @Test @MainActor
178
- func retryingErrorWhilePlaying_isSuppressed() async {
179
- let (c, _, cb, _) = makeRetrying()
180
- c.transition(.avPlayerPlaying)
181
- cb.playbackChanges.removeAll()
182
-
183
- c.errorHandler.handleError(URLError(.cannotConnectToHost), context: .playback)
184
-
185
- #expect(c.playbackError == nil)
186
- #expect(cb.playbackChanges.isEmpty)
187
- await c.errorHandler.pendingRetryTask?.value
188
- }
189
-
190
- /// Reaching .ready proves the retry recovered: the advisory error must not
191
- /// survive into the clean state's emission.
192
- @Test @MainActor
193
- func recovery_clearsTheRetryingError() async {
194
- let (c, _, cb, _) = makeRetrying()
195
- c.transition(.trackLoading)
196
- c.errorHandler.handleError(URLError(.cannotConnectToHost), context: .mediaLoad)
197
- await c.errorHandler.pendingRetryTask?.value
198
-
199
- c.transition(.loadSeekCompleted)
200
-
201
- #expect(c.state == .ready)
202
- #expect(c.playbackError == nil)
203
- #expect(cb.playbackChanges.last?.error == nil)
204
- }
111
+ func activeStates_updateNowPlayingValues() {
112
+ let (c, eh, _, _) = makeCoordinator()
113
+ eh.hasLoadedAsset = true
114
+ eh.duration = 120
115
+ eh.currentTime = 30
205
116
 
206
- /// Giving up hardens the advisory into a terminal error: same kind, state
207
- /// .error, `retrying` gone.
208
- @Test @MainActor
209
- func exhaustion_hardensIntoTerminalError() async {
210
- let (c, retryHandler, cb, _) = makeRetrying()
211
117
  c.transition(.trackLoading)
212
- c.errorHandler.handleError(URLError(.cannotConnectToHost), context: .mediaLoad)
213
- await c.errorHandler.pendingRetryTask?.value
118
+ #expect(eh.updateNowPlayingValuesCalls.count == 1)
214
119
 
215
- retryHandler.attemptRetryResult = false
216
- c.errorHandler.handleError(URLError(.cannotConnectToHost), context: .mediaLoad)
217
- await c.errorHandler.pendingRetryTask?.value
218
-
219
- #expect(c.state == .error)
220
- #expect(cb.playbackChanges.last?.state == .error)
221
- #expect(cb.playbackChanges.last?.error?.retrying == nil)
222
- #expect(cb.errorEvents.count == 1)
120
+ c.transition(.bufferingSufficient)
121
+ #expect(eh.updateNowPlayingValuesCalls.count == 2)
223
122
  }
224
123
  }
225
124
 
@@ -354,7 +253,7 @@ struct ObserverGuardTests {
354
253
 
355
254
  c.avPlayerDidChangeTimeControlStatus(.waitingToPlayAtSpecifiedRate)
356
255
 
357
- #expect(c.state == .playing) // unchanged
256
+ #expect(c.state == .playing) // unchanged
358
257
  }
359
258
 
360
259
  @Test @MainActor
@@ -485,60 +384,6 @@ struct PlayWhenReadyTests {
485
384
  }
486
385
  }
487
386
 
488
- // MARK: - Skip availability (next/previous greying)
489
-
490
- @Suite("PlaybackCoordinator - skip availability")
491
- struct SkipAvailabilityCoordinatorTests {
492
- private static func multiTrack() -> [Track] {
493
- [
494
- Track(id: "t1", src: "https://example.com/1.mp3", title: "Track 1"),
495
- Track(id: "t2", src: "https://example.com/2.mp3", title: "Track 2"),
496
- ]
497
- }
498
-
499
- @Test @MainActor
500
- func singleTrack_disablesBoth() {
501
- let (c, eh, _, _) = makeCoordinator()
502
- c.setQueue([Track(id: "t1", src: "https://example.com/1.mp3", title: "Track 1")])
503
-
504
- #expect(eh.updateSkipAvailabilityCalls.last?.canNext == false)
505
- #expect(eh.updateSkipAvailabilityCalls.last?.canPrevious == false)
506
- }
507
-
508
- @Test @MainActor
509
- func firstOfMany_nextOnly() {
510
- let (c, eh, _, _) = makeCoordinator()
511
- c.setQueue(Self.multiTrack())
512
-
513
- #expect(eh.updateSkipAvailabilityCalls.last?.canNext == true)
514
- #expect(eh.updateSkipAvailabilityCalls.last?.canPrevious == false)
515
- }
516
-
517
- @Test @MainActor
518
- func lastOfMany_previousOnly() {
519
- let (c, eh, _, _) = makeCoordinator()
520
- c.setQueue(Self.multiTrack())
521
- try? c.skipTo(1)
522
-
523
- #expect(eh.updateSkipAvailabilityCalls.last?.canNext == false)
524
- #expect(eh.updateSkipAvailabilityCalls.last?.canPrevious == true)
525
- }
526
-
527
- @Test @MainActor
528
- func repeatAll_repushesAvailability_atEnd() {
529
- let (c, eh, _, _) = makeCoordinator()
530
- c.setQueue(Self.multiTrack())
531
- try? c.skipTo(1) // last track
532
- eh.updateSkipAvailabilityCalls.removeAll()
533
-
534
- c.repeatMode = .queue
535
-
536
- // repeat-all wraps, so Next becomes available again at the last track.
537
- #expect(eh.updateSkipAvailabilityCalls.last?.canNext == true)
538
- #expect(eh.updateSkipAvailabilityCalls.last?.canPrevious == true)
539
- }
540
- }
541
-
542
387
  // MARK: - handleCurrentTrackChanged
543
388
 
544
389
  @Suite("PlaybackCoordinator - handleCurrentTrackChanged")
@@ -602,7 +447,6 @@ struct HandleTrackDidPlayToEndTimeTests {
602
447
  let (c, eh, _, _) = makeCoordinator()
603
448
  loadTrack(c)
604
449
  c.repeatMode = .track
605
- c.playWhenReady = true
606
450
 
607
451
  c.handleTrackDidPlayToEndTime()
608
452
 
@@ -610,25 +454,6 @@ struct HandleTrackDidPlayToEndTimeTests {
610
454
  #expect(eh.replayCurrentTrackCallCount == 1)
611
455
  }
612
456
 
613
- /// The end-of-track sleep timer pauses (clears intent) just before this
614
- /// handler runs — an unguarded replay would resume seconds after the sleep
615
- /// timer paused. Without intent the track settles in .ended, where play()
616
- /// reloads (a bare .paused would park at the end, where play() no-ops).
617
- /// A repeating queue never conceptually ends, so no queue-ended reaches JS.
618
- @Test @MainActor
619
- func repeatTrack_withoutIntent_settlesEnded() {
620
- let (c, eh, cb, _) = makeCoordinator()
621
- loadTrack(c)
622
- c.repeatMode = .track
623
- c.playWhenReady = false
624
-
625
- c.handleTrackDidPlayToEndTime()
626
-
627
- #expect(cb.queueEndedEvents.isEmpty)
628
- #expect(eh.replayCurrentTrackCallCount == 0)
629
- #expect(c.state == .ended)
630
- }
631
-
632
457
  @Test @MainActor
633
458
  func lastTrack_noRepeat_transitionsToEnded() {
634
459
  let (c, eh, cb, _) = makeCoordinator()
@@ -659,602 +484,3 @@ struct HandleTrackDidPlayToEndTimeTests {
659
484
  #expect(cb.activeTrackChanges.first?.track?.id == "t2")
660
485
  }
661
486
  }
662
-
663
- // MARK: - Natural end drops play intent
664
-
665
- /// A natural queue end exhausts the play intent: nothing is left to play, so
666
- /// `playWhenReady` must not stay true. Keeping it inverted the play/pause
667
- /// toggle, held the audio session forever, armed interruption auto-resume into
668
- /// silence, and made play-from-ended a silent no-op.
669
- @Suite("PlaybackCoordinator - natural end drops play intent")
670
- struct NaturalEndPlayIntentTests {
671
- @Test @MainActor
672
- func naturalEnd_clearsPlayWhenReady() {
673
- let (c, eh, _, _) = makeCoordinator()
674
- startPlaying(c, eh)
675
-
676
- c.handleTrackDidPlayToEndTime()
677
-
678
- #expect(c.state == .ended)
679
- #expect(c.playWhenReady == false)
680
- }
681
-
682
- @Test @MainActor
683
- func naturalEnd_requestsSessionRelease() {
684
- let (c, eh, callbacks, _) = makeCoordinator()
685
- startPlaying(c, eh)
686
- callbacks.releaseSessionCount = 0
687
-
688
- c.handleTrackDidPlayToEndTime()
689
-
690
- #expect(callbacks.releaseSessionCount == 1)
691
- }
692
-
693
- /// play() from .ended must reload from the start — startPlayback() alone is a
694
- /// silent no-op on a player parked at the end of its item.
695
- @Test @MainActor
696
- func playAfterNaturalEnd_reloadsFromStart() {
697
- let (c, eh, _, _) = makeCoordinator()
698
- startPlaying(c, eh)
699
- c.handleTrackDidPlayToEndTime()
700
- eh.reloadTrackCalls.removeAll()
701
-
702
- c.play()
703
-
704
- #expect(eh.reloadTrackCalls == [false])
705
- }
706
-
707
- /// The cleared intent opens the call-site `!playWhenReady` gate, so a stray
708
- /// timeControlStatus pause after the end reaches the state machine — the
709
- /// table's .ended guard must hold the state.
710
- @Test @MainActor
711
- func strayPauseAfterNaturalEnd_staysEnded() {
712
- let (c, eh, _, _) = makeCoordinator()
713
- startPlaying(c, eh)
714
- c.handleTrackDidPlayToEndTime()
715
- #expect(c.state == .ended)
716
-
717
- c.avPlayerDidChangeTimeControlStatus(.paused)
718
-
719
- #expect(c.state == .ended)
720
- }
721
-
722
- @Test @MainActor
723
- func interruptionAfterNaturalEnd_doesNotArmResume() {
724
- let (c, eh, _, _) = makeCoordinator()
725
- startPlaying(c, eh)
726
- c.handleTrackDidPlayToEndTime()
727
- eh.reloadTrackCalls.removeAll()
728
-
729
- c.handleInterruptionBegan()
730
- c.handleInterruptionEnded(shouldResume: true)
731
-
732
- #expect(c.playWhenReady == false) // nothing was playing — never resume
733
- #expect(eh.reloadTrackCalls.isEmpty)
734
- }
735
- }
736
-
737
- // MARK: - Healthy playback refills the retry budget
738
-
739
- /// Sustained audible playback proves the stream recovered, so the retry
740
- /// window/attempt counters must refill (mirrors Android's healthy-playback
741
- /// refill) — otherwise a long-lived stream permanently loses retry after its
742
- /// first recovered blip.
743
- @Suite("PlaybackCoordinator - healthy playback resets retry budget")
744
- struct HealthyPlaybackRetryResetTests {
745
- @Test @MainActor
746
- func sustainedPlayback_resetsRetryBudget() async {
747
- let retryHandler = MockRetryHandling()
748
- let errorHandler = PlaybackErrorHandler(retryHandler: retryHandler)
749
- let coordinator = PlaybackCoordinator(
750
- errorHandler: errorHandler, sleepTimerManager: MockSleepTimerHandling(),
751
- )
752
- let effectHandler = MockPlaybackEffectHandler()
753
- coordinator.effectHandler = effectHandler
754
- coordinator.healthyPlaybackDuration = 0.01
755
-
756
- coordinator.transition(.avPlayerPlaying)
757
- await coordinator.healthyPlaybackTask?.value
758
-
759
- #expect(retryHandler.resetCallCount == 1)
760
- }
761
-
762
- /// resetRetry() cancels a pending retry — firing the refill mid-episode
763
- /// would kill an in-flight reconnect silently (stuck .playing forever).
764
- @Test @MainActor
765
- func refill_skipsWhileRetryIsPending() async {
766
- let retryHandler = MockRetryHandling()
767
- retryHandler.isRetryableResult = true
768
- retryHandler.attemptRetryDelayNs = 1_000_000_000
769
- let errorHandler = PlaybackErrorHandler(retryHandler: retryHandler)
770
- let coordinator = PlaybackCoordinator(
771
- errorHandler: errorHandler, sleepTimerManager: MockSleepTimerHandling(),
772
- )
773
- let effectHandler = MockPlaybackEffectHandler()
774
- coordinator.effectHandler = effectHandler
775
- coordinator.healthyPlaybackDuration = 0.01
776
-
777
- coordinator.transition(.avPlayerPlaying)
778
- errorHandler.handleError(URLError(.timedOut), context: .playback)
779
- await coordinator.healthyPlaybackTask?.value
780
-
781
- #expect(retryHandler.resetCallCount == 0)
782
- #expect(errorHandler.pendingRetryTask != nil)
783
- }
784
-
785
- @Test @MainActor
786
- func playbackInterruptedBeforeThreshold_doesNotReset() async {
787
- let retryHandler = MockRetryHandling()
788
- let errorHandler = PlaybackErrorHandler(retryHandler: retryHandler)
789
- let coordinator = PlaybackCoordinator(
790
- errorHandler: errorHandler, sleepTimerManager: MockSleepTimerHandling(),
791
- )
792
- let effectHandler = MockPlaybackEffectHandler()
793
- coordinator.effectHandler = effectHandler
794
- effectHandler.hasLoadedAsset = true
795
- coordinator.healthyPlaybackDuration = 0.5
796
-
797
- coordinator.transition(.avPlayerPlaying)
798
- let refill = coordinator.healthyPlaybackTask
799
- coordinator.transition(.avPlayerWaiting) // stalls before the threshold
800
-
801
- // Leaving .playing cancels the refill; awaiting the cancelled task is the
802
- // deterministic way to reach the point where it would have fired.
803
- await refill?.value
804
-
805
- #expect(retryHandler.resetCallCount == 0)
806
- }
807
- }
808
-
809
- @Suite("PlaybackCoordinator - now playing state")
810
- struct PlaybackCoordinatorNowPlayingStateTests {
811
- @Test @MainActor
812
- func change_updatesNowPlayingState_evenDuringLoading() {
813
- let (c, eh, _, _) = makeCoordinator()
814
- c.transition(.trackLoading) // mid track-load; start/pause is deferred
815
- eh.updateNowPlayingStateCalls.removeAll()
816
-
817
- c.playWhenReady = true
818
-
819
- // The lock-screen / CarPlay play-pause button reflects the user's play
820
- // *intent* immediately, even while the new item is still loading — otherwise
821
- // it stays stuck showing "paused" until a later state transition repairs it.
822
- #expect(eh.updateNowPlayingStateCalls.last == true)
823
- }
824
-
825
- @Test @MainActor
826
- func staysPlaying_whenBufferRunsDry() {
827
- let (c, eh, _, _) = makeCoordinator()
828
- c.playWhenReady = true
829
- c.transition(.avPlayerPlaying)
830
- eh.updateNowPlayingStateCalls.removeAll()
831
-
832
- c.transition(.avPlayerWaiting) // buffer ran dry → .buffering
833
-
834
- // A buffer underrun doesn't change play intent, so the button stays "playing"
835
- // (the system shows buffering) — it must NOT flip to paused like a user pause.
836
- #expect(eh.updateNowPlayingStateCalls.last == true)
837
- }
838
-
839
- @Test @MainActor
840
- func fallsBackToPaused_onError() {
841
- let (c, eh, _, _) = makeCoordinator()
842
- c.playWhenReady = true
843
- c.transition(.trackLoading) // active + intent → playing
844
- eh.updateNowPlayingStateCalls.removeAll()
845
-
846
- c.transition(.errorOccurred(.playbackFailed))
847
-
848
- // On a terminal error the button must fall back to paused — never stick on
849
- // "playing" — even though playWhenReady is still true.
850
- #expect(eh.updateNowPlayingStateCalls.last == false)
851
- }
852
-
853
- @Test @MainActor
854
- func change_doesNotStampNowPlayingState_fromTerminalState() {
855
- let (c, eh, _, _) = makeCoordinator()
856
- c.transition(.errorOccurred(.playbackFailed)) // terminal, not playbackActive
857
- eh.updateNowPlayingStateCalls.removeAll()
858
-
859
- c.playWhenReady = true
860
-
861
- // Must NOT stamp .playing from a terminal state: the reload may fail and no
862
- // active transition would repair a premature "playing", leaving a phantom
863
- // playing button. The reload's own .loading/.ready transition stamps it.
864
- #expect(eh.updateNowPlayingStateCalls.isEmpty)
865
- }
866
-
867
- @Test @MainActor
868
- func selectingNewTrack_whileStopped_showsPlayingInNowPlaying() {
869
- let (c, eh, _, _) = makeCoordinator()
870
- let tracks = [
871
- Track(id: "t1", src: "https://example.com/1.mp3", title: "Track 1"),
872
- Track(id: "t2", src: "https://example.com/2.mp3", title: "Track 2"),
873
- ]
874
- c.setQueue(tracks) // loads t1 (playWhenReady defaults to false)
875
- c.transition(.stopped) // user had paused/stopped
876
- eh.updateNowPlayingStateCalls.removeAll()
877
-
878
- // User selects another track, intending to play it.
879
- try? c.skipTo(1, playWhenReady: true)
880
-
881
- // Audio will play, so the now-playing button must end up "playing" — not the
882
- // stale "paused" captured before playWhenReady flipped true during loading.
883
- #expect(eh.updateNowPlayingStateCalls.last == true)
884
- }
885
- }
886
-
887
- // MARK: - Sleep Timer Fade
888
-
889
- @Suite("PlaybackCoordinator - sleep timer fade")
890
- struct SleepTimerFadeTests {
891
- @Test @MainActor
892
- func fadeStart_capturesPreFadeVolume() {
893
- let (c, eh, _, st) = makeCoordinator()
894
- eh.volume = 0.8
895
-
896
- st.onFadeStart?(10)
897
-
898
- #expect(c.volumeFader.isActive)
899
- #expect(c.volumeFader.originalVolume == 0.8)
900
- }
901
-
902
- @Test @MainActor
903
- func completion_pausesThenRestoresPreFadeVolume() {
904
- let (c, eh, _, st) = makeCoordinator()
905
- loadTrack(c)
906
- c.playWhenReady = true
907
- c.transition(.bufferingSufficient) // leave .loading so pause reaches the player
908
- eh.pausePlaybackCallCount = 0
909
-
910
- st.onFadeStart?(10)
911
- eh.volume = 0.2 // mid-fade
912
-
913
- st.onComplete?()
914
-
915
- #expect(c.playWhenReady == false)
916
- #expect(eh.pausePlaybackCallCount == 1)
917
- #expect(eh.volume == 1.0)
918
- #expect(!c.volumeFader.isActive)
919
- }
920
-
921
- @Test @MainActor
922
- func completion_withoutFade_justPauses() {
923
- let (c, eh, _, st) = makeCoordinator()
924
- loadTrack(c)
925
- c.playWhenReady = true
926
- eh.volume = 0.8
927
-
928
- st.onComplete?()
929
-
930
- #expect(c.playWhenReady == false)
931
- #expect(eh.volume == 0.8) // untouched — no fade ran
932
- }
933
-
934
- @Test @MainActor
935
- func fadeCancel_restoresPreFadeVolume() {
936
- let (c, eh, _, st) = makeCoordinator()
937
- eh.volume = 0.8
938
-
939
- st.onFadeStart?(10)
940
- eh.volume = 0.1 // mid-fade
941
-
942
- st.onFadeCancel?()
943
-
944
- #expect(eh.volume == 0.8)
945
- #expect(!c.volumeFader.isActive)
946
- }
947
-
948
- @Test @MainActor
949
- func pauseDuringFade_clearsSleepTimer() {
950
- let (c, _, _, st) = makeCoordinator()
951
- loadTrack(c)
952
- c.playWhenReady = true
953
-
954
- st.onFadeStart?(10)
955
- c.pause()
956
-
957
- #expect(st.clearCallCount == 1)
958
- }
959
-
960
- @Test @MainActor
961
- func pauseWithoutFade_leavesSleepTimerAlone() {
962
- let (c, _, _, st) = makeCoordinator()
963
- loadTrack(c)
964
- c.playWhenReady = true
965
-
966
- c.pause()
967
-
968
- #expect(st.clearCallCount == 0)
969
- }
970
- }
971
-
972
- // MARK: - Audio Session Interruptions
973
-
974
- /// Helper to drive the coordinator into an actively-playing state.
975
- @MainActor
976
- private func startPlaying(_ c: PlaybackCoordinator, _ eh: MockPlaybackEffectHandler) {
977
- loadTrack(c)
978
- eh.hasLoadedAsset = true
979
- c.playWhenReady = true
980
- c.transition(.avPlayerPlaying)
981
- }
982
-
983
- @Suite("PlaybackCoordinator - audio session interruptions")
984
- struct InterruptionTests {
985
- @Test @MainActor
986
- func began_whilePlaying_pauses() {
987
- let (c, eh, _, _) = makeCoordinator()
988
- startPlaying(c, eh)
989
- #expect(c.state == .playing)
990
-
991
- c.handleInterruptionBegan()
992
-
993
- #expect(c.state == .paused)
994
- #expect(c.playWhenReady == false)
995
- }
996
-
997
- /// The bug: iOS pauses the AVPlayer first; that `timeControlStatus → paused`
998
- /// is swallowed because `playWhenReady` is still true, so the state stays
999
- /// `.playing`. The interruption handler must force the pause regardless.
1000
- @Test @MainActor
1001
- func began_afterSwallowedTimeControlPause_stillPauses() {
1002
- let (c, eh, _, _) = makeCoordinator()
1003
- startPlaying(c, eh)
1004
-
1005
- c.avPlayerDidChangeTimeControlStatus(.paused)
1006
- #expect(c.state == .playing) // swallowed — the symptom this fix targets
1007
-
1008
- c.handleInterruptionBegan()
1009
-
1010
- #expect(c.state == .paused)
1011
- }
1012
-
1013
- @Test @MainActor
1014
- func ended_shouldResume_resumesWhenWasPlaying() {
1015
- let (c, eh, _, _) = makeCoordinator()
1016
- startPlaying(c, eh)
1017
- c.handleInterruptionBegan()
1018
- #expect(c.playWhenReady == false)
1019
- eh.startPlaybackCallCount = 0
1020
-
1021
- c.handleInterruptionEnded(shouldResume: true)
1022
-
1023
- #expect(c.playWhenReady == true)
1024
- #expect(eh.startPlaybackCallCount == 1)
1025
- }
1026
-
1027
- @Test @MainActor
1028
- func ended_withoutShouldResume_staysPaused() {
1029
- let (c, eh, _, _) = makeCoordinator()
1030
- startPlaying(c, eh)
1031
- c.handleInterruptionBegan()
1032
-
1033
- c.handleInterruptionEnded(shouldResume: false)
1034
-
1035
- #expect(c.state == .paused)
1036
- #expect(c.playWhenReady == false)
1037
- }
1038
-
1039
- /// The host gates audio-session reactivation at interruption-end on this:
1040
- /// paused-when-interrupted must not grab a non-mixable session for a resume
1041
- /// that never happens.
1042
- @Test @MainActor
1043
- func willResumeAfterInterruption_reflectsCapturedIntent() {
1044
- let (c, eh, _, _) = makeCoordinator()
1045
- startPlaying(c, eh)
1046
-
1047
- c.handleInterruptionBegan()
1048
- #expect(c.willResumeAfterInterruption == true)
1049
-
1050
- c.handleInterruptionEnded(shouldResume: false)
1051
- #expect(c.willResumeAfterInterruption == false)
1052
-
1053
- // Paused before the interruption: no resume will happen.
1054
- c.handleInterruptionBegan()
1055
- #expect(c.willResumeAfterInterruption == false)
1056
- }
1057
-
1058
- /// iOS can deliver nested interruptions (Siri, then a phone call) — a second
1059
- /// .began must not re-capture the now-false intent and wipe the resume flag.
1060
- @Test @MainActor
1061
- func doubleBegan_preservesResumeIntent() {
1062
- let (c, eh, _, _) = makeCoordinator()
1063
- startPlaying(c, eh)
1064
-
1065
- c.handleInterruptionBegan()
1066
- c.handleInterruptionBegan()
1067
- c.handleInterruptionEnded(shouldResume: true)
1068
-
1069
- #expect(c.playWhenReady == true)
1070
- }
1071
-
1072
- /// Unplugging headphones during a call is a deliberate output loss — the
1073
- /// call ending must not blast playback from the built-in speaker.
1074
- @Test @MainActor
1075
- func routeDisconnectDuringInterruption_cancelsResume() {
1076
- let (c, eh, _, _) = makeCoordinator()
1077
- startPlaying(c, eh)
1078
- c.handleInterruptionBegan()
1079
-
1080
- c.handleRouteDisconnected()
1081
- c.handleInterruptionEnded(shouldResume: true)
1082
-
1083
- #expect(c.playWhenReady == false)
1084
- }
1085
-
1086
- /// An explicit stop during the interruption is a terminal command — the
1087
- /// interruption-end must not restart playback over it.
1088
- @Test @MainActor
1089
- func stopDuringInterruption_isNotOverriddenByResume() {
1090
- let (c, eh, _, _) = makeCoordinator()
1091
- startPlaying(c, eh)
1092
- c.handleInterruptionBegan()
1093
-
1094
- c.stop()
1095
- c.handleInterruptionEnded(shouldResume: true)
1096
-
1097
- #expect(c.state == .stopped)
1098
- #expect(c.playWhenReady == false)
1099
- #expect(eh.reloadTrackCalls.isEmpty)
1100
- }
1101
-
1102
- /// A user who plays then pauses during the interruption has taken ownership
1103
- /// of the intent — interruption-end must not override their pause.
1104
- @Test @MainActor
1105
- func userPauseDuringInterruption_overridesResume() {
1106
- let (c, eh, _, _) = makeCoordinator()
1107
- startPlaying(c, eh)
1108
- c.handleInterruptionBegan()
1109
-
1110
- c.play()
1111
- c.pause()
1112
- c.handleInterruptionEnded(shouldResume: true)
1113
-
1114
- #expect(c.playWhenReady == false)
1115
- }
1116
-
1117
- @Test @MainActor
1118
- func ended_doesNotResume_whenNotPlayingBeforeInterruption() {
1119
- let (c, eh, _, _) = makeCoordinator()
1120
- startPlaying(c, eh)
1121
- // Pause before the interruption (e.g. user already paused).
1122
- c.playWhenReady = false
1123
- c.avPlayerDidChangeTimeControlStatus(.paused)
1124
- #expect(c.state == .paused)
1125
-
1126
- c.handleInterruptionBegan()
1127
- c.handleInterruptionEnded(shouldResume: true)
1128
-
1129
- #expect(c.playWhenReady == false) // never resumes — we weren't playing
1130
- }
1131
- }
1132
-
1133
- // MARK: - Skip availability freshness
1134
-
1135
- /// tracks.didSet pushes availability mid-mutation, while currentIndex and the
1136
- /// shuffle order are still stale — the coordinator must re-push after the
1137
- /// mutation settles or the lock-screen buttons keep the wrong state.
1138
- @Suite("PlaybackCoordinator - skip availability after mutations")
1139
- struct MutationSkipAvailabilityTests {
1140
- @Test @MainActor
1141
- func move_pushesPostMutationAvailability() throws {
1142
- let (c, eh, _, _) = makeCoordinator()
1143
- c.setQueue([
1144
- Track(id: "a", src: "https://example.com/a.mp3", title: "A"),
1145
- Track(id: "b", src: "https://example.com/b.mp3", title: "B"),
1146
- ])
1147
- eh.updateSkipAvailabilityCalls.removeAll()
1148
-
1149
- try c.move(fromIndex: 0, toIndex: 1)
1150
-
1151
- // Current track is now last: nothing to skip to.
1152
- #expect(eh.updateSkipAvailabilityCalls.last?.canNext == false)
1153
- }
1154
-
1155
- @Test @MainActor
1156
- func removeBeforeCurrent_pushesPostMutationAvailability() throws {
1157
- let (c, eh, _, _) = makeCoordinator()
1158
- c.setQueue(
1159
- [
1160
- Track(id: "a", src: "https://example.com/a.mp3", title: "A"),
1161
- Track(id: "b", src: "https://example.com/b.mp3", title: "B"),
1162
- Track(id: "c", src: "https://example.com/c.mp3", title: "C"),
1163
- ], initialIndex: 2,
1164
- )
1165
- eh.updateSkipAvailabilityCalls.removeAll()
1166
-
1167
- try c.remove(0)
1168
-
1169
- // Current settled at index 1 of 2: previous available, next not.
1170
- #expect(eh.updateSkipAvailabilityCalls.last?.canNext == false)
1171
- #expect(eh.updateSkipAvailabilityCalls.last?.canPrevious == true)
1172
- }
1173
- }
1174
-
1175
- // MARK: - Stop cancels pending retry
1176
-
1177
- @Suite("PlaybackCoordinator - stop cancels pending retry")
1178
- struct StopCancelsRetryTests {
1179
- /// A retry surviving stop() gives up later (intent dropped) and surfaced
1180
- /// .errorOccurred over the deliberate stop — the UI showed an error seconds
1181
- /// after the user stopped.
1182
- @Test @MainActor
1183
- func stop_cancelsPendingRetry_andStaysSilent() async {
1184
- let retryHandler = MockRetryHandling()
1185
- retryHandler.isRetryableResult = true
1186
- retryHandler.attemptRetryResult = false
1187
- retryHandler.attemptRetryDelayNs = 50_000_000
1188
- let errorHandler = PlaybackErrorHandler(retryHandler: retryHandler)
1189
- let coordinator = PlaybackCoordinator(
1190
- errorHandler: errorHandler, sleepTimerManager: MockSleepTimerHandling(),
1191
- )
1192
- let effectHandler = MockPlaybackEffectHandler()
1193
- let callbacks = MockPlaybackCoordinatorCallbacks()
1194
- coordinator.effectHandler = effectHandler
1195
- coordinator.callbacks = callbacks
1196
-
1197
- errorHandler.handleError(URLError(.timedOut), context: .playback)
1198
- let task = errorHandler.pendingRetryTask
1199
- #expect(task != nil)
1200
-
1201
- coordinator.stop()
1202
- #expect(errorHandler.pendingRetryTask == nil)
1203
-
1204
- await task?.value
1205
- #expect(coordinator.state == .stopped)
1206
- #expect(callbacks.errorEvents.isEmpty)
1207
- }
1208
- }
1209
-
1210
- // MARK: - Audio session release (#60)
1211
-
1212
- @Suite("PlaybackCoordinator - audio session release")
1213
- struct SessionReleaseTests {
1214
- @Test @MainActor
1215
- func deliberatePause_requestsRelease() {
1216
- let (c, eh, callbacks, _) = makeCoordinator()
1217
- startPlaying(c, eh)
1218
- callbacks.releaseSessionCount = 0
1219
- c.pause()
1220
- #expect(callbacks.releaseSessionCount == 1)
1221
- }
1222
-
1223
- @Test @MainActor
1224
- func play_doesNotRequestRelease() {
1225
- let (c, eh, callbacks, _) = makeCoordinator()
1226
- startPlaying(c, eh)
1227
- #expect(callbacks.releaseSessionCount == 0)
1228
- }
1229
-
1230
- @Test @MainActor
1231
- func interruptionBegan_doesNotRequestRelease() {
1232
- // A phone call pauses (playWhenReady → false) but is meant to resume, so the session must be
1233
- // held — the exact race the intent-gating design exists to avoid.
1234
- let (c, eh, callbacks, _) = makeCoordinator()
1235
- startPlaying(c, eh)
1236
- callbacks.releaseSessionCount = 0
1237
- c.handleInterruptionBegan()
1238
- #expect(callbacks.releaseSessionCount == 0)
1239
- }
1240
-
1241
- @Test @MainActor
1242
- func interruptionEnded_withResume_doesNotRequestRelease() {
1243
- let (c, eh, callbacks, _) = makeCoordinator()
1244
- startPlaying(c, eh)
1245
- c.handleInterruptionBegan()
1246
- callbacks.releaseSessionCount = 0
1247
- c.handleInterruptionEnded(shouldResume: true)
1248
- #expect(callbacks.releaseSessionCount == 0)
1249
- }
1250
-
1251
- @Test @MainActor
1252
- func interruptionEnded_withoutResume_requestsRelease() {
1253
- let (c, eh, callbacks, _) = makeCoordinator()
1254
- startPlaying(c, eh)
1255
- c.handleInterruptionBegan()
1256
- callbacks.releaseSessionCount = 0
1257
- c.handleInterruptionEnded(shouldResume: false)
1258
- #expect(callbacks.releaseSessionCount == 1)
1259
- }
1260
- }