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
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
package com.audiobrowser.browser
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import androidx.media3.common.C
|
|
4
|
+
import androidx.media3.common.MediaItem
|
|
4
5
|
import com.audiobrowser.TestFixtures.resolvedTrack
|
|
6
|
+
import com.audiobrowser.TestFixtures.section
|
|
7
|
+
import com.audiobrowser.TestFixtures.sectionStyle
|
|
5
8
|
import com.audiobrowser.TestFixtures.staticRoute
|
|
6
9
|
import com.audiobrowser.TestFixtures.track
|
|
7
10
|
import com.audiobrowser.util.BrowserPathHelper
|
|
@@ -17,14 +20,14 @@ import org.robolectric.RobolectricTestRunner
|
|
|
17
20
|
/**
|
|
18
21
|
* Navigation and queue-expansion glue.
|
|
19
22
|
*
|
|
20
|
-
* [BrowserManager.
|
|
23
|
+
* [BrowserManager.expandQueueFromContextualPath] is the seam between the page a listener tapped in
|
|
21
24
|
* and the queue that starts playing. Its two halves are covered on their own — the section logic in
|
|
22
25
|
* [SectionScopeTest], the caller's single-track fallback in the player tests — but the wiring
|
|
23
26
|
* between them is what decides whether tapping row 3 of a page resumes the right station, and only
|
|
24
27
|
* these tests exercise it.
|
|
25
28
|
*
|
|
26
29
|
* Routes serve `browseStatic`, the one browse arm that needs neither the JNI bridge nor HTTP.
|
|
27
|
-
* Robolectric is required for `android.net.Uri` (contextual-
|
|
30
|
+
* Robolectric is required for `android.net.Uri` (contextual-path parsing) and
|
|
28
31
|
* `android.util.LruCache` (the content cache).
|
|
29
32
|
*/
|
|
30
33
|
@RunWith(RobolectricTestRunner::class)
|
|
@@ -46,11 +49,20 @@ class BrowserManagerTest {
|
|
|
46
49
|
browserManager.config =
|
|
47
50
|
BrowserConfig(
|
|
48
51
|
routes =
|
|
49
|
-
arrayOf(staticRoute(path, resolvedTrack(
|
|
52
|
+
arrayOf(staticRoute(path, resolvedTrack(path = path, children = arrayOf(*children)))),
|
|
50
53
|
singleTrack = singleTrack,
|
|
51
54
|
)
|
|
52
55
|
}
|
|
53
56
|
|
|
57
|
+
/** Configures a single static route at [path] serving [sections] as its page. */
|
|
58
|
+
private fun serveSections(path: String, vararg sections: com.margelo.nitro.audiobrowser.Section) {
|
|
59
|
+
browserManager.config =
|
|
60
|
+
BrowserConfig(
|
|
61
|
+
routes =
|
|
62
|
+
arrayOf(staticRoute(path, resolvedTrack(path = path, sections = arrayOf(*sections))))
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
54
66
|
private fun contextual(path: String, trackId: String) = BrowserPathHelper.build(path, trackId)
|
|
55
67
|
|
|
56
68
|
@Test
|
|
@@ -100,28 +112,30 @@ class BrowserManagerTest {
|
|
|
100
112
|
|
|
101
113
|
val resolved = browserManager.navigate("/library")
|
|
102
114
|
|
|
103
|
-
assertEquals(listOf("A", "B"), resolved.
|
|
104
|
-
// The tap target: a child's
|
|
115
|
+
assertEquals(listOf("A", "B"), resolved.flattenedChildren?.map { it.title })
|
|
116
|
+
// The tap target: a child's path is rewritten to point back at this page
|
|
117
|
+
// plus its own id and page position (the duplicate-identity tie-breaker).
|
|
105
118
|
assertEquals(
|
|
106
|
-
listOf(
|
|
107
|
-
|
|
119
|
+
listOf(
|
|
120
|
+
BrowserPathHelper.build("/library", "a", 0),
|
|
121
|
+
BrowserPathHelper.build("/library", "b", 1),
|
|
122
|
+
),
|
|
123
|
+
resolved.flattenedChildren?.map { it.path },
|
|
108
124
|
)
|
|
109
125
|
assertEquals("/library", browserManager.getPath())
|
|
110
126
|
}
|
|
111
127
|
|
|
112
|
-
// MARK: -
|
|
128
|
+
// MARK: - expandQueueFromContextualPath
|
|
113
129
|
|
|
114
130
|
@Test
|
|
115
|
-
fun `
|
|
116
|
-
|
|
131
|
+
fun `expandQueueFromContextualPath scopes the queue to the tapped section`() = runBlocking {
|
|
132
|
+
serveSections(
|
|
117
133
|
"/home",
|
|
118
|
-
track(src = "a",
|
|
119
|
-
track(src = "
|
|
120
|
-
track(src = "c", groupTitle = "Popular"),
|
|
121
|
-
track(src = "d", groupTitle = "Popular"),
|
|
134
|
+
section(title = "Recent", children = arrayOf(track(src = "a"), track(src = "b"))),
|
|
135
|
+
section(title = "Popular", children = arrayOf(track(src = "c"), track(src = "d"))),
|
|
122
136
|
)
|
|
123
137
|
|
|
124
|
-
val expanded = browserManager.
|
|
138
|
+
val expanded = browserManager.expandQueueFromContextualPath(contextual("/home", "c"))
|
|
125
139
|
|
|
126
140
|
// "Popular" only — a page aggregating sections must not leak next/previous across them.
|
|
127
141
|
val (queue, index) = requireNotNull(expanded)
|
|
@@ -130,97 +144,262 @@ class BrowserManagerTest {
|
|
|
130
144
|
}
|
|
131
145
|
|
|
132
146
|
@Test
|
|
133
|
-
fun `
|
|
134
|
-
|
|
147
|
+
fun `expandQueueFromContextualPath indexes the tapped track within its section`() = runBlocking {
|
|
148
|
+
serveSections(
|
|
135
149
|
"/home",
|
|
136
|
-
|
|
137
|
-
track(src = "b",
|
|
138
|
-
track(src = "c", groupTitle = "Popular"),
|
|
150
|
+
section(title = "Recent", children = arrayOf(track(src = "a"))),
|
|
151
|
+
section(title = "Popular", children = arrayOf(track(src = "b"), track(src = "c"))),
|
|
139
152
|
)
|
|
140
153
|
|
|
141
154
|
val (queue, index) =
|
|
142
|
-
requireNotNull(browserManager.
|
|
155
|
+
requireNotNull(browserManager.expandQueueFromContextualPath(contextual("/home", "c")))
|
|
143
156
|
|
|
144
157
|
assertEquals(listOf("b", "c"), queue.map { it.src })
|
|
145
158
|
assertEquals(1, index)
|
|
146
159
|
}
|
|
147
160
|
|
|
148
161
|
@Test
|
|
149
|
-
fun `
|
|
162
|
+
fun `expandQueueFromContextualPath pins the tapped copy of a duplicate identity`() = runBlocking {
|
|
163
|
+
// The same src twice in one section (normal for music playlists): the
|
|
164
|
+
// stamped page index selects the tapped copy, so "next" continues from
|
|
165
|
+
// there instead of from the first copy.
|
|
166
|
+
servePage("/playlist", track(src = "a"), track(src = "b"), track(src = "a"), track(src = "c"))
|
|
167
|
+
|
|
168
|
+
val (queue, index) =
|
|
169
|
+
requireNotNull(
|
|
170
|
+
browserManager.expandQueueFromContextualPath(BrowserPathHelper.build("/playlist", "a", 2))
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
assertEquals(listOf("a", "b", "a", "c"), queue.map { it.src })
|
|
174
|
+
assertEquals(2, index)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
@Test
|
|
178
|
+
fun `expandQueueFromContextualPath scopes a cross-section duplicate to the tapped section`() =
|
|
150
179
|
runBlocking {
|
|
151
|
-
// The
|
|
180
|
+
// The same identity in a rail section AND the list section below it:
|
|
181
|
+
// the stamped flat index resolves the tap to the list section.
|
|
182
|
+
serveSections(
|
|
183
|
+
"/home",
|
|
184
|
+
section(
|
|
185
|
+
title = "Row",
|
|
186
|
+
style =
|
|
187
|
+
sectionStyle(
|
|
188
|
+
display = com.margelo.nitro.audiobrowser.StyleDisplay.GRID,
|
|
189
|
+
artworkRendering = null,
|
|
190
|
+
gridWrap = false,
|
|
191
|
+
),
|
|
192
|
+
children = arrayOf(track(src = "dup")),
|
|
193
|
+
),
|
|
194
|
+
section(title = "Stations", children = arrayOf(track(src = "dup"), track(src = "b"))),
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
val (queue, index) =
|
|
198
|
+
requireNotNull(
|
|
199
|
+
browserManager.expandQueueFromContextualPath(BrowserPathHelper.build("/home", "dup", 1))
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
assertEquals(listOf("dup", "b"), queue.map { it.src })
|
|
203
|
+
assertEquals(0, index)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
@Test
|
|
207
|
+
fun `expandQueueFromContextualPath falls back to the first match on a stale index`() =
|
|
208
|
+
runBlocking {
|
|
209
|
+
// The list shifted since the stamp: the child at the index no longer
|
|
210
|
+
// carries the identity, so resolution ignores the index and falls back
|
|
211
|
+
// to the first identity match instead of aborting.
|
|
212
|
+
servePage("/home", track(src = "x"), track(src = "a"), track(src = "b"))
|
|
213
|
+
|
|
214
|
+
val (queue, index) =
|
|
215
|
+
requireNotNull(
|
|
216
|
+
browserManager.expandQueueFromContextualPath(BrowserPathHelper.build("/home", "a", 0))
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
assertEquals(listOf("x", "a", "b"), queue.map { it.src })
|
|
220
|
+
assertEquals(1, index)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
@Test
|
|
224
|
+
fun `expandQueueFromContextualPath returns null when the id has vanished from the page`() =
|
|
225
|
+
runBlocking {
|
|
226
|
+
// The stored path points at a track the page no longer lists — the page changed under a
|
|
152
227
|
// resumed session. Queueing the current list would resume the wrong station, so expansion
|
|
153
228
|
// aborts and the caller falls back to the stored single track.
|
|
154
229
|
servePage("/home", track(src = "a"), track(src = "b"))
|
|
155
230
|
|
|
156
|
-
assertNull(browserManager.
|
|
231
|
+
assertNull(browserManager.expandQueueFromContextualPath(contextual("/home", "gone")))
|
|
157
232
|
}
|
|
158
233
|
|
|
159
234
|
@Test
|
|
160
|
-
fun `
|
|
235
|
+
fun `expandQueueFromContextualPath returns null for a non-contextual path`() = runBlocking {
|
|
161
236
|
servePage("/home", track(src = "a"))
|
|
162
237
|
|
|
163
|
-
assertNull(browserManager.
|
|
238
|
+
assertNull(browserManager.expandQueueFromContextualPath("/home"))
|
|
164
239
|
}
|
|
165
240
|
|
|
166
241
|
@Test
|
|
167
|
-
fun `
|
|
242
|
+
fun `expandQueueFromContextualPath returns null when the page has no children`() = runBlocking {
|
|
168
243
|
browserManager.config =
|
|
169
|
-
BrowserConfig(routes = arrayOf(staticRoute("/home", resolvedTrack(
|
|
244
|
+
BrowserConfig(routes = arrayOf(staticRoute("/home", resolvedTrack(path = "/home"))))
|
|
170
245
|
|
|
171
|
-
assertNull(browserManager.
|
|
246
|
+
assertNull(browserManager.expandQueueFromContextualPath(contextual("/home", "a")))
|
|
172
247
|
}
|
|
173
248
|
|
|
174
249
|
@Test
|
|
175
|
-
fun `
|
|
176
|
-
|
|
250
|
+
fun `expandQueueFromContextualPath scopes a rail section to its own tiles`() = runBlocking {
|
|
251
|
+
serveSections(
|
|
177
252
|
"/home",
|
|
178
|
-
|
|
253
|
+
section(
|
|
179
254
|
title = "Most Played",
|
|
180
|
-
|
|
181
|
-
|
|
255
|
+
style =
|
|
256
|
+
sectionStyle(
|
|
257
|
+
display = com.margelo.nitro.audiobrowser.StyleDisplay.GRID,
|
|
258
|
+
artworkRendering = null,
|
|
259
|
+
gridWrap = false,
|
|
260
|
+
),
|
|
261
|
+
children = arrayOf(track(src = "r1"), track(src = "r2")),
|
|
182
262
|
),
|
|
183
|
-
track(src = "a"),
|
|
263
|
+
section(children = arrayOf(track(src = "a"))),
|
|
184
264
|
)
|
|
185
265
|
|
|
186
266
|
val (queue, index) =
|
|
187
|
-
requireNotNull(browserManager.
|
|
267
|
+
requireNotNull(browserManager.expandQueueFromContextualPath(contextual("/home", "r2")))
|
|
188
268
|
|
|
189
|
-
// A tile tap queues its
|
|
269
|
+
// A tile tap queues its section, not the list rows beside it.
|
|
190
270
|
assertEquals(listOf("r1", "r2"), queue.map { it.src })
|
|
191
271
|
assertEquals(1, index)
|
|
192
272
|
}
|
|
193
273
|
|
|
194
274
|
@Test
|
|
195
|
-
fun `
|
|
196
|
-
|
|
275
|
+
fun `expandQueueFromContextualPath drops unplayable siblings`() = runBlocking {
|
|
276
|
+
serveSections(
|
|
197
277
|
"/home",
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
278
|
+
section(
|
|
279
|
+
title = "Mixed",
|
|
280
|
+
children =
|
|
281
|
+
arrayOf(
|
|
282
|
+
track(src = "a"),
|
|
283
|
+
// A browsable row sitting inside the same section — no src, so not queueable.
|
|
284
|
+
track(src = null).copy(path = "/sub"),
|
|
285
|
+
track(src = "b"),
|
|
286
|
+
),
|
|
287
|
+
),
|
|
202
288
|
)
|
|
203
289
|
|
|
204
290
|
val (queue, index) =
|
|
205
|
-
requireNotNull(browserManager.
|
|
291
|
+
requireNotNull(browserManager.expandQueueFromContextualPath(contextual("/home", "b")))
|
|
206
292
|
|
|
207
293
|
assertEquals(listOf("a", "b"), queue.map { it.src })
|
|
208
294
|
assertEquals(1, index)
|
|
209
295
|
}
|
|
210
296
|
|
|
211
297
|
@Test
|
|
212
|
-
fun `
|
|
298
|
+
fun `navigate stamps the identity, not the src, into id-bearing children's contextual urls`() =
|
|
299
|
+
runBlocking {
|
|
300
|
+
servePage(
|
|
301
|
+
"/home",
|
|
302
|
+
track(id = "stable-a", src = "https://s/a.mp3", title = "A"),
|
|
303
|
+
track(src = "https://s/b.mp3", title = "B"),
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
val resolved = browserManager.navigate("/home")
|
|
307
|
+
|
|
308
|
+
// id when non-blank, else src — Track.identity (ADR 0008).
|
|
309
|
+
assertEquals(
|
|
310
|
+
listOf(
|
|
311
|
+
BrowserPathHelper.build("/home", "stable-a", 0),
|
|
312
|
+
BrowserPathHelper.build("/home", "https://s/b.mp3", 1),
|
|
313
|
+
),
|
|
314
|
+
resolved.flattenedChildren?.map { it.path },
|
|
315
|
+
)
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
@Test
|
|
319
|
+
fun `expandQueueFromContextualPath finds the selected index by identity`() = runBlocking {
|
|
213
320
|
servePage(
|
|
214
321
|
"/home",
|
|
215
|
-
track(
|
|
216
|
-
track(
|
|
217
|
-
|
|
322
|
+
track(id = "stable-a", src = "https://s/a.mp3"),
|
|
323
|
+
track(id = "stable-b", src = "https://s/b.mp3"),
|
|
324
|
+
track(id = "stable-c", src = "https://s/c.mp3"),
|
|
218
325
|
)
|
|
219
326
|
|
|
220
327
|
val (queue, index) =
|
|
221
|
-
requireNotNull(browserManager.
|
|
328
|
+
requireNotNull(browserManager.expandQueueFromContextualPath(contextual("/home", "stable-c")))
|
|
329
|
+
|
|
330
|
+
assertEquals(listOf("stable-a", "stable-b", "stable-c"), queue.map { it.id })
|
|
331
|
+
assertEquals(2, index)
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
@Test
|
|
335
|
+
fun `getCachedTrack resolves an id-valued trackId through the cache`() = runBlocking {
|
|
336
|
+
servePage("/home", track(id = "stable-b", src = "https://s/b.mp3", title = "B"))
|
|
337
|
+
browserManager.navigate("/home")
|
|
338
|
+
|
|
339
|
+
// A contextual mediaId whose __trackId is the identity (the id), with a parent path that was
|
|
340
|
+
// never cached directly — the extract-then-lookup path must find it via the id key.
|
|
341
|
+
val mediaId = contextual("/elsewhere", "stable-b")
|
|
342
|
+
|
|
343
|
+
assertEquals("B", browserManager.getCachedTrack(mediaId)?.title)
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
@Test
|
|
347
|
+
fun `expandQueueFromContextualPath honours singleTrack`() = runBlocking {
|
|
348
|
+
servePage("/home", track(src = "a"), track(src = "b"), singleTrack = true)
|
|
349
|
+
|
|
350
|
+
val (queue, index) =
|
|
351
|
+
requireNotNull(browserManager.expandQueueFromContextualPath(contextual("/home", "b")))
|
|
222
352
|
|
|
223
353
|
assertEquals(listOf("b"), queue.map { it.src })
|
|
224
354
|
assertEquals(0, index)
|
|
225
355
|
}
|
|
356
|
+
|
|
357
|
+
// --- Track.disabled: queue expansion excludes unavailable tracks ---
|
|
358
|
+
|
|
359
|
+
@Test
|
|
360
|
+
fun `expandQueueFromContextualPath excludes disabled tracks`() = runBlocking {
|
|
361
|
+
servePage(
|
|
362
|
+
"/home",
|
|
363
|
+
track(src = "a"),
|
|
364
|
+
track(src = "unavailable", disabled = true),
|
|
365
|
+
track(src = "b"),
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
val (queue, index) =
|
|
369
|
+
requireNotNull(browserManager.expandQueueFromContextualPath(contextual("/home", "b")))
|
|
370
|
+
|
|
371
|
+
assertEquals(listOf("a", "b"), queue.map { it.src })
|
|
372
|
+
assertEquals(1, index)
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
@Test
|
|
376
|
+
fun `expandQueueFromContextualPath aborts when the tapped track is disabled`() = runBlocking {
|
|
377
|
+
// A disabled track never plays: with the tapped identity excluded from the
|
|
378
|
+
// playable list, expansion aborts, and every caller's fallback refuses the
|
|
379
|
+
// disabled track itself — navigateTrack's guard on tap,
|
|
380
|
+
// onPlaybackResumption's refusal on resume.
|
|
381
|
+
servePage("/home", track(src = "a"), track(src = "unavailable", disabled = true))
|
|
382
|
+
|
|
383
|
+
assertNull(browserManager.expandQueueFromContextualPath(contextual("/home", "unavailable")))
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
@Test
|
|
387
|
+
fun `resolveMediaItemsForPlayback refuses a disabled track on the legacy INDEX_UNSET path`() =
|
|
388
|
+
runBlocking {
|
|
389
|
+
// Android Auto and Assistant request playback through Media3's legacy
|
|
390
|
+
// path, which passes C.INDEX_UNSET ("the default item") — the refusal
|
|
391
|
+
// must cover it, or a stale browse row for a now-disabled track plays.
|
|
392
|
+
servePage("/home", track(src = "unavailable", disabled = true))
|
|
393
|
+
browserManager.resolve("/home")
|
|
394
|
+
|
|
395
|
+
val item = MediaItem.Builder().setMediaId("unavailable").build()
|
|
396
|
+
|
|
397
|
+
try {
|
|
398
|
+
browserManager.resolveMediaItemsForPlayback(listOf(item), C.INDEX_UNSET, 0)
|
|
399
|
+
fail("Expected refusal of a disabled track")
|
|
400
|
+
} catch (expected: IllegalStateException) {
|
|
401
|
+
// Refused by failing the future: Media3 surfaces an error to the
|
|
402
|
+
// controller and live playback stays untouched.
|
|
403
|
+
}
|
|
404
|
+
}
|
|
226
405
|
}
|
|
@@ -91,6 +91,44 @@ class BrowserUrlResolutionTest {
|
|
|
91
91
|
assertEquals("https://api.example.com/artwork/abc", source?.uri)
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
@Test
|
|
95
|
+
fun `resolveArtworkUrl leaves the id token literal for a track without an id`() = runTest {
|
|
96
|
+
bm.config =
|
|
97
|
+
BrowserConfig(
|
|
98
|
+
request = transformableConfig(baseUrl = "https://api.example.com"),
|
|
99
|
+
artwork = artworkConfig(path = "/artwork/{id}"),
|
|
100
|
+
)
|
|
101
|
+
// The config still runs (no blanket skip); the token stays literal so the resulting request
|
|
102
|
+
// 404s with a self-describing URL.
|
|
103
|
+
val source = bm.resolveArtworkUrl(track(artwork = null, id = null))
|
|
104
|
+
assertEquals("https://api.example.com/artwork/{id}", source?.uri)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
@Test
|
|
108
|
+
fun `resolveArtworkUrl treats a blank id like a missing one`() = runTest {
|
|
109
|
+
bm.config =
|
|
110
|
+
BrowserConfig(
|
|
111
|
+
request = transformableConfig(baseUrl = "https://api.example.com"),
|
|
112
|
+
artwork = artworkConfig(path = "/artwork/{id}"),
|
|
113
|
+
)
|
|
114
|
+
val source = bm.resolveArtworkUrl(track(artwork = null, id = ""))
|
|
115
|
+
assertEquals("https://api.example.com/artwork/{id}", source?.uri)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
@Test
|
|
119
|
+
fun `resolveArtworkUrl leaves the id token literal in header values without an id`() = runTest {
|
|
120
|
+
bm.config =
|
|
121
|
+
BrowserConfig(
|
|
122
|
+
request = transformableConfig(baseUrl = "https://api.example.com"),
|
|
123
|
+
artwork = artworkConfig(path = "/artwork", headers = mapOf("x-track" to "{id}")),
|
|
124
|
+
)
|
|
125
|
+
val source = bm.resolveArtworkUrl(track(artwork = null, id = null))
|
|
126
|
+
assertEquals("{id}", source?.headers?.get("x-track"))
|
|
127
|
+
|
|
128
|
+
val substituted = bm.resolveArtworkUrl(track(artwork = null, id = "abc"))
|
|
129
|
+
assertEquals("abc", substituted?.headers?.get("x-track"))
|
|
130
|
+
}
|
|
131
|
+
|
|
94
132
|
@Test
|
|
95
133
|
fun `resolveArtworkUrl applies image query params from the image context`() = runTest {
|
|
96
134
|
bm.config =
|