@5stones/react-native-audio-browser 0.2.0 → 0.3.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 (605) hide show
  1. package/AudioBrowser.podspec +3 -1
  2. package/android/src/main/cpp/cpp-adapter.cpp +4 -1
  3. package/android/src/main/java/com/audiobrowser/AudioBrowser.kt +8 -27
  4. package/android/src/main/java/com/audiobrowser/Service.kt +0 -2
  5. package/android/src/main/java/com/audiobrowser/browser/BrowserManager.kt +5 -0
  6. package/android/src/main/java/com/audiobrowser/browser/JsonModels.kt +31 -0
  7. package/android/src/main/java/com/audiobrowser/browser/SimpleRouter.kt +10 -6
  8. package/android/src/main/java/com/audiobrowser/browser/TrackLoadHandler.kt +45 -0
  9. package/android/src/main/java/com/audiobrowser/player/MediaSessionCallback.kt +3 -21
  10. package/android/src/main/java/com/audiobrowser/player/PlaybackStateStore.kt +1 -0
  11. package/android/src/main/java/com/audiobrowser/player/Player.kt +1 -0
  12. package/android/src/test/java/com/audiobrowser/browser/SimpleRouterTest.kt +104 -95
  13. package/ios/Browser/BrowserConfig.swift +31 -5
  14. package/ios/Browser/BrowserManager.swift +96 -6
  15. package/ios/Browser/JsonModels.swift +37 -0
  16. package/ios/CarPlay/CarPlayController.swift +219 -99
  17. package/ios/CarPlay/RNABAudioBrowser.h +23 -0
  18. package/ios/CarPlay/RNABAudioBrowser.m +22 -0
  19. package/ios/CarPlay/RNABMediaIntentHandler.swift +60 -0
  20. package/ios/Extension/ChapterMetadata+AVFoundation.swift +1 -1
  21. package/ios/Extension/CxxVectorConformances.swift +20 -0
  22. package/ios/Extension/TimedMetadata+AVFoundation.swift +5 -5
  23. package/ios/Extension/Track+AVPlayer.swift +5 -6
  24. package/ios/Extension/TrackMetadata+AVFoundation.swift +1 -1
  25. package/ios/HybridAudioBrowser.swift +107 -46
  26. package/ios/Model/MediaURL.swift +2 -1
  27. package/ios/Player/PlayingStateManager.swift +1 -0
  28. package/ios/Player/RetryManager.swift +26 -65
  29. package/ios/Player/SleepTimerManager.swift +6 -8
  30. package/ios/RemoteCommand/RemoteCommandController.swift +6 -0
  31. package/ios/Tests/SimpleRouterTests.swift +139 -0
  32. package/ios/TrackPlayer.swift +35 -24
  33. package/ios/Util/NetworkMonitor.swift +3 -6
  34. package/ios/Util/SFSymbolRenderer.swift +142 -0
  35. package/lib/commonjs/features/browser.js +1 -0
  36. package/lib/commonjs/features/browser.js.map +1 -1
  37. package/lib/commonjs/features/remoteControls.js +1 -24
  38. package/lib/commonjs/features/remoteControls.js.map +1 -1
  39. package/lib/commonjs/web/NativeAudioBrowser.js +20 -24
  40. package/lib/commonjs/web/NativeAudioBrowser.js.map +1 -1
  41. package/lib/commonjs/web/SimpleRouter.js +4 -3
  42. package/lib/commonjs/web/SimpleRouter.js.map +1 -1
  43. package/lib/commonjs/web/SimpleRouter.test.js +174 -0
  44. package/lib/commonjs/web/SimpleRouter.test.js.map +1 -0
  45. package/lib/module/features/browser.js +1 -0
  46. package/lib/module/features/browser.js.map +1 -1
  47. package/lib/module/features/remoteControls.js +0 -22
  48. package/lib/module/features/remoteControls.js.map +1 -1
  49. package/lib/module/web/NativeAudioBrowser.js +20 -24
  50. package/lib/module/web/NativeAudioBrowser.js.map +1 -1
  51. package/lib/module/web/SimpleRouter.js +4 -3
  52. package/lib/module/web/SimpleRouter.js.map +1 -1
  53. package/lib/module/web/SimpleRouter.test.js +174 -0
  54. package/lib/module/web/SimpleRouter.test.js.map +1 -0
  55. package/lib/typescript/src/features/browser.d.ts.map +1 -1
  56. package/lib/typescript/src/features/remoteControls.d.ts +0 -26
  57. package/lib/typescript/src/features/remoteControls.d.ts.map +1 -1
  58. package/lib/typescript/src/specs/audio-browser.nitro.d.ts +1 -3
  59. package/lib/typescript/src/specs/audio-browser.nitro.d.ts.map +1 -1
  60. package/lib/typescript/src/types/browser-native.d.ts +2 -1
  61. package/lib/typescript/src/types/browser-native.d.ts.map +1 -1
  62. package/lib/typescript/src/types/browser-nodes.d.ts +46 -1
  63. package/lib/typescript/src/types/browser-nodes.d.ts.map +1 -1
  64. package/lib/typescript/src/types/browser.d.ts +32 -0
  65. package/lib/typescript/src/types/browser.d.ts.map +1 -1
  66. package/lib/typescript/src/web/NativeAudioBrowser.d.ts +3 -6
  67. package/lib/typescript/src/web/NativeAudioBrowser.d.ts.map +1 -1
  68. package/lib/typescript/src/web/SimpleRouter.d.ts.map +1 -1
  69. package/lib/typescript/src/web/SimpleRouter.test.d.ts +2 -0
  70. package/lib/typescript/src/web/SimpleRouter.test.d.ts.map +1 -0
  71. package/nitrogen/generated/android/AudioBrowser+autolinking.cmake +1 -1
  72. package/nitrogen/generated/android/AudioBrowser+autolinking.gradle +1 -1
  73. package/nitrogen/generated/android/AudioBrowserOnLoad.cpp +67 -57
  74. package/nitrogen/generated/android/AudioBrowserOnLoad.hpp +14 -5
  75. package/nitrogen/generated/android/c++/JAndroidAudioContentType.hpp +6 -7
  76. package/nitrogen/generated/android/c++/JAndroidAudioOffloadSettings.hpp +1 -1
  77. package/nitrogen/generated/android/c++/JAndroidOptions.hpp +1 -1
  78. package/nitrogen/generated/android/c++/JAndroidPlayerWakeMode.hpp +4 -5
  79. package/nitrogen/generated/android/c++/JAndroidUpdateOptions.hpp +1 -1
  80. package/nitrogen/generated/android/c++/JAppKilledPlaybackBehavior.hpp +4 -5
  81. package/nitrogen/generated/android/c++/JArtworkRequestConfig.hpp +4 -1
  82. package/nitrogen/generated/android/c++/JBatteryOptimizationStatus.hpp +4 -5
  83. package/nitrogen/generated/android/c++/JBatteryOptimizationStatusChangedEvent.hpp +1 -1
  84. package/nitrogen/generated/android/c++/JBatteryWarningPendingChangedEvent.hpp +1 -1
  85. package/nitrogen/generated/android/c++/JBrowseError.hpp +1 -1
  86. package/nitrogen/generated/android/c++/JBrowseResult.cpp +1 -1
  87. package/nitrogen/generated/android/c++/JBrowseResult.hpp +7 -3
  88. package/nitrogen/generated/android/c++/JBrowserSourceCallbackParam.hpp +1 -1
  89. package/nitrogen/generated/android/c++/JCarPlayNowPlayingButton.hpp +5 -6
  90. package/nitrogen/generated/android/c++/JCarPlaySiriListButtonPosition.hpp +58 -0
  91. package/nitrogen/generated/android/c++/JChapterMetadata.hpp +1 -1
  92. package/nitrogen/generated/android/c++/JEqualizerSettings.hpp +1 -1
  93. package/nitrogen/generated/android/c++/JFavoriteChangedEvent.hpp +4 -1
  94. package/nitrogen/generated/android/c++/JFormatNavigationErrorParams.hpp +1 -1
  95. package/nitrogen/generated/android/c++/JFormattedNavigationError.hpp +1 -1
  96. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_FormattedNavigationError____FormatNavigationErrorParams.hpp +1 -1
  97. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____MediaTransformParams.hpp +1 -1
  98. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____RequestConfig_std__optional_std__unordered_map_std__string__std__string__.hpp +1 -1
  99. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____Track.hpp +4 -1
  100. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.hpp +5 -1
  101. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_Track______SearchParams.hpp +3 -1
  102. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_void_____TrackLoadEvent.hpp +139 -0
  103. package/nitrogen/generated/android/c++/JFunc_void.hpp +1 -1
  104. package/nitrogen/generated/android/c++/JFunc_void_BatteryOptimizationStatusChangedEvent.hpp +1 -1
  105. package/nitrogen/generated/android/c++/JFunc_void_BatteryWarningPendingChangedEvent.hpp +1 -1
  106. package/nitrogen/generated/android/c++/JFunc_void_EqualizerSettings.hpp +1 -1
  107. package/nitrogen/generated/android/c++/JFunc_void_FavoriteChangedEvent.hpp +4 -1
  108. package/nitrogen/generated/android/c++/JFunc_void_IosOutput.hpp +1 -1
  109. package/nitrogen/generated/android/c++/JFunc_void_NavigationErrorEvent.hpp +1 -1
  110. package/nitrogen/generated/android/c++/JFunc_void_NowPlayingMetadata.hpp +1 -1
  111. package/nitrogen/generated/android/c++/JFunc_void_Options.hpp +1 -1
  112. package/nitrogen/generated/android/c++/JFunc_void_Playback.hpp +1 -1
  113. package/nitrogen/generated/android/c++/JFunc_void_PlaybackActiveTrackChangedEvent.hpp +4 -1
  114. package/nitrogen/generated/android/c++/JFunc_void_PlaybackErrorEvent.hpp +1 -1
  115. package/nitrogen/generated/android/c++/JFunc_void_PlaybackPlayWhenReadyChangedEvent.hpp +1 -1
  116. package/nitrogen/generated/android/c++/JFunc_void_PlaybackProgressUpdatedEvent.hpp +1 -1
  117. package/nitrogen/generated/android/c++/JFunc_void_PlaybackQueueEndedEvent.hpp +1 -1
  118. package/nitrogen/generated/android/c++/JFunc_void_PlayingState.hpp +1 -1
  119. package/nitrogen/generated/android/c++/JFunc_void_RemoteJumpBackwardEvent.hpp +1 -1
  120. package/nitrogen/generated/android/c++/JFunc_void_RemoteJumpForwardEvent.hpp +1 -1
  121. package/nitrogen/generated/android/c++/JFunc_void_RemotePlayIdEvent.hpp +1 -1
  122. package/nitrogen/generated/android/c++/JFunc_void_RemotePlaySearchEvent.hpp +1 -1
  123. package/nitrogen/generated/android/c++/JFunc_void_RemoteSeekEvent.hpp +1 -1
  124. package/nitrogen/generated/android/c++/JFunc_void_RemoteSetRatingEvent.hpp +1 -1
  125. package/nitrogen/generated/android/c++/JFunc_void_RemoteSkipEvent.hpp +1 -1
  126. package/nitrogen/generated/android/c++/JFunc_void_RepeatModeChangedEvent.hpp +1 -1
  127. package/nitrogen/generated/android/c++/JFunc_void_TimedMetadata.hpp +1 -1
  128. package/nitrogen/generated/android/c++/JFunc_void_TrackMetadata.hpp +1 -1
  129. package/nitrogen/generated/android/c++/JFunc_void_bool.hpp +1 -1
  130. package/nitrogen/generated/android/c++/JFunc_void_double.hpp +1 -1
  131. package/nitrogen/generated/android/c++/JFunc_void_std__optional_FormattedNavigationError_.hpp +1 -1
  132. package/nitrogen/generated/android/c++/JFunc_void_std__optional_ResolvedTrack_.hpp +5 -1
  133. package/nitrogen/generated/android/c++/JFunc_void_std__optional_std__variant_nitro__NullType__SleepTimerTime__SleepTimerEndOfTrack__.hpp +1 -1
  134. package/nitrogen/generated/android/c++/JFunc_void_std__string.hpp +1 -1
  135. package/nitrogen/generated/android/c++/JFunc_void_std__vector_ChapterMetadata_.hpp +1 -1
  136. package/nitrogen/generated/android/c++/JFunc_void_std__vector_Track_.hpp +3 -1
  137. package/nitrogen/generated/android/c++/JHeartRating.hpp +1 -1
  138. package/nitrogen/generated/android/c++/JHttpMethod.hpp +8 -9
  139. package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.cpp +230 -245
  140. package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.hpp +20 -26
  141. package/nitrogen/generated/android/c++/JIOSCategory.hpp +7 -8
  142. package/nitrogen/generated/android/c++/JIOSCategoryMode.hpp +10 -11
  143. package/nitrogen/generated/android/c++/JIOSCategoryOptions.hpp +8 -9
  144. package/nitrogen/generated/android/c++/JIOSCategoryPolicy.hpp +4 -5
  145. package/nitrogen/generated/android/c++/JImageContext.hpp +1 -1
  146. package/nitrogen/generated/android/c++/JImageQueryParams.hpp +1 -1
  147. package/nitrogen/generated/android/c++/JImageRowItem.hpp +75 -0
  148. package/nitrogen/generated/android/c++/JImageSource.hpp +1 -1
  149. package/nitrogen/generated/android/c++/JIosOutput.hpp +1 -1
  150. package/nitrogen/generated/android/c++/JIosOutputType.hpp +12 -13
  151. package/nitrogen/generated/android/c++/JMediaRequestConfig.hpp +4 -1
  152. package/nitrogen/generated/android/c++/JMediaTransformParams.hpp +1 -1
  153. package/nitrogen/generated/android/c++/JNativeBrowserConfiguration.hpp +22 -2
  154. package/nitrogen/generated/android/c++/JNativeRouteEntry.hpp +5 -1
  155. package/nitrogen/generated/android/c++/JNativeUpdateOptions.hpp +1 -1
  156. package/nitrogen/generated/android/c++/JNavigationError.hpp +1 -1
  157. package/nitrogen/generated/android/c++/JNavigationErrorEvent.hpp +1 -1
  158. package/nitrogen/generated/android/c++/JNavigationErrorType.hpp +6 -7
  159. package/nitrogen/generated/android/c++/JNitroAndroidUpdateOptions.hpp +1 -1
  160. package/nitrogen/generated/android/c++/JNotificationButton.hpp +6 -7
  161. package/nitrogen/generated/android/c++/JNotificationButtonLayout.hpp +1 -1
  162. package/nitrogen/generated/android/c++/JNowPlayingMetadata.hpp +1 -1
  163. package/nitrogen/generated/android/c++/JNowPlayingUpdate.hpp +1 -1
  164. package/nitrogen/generated/android/c++/JOptions.hpp +1 -1
  165. package/nitrogen/generated/android/c++/JPartialAndroidSetupPlayerOptions.hpp +1 -1
  166. package/nitrogen/generated/android/c++/JPartialIOSSetupPlayerOptions.hpp +1 -1
  167. package/nitrogen/generated/android/c++/JPartialSetupPlayerOptions.hpp +1 -1
  168. package/nitrogen/generated/android/c++/JPercentageRating.hpp +1 -1
  169. package/nitrogen/generated/android/c++/JPlayback.hpp +1 -1
  170. package/nitrogen/generated/android/c++/JPlaybackActiveTrackChangedEvent.hpp +4 -1
  171. package/nitrogen/generated/android/c++/JPlaybackError.hpp +1 -1
  172. package/nitrogen/generated/android/c++/JPlaybackErrorEvent.hpp +1 -1
  173. package/nitrogen/generated/android/c++/JPlaybackPlayWhenReadyChangedEvent.hpp +1 -1
  174. package/nitrogen/generated/android/c++/JPlaybackProgressUpdatedEvent.hpp +1 -1
  175. package/nitrogen/generated/android/c++/JPlaybackQueueEndedEvent.hpp +1 -1
  176. package/nitrogen/generated/android/c++/JPlaybackState.hpp +10 -11
  177. package/nitrogen/generated/android/c++/JPlayerCapabilities.hpp +1 -1
  178. package/nitrogen/generated/android/c++/JPlayingState.hpp +1 -1
  179. package/nitrogen/generated/android/c++/JProgress.hpp +1 -1
  180. package/nitrogen/generated/android/c++/JRatingType.hpp +8 -9
  181. package/nitrogen/generated/android/c++/JRemoteJumpBackwardEvent.hpp +1 -1
  182. package/nitrogen/generated/android/c++/JRemoteJumpForwardEvent.hpp +1 -1
  183. package/nitrogen/generated/android/c++/JRemotePlayIdEvent.hpp +1 -1
  184. package/nitrogen/generated/android/c++/JRemotePlaySearchEvent.hpp +1 -1
  185. package/nitrogen/generated/android/c++/JRemoteSeekEvent.hpp +1 -1
  186. package/nitrogen/generated/android/c++/JRemoteSetRatingEvent.hpp +1 -1
  187. package/nitrogen/generated/android/c++/JRemoteSkipEvent.hpp +1 -1
  188. package/nitrogen/generated/android/c++/JRepeatMode.hpp +4 -5
  189. package/nitrogen/generated/android/c++/JRepeatModeChangedEvent.hpp +1 -1
  190. package/nitrogen/generated/android/c++/JRequestConfig.hpp +1 -1
  191. package/nitrogen/generated/android/c++/JResolvedTrack.hpp +34 -4
  192. package/nitrogen/generated/android/c++/JRetryConfig.hpp +1 -1
  193. package/nitrogen/generated/android/c++/JSearchMode.hpp +7 -8
  194. package/nitrogen/generated/android/c++/JSearchParams.hpp +1 -1
  195. package/nitrogen/generated/android/c++/JSleepTimer.cpp +1 -1
  196. package/nitrogen/generated/android/c++/JSleepTimer.hpp +4 -4
  197. package/nitrogen/generated/android/c++/JSleepTimerEndOfTrack.hpp +1 -1
  198. package/nitrogen/generated/android/c++/JSleepTimerTime.hpp +1 -1
  199. package/nitrogen/generated/android/c++/JStarRating.hpp +1 -1
  200. package/nitrogen/generated/android/c++/JThumbsRating.hpp +1 -1
  201. package/nitrogen/generated/android/c++/JTimedMetadata.hpp +1 -1
  202. package/nitrogen/generated/android/c++/JTrack.hpp +29 -4
  203. package/nitrogen/generated/android/c++/{JRemoteLoadEvent.hpp → JTrackLoadEvent.hpp} +13 -11
  204. package/nitrogen/generated/android/c++/JTrackMetadata.hpp +1 -1
  205. package/nitrogen/generated/android/c++/JTrackStyle.hpp +3 -4
  206. package/nitrogen/generated/android/c++/JTransformableRequestConfig.hpp +1 -1
  207. package/nitrogen/generated/android/c++/JUpdateOptions.hpp +1 -1
  208. package/nitrogen/generated/android/c++/JVariant_Boolean_AndroidAudioOffloadSettings.cpp +1 -1
  209. package/nitrogen/generated/android/c++/JVariant_Boolean_AndroidAudioOffloadSettings.hpp +3 -3
  210. package/nitrogen/generated/android/c++/JVariant_Boolean_RetryConfig.cpp +1 -1
  211. package/nitrogen/generated/android/c++/JVariant_Boolean_RetryConfig.hpp +3 -3
  212. package/nitrogen/generated/android/c++/JVariant_HeartRating_ThumbsRating_StarRating_PercentageRating.cpp +1 -1
  213. package/nitrogen/generated/android/c++/JVariant_HeartRating_ThumbsRating_StarRating_PercentageRating.hpp +5 -5
  214. package/nitrogen/generated/android/c++/JVariant_NullType_Double.cpp +1 -1
  215. package/nitrogen/generated/android/c++/JVariant_NullType_Double.hpp +3 -3
  216. package/nitrogen/generated/android/c++/JVariant_NullType_NotificationButtonLayout.cpp +1 -1
  217. package/nitrogen/generated/android/c++/JVariant_NullType_NotificationButtonLayout.hpp +3 -3
  218. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidAudioContentType.kt +3 -1
  219. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidAudioOffloadSettings.kt +2 -2
  220. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidOptions.kt +2 -2
  221. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidPlayerWakeMode.kt +3 -1
  222. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidUpdateOptions.kt +2 -2
  223. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AppKilledPlaybackBehavior.kt +3 -1
  224. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ArtworkRequestConfig.kt +2 -2
  225. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AudioBrowserOnLoad.kt +1 -1
  226. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BatteryOptimizationStatus.kt +3 -1
  227. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BatteryOptimizationStatusChangedEvent.kt +2 -2
  228. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BatteryWarningPendingChangedEvent.kt +2 -2
  229. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BrowseError.kt +2 -2
  230. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BrowseResult.kt +1 -7
  231. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/BrowserSourceCallbackParam.kt +2 -2
  232. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/CarPlayNowPlayingButton.kt +3 -1
  233. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/CarPlaySiriListButtonPosition.kt +23 -0
  234. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ChapterMetadata.kt +2 -2
  235. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/EqualizerSettings.kt +2 -2
  236. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FavoriteChangedEvent.kt +2 -2
  237. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormatNavigationErrorParams.kt +2 -2
  238. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormattedNavigationError.kt +2 -2
  239. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_FormattedNavigationError____FormatNavigationErrorParams.kt +1 -1
  240. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____MediaTransformParams.kt +1 -1
  241. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____RequestConfig_std__optional_std__unordered_map_std__string__std__string__.kt +1 -1
  242. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____Track.kt +1 -1
  243. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.kt +1 -1
  244. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_Track______SearchParams.kt +1 -1
  245. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Func_void_RemoteLoadEvent.kt → Func_std__shared_ptr_Promise_std__shared_ptr_Promise_void_____TrackLoadEvent.kt} +14 -14
  246. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void.kt +1 -1
  247. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_BatteryOptimizationStatusChangedEvent.kt +1 -1
  248. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_BatteryWarningPendingChangedEvent.kt +1 -1
  249. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_EqualizerSettings.kt +1 -1
  250. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_FavoriteChangedEvent.kt +1 -1
  251. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_IosOutput.kt +1 -1
  252. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_NavigationErrorEvent.kt +1 -1
  253. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_NowPlayingMetadata.kt +1 -1
  254. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_Options.kt +1 -1
  255. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_Playback.kt +1 -1
  256. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackActiveTrackChangedEvent.kt +1 -1
  257. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackErrorEvent.kt +1 -1
  258. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackPlayWhenReadyChangedEvent.kt +1 -1
  259. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackProgressUpdatedEvent.kt +1 -1
  260. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlaybackQueueEndedEvent.kt +1 -1
  261. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_PlayingState.kt +1 -1
  262. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemoteJumpBackwardEvent.kt +1 -1
  263. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemoteJumpForwardEvent.kt +1 -1
  264. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemotePlayIdEvent.kt +1 -1
  265. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemotePlaySearchEvent.kt +1 -1
  266. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemoteSeekEvent.kt +1 -1
  267. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemoteSetRatingEvent.kt +1 -1
  268. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RemoteSkipEvent.kt +1 -1
  269. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_RepeatModeChangedEvent.kt +1 -1
  270. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_TimedMetadata.kt +1 -1
  271. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_TrackMetadata.kt +1 -1
  272. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_bool.kt +1 -1
  273. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_double.kt +1 -1
  274. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__optional_FormattedNavigationError_.kt +1 -1
  275. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__optional_ResolvedTrack_.kt +1 -1
  276. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__optional_std__variant_nitro__NullType__SleepTimerTime__SleepTimerEndOfTrack__.kt +1 -1
  277. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__string.kt +1 -1
  278. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__vector_ChapterMetadata_.kt +1 -1
  279. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_std__vector_Track_.kt +1 -1
  280. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/HeartRating.kt +2 -2
  281. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/HttpMethod.kt +3 -1
  282. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/HybridAudioBrowserSpec.kt +16 -47
  283. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IOSCategory.kt +3 -1
  284. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IOSCategoryMode.kt +3 -1
  285. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IOSCategoryOptions.kt +3 -1
  286. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IOSCategoryPolicy.kt +3 -1
  287. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageContext.kt +2 -2
  288. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageQueryParams.kt +2 -2
  289. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageRowItem.kt +47 -0
  290. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageSource.kt +2 -2
  291. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IosOutput.kt +2 -2
  292. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IosOutputType.kt +3 -1
  293. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaRequestConfig.kt +2 -2
  294. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaTransformParams.kt +2 -2
  295. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeBrowserConfiguration.kt +9 -6
  296. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeRouteEntry.kt +2 -2
  297. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeUpdateOptions.kt +2 -2
  298. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NavigationError.kt +2 -2
  299. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NavigationErrorEvent.kt +2 -2
  300. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NavigationErrorType.kt +3 -1
  301. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroAndroidUpdateOptions.kt +2 -2
  302. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NotificationButton.kt +3 -1
  303. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NotificationButtonLayout.kt +2 -2
  304. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingMetadata.kt +2 -2
  305. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingUpdate.kt +2 -2
  306. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Options.kt +2 -2
  307. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PartialAndroidSetupPlayerOptions.kt +2 -2
  308. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PartialIOSSetupPlayerOptions.kt +2 -2
  309. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PartialSetupPlayerOptions.kt +2 -2
  310. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PercentageRating.kt +2 -2
  311. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Playback.kt +2 -2
  312. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackActiveTrackChangedEvent.kt +2 -2
  313. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackError.kt +2 -2
  314. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackErrorEvent.kt +2 -2
  315. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackPlayWhenReadyChangedEvent.kt +2 -2
  316. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackProgressUpdatedEvent.kt +2 -2
  317. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackQueueEndedEvent.kt +2 -2
  318. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackState.kt +3 -1
  319. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlayerCapabilities.kt +2 -2
  320. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlayingState.kt +2 -2
  321. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Progress.kt +2 -2
  322. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RatingType.kt +3 -1
  323. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteJumpBackwardEvent.kt +2 -2
  324. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteJumpForwardEvent.kt +2 -2
  325. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemotePlayIdEvent.kt +2 -2
  326. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemotePlaySearchEvent.kt +2 -2
  327. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteSeekEvent.kt +2 -2
  328. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteSetRatingEvent.kt +2 -2
  329. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteSkipEvent.kt +2 -2
  330. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RepeatMode.kt +3 -1
  331. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RepeatModeChangedEvent.kt +2 -2
  332. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RequestConfig.kt +2 -2
  333. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ResolvedTrack.kt +11 -5
  334. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RetryConfig.kt +2 -2
  335. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SearchMode.kt +3 -1
  336. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SearchParams.kt +2 -2
  337. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SleepTimer.kt +1 -8
  338. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SleepTimerEndOfTrack.kt +2 -2
  339. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SleepTimerTime.kt +2 -2
  340. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/StarRating.kt +2 -2
  341. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ThumbsRating.kt +2 -2
  342. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TimedMetadata.kt +2 -2
  343. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Track.kt +8 -5
  344. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{RemoteLoadEvent.kt → TrackLoadEvent.kt} +7 -7
  345. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackMetadata.kt +2 -2
  346. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackStyle.kt +3 -1
  347. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TransformableRequestConfig.kt +2 -2
  348. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/UpdateOptions.kt +2 -2
  349. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_Boolean_AndroidAudioOffloadSettings.kt +1 -7
  350. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_Boolean_RetryConfig.kt +1 -7
  351. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_HeartRating_ThumbsRating_StarRating_PercentageRating.kt +1 -9
  352. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_NullType_Double.kt +1 -7
  353. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_NullType_NotificationButtonLayout.kt +1 -7
  354. package/nitrogen/generated/ios/AudioBrowser+autolinking.rb +2 -2
  355. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.cpp +23 -14
  356. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.hpp +239 -142
  357. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Umbrella.hpp +10 -4
  358. package/nitrogen/generated/ios/AudioBrowserAutolinking.mm +1 -1
  359. package/nitrogen/generated/ios/AudioBrowserAutolinking.swift +9 -8
  360. package/nitrogen/generated/ios/c++/HybridAudioBrowserSpecSwift.cpp +1 -1
  361. package/nitrogen/generated/ios/c++/HybridAudioBrowserSpecSwift.hpp +25 -18
  362. package/nitrogen/generated/ios/swift/AndroidAudioContentType.swift +1 -1
  363. package/nitrogen/generated/ios/swift/AndroidAudioOffloadSettings.swift +19 -44
  364. package/nitrogen/generated/ios/swift/AndroidOptions.swift +30 -74
  365. package/nitrogen/generated/ios/swift/AndroidPlayerWakeMode.swift +1 -1
  366. package/nitrogen/generated/ios/swift/AndroidUpdateOptions.swift +44 -112
  367. package/nitrogen/generated/ios/swift/AppKilledPlaybackBehavior.swift +1 -1
  368. package/nitrogen/generated/ios/swift/ArtworkRequestConfig.swift +152 -303
  369. package/nitrogen/generated/ios/swift/BatteryOptimizationStatus.swift +1 -1
  370. package/nitrogen/generated/ios/swift/BatteryOptimizationStatusChangedEvent.swift +3 -10
  371. package/nitrogen/generated/ios/swift/BatteryWarningPendingChangedEvent.swift +3 -10
  372. package/nitrogen/generated/ios/swift/BrowseError.swift +3 -10
  373. package/nitrogen/generated/ios/swift/BrowseResult.swift +1 -1
  374. package/nitrogen/generated/ios/swift/BrowserSourceCallbackParam.swift +20 -45
  375. package/nitrogen/generated/ios/swift/CarPlayNowPlayingButton.swift +1 -1
  376. package/nitrogen/generated/ios/swift/CarPlaySiriListButtonPosition.swift +40 -0
  377. package/nitrogen/generated/ios/swift/ChapterMetadata.swift +23 -60
  378. package/nitrogen/generated/ios/swift/EqualizerSettings.swift +24 -97
  379. package/nitrogen/generated/ios/swift/FavoriteChangedEvent.swift +5 -18
  380. package/nitrogen/generated/ios/swift/FormatNavigationErrorParams.swift +7 -26
  381. package/nitrogen/generated/ios/swift/FormattedNavigationError.swift +5 -18
  382. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__optional_FormattedNavigationError____FormatNavigationErrorParams.swift +1 -2
  383. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____MediaTransformParams.swift +1 -2
  384. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____RequestConfig_std__optional_std__unordered_map_std__string__std__string__.swift +1 -2
  385. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____Track.swift +1 -2
  386. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.swift +1 -2
  387. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_Track______SearchParams.swift +1 -2
  388. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_void_____TrackLoadEvent.swift +61 -0
  389. package/nitrogen/generated/ios/swift/Func_void.swift +1 -2
  390. package/nitrogen/generated/ios/swift/Func_void_BatteryOptimizationStatusChangedEvent.swift +1 -2
  391. package/nitrogen/generated/ios/swift/Func_void_BatteryWarningPendingChangedEvent.swift +1 -2
  392. package/nitrogen/generated/ios/swift/Func_void_EqualizerSettings.swift +1 -2
  393. package/nitrogen/generated/ios/swift/Func_void_FavoriteChangedEvent.swift +1 -2
  394. package/nitrogen/generated/ios/swift/Func_void_IosOutput.swift +1 -2
  395. package/nitrogen/generated/ios/swift/Func_void_NavigationErrorEvent.swift +1 -2
  396. package/nitrogen/generated/ios/swift/Func_void_NowPlayingMetadata.swift +1 -2
  397. package/nitrogen/generated/ios/swift/Func_void_Options.swift +1 -2
  398. package/nitrogen/generated/ios/swift/Func_void_Playback.swift +1 -2
  399. package/nitrogen/generated/ios/swift/Func_void_PlaybackActiveTrackChangedEvent.swift +1 -2
  400. package/nitrogen/generated/ios/swift/Func_void_PlaybackErrorEvent.swift +1 -2
  401. package/nitrogen/generated/ios/swift/Func_void_PlaybackPlayWhenReadyChangedEvent.swift +1 -2
  402. package/nitrogen/generated/ios/swift/Func_void_PlaybackProgressUpdatedEvent.swift +1 -2
  403. package/nitrogen/generated/ios/swift/Func_void_PlaybackQueueEndedEvent.swift +1 -2
  404. package/nitrogen/generated/ios/swift/Func_void_PlayingState.swift +1 -2
  405. package/nitrogen/generated/ios/swift/Func_void_RemoteJumpBackwardEvent.swift +1 -2
  406. package/nitrogen/generated/ios/swift/Func_void_RemoteJumpForwardEvent.swift +1 -2
  407. package/nitrogen/generated/ios/swift/Func_void_RemotePlayIdEvent.swift +1 -2
  408. package/nitrogen/generated/ios/swift/Func_void_RemotePlaySearchEvent.swift +1 -2
  409. package/nitrogen/generated/ios/swift/Func_void_RemoteSeekEvent.swift +1 -2
  410. package/nitrogen/generated/ios/swift/Func_void_RemoteSetRatingEvent.swift +1 -2
  411. package/nitrogen/generated/ios/swift/Func_void_RemoteSkipEvent.swift +1 -2
  412. package/nitrogen/generated/ios/swift/Func_void_RepeatModeChangedEvent.swift +1 -2
  413. package/nitrogen/generated/ios/swift/Func_void_RequestConfig.swift +1 -2
  414. package/nitrogen/generated/ios/swift/Func_void_TimedMetadata.swift +1 -2
  415. package/nitrogen/generated/ios/swift/Func_void_TrackMetadata.swift +1 -2
  416. package/nitrogen/generated/ios/swift/Func_void_bool.swift +1 -2
  417. package/nitrogen/generated/ios/swift/Func_void_double.swift +1 -2
  418. package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +1 -2
  419. package/nitrogen/generated/ios/swift/Func_void_std__optional_FormattedNavigationError_.swift +1 -2
  420. package/nitrogen/generated/ios/swift/Func_void_std__optional_ResolvedTrack_.swift +1 -2
  421. package/nitrogen/generated/ios/swift/Func_void_std__optional_std__variant_nitro__NullType__SleepTimerTime__SleepTimerEndOfTrack__.swift +1 -2
  422. package/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_RequestConfig__.swift +1 -2
  423. package/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError___.swift +1 -2
  424. package/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_std__vector_Track___.swift +1 -2
  425. package/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_void__.swift +64 -0
  426. package/nitrogen/generated/ios/swift/Func_void_std__string.swift +1 -2
  427. package/nitrogen/generated/ios/swift/Func_void_std__variant_ResolvedTrack__BrowseError_.swift +1 -2
  428. package/nitrogen/generated/ios/swift/Func_void_std__vector_ChapterMetadata_.swift +1 -2
  429. package/nitrogen/generated/ios/swift/Func_void_std__vector_Track_.swift +1 -2
  430. package/nitrogen/generated/ios/swift/HeartRating.swift +3 -10
  431. package/nitrogen/generated/ios/swift/HttpMethod.swift +1 -1
  432. package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec.swift +3 -6
  433. package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec_cxx.swift +56 -58
  434. package/nitrogen/generated/ios/swift/IOSCategory.swift +1 -1
  435. package/nitrogen/generated/ios/swift/IOSCategoryMode.swift +1 -1
  436. package/nitrogen/generated/ios/swift/IOSCategoryOptions.swift +1 -1
  437. package/nitrogen/generated/ios/swift/IOSCategoryPolicy.swift +1 -1
  438. package/nitrogen/generated/ios/swift/ImageContext.swift +19 -30
  439. package/nitrogen/generated/ios/swift/ImageQueryParams.swift +19 -44
  440. package/nitrogen/generated/ios/swift/ImageRowItem.swift +76 -0
  441. package/nitrogen/generated/ios/swift/ImageSource.swift +31 -80
  442. package/nitrogen/generated/ios/swift/IosOutput.swift +7 -26
  443. package/nitrogen/generated/ios/swift/IosOutputType.swift +1 -1
  444. package/nitrogen/generated/ios/swift/MediaRequestConfig.swift +162 -301
  445. package/nitrogen/generated/ios/swift/MediaTransformParams.swift +5 -24
  446. package/nitrogen/generated/ios/swift/NativeBrowserConfiguration.swift +143 -232
  447. package/nitrogen/generated/ios/swift/NativeRouteEntry.swift +81 -178
  448. package/nitrogen/generated/ios/swift/NativeUpdateOptions.swift +53 -125
  449. package/nitrogen/generated/ios/swift/NavigationError.swift +23 -53
  450. package/nitrogen/generated/ios/swift/NavigationErrorEvent.swift +3 -16
  451. package/nitrogen/generated/ios/swift/NavigationErrorType.swift +1 -1
  452. package/nitrogen/generated/ios/swift/NitroAndroidUpdateOptions.swift +44 -112
  453. package/nitrogen/generated/ios/swift/NotificationButton.swift +1 -1
  454. package/nitrogen/generated/ios/swift/NotificationButtonLayout.swift +18 -85
  455. package/nitrogen/generated/ios/swift/NowPlayingMetadata.swift +109 -227
  456. package/nitrogen/generated/ios/swift/NowPlayingUpdate.swift +19 -44
  457. package/nitrogen/generated/ios/swift/Options.swift +32 -88
  458. package/nitrogen/generated/ios/swift/PartialAndroidSetupPlayerOptions.swift +101 -201
  459. package/nitrogen/generated/ios/swift/PartialIOSSetupPlayerOptions.swift +25 -85
  460. package/nitrogen/generated/ios/swift/PartialSetupPlayerOptions.swift +35 -91
  461. package/nitrogen/generated/ios/swift/PercentageRating.swift +3 -10
  462. package/nitrogen/generated/ios/swift/Playback.swift +5 -24
  463. package/nitrogen/generated/ios/swift/PlaybackActiveTrackChangedEvent.swift +25 -66
  464. package/nitrogen/generated/ios/swift/PlaybackError.swift +5 -18
  465. package/nitrogen/generated/ios/swift/PlaybackErrorEvent.swift +3 -16
  466. package/nitrogen/generated/ios/swift/PlaybackPlayWhenReadyChangedEvent.swift +3 -10
  467. package/nitrogen/generated/ios/swift/PlaybackProgressUpdatedEvent.swift +9 -34
  468. package/nitrogen/generated/ios/swift/PlaybackQueueEndedEvent.swift +5 -18
  469. package/nitrogen/generated/ios/swift/PlaybackState.swift +1 -1
  470. package/nitrogen/generated/ios/swift/PlayerCapabilities.swift +109 -254
  471. package/nitrogen/generated/ios/swift/PlayingState.swift +5 -18
  472. package/nitrogen/generated/ios/swift/Progress.swift +7 -26
  473. package/nitrogen/generated/ios/swift/RatingType.swift +1 -1
  474. package/nitrogen/generated/ios/swift/RemoteJumpBackwardEvent.swift +3 -10
  475. package/nitrogen/generated/ios/swift/RemoteJumpForwardEvent.swift +3 -10
  476. package/nitrogen/generated/ios/swift/RemotePlayIdEvent.swift +12 -24
  477. package/nitrogen/generated/ios/swift/RemotePlaySearchEvent.swift +3 -10
  478. package/nitrogen/generated/ios/swift/RemoteSeekEvent.swift +3 -10
  479. package/nitrogen/generated/ios/swift/RemoteSetRatingEvent.swift +21 -39
  480. package/nitrogen/generated/ios/swift/RemoteSkipEvent.swift +3 -10
  481. package/nitrogen/generated/ios/swift/RepeatMode.swift +1 -1
  482. package/nitrogen/generated/ios/swift/RepeatModeChangedEvent.swift +3 -10
  483. package/nitrogen/generated/ios/swift/RequestConfig.swift +82 -191
  484. package/nitrogen/generated/ios/swift/ResolvedTrack.swift +164 -333
  485. package/nitrogen/generated/ios/swift/RetryConfig.swift +12 -24
  486. package/nitrogen/generated/ios/swift/SearchMode.swift +1 -1
  487. package/nitrogen/generated/ios/swift/SearchParams.swift +50 -129
  488. package/nitrogen/generated/ios/swift/SleepTimer.swift +1 -1
  489. package/nitrogen/generated/ios/swift/SleepTimerEndOfTrack.swift +3 -10
  490. package/nitrogen/generated/ios/swift/SleepTimerTime.swift +3 -10
  491. package/nitrogen/generated/ios/swift/StarRating.swift +3 -10
  492. package/nitrogen/generated/ios/swift/ThumbsRating.swift +3 -10
  493. package/nitrogen/generated/ios/swift/TimedMetadata.swift +46 -107
  494. package/nitrogen/generated/ios/swift/Track.swift +151 -319
  495. package/nitrogen/generated/ios/swift/TrackLoadEvent.swift +45 -0
  496. package/nitrogen/generated/ios/swift/TrackMetadata.swift +145 -338
  497. package/nitrogen/generated/ios/swift/TrackStyle.swift +1 -1
  498. package/nitrogen/generated/ios/swift/TransformableRequestConfig.swift +128 -252
  499. package/nitrogen/generated/ios/swift/UpdateOptions.swift +53 -125
  500. package/nitrogen/generated/ios/swift/Variant_Bool_AndroidAudioOffloadSettings.swift +1 -1
  501. package/nitrogen/generated/ios/swift/Variant_Bool_RetryConfig.swift +1 -1
  502. package/nitrogen/generated/ios/swift/Variant_HeartRating_ThumbsRating_StarRating_PercentageRating.swift +1 -1
  503. package/nitrogen/generated/ios/swift/Variant_NullType_Double.swift +1 -1
  504. package/nitrogen/generated/ios/swift/Variant_NullType_NotificationButtonLayout.swift +1 -1
  505. package/nitrogen/generated/shared/c++/AndroidAudioContentType.hpp +1 -1
  506. package/nitrogen/generated/shared/c++/AndroidAudioOffloadSettings.hpp +16 -8
  507. package/nitrogen/generated/shared/c++/AndroidOptions.hpp +25 -17
  508. package/nitrogen/generated/shared/c++/AndroidPlayerWakeMode.hpp +1 -1
  509. package/nitrogen/generated/shared/c++/AndroidUpdateOptions.hpp +25 -17
  510. package/nitrogen/generated/shared/c++/AppKilledPlaybackBehavior.hpp +1 -1
  511. package/nitrogen/generated/shared/c++/ArtworkRequestConfig.hpp +43 -35
  512. package/nitrogen/generated/shared/c++/BatteryOptimizationStatus.hpp +1 -1
  513. package/nitrogen/generated/shared/c++/BatteryOptimizationStatusChangedEvent.hpp +13 -5
  514. package/nitrogen/generated/shared/c++/BatteryWarningPendingChangedEvent.hpp +13 -5
  515. package/nitrogen/generated/shared/c++/BrowseError.hpp +13 -5
  516. package/nitrogen/generated/shared/c++/BrowserSourceCallbackParam.hpp +16 -8
  517. package/nitrogen/generated/shared/c++/CarPlayNowPlayingButton.hpp +1 -1
  518. package/nitrogen/generated/shared/c++/CarPlaySiriListButtonPosition.hpp +76 -0
  519. package/nitrogen/generated/shared/c++/ChapterMetadata.hpp +22 -14
  520. package/nitrogen/generated/shared/c++/EqualizerSettings.hpp +34 -26
  521. package/nitrogen/generated/shared/c++/FavoriteChangedEvent.hpp +16 -8
  522. package/nitrogen/generated/shared/c++/FormatNavigationErrorParams.hpp +19 -11
  523. package/nitrogen/generated/shared/c++/FormattedNavigationError.hpp +16 -8
  524. package/nitrogen/generated/shared/c++/HeartRating.hpp +13 -5
  525. package/nitrogen/generated/shared/c++/HttpMethod.hpp +1 -1
  526. package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.cpp +1 -5
  527. package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.hpp +1 -8
  528. package/nitrogen/generated/shared/c++/IOSCategory.hpp +1 -1
  529. package/nitrogen/generated/shared/c++/IOSCategoryMode.hpp +1 -1
  530. package/nitrogen/generated/shared/c++/IOSCategoryOptions.hpp +1 -1
  531. package/nitrogen/generated/shared/c++/IOSCategoryPolicy.hpp +1 -1
  532. package/nitrogen/generated/shared/c++/ImageContext.hpp +16 -8
  533. package/nitrogen/generated/shared/c++/ImageQueryParams.hpp +16 -8
  534. package/nitrogen/generated/shared/c++/ImageRowItem.hpp +98 -0
  535. package/nitrogen/generated/shared/c++/ImageSource.hpp +22 -14
  536. package/nitrogen/generated/shared/c++/IosOutput.hpp +19 -11
  537. package/nitrogen/generated/shared/c++/IosOutputType.hpp +1 -1
  538. package/nitrogen/generated/shared/c++/MediaRequestConfig.hpp +40 -32
  539. package/nitrogen/generated/shared/c++/MediaTransformParams.hpp +16 -8
  540. package/nitrogen/generated/shared/c++/NativeBrowserConfiguration.hpp +50 -35
  541. package/nitrogen/generated/shared/c++/NativeRouteEntry.hpp +34 -26
  542. package/nitrogen/generated/shared/c++/NativeUpdateOptions.hpp +28 -20
  543. package/nitrogen/generated/shared/c++/NavigationError.hpp +22 -14
  544. package/nitrogen/generated/shared/c++/NavigationErrorEvent.hpp +13 -5
  545. package/nitrogen/generated/shared/c++/NavigationErrorType.hpp +1 -1
  546. package/nitrogen/generated/shared/c++/NitroAndroidUpdateOptions.hpp +25 -17
  547. package/nitrogen/generated/shared/c++/NotificationButton.hpp +1 -1
  548. package/nitrogen/generated/shared/c++/NotificationButtonLayout.hpp +25 -17
  549. package/nitrogen/generated/shared/c++/NowPlayingMetadata.hpp +40 -32
  550. package/nitrogen/generated/shared/c++/NowPlayingUpdate.hpp +16 -8
  551. package/nitrogen/generated/shared/c++/Options.hpp +28 -20
  552. package/nitrogen/generated/shared/c++/PartialAndroidSetupPlayerOptions.hpp +40 -32
  553. package/nitrogen/generated/shared/c++/PartialIOSSetupPlayerOptions.hpp +25 -17
  554. package/nitrogen/generated/shared/c++/PartialSetupPlayerOptions.hpp +22 -14
  555. package/nitrogen/generated/shared/c++/PercentageRating.hpp +13 -5
  556. package/nitrogen/generated/shared/c++/Playback.hpp +16 -8
  557. package/nitrogen/generated/shared/c++/PlaybackActiveTrackChangedEvent.hpp +25 -17
  558. package/nitrogen/generated/shared/c++/PlaybackError.hpp +16 -8
  559. package/nitrogen/generated/shared/c++/PlaybackErrorEvent.hpp +13 -5
  560. package/nitrogen/generated/shared/c++/PlaybackPlayWhenReadyChangedEvent.hpp +13 -5
  561. package/nitrogen/generated/shared/c++/PlaybackProgressUpdatedEvent.hpp +22 -14
  562. package/nitrogen/generated/shared/c++/PlaybackQueueEndedEvent.hpp +16 -8
  563. package/nitrogen/generated/shared/c++/PlaybackState.hpp +1 -1
  564. package/nitrogen/generated/shared/c++/PlayerCapabilities.hpp +46 -38
  565. package/nitrogen/generated/shared/c++/PlayingState.hpp +16 -8
  566. package/nitrogen/generated/shared/c++/Progress.hpp +19 -11
  567. package/nitrogen/generated/shared/c++/RatingType.hpp +1 -1
  568. package/nitrogen/generated/shared/c++/RemoteJumpBackwardEvent.hpp +13 -5
  569. package/nitrogen/generated/shared/c++/RemoteJumpForwardEvent.hpp +13 -5
  570. package/nitrogen/generated/shared/c++/RemotePlayIdEvent.hpp +16 -8
  571. package/nitrogen/generated/shared/c++/RemotePlaySearchEvent.hpp +13 -5
  572. package/nitrogen/generated/shared/c++/RemoteSeekEvent.hpp +13 -5
  573. package/nitrogen/generated/shared/c++/RemoteSetRatingEvent.hpp +13 -5
  574. package/nitrogen/generated/shared/c++/RemoteSkipEvent.hpp +13 -5
  575. package/nitrogen/generated/shared/c++/RepeatMode.hpp +1 -1
  576. package/nitrogen/generated/shared/c++/RepeatModeChangedEvent.hpp +13 -5
  577. package/nitrogen/generated/shared/c++/RequestConfig.hpp +34 -26
  578. package/nitrogen/generated/shared/c++/ResolvedTrack.hpp +79 -57
  579. package/nitrogen/generated/shared/c++/RetryConfig.hpp +16 -8
  580. package/nitrogen/generated/shared/c++/SearchMode.hpp +1 -1
  581. package/nitrogen/generated/shared/c++/SearchParams.hpp +31 -23
  582. package/nitrogen/generated/shared/c++/SleepTimerEndOfTrack.hpp +13 -5
  583. package/nitrogen/generated/shared/c++/SleepTimerTime.hpp +13 -5
  584. package/nitrogen/generated/shared/c++/StarRating.hpp +13 -5
  585. package/nitrogen/generated/shared/c++/ThumbsRating.hpp +13 -5
  586. package/nitrogen/generated/shared/c++/TimedMetadata.hpp +25 -17
  587. package/nitrogen/generated/shared/c++/Track.hpp +70 -54
  588. package/nitrogen/generated/shared/c++/{RemoteLoadEvent.hpp → TrackLoadEvent.hpp} +28 -20
  589. package/nitrogen/generated/shared/c++/TrackMetadata.hpp +58 -50
  590. package/nitrogen/generated/shared/c++/TrackStyle.hpp +1 -1
  591. package/nitrogen/generated/shared/c++/TransformableRequestConfig.hpp +37 -29
  592. package/nitrogen/generated/shared/c++/UpdateOptions.hpp +28 -20
  593. package/package.json +6 -7
  594. package/src/features/browser.ts +1 -0
  595. package/src/features/remoteControls.ts +0 -35
  596. package/src/specs/audio-browser.nitro.ts +0 -3
  597. package/src/types/browser-native.ts +2 -0
  598. package/src/types/browser-nodes.ts +49 -1
  599. package/src/types/browser.ts +36 -0
  600. package/src/web/NativeAudioBrowser.ts +19 -24
  601. package/src/web/SimpleRouter.test.ts +160 -0
  602. package/src/web/SimpleRouter.ts +10 -8
  603. package/nitrogen/generated/android/c++/JFunc_void_RemoteLoadEvent.hpp +0 -89
  604. package/nitrogen/generated/ios/swift/Func_void_RemoteLoadEvent.swift +0 -47
  605. package/nitrogen/generated/ios/swift/RemoteLoadEvent.swift +0 -70
@@ -26,26 +26,25 @@ extension Track {
26
26
  /// Uses Kingfisher for caching and efficient image loading
27
27
  func loadArtwork() async -> UIImage? {
28
28
  // Try artworkSource first (has more detailed config), then fall back to artwork string
29
+ // Skip SF Symbol strings - those require SFSymbolRenderer and can't be loaded as URLs
29
30
  let artworkUrlString: String?
30
31
  let artworkHeaders: [String: String]?
31
32
 
32
33
  if let source = artworkSource {
33
34
  artworkUrlString = source.uri
34
35
  artworkHeaders = source.headers
35
- } else {
36
+ } else if let artwork, !SFSymbolRenderer.isSFSymbol(artwork) {
36
37
  artworkUrlString = artwork
37
38
  artworkHeaders = nil
39
+ } else {
40
+ artworkUrlString = nil
41
+ artworkHeaders = nil
38
42
  }
39
43
 
40
44
  guard let urlString = artworkUrlString, let url = URL(string: urlString) else {
41
45
  return nil
42
46
  }
43
47
 
44
- if url.isFileURL {
45
- return UIImage(contentsOfFile: url.path)
46
- }
47
-
48
- // Build Kingfisher options with headers if provided
49
48
  var options: KingfisherOptionsInfo = []
50
49
  if let headers = artworkHeaders, !headers.isEmpty {
51
50
  let modifier = AnyModifier { request in
@@ -122,7 +122,7 @@ extension TrackMetadata {
122
122
  mediaType: nil,
123
123
  creationDate: creationDate,
124
124
  creationYear: creationYear,
125
- url: nil
125
+ url: nil,
126
126
  )
127
127
  }
128
128
  }
@@ -48,12 +48,6 @@ public class HybridAudioBrowser: HybridAudioBrowserSpec, @unchecked Sendable {
48
48
  }
49
49
  }
50
50
 
51
- // MARK: - Internal Callbacks (for CarPlay/external controllers)
52
-
53
- /// Called when notifyContentChanged is invoked, allowing CarPlay to refresh its templates.
54
- /// Set by CarPlayController during setup.
55
- var onExternalContentChanged: ((String) -> Void)?
56
-
57
51
  // MARK: - Multi-Listener Emitters
58
52
 
59
53
  /// Emitters allow multiple listeners for each event type, avoiding callback hijacking
@@ -114,8 +108,8 @@ public class HybridAudioBrowser: HybridAudioBrowserSpec, @unchecked Sendable {
114
108
 
115
109
  public var configuration: NativeBrowserConfiguration = .init(
116
110
  path: nil, request: nil, media: nil, artwork: nil, routes: nil,
117
- singleTrack: nil, androidControllerOfflineError: nil, carPlayUpNextButton: nil,
118
- carPlayNowPlayingButtons: nil, formatNavigationError: nil,
111
+ singleTrack: nil, handleTrackLoad: nil, androidControllerOfflineError: nil,
112
+ carPlayUpNextButton: nil, carPlayNowPlayingButtons: nil, formatNavigationError: nil,
119
113
  ) {
120
114
  didSet {
121
115
  browserManager.config = BrowserConfig(from: configuration)
@@ -175,7 +169,6 @@ public class HybridAudioBrowser: HybridAudioBrowserSpec, @unchecked Sendable {
175
169
  public var onRemoteJumpBackward: (RemoteJumpBackwardEvent) -> Void = { _ in }
176
170
  public var onRemoteJumpForward: (RemoteJumpForwardEvent) -> Void = { _ in }
177
171
  public var onRemoteLike: () -> Void = {}
178
- public var onRemoteLoad: (RemoteLoadEvent) -> Void = { _ in }
179
172
  public var onRemoteNext: () -> Void = {}
180
173
  public var onRemotePause: () -> Void = {}
181
174
  public var onRemotePlay: () -> Void = {}
@@ -194,7 +187,6 @@ public class HybridAudioBrowser: HybridAudioBrowserSpec, @unchecked Sendable {
194
187
  public var handleRemoteJumpBackward: ((RemoteJumpBackwardEvent) -> Void)?
195
188
  public var handleRemoteJumpForward: ((RemoteJumpForwardEvent) -> Void)?
196
189
  public var handleRemoteLike: (() -> Void)?
197
- public var handleRemoteLoad: ((RemoteLoadEvent) -> Void)?
198
190
  public var handleRemoteNext: (() -> Void)?
199
191
  public var handleRemotePause: (() -> Void)?
200
192
  public var handleRemotePlay: (() -> Void)?
@@ -228,6 +220,7 @@ public class HybridAudioBrowser: HybridAudioBrowserSpec, @unchecked Sendable {
228
220
  setupVolumeObserver()
229
221
  }
230
222
  }
223
+
231
224
  public var onIosOutputChanged: (IosOutput) -> Void = { _ in } {
232
225
  didSet {
233
226
  setupRouteChangeObserver()
@@ -238,11 +231,30 @@ public class HybridAudioBrowser: HybridAudioBrowserSpec, @unchecked Sendable {
238
231
 
239
232
  override public init() {
240
233
  super.init()
241
- HybridAudioBrowser.shared = self
234
+
235
+ // Clean up the previous instance (e.g., on JS runtime reload).
236
+ // The old HybridAudioBrowser may still be retained by the global
237
+ // playerAndConfiguredBrowser OnceValue, so we must explicitly stop
238
+ // its player to prevent two audio streams running simultaneously.
239
+ onMainActor {
240
+ HybridAudioBrowser.shared?.player?.destroy()
241
+ playerAndConfiguredBrowser.reset()
242
+ HybridAudioBrowser.shared = self
243
+ }
242
244
  setupEmitterToNitroForwarding()
243
245
  setupBrowserCallbacks()
244
246
  }
245
247
 
248
+ deinit {
249
+ // Safety net: ensure the AVPlayer is stopped if this instance is deallocated.
250
+ let player = self.player
251
+ if Thread.isMainThread {
252
+ MainActor.assumeIsolated { player?.destroy() }
253
+ } else {
254
+ DispatchQueue.main.async { MainActor.assumeIsolated { player?.destroy() } }
255
+ }
256
+ }
257
+
246
258
  /// Returns the TrackPlayer instance, if setup has been called.
247
259
  func getPlayer() -> TrackPlayer? {
248
260
  player
@@ -327,13 +339,16 @@ public class HybridAudioBrowser: HybridAudioBrowserSpec, @unchecked Sendable {
327
339
  let defaultFormatted = defaultFormattedError(navError)
328
340
  if let formatter = browserManager.config.formatNavigationError {
329
341
  let params = FormatNavigationErrorParams(error: navError, defaultFormatted: defaultFormatted, path: path)
330
- formatter(params)
331
- .then { [weak self] customDisplay in
332
- self?.lastFormattedNavigationError = customDisplay ?? defaultFormatted
333
- }
334
- .catch { [weak self] _ in
335
- self?.lastFormattedNavigationError = defaultFormatted
336
- }
342
+ // Dispatch to main thread for the Nitro bridge call to avoid C++ noexcept crashes
343
+ DispatchQueue.main.async { [weak self] in
344
+ formatter(params)
345
+ .then { customDisplay in
346
+ self?.lastFormattedNavigationError = customDisplay ?? defaultFormatted
347
+ }
348
+ .catch { _ in
349
+ self?.lastFormattedNavigationError = defaultFormatted
350
+ }
351
+ }
337
352
  } else {
338
353
  lastFormattedNavigationError = defaultFormatted
339
354
  }
@@ -375,21 +390,15 @@ public class HybridAudioBrowser: HybridAudioBrowserSpec, @unchecked Sendable {
375
390
  }
376
391
  }
377
392
 
378
- /// Centralizes handleRemoteLoad interception logic.
379
- /// If handleRemoteLoad is set, calls it (intercepted). Otherwise runs defaultBehavior.
380
- /// Always fires onRemoteLoad afterward.
393
+ /// Centralizes handleTrackLoad interception logic.
394
+ /// If handleTrackLoad is set on config, awaits it (intercepted). Otherwise runs defaultBehavior.
381
395
  ///
382
396
  /// - Returns: true if the handler intercepted, false if defaultBehavior ran
383
397
  @discardableResult
384
- private func handleLoad(track: Track, queue: [Track], startIndex: Double, defaultBehavior: () -> Void) -> Bool {
385
- let event = RemoteLoadEvent(track: track, queue: queue, startIndex: startIndex)
386
- if let handler = handleRemoteLoad {
387
- handler(event)
388
- onRemoteLoad(event)
389
- return true
390
- }
391
- defaultBehavior()
392
- onRemoteLoad(event)
398
+ private func handleLoadAsync(track: Track, queue: [Track], startIndex: Double, defaultBehavior: () async -> Void) async -> Bool {
399
+ let event = TrackLoadEvent(track: track, queue: queue, startIndex: startIndex)
400
+ if await browserManager.config.awaitTrackLoadHandler(event: event) { return true }
401
+ await defaultBehavior()
393
402
  return false
394
403
  }
395
404
 
@@ -412,9 +421,17 @@ public class HybridAudioBrowser: HybridAudioBrowserSpec, @unchecked Sendable {
412
421
  if let index = existingIndex {
413
422
  logger.debug("Queue already from \(parentPath), skipping to index \(index)")
414
423
  let queue: [Track] = onMainActor { player?.tracks ?? [] }
415
- handleLoad(track: track, queue: queue, startIndex: Double(index)) {
416
- onMainActor {
417
- try? player?.skipTo(index, playWhenReady: true)
424
+ Task {
425
+ await handleLoadAsync(track: track, queue: queue, startIndex: Double(index)) {
426
+ do {
427
+ try onMainActor {
428
+ try player?.skipTo(index, playWhenReady: true)
429
+ }
430
+ } catch {
431
+ // NOTE: because we have a throwing closure here, the thrown error
432
+ // can't be propogated up. Log it out instead.
433
+ logger.error("Failed to skip to track at index \(index): \(error)")
434
+ }
418
435
  }
419
436
  }
420
437
  return
@@ -425,7 +442,7 @@ public class HybridAudioBrowser: HybridAudioBrowserSpec, @unchecked Sendable {
425
442
  // Expand the queue from the contextual URL
426
443
  if let expanded = try await browserManager.expandQueueFromContextualUrl(url) {
427
444
  let (tracks, startIndex) = expanded
428
- handleLoad(track: track, queue: tracks, startIndex: Double(startIndex)) {
445
+ await handleLoadAsync(track: track, queue: tracks, startIndex: Double(startIndex)) {
429
446
  // Replace queue and start at the selected track (auto-play)
430
447
  onMainActor {
431
448
  player?.setQueue(tracks, initialIndex: startIndex, playWhenReady: true, sourcePath: parentPath)
@@ -433,7 +450,7 @@ public class HybridAudioBrowser: HybridAudioBrowserSpec, @unchecked Sendable {
433
450
  }
434
451
  } else {
435
452
  // Fallback: just load the single track (auto-play)
436
- handleLoad(track: track, queue: [track], startIndex: 0) {
453
+ await handleLoadAsync(track: track, queue: [track], startIndex: 0) {
437
454
  onMainActor {
438
455
  player?.load(track, playWhenReady: true)
439
456
  }
@@ -442,7 +459,7 @@ public class HybridAudioBrowser: HybridAudioBrowserSpec, @unchecked Sendable {
442
459
  } catch {
443
460
  logger.error("Error expanding queue: \(error.localizedDescription)")
444
461
  // Fallback to single track (auto-play) - playback errors reported via TrackPlayer callbacks
445
- handleLoad(track: track, queue: [track], startIndex: 0) {
462
+ await handleLoadAsync(track: track, queue: [track], startIndex: 0) {
446
463
  onMainActor {
447
464
  player?.load(track, playWhenReady: true)
448
465
  }
@@ -452,9 +469,11 @@ public class HybridAudioBrowser: HybridAudioBrowserSpec, @unchecked Sendable {
452
469
  }
453
470
  // If track has src, it's playable - load and auto-play
454
471
  else if track.src != nil {
455
- handleLoad(track: track, queue: [track], startIndex: 0) {
456
- onMainActor {
457
- player?.load(track, playWhenReady: true)
472
+ Task {
473
+ await handleLoadAsync(track: track, queue: [track], startIndex: 0) {
474
+ onMainActor {
475
+ player?.load(track, playWhenReady: true)
476
+ }
458
477
  }
459
478
  }
460
479
  }
@@ -497,7 +516,6 @@ public class HybridAudioBrowser: HybridAudioBrowserSpec, @unchecked Sendable {
497
516
  browserManager.invalidateContentCache(path)
498
517
 
499
518
  // Notify external controllers (CarPlay) that content changed
500
- onExternalContentChanged?(path)
501
519
  externalContentChangedEmitter.emit(path)
502
520
 
503
521
  // Re-resolve the path if it's the current browser path
@@ -828,9 +846,10 @@ public class HybridAudioBrowser: HybridAudioBrowserSpec, @unchecked Sendable {
828
846
  favorited: favorited,
829
847
  groupTitle: track.groupTitle,
830
848
  live: track.live,
849
+ imageRow: track.imageRow,
831
850
  )
832
851
  // Update the track in the player's queue so getActiveTrack() returns correct state
833
- player?.setTrack(at: index, updatedTrack)
852
+ player?.replace(index, updatedTrack)
834
853
  favoriteChangedEmitter.emit(FavoriteChangedEvent(track: updatedTrack, favorited: favorited))
835
854
  // Fire active track changed so useActiveTrack() hook updates UI
836
855
  let position = player?.currentTime ?? 0
@@ -911,7 +930,7 @@ public class HybridAudioBrowser: HybridAudioBrowserSpec, @unchecked Sendable {
911
930
  album: track.album,
912
931
  artist: override?.artist ?? track.artist,
913
932
  duration: track.duration,
914
- artwork: track.artwork,
933
+ artwork: nowPlayingArtwork(for: track),
915
934
  description: track.description,
916
935
  mediaId: track.src ?? track.url,
917
936
  genre: track.genre,
@@ -920,6 +939,15 @@ public class HybridAudioBrowser: HybridAudioBrowserSpec, @unchecked Sendable {
920
939
  }
921
940
  }
922
941
 
942
+ /// Returns the artwork URI suitable for JS consumption.
943
+ /// Prefers the resolved artworkSource URI (e.g. file:// for rendered SF Symbols).
944
+ /// Falls back to the raw artwork string only if it's not an SF Symbol (which JS can't load).
945
+ private func nowPlayingArtwork(for track: Track) -> String? {
946
+ if let uri = track.artworkSource?.uri { return uri }
947
+ guard let artwork = track.artwork else { return nil }
948
+ return SFSymbolRenderer.isSFSymbol(artwork) ? nil : artwork
949
+ }
950
+
923
951
  /// Applies the current now playing metadata (with override if set) to NowPlayingInfoCenter and notifies JS.
924
952
  @MainActor
925
953
  private func applyNowPlayingMetadata() {
@@ -932,7 +960,7 @@ public class HybridAudioBrowser: HybridAudioBrowserSpec, @unchecked Sendable {
932
960
  album: track.album,
933
961
  artist: override?.artist ?? track.artist,
934
962
  duration: track.duration,
935
- artwork: track.artwork,
963
+ artwork: nowPlayingArtwork(for: track),
936
964
  description: track.description,
937
965
  mediaId: track.src ?? track.url,
938
966
  genre: track.genre,
@@ -989,7 +1017,7 @@ public class HybridAudioBrowser: HybridAudioBrowserSpec, @unchecked Sendable {
989
1017
  routeChangeObserver = NotificationCenter.default.addObserver(
990
1018
  forName: AVAudioSession.routeChangeNotification,
991
1019
  object: nil,
992
- queue: .main
1020
+ queue: .main,
993
1021
  ) { [weak self] _ in
994
1022
  guard let self, let output = self.getCurrentOutput() else { return }
995
1023
  self.onIosOutputChanged(output)
@@ -1038,15 +1066,21 @@ public class HybridAudioBrowser: HybridAudioBrowserSpec, @unchecked Sendable {
1038
1066
  guard let windowScene = UIApplication.shared.connectedScenes
1039
1067
  .compactMap({ $0 as? UIWindowScene })
1040
1068
  .first(where: { $0.activationState == .foregroundActive }),
1041
- let window = windowScene.windows.first(where: { $0.isKeyWindow })
1069
+ let window = windowScene.windows.first(where: { $0.isKeyWindow }),
1070
+ var topController = window.rootViewController
1042
1071
  else {
1043
1072
  self?.logger.debug("openIosOutputPicker: Could not find active window scene")
1044
1073
  return
1045
1074
  }
1046
1075
 
1076
+ // Walk up to the topmost presented view controller
1077
+ while let presented = topController.presentedViewController {
1078
+ topController = presented
1079
+ }
1080
+
1047
1081
  let routePicker = AVRoutePickerView(frame: .zero)
1048
1082
  routePicker.isHidden = true
1049
- window.addSubview(routePicker)
1083
+ topController.view.addSubview(routePicker)
1050
1084
 
1051
1085
  // Find the button inside AVRoutePickerView and trigger it
1052
1086
  for subview in routePicker.subviews {
@@ -1296,6 +1330,33 @@ extension HybridAudioBrowser: TrackPlayerCallbacks {
1296
1330
  }
1297
1331
  }
1298
1332
 
1333
+ /// Handles an INPlayMediaIntent by searching for the given term and starting playback.
1334
+ ///
1335
+ /// Host apps should call this from their `INPlayMediaIntentHandling` implementation.
1336
+ /// Uses the browser's search route to find tracks, then queues and plays them.
1337
+ ///
1338
+ /// - Parameters:
1339
+ /// - searchTerm: The search query from Siri.
1340
+ /// - completion: Called with `true` if tracks were found and queued, `false` otherwise.
1341
+ public func handlePlayMediaIntent(searchTerm: String, completion: @escaping @Sendable (Bool) -> Void) {
1342
+ Task {
1343
+ do {
1344
+ let resolved = try await self.browserManager.search(searchTerm)
1345
+ guard let tracks = resolved.children, !tracks.isEmpty else {
1346
+ completion(false)
1347
+ return
1348
+ }
1349
+ await MainActor.run {
1350
+ self.getPlayer()?.setQueue(tracks, initialIndex: 0, playWhenReady: true)
1351
+ }
1352
+ completion(true)
1353
+ } catch {
1354
+ self.logger.error("handlePlayMediaIntent failed: \(error.localizedDescription)")
1355
+ completion(false)
1356
+ }
1357
+ }
1358
+ }
1359
+
1299
1360
  public func remoteLike() {
1300
1361
  if let handler = handleRemoteLike {
1301
1362
  handler()
@@ -45,7 +45,8 @@ struct MediaURL {
45
45
  allowed.formUnion(.urlQueryAllowed)
46
46
  allowed.formUnion(.urlFragmentAllowed)
47
47
  if let encoded = string.addingPercentEncoding(withAllowedCharacters: allowed),
48
- let url = URL(string: encoded) {
48
+ let url = URL(string: encoded)
49
+ {
49
50
  return url
50
51
  }
51
52
  }
@@ -2,6 +2,7 @@ import Foundation
2
2
  import NitroModules
3
3
 
4
4
  /// Manages the playing state (playing and buffering flags) and notifies when they change.
5
+ @MainActor
5
6
  class PlayingStateManager {
6
7
  private(set) var playing: Bool = false
7
8
  private(set) var buffering: Bool = false
@@ -12,39 +12,31 @@ import os.log
12
12
  class RetryManager {
13
13
  private let logger = Logger(subsystem: "com.audiobrowser", category: "RetryManager")
14
14
 
15
- /// Retry policy configuration
16
15
  enum Policy {
17
16
  case disabled
18
17
  case infinite
19
18
  case limited(maxRetries: Int)
20
19
  }
21
20
 
22
- /// Default maximum duration to keep retrying before giving up (in milliseconds).
23
21
  private static let defaultMaxRetryDurationMs: Double = 120_000 // 2 minutes
24
22
 
25
- /// Maximum duration to keep retrying before giving up (in seconds).
26
- /// This prevents surprising playback resumption after long periods offline.
23
+ /// Prevents surprising playback resumption after long periods offline.
27
24
  private var maxRetryDuration: TimeInterval = defaultMaxRetryDurationMs / 1000
28
25
 
29
26
  private var policy: Policy = .disabled
30
27
  private var attemptCount = 0
31
28
  private var firstRetryTime: Date?
32
29
 
33
- /// Network monitor for accelerating retries when connectivity is restored
34
30
  weak var networkMonitor: NetworkMonitor?
35
-
36
- /// Flag to track if we're waiting for network (for cleanup on reset)
37
31
  private var isWaitingForNetwork = false
32
+ /// Invalidates in-flight retries when reset() is called (e.g. track change)
33
+ private var generation: Int = 0
38
34
 
39
- /// Callback to check if we should retry (typically checks playWhenReady)
40
35
  var shouldRetry: () -> Bool = { true }
41
-
42
- /// Callback to trigger reload
43
36
  var onRetry: ((Bool) -> Void)?
44
37
 
45
38
  // MARK: - Configuration
46
39
 
47
- /// Updates the retry policy from the Nitro config type
48
40
  func updatePolicy(from config: Variant_Bool_RetryConfig?) {
49
41
  guard let config else {
50
42
  policy = .disabled
@@ -61,7 +53,6 @@ class RetryManager {
61
53
  case let .second(retryConfig):
62
54
  let maxRetries = Int(retryConfig.maxRetries)
63
55
  policy = .limited(maxRetries: maxRetries)
64
- // Use configured duration or default
65
56
  let durationMs = retryConfig.maxRetryDurationMs ?? Self.defaultMaxRetryDurationMs
66
57
  maxRetryDuration = durationMs / 1000
67
58
  logger.debug("Retry policy: limited to \(maxRetries) retries, max duration \(self.maxRetryDuration)s")
@@ -70,9 +61,7 @@ class RetryManager {
70
61
 
71
62
  // MARK: - Exponential Backoff
72
63
 
73
- /// Calculates delay for current attempt using exponential backoff.
74
64
  /// Delays: 1s -> 1.5s -> 2.3s -> 3.4s -> 5s (capped)
75
- /// Returns delay in seconds.
76
65
  private func calculateDelaySeconds() -> Double {
77
66
  let baseDelay = 1.0
78
67
  let multiplier = 1.5
@@ -83,8 +72,6 @@ class RetryManager {
83
72
 
84
73
  // MARK: - Error Classification
85
74
 
86
- /// Classifies whether an error is retryable or permanent.
87
- /// Only clearly transient network errors are retried.
88
75
  func isRetryable(_ error: Error?) -> Bool {
89
76
  guard let error else { return false }
90
77
 
@@ -113,34 +100,25 @@ class RetryManager {
113
100
 
114
101
  // MARK: - Retry Management
115
102
 
116
- /// Resets retry count. Call when track changes.
117
103
  func reset() {
118
104
  attemptCount = 0
119
105
  firstRetryTime = nil
120
106
  isWaitingForNetwork = false
121
- logger.debug("Retry count reset")
107
+ generation += 1
108
+ logger.debug("Retry count reset (generation \(self.generation))")
122
109
  }
123
110
 
124
- /// Attempts a retry if policy allows.
125
- /// Returns true if retry was scheduled, false if max retries exceeded or disabled.
126
- ///
127
- /// If a network monitor is configured and the device is offline, the retry will
128
- /// trigger immediately when connectivity is restored instead of waiting for the
129
- /// full backoff delay.
130
111
  func attemptRetry(startFromCurrentTime: Bool) async -> Bool {
131
- // Check if retry is disabled
132
112
  if case .disabled = policy {
133
113
  logger.debug("Retry disabled, not retrying")
134
114
  return false
135
115
  }
136
116
 
137
- // Check if we should retry (e.g., playWhenReady is true)
138
117
  guard shouldRetry() else {
139
118
  logger.debug("shouldRetry returned false, not retrying")
140
119
  return false
141
120
  }
142
121
 
143
- // Check max retries for limited policy
144
122
  if case let .limited(maxRetries) = policy {
145
123
  if attemptCount >= maxRetries {
146
124
  logger.info("Max retries (\(maxRetries)) exceeded, giving up")
@@ -148,7 +126,6 @@ class RetryManager {
148
126
  }
149
127
  }
150
128
 
151
- // Track when we started retrying
152
129
  if firstRetryTime == nil {
153
130
  firstRetryTime = Date()
154
131
  }
@@ -162,10 +139,9 @@ class RetryManager {
162
139
  }
163
140
  }
164
141
 
165
- // Schedule retry with exponential backoff
166
142
  let delaySeconds = calculateDelaySeconds()
167
- attemptCount += 1
168
- logger.info("Scheduling retry #\(self.attemptCount) after \(delaySeconds)s")
143
+ let currentGeneration = generation
144
+ logger.info("Scheduling retry after \(delaySeconds)s")
169
145
 
170
146
  // Race between: backoff delay OR network restored (if offline)
171
147
  let waitCancelled = await waitForDelayOrNetworkRestored(delaySeconds: delaySeconds)
@@ -175,13 +151,18 @@ class RetryManager {
175
151
  return false
176
152
  }
177
153
 
178
- // Double-check we should still retry after the delay
154
+ // Check if reset() was called while we were waiting
155
+ guard generation == currentGeneration else {
156
+ logger.debug("Retry invalidated by reset (generation changed)")
157
+ return false
158
+ }
159
+
179
160
  guard shouldRetry() else {
180
161
  logger.debug("shouldRetry returned false after delay, cancelling retry")
181
162
  return false
182
163
  }
183
164
 
184
- // Check duration again after waiting (in case we waited a long time for network)
165
+ // Re-check duration we may have waited a long time for network restoration
185
166
  if let startTime = firstRetryTime {
186
167
  let elapsed = Date().timeIntervalSince(startTime)
187
168
  if elapsed >= maxRetryDuration {
@@ -190,7 +171,7 @@ class RetryManager {
190
171
  }
191
172
  }
192
173
 
193
- // Trigger the retry
174
+ attemptCount += 1
194
175
  logger.info("Executing retry #\(self.attemptCount)")
195
176
  onRetry?(startFromCurrentTime)
196
177
  return true
@@ -198,12 +179,10 @@ class RetryManager {
198
179
 
199
180
  // MARK: - Network-Aware Waiting
200
181
 
201
- /// Waits for either the backoff delay to elapse OR network to be restored (if offline).
202
182
  /// Returns true if cancelled, false if ready to retry.
203
183
  private func waitForDelayOrNetworkRestored(delaySeconds: Double) async -> Bool {
204
184
  let isOffline = !(networkMonitor?.isOnline ?? true)
205
185
 
206
- // If online or no monitor, just do a simple sleep
207
186
  guard isOffline, let monitor = networkMonitor else {
208
187
  do {
209
188
  let nanoseconds = UInt64(delaySeconds * 1_000_000_000)
@@ -216,66 +195,48 @@ class RetryManager {
216
195
 
217
196
  logger.debug("Device is offline, will retry immediately when connectivity is restored")
218
197
 
219
- // Race between sleep and network restoration
220
198
  return await withTaskGroup(of: Bool.self, returning: Bool.self) { group in
221
- // Task 1: Sleep for backoff delay
222
199
  group.addTask {
223
200
  do {
224
201
  let nanoseconds = UInt64(delaySeconds * 1_000_000_000)
225
202
  try await Task.sleep(nanoseconds: nanoseconds)
226
- return false // Sleep completed, ready to retry
203
+ return false
227
204
  } catch {
228
- return true // Sleep cancelled
205
+ return true
229
206
  }
230
207
  }
231
208
 
232
- // Task 2: Wait for network restoration
233
209
  group.addTask { [weak self] in
234
210
  await self?.waitForNetworkRestored(monitor: monitor) ?? true
235
211
  }
236
212
 
237
- // Return when either completes
238
213
  let result = await group.next() ?? true
239
214
  group.cancelAll()
240
215
  return result
241
216
  }
242
217
  }
243
218
 
244
- /// Waits until network connectivity is restored.
245
219
  /// Returns false when network is restored, true if cancelled.
246
220
  @MainActor
247
221
  private func waitForNetworkRestored(monitor: NetworkMonitor) async -> Bool {
248
- // If already online, return immediately
249
222
  if monitor.isOnline {
250
223
  return false
251
224
  }
252
225
 
253
226
  isWaitingForNetwork = true
227
+ defer { isWaitingForNetwork = false }
254
228
 
255
- // Set up listener for network restoration
256
- let previousHandler = monitor.onChanged
257
-
258
- // Use withCheckedContinuation to wait for network
259
- let result: Bool = await withCheckedContinuation { continuation in
260
- var hasResumed = false
229
+ logger.debug("Device is offline, polling for network restoration")
261
230
 
262
- monitor.onChanged = { [weak self] isOnline in
263
- // Always call previous handler to maintain JS callback
264
- previousHandler?(isOnline)
265
-
266
- guard !hasResumed else { return }
267
-
268
- if isOnline {
269
- hasResumed = true
270
- self?.logger.info("Network restored, accelerating retry")
271
- // Restore original handler
272
- monitor.onChanged = previousHandler
273
- continuation.resume(returning: false) // Network restored, ready to retry
274
- }
231
+ while !monitor.isOnline {
232
+ do {
233
+ try await Task.sleep(nanoseconds: 500_000_000) // 0.5s poll
234
+ } catch {
235
+ return true // Task cancelled
275
236
  }
276
237
  }
277
238
 
278
- isWaitingForNetwork = false
279
- return result
239
+ logger.info("Network restored, accelerating retry")
240
+ return false
280
241
  }
281
242
  }
@@ -39,7 +39,7 @@ class SleepTimerManager {
39
39
  var onComplete: (() -> Void)?
40
40
 
41
41
  /// Callback invoked when the sleep timer state changes
42
- var onChanged: ((SleepTimerState?) -> Void)?
42
+ var onChanged: ((SleepTimerState) -> Void)?
43
43
 
44
44
  // MARK: - Public Methods
45
45
 
@@ -52,7 +52,7 @@ class SleepTimerManager {
52
52
  if !hasSleepTimer { return false }
53
53
  sleepTimerTime = -1
54
54
  willSleepWhenCurrentItemReachesEnd = false
55
- onChanged?(nil)
55
+ onChanged?(.first(NullType.null))
56
56
  return true
57
57
  }
58
58
 
@@ -88,7 +88,7 @@ class SleepTimerManager {
88
88
  sleepTimerJob = job
89
89
  sleepTimerTime = Date().timeIntervalSince1970 + seconds
90
90
  DispatchQueue.main.asyncAfter(deadline: .now() + seconds, execute: job)
91
- onChanged?(get())
91
+ if let state = get() { onChanged?(state) }
92
92
  }
93
93
 
94
94
  /// Sets the timer to stop playback when the current track ends.
@@ -96,16 +96,14 @@ class SleepTimerManager {
96
96
  assertMainThread()
97
97
  let changed = !willSleepWhenCurrentItemReachesEnd
98
98
  willSleepWhenCurrentItemReachesEnd = true
99
- if changed {
100
- onChanged?(get())
101
- }
99
+ if changed, let state = get() { onChanged?(state) }
102
100
  }
103
101
 
104
102
  /// Called when the current track changes. Resets end-of-track timer.
105
103
  func onTrackChanged() {
106
104
  if willSleepWhenCurrentItemReachesEnd {
107
105
  willSleepWhenCurrentItemReachesEnd = false
108
- onChanged?(nil)
106
+ onChanged?(.first(NullType.null))
109
107
  }
110
108
  }
111
109
 
@@ -127,7 +125,7 @@ class SleepTimerManager {
127
125
  private func complete() {
128
126
  sleepTimerTime = -1
129
127
  willSleepWhenCurrentItemReachesEnd = false
130
- onChanged?(nil)
128
+ onChanged?(.first(NullType.null))
131
129
  onComplete?()
132
130
  }
133
131