@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
@@ -7,150 +7,159 @@ class SimpleRouterTest {
7
7
 
8
8
  private val router = SimpleRouter()
9
9
 
10
- @Test
11
- fun `exact match works`() {
12
- val routes = mapOf("/artists" to "config1")
13
- val result = router.findBestMatch("/artists", routes)
10
+ // -- exact matches --
14
11
 
12
+ @Test
13
+ fun `matches a simple path`() {
14
+ val result = router.findBestMatch("/artists", mapOf("/artists" to true))
15
15
  assertNotNull(result)
16
16
  assertEquals("/artists", result!!.first)
17
17
  assertTrue(result.second.params.isEmpty())
18
18
  }
19
19
 
20
20
  @Test
21
- fun `parameter extraction works`() {
22
- val routes = mapOf("/artists/{id}" to "config1")
23
- val result = router.findBestMatch("/artists/123", routes)
24
-
21
+ fun `matches multi-segment paths`() {
22
+ val result = router.findBestMatch("/artists/top/rated", mapOf("/artists/top/rated" to true))
25
23
  assertNotNull(result)
26
- assertEquals("/artists/{id}", result!!.first)
27
- assertEquals("123", result.second.params["id"])
24
+ assertEquals("/artists/top/rated", result!!.first)
28
25
  }
29
26
 
30
27
  @Test
31
- fun `multiple parameters work`() {
32
- val routes = mapOf("/artists/{artistId}/albums/{albumId}" to "config1")
33
- val result = router.findBestMatch("/artists/123/albums/456", routes)
34
-
35
- assertNotNull(result)
36
- assertEquals("123", result!!.second.params["artistId"])
37
- assertEquals("456", result.second.params["albumId"])
28
+ fun `returns null when no route matches`() {
29
+ assertNull(router.findBestMatch("/unknown", mapOf("/artists" to true)))
38
30
  }
39
31
 
40
32
  @Test
41
- fun `specificity works - constants win over parameters`() {
42
- val routes = mapOf("/artists/{id}" to "generic", "/artists/popular" to "specific")
43
- val result = router.findBestMatch("/artists/popular", routes)
44
-
45
- assertEquals("/artists/popular", result!!.first)
33
+ fun `returns null when segment count differs`() {
34
+ assertNull(router.findBestMatch("/artists/123", mapOf("/artists" to true)))
46
35
  }
47
36
 
48
37
  @Test
49
- fun `specificity works - more segments win`() {
50
- val routes = mapOf("/artists" to "short", "/artists/premium" to "longer")
51
-
52
- val result1 = router.findBestMatch("/artists", routes)
53
- assertEquals("/artists", result1!!.first)
54
-
55
- val result2 = router.findBestMatch("/artists/premium", routes)
56
- assertEquals("/artists/premium", result2!!.first)
38
+ fun `returns null when routes are empty`() {
39
+ assertNull(router.findBestMatch("/artists", emptyMap<String, Boolean>()))
57
40
  }
58
41
 
59
42
  @Test
60
- fun `no match returns null`() {
61
- val routes = mapOf("/artists" to "config1")
62
- val result = router.findBestMatch("/songs", routes)
63
-
64
- assertNull(result)
43
+ fun `treats trailing slashes the same as without`() {
44
+ val result = router.findBestMatch("/artists/", mapOf("/artists" to true))
45
+ assertNotNull(result)
46
+ assertEquals("/artists", result!!.first)
65
47
  }
66
48
 
67
- @Test
68
- fun `different segment count returns null`() {
69
- val routes = mapOf("/artists/{id}" to "config1")
70
- val result = router.findBestMatch("/artists/123/extra", routes)
49
+ // -- parameter extraction --
71
50
 
72
- assertNull(result)
51
+ @Test
52
+ fun `extracts a single parameter`() {
53
+ val result = router.findBestMatch("/artists/123", mapOf("/artists/{id}" to true))
54
+ assertNotNull(result)
55
+ assertEquals(mapOf("id" to "123"), result!!.second.params)
73
56
  }
74
57
 
75
58
  @Test
76
- fun `single wildcard matching works`() {
77
- val routes = mapOf("/artists/*" to "wildcard")
78
- val result = router.findBestMatch("/artists/anything", routes)
79
-
59
+ fun `extracts multiple parameters`() {
60
+ val result =
61
+ router.findBestMatch(
62
+ "/artists/123/albums/456",
63
+ mapOf("/artists/{artistId}/albums/{albumId}" to true),
64
+ )
80
65
  assertNotNull(result)
81
- assertEquals("/artists/*", result!!.first)
82
- assertTrue(result.second.params.isEmpty()) // Wildcards don't capture
66
+ assertEquals(mapOf("artistId" to "123", "albumId" to "456"), result!!.second.params)
83
67
  }
84
68
 
69
+ // -- single wildcard --
70
+
85
71
  @Test
86
- fun `tail wildcard matching works`() {
87
- val routes = mapOf("/files/**" to "allFiles")
72
+ fun `matches any single segment`() {
73
+ assertNotNull(router.findBestMatch("/artists/anything", mapOf("/artists/*" to true)))
74
+ }
88
75
 
89
- val result1 = router.findBestMatch("/files/docs/readme.md", routes)
90
- assertNotNull(result1)
91
- assertEquals("docs/readme.md", result1!!.second.params["tail"])
76
+ @Test
77
+ fun `does not extract wildcard value into params`() {
78
+ val result = router.findBestMatch("/artists/anything", mapOf("/artists/*" to true))
79
+ assertTrue(result!!.second.params.isEmpty())
80
+ }
92
81
 
93
- val result2 = router.findBestMatch("/files/images/2023/vacation.jpg", routes)
94
- assertNotNull(result2)
95
- assertEquals("images/2023/vacation.jpg", result2!!.second.params["tail"])
82
+ // -- tail wildcard --
96
83
 
97
- // Also matches shorter paths
98
- val result3 = router.findBestMatch("/files", routes)
99
- assertNotNull(result3)
100
- assertFalse(result3!!.second.params.containsKey("tail")) // No tail captured
84
+ @Test
85
+ fun `matches with no remaining segments and has no tail param`() {
86
+ val result = router.findBestMatch("/files", mapOf("/files/**" to true))
87
+ assertNotNull(result)
88
+ assertTrue(result!!.second.params.isEmpty())
101
89
  }
102
90
 
103
91
  @Test
104
- fun `wildcard specificity works correctly`() {
105
- val routes =
106
- mapOf(
107
- "/artists/*" to "wildcard",
108
- "/artists/{id}" to "parameter",
109
- "/artists/popular" to "constant",
110
- )
92
+ fun `matches with remaining segments and captures tail`() {
93
+ val result = router.findBestMatch("/files/a/b/c", mapOf("/files/**" to true))
94
+ assertNotNull(result)
95
+ assertEquals(mapOf("tail" to "a/b/c"), result!!.second.params)
96
+ }
111
97
 
112
- // Constant wins
113
- val result1 = router.findBestMatch("/artists/popular", routes)
114
- assertEquals("/artists/popular", result1!!.first)
98
+ @Test
99
+ fun `matches with a single remaining segment`() {
100
+ val result = router.findBestMatch("/files/readme.txt", mapOf("/files/**" to true))
101
+ assertNotNull(result)
102
+ assertEquals(mapOf("tail" to "readme.txt"), result!!.second.params)
103
+ }
115
104
 
116
- // Parameter wins over wildcard for non-constant values
117
- val result2 = router.findBestMatch("/artists/123", routes)
118
- assertEquals("/artists/{id}", result2!!.first)
119
- assertEquals("123", result2.second.params["id"])
105
+ @Test
106
+ fun `returns null when prefix segments do not match`() {
107
+ assertNull(router.findBestMatch("/other/a/b", mapOf("/files/**" to true)))
120
108
  }
121
109
 
122
110
  @Test
123
- fun `tail wildcard specificity works`() {
124
- val routes =
125
- mapOf("/api/**" to "catchAll", "/api/users" to "specific", "/api/users/{id}" to "userById")
111
+ fun `works with parameters before tail wildcard`() {
112
+ val result =
113
+ router.findBestMatch("/api/v1/users/list", mapOf("/api/{version}/**" to true))
114
+ assertNotNull(result)
115
+ assertEquals(mapOf("version" to "v1", "tail" to "users/list"), result!!.second.params)
116
+ }
126
117
 
127
- // Specific routes win over tail wildcard
128
- val result1 = router.findBestMatch("/api/users", routes)
129
- assertEquals("/api/users", result1!!.first)
118
+ @Test
119
+ fun `matches any path with bare tail wildcard pattern`() {
120
+ val result = router.findBestMatch("/any/path/here", mapOf("/**" to true))
121
+ assertNotNull(result)
122
+ assertEquals(mapOf("tail" to "any/path/here"), result!!.second.params)
123
+ }
130
124
 
131
- val result2 = router.findBestMatch("/api/users/123", routes)
132
- assertEquals("/api/users/{id}", result2!!.first)
125
+ // -- specificity --
133
126
 
134
- // Tail wildcard catches unmatched paths
135
- val result3 = router.findBestMatch("/api/posts/recent", routes)
136
- assertEquals("/api/**", result3!!.first)
137
- assertEquals("posts/recent", result3.second.params["tail"])
127
+ @Test
128
+ fun `prefers constant segments over parameters`() {
129
+ val routes = mapOf("/artists/{id}" to true, "/artists/top" to true)
130
+ val result = router.findBestMatch("/artists/top", routes)
131
+ assertEquals("/artists/top", result!!.first)
138
132
  }
139
133
 
140
134
  @Test
141
- fun `example from plan works`() {
142
- val routes =
143
- mapOf("/artists" to "generic", "/artists/{id}" to "byId", "/artists/premium" to "premium")
135
+ fun `prefers parameters over wildcards`() {
136
+ val routes = mapOf("/artists/*" to true, "/artists/{id}" to true)
137
+ val result = router.findBestMatch("/artists/123", routes)
138
+ assertEquals("/artists/{id}", result!!.first)
139
+ }
144
140
 
145
- // Test each case
146
- val result1 = router.findBestMatch("/artists", routes)
147
- assertEquals("/artists", result1!!.first)
141
+ @Test
142
+ fun `prefers exact match over tail wildcard`() {
143
+ val routes = mapOf("/api/**" to true, "/api/{version}" to true)
144
+ val result = router.findBestMatch("/api/v1", routes)
145
+ assertEquals("/api/{version}", result!!.first)
146
+ }
148
147
 
149
- val result2 = router.findBestMatch("/artists/123", routes)
150
- assertEquals("/artists/{id}", result2!!.first)
151
- assertEquals("123", result2.second.params["id"])
148
+ @Test
149
+ fun `computes correct specificity for tail wildcard patterns`() {
150
+ // Regression test for issue #27: specificity must account for
151
+ // segment types before the ** wildcard.
152
+ val result = router.findBestMatch("/api/v1/users", mapOf("/api/v1/**" to true))
153
+ // constant "api" (1000) + constant "v1" (1000) + tail(1) + 3 segments = 2004
154
+ assertEquals(2004, result!!.second.specificity)
155
+ }
152
156
 
153
- val result3 = router.findBestMatch("/artists/premium", routes)
154
- assertEquals("/artists/premium", result3!!.first) // More specific than {id}
157
+ @Test
158
+ fun `prefers constant prefix over parameter prefix in tail wildcards`() {
159
+ // Second part of issue #27: with correct specificity, the constant
160
+ // prefix should beat the parameter prefix.
161
+ val routes = mapOf("/api/{version}/**" to true, "/api/v1/**" to true)
162
+ val result = router.findBestMatch("/api/v1/users", routes)
163
+ assertEquals("/api/v1/**", result!!.first)
155
164
  }
156
165
  }
@@ -1,5 +1,6 @@
1
1
  import Foundation
2
2
  import NitroModules
3
+ import os.log
3
4
 
4
5
  /// Flattened browser configuration (matches Kotlin BrowserConfig).
5
6
  ///
@@ -33,6 +34,9 @@ struct BrowserConfig {
33
34
  /// Custom buttons for CarPlay Now Playing screen (e.g., .repeat, .favorite)
34
35
  let carPlayNowPlayingButtons: [CarPlayNowPlayingButton]
35
36
 
37
+ /// Custom handler for track load events (overrides default load behavior)
38
+ let handleTrackLoad: ((_ event: TrackLoadEvent) -> Promise<Promise<Void>>)?
39
+
36
40
  /// Callback to customize navigation error display (for i18n)
37
41
  /// Used by CarPlay and available via `useFormattedNavigationError()` for app UI.
38
42
  let formatNavigationError: ((_ params: FormatNavigationErrorParams) -> Promise<FormattedNavigationError?>)?
@@ -43,6 +47,7 @@ struct BrowserConfig {
43
47
  artwork: ArtworkRequestConfig? = nil,
44
48
  routes: [NativeRouteEntry]? = nil,
45
49
  singleTrack: Bool = false,
50
+ handleTrackLoad: ((_ event: TrackLoadEvent) -> Promise<Promise<Void>>)? = nil,
46
51
  androidControllerOfflineError: Bool = true,
47
52
  carPlayUpNextButton: Bool = true,
48
53
  carPlayNowPlayingButtons: [CarPlayNowPlayingButton] = [],
@@ -53,6 +58,7 @@ struct BrowserConfig {
53
58
  self.artwork = artwork
54
59
  self.routes = routes
55
60
  self.singleTrack = singleTrack
61
+ self.handleTrackLoad = handleTrackLoad
56
62
  self.androidControllerOfflineError = androidControllerOfflineError
57
63
  self.carPlayUpNextButton = carPlayUpNextButton
58
64
  self.carPlayNowPlayingButtons = carPlayNowPlayingButtons
@@ -66,17 +72,37 @@ struct BrowserConfig {
66
72
  artwork = config.artwork
67
73
  routes = config.routes
68
74
  singleTrack = config.singleTrack ?? false
75
+ handleTrackLoad = config.handleTrackLoad
69
76
  androidControllerOfflineError = config.androidControllerOfflineError ?? true
70
77
  carPlayUpNextButton = config.carPlayUpNextButton ?? true
71
78
  carPlayNowPlayingButtons = config.carPlayNowPlayingButtons ?? []
72
79
  formatNavigationError = config.formatNavigationError
73
80
  }
74
81
 
75
- /// Returns true if search functionality is configured (either callback or config).
76
- var hasSearch: Bool {
77
- guard let routes else { return false }
78
- let searchEntry = routes.first { $0.path == BrowserManager.searchRoutePath }
79
- return searchEntry?.searchCallback != nil || searchEntry?.searchConfig != nil
82
+ // MARK: - Track Load Handler
83
+
84
+ private static let logger = Logger(subsystem: "com.audiobrowser", category: "BrowserConfig")
85
+
86
+ /// Awaits the handleTrackLoad callback using the double-Promise pattern required by Nitro.
87
+ ///
88
+ /// Nitro wraps value-returning JS callbacks in Promise<T> for thread safety, so a JS callback
89
+ /// returning Promise<void> becomes Promise<Promise<Void>> on the native side. Both layers
90
+ /// must be awaited to properly wait for the JS work to complete.
91
+ ///
92
+ /// - Returns: true if the handler was present and invoked, false if not configured
93
+ func awaitTrackLoadHandler(event: TrackLoadEvent) async -> Bool {
94
+ guard let handler = handleTrackLoad else { return false }
95
+ do {
96
+ // MainActor: Nitro bridge call must be on main thread (C++ noexcept)
97
+ nonisolated(unsafe) let _handler = handler
98
+ nonisolated(unsafe) let _event = event
99
+ let outerPromise = await MainActor.run { _handler(_event) }
100
+ let innerPromise = try await outerPromise.await()
101
+ try await innerPromise.await()
102
+ } catch {
103
+ Self.logger.error("handleTrackLoad failed: \(error.localizedDescription)")
104
+ }
105
+ return true
80
106
  }
81
107
  }
82
108
 
@@ -183,6 +183,7 @@ final class BrowserManager: @unchecked Sendable {
183
183
  favorited: isFavorited,
184
184
  groupTitle: track.groupTitle,
185
185
  live: track.live,
186
+ imageRow: track.imageRow,
186
187
  )
187
188
  }
188
189
 
@@ -193,6 +194,7 @@ final class BrowserManager: @unchecked Sendable {
193
194
  return ResolvedTrack(
194
195
  url: resolvedTrack.url,
195
196
  children: hydratedChildren,
197
+ carPlaySiriListButton: resolvedTrack.carPlaySiriListButton,
196
198
  src: resolvedTrack.src,
197
199
  artwork: resolvedTrack.artwork,
198
200
  artworkSource: resolvedTrack.artworkSource,
@@ -209,6 +211,7 @@ final class BrowserManager: @unchecked Sendable {
209
211
  favorited: resolvedTrack.favorited,
210
212
  groupTitle: resolvedTrack.groupTitle,
211
213
  live: resolvedTrack.live,
214
+ imageRow: resolvedTrack.imageRow,
212
215
  )
213
216
  }
214
217
 
@@ -336,6 +339,7 @@ final class BrowserManager: @unchecked Sendable {
336
339
  return ResolvedTrack(
337
340
  url: resolvedTrack.url,
338
341
  children: transformedChildren,
342
+ carPlaySiriListButton: resolvedTrack.carPlaySiriListButton,
339
343
  src: resolvedTrack.src,
340
344
  artwork: resolvedTrack.artwork,
341
345
  artworkSource: resolvedTrack.artworkSource,
@@ -352,6 +356,7 @@ final class BrowserManager: @unchecked Sendable {
352
356
  favorited: resolvedTrack.favorited,
353
357
  groupTitle: resolvedTrack.groupTitle,
354
358
  live: resolvedTrack.live,
359
+ imageRow: resolvedTrack.imageRow,
355
360
  )
356
361
  }
357
362
 
@@ -393,7 +398,8 @@ final class BrowserManager: @unchecked Sendable {
393
398
  if let callback = entry.browseCallback {
394
399
  let callbackParam = BrowserSourceCallbackParam(path: path, routeParams: params)
395
400
  // Callback returns Promise<Promise<BrowseResult>> - await both layers
396
- let outerPromise = callback(callbackParam)
401
+ // MainActor: Nitro bridge call must be on main thread (C++ noexcept)
402
+ let outerPromise = await MainActor.run { callback(callbackParam) }
397
403
  let innerPromise = try await outerPromise.await()
398
404
  let result = try await innerPromise.await()
399
405
 
@@ -526,6 +532,7 @@ final class BrowserManager: @unchecked Sendable {
526
532
  favorited: track.favorited,
527
533
  groupTitle: track.groupTitle,
528
534
  live: track.live,
535
+ imageRow: track.imageRow,
529
536
  )
530
537
  }
531
538
 
@@ -553,6 +560,63 @@ final class BrowserManager: @unchecked Sendable {
553
560
  favorited: transformedTrack.favorited,
554
561
  groupTitle: transformedTrack.groupTitle,
555
562
  live: transformedTrack.live,
563
+ imageRow: transformedTrack.imageRow,
564
+ )
565
+ }
566
+
567
+ // Also resolve artwork for image row items
568
+ if let imageRowItems = transformedTrack.imageRow {
569
+ let artworkConfig = routeEntry.artwork ?? config.artwork
570
+ var resolvedItems: [ImageRowItem] = []
571
+ for item in imageRowItems {
572
+ // Create a minimal Track to pass to the artwork resolver
573
+ let itemTrack = Track(
574
+ url: item.url,
575
+ src: nil,
576
+ artwork: item.artwork,
577
+ artworkSource: nil,
578
+ artworkCarPlayTinted: nil,
579
+ title: item.title,
580
+ subtitle: nil,
581
+ artist: nil,
582
+ album: nil,
583
+ description: nil,
584
+ genre: nil,
585
+ duration: nil,
586
+ style: nil,
587
+ childrenStyle: nil,
588
+ favorited: nil,
589
+ groupTitle: nil,
590
+ live: nil,
591
+ imageRow: nil,
592
+ )
593
+ let itemImageSource = await resolver(itemTrack, artworkConfig, browseContext)
594
+ resolvedItems.append(ImageRowItem(
595
+ url: item.url,
596
+ artwork: item.artwork,
597
+ artworkSource: itemImageSource,
598
+ title: item.title,
599
+ ))
600
+ }
601
+ transformedTrack = Track(
602
+ url: transformedTrack.url,
603
+ src: transformedTrack.src,
604
+ artwork: transformedTrack.artwork,
605
+ artworkSource: transformedTrack.artworkSource,
606
+ artworkCarPlayTinted: transformedTrack.artworkCarPlayTinted,
607
+ title: transformedTrack.title,
608
+ subtitle: transformedTrack.subtitle,
609
+ artist: transformedTrack.artist,
610
+ album: transformedTrack.album,
611
+ description: transformedTrack.description,
612
+ genre: transformedTrack.genre,
613
+ duration: transformedTrack.duration,
614
+ style: transformedTrack.style,
615
+ childrenStyle: transformedTrack.childrenStyle,
616
+ favorited: transformedTrack.favorited,
617
+ groupTitle: transformedTrack.groupTitle,
618
+ live: transformedTrack.live,
619
+ imageRow: resolvedItems,
556
620
  )
557
621
  }
558
622
  }
@@ -573,6 +637,7 @@ final class BrowserManager: @unchecked Sendable {
573
637
  return ResolvedTrack(
574
638
  url: BrowserPathHelper.createSearchPath(query),
575
639
  children: hydratedResults,
640
+ carPlaySiriListButton: nil,
576
641
  src: nil,
577
642
  artwork: nil,
578
643
  artworkSource: nil,
@@ -589,6 +654,7 @@ final class BrowserManager: @unchecked Sendable {
589
654
  favorited: nil,
590
655
  groupTitle: nil,
591
656
  live: nil,
657
+ imageRow: nil,
592
658
  )
593
659
  }
594
660
 
@@ -614,7 +680,8 @@ final class BrowserManager: @unchecked Sendable {
614
680
 
615
681
  if let callback = searchEntry.searchCallback {
616
682
  // Callback returns Promise<Promise<[Track]>> - await both layers
617
- let outerPromise = callback(searchParams)
683
+ // MainActor: Nitro bridge call must be on main thread (C++ noexcept)
684
+ let outerPromise = await MainActor.run { callback(searchParams) }
618
685
  let innerPromise = try await outerPromise.await()
619
686
  results = try await innerPromise.await()
620
687
  } else if let searchConfig = searchEntry.searchConfig {
@@ -637,6 +704,7 @@ final class BrowserManager: @unchecked Sendable {
637
704
  return ResolvedTrack(
638
705
  url: BrowserPathHelper.createSearchPath(query),
639
706
  children: hydratedResults,
707
+ carPlaySiriListButton: nil,
640
708
  src: nil,
641
709
  artwork: nil,
642
710
  artworkSource: nil,
@@ -653,6 +721,7 @@ final class BrowserManager: @unchecked Sendable {
653
721
  favorited: nil,
654
722
  groupTitle: nil,
655
723
  live: nil,
724
+ imageRow: nil,
656
725
  )
657
726
  }
658
727
 
@@ -743,8 +812,13 @@ final class BrowserManager: @unchecked Sendable {
743
812
  )
744
813
 
745
814
  logger.debug("resolveMediaUrl: calling transform callback...")
746
- // MediaRequestConfig.transform takes (request, routeParams) - pass nil for routeParams
747
- let outerPromise = transform(baseRequest, nil)
815
+ // Dispatch the Nitro bridge call to MainActor to avoid C++ noexcept crashes.
816
+ // The generated C++ call() wrapper is noexcept, so any exception from JSI
817
+ // causes std::terminate. Calling from the main thread is safer for JS callbacks.
818
+ // Only the initial call is dispatched; awaiting happens on the background thread.
819
+ let outerPromise = await MainActor.run {
820
+ transform(baseRequest, nil)
821
+ }
748
822
  logger.debug("resolveMediaUrl: awaiting outer promise...")
749
823
  let innerPromise = try await outerPromise.await()
750
824
  logger.debug("resolveMediaUrl: awaiting inner promise...")
@@ -819,6 +893,18 @@ final class BrowserManager: @unchecked Sendable {
819
893
  /// - imageContext: Optional size context for CDN URL generation (nil at browse-time)
820
894
  /// - Returns: ImageSource ready for image loading, or nil if no artwork
821
895
  func resolveArtworkUrl(track: Track, perRouteConfig: ArtworkRequestConfig?, imageContext: ImageContext? = nil) async -> ImageSource? {
896
+ if let artwork = track.artwork, SFSymbolRenderer.isSFSymbol(artwork) {
897
+ let canvasSize: CGSize = if let w = imageContext?.width, let h = imageContext?.height {
898
+ CGSize(width: w, height: h)
899
+ } else {
900
+ SFSymbolRenderer.defaultCanvasSize
901
+ }
902
+ if let uri = await SFSymbolRenderer.shared.render(artwork, canvasSize: canvasSize) {
903
+ return ImageSource(uri: uri, method: nil, headers: nil, body: nil)
904
+ }
905
+ return nil
906
+ }
907
+
822
908
  // Determine effective artwork config: per-route overrides global
823
909
  let effectiveArtworkConfig = perRouteConfig ?? config.artwork
824
910
 
@@ -848,7 +934,8 @@ final class BrowserManager: @unchecked Sendable {
848
934
 
849
935
  // If there's a resolve callback, call it for per-track config
850
936
  if let resolve = artworkConfig.resolve {
851
- let outerPromise = resolve(track)
937
+ // MainActor: Nitro bridge call must be on main thread (C++ noexcept)
938
+ let outerPromise = await MainActor.run { resolve(track) }
852
939
  let innerPromise = try await outerPromise.await()
853
940
  let resolvedConfig = try await innerPromise.await()
854
941
 
@@ -904,7 +991,10 @@ final class BrowserManager: @unchecked Sendable {
904
991
  // Transform will be called at load-time when actual display size is known
905
992
  let hasSize = imageContext?.width != nil || imageContext?.height != nil
906
993
  if let transform = artworkConfig.transform, hasSize {
907
- let outerPromise = transform(MediaTransformParams(request: mergedConfig, context: imageContext))
994
+ // MainActor: Nitro bridge call must be on main thread (C++ noexcept)
995
+ let outerPromise = await MainActor.run {
996
+ transform(MediaTransformParams(request: mergedConfig, context: imageContext))
997
+ }
908
998
  let innerPromise = try await outerPromise.await()
909
999
  let transformedConfig = try await innerPromise.await()
910
1000
 
@@ -4,6 +4,23 @@ import NitroModules
4
4
  /// JSON serializable models for parsing API responses.
5
5
  /// These will be converted to Nitro types after parsing.
6
6
 
7
+ /// JSON model for image row items (horizontal thumbnail row).
8
+ struct JsonImageRowItem: Codable {
9
+ let url: String?
10
+ let artwork: String?
11
+ let title: String
12
+
13
+ init(
14
+ url: String? = nil,
15
+ artwork: String? = nil,
16
+ title: String,
17
+ ) {
18
+ self.url = url
19
+ self.artwork = artwork
20
+ self.title = title
21
+ }
22
+ }
23
+
7
24
  /// JSON model for resolved track (container with children).
8
25
  struct JsonResolvedTrack: Codable {
9
26
  let url: String
@@ -21,6 +38,7 @@ struct JsonResolvedTrack: Codable {
21
38
  let childrenStyle: String?
22
39
  let groupTitle: String?
23
40
  let live: Bool?
41
+ let carPlaySiriListButton: String?
24
42
 
25
43
  init(
26
44
  url: String,
@@ -38,6 +56,7 @@ struct JsonResolvedTrack: Codable {
38
56
  childrenStyle: String? = nil,
39
57
  groupTitle: String? = nil,
40
58
  live: Bool? = nil,
59
+ carPlaySiriListButton: String? = nil,
41
60
  ) {
42
61
  self.url = url
43
62
  self.title = title
@@ -54,6 +73,7 @@ struct JsonResolvedTrack: Codable {
54
73
  self.childrenStyle = childrenStyle
55
74
  self.groupTitle = groupTitle
56
75
  self.live = live
76
+ self.carPlaySiriListButton = carPlaySiriListButton
57
77
  }
58
78
  }
59
79
 
@@ -73,6 +93,7 @@ struct JsonTrack: Codable {
73
93
  let childrenStyle: String?
74
94
  let groupTitle: String?
75
95
  let live: Bool?
96
+ let imageRow: [JsonImageRowItem]?
76
97
 
77
98
  init(
78
99
  url: String? = nil,
@@ -89,6 +110,7 @@ struct JsonTrack: Codable {
89
110
  childrenStyle: String? = nil,
90
111
  groupTitle: String? = nil,
91
112
  live: Bool? = nil,
113
+ imageRow: [JsonImageRowItem]? = nil,
92
114
  ) {
93
115
  self.url = url
94
116
  self.title = title
@@ -104,6 +126,7 @@ struct JsonTrack: Codable {
104
126
  self.childrenStyle = childrenStyle
105
127
  self.groupTitle = groupTitle
106
128
  self.live = live
129
+ self.imageRow = imageRow
107
130
  }
108
131
  }
109
132
 
@@ -115,11 +138,23 @@ private extension String {
115
138
  }
116
139
  }
117
140
 
141
+ extension JsonImageRowItem {
142
+ func toNitro() -> ImageRowItem {
143
+ ImageRowItem(
144
+ url: url,
145
+ artwork: artwork,
146
+ artworkSource: nil,
147
+ title: title,
148
+ )
149
+ }
150
+ }
151
+
118
152
  extension JsonResolvedTrack {
119
153
  func toNitro() -> ResolvedTrack {
120
154
  ResolvedTrack(
121
155
  url: url,
122
156
  children: children?.map { $0.toNitro() },
157
+ carPlaySiriListButton: carPlaySiriListButton.flatMap { CarPlaySiriListButtonPosition(fromString: $0) },
123
158
  src: src,
124
159
  artwork: artwork,
125
160
  artworkSource: nil,
@@ -136,6 +171,7 @@ extension JsonResolvedTrack {
136
171
  favorited: nil,
137
172
  groupTitle: groupTitle,
138
173
  live: live,
174
+ imageRow: nil,
139
175
  )
140
176
  }
141
177
  }
@@ -160,6 +196,7 @@ extension JsonTrack {
160
196
  favorited: nil,
161
197
  groupTitle: groupTitle,
162
198
  live: live,
199
+ imageRow: imageRow?.map { $0.toNitro() },
163
200
  )
164
201
  }
165
202
  }