react-native-audio-browser 0.2.0-next.11 → 0.2.0-next.13
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.
- package/README.md +14 -4
- package/android/build.gradle +20 -1
- package/android/src/main/java/com/audiobrowser/AudioBrowser.kt +115 -26
- package/android/src/main/java/com/audiobrowser/browser/BrowserManager.kt +262 -188
- package/android/src/main/java/com/audiobrowser/browser/BrowserUrlResolution.kt +23 -3
- package/android/src/main/java/com/audiobrowser/browser/InertStyleDiagnostic.kt +267 -0
- package/android/src/main/java/com/audiobrowser/browser/JsonModels.kt +95 -58
- package/android/src/main/java/com/audiobrowser/browser/SectionScope.kt +68 -26
- package/android/src/main/java/com/audiobrowser/browser/StyleResolver.kt +60 -0
- package/android/src/main/java/com/audiobrowser/extension/ResolvedTrackExt.kt +19 -7
- package/android/src/main/java/com/audiobrowser/extension/TappedTrack.kt +20 -0
- package/android/src/main/java/com/audiobrowser/extension/TrackIdentity.kt +15 -0
- package/android/src/main/java/com/audiobrowser/model/PlayerUpdateOptions.kt +1 -1
- package/android/src/main/java/com/audiobrowser/player/MediaSessionCallback.kt +120 -67
- package/android/src/main/java/com/audiobrowser/player/NowPlayingUpdater.kt +21 -24
- package/android/src/main/java/com/audiobrowser/player/PlaybackStateStore.kt +109 -74
- package/android/src/main/java/com/audiobrowser/player/Player.kt +51 -30
- package/android/src/main/java/com/audiobrowser/player/PlayerCapabilitiesExt.kt +2 -15
- package/android/src/main/java/com/audiobrowser/player/ShuffleOrderLedBy.kt +30 -0
- package/android/src/main/java/com/audiobrowser/util/BrowserPathHelper.kt +44 -40
- package/android/src/main/java/com/audiobrowser/util/MediaExtrasBuilder.kt +28 -23
- package/android/src/main/java/com/audiobrowser/util/StyleWire.kt +108 -0
- package/android/src/main/java/com/audiobrowser/util/TrackFactory.kt +52 -53
- package/android/src/test/java/com/audiobrowser/TestFixtures.kt +74 -41
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerFavoritesTest.kt +153 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerTest.kt +229 -50
- package/android/src/test/java/com/audiobrowser/browser/BrowserUrlResolutionTest.kt +38 -0
- package/android/src/test/java/com/audiobrowser/browser/InertStyleDiagnosticTest.kt +277 -0
- package/android/src/test/java/com/audiobrowser/browser/JsonArtworkTest.kt +1 -1
- package/android/src/test/java/com/audiobrowser/browser/JsonStyleTest.kt +147 -0
- package/android/src/test/java/com/audiobrowser/browser/SectionScopeTest.kt +128 -53
- package/android/src/test/java/com/audiobrowser/browser/StyleResolverTest.kt +154 -0
- package/android/src/test/java/com/audiobrowser/extension/TappedTrackTest.kt +43 -0
- package/android/src/test/java/com/audiobrowser/extension/TrackIdentityTest.kt +41 -0
- package/android/src/test/java/com/audiobrowser/player/CapabilityControlsTest.kt +1 -2
- package/android/src/test/java/com/audiobrowser/player/NowPlayingUpdaterTest.kt +42 -2
- package/android/src/test/java/com/audiobrowser/player/PlaybackStateStoreTrackJsonTest.kt +55 -0
- package/android/src/test/java/com/audiobrowser/player/ShuffleOrderLedByTest.kt +79 -0
- package/android/src/test/java/com/audiobrowser/util/BrowserPathHelperTest.kt +41 -16
- package/android/src/test/java/com/audiobrowser/util/MediaExtrasBuilderTest.kt +161 -0
- package/android/src/test/java/com/audiobrowser/util/TrackFactoryMediaIdTest.kt +7 -7
- package/ios/Browser/BrowserConfig.swift +102 -5
- package/ios/Browser/BrowserManager+URLResolution.swift +18 -14
- package/ios/Browser/BrowserManager.swift +229 -180
- package/ios/Browser/BrowserPathHelper.swift +44 -44
- package/ios/Browser/InertStyleDiagnostic.swift +279 -0
- package/ios/Browser/JsonModels.swift +258 -106
- package/ios/Browser/SearchDrillIn.swift +6 -6
- package/ios/Browser/SectionPresentation.swift +64 -0
- package/ios/Browser/SectionScope.swift +58 -24
- package/ios/Browser/StyleResolver.swift +58 -0
- package/ios/Browser/TabBarEntries.swift +9 -3
- package/ios/Browser/TrackIdTemplate.swift +37 -0
- package/ios/CarPlay/CarPlayArtworkResolver.swift +8 -7
- package/ios/CarPlay/CarPlayController.swift +227 -85
- package/ios/CarPlay/CarPlayImageLoader.swift +38 -18
- package/ios/CarPlay/CarPlayListItemFactory.swift +289 -84
- package/ios/CarPlay/CarPlayNowPlayingManager.swift +15 -12
- package/ios/Extension/Capability+RemoteCommand.swift +1 -1
- package/ios/Extension/PlayerCapabilities+Favorite.swift +1 -15
- package/ios/Extension/ResolvedTrack+Copying.swift +11 -15
- package/ios/Extension/Section+Copying.swift +31 -0
- package/ios/Extension/Track+Copying.swift +6 -12
- package/ios/Extension/Track+Identity.swift +18 -0
- package/ios/Extension/UIApplication+ActiveScene.swift +27 -0
- package/ios/Http/HttpClient.swift +8 -2
- package/ios/HybridAudioBrowser.swift +166 -45
- package/ios/Model/NitroTypeStubs.swift +106 -21
- package/ios/Model/PlayerUpdateOptions.swift +7 -0
- package/ios/Player/MediaIntentCriteria.swift +13 -5
- package/ios/Player/MediaLoader.swift +33 -9
- package/ios/Player/NowPlayingUpdater.swift +54 -6
- package/ios/Player/PlaybackCoordinator.swift +13 -6
- package/ios/Player/PlaybackTimer.swift +8 -2
- package/ios/Player/QueueManager.swift +36 -10
- package/ios/Player/RetryManager.swift +4 -3
- package/ios/Player/ShuffleOrder.swift +23 -0
- package/ios/Player/SleepTimerHandling.swift +13 -0
- package/ios/RemoteCommand/RemoteCommandController.swift +53 -18
- package/ios/Tests/BrowserPathHelperTests.swift +50 -20
- package/ios/Tests/CarPlayArtworkResolverTests.swift +24 -41
- package/ios/Tests/InertStyleDiagnosticTests.swift +200 -0
- package/ios/Tests/JsonModelsTests.swift +150 -1
- package/ios/Tests/PlaybackStateStoreTests.swift +4 -3
- package/ios/Tests/QueueManagerTests.swift +72 -6
- package/ios/Tests/RemoteCommandControllerTests.swift +16 -0
- package/ios/Tests/ResolvedTrackCopyingTests.swift +37 -35
- package/ios/Tests/SearchDrillInTests.swift +16 -16
- package/ios/Tests/SectionPresentationTests.swift +90 -0
- package/ios/Tests/SectionScopeTests.swift +87 -55
- package/ios/Tests/StyleResolverTests.swift +127 -0
- package/ios/Tests/Support/TestTypes.swift +7 -0
- package/ios/Tests/TabBarEntriesTests.swift +18 -18
- package/ios/Tests/TrackIdTemplateTests.swift +67 -0
- package/ios/Tests/TrackIdentityTests.swift +20 -0
- package/ios/Tests/TrackSelectorTests.swift +168 -33
- package/ios/TrackPlayer.swift +57 -34
- package/ios/TrackSelector.swift +45 -30
- package/ios/Util/ArtworkImageFetcher.swift +16 -1
- package/ios/Util/NetworkMonitor.swift +43 -26
- package/ios/Util/SFSymbolRenderer.swift +24 -2
- package/ios/Util/SVGProcessor.swift +9 -2
- package/lib/commonjs/AudioBrowser.js +11 -0
- package/lib/commonjs/AudioBrowser.js.map +1 -1
- package/lib/commonjs/features/browser-config.js +11 -8
- package/lib/commonjs/features/browser-config.js.map +1 -1
- package/lib/commonjs/features/browser.js +2 -2
- package/lib/commonjs/features/favorites.js +13 -10
- package/lib/commonjs/features/favorites.js.map +1 -1
- package/lib/commonjs/features/playback/controls.js +4 -2
- package/lib/commonjs/features/playback/controls.js.map +1 -1
- package/lib/commonjs/features/playback/progress.js +2 -1
- package/lib/commonjs/features/playback/progress.js.map +1 -1
- package/lib/commonjs/features/playback/rate.js +8 -1
- package/lib/commonjs/features/playback/rate.js.map +1 -1
- package/lib/commonjs/features/playback/state.js +2 -3
- package/lib/commonjs/features/playback/state.js.map +1 -1
- package/lib/commonjs/features/player/options.js.map +1 -1
- package/lib/commonjs/features/player/setup.js +3 -1
- package/lib/commonjs/features/player/setup.js.map +1 -1
- package/lib/commonjs/features/player/validateOptions.js +2 -0
- package/lib/commonjs/features/player/validateOptions.js.map +1 -1
- package/lib/commonjs/features/queue/activeTrack.js +14 -3
- package/lib/commonjs/features/queue/activeTrack.js.map +1 -1
- package/lib/commonjs/features/queue/queue.js +11 -4
- package/lib/commonjs/features/queue/queue.js.map +1 -1
- package/lib/commonjs/utils/LazyNativeEmitter.js +21 -10
- package/lib/commonjs/utils/LazyNativeEmitter.js.map +1 -1
- package/lib/commonjs/utils/NativeUpdatedValue.js +31 -13
- package/lib/commonjs/utils/NativeUpdatedValue.js.map +1 -1
- package/lib/commonjs/utils/getTrackIdentity.js +24 -0
- package/lib/commonjs/utils/getTrackIdentity.js.map +1 -0
- package/lib/commonjs/utils/useNativeValueRefreshedBy.js +33 -0
- package/lib/commonjs/utils/useNativeValueRefreshedBy.js.map +1 -0
- package/lib/commonjs/web/NativeAudioBrowser.js +32 -24
- package/lib/commonjs/web/NativeAudioBrowser.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/QueueManager.js +14 -0
- package/lib/commonjs/web/TrackPlayer/QueueManager.js.map +1 -1
- package/lib/commonjs/web/browser/BrowserManager.js +144 -87
- package/lib/commonjs/web/browser/BrowserManager.js.map +1 -1
- package/lib/commonjs/web/browser/FavoriteManager.js +30 -21
- package/lib/commonjs/web/browser/FavoriteManager.js.map +1 -1
- package/lib/commonjs/web/browser/assertBrowsePageShape.js +2 -2
- package/lib/commonjs/web/browser/assertBrowsePageShape.js.map +1 -1
- package/lib/commonjs/web/browser/classifyTrackNavigation.js +9 -9
- package/lib/commonjs/web/browser/classifyTrackNavigation.js.map +1 -1
- package/lib/commonjs/web/browser/sections.js +89 -0
- package/lib/commonjs/web/browser/sections.js.map +1 -0
- package/lib/commonjs/web/player/NowPlayingManager.js +4 -3
- package/lib/commonjs/web/player/NowPlayingManager.js.map +1 -1
- package/lib/commonjs/web/util/BrowserPathHelper.js +56 -11
- package/lib/commonjs/web/util/BrowserPathHelper.js.map +1 -1
- package/lib/module/AudioBrowser.js +1 -0
- package/lib/module/AudioBrowser.js.map +1 -1
- package/lib/module/features/browser-config.js +11 -8
- package/lib/module/features/browser-config.js.map +1 -1
- package/lib/module/features/browser.js +2 -2
- package/lib/module/features/favorites.js +13 -10
- package/lib/module/features/favorites.js.map +1 -1
- package/lib/module/features/playback/controls.js +4 -2
- package/lib/module/features/playback/controls.js.map +1 -1
- package/lib/module/features/playback/progress.js +2 -1
- package/lib/module/features/playback/progress.js.map +1 -1
- package/lib/module/features/playback/rate.js +8 -1
- package/lib/module/features/playback/rate.js.map +1 -1
- package/lib/module/features/playback/state.js +2 -3
- package/lib/module/features/playback/state.js.map +1 -1
- package/lib/module/features/player/options.js.map +1 -1
- package/lib/module/features/player/setup.js +3 -1
- package/lib/module/features/player/setup.js.map +1 -1
- package/lib/module/features/player/validateOptions.js +2 -0
- package/lib/module/features/player/validateOptions.js.map +1 -1
- package/lib/module/features/queue/activeTrack.js +14 -3
- package/lib/module/features/queue/activeTrack.js.map +1 -1
- package/lib/module/features/queue/queue.js +11 -4
- package/lib/module/features/queue/queue.js.map +1 -1
- package/lib/module/utils/LazyNativeEmitter.js +21 -10
- package/lib/module/utils/LazyNativeEmitter.js.map +1 -1
- package/lib/module/utils/NativeUpdatedValue.js +31 -13
- package/lib/module/utils/NativeUpdatedValue.js.map +1 -1
- package/lib/module/utils/getTrackIdentity.js +20 -0
- package/lib/module/utils/getTrackIdentity.js.map +1 -0
- package/lib/module/utils/useNativeValueRefreshedBy.js +29 -0
- package/lib/module/utils/useNativeValueRefreshedBy.js.map +1 -0
- package/lib/module/web/NativeAudioBrowser.js +32 -24
- package/lib/module/web/NativeAudioBrowser.js.map +1 -1
- package/lib/module/web/TrackPlayer/QueueManager.js +14 -0
- package/lib/module/web/TrackPlayer/QueueManager.js.map +1 -1
- package/lib/module/web/browser/BrowserManager.js +144 -87
- package/lib/module/web/browser/BrowserManager.js.map +1 -1
- package/lib/module/web/browser/FavoriteManager.js +31 -21
- package/lib/module/web/browser/FavoriteManager.js.map +1 -1
- package/lib/module/web/browser/assertBrowsePageShape.js +2 -2
- package/lib/module/web/browser/assertBrowsePageShape.js.map +1 -1
- package/lib/module/web/browser/classifyTrackNavigation.js +9 -9
- package/lib/module/web/browser/classifyTrackNavigation.js.map +1 -1
- package/lib/module/web/browser/sections.js +83 -0
- package/lib/module/web/browser/sections.js.map +1 -0
- package/lib/module/web/player/NowPlayingManager.js +4 -3
- package/lib/module/web/player/NowPlayingManager.js.map +1 -1
- package/lib/module/web/util/BrowserPathHelper.js +56 -11
- package/lib/module/web/util/BrowserPathHelper.js.map +1 -1
- package/lib/typescript/src/AudioBrowser.d.ts +1 -0
- package/lib/typescript/src/AudioBrowser.d.ts.map +1 -1
- package/lib/typescript/src/features/browser-config.d.ts.map +1 -1
- package/lib/typescript/src/features/browser.d.ts +2 -2
- package/lib/typescript/src/features/favorites.d.ts +13 -10
- package/lib/typescript/src/features/favorites.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/controls.d.ts +4 -2
- package/lib/typescript/src/features/playback/controls.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/progress.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/rate.d.ts +8 -1
- package/lib/typescript/src/features/playback/rate.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/state.d.ts +2 -3
- package/lib/typescript/src/features/playback/state.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts +1 -1
- package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts.map +1 -1
- package/lib/typescript/src/features/player/options.d.ts +21 -19
- package/lib/typescript/src/features/player/options.d.ts.map +1 -1
- package/lib/typescript/src/features/player/setup.d.ts.map +1 -1
- package/lib/typescript/src/features/player/validateOptions.d.ts +1 -8
- package/lib/typescript/src/features/player/validateOptions.d.ts.map +1 -1
- package/lib/typescript/src/features/queue/activeTrack.d.ts +8 -1
- package/lib/typescript/src/features/queue/activeTrack.d.ts.map +1 -1
- package/lib/typescript/src/features/queue/queue.d.ts +5 -2
- package/lib/typescript/src/features/queue/queue.d.ts.map +1 -1
- package/lib/typescript/src/types/browser-native.d.ts +2 -2
- package/lib/typescript/src/types/browser-native.d.ts.map +1 -1
- package/lib/typescript/src/types/browser-nodes.d.ts +361 -126
- package/lib/typescript/src/types/browser-nodes.d.ts.map +1 -1
- package/lib/typescript/src/types/browser.d.ts +33 -53
- package/lib/typescript/src/types/browser.d.ts.map +1 -1
- package/lib/typescript/src/utils/LazyNativeEmitter.d.ts +16 -17
- package/lib/typescript/src/utils/LazyNativeEmitter.d.ts.map +1 -1
- package/lib/typescript/src/utils/NativeUpdatedValue.d.ts +24 -19
- package/lib/typescript/src/utils/NativeUpdatedValue.d.ts.map +1 -1
- package/lib/typescript/src/utils/getTrackIdentity.d.ts +18 -0
- package/lib/typescript/src/utils/getTrackIdentity.d.ts.map +1 -0
- package/lib/typescript/src/utils/useNativeValueRefreshedBy.d.ts +21 -0
- package/lib/typescript/src/utils/useNativeValueRefreshedBy.d.ts.map +1 -0
- package/nitrogen/generated/android/AudioBrowser+autolinking.cmake +0 -1
- package/nitrogen/generated/android/c++/{JFavoritesMatchMode.hpp → JArtworkRendering.hpp} +15 -15
- package/nitrogen/generated/android/c++/JArtworkRequestConfig.hpp +8 -3
- package/nitrogen/generated/android/c++/JBrowseResult.hpp +16 -4
- package/nitrogen/generated/android/c++/JCarPlayPlayingIndicatorLocation.hpp +58 -0
- package/nitrogen/generated/android/c++/JCardImage.hpp +58 -0
- package/nitrogen/generated/android/c++/JFavoriteChangedEvent.hpp +8 -3
- package/nitrogen/generated/android/c++/JFormatNowPlayingParams.hpp +8 -3
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___Track.hpp +8 -3
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.hpp +8 -3
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_std__string____Track.hpp +8 -3
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____Track.hpp +8 -3
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_Track______SearchParams.hpp +8 -2
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_void_____TrackLoadEvent.hpp +8 -2
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.hpp +16 -4
- package/nitrogen/generated/android/c++/JFunc_void_FavoriteChangedEvent.hpp +8 -3
- package/nitrogen/generated/android/c++/JFunc_void_Options.hpp +2 -5
- package/nitrogen/generated/android/c++/JFunc_void_PlaybackActiveTrackChangedEvent.hpp +8 -3
- package/nitrogen/generated/android/c++/JFunc_void_std__optional_ResolvedTrack_.hpp +15 -3
- package/nitrogen/generated/android/c++/JFunc_void_std__vector_Track_.hpp +8 -2
- package/nitrogen/generated/android/c++/JGridTile.hpp +61 -0
- package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.cpp +33 -14
- package/nitrogen/generated/android/c++/JIOSOptions.hpp +9 -3
- package/nitrogen/generated/android/c++/JImageShape.hpp +58 -0
- package/nitrogen/generated/android/c++/JMediaRequestConfig.hpp +8 -3
- package/nitrogen/generated/android/c++/JNativeBrowserConfiguration.hpp +22 -10
- package/nitrogen/generated/android/c++/JNativeRouteEntry.hpp +14 -2
- package/nitrogen/generated/android/c++/JNativeSetupPlayerOptions.hpp +10 -7
- package/nitrogen/generated/android/c++/JNativeUpdateOptions.hpp +2 -5
- package/nitrogen/generated/android/c++/JNitroIOSUpdateOptions.hpp +9 -3
- package/nitrogen/generated/android/c++/JOptions.hpp +2 -5
- package/nitrogen/generated/android/c++/JPlaybackActiveTrackChangedEvent.hpp +8 -3
- package/nitrogen/generated/android/c++/JPlayerCapabilities.hpp +5 -11
- package/nitrogen/generated/android/c++/JResolvedTrack.hpp +55 -51
- package/nitrogen/generated/android/c++/JSection.hpp +120 -0
- package/nitrogen/generated/android/c++/JSectionStyle.hpp +96 -0
- package/nitrogen/generated/android/c++/JStyleDisplay.hpp +58 -0
- package/nitrogen/generated/android/c++/JTrack.hpp +23 -48
- package/nitrogen/generated/android/c++/JTrackLoadEvent.hpp +8 -2
- package/nitrogen/generated/android/c++/JTrackStyle.hpp +46 -18
- package/nitrogen/generated/android/c++/JVariant_ResolvedTrack_BrowseError_Promise_BrowseResult_.hpp +16 -4
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{FavoritesMatchMode.kt → ArtworkRendering.kt} +5 -5
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/CarPlayPlayingIndicatorLocation.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/CardImage.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/GridTile.kt +24 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IOSOptions.kt +6 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageShape.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeBrowserConfiguration.kt +5 -5
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroIOSUpdateOptions.kt +6 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlayerCapabilities.kt +2 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ResolvedTrack.kt +12 -18
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{FavoriteConfig.kt → Section.kt} +18 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SectionStyle.kt +59 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/StyleDisplay.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Track.kt +6 -15
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackStyle.kt +35 -5
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.hpp +158 -82
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Umbrella.hpp +25 -10
- package/nitrogen/generated/ios/c++/HybridAudioBrowserSpecSwift.hpp +25 -10
- package/nitrogen/generated/ios/swift/ArtworkRendering.swift +40 -0
- package/nitrogen/generated/ios/swift/CarPlayPlayingIndicatorLocation.swift +40 -0
- package/nitrogen/generated/ios/swift/CardImage.swift +40 -0
- package/nitrogen/generated/ios/swift/GridTile.swift +44 -0
- package/nitrogen/generated/ios/swift/IOSOptions.swift +7 -2
- package/nitrogen/generated/ios/swift/ImageShape.swift +40 -0
- package/nitrogen/generated/ios/swift/NativeBrowserConfiguration.swift +5 -5
- package/nitrogen/generated/ios/swift/NitroIOSUpdateOptions.swift +12 -1
- package/nitrogen/generated/ios/swift/PlayerCapabilities.swift +8 -27
- package/nitrogen/generated/ios/swift/ResolvedTrack.swift +54 -83
- package/nitrogen/generated/ios/swift/Section.swift +100 -0
- package/nitrogen/generated/ios/swift/SectionStyle.swift +133 -0
- package/nitrogen/generated/ios/swift/StyleDisplay.swift +40 -0
- package/nitrogen/generated/ios/swift/Track.swift +20 -73
- package/nitrogen/generated/ios/swift/TrackStyle.swift +86 -22
- package/nitrogen/generated/shared/c++/{FavoritesMatchMode.hpp → ArtworkRendering.hpp} +17 -17
- package/nitrogen/generated/shared/c++/CarPlayPlayingIndicatorLocation.hpp +76 -0
- package/nitrogen/generated/shared/c++/CardImage.hpp +76 -0
- package/nitrogen/generated/shared/c++/GridTile.hpp +80 -0
- package/nitrogen/generated/shared/c++/IOSOptions.hpp +9 -2
- package/nitrogen/generated/shared/c++/ImageShape.hpp +76 -0
- package/nitrogen/generated/shared/c++/NativeBrowserConfiguration.hpp +6 -6
- package/nitrogen/generated/shared/c++/NitroIOSUpdateOptions.hpp +9 -2
- package/nitrogen/generated/shared/c++/PlayerCapabilities.hpp +6 -9
- package/nitrogen/generated/shared/c++/ResolvedTrack.hpp +30 -38
- package/nitrogen/generated/shared/c++/Section.hpp +106 -0
- package/nitrogen/generated/shared/c++/SectionStyle.hpp +126 -0
- package/nitrogen/generated/shared/c++/StyleDisplay.hpp +76 -0
- package/nitrogen/generated/shared/c++/Track.hpp +15 -31
- package/nitrogen/generated/shared/c++/TrackStyle.hpp +73 -34
- package/package.json +7 -2
- package/src/AudioBrowser.ts +1 -0
- package/src/features/browser-config.test.ts +21 -6
- package/src/features/browser-config.ts +11 -8
- package/src/features/browser.test.ts +1 -1
- package/src/features/browser.ts +2 -2
- package/src/features/favorites.ts +13 -10
- package/src/features/hook-wiring.test.ts +63 -15
- package/src/features/playback/controls.ts +4 -2
- package/src/features/playback/progress.ts +2 -1
- package/src/features/playback/rate.ts +8 -1
- package/src/features/playback/state.ts +2 -3
- package/src/features/playback/trackPlaybackTime.ts +1 -1
- package/src/features/player/options.ts +27 -19
- package/src/features/player/setup.test.ts +12 -3
- package/src/features/player/setup.ts +3 -1
- package/src/features/player/validateOptions.ts +2 -0
- package/src/features/queue/activeTrack.ts +14 -3
- package/src/features/queue/queue.ts +11 -4
- package/src/nitro-stub-drift.test.ts +40 -0
- package/src/public-surface.test.ts +40 -0
- package/src/specs/audio-browser.nitro.ts +4 -3
- package/src/style-resolution.test.ts +210 -0
- package/src/types/browser-native.ts +2 -2
- package/src/types/browser-nodes.ts +377 -135
- package/src/types/browser.ts +34 -55
- package/src/utils/LazyNativeEmitter.ts +20 -10
- package/src/utils/NativeUpdatedValue.ts +29 -13
- package/src/utils/getTrackIdentity.ts +20 -0
- package/src/utils/useNativeValueRefreshedBy.ts +38 -0
- package/src/web/NativeAudioBrowser.ts +37 -22
- package/src/web/TrackPlayer/QueueManager.test.ts +29 -0
- package/src/web/TrackPlayer/QueueManager.ts +14 -0
- package/src/web/browser/BrowserManager.ts +176 -95
- package/src/web/browser/FavoriteManager.test.ts +84 -0
- package/src/web/browser/FavoriteManager.ts +28 -23
- package/src/web/browser/assertBrowsePageShape.test.ts +1 -1
- package/src/web/browser/assertBrowsePageShape.ts +5 -3
- package/src/web/browser/classifyTrackNavigation.test.ts +10 -8
- package/src/web/browser/classifyTrackNavigation.ts +9 -9
- package/src/web/browser/parseSearchResponse.test.ts +8 -2
- package/src/web/browser/sections.test.ts +91 -0
- package/src/web/browser/sections.ts +72 -0
- package/src/web/player/NowPlayingManager.ts +4 -3
- package/src/web/util/BrowserPathHelper.test.ts +52 -0
- package/src/web/util/BrowserPathHelper.ts +61 -13
- package/website/guide/android-auto.md +114 -0
- package/website/guide/android-certificates.md +409 -0
- package/website/guide/artwork.md +255 -0
- package/website/guide/audio-output.md +135 -0
- package/website/guide/automotive.md +86 -0
- package/website/guide/basic-usage.md +151 -0
- package/website/guide/battery.md +115 -0
- package/website/guide/browser.md +581 -0
- package/website/guide/carplay.md +620 -0
- package/website/guide/configuration.md +173 -0
- package/website/guide/equalizer.md +231 -0
- package/website/guide/errors.md +310 -0
- package/website/guide/favorites.md +154 -0
- package/website/guide/gate.md +143 -0
- package/website/guide/getting-started.md +46 -0
- package/website/guide/hooks.md +238 -0
- package/website/guide/live-streams.md +125 -0
- package/website/guide/metadata.md +239 -0
- package/website/guide/migrating-from-track-player.md +244 -0
- package/website/guide/native-callback-fetch.md +127 -0
- package/website/guide/network.md +86 -0
- package/website/guide/now-playing.md +175 -0
- package/website/guide/playback.md +328 -0
- package/website/guide/queue.md +300 -0
- package/website/guide/remote-controls.md +256 -0
- package/website/guide/search.md +255 -0
- package/website/guide/sleep-timer.md +268 -0
- package/website/guide/track.md +246 -0
- package/ios/CarPlay/ImageRowItem+CarPlay.swift +0 -19
- package/nitrogen/generated/android/c++/JFavoriteConfig.hpp +0 -58
- package/nitrogen/generated/android/c++/JImageRowItem.hpp +0 -105
- package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.cpp +0 -26
- package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.hpp +0 -71
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageRowItem.kt +0 -68
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_Boolean_FavoriteConfig.kt +0 -53
- package/nitrogen/generated/ios/swift/FavoriteConfig.swift +0 -29
- package/nitrogen/generated/ios/swift/FavoritesMatchMode.swift +0 -40
- package/nitrogen/generated/ios/swift/ImageRowItem.swift +0 -195
- package/nitrogen/generated/ios/swift/Variant_Bool_FavoriteConfig.swift +0 -18
- package/nitrogen/generated/shared/c++/FavoriteConfig.hpp +0 -84
- package/nitrogen/generated/shared/c++/ImageRowItem.hpp +0 -129
package/README.md
CHANGED
|
@@ -63,7 +63,7 @@ import AudioBrowser from 'react-native-audio-browser'
|
|
|
63
63
|
await AudioBrowser.setupPlayer()
|
|
64
64
|
|
|
65
65
|
AudioBrowser.configureBrowser({
|
|
66
|
-
tabs: [{ title: 'Browse',
|
|
66
|
+
tabs: [{ title: 'Browse', path: '/browse' }],
|
|
67
67
|
routes: {
|
|
68
68
|
// Every path under /browse is fetched from your API, on demand.
|
|
69
69
|
'/browse/**': { baseUrl: 'https://api.example.com' }
|
|
@@ -71,15 +71,15 @@ AudioBrowser.configureBrowser({
|
|
|
71
71
|
})
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
-
Each route returns a page of children — a child with a `
|
|
74
|
+
Each route returns a page of children — a child with a `path` is browsable (open it for more), one with a `src` is a playable track (plus optional `artist`, `artwork`, …):
|
|
75
75
|
|
|
76
76
|
```jsonc
|
|
77
77
|
// GET https://api.example.com/browse/jazz →
|
|
78
78
|
{
|
|
79
|
-
"
|
|
79
|
+
"path": "/browse/jazz",
|
|
80
80
|
"title": "Jazz",
|
|
81
81
|
"children": [
|
|
82
|
-
{ "title": "Smooth Floret FM", "
|
|
82
|
+
{ "title": "Smooth Floret FM", "path": "/browse/jazz/floret-fm" }, // path → open for children
|
|
83
83
|
{ "title": "The Stalk 88.5", "src": "https://stream.example.com/stalk.mp3" } // src → play this stream
|
|
84
84
|
]
|
|
85
85
|
}
|
|
@@ -174,6 +174,16 @@ Full guides and the complete [API Reference](https://audiobrowser.dev/api/) live
|
|
|
174
174
|
|
|
175
175
|
The example app in [`apps/example-native`](https://github.com/radio-garden/react-native-audio-browser/tree/main/apps/example-native) browses archive.org's audio collection — in-app, on CarPlay, and on Android Auto — with search, favorites, and the gate.
|
|
176
176
|
|
|
177
|
+
### For coding agents
|
|
178
|
+
|
|
179
|
+
Every page is also served as raw Markdown — append `.md` to any URL, e.g.
|
|
180
|
+
[`audiobrowser.dev/guide/queue.md`](https://audiobrowser.dev/guide/queue.md).
|
|
181
|
+
|
|
182
|
+
- [`/llms.txt`](https://audiobrowser.dev/llms.txt) — an index of every page with a one-line summary, to pick what to read.
|
|
183
|
+
- [`/llms-full.txt`](https://audiobrowser.dev/llms-full.txt) — every guide in one file.
|
|
184
|
+
|
|
185
|
+
The same guide Markdown ships in the package, so it can be read straight off disk without a network fetch: `node_modules/react-native-audio-browser/website/guide/`.
|
|
186
|
+
|
|
177
187
|
## Support
|
|
178
188
|
|
|
179
189
|
Questions or bugs? [Open an issue](https://github.com/radio-garden/react-native-audio-browser/issues). Release notes live in the [changelog](CHANGELOG.md).
|
package/android/build.gradle
CHANGED
|
@@ -158,6 +158,13 @@ repositories {
|
|
|
158
158
|
google()
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
+
// Mockito's inline mock maker needs a Byte Buddy agent in the running JVM. Left to itself it
|
|
162
|
+
// installs one through the JVM attach mechanism, which binds a unix socket under $TMPDIR —
|
|
163
|
+
// denied inside sandboxed shells, and disabled by default on JDK 24+. Resolving the agent as its
|
|
164
|
+
// own configuration lets the test JVM pre-load it with -javaagent, so no attach is needed.
|
|
165
|
+
configurations {
|
|
166
|
+
mockitoAgent
|
|
167
|
+
}
|
|
161
168
|
|
|
162
169
|
dependencies {
|
|
163
170
|
// For < 0.71, this will be from the local maven repo
|
|
@@ -210,14 +217,26 @@ dependencies {
|
|
|
210
217
|
implementation("io.coil-kt.coil3:coil-network-okhttp:3.3.0")
|
|
211
218
|
|
|
212
219
|
// Testing dependencies
|
|
220
|
+
def mockitoVersion = "5.8.0"
|
|
213
221
|
testImplementation 'junit:junit:4.13.2'
|
|
214
|
-
testImplementation
|
|
222
|
+
testImplementation "org.mockito:mockito-core:${mockitoVersion}"
|
|
223
|
+
// Resolved transitively so the agent jar always matches the Byte Buddy that Mockito uses.
|
|
224
|
+
mockitoAgent "org.mockito:mockito-core:${mockitoVersion}"
|
|
215
225
|
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3'
|
|
216
226
|
testImplementation 'org.robolectric:robolectric:4.11.1'
|
|
217
227
|
|
|
218
228
|
api 'com.jakewharton.timber:timber:5.0.1'
|
|
219
229
|
}
|
|
220
230
|
|
|
231
|
+
tasks.withType(Test).configureEach {
|
|
232
|
+
def agentJar = configurations.mockitoAgent.find { it.name.startsWith("byte-buddy-agent") }
|
|
233
|
+
if (agentJar == null) {
|
|
234
|
+
throw new GradleException("No byte-buddy-agent jar in the mockitoAgent configuration; " +
|
|
235
|
+
"Mockito would fall back to runtime self-attach. Check the mockito-core coordinates.")
|
|
236
|
+
}
|
|
237
|
+
jvmArgs "-javaagent:${agentJar}"
|
|
238
|
+
}
|
|
239
|
+
|
|
221
240
|
if (isNewArchitectureEnabled()) {
|
|
222
241
|
react {
|
|
223
242
|
jsRootDir = file("../src/")
|
|
@@ -20,9 +20,11 @@ import com.audiobrowser.browser.CallbackException
|
|
|
20
20
|
import com.audiobrowser.browser.ContentNotFoundException
|
|
21
21
|
import com.audiobrowser.browser.HttpStatusException
|
|
22
22
|
import com.audiobrowser.browser.NetworkException
|
|
23
|
+
import com.audiobrowser.browser.flattenedChildren
|
|
23
24
|
import com.audiobrowser.browser.handleTrackLoad
|
|
24
25
|
import com.audiobrowser.browser.resolveMediaUrl
|
|
25
26
|
import com.audiobrowser.extension.NumberExt.Companion.toSeconds
|
|
27
|
+
import com.audiobrowser.extension.indexOfTappedTrack
|
|
26
28
|
import com.audiobrowser.model.PlayerSetupOptions
|
|
27
29
|
import com.audiobrowser.model.PlayerUpdateOptions
|
|
28
30
|
import com.audiobrowser.player.Player
|
|
@@ -35,6 +37,7 @@ import com.audiobrowser.util.SystemVolumeMonitor
|
|
|
35
37
|
import com.facebook.proguard.annotations.DoNotStrip
|
|
36
38
|
import com.google.common.util.concurrent.ListenableFuture
|
|
37
39
|
import com.margelo.nitro.NitroModules
|
|
40
|
+
import com.margelo.nitro.audiobrowser.ArtworkRequestConfig
|
|
38
41
|
import com.margelo.nitro.audiobrowser.BatteryOptimizationStatus
|
|
39
42
|
import com.margelo.nitro.audiobrowser.BatteryOptimizationStatusChangedEvent
|
|
40
43
|
import com.margelo.nitro.audiobrowser.BatteryWarningPendingChangedEvent
|
|
@@ -50,6 +53,7 @@ import com.margelo.nitro.audiobrowser.HybridAudioBrowserSpec
|
|
|
50
53
|
import com.margelo.nitro.audiobrowser.MediaRequestConfig
|
|
51
54
|
import com.margelo.nitro.audiobrowser.NativeBrowserConfiguration
|
|
52
55
|
import com.margelo.nitro.audiobrowser.NativeGateRequest
|
|
56
|
+
import com.margelo.nitro.audiobrowser.NativeRouteEntry
|
|
53
57
|
import com.margelo.nitro.audiobrowser.NativeSetupPlayerOptions
|
|
54
58
|
import com.margelo.nitro.audiobrowser.NativeUpdateOptions
|
|
55
59
|
import com.margelo.nitro.audiobrowser.NavigationError
|
|
@@ -82,6 +86,7 @@ import com.margelo.nitro.audiobrowser.SleepTimer
|
|
|
82
86
|
import com.margelo.nitro.audiobrowser.TimedMetadata
|
|
83
87
|
import com.margelo.nitro.audiobrowser.Track
|
|
84
88
|
import com.margelo.nitro.audiobrowser.TrackMetadata
|
|
89
|
+
import com.margelo.nitro.audiobrowser.TransformableRequestConfig
|
|
85
90
|
import com.margelo.nitro.core.Promise
|
|
86
91
|
import java.util.concurrent.TimeUnit
|
|
87
92
|
import java.util.concurrent.atomic.AtomicReference
|
|
@@ -121,6 +126,12 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
121
126
|
// Only when still ours: on a reload the replacement may already own the slot.
|
|
122
127
|
carConnectionTarget.compareAndSet(onCarConnectedChanged, null)
|
|
123
128
|
|
|
129
|
+
// The runtime behind the config's JS functions is going away, but anything still holding
|
|
130
|
+
// this instance (an in-flight browse coroutine, the running player) can invoke them after
|
|
131
|
+
// it's gone — each invoke then throws instead of answering, so browse takes its error path
|
|
132
|
+
// rather than its fallback.
|
|
133
|
+
dropStaleJSCallbacks()
|
|
134
|
+
|
|
124
135
|
handler.post {
|
|
125
136
|
connectedService?.let { service ->
|
|
126
137
|
// Identity-guarded: both instances bind to the same singleton Service, so a late dispose
|
|
@@ -129,6 +140,10 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
129
140
|
if (service.player.browser === this) {
|
|
130
141
|
service.player.browser = null
|
|
131
142
|
service.player.forgetBrowserRegistration()
|
|
143
|
+
// The formatter wraps a JS callback from this instance's runtime (installed by our
|
|
144
|
+
// setup(); browser still being ours means no replacement has run setup yet). Without
|
|
145
|
+
// this, every track change until the next setup() throws into the updater's fallback.
|
|
146
|
+
service.player.nowPlaying.formatter = null
|
|
132
147
|
}
|
|
133
148
|
if (service.onBatteryWarningPendingChanged === onBatteryWarningPending) {
|
|
134
149
|
service.onBatteryWarningPendingChanged = null
|
|
@@ -152,6 +167,20 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
152
167
|
super.dispose()
|
|
153
168
|
}
|
|
154
169
|
|
|
170
|
+
/**
|
|
171
|
+
* Demotes the config to data-only (deep strip of every JS function field) and reverts the JS
|
|
172
|
+
* callbacks stored outside the config tree ([resolveGate]; the now-playing formatter is cleared
|
|
173
|
+
* in [dispose]'s service block, identity-guarded). Stale paths then degrade the same way as a
|
|
174
|
+
* config that never had callbacks — static request/browse layers, default error copy, fail-closed
|
|
175
|
+
* gate — instead of throwing into the error path. Mirrors iOS `dropStaleJSCallbacks`, where the
|
|
176
|
+
* same invoke is fatal rather than a throw.
|
|
177
|
+
*/
|
|
178
|
+
private fun dropStaleJSCallbacks() {
|
|
179
|
+
_configuration = _configuration.strippingJSCallbacks()
|
|
180
|
+
browserManager.config = buildConfig()
|
|
181
|
+
resolveGate = defaultResolveGate
|
|
182
|
+
}
|
|
183
|
+
|
|
155
184
|
private val mainScope = MainScope()
|
|
156
185
|
private var navigationJob: Job? = null
|
|
157
186
|
private val handler = Handler(Looper.getMainLooper())
|
|
@@ -175,7 +204,7 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
175
204
|
handleTrackLoad = null,
|
|
176
205
|
androidControllerOfflineError = null,
|
|
177
206
|
carPlayLoadingTitle = null,
|
|
178
|
-
|
|
207
|
+
resolveAlbumPath = null,
|
|
179
208
|
formatNavigationError = null,
|
|
180
209
|
)
|
|
181
210
|
|
|
@@ -220,14 +249,14 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
220
249
|
override var onFormattedNavigationError: (FormattedNavigationError?) -> Unit = {}
|
|
221
250
|
|
|
222
251
|
// MARK: Gate callbacks (native→JS; set from JS, native CALLS them)
|
|
223
|
-
// Default resolver: only reachable
|
|
224
|
-
//
|
|
252
|
+
// Default resolver: only reachable while hasResolver=true but no live runtime has the real
|
|
253
|
+
// `resolveGate` bound — the init window before JS assigns it, or after [dispose] reverts a dead
|
|
254
|
+
// runtime's resolver. It DENIES by default
|
|
225
255
|
// (gated=true) so an active gate never serves content during that window — same fail-closed
|
|
226
256
|
// direction as the resolver-error path in [gateDecision]. The static-gate fast path skips it
|
|
227
257
|
// entirely once a resolver-less gate is set.
|
|
228
|
-
override var resolveGate: (request: NativeGateRequest) -> Promise<Promise<GateDecision>> =
|
|
229
|
-
|
|
230
|
-
}
|
|
258
|
+
override var resolveGate: (request: NativeGateRequest) -> Promise<Promise<GateDecision>> =
|
|
259
|
+
defaultResolveGate
|
|
231
260
|
override var onGate: (event: GateEvent) -> Unit = {}
|
|
232
261
|
|
|
233
262
|
// MARK: Player callbacks
|
|
@@ -373,8 +402,8 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
373
402
|
browserManager.config = buildConfig()
|
|
374
403
|
val tabs = browserManager.queryTabs()
|
|
375
404
|
if (tabs.isNotEmpty()) {
|
|
376
|
-
Timber.d("Using first tab as default path: ${tabs[0].
|
|
377
|
-
tabs[0].
|
|
405
|
+
Timber.d("Using first tab as default path: ${tabs[0].path}")
|
|
406
|
+
tabs[0].path
|
|
378
407
|
} else {
|
|
379
408
|
Timber.d("Using root path as default: /")
|
|
380
409
|
"/"
|
|
@@ -612,26 +641,38 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
612
641
|
}
|
|
613
642
|
|
|
614
643
|
override fun navigateTrack(track: Track) {
|
|
644
|
+
// A disabled track is unavailable — it never plays, whichever surface or
|
|
645
|
+
// stale resume path delivered the selection (Track.disabled; mirrors iOS
|
|
646
|
+
// TrackSelector.select). Refused before any state changes: an inert tap
|
|
647
|
+
// must not clear an unrelated navigation error or cancel an in-flight
|
|
648
|
+
// navigation.
|
|
649
|
+
if (track.disabled == true) {
|
|
650
|
+
Timber.d("Ignoring selection of disabled track: ${track.title}")
|
|
651
|
+
return
|
|
652
|
+
}
|
|
653
|
+
|
|
615
654
|
clearNavigationError()
|
|
616
655
|
|
|
617
656
|
// Cancel previous navigation to avoid race conditions
|
|
618
657
|
navigationJob?.cancel()
|
|
619
658
|
|
|
620
|
-
val
|
|
659
|
+
val path = track.path
|
|
621
660
|
navigationJob =
|
|
622
661
|
mainScope.launch {
|
|
623
662
|
try {
|
|
624
663
|
when {
|
|
625
|
-
// Check if this is a contextual
|
|
626
|
-
|
|
627
|
-
Timber.d("Navigating to contextual track
|
|
664
|
+
// Check if this is a contextual path (playable-only track with queue context)
|
|
665
|
+
path != null && BrowserPathHelper.isContextual(path) -> {
|
|
666
|
+
Timber.d("Navigating to contextual track path: $path")
|
|
628
667
|
|
|
629
|
-
val parentPath = BrowserPathHelper.stripTrackId(
|
|
630
|
-
val trackId = BrowserPathHelper.extractTrackId(
|
|
668
|
+
val parentPath = BrowserPathHelper.stripTrackId(path)
|
|
669
|
+
val trackId = BrowserPathHelper.extractTrackId(path)
|
|
631
670
|
|
|
632
|
-
// Check if queue already came from this parent path - just skip
|
|
671
|
+
// Check if queue already came from this parent path - just skip
|
|
672
|
+
// to the tapped surface (exact path first, identity for
|
|
673
|
+
// index-less paths — see indexOfTappedTrack)
|
|
633
674
|
if (trackId != null && parentPath == player.queueSourcePath) {
|
|
634
|
-
val index = player.tracks.
|
|
675
|
+
val index = player.tracks.indexOfTappedTrack(path, trackId)
|
|
635
676
|
if (index >= 0) {
|
|
636
677
|
Timber.d("Queue already from $parentPath, skipping to index $index")
|
|
637
678
|
handleTrackLoad(
|
|
@@ -649,8 +690,8 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
649
690
|
}
|
|
650
691
|
}
|
|
651
692
|
|
|
652
|
-
// Expand the queue from the contextual
|
|
653
|
-
val expanded = browserManager.
|
|
693
|
+
// Expand the queue from the contextual path
|
|
694
|
+
val expanded = browserManager.expandQueueFromContextualPath(path)
|
|
654
695
|
|
|
655
696
|
if (expanded != null) {
|
|
656
697
|
val (tracks, startIndex) = expanded
|
|
@@ -685,9 +726,9 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
685
726
|
}
|
|
686
727
|
}
|
|
687
728
|
// Navigate to browsable track to show browsing UI
|
|
688
|
-
|
|
689
|
-
Timber.d("Navigating to browsable track: $
|
|
690
|
-
browserManager.navigate(
|
|
729
|
+
path != null -> {
|
|
730
|
+
Timber.d("Navigating to browsable track: $path")
|
|
731
|
+
browserManager.navigate(path)
|
|
691
732
|
}
|
|
692
733
|
// If track is playable (has src), load it into player
|
|
693
734
|
track.src != null -> {
|
|
@@ -702,13 +743,13 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
702
743
|
)
|
|
703
744
|
}
|
|
704
745
|
else -> {
|
|
705
|
-
throw IllegalArgumentException("Track must have either
|
|
746
|
+
throw IllegalArgumentException("Track must have either a 'path' or an 'src' property")
|
|
706
747
|
}
|
|
707
748
|
}
|
|
708
749
|
} catch (e: CancellationException) {
|
|
709
750
|
throw e // Rethrow to properly cancel
|
|
710
751
|
} catch (e: Exception) {
|
|
711
|
-
handleBrowserException(e,
|
|
752
|
+
handleBrowserException(e, path ?: track.src ?: "", "navigating to track: ${track.title}")
|
|
712
753
|
}
|
|
713
754
|
}
|
|
714
755
|
}
|
|
@@ -717,7 +758,10 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
717
758
|
return Promise.async(mainScope) {
|
|
718
759
|
Timber.d("Searching for: $query")
|
|
719
760
|
val searchResults = browserManager.search(query)
|
|
720
|
-
|
|
761
|
+
// Flattened, not `children`: a resolved page carries its rows in
|
|
762
|
+
// `sections` (ADR 0010) and search builds exactly one untitled section,
|
|
763
|
+
// so `children` is always null here and this returned nothing at all.
|
|
764
|
+
searchResults.flattenedChildren?.toTypedArray() ?: emptyArray()
|
|
721
765
|
}
|
|
722
766
|
}
|
|
723
767
|
|
|
@@ -1027,12 +1071,15 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
1027
1071
|
player.setQueue(tracks, startIndex?.toInt() ?: 0, ((startPosition ?: 0.0) * 1000).toLong())
|
|
1028
1072
|
}
|
|
1029
1073
|
|
|
1030
|
-
override fun setActiveTrackFavorited(favorited: Boolean) = runBlockingOnMain {
|
|
1074
|
+
override fun setActiveTrackFavorited(favorited: Boolean): Unit = runBlockingOnMain {
|
|
1075
|
+
// Applied-result is for MediaSession honesty; the JS API stays fire-and-forget.
|
|
1031
1076
|
player.setActiveTrackFavorited(favorited)
|
|
1077
|
+
Unit
|
|
1032
1078
|
}
|
|
1033
1079
|
|
|
1034
|
-
override fun toggleActiveTrackFavorited() = runBlockingOnMain {
|
|
1080
|
+
override fun toggleActiveTrackFavorited(): Unit = runBlockingOnMain {
|
|
1035
1081
|
player.toggleActiveTrackFavorited()
|
|
1082
|
+
Unit
|
|
1036
1083
|
}
|
|
1037
1084
|
|
|
1038
1085
|
override fun getQueue(): Array<Track> = runBlockingOnMain { player.tracks }
|
|
@@ -1494,6 +1541,11 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
1494
1541
|
current.getAndSet(null)?.dispose()
|
|
1495
1542
|
}
|
|
1496
1543
|
|
|
1544
|
+
/** Shared by the [resolveGate] initializer and [dispose], which reverts to it. */
|
|
1545
|
+
private val defaultResolveGate: (NativeGateRequest) -> Promise<Promise<GateDecision>> = {
|
|
1546
|
+
Promise.resolved(Promise.resolved(GateDecision(gated = true, gate = null)))
|
|
1547
|
+
}
|
|
1548
|
+
|
|
1497
1549
|
private fun startCarConnectionObserver(context: Context, handler: Handler) {
|
|
1498
1550
|
// Posted to main: LiveData observation is main-thread only, and the
|
|
1499
1551
|
// single-start guard is then only ever touched from one thread.
|
|
@@ -1510,3 +1562,40 @@ class AudioBrowser : HybridAudioBrowserSpec(), ServiceConnection {
|
|
|
1510
1562
|
}
|
|
1511
1563
|
}
|
|
1512
1564
|
}
|
|
1565
|
+
|
|
1566
|
+
// MARK: Deep JS-callback stripping (used by dispose)
|
|
1567
|
+
// Functions live at every level of the config, not just the top; each type's strip nils its own.
|
|
1568
|
+
|
|
1569
|
+
private fun NativeBrowserConfiguration.strippingJSCallbacks() =
|
|
1570
|
+
copy(
|
|
1571
|
+
requestResolver = null,
|
|
1572
|
+
browseResolver = null,
|
|
1573
|
+
handleTrackLoad = null,
|
|
1574
|
+
resolveAlbumPath = null,
|
|
1575
|
+
formatNavigationError = null,
|
|
1576
|
+
request = request?.strippingJSCallbacks(),
|
|
1577
|
+
browse = browse?.strippingJSCallbacks(),
|
|
1578
|
+
media = media?.strippingJSCallbacks(),
|
|
1579
|
+
artwork = artwork?.strippingJSCallbacks(),
|
|
1580
|
+
nowPlayingArtwork = nowPlayingArtwork?.strippingJSCallbacks(),
|
|
1581
|
+
routes = routes?.map { it.strippingJSCallbacks() }?.toTypedArray(),
|
|
1582
|
+
)
|
|
1583
|
+
|
|
1584
|
+
private fun TransformableRequestConfig.strippingJSCallbacks() =
|
|
1585
|
+
copy(transform = null, transformSync = null)
|
|
1586
|
+
|
|
1587
|
+
private fun MediaRequestConfig.strippingJSCallbacks() =
|
|
1588
|
+
copy(resolve = null, resolveSync = null, transform = null, transformSync = null)
|
|
1589
|
+
|
|
1590
|
+
private fun ArtworkRequestConfig.strippingJSCallbacks() =
|
|
1591
|
+
copy(resolve = null, resolveSync = null, transform = null, transformSync = null)
|
|
1592
|
+
|
|
1593
|
+
private fun NativeRouteEntry.strippingJSCallbacks() =
|
|
1594
|
+
copy(
|
|
1595
|
+
browseCallback = null,
|
|
1596
|
+
browseConfig = browseConfig?.strippingJSCallbacks(),
|
|
1597
|
+
searchCallback = null,
|
|
1598
|
+
searchConfig = searchConfig?.strippingJSCallbacks(),
|
|
1599
|
+
media = media?.strippingJSCallbacks(),
|
|
1600
|
+
artwork = artwork?.strippingJSCallbacks(),
|
|
1601
|
+
)
|