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

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 (290) hide show
  1. package/README.md +22 -18
  2. package/android/build.gradle +13 -10
  3. package/android/gradle.properties +2 -2
  4. package/android/src/main/AndroidManifest.xml +3 -1
  5. package/android/src/main/java/com/audiobrowser/AudioBrowser.kt +76 -21
  6. package/android/src/main/java/com/audiobrowser/AudioBrowserLifecycleModule.kt +38 -0
  7. package/android/src/main/java/com/audiobrowser/AudioBrowserPackage.kt +18 -2
  8. package/android/src/main/java/com/audiobrowser/ServiceBinding.kt +48 -0
  9. package/android/src/main/java/com/audiobrowser/browser/BrowserManager.kt +1 -2
  10. package/android/src/main/java/com/audiobrowser/browser/BrowserUrlResolution.kt +1 -2
  11. package/android/src/main/java/com/audiobrowser/browser/SectionScope.kt +6 -7
  12. package/android/src/main/java/com/audiobrowser/http/HttpClient.kt +20 -3
  13. package/android/src/main/java/com/audiobrowser/model/PlayerUpdateOptions.kt +11 -11
  14. package/android/src/main/java/com/audiobrowser/player/CapabilityControls.kt +111 -58
  15. package/android/src/main/java/com/audiobrowser/player/MediaSessionCallback.kt +9 -5
  16. package/android/src/main/java/com/audiobrowser/player/MediaSessionCommandManager.kt +218 -252
  17. package/android/src/main/java/com/audiobrowser/player/NowPlayingUpdater.kt +0 -1
  18. package/android/src/main/java/com/audiobrowser/player/PlaybackStateStore.kt +2 -4
  19. package/android/src/main/java/com/audiobrowser/player/Player.kt +30 -8
  20. package/android/src/main/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicy.kt +2 -1
  21. package/android/src/main/java/com/audiobrowser/player/TransformingDataSource.kt +2 -1
  22. package/android/src/main/java/com/audiobrowser/tls/AiaCertChaser.kt +67 -11
  23. package/android/src/main/java/com/audiobrowser/tls/AiaChasingExtendedTrustManager.kt +168 -0
  24. package/android/src/main/java/com/audiobrowser/tls/AiaChasingTrustManager.kt +58 -14
  25. package/android/src/main/java/com/audiobrowser/tls/AiaTls.kt +35 -7
  26. package/android/src/main/java/com/audiobrowser/tls/CachingCertificateFetcher.kt +278 -59
  27. package/android/src/main/java/com/audiobrowser/util/ArtworkVariant.kt +7 -9
  28. package/android/src/main/java/com/audiobrowser/util/TrackFactory.kt +8 -7
  29. package/android/src/test/java/com/audiobrowser/ServiceBindingTest.kt +87 -0
  30. package/android/src/test/java/com/audiobrowser/TestFixtures.kt +52 -1
  31. package/android/src/test/java/com/audiobrowser/browser/BrowserManagerLayerResolutionTest.kt +6 -0
  32. package/android/src/test/java/com/audiobrowser/browser/BrowserManagerTest.kt +167 -8
  33. package/android/src/test/java/com/audiobrowser/browser/JsonArtworkTest.kt +2 -1
  34. package/android/src/test/java/com/audiobrowser/browser/SectionScopeTest.kt +2 -4
  35. package/android/src/test/java/com/audiobrowser/player/CapabilityControlsTest.kt +100 -56
  36. package/android/src/test/java/com/audiobrowser/player/MediaSessionSlotMappingTest.kt +45 -0
  37. package/android/src/test/java/com/audiobrowser/player/PlaybackErrorClassifierTest.kt +3 -4
  38. package/android/src/test/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicyTest.kt +3 -3
  39. package/android/src/test/java/com/audiobrowser/tls/AiaCertChaserTest.kt +197 -7
  40. package/android/src/test/java/com/audiobrowser/tls/AiaChasingTrustManagerTest.kt +325 -4
  41. package/android/src/test/java/com/audiobrowser/tls/CachingCertificateFetcherCallSiteTest.kt +322 -0
  42. package/android/src/test/java/com/audiobrowser/tls/CachingCertificateFetcherTest.kt +83 -0
  43. package/ios/Browser/BrowserManager.swift +2 -27
  44. package/ios/Browser/SearchDrillIn.swift +1 -1
  45. package/ios/CarPlay/RNABMediaAddHandler.swift +6 -6
  46. package/ios/CarPlay/RNABMediaAffinityHandler.swift +2 -2
  47. package/ios/CarPlay/RNABMediaIntentHandler.swift +16 -16
  48. package/ios/HybridAudioBrowser.swift +87 -56
  49. package/ios/Model/NitroTypeStubs.swift +18 -2
  50. package/ios/Model/RemoteCommand.swift +18 -0
  51. package/ios/Model/TrackPlayerError.swift +2 -2
  52. package/ios/Option/SessionCategories.swift +3 -2
  53. package/ios/Player/MediaIntentCriteria.swift +4 -4
  54. package/ios/Player/MediaLoader.swift +3 -1
  55. package/ios/Player/PlaybackCoordinator.swift +4 -1
  56. package/ios/Player/PlaybackErrorHandler.swift +4 -4
  57. package/ios/Player/QueueManager.swift +10 -3
  58. package/ios/Player/RetryManager.swift +79 -18
  59. package/ios/Player/ShuffleOrder.swift +10 -0
  60. package/ios/Player/SleepTimerManager.swift +43 -15
  61. package/ios/RemoteCommand/RemoteCommandCallbacks.swift +47 -0
  62. package/ios/RemoteCommand/RemoteCommandController.swift +9 -6
  63. package/ios/Tests/LRUCacheTests.swift +111 -0
  64. package/ios/Tests/LoadSeekCoordinatorTests.swift +3 -1
  65. package/ios/Tests/MediaIntentCriteriaTests.swift +2 -2
  66. package/ios/Tests/MediaLoaderTests.swift +10 -13
  67. package/ios/Tests/PlaybackCoordinatorTests.swift +10 -7
  68. package/ios/Tests/PlaybackErrorHandlerTests.swift +3 -1
  69. package/ios/Tests/PlayerTimeObserverTests.swift +37 -0
  70. package/ios/Tests/QueueManagerTests.swift +50 -4
  71. package/ios/Tests/RemoteCommandControllerTests.swift +156 -0
  72. package/ios/Tests/RemoteCommandTests.swift +67 -0
  73. package/ios/Tests/RetryManagerTests.swift +89 -0
  74. package/ios/Tests/SectionScopeTests.swift +2 -2
  75. package/ios/Tests/SleepTimerManagerTests.swift +22 -19
  76. package/ios/Tests/Support/ManualSleepTimerScheduler.swift +47 -0
  77. package/ios/Tests/Support/TestTypes.swift +1 -1
  78. package/ios/Tests/TabBarEntriesTests.swift +7 -7
  79. package/ios/TrackPlayer.swift +6 -1
  80. package/ios/TrackPlayerCallbacks.swift +5 -38
  81. package/ios/Util/LRUCache.swift +4 -1
  82. package/lib/commonjs/AudioBrowser.js +0 -11
  83. package/lib/commonjs/AudioBrowser.js.map +1 -1
  84. package/lib/commonjs/CLAUDE.md +52 -0
  85. package/lib/commonjs/features/browser.js +1 -1
  86. package/lib/commonjs/features/browser.js.map +1 -1
  87. package/lib/commonjs/features/carConnection.js +1 -1
  88. package/lib/commonjs/features/equalizer.js +1 -1
  89. package/lib/commonjs/features/errors.js +3 -3
  90. package/lib/commonjs/features/favorites.js +1 -1
  91. package/lib/commonjs/features/gate.js +16 -1
  92. package/lib/commonjs/features/gate.js.map +1 -1
  93. package/lib/commonjs/features/metadata.js +20 -3
  94. package/lib/commonjs/features/metadata.js.map +1 -1
  95. package/lib/commonjs/features/network.js +1 -1
  96. package/lib/commonjs/features/nowPlaying.js +1 -1
  97. package/lib/commonjs/features/output.js +1 -1
  98. package/lib/commonjs/features/playback/playWhenReady.js +1 -1
  99. package/lib/commonjs/features/playback/playing.js +1 -1
  100. package/lib/commonjs/features/playback/progress.js +1 -1
  101. package/lib/commonjs/features/playback/state.js +1 -1
  102. package/lib/commonjs/features/playback/trackPlaybackTime.js +0 -6
  103. package/lib/commonjs/features/playback/trackPlaybackTime.js.map +1 -1
  104. package/lib/commonjs/features/playback/volume.js +1 -1
  105. package/lib/commonjs/features/player/options.js +48 -34
  106. package/lib/commonjs/features/player/options.js.map +1 -1
  107. package/lib/commonjs/features/player/setup.js +15 -8
  108. package/lib/commonjs/features/player/setup.js.map +1 -1
  109. package/lib/commonjs/features/player/validateOptions.js +21 -0
  110. package/lib/commonjs/features/player/validateOptions.js.map +1 -0
  111. package/lib/commonjs/features/queue/activeTrack.js +1 -1
  112. package/lib/commonjs/features/queue/queue.js +2 -2
  113. package/lib/commonjs/features/queue/repeatMode.js +1 -1
  114. package/lib/commonjs/features/queue/shuffle.js +1 -1
  115. package/lib/commonjs/features/remoteControls.js +13 -92
  116. package/lib/commonjs/features/remoteControls.js.map +1 -1
  117. package/lib/commonjs/features/sleepTimer.js +13 -1
  118. package/lib/commonjs/features/sleepTimer.js.map +1 -1
  119. package/lib/commonjs/test-utils/reactNativeStub.js +65 -0
  120. package/lib/commonjs/test-utils/reactNativeStub.js.map +1 -0
  121. package/lib/commonjs/utils/LazyNativeEmitter.js +8 -5
  122. package/lib/commonjs/utils/LazyNativeEmitter.js.map +1 -1
  123. package/lib/commonjs/web/NativeAudioBrowser.js +1 -1
  124. package/lib/commonjs/web/NativeAudioBrowser.js.map +1 -1
  125. package/lib/commonjs/web/browser/BrowserManager.js +1 -1
  126. package/lib/module/AudioBrowser.js +1 -1
  127. package/lib/module/AudioBrowser.js.map +1 -1
  128. package/lib/module/CLAUDE.md +52 -0
  129. package/lib/module/features/browser.js +1 -1
  130. package/lib/module/features/browser.js.map +1 -1
  131. package/lib/module/features/carConnection.js +1 -1
  132. package/lib/module/features/equalizer.js +1 -1
  133. package/lib/module/features/errors.js +3 -3
  134. package/lib/module/features/favorites.js +1 -1
  135. package/lib/module/features/gate.js +16 -1
  136. package/lib/module/features/gate.js.map +1 -1
  137. package/lib/module/features/metadata.js +20 -3
  138. package/lib/module/features/metadata.js.map +1 -1
  139. package/lib/module/features/network.js +1 -1
  140. package/lib/module/features/nowPlaying.js +1 -1
  141. package/lib/module/features/output.js +1 -1
  142. package/lib/module/features/playback/playWhenReady.js +1 -1
  143. package/lib/module/features/playback/playing.js +1 -1
  144. package/lib/module/features/playback/progress.js +1 -1
  145. package/lib/module/features/playback/state.js +1 -1
  146. package/lib/module/features/playback/trackPlaybackTime.js +0 -5
  147. package/lib/module/features/playback/trackPlaybackTime.js.map +1 -1
  148. package/lib/module/features/playback/volume.js +1 -1
  149. package/lib/module/features/player/options.js +47 -32
  150. package/lib/module/features/player/options.js.map +1 -1
  151. package/lib/module/features/player/setup.js +14 -7
  152. package/lib/module/features/player/setup.js.map +1 -1
  153. package/lib/module/features/player/validateOptions.js +17 -0
  154. package/lib/module/features/player/validateOptions.js.map +1 -0
  155. package/lib/module/features/queue/activeTrack.js +1 -1
  156. package/lib/module/features/queue/queue.js +2 -2
  157. package/lib/module/features/queue/repeatMode.js +1 -1
  158. package/lib/module/features/queue/shuffle.js +1 -1
  159. package/lib/module/features/remoteControls.js +13 -92
  160. package/lib/module/features/remoteControls.js.map +1 -1
  161. package/lib/module/features/sleepTimer.js +13 -1
  162. package/lib/module/features/sleepTimer.js.map +1 -1
  163. package/lib/module/test-utils/reactNativeStub.js +58 -0
  164. package/lib/module/test-utils/reactNativeStub.js.map +1 -0
  165. package/lib/module/utils/LazyNativeEmitter.js +8 -5
  166. package/lib/module/utils/LazyNativeEmitter.js.map +1 -1
  167. package/lib/module/web/NativeAudioBrowser.js +1 -1
  168. package/lib/module/web/NativeAudioBrowser.js.map +1 -1
  169. package/lib/module/web/browser/BrowserManager.js +1 -1
  170. package/lib/typescript/src/AudioBrowser.d.ts +0 -1
  171. package/lib/typescript/src/AudioBrowser.d.ts.map +1 -1
  172. package/lib/typescript/src/features/carConnection.d.ts +1 -1
  173. package/lib/typescript/src/features/equalizer.d.ts +1 -1
  174. package/lib/typescript/src/features/errors.d.ts +3 -3
  175. package/lib/typescript/src/features/favorites.d.ts +1 -1
  176. package/lib/typescript/src/features/gate.d.ts +18 -2
  177. package/lib/typescript/src/features/gate.d.ts.map +1 -1
  178. package/lib/typescript/src/features/metadata.d.ts +20 -3
  179. package/lib/typescript/src/features/metadata.d.ts.map +1 -1
  180. package/lib/typescript/src/features/network.d.ts +1 -1
  181. package/lib/typescript/src/features/nowPlaying.d.ts +1 -1
  182. package/lib/typescript/src/features/output.d.ts +1 -1
  183. package/lib/typescript/src/features/playback/playWhenReady.d.ts +1 -1
  184. package/lib/typescript/src/features/playback/playing.d.ts +1 -1
  185. package/lib/typescript/src/features/playback/progress.d.ts +1 -1
  186. package/lib/typescript/src/features/playback/state.d.ts +1 -1
  187. package/lib/typescript/src/features/playback/volume.d.ts +1 -1
  188. package/lib/typescript/src/features/player/options.d.ts +87 -37
  189. package/lib/typescript/src/features/player/options.d.ts.map +1 -1
  190. package/lib/typescript/src/features/player/setup.d.ts +14 -4
  191. package/lib/typescript/src/features/player/setup.d.ts.map +1 -1
  192. package/lib/typescript/src/features/player/validateOptions.d.ts +9 -0
  193. package/lib/typescript/src/features/player/validateOptions.d.ts.map +1 -0
  194. package/lib/typescript/src/features/queue/activeTrack.d.ts +1 -1
  195. package/lib/typescript/src/features/queue/queue.d.ts +2 -2
  196. package/lib/typescript/src/features/queue/repeatMode.d.ts +1 -1
  197. package/lib/typescript/src/features/queue/shuffle.d.ts +1 -1
  198. package/lib/typescript/src/features/remoteControls.d.ts +23 -22
  199. package/lib/typescript/src/features/remoteControls.d.ts.map +1 -1
  200. package/lib/typescript/src/features/sleepTimer.d.ts +1 -1
  201. package/lib/typescript/src/features/sleepTimer.d.ts.map +1 -1
  202. package/lib/typescript/src/test-utils/reactNativeStub.d.ts +36 -0
  203. package/lib/typescript/src/test-utils/reactNativeStub.d.ts.map +1 -0
  204. package/lib/typescript/src/utils/LazyNativeEmitter.d.ts +8 -4
  205. package/lib/typescript/src/utils/LazyNativeEmitter.d.ts.map +1 -1
  206. package/nitrogen/generated/android/AudioBrowser+autolinking.cmake +1 -1
  207. package/nitrogen/generated/android/c++/JAndroidOptions.hpp +10 -10
  208. package/nitrogen/generated/android/c++/JFunc_void_Options.hpp +5 -5
  209. package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.cpp +11 -11
  210. package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.hpp +1 -1
  211. package/nitrogen/generated/android/c++/JNativeSetupPlayerOptions.hpp +5 -5
  212. package/nitrogen/generated/android/c++/JNativeUpdateOptions.hpp +5 -5
  213. package/nitrogen/generated/android/c++/JNitroAndroidUpdateOptions.hpp +10 -10
  214. package/nitrogen/generated/android/c++/JOptions.hpp +5 -5
  215. package/nitrogen/generated/android/c++/{JNotificationButton.hpp → JRemoteButton.hpp} +19 -19
  216. package/nitrogen/generated/android/c++/JRemoteButtonLayout.hpp +86 -0
  217. package/nitrogen/generated/android/c++/JVariant_NullType_RemoteButtonLayout.cpp +26 -0
  218. package/nitrogen/generated/android/c++/JVariant_NullType_RemoteButtonLayout.hpp +75 -0
  219. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidOptions.kt +3 -3
  220. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/HybridAudioBrowserSpec.kt +1 -1
  221. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroAndroidUpdateOptions.kt +3 -3
  222. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{NotificationButton.kt → RemoteButton.kt} +3 -3
  223. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteButtonLayout.kt +44 -0
  224. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Variant_NullType_NotificationButtonLayout.kt → Variant_NullType_RemoteButtonLayout.kt} +9 -9
  225. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.hpp +36 -51
  226. package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Umbrella.hpp +6 -6
  227. package/nitrogen/generated/ios/c++/HybridAudioBrowserSpecSwift.hpp +8 -8
  228. package/nitrogen/generated/ios/swift/AndroidOptions.swift +12 -12
  229. package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec.swift +1 -1
  230. package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec_cxx.swift +2 -2
  231. package/nitrogen/generated/ios/swift/NitroAndroidUpdateOptions.swift +12 -12
  232. package/nitrogen/generated/ios/swift/{NotificationButton.swift → RemoteButton.swift} +6 -6
  233. package/nitrogen/generated/ios/swift/RemoteButtonLayout.swift +57 -0
  234. package/nitrogen/generated/ios/swift/{Variant_NullType_NotificationButtonLayout.swift → Variant_NullType_RemoteButtonLayout.swift} +3 -3
  235. package/nitrogen/generated/shared/c++/AndroidOptions.hpp +8 -8
  236. package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.cpp +1 -1
  237. package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.hpp +1 -1
  238. package/nitrogen/generated/shared/c++/NitroAndroidUpdateOptions.hpp +8 -8
  239. package/nitrogen/generated/shared/c++/{NotificationButton.hpp → RemoteButton.hpp} +19 -19
  240. package/nitrogen/generated/shared/c++/RemoteButtonLayout.hpp +94 -0
  241. package/package.json +12 -4
  242. package/src/AudioBrowser.ts +1 -1
  243. package/src/CLAUDE.md +52 -0
  244. package/src/features/battery.test.ts +79 -0
  245. package/src/features/browser.ts +1 -1
  246. package/src/features/carConnection.ts +1 -1
  247. package/src/features/equalizer.ts +1 -1
  248. package/src/features/errors.ts +3 -3
  249. package/src/features/favorites.ts +1 -1
  250. package/src/features/gate.ts +16 -1
  251. package/src/features/hook-wiring.test.ts +254 -0
  252. package/src/features/metadata.ts +20 -3
  253. package/src/features/network.ts +1 -1
  254. package/src/features/nowPlaying.ts +1 -1
  255. package/src/features/output.ts +1 -1
  256. package/src/features/playback/playWhenReady.ts +1 -1
  257. package/src/features/playback/playing.ts +1 -1
  258. package/src/features/playback/progress.test.ts +169 -0
  259. package/src/features/playback/progress.ts +1 -1
  260. package/src/features/playback/state.ts +1 -1
  261. package/src/features/playback/trackPlaybackTime.test.ts +16 -6
  262. package/src/features/playback/trackPlaybackTime.ts +0 -5
  263. package/src/features/playback/volume.ts +1 -1
  264. package/src/features/player/options.ts +99 -57
  265. package/src/features/player/setup.test.ts +12 -4
  266. package/src/features/player/setup.ts +19 -9
  267. package/src/features/player/validateOptions.ts +19 -0
  268. package/src/features/queue/activeTrack.ts +1 -1
  269. package/src/features/queue/queue.ts +2 -2
  270. package/src/features/queue/repeatMode.ts +1 -1
  271. package/src/features/queue/shuffle.ts +1 -1
  272. package/src/features/remoteControls.ts +13 -92
  273. package/src/features/sleepTimer.test.ts +172 -0
  274. package/src/features/sleepTimer.ts +9 -1
  275. package/src/nitro-stub-drift.test.ts +237 -0
  276. package/src/public-surface.test.ts +107 -0
  277. package/src/specs/audio-browser.nitro.ts +1 -1
  278. package/src/test-utils/reactNativeStub.ts +60 -0
  279. package/src/utils/LazyNativeEmitter.ts +9 -6
  280. package/src/utils/useDebug.test.ts +182 -0
  281. package/src/utils/useNativeUpdatedValue.test.ts +103 -0
  282. package/src/web/NativeAudioBrowser.ts +1 -1
  283. package/src/web/browser/BrowserManager.ts +1 -1
  284. package/ios/Model/MediaURL.swift +0 -67
  285. package/nitrogen/generated/android/c++/JNotificationButtonLayout.hpp +0 -94
  286. package/nitrogen/generated/android/c++/JVariant_NullType_NotificationButtonLayout.cpp +0 -26
  287. package/nitrogen/generated/android/c++/JVariant_NullType_NotificationButtonLayout.hpp +0 -75
  288. package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NotificationButtonLayout.kt +0 -50
  289. package/nitrogen/generated/ios/swift/NotificationButtonLayout.swift +0 -92
  290. package/nitrogen/generated/shared/c++/NotificationButtonLayout.hpp +0 -102
@@ -0,0 +1,182 @@
1
+ /** @vitest-environment happy-dom */
2
+
3
+ import { renderHook, act, cleanup } from '@testing-library/react'
4
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
5
+
6
+ const native = vi.hoisted(() => {
7
+ const slots = new Map<string, (event: never) => void>()
8
+ return {
9
+ slots,
10
+ browser: new Proxy({} as Record<string, unknown>, {
11
+ get(target, prop: string) {
12
+ // Defaults have to be shaped, not undefined: useDebugState reads
13
+ // `playback.state`, `queue.map(...)` and `progress.position` directly.
14
+ target[prop] ??= vi.fn(() => defaults[prop])
15
+ return target[prop]
16
+ },
17
+ set(target, prop: string, value) {
18
+ if (typeof value === 'function') slots.set(prop, value)
19
+ target[prop] = value
20
+ return true
21
+ }
22
+ })
23
+ }
24
+ })
25
+
26
+ const defaults: Record<string, unknown> = {
27
+ getPlayback: { state: 'none' },
28
+ getQueue: [],
29
+ getProgress: { position: 0, duration: 0, buffered: 0 },
30
+ getOptions: {},
31
+ getPlayWhenReady: false,
32
+ getShuffle: false,
33
+ getRepeatMode: 'off',
34
+ getOnline: true
35
+ }
36
+
37
+ vi.mock('../native', () => ({ nativeBrowser: native.browser }))
38
+
39
+ const { useDebug } = await import('./useDebug')
40
+
41
+ const fire = (slot: string, event: unknown) =>
42
+ act(() => native.slots.get(slot)?.(event as never))
43
+
44
+ let logSpy: ReturnType<typeof vi.spyOn>
45
+
46
+ beforeEach(() => {
47
+ logSpy = vi.spyOn(console, 'log').mockImplementation(() => {})
48
+ // Emitters and the log store are module singletons, so both the last value
49
+ // and the entries outlive a test. Pin a baseline rather than letting each
50
+ // test inherit whatever the previous one happened to fire.
51
+ fire('onOnlineChanged', true)
52
+ fire('onPlaybackProgressUpdated', { position: 0, duration: 0, buffered: 0 })
53
+ const { result, unmount } = renderHook(() => useDebug({ enabled: false }))
54
+ act(() => result.current.clear())
55
+ unmount()
56
+ logSpy.mockClear()
57
+ })
58
+
59
+ afterEach(() => {
60
+ cleanup()
61
+ logSpy.mockRestore()
62
+ })
63
+
64
+ describe('useDebug', () => {
65
+ it('records nothing while disabled', () => {
66
+ const { result } = renderHook(() => useDebug({ enabled: false }))
67
+ fire('onOnlineChanged', false)
68
+ expect(result.current.logs).toEqual([])
69
+ expect(logSpy).not.toHaveBeenCalled()
70
+ })
71
+
72
+ it('logs a single initial snapshot on mount', () => {
73
+ const { result } = renderHook(() => useDebug({ enabled: true }))
74
+ expect(result.current.logs).toHaveLength(1)
75
+ expect(result.current.logs[0]).toMatchObject({
76
+ type: 'initial',
77
+ elapsed: null
78
+ })
79
+ expect(result.current.logs[0]!.message).toContain('online: true')
80
+ })
81
+
82
+ it('logs a change entry naming the field that moved', () => {
83
+ const { result } = renderHook(() => useDebug({ enabled: true }))
84
+ fire('onOnlineChanged', false)
85
+
86
+ expect(result.current.logs).toHaveLength(2)
87
+ const entry = result.current.logs[1]!
88
+ expect(entry.type).toBe('change')
89
+ expect(entry.message).toContain('online')
90
+ expect(entry.message).toContain('old → true')
91
+ expect(entry.message).toContain('new → false')
92
+ })
93
+
94
+ it('logs nothing when a re-render changes no field', () => {
95
+ const { result } = renderHook(() => useDebug({ enabled: true }))
96
+ fire('onOnlineChanged', true) // already true
97
+ expect(result.current.logs).toHaveLength(1)
98
+ })
99
+
100
+ // Progress ticks every second; logging each one would bury every other event.
101
+ it('ignores position drift under two seconds but reports a real seek', () => {
102
+ const { result } = renderHook(() => useDebug({ enabled: true }))
103
+
104
+ fire('onPlaybackProgressUpdated', { position: 1, duration: 0, buffered: 0 })
105
+ expect(result.current.logs).toHaveLength(1)
106
+
107
+ fire('onPlaybackProgressUpdated', {
108
+ position: 30,
109
+ duration: 0,
110
+ buffered: 0
111
+ })
112
+ expect(result.current.logs).toHaveLength(2)
113
+ expect(result.current.logs[1]!.message).toContain('position')
114
+ })
115
+
116
+ it('clears on demand', () => {
117
+ const { result } = renderHook(() => useDebug({ enabled: true }))
118
+ fire('onOnlineChanged', false)
119
+ expect(result.current.logs.length).toBeGreaterThan(0)
120
+
121
+ act(() => result.current.clear())
122
+ expect(result.current.logs).toEqual([])
123
+ })
124
+
125
+ it('caps the history and keeps the newest entries', () => {
126
+ const { result } = renderHook(() => useDebug({ enabled: true }))
127
+ for (let i = 0; i < 120; i++) fire('onOnlineChanged', i % 2 === 0)
128
+
129
+ expect(result.current.logs).toHaveLength(100)
130
+ // 120 alternating flips after the initial snapshot: the last one set online
131
+ // to false (i = 119 is odd), so the newest entry is the tail, not the head.
132
+ expect(result.current.logs.at(-1)!.message).toContain('new → false')
133
+ })
134
+
135
+ describe('metadata logging', () => {
136
+ it('is off by default', () => {
137
+ const { result } = renderHook(() => useDebug({ enabled: true }))
138
+ fire('onTrackMetadata', { title: 'Song' })
139
+ expect(result.current.logs.filter((l) => l.type === 'metadata')).toEqual(
140
+ []
141
+ )
142
+ })
143
+
144
+ it('records track, timed and chapter events when enabled', () => {
145
+ const { result } = renderHook(() =>
146
+ useDebug({ enabled: true, metadata: true })
147
+ )
148
+
149
+ fire('onTrackMetadata', { title: 'Song', artist: null })
150
+ fire('onTimedMetadata', { title: 'Live' })
151
+ fire('onChapterMetadata', [{}, {}])
152
+
153
+ const entries = result.current.logs.filter((l) => l.type === 'metadata')
154
+ expect(entries).toHaveLength(3)
155
+ expect(entries[0]!.message).toContain('[track] title: "Song"')
156
+ // Null fields are dropped rather than printed as `artist: "null"`.
157
+ expect(entries[0]!.message).not.toContain('artist')
158
+ expect(entries[1]!.message).toContain('[timed]')
159
+ expect(entries[2]!.message).toContain('2 chapters')
160
+ })
161
+
162
+ it('stops recording metadata after unmount', () => {
163
+ const { result, unmount } = renderHook(() =>
164
+ useDebug({ enabled: true, metadata: true })
165
+ )
166
+ const before = result.current.logs.length
167
+ unmount()
168
+ fire('onTrackMetadata', { title: 'Song' })
169
+ expect(result.current.logs).toHaveLength(before)
170
+ })
171
+ })
172
+
173
+ it('falls back to __DEV__ when enabled is not given', () => {
174
+ ;(globalThis as { __DEV__?: boolean }).__DEV__ = false
175
+ try {
176
+ const { result } = renderHook(() => useDebug())
177
+ expect(result.current.logs).toEqual([])
178
+ } finally {
179
+ delete (globalThis as { __DEV__?: boolean }).__DEV__
180
+ }
181
+ })
182
+ })
@@ -0,0 +1,103 @@
1
+ /** @vitest-environment happy-dom */
2
+
3
+ import { renderHook, act, cleanup } from '@testing-library/react'
4
+ import { describe, it, expect, afterEach, vi } from 'vitest'
5
+ import { NativeUpdatedValue } from './NativeUpdatedValue'
6
+ import { useNativeUpdatedValue } from './useNativeUpdatedValue'
7
+
8
+ afterEach(cleanup)
9
+
10
+ /**
11
+ * Builds an emitter plus the native-side callback that feeds it, so a test can
12
+ * push a value the way native would. `NativeUpdatedValue` hands its internal
13
+ * handler to the setter it is constructed with; capturing that handler _is_ the
14
+ * native bridge.
15
+ */
16
+ function makeEmitter<T>() {
17
+ let emit: (value: T) => void = () => {}
18
+ const emitter = NativeUpdatedValue.emitterize<T>((cb) => (emit = cb))
19
+ return {
20
+ emitter,
21
+ /** Emit from outside React, as a native event would arrive. */
22
+ fire: (value: T) => act(() => emit(value)),
23
+ /** Emit from inside a render pass, where wrapping in `act` would nest. */
24
+ fireDuringRender: (value: T) => emit(value)
25
+ }
26
+ }
27
+
28
+ describe('useNativeUpdatedValue', () => {
29
+ it('falls back to the getter when nothing has fired yet', () => {
30
+ const { emitter } = makeEmitter<string>()
31
+ const { result } = renderHook(() =>
32
+ useNativeUpdatedValue(() => 'a', emitter)
33
+ )
34
+ expect(result.current).toBe('a')
35
+ })
36
+
37
+ it('prefers lastValue over the getter', () => {
38
+ const { emitter, fire } = makeEmitter<string>()
39
+ fire('fromNative')
40
+ const getter = vi.fn(() => 'fromGetter')
41
+ const { result } = renderHook(() => useNativeUpdatedValue(getter, emitter))
42
+ expect(result.current).toBe('fromNative')
43
+ expect(getter).not.toHaveBeenCalled()
44
+ })
45
+
46
+ it('updates when the emitter fires', () => {
47
+ const { emitter, fire } = makeEmitter<string>()
48
+ const { result } = renderHook(() =>
49
+ useNativeUpdatedValue(() => 'a', emitter)
50
+ )
51
+ fire('b')
52
+ expect(result.current).toBe('b')
53
+ })
54
+
55
+ it('extracts eventKey from both lastValue and later events', () => {
56
+ const { emitter, fire } = makeEmitter<{ volume: number }>()
57
+ fire({ volume: 0.5 })
58
+ const { result } = renderHook(() =>
59
+ useNativeUpdatedValue(() => 0, emitter, 'volume')
60
+ )
61
+ expect(result.current).toBe(0.5)
62
+ fire({ volume: 0.9 })
63
+ expect(result.current).toBe(0.9)
64
+ })
65
+
66
+ // The reason the effect re-reads `lastValue` instead of going straight to
67
+ // `addListener`. Nothing reads the value again until the next native event, so
68
+ // a value landing in this window would otherwise be missed permanently.
69
+ it('re-syncs a value that lands between the render read and the effect', () => {
70
+ const { emitter, fireDuringRender } = makeEmitter<string>()
71
+ // Firing from inside the getter puts the emit exactly where the race is:
72
+ // after the useState initializer has read, before the effect subscribes.
73
+ const getter = () => {
74
+ fireDuringRender('landedMidRender')
75
+ return 'staleAtRender'
76
+ }
77
+ const { result } = renderHook(() => useNativeUpdatedValue(getter, emitter))
78
+ expect(result.current).toBe('landedMidRender')
79
+ })
80
+
81
+ it('stops updating after unmount', () => {
82
+ const { emitter, fire } = makeEmitter<string>()
83
+ const { result, unmount } = renderHook(() =>
84
+ useNativeUpdatedValue(() => 'a', emitter)
85
+ )
86
+ unmount()
87
+ fire('b')
88
+ expect(result.current).toBe('a')
89
+ })
90
+
91
+ it('leaves no listener behind on unmount', () => {
92
+ const { emitter, fire } = makeEmitter<string>()
93
+ const { unmount } = renderHook(() =>
94
+ useNativeUpdatedValue(() => 'a', emitter)
95
+ )
96
+ unmount()
97
+ const seen: string[] = []
98
+ emitter.addListener((v) => seen.push(v))
99
+ fire('b')
100
+ // Only the listener added above — the hook's is gone, not merely inert.
101
+ expect(seen).toEqual(['b'])
102
+ })
103
+ })
@@ -520,7 +520,7 @@ export class NativeAudioBrowser
520
520
  })
521
521
  }
522
522
 
523
- async onSearch(query: string): Promise<Track[]> {
523
+ async search(query: string): Promise<Track[]> {
524
524
  // Wrap query string in SearchParams (matches Android's search(query: String) overload)
525
525
  return this.searchManager.search({ query, reference: 'unknown' })
526
526
  }
@@ -573,7 +573,7 @@ export class BrowserManager {
573
573
  * `request → search` chain (search is its own kind — no browse layer). The
574
574
  * query params are seeded on the base so they survive both the static merge
575
575
  * and a search `transform`. Shared by `resolveSearchContent` (navigating to a
576
- * search path) and `SearchManager` (the voice/`onSearch` API), so the ladder
576
+ * search path) and `SearchManager` (the voice/`search` API), so the ladder
577
577
  * isn't duplicated. Errors propagate to the caller.
578
578
  */
579
579
  async fetchSearchResults(
@@ -1,67 +0,0 @@
1
- import Foundation
2
-
3
- struct MediaURL {
4
- let value: URL
5
- let isLocal: Bool
6
- private let originalObject: Any
7
-
8
- init?(object: Any?) {
9
- guard let object else { return nil }
10
- originalObject = object
11
-
12
- // This is based on logic found in RCTConvert NSURLRequest
13
- if let localObject = object as? [String: Any] {
14
- var urlString = localObject["uri"] as? String ?? localObject["url"] as! String
15
-
16
- if let bundleName = localObject["bundle"] as? String {
17
- urlString = String(format: "%@.bundle/%@", bundleName, urlString)
18
- }
19
-
20
- isLocal = !urlString.lowercased().hasPrefix("http")
21
- guard let converted = Self.convertToURL(urlString) else { return nil }
22
- value = converted
23
- } else {
24
- let urlString = object as! String
25
- isLocal = urlString.lowercased().hasPrefix("file://")
26
- guard let converted = Self.convertToURL(urlString) else { return nil }
27
- value = converted
28
- }
29
- }
30
-
31
- /// Convert a string to URL, matching RCTConvert NSURL behavior
32
- private static func convertToURL(_ string: String) -> URL? {
33
- // Try as absolute URL first
34
- if let url = URL(string: string), url.scheme != nil {
35
- return url
36
- }
37
-
38
- // If it has a scheme but failed, try percent-encoding
39
- if string.contains("://") {
40
- var allowed = CharacterSet()
41
- allowed.formUnion(.urlUserAllowed)
42
- allowed.formUnion(.urlPasswordAllowed)
43
- allowed.formUnion(.urlHostAllowed)
44
- allowed.formUnion(.urlPathAllowed)
45
- allowed.formUnion(.urlQueryAllowed)
46
- allowed.formUnion(.urlFragmentAllowed)
47
- if let encoded = string.addingPercentEncoding(withAllowedCharacters: allowed),
48
- let url = URL(string: encoded)
49
- {
50
- return url
51
- }
52
- }
53
-
54
- // Assume it's a local path
55
- var path = string.removingPercentEncoding ?? string
56
-
57
- if path.hasPrefix("~") {
58
- // Expand tilde for user directory
59
- path = NSString(string: path).expandingTildeInPath
60
- } else if !path.hasPrefix("/") {
61
- // Not absolute - assume it's a bundle resource path
62
- path = (Bundle.main.resourcePath ?? "") + "/" + path
63
- }
64
-
65
- return URL(fileURLWithPath: path)
66
- }
67
- }
@@ -1,94 +0,0 @@
1
- ///
2
- /// JNotificationButtonLayout.hpp
3
- /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
- /// https://github.com/mrousavy/nitro
5
- /// Copyright © Marc Rousavy @ Margelo
6
- ///
7
-
8
- #pragma once
9
-
10
- #include <fbjni/fbjni.h>
11
- #include "NotificationButtonLayout.hpp"
12
-
13
- #include "JNotificationButton.hpp"
14
- #include "NotificationButton.hpp"
15
- #include <optional>
16
- #include <vector>
17
-
18
- namespace margelo::nitro::audiobrowser {
19
-
20
- using namespace facebook;
21
-
22
- /**
23
- * The C++ JNI bridge between the C++ struct "NotificationButtonLayout" and the the Kotlin data class "NotificationButtonLayout".
24
- */
25
- struct JNotificationButtonLayout final: public jni::JavaClass<JNotificationButtonLayout> {
26
- public:
27
- static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/audiobrowser/NotificationButtonLayout;";
28
-
29
- public:
30
- /**
31
- * Convert this Java/Kotlin-based struct to the C++ struct NotificationButtonLayout by copying all values to C++.
32
- */
33
- [[maybe_unused]]
34
- [[nodiscard]]
35
- NotificationButtonLayout toCpp() const {
36
- static const auto clazz = javaClassStatic();
37
- static const auto fieldBack = clazz->getField<JNotificationButton>("back");
38
- jni::local_ref<JNotificationButton> back = this->getFieldValue(fieldBack);
39
- static const auto fieldForward = clazz->getField<JNotificationButton>("forward");
40
- jni::local_ref<JNotificationButton> forward = this->getFieldValue(fieldForward);
41
- static const auto fieldBackSecondary = clazz->getField<JNotificationButton>("backSecondary");
42
- jni::local_ref<JNotificationButton> backSecondary = this->getFieldValue(fieldBackSecondary);
43
- static const auto fieldForwardSecondary = clazz->getField<JNotificationButton>("forwardSecondary");
44
- jni::local_ref<JNotificationButton> forwardSecondary = this->getFieldValue(fieldForwardSecondary);
45
- static const auto fieldOverflow = clazz->getField<jni::JArrayClass<JNotificationButton>>("overflow");
46
- jni::local_ref<jni::JArrayClass<JNotificationButton>> overflow = this->getFieldValue(fieldOverflow);
47
- return NotificationButtonLayout(
48
- back != nullptr ? std::make_optional(back->toCpp()) : std::nullopt,
49
- forward != nullptr ? std::make_optional(forward->toCpp()) : std::nullopt,
50
- backSecondary != nullptr ? std::make_optional(backSecondary->toCpp()) : std::nullopt,
51
- forwardSecondary != nullptr ? std::make_optional(forwardSecondary->toCpp()) : std::nullopt,
52
- overflow != nullptr ? std::make_optional([&]() {
53
- size_t __size = overflow->size();
54
- std::vector<NotificationButton> __vector;
55
- __vector.reserve(__size);
56
- for (size_t __i = 0; __i < __size; __i++) {
57
- auto __element = overflow->getElement(__i);
58
- __vector.push_back(__element->toCpp());
59
- }
60
- return __vector;
61
- }()) : std::nullopt
62
- );
63
- }
64
-
65
- public:
66
- /**
67
- * Create a Java/Kotlin-based struct by copying all values from the given C++ struct to Java.
68
- */
69
- [[maybe_unused]]
70
- static jni::local_ref<JNotificationButtonLayout::javaobject> fromCpp(const NotificationButtonLayout& value) {
71
- using JSignature = JNotificationButtonLayout(jni::alias_ref<JNotificationButton>, jni::alias_ref<JNotificationButton>, jni::alias_ref<JNotificationButton>, jni::alias_ref<JNotificationButton>, jni::alias_ref<jni::JArrayClass<JNotificationButton>>);
72
- static const auto clazz = javaClassStatic();
73
- static const auto create = clazz->getStaticMethod<JSignature>("fromCpp");
74
- return create(
75
- clazz,
76
- value.back.has_value() ? JNotificationButton::fromCpp(value.back.value()) : nullptr,
77
- value.forward.has_value() ? JNotificationButton::fromCpp(value.forward.value()) : nullptr,
78
- value.backSecondary.has_value() ? JNotificationButton::fromCpp(value.backSecondary.value()) : nullptr,
79
- value.forwardSecondary.has_value() ? JNotificationButton::fromCpp(value.forwardSecondary.value()) : nullptr,
80
- value.overflow.has_value() ? [&]() {
81
- size_t __size = value.overflow.value().size();
82
- jni::local_ref<jni::JArrayClass<JNotificationButton>> __array = jni::JArrayClass<JNotificationButton>::newArray(__size);
83
- for (size_t __i = 0; __i < __size; __i++) {
84
- const auto& __element = value.overflow.value()[__i];
85
- auto __elementJni = JNotificationButton::fromCpp(__element);
86
- __array->setElement(__i, *__elementJni);
87
- }
88
- return __array;
89
- }() : nullptr
90
- );
91
- }
92
- };
93
-
94
- } // namespace margelo::nitro::audiobrowser
@@ -1,26 +0,0 @@
1
- ///
2
- /// JVariant_NullType_NotificationButtonLayout.cpp
3
- /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
- /// https://github.com/mrousavy/nitro
5
- /// Copyright © Marc Rousavy @ Margelo
6
- ///
7
-
8
- #include "JVariant_NullType_NotificationButtonLayout.hpp"
9
-
10
- namespace margelo::nitro::audiobrowser {
11
- /**
12
- * Converts JVariant_NullType_NotificationButtonLayout to std::variant<nitro::NullType, NotificationButtonLayout>
13
- */
14
- std::variant<nitro::NullType, NotificationButtonLayout> JVariant_NullType_NotificationButtonLayout::toCpp() const {
15
- if (isInstanceOf(JVariant_NullType_NotificationButtonLayout_impl::First::javaClassStatic())) {
16
- // It's a `nitro::NullType`
17
- auto jniValue = static_cast<const JVariant_NullType_NotificationButtonLayout_impl::First*>(this)->getValue();
18
- return nitro::null;
19
- } else if (isInstanceOf(JVariant_NullType_NotificationButtonLayout_impl::Second::javaClassStatic())) {
20
- // It's a `NotificationButtonLayout`
21
- auto jniValue = static_cast<const JVariant_NullType_NotificationButtonLayout_impl::Second*>(this)->getValue();
22
- return jniValue->toCpp();
23
- }
24
- throw std::invalid_argument("Variant is unknown Kotlin instance!");
25
- }
26
- } // namespace margelo::nitro::audiobrowser
@@ -1,75 +0,0 @@
1
- ///
2
- /// JVariant_NullType_NotificationButtonLayout.hpp
3
- /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
- /// https://github.com/mrousavy/nitro
5
- /// Copyright © Marc Rousavy @ Margelo
6
- ///
7
-
8
- #pragma once
9
-
10
- #include <fbjni/fbjni.h>
11
- #include <variant>
12
-
13
- #include <NitroModules/Null.hpp>
14
- #include "NotificationButtonLayout.hpp"
15
- #include <variant>
16
- #include <NitroModules/JNull.hpp>
17
- #include "JNotificationButtonLayout.hpp"
18
- #include "NotificationButton.hpp"
19
- #include <optional>
20
- #include "JNotificationButton.hpp"
21
- #include <vector>
22
-
23
- namespace margelo::nitro::audiobrowser {
24
-
25
- using namespace facebook;
26
-
27
- /**
28
- * The C++ JNI bridge between the C++ std::variant and the Java class "Variant_NullType_NotificationButtonLayout".
29
- */
30
- class JVariant_NullType_NotificationButtonLayout: public jni::JavaClass<JVariant_NullType_NotificationButtonLayout> {
31
- public:
32
- static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/audiobrowser/Variant_NullType_NotificationButtonLayout;";
33
-
34
- static jni::local_ref<JVariant_NullType_NotificationButtonLayout> create_0(jni::alias_ref<JNull> value) {
35
- static const auto method = javaClassStatic()->getStaticMethod<JVariant_NullType_NotificationButtonLayout(jni::alias_ref<JNull>)>("create");
36
- return method(javaClassStatic(), value);
37
- }
38
- static jni::local_ref<JVariant_NullType_NotificationButtonLayout> create_1(jni::alias_ref<JNotificationButtonLayout> value) {
39
- static const auto method = javaClassStatic()->getStaticMethod<JVariant_NullType_NotificationButtonLayout(jni::alias_ref<JNotificationButtonLayout>)>("create");
40
- return method(javaClassStatic(), value);
41
- }
42
-
43
- static jni::local_ref<JVariant_NullType_NotificationButtonLayout> fromCpp(const std::variant<nitro::NullType, NotificationButtonLayout>& variant) {
44
- switch (variant.index()) {
45
- case 0: return create_0(JNull::null());
46
- case 1: return create_1(JNotificationButtonLayout::fromCpp(std::get<1>(variant)));
47
- default: throw std::invalid_argument("Variant holds unknown index! (" + std::to_string(variant.index()) + ")");
48
- }
49
- }
50
-
51
- [[nodiscard]] std::variant<nitro::NullType, NotificationButtonLayout> toCpp() const;
52
- };
53
-
54
- namespace JVariant_NullType_NotificationButtonLayout_impl {
55
- class First final: public jni::JavaClass<First, JVariant_NullType_NotificationButtonLayout> {
56
- public:
57
- static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/audiobrowser/Variant_NullType_NotificationButtonLayout$First;";
58
-
59
- [[nodiscard]] jni::local_ref<JNull> getValue() const {
60
- static const auto field = javaClassStatic()->getField<JNull>("value");
61
- return getFieldValue(field);
62
- }
63
- };
64
-
65
- class Second final: public jni::JavaClass<Second, JVariant_NullType_NotificationButtonLayout> {
66
- public:
67
- static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/audiobrowser/Variant_NullType_NotificationButtonLayout$Second;";
68
-
69
- [[nodiscard]] jni::local_ref<JNotificationButtonLayout> getValue() const {
70
- static const auto field = javaClassStatic()->getField<JNotificationButtonLayout>("value");
71
- return getFieldValue(field);
72
- }
73
- };
74
- } // namespace JVariant_NullType_NotificationButtonLayout_impl
75
- } // namespace margelo::nitro::audiobrowser
@@ -1,50 +0,0 @@
1
- ///
2
- /// NotificationButtonLayout.kt
3
- /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
4
- /// https://github.com/mrousavy/nitro
5
- /// Copyright © Marc Rousavy @ Margelo
6
- ///
7
-
8
- package com.margelo.nitro.audiobrowser
9
-
10
- import androidx.annotation.Keep
11
- import com.facebook.proguard.annotations.DoNotStrip
12
-
13
-
14
- /**
15
- * Represents the JavaScript object/struct "NotificationButtonLayout".
16
- */
17
- @DoNotStrip
18
- @Keep
19
- data class NotificationButtonLayout(
20
- @DoNotStrip
21
- @Keep
22
- val back: NotificationButton?,
23
- @DoNotStrip
24
- @Keep
25
- val forward: NotificationButton?,
26
- @DoNotStrip
27
- @Keep
28
- val backSecondary: NotificationButton?,
29
- @DoNotStrip
30
- @Keep
31
- val forwardSecondary: NotificationButton?,
32
- @DoNotStrip
33
- @Keep
34
- val overflow: Array<NotificationButton>?
35
- ) {
36
- /* primary constructor */
37
-
38
- companion object {
39
- /**
40
- * Constructor called from C++
41
- */
42
- @DoNotStrip
43
- @Keep
44
- @Suppress("unused")
45
- @JvmStatic
46
- private fun fromCpp(back: NotificationButton?, forward: NotificationButton?, backSecondary: NotificationButton?, forwardSecondary: NotificationButton?, overflow: Array<NotificationButton>?): NotificationButtonLayout {
47
- return NotificationButtonLayout(back, forward, backSecondary, forwardSecondary, overflow)
48
- }
49
- }
50
- }