react-native-audio-browser 0.2.0-next.2 → 0.2.0-next.21
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 +35 -21
- package/android/build.gradle +35 -12
- package/android/gradle.properties +2 -2
- package/android/src/main/AndroidManifest.xml +3 -1
- package/android/src/main/java/com/audiobrowser/AudioBrowser.kt +389 -164
- package/android/src/main/java/com/audiobrowser/AudioBrowserLifecycleModule.kt +38 -0
- package/android/src/main/java/com/audiobrowser/AudioBrowserPackage.kt +18 -2
- package/android/src/main/java/com/audiobrowser/ServiceBinding.kt +48 -0
- package/android/src/main/java/com/audiobrowser/browser/BrowserManager.kt +315 -213
- package/android/src/main/java/com/audiobrowser/browser/BrowserUrlResolution.kt +24 -5
- package/android/src/main/java/com/audiobrowser/browser/InertStyleDiagnostic.kt +267 -0
- package/android/src/main/java/com/audiobrowser/browser/JsonModels.kt +97 -58
- package/android/src/main/java/com/audiobrowser/browser/SectionScope.kt +70 -29
- package/android/src/main/java/com/audiobrowser/browser/StyleResolver.kt +60 -0
- package/android/src/main/java/com/audiobrowser/extension/ResolvedTrackExt.kt +20 -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/http/HttpClient.kt +20 -3
- package/android/src/main/java/com/audiobrowser/model/IcyTitle.kt +24 -0
- package/android/src/main/java/com/audiobrowser/model/PlaybackMetadata.kt +10 -6
- package/android/src/main/java/com/audiobrowser/model/PlayerUpdateOptions.kt +12 -12
- package/android/src/main/java/com/audiobrowser/player/CapabilityControls.kt +111 -58
- package/android/src/main/java/com/audiobrowser/player/CrossOriginHeaderStripper.kt +77 -0
- package/android/src/main/java/com/audiobrowser/player/MediaFactory.kt +28 -10
- package/android/src/main/java/com/audiobrowser/player/MediaSessionCallback.kt +509 -230
- package/android/src/main/java/com/audiobrowser/player/MediaSessionCommandManager.kt +218 -252
- package/android/src/main/java/com/audiobrowser/player/NowPlayingUpdater.kt +21 -25
- package/android/src/main/java/com/audiobrowser/player/PlaybackStateStore.kt +113 -78
- package/android/src/main/java/com/audiobrowser/player/Player.kt +81 -38
- package/android/src/main/java/com/audiobrowser/player/PlayerCapabilitiesExt.kt +2 -15
- package/android/src/main/java/com/audiobrowser/player/PlayerListener.kt +1 -1
- package/android/src/main/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicy.kt +2 -1
- package/android/src/main/java/com/audiobrowser/player/ShuffleOrderLedBy.kt +30 -0
- package/android/src/main/java/com/audiobrowser/tls/AiaCertChaser.kt +67 -11
- package/android/src/main/java/com/audiobrowser/tls/AiaChasingExtendedTrustManager.kt +168 -0
- package/android/src/main/java/com/audiobrowser/tls/AiaChasingTrustManager.kt +58 -14
- package/android/src/main/java/com/audiobrowser/tls/AiaTls.kt +35 -7
- package/android/src/main/java/com/audiobrowser/tls/CachingCertificateFetcher.kt +278 -59
- package/android/src/main/java/com/audiobrowser/util/ArtworkVariant.kt +7 -9
- package/android/src/main/java/com/audiobrowser/util/BrowserPathHelper.kt +56 -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 +56 -52
- package/android/src/main/res/values/strings.xml +25 -5
- package/android/src/test/java/com/audiobrowser/ServiceBindingTest.kt +87 -0
- package/android/src/test/java/com/audiobrowser/TestFixtures.kt +119 -33
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerFavoritesTest.kt +153 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerLayerResolutionTest.kt +15 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerTest.kt +346 -8
- 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 +3 -2
- package/android/src/test/java/com/audiobrowser/browser/JsonStyleTest.kt +147 -0
- package/android/src/test/java/com/audiobrowser/browser/SectionScopeTest.kt +128 -55
- 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/model/IcyTitleTest.kt +49 -0
- package/android/src/test/java/com/audiobrowser/player/BrowseTilesTest.kt +385 -0
- package/android/src/test/java/com/audiobrowser/player/CapabilityControlsTest.kt +101 -58
- package/android/src/test/java/com/audiobrowser/player/CrossOriginHeaderStripperTest.kt +94 -0
- package/android/src/test/java/com/audiobrowser/player/MediaSessionSlotMappingTest.kt +45 -0
- package/android/src/test/java/com/audiobrowser/player/NowPlayingUpdaterTest.kt +42 -2
- package/android/src/test/java/com/audiobrowser/player/PlaybackErrorClassifierTest.kt +3 -4
- package/android/src/test/java/com/audiobrowser/player/PlaybackStateStoreTrackJsonTest.kt +55 -0
- package/android/src/test/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicyTest.kt +3 -3
- package/android/src/test/java/com/audiobrowser/player/ShuffleOrderLedByTest.kt +79 -0
- package/android/src/test/java/com/audiobrowser/tls/AiaCertChaserTest.kt +197 -7
- package/android/src/test/java/com/audiobrowser/tls/AiaChasingTrustManagerTest.kt +325 -4
- package/android/src/test/java/com/audiobrowser/tls/CachingCertificateFetcherCallSiteTest.kt +322 -0
- package/android/src/test/java/com/audiobrowser/tls/CachingCertificateFetcherTest.kt +83 -0
- package/android/src/test/java/com/audiobrowser/util/BrowserPathHelperTest.kt +41 -16
- package/android/src/test/java/com/audiobrowser/util/MediaExtrasBuilderTest.kt +162 -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 +230 -205
- package/ios/Browser/BrowserPathHelper.swift +44 -44
- package/ios/Browser/InertStyleDiagnostic.swift +279 -0
- package/ios/Browser/JsonModels.swift +264 -106
- package/ios/Browser/SearchDrillIn.swift +7 -7
- 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 +42 -20
- package/ios/CarPlay/CarPlayListItemFactory.swift +289 -84
- package/ios/CarPlay/CarPlayNowPlayingManager.swift +15 -12
- package/ios/CarPlay/RNABMediaAddHandler.swift +6 -6
- package/ios/CarPlay/RNABMediaAffinityHandler.swift +2 -2
- package/ios/CarPlay/RNABMediaIntentHandler.swift +16 -16
- package/ios/Extension/Capability+RemoteCommand.swift +1 -1
- package/ios/Extension/PlayerCapabilities+Favorite.swift +1 -15
- package/ios/Extension/ResolvedTrack+Copying.swift +13 -15
- package/ios/Extension/Section+Copying.swift +29 -0
- package/ios/Extension/String+IcyCharset.swift +21 -0
- package/ios/Extension/TimedMetadata+AVFoundation.swift +6 -4
- package/ios/Extension/Track+Copying.swift +8 -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 +253 -100
- package/ios/Model/NitroTypeStubs.swift +125 -23
- package/ios/Model/PlayerUpdateOptions.swift +7 -0
- package/ios/Model/RemoteCommand.swift +18 -0
- package/ios/Model/TrackPlayerError.swift +2 -2
- package/ios/Option/SessionCategories.swift +3 -2
- package/ios/Player/MediaIntentCriteria.swift +17 -9
- package/ios/Player/MediaLoader.swift +33 -9
- package/ios/Player/NowPlayingUpdater.swift +54 -6
- package/ios/Player/PlaybackCoordinator.swift +13 -6
- package/ios/Player/PlaybackErrorHandler.swift +4 -4
- package/ios/Player/PlaybackTimer.swift +8 -2
- package/ios/Player/QueueManager.swift +46 -13
- package/ios/Player/RetryManager.swift +80 -18
- package/ios/Player/SeekCompletionHandler.swift +3 -1
- package/ios/Player/ShuffleOrder.swift +33 -0
- package/ios/Player/SleepTimerHandling.swift +13 -0
- package/ios/RemoteCommand/RemoteCommandCallbacks.swift +47 -0
- package/ios/RemoteCommand/RemoteCommandController.swift +62 -24
- 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/LRUCacheTests.swift +111 -0
- package/ios/Tests/LoadSeekCoordinatorTests.swift +3 -1
- package/ios/Tests/MediaIntentCriteriaTests.swift +2 -2
- package/ios/Tests/PlaybackCoordinatorTests.swift +1 -1
- package/ios/Tests/PlaybackErrorHandlerTests.swift +3 -1
- package/ios/Tests/PlaybackStateStoreTests.swift +4 -3
- package/ios/Tests/PlayerTimeObserverTests.swift +37 -0
- package/ios/Tests/QueueManagerTests.swift +122 -10
- package/ios/Tests/RemoteCommandControllerTests.swift +172 -0
- package/ios/Tests/RemoteCommandTests.swift +67 -0
- package/ios/Tests/ResolvedTrackCopyingTests.swift +39 -35
- package/ios/Tests/RetryManagerTests.swift +89 -0
- 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 +8 -1
- package/ios/Tests/TabBarEntriesTests.swift +19 -19
- package/ios/Tests/TimedMetadataAVFoundationTests.swift +42 -0
- 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 +63 -35
- package/ios/TrackPlayerCallbacks.swift +5 -38
- package/ios/TrackSelector.swift +45 -30
- package/ios/Util/ArtworkImageFetcher.swift +16 -1
- package/ios/Util/LRUCache.swift +4 -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 +8 -8
- package/lib/commonjs/AudioBrowser.js.map +1 -1
- package/lib/commonjs/CLAUDE.md +52 -0
- package/lib/commonjs/features/browser-config.js +12 -8
- package/lib/commonjs/features/browser-config.js.map +1 -1
- package/lib/commonjs/features/browser.js +11 -3
- package/lib/commonjs/features/browser.js.map +1 -1
- package/lib/commonjs/features/carConnection.js +1 -1
- package/lib/commonjs/features/equalizer.js +1 -1
- package/lib/commonjs/features/errors.js +3 -3
- package/lib/commonjs/features/favorites.js +14 -11
- package/lib/commonjs/features/favorites.js.map +1 -1
- package/lib/commonjs/features/gate.js +16 -1
- package/lib/commonjs/features/gate.js.map +1 -1
- package/lib/commonjs/features/metadata.js +20 -3
- package/lib/commonjs/features/metadata.js.map +1 -1
- package/lib/commonjs/features/network.js +1 -1
- package/lib/commonjs/features/nowPlaying.js +1 -1
- package/lib/commonjs/features/output.js +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/playWhenReady.js +1 -1
- package/lib/commonjs/features/playback/playing.js +1 -1
- package/lib/commonjs/features/playback/progress.js +3 -2
- 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 +3 -4
- package/lib/commonjs/features/playback/state.js.map +1 -1
- package/lib/commonjs/features/playback/trackPlaybackTime.js +0 -6
- package/lib/commonjs/features/playback/trackPlaybackTime.js.map +1 -1
- package/lib/commonjs/features/playback/volume.js +1 -1
- package/lib/commonjs/features/player/options.js +48 -34
- package/lib/commonjs/features/player/options.js.map +1 -1
- package/lib/commonjs/features/player/setup.js +18 -9
- package/lib/commonjs/features/player/setup.js.map +1 -1
- package/lib/commonjs/features/player/validateOptions.js +23 -0
- package/lib/commonjs/features/player/validateOptions.js.map +1 -0
- package/lib/commonjs/features/queue/activeTrack.js +15 -4
- package/lib/commonjs/features/queue/activeTrack.js.map +1 -1
- package/lib/commonjs/features/queue/queue.js +13 -6
- package/lib/commonjs/features/queue/queue.js.map +1 -1
- package/lib/commonjs/features/queue/repeatMode.js +1 -1
- package/lib/commonjs/features/queue/shuffle.js +1 -1
- package/lib/commonjs/features/remoteControls.js +13 -92
- package/lib/commonjs/features/remoteControls.js.map +1 -1
- package/lib/commonjs/features/sleepTimer.js +13 -1
- package/lib/commonjs/features/sleepTimer.js.map +1 -1
- package/lib/commonjs/test-utils/reactNativeStub.js +65 -0
- package/lib/commonjs/test-utils/reactNativeStub.js.map +1 -0
- package/lib/commonjs/utils/LazyNativeEmitter.js +28 -14
- 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 +200 -75
- package/lib/commonjs/web/NativeAudioBrowser.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/LoadAttempt.js +37 -0
- package/lib/commonjs/web/TrackPlayer/LoadAttempt.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js +18 -2
- package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/Player.js +254 -39
- package/lib/commonjs/web/TrackPlayer/Player.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/TrackPlayer/QueuePlayer.js +33 -12
- package/lib/commonjs/web/TrackPlayer/QueuePlayer.js.map +1 -1
- package/lib/commonjs/web/browser/BrowserManager.js +175 -100
- 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/SearchManager.js +18 -23
- package/lib/commonjs/web/browser/SearchManager.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/http/RequestConfigBuilder.js +110 -27
- package/lib/commonjs/web/http/RequestConfigBuilder.js.map +1 -1
- package/lib/commonjs/web/http/followMediaRedirect.js +219 -0
- package/lib/commonjs/web/http/followMediaRedirect.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 +2 -1
- package/lib/module/AudioBrowser.js.map +1 -1
- package/lib/module/CLAUDE.md +52 -0
- package/lib/module/features/browser-config.js +12 -8
- package/lib/module/features/browser-config.js.map +1 -1
- package/lib/module/features/browser.js +11 -3
- package/lib/module/features/browser.js.map +1 -1
- package/lib/module/features/carConnection.js +1 -1
- package/lib/module/features/equalizer.js +1 -1
- package/lib/module/features/errors.js +3 -3
- package/lib/module/features/favorites.js +14 -11
- package/lib/module/features/favorites.js.map +1 -1
- package/lib/module/features/gate.js +16 -1
- package/lib/module/features/gate.js.map +1 -1
- package/lib/module/features/metadata.js +20 -3
- package/lib/module/features/metadata.js.map +1 -1
- package/lib/module/features/network.js +1 -1
- package/lib/module/features/nowPlaying.js +1 -1
- package/lib/module/features/output.js +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/playWhenReady.js +1 -1
- package/lib/module/features/playback/playing.js +1 -1
- package/lib/module/features/playback/progress.js +3 -2
- 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 +3 -4
- package/lib/module/features/playback/state.js.map +1 -1
- package/lib/module/features/playback/trackPlaybackTime.js +0 -5
- package/lib/module/features/playback/trackPlaybackTime.js.map +1 -1
- package/lib/module/features/playback/volume.js +1 -1
- package/lib/module/features/player/options.js +47 -32
- package/lib/module/features/player/options.js.map +1 -1
- package/lib/module/features/player/setup.js +17 -8
- package/lib/module/features/player/setup.js.map +1 -1
- package/lib/module/features/player/validateOptions.js +19 -0
- package/lib/module/features/player/validateOptions.js.map +1 -0
- package/lib/module/features/queue/activeTrack.js +15 -4
- package/lib/module/features/queue/activeTrack.js.map +1 -1
- package/lib/module/features/queue/queue.js +13 -6
- package/lib/module/features/queue/queue.js.map +1 -1
- package/lib/module/features/queue/repeatMode.js +1 -1
- package/lib/module/features/queue/shuffle.js +1 -1
- package/lib/module/features/remoteControls.js +13 -92
- package/lib/module/features/remoteControls.js.map +1 -1
- package/lib/module/features/sleepTimer.js +13 -1
- package/lib/module/features/sleepTimer.js.map +1 -1
- package/lib/module/test-utils/reactNativeStub.js +58 -0
- package/lib/module/test-utils/reactNativeStub.js.map +1 -0
- package/lib/module/utils/LazyNativeEmitter.js +28 -14
- 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 +200 -75
- package/lib/module/web/NativeAudioBrowser.js.map +1 -1
- package/lib/module/web/TrackPlayer/LoadAttempt.js +32 -0
- package/lib/module/web/TrackPlayer/LoadAttempt.js.map +1 -0
- package/lib/module/web/TrackPlayer/PlaybackStateMachine.js +18 -2
- package/lib/module/web/TrackPlayer/PlaybackStateMachine.js.map +1 -1
- package/lib/module/web/TrackPlayer/Player.js +254 -39
- package/lib/module/web/TrackPlayer/Player.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/TrackPlayer/QueuePlayer.js +33 -12
- package/lib/module/web/TrackPlayer/QueuePlayer.js.map +1 -1
- package/lib/module/web/browser/BrowserManager.js +175 -100
- 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/SearchManager.js +18 -23
- package/lib/module/web/browser/SearchManager.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/http/RequestConfigBuilder.js +110 -27
- package/lib/module/web/http/RequestConfigBuilder.js.map +1 -1
- package/lib/module/web/http/followMediaRedirect.js +215 -0
- package/lib/module/web/http/followMediaRedirect.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/package.json +1 -0
- package/lib/typescript/src/AudioBrowser.d.ts +1 -1
- 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 +10 -2
- package/lib/typescript/src/features/browser.d.ts.map +1 -1
- package/lib/typescript/src/features/carConnection.d.ts +1 -1
- package/lib/typescript/src/features/equalizer.d.ts +1 -1
- package/lib/typescript/src/features/errors.d.ts +3 -3
- package/lib/typescript/src/features/favorites.d.ts +14 -11
- package/lib/typescript/src/features/favorites.d.ts.map +1 -1
- package/lib/typescript/src/features/gate.d.ts +18 -2
- package/lib/typescript/src/features/gate.d.ts.map +1 -1
- package/lib/typescript/src/features/metadata.d.ts +20 -3
- package/lib/typescript/src/features/metadata.d.ts.map +1 -1
- package/lib/typescript/src/features/network.d.ts +1 -1
- package/lib/typescript/src/features/nowPlaying.d.ts +1 -1
- package/lib/typescript/src/features/output.d.ts +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/playWhenReady.d.ts +1 -1
- package/lib/typescript/src/features/playback/playing.d.ts +1 -1
- package/lib/typescript/src/features/playback/progress.d.ts +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 +3 -4
- 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/playback/volume.d.ts +1 -1
- package/lib/typescript/src/features/player/options.d.ts +108 -56
- package/lib/typescript/src/features/player/options.d.ts.map +1 -1
- package/lib/typescript/src/features/player/setup.d.ts +14 -4
- package/lib/typescript/src/features/player/setup.d.ts.map +1 -1
- package/lib/typescript/src/features/player/validateOptions.d.ts +2 -0
- package/lib/typescript/src/features/player/validateOptions.d.ts.map +1 -0
- package/lib/typescript/src/features/queue/activeTrack.d.ts +9 -2
- package/lib/typescript/src/features/queue/activeTrack.d.ts.map +1 -1
- package/lib/typescript/src/features/queue/queue.d.ts +7 -4
- package/lib/typescript/src/features/queue/queue.d.ts.map +1 -1
- package/lib/typescript/src/features/queue/repeatMode.d.ts +1 -1
- package/lib/typescript/src/features/queue/shuffle.d.ts +1 -1
- package/lib/typescript/src/features/remoteControls.d.ts +23 -22
- package/lib/typescript/src/features/remoteControls.d.ts.map +1 -1
- package/lib/typescript/src/features/sleepTimer.d.ts +1 -1
- package/lib/typescript/src/features/sleepTimer.d.ts.map +1 -1
- package/lib/typescript/src/test-utils/reactNativeStub.d.ts +36 -0
- package/lib/typescript/src/test-utils/reactNativeStub.d.ts.map +1 -0
- package/lib/typescript/src/types/browser-native.d.ts +3 -2
- package/lib/typescript/src/types/browser-native.d.ts.map +1 -1
- package/lib/typescript/src/types/browser-nodes.d.ts +380 -126
- package/lib/typescript/src/types/browser-nodes.d.ts.map +1 -1
- package/lib/typescript/src/types/browser.d.ts +82 -57
- package/lib/typescript/src/types/browser.d.ts.map +1 -1
- package/lib/typescript/src/utils/LazyNativeEmitter.d.ts +19 -16
- 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 +1 -2
- package/nitrogen/generated/android/AudioBrowserOnLoad.cpp +2 -0
- package/nitrogen/generated/android/c++/JAndroidOptions.hpp +10 -10
- 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__string__.hpp +102 -0
- 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 +7 -10
- 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 +45 -25
- package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.hpp +1 -1
- 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 +36 -11
- package/nitrogen/generated/android/c++/JNativeRouteEntry.hpp +14 -2
- package/nitrogen/generated/android/c++/JNativeSetupPlayerOptions.hpp +15 -12
- package/nitrogen/generated/android/c++/JNativeUpdateOptions.hpp +7 -10
- package/nitrogen/generated/android/c++/JNitroAndroidUpdateOptions.hpp +10 -10
- package/nitrogen/generated/android/c++/JNitroIOSUpdateOptions.hpp +9 -3
- package/nitrogen/generated/android/c++/JOptions.hpp +7 -10
- package/nitrogen/generated/android/c++/JPlaybackActiveTrackChangedEvent.hpp +8 -3
- package/nitrogen/generated/android/c++/JPlayerCapabilities.hpp +5 -11
- package/nitrogen/generated/android/c++/{JNotificationButton.hpp → JRemoteButton.hpp} +19 -19
- package/nitrogen/generated/android/c++/JRemoteButtonLayout.hpp +86 -0
- package/nitrogen/generated/android/c++/JResolvedTrack.hpp +57 -49
- package/nitrogen/generated/android/c++/JSection.hpp +116 -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 +25 -46
- package/nitrogen/generated/android/c++/JTrackLoadEvent.hpp +8 -2
- package/nitrogen/generated/android/c++/JTrackStyle.hpp +46 -18
- package/nitrogen/generated/android/c++/JVariant_NullType_RemoteButtonLayout.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_RemoteButtonLayout.hpp +75 -0
- package/nitrogen/generated/android/c++/JVariant_ResolvedTrack_BrowseError_Promise_BrowseResult_.hpp +16 -4
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidOptions.kt +3 -3
- 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/Func_std__shared_ptr_Promise_std__string__.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/GridTile.kt +24 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/HybridAudioBrowserSpec.kt +1 -1
- 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 +8 -5
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroAndroidUpdateOptions.kt +3 -3
- 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/{NotificationButton.kt → RemoteButton.kt} +3 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteButtonLayout.kt +44 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ResolvedTrack.kt +12 -15
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{FavoriteConfig.kt → Section.kt} +15 -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 -12
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackStyle.kt +35 -5
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Variant_NullType_NotificationButtonLayout.kt → Variant_NullType_RemoteButtonLayout.kt} +9 -9
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.cpp +9 -0
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.hpp +244 -133
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Umbrella.hpp +31 -16
- package/nitrogen/generated/ios/c++/HybridAudioBrowserSpecSwift.hpp +33 -18
- package/nitrogen/generated/ios/swift/AndroidOptions.swift +12 -12
- 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/Func_std__shared_ptr_Promise_std__string__.swift +54 -0
- package/nitrogen/generated/ios/swift/GridTile.swift +44 -0
- package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec.swift +1 -1
- package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec_cxx.swift +2 -2
- 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 +52 -5
- package/nitrogen/generated/ios/swift/NitroAndroidUpdateOptions.swift +12 -12
- package/nitrogen/generated/ios/swift/NitroIOSUpdateOptions.swift +12 -1
- package/nitrogen/generated/ios/swift/PlayerCapabilities.swift +8 -27
- package/nitrogen/generated/ios/swift/{NotificationButton.swift → RemoteButton.swift} +6 -6
- package/nitrogen/generated/ios/swift/RemoteButtonLayout.swift +57 -0
- package/nitrogen/generated/ios/swift/ResolvedTrack.swift +62 -73
- package/nitrogen/generated/ios/swift/Section.swift +82 -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 +28 -63
- package/nitrogen/generated/ios/swift/TrackStyle.swift +86 -22
- package/nitrogen/generated/ios/swift/{Variant_NullType_NotificationButtonLayout.swift → Variant_NullType_RemoteButtonLayout.swift} +3 -3
- package/nitrogen/generated/shared/c++/AndroidOptions.hpp +8 -8
- 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++/HybridAudioBrowserSpec.cpp +1 -1
- package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.hpp +1 -1
- 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 +10 -6
- package/nitrogen/generated/shared/c++/NitroAndroidUpdateOptions.hpp +8 -8
- package/nitrogen/generated/shared/c++/NitroIOSUpdateOptions.hpp +9 -2
- package/nitrogen/generated/shared/c++/PlayerCapabilities.hpp +6 -9
- package/nitrogen/generated/shared/c++/{NotificationButton.hpp → RemoteButton.hpp} +19 -19
- package/nitrogen/generated/shared/c++/RemoteButtonLayout.hpp +94 -0
- package/nitrogen/generated/shared/c++/ResolvedTrack.hpp +33 -37
- package/nitrogen/generated/shared/c++/Section.hpp +102 -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 +18 -30
- package/nitrogen/generated/shared/c++/TrackStyle.hpp +73 -34
- package/package.json +24 -11
- package/src/AudioBrowser.ts +2 -1
- package/src/CLAUDE.md +52 -0
- package/src/features/battery.test.ts +79 -0
- package/src/features/browser-config.test.ts +21 -6
- package/src/features/browser-config.ts +12 -8
- package/src/features/browser.test.ts +1 -1
- package/src/features/browser.ts +11 -3
- package/src/features/carConnection.ts +1 -1
- package/src/features/equalizer.ts +1 -1
- package/src/features/errors.ts +3 -3
- package/src/features/favorites.ts +14 -11
- package/src/features/gate.ts +16 -1
- package/src/features/hook-wiring.test.ts +302 -0
- package/src/features/metadata.ts +20 -3
- package/src/features/network.ts +1 -1
- package/src/features/nowPlaying.ts +1 -1
- package/src/features/output.ts +1 -1
- package/src/features/playback/controls.ts +4 -2
- package/src/features/playback/playWhenReady.ts +1 -1
- package/src/features/playback/playing.ts +1 -1
- package/src/features/playback/progress.test.ts +169 -0
- package/src/features/playback/progress.ts +3 -2
- package/src/features/playback/rate.ts +8 -1
- package/src/features/playback/state.ts +3 -4
- package/src/features/playback/trackPlaybackTime.test.ts +16 -6
- package/src/features/playback/trackPlaybackTime.ts +1 -6
- package/src/features/playback/volume.ts +1 -1
- package/src/features/player/options.ts +126 -76
- package/src/features/player/setup.test.ts +24 -7
- package/src/features/player/setup.ts +22 -10
- package/src/features/player/validateOptions.ts +21 -0
- package/src/features/queue/activeTrack.ts +15 -4
- package/src/features/queue/queue.ts +13 -6
- package/src/features/queue/repeatMode.ts +1 -1
- package/src/features/queue/shuffle.ts +1 -1
- package/src/features/remoteControls.ts +13 -92
- package/src/features/sleepTimer.test.ts +172 -0
- package/src/features/sleepTimer.ts +9 -1
- package/src/nitro-stub-drift.test.ts +277 -0
- package/src/public-surface.test.ts +147 -0
- package/src/specs/audio-browser.nitro.ts +5 -4
- package/src/style-resolution.test.ts +210 -0
- package/src/test-utils/reactNativeStub.ts +60 -0
- package/src/types/browser-native.ts +7 -3
- package/src/types/browser-nodes.ts +396 -134
- package/src/types/browser.ts +85 -59
- package/src/utils/LazyNativeEmitter.ts +28 -15
- package/src/utils/NativeUpdatedValue.ts +29 -13
- package/src/utils/getTrackIdentity.ts +20 -0
- package/src/utils/useDebug.test.ts +182 -0
- package/src/utils/useNativeUpdatedValue.test.ts +103 -0
- package/src/utils/useNativeValueRefreshedBy.ts +38 -0
- package/src/web/NativeAudioBrowser.playWhenReady.test.ts +232 -2
- package/src/web/NativeAudioBrowser.ts +239 -82
- package/src/web/TrackPlayer/LoadAttempt.ts +29 -0
- package/src/web/TrackPlayer/PlaybackStateMachine.test.ts +60 -13
- package/src/web/TrackPlayer/PlaybackStateMachine.ts +22 -6
- package/src/web/TrackPlayer/Player.dispatch.test.ts +5 -3
- package/src/web/TrackPlayer/Player.load.test.ts +137 -1
- package/src/web/TrackPlayer/Player.ts +284 -37
- package/src/web/TrackPlayer/QueueManager.test.ts +29 -0
- package/src/web/TrackPlayer/QueueManager.ts +14 -0
- package/src/web/TrackPlayer/QueuePlayer.ts +33 -14
- package/src/web/__tests__/lifecycle.test.ts +345 -0
- package/src/web/__tests__/lifecycleHarness.ts +351 -0
- package/src/web/__tests__/loadEdgeCases.test.ts +246 -0
- package/src/web/__tests__/loadSupersession.test.ts +175 -0
- package/src/web/__tests__/retry.test.ts +169 -0
- package/src/web/browser/BrowserManager.ts +209 -111
- package/src/web/browser/FavoriteManager.test.ts +84 -0
- package/src/web/browser/FavoriteManager.ts +28 -23
- package/src/web/browser/SearchManager.test.ts +75 -0
- package/src/web/browser/SearchManager.ts +25 -28
- package/src/web/browser/__tests__/artwork-resolution.test.ts +117 -0
- package/src/web/browser/__tests__/layer-resolver.test.ts +35 -0
- package/src/web/browser/__tests__/search-artwork.test.ts +46 -0
- package/src/web/browser/__tests__/search-navigation.test.ts +76 -0
- 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/http/RequestConfigBuilder.test.ts +241 -1
- package/src/web/http/RequestConfigBuilder.ts +140 -33
- package/src/web/http/followMediaRedirect.test.ts +289 -0
- package/src/web/http/followMediaRedirect.ts +253 -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 +247 -0
- package/ios/CarPlay/ImageRowItem+CarPlay.swift +0 -19
- package/ios/Model/MediaURL.swift +0 -67
- package/nitrogen/generated/android/c++/JFavoriteConfig.hpp +0 -58
- package/nitrogen/generated/android/c++/JImageRowItem.hpp +0 -105
- package/nitrogen/generated/android/c++/JNotificationButtonLayout.hpp +0 -94
- 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/c++/JVariant_NullType_NotificationButtonLayout.cpp +0 -26
- package/nitrogen/generated/android/c++/JVariant_NullType_NotificationButtonLayout.hpp +0 -75
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageRowItem.kt +0 -68
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NotificationButtonLayout.kt +0 -50
- 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/NotificationButtonLayout.swift +0 -92
- 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/nitrogen/generated/shared/c++/NotificationButtonLayout.hpp +0 -102
|
@@ -160,6 +160,35 @@ describe('QueueManager', () => {
|
|
|
160
160
|
expect(q.nextIndex()).toBeUndefined()
|
|
161
161
|
})
|
|
162
162
|
|
|
163
|
+
// Filling a queue that had no current track: the order is shuffled with
|
|
164
|
+
// nothing to lead it, so the track that becomes current can land anywhere —
|
|
165
|
+
// last included, which reads as end-of-queue from the very first track.
|
|
166
|
+
it('leads the order with the start track when setTracks fills an empty queue', () => {
|
|
167
|
+
const fresh = new QueueManager()
|
|
168
|
+
fresh.setShuffleEnabled(true) // shuffle already on, queue still empty
|
|
169
|
+
fresh.setTracks(tracks(4))
|
|
170
|
+
fresh.currentIndex = 2 // the start index
|
|
171
|
+
|
|
172
|
+
// identity order [0,1,2,3] re-pinned on 2 → [2,1,0,3]
|
|
173
|
+
expect(fresh.previousIndex()).toBeUndefined()
|
|
174
|
+
expect(fresh.nextIndex()).toBe(1)
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
it('leads the order with the start track when insert fills an empty queue', () => {
|
|
178
|
+
const fresh = new QueueManager()
|
|
179
|
+
fresh.setShuffleEnabled(true)
|
|
180
|
+
const random = vi.spyOn(Math, 'random').mockReturnValue(0.999)
|
|
181
|
+
try {
|
|
182
|
+
fresh.insert(tracks(4)) // slotted in at the order's end → [0,1,2,3]
|
|
183
|
+
} finally {
|
|
184
|
+
random.mockRestore()
|
|
185
|
+
}
|
|
186
|
+
fresh.currentIndex = 3 // would sit LAST in the order without the re-pin
|
|
187
|
+
|
|
188
|
+
expect(fresh.nextIndex()).toBe(1)
|
|
189
|
+
expect(fresh.previousIndex()).toBeUndefined()
|
|
190
|
+
})
|
|
191
|
+
|
|
163
192
|
it('keeps every track at its shuffle position across a move', () => {
|
|
164
193
|
q.currentIndex = 1
|
|
165
194
|
q.move(1, 3) // tracks [s0,s2,s3,s1]; order remapped to [0,3,1,2]
|
|
@@ -63,8 +63,22 @@ export class QueueManager {
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
set currentIndex(index: number | undefined) {
|
|
66
|
+
const hadNoCurrent = this._currentIndex === undefined
|
|
66
67
|
this._lastIndex = this._currentIndex
|
|
67
68
|
this._currentIndex = index
|
|
69
|
+
|
|
70
|
+
// A queue with no current track has an order that was shuffled with nothing
|
|
71
|
+
// to lead it — `setTracks` clears the index before regenerating, and
|
|
72
|
+
// `insert` drops new indices at random positions — so the track that then
|
|
73
|
+
// becomes current can sit anywhere, including last. That reads as
|
|
74
|
+
// end-of-queue immediately: `nextIndex` is undefined from the first track,
|
|
75
|
+
// so auto-advance fires onQueueEnded after one track. Re-pin at the moment
|
|
76
|
+
// the queue gains a current track. Safe as a setter hook here because the
|
|
77
|
+
// tracks are always in place before the index is assigned (both `setTracks`
|
|
78
|
+
// and `insert` run first).
|
|
79
|
+
if (hadNoCurrent && index !== undefined && this._shuffleEnabled) {
|
|
80
|
+
this.regenerateShuffleOrder()
|
|
81
|
+
}
|
|
68
82
|
}
|
|
69
83
|
|
|
70
84
|
get lastIndex(): number | undefined {
|
|
@@ -22,18 +22,33 @@ export class QueuePlayer extends Player {
|
|
|
22
22
|
// was a silent pause) and armed load()'s auto-play with phantom intent.
|
|
23
23
|
// Cleared before the state lands so consumers observe the native order
|
|
24
24
|
// (intent → state → queueEnded), independent of onQueueEnded overrides.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
if (state !== State.Ended) {
|
|
26
|
+
super.applyState(state)
|
|
27
|
+
return
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
|
|
30
|
+
// A track ending mid-queue is not an `ended` playback state: ExoPlayer
|
|
31
|
+
// reaches STATE_ENDED only at the end of the *playlist*, and an advance
|
|
32
|
+
// between items stays READY/BUFFERING. Web loads one track at a time, so
|
|
33
|
+
// the element's own `ended` arrives every time — reporting it flashed a
|
|
34
|
+
// terminal state, and dropped `PlayingState.playing` to false, between
|
|
35
|
+
// every pair of tracks. Repeat-one counts as mid-queue for the same
|
|
36
|
+
// reason: native reports nothing there either.
|
|
37
|
+
if (this.endsQueue()) {
|
|
38
|
+
// The real end: the intent goes with it, and the state is genuinely ended.
|
|
39
|
+
this.playWhenReady = false
|
|
40
|
+
super.applyState(state)
|
|
41
|
+
// dispatch() already gates on _isStopped before reaching applyState, so a
|
|
42
|
+
// natural end while stopped never advances the queue.
|
|
35
43
|
this.onTrackEnded()
|
|
44
|
+
return
|
|
36
45
|
}
|
|
46
|
+
|
|
47
|
+
// Suppressing `ended` is only safe when something takes over the state. A
|
|
48
|
+
// handler that declines to advance — the sleep timer set to end-of-track —
|
|
49
|
+
// leaves nothing to move it, and the player would sit reporting `playing`
|
|
50
|
+
// with nothing playing. Report the end in that case, as before.
|
|
51
|
+
if (!this.onTrackEnded()) super.applyState(state)
|
|
37
52
|
}
|
|
38
53
|
|
|
39
54
|
/** True when a natural end has nowhere to go: not repeating, no next track. */
|
|
@@ -45,18 +60,22 @@ export class QueuePlayer extends Player {
|
|
|
45
60
|
)
|
|
46
61
|
}
|
|
47
62
|
|
|
48
|
-
|
|
63
|
+
/**
|
|
64
|
+
* @returns whether it started another load, and so owns the playback state
|
|
65
|
+
* from here. `false` means the caller still has to report the end itself.
|
|
66
|
+
*/
|
|
67
|
+
protected onTrackEnded(): boolean {
|
|
49
68
|
if (this.queue.repeatMode === RepeatMode.Track) {
|
|
50
|
-
if (this.queue.currentIndex
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
return
|
|
69
|
+
if (this.queue.currentIndex === undefined) return false
|
|
70
|
+
this.goToIndex(this.queue.currentIndex)
|
|
71
|
+
return true
|
|
54
72
|
}
|
|
55
73
|
if (this.endsQueue()) {
|
|
56
74
|
this.onQueueEnded()
|
|
57
|
-
return
|
|
75
|
+
return false
|
|
58
76
|
}
|
|
59
77
|
this.skipToNext()
|
|
78
|
+
return true
|
|
60
79
|
}
|
|
61
80
|
|
|
62
81
|
/**
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
/** @vitest-environment happy-dom */
|
|
2
|
+
|
|
3
|
+
import { beforeEach, describe, expect, it } from 'vitest'
|
|
4
|
+
import { LifecycleHarness, trackA, trackB } from './lifecycleHarness'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* What the web player actually emits, recorded rather than reasoned about.
|
|
8
|
+
*
|
|
9
|
+
* Two halves, deliberately kept apart:
|
|
10
|
+
*
|
|
11
|
+
* - **Characterization** records today's behaviour. These assertions describe
|
|
12
|
+
* what happens, not what should — a change to any of them means the emission
|
|
13
|
+
* lifecycle moved, which is worth a deliberate look even when the move is an
|
|
14
|
+
* improvement.
|
|
15
|
+
* - **Parity** asserts what native emits for the same flow, derived from
|
|
16
|
+
* `PlaybackStateMachine.kt` and `PlayerListener.kt`. A divergence that is
|
|
17
|
+
* known but not yet closed belongs here as `it.fails`: the target is
|
|
18
|
+
* documented, the suite stays green while the gap stands, and the test
|
|
19
|
+
* starts failing the moment someone closes it — at which point flip it to a
|
|
20
|
+
* plain `it`.
|
|
21
|
+
*
|
|
22
|
+
* Fidelity: the harness runs the real wiring — `setupPlayer`, the real
|
|
23
|
+
* listeners, state machine and emitters — against a modelled Shaka whose
|
|
24
|
+
* behaviours are each cited to shaka-player 4.16.15's source. Every sequence
|
|
25
|
+
* below was also recorded in a real browser (Cypress against the Next.js
|
|
26
|
+
* example) and matched. Two modelled behaviours were *corrected* by that run:
|
|
27
|
+
* Shaka's teardown fires `emptied`/`loadstart` rather than `pause`, and a load
|
|
28
|
+
* that does not stall emits no Shaka `buffering` event at all.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
let h: LifecycleHarness
|
|
32
|
+
|
|
33
|
+
beforeEach(async () => {
|
|
34
|
+
h = new LifecycleHarness()
|
|
35
|
+
await h.setup()
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
describe('characterization — what the player emits today', () => {
|
|
39
|
+
it('load announces the active track, then hands off to Shaka', async () => {
|
|
40
|
+
h.browser.load(trackA)
|
|
41
|
+
await h.flush()
|
|
42
|
+
|
|
43
|
+
expect(h.recorded).toEqual([
|
|
44
|
+
'queue',
|
|
45
|
+
'activeTrack',
|
|
46
|
+
'nowPlaying',
|
|
47
|
+
'state:loading',
|
|
48
|
+
'playing:false|buffering:false',
|
|
49
|
+
'state:buffering'
|
|
50
|
+
])
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('the rest of a first load, paused', async () => {
|
|
54
|
+
h.browser.load(trackA)
|
|
55
|
+
await h.flush()
|
|
56
|
+
h.clear()
|
|
57
|
+
await h.completeLoad()
|
|
58
|
+
|
|
59
|
+
expect(h.recorded).toEqual(['state:ready'])
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
it('the rest of a first load, playWhenReady', async () => {
|
|
63
|
+
h.browser.setPlayWhenReady(true)
|
|
64
|
+
h.browser.load(trackA)
|
|
65
|
+
await h.flush()
|
|
66
|
+
h.clear()
|
|
67
|
+
await h.completeLoad()
|
|
68
|
+
|
|
69
|
+
// no `ready`: suppressed while the intent is to play, as native does
|
|
70
|
+
expect(h.recorded).toEqual([
|
|
71
|
+
'state:playing',
|
|
72
|
+
'playing:true|buffering:false'
|
|
73
|
+
])
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
it('switching tracks while playing', async () => {
|
|
77
|
+
h.browser.setPlayWhenReady(true)
|
|
78
|
+
h.browser.load(trackA)
|
|
79
|
+
await h.flush()
|
|
80
|
+
await h.completeLoad()
|
|
81
|
+
h.clear()
|
|
82
|
+
|
|
83
|
+
h.browser.load(trackB)
|
|
84
|
+
await h.flush()
|
|
85
|
+
await h.completeLoad()
|
|
86
|
+
|
|
87
|
+
// No `paused`: the teardown inside Shaka's load() fires `emptied` and
|
|
88
|
+
// `loadstart`, not `pause` — confirmed in a real browser.
|
|
89
|
+
expect(h.recorded).toEqual([
|
|
90
|
+
'queue',
|
|
91
|
+
'activeTrack',
|
|
92
|
+
'nowPlaying',
|
|
93
|
+
'state:loading',
|
|
94
|
+
'playing:true|buffering:true',
|
|
95
|
+
'state:buffering',
|
|
96
|
+
'state:playing',
|
|
97
|
+
'playing:true|buffering:false'
|
|
98
|
+
])
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
it('pause then play', async () => {
|
|
102
|
+
h.browser.setPlayWhenReady(true)
|
|
103
|
+
h.browser.load(trackA)
|
|
104
|
+
await h.flush()
|
|
105
|
+
await h.completeLoad()
|
|
106
|
+
h.clear()
|
|
107
|
+
|
|
108
|
+
h.browser.pause()
|
|
109
|
+
await h.flush()
|
|
110
|
+
h.browser.play()
|
|
111
|
+
await h.flush()
|
|
112
|
+
|
|
113
|
+
expect(h.recorded).toEqual([
|
|
114
|
+
'playWhenReady:false',
|
|
115
|
+
'playing:false|buffering:false',
|
|
116
|
+
'state:paused',
|
|
117
|
+
'playWhenReady:true',
|
|
118
|
+
'playing:true|buffering:false',
|
|
119
|
+
'state:playing'
|
|
120
|
+
])
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
it('mid-queue track end auto-advances', async () => {
|
|
124
|
+
h.browser.setQueue([trackA, trackB])
|
|
125
|
+
h.browser.setPlayWhenReady(true)
|
|
126
|
+
h.browser.skip(0)
|
|
127
|
+
await h.flush()
|
|
128
|
+
await h.completeLoad()
|
|
129
|
+
h.clear()
|
|
130
|
+
|
|
131
|
+
h.endTrack()
|
|
132
|
+
await h.flush()
|
|
133
|
+
|
|
134
|
+
// Neither `paused` nor `ended`: the element fires both when a track plays
|
|
135
|
+
// out, and both are suppressed so an advance looks like native's.
|
|
136
|
+
expect(h.recorded).toEqual([
|
|
137
|
+
'activeTrack',
|
|
138
|
+
'nowPlaying',
|
|
139
|
+
'state:loading',
|
|
140
|
+
'playing:true|buffering:true',
|
|
141
|
+
'state:buffering'
|
|
142
|
+
])
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
it('last track end ends the queue', async () => {
|
|
146
|
+
h.browser.setQueue([trackA])
|
|
147
|
+
h.browser.setPlayWhenReady(true)
|
|
148
|
+
h.browser.skip(0)
|
|
149
|
+
await h.flush()
|
|
150
|
+
await h.completeLoad()
|
|
151
|
+
h.clear()
|
|
152
|
+
|
|
153
|
+
h.endTrack()
|
|
154
|
+
await h.flush()
|
|
155
|
+
|
|
156
|
+
// the real end does report `ended`; only the end-of-track `paused` is gone
|
|
157
|
+
expect(h.recorded).toEqual([
|
|
158
|
+
'playWhenReady:false',
|
|
159
|
+
'playing:false|buffering:false',
|
|
160
|
+
'state:ended',
|
|
161
|
+
'queueEnded'
|
|
162
|
+
])
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
it('stop', async () => {
|
|
166
|
+
h.browser.setPlayWhenReady(true)
|
|
167
|
+
h.browser.load(trackA)
|
|
168
|
+
await h.flush()
|
|
169
|
+
await h.completeLoad()
|
|
170
|
+
h.clear()
|
|
171
|
+
|
|
172
|
+
h.browser.stop()
|
|
173
|
+
await h.flush()
|
|
174
|
+
|
|
175
|
+
expect(h.recorded).toEqual([
|
|
176
|
+
'playWhenReady:false',
|
|
177
|
+
'playing:false|buffering:false',
|
|
178
|
+
'state:stopped'
|
|
179
|
+
])
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
it('a load Shaka rejects', async () => {
|
|
183
|
+
h.failLoad()
|
|
184
|
+
h.browser.load(trackA)
|
|
185
|
+
await h.flush()
|
|
186
|
+
|
|
187
|
+
// the code is whatever the rejection carried; -1 is the normalizer's
|
|
188
|
+
// fallback for a plain Error
|
|
189
|
+
expect(h.recorded).toEqual([
|
|
190
|
+
'queue',
|
|
191
|
+
'activeTrack',
|
|
192
|
+
'nowPlaying',
|
|
193
|
+
'state:loading',
|
|
194
|
+
'playing:false|buffering:false',
|
|
195
|
+
'state:buffering',
|
|
196
|
+
'state:error',
|
|
197
|
+
'error:-1'
|
|
198
|
+
])
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
it('a track with no src', async () => {
|
|
202
|
+
h.browser.load({ id: 'x', title: 'No src' })
|
|
203
|
+
await h.flush()
|
|
204
|
+
|
|
205
|
+
expect(h.recorded).toEqual([
|
|
206
|
+
'queue',
|
|
207
|
+
'activeTrack',
|
|
208
|
+
'nowPlaying',
|
|
209
|
+
'state:loading',
|
|
210
|
+
'playing:false|buffering:false',
|
|
211
|
+
'state:error',
|
|
212
|
+
'error:invalid_track'
|
|
213
|
+
])
|
|
214
|
+
})
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
describe('parity — what native emits for the same flow', () => {
|
|
218
|
+
/**
|
|
219
|
+
* Android fires the active-track callback from `onMediaItemTransition`
|
|
220
|
+
* (PlayerListener.kt:106) and maps the same event to LOADING in `onEvents`
|
|
221
|
+
* (:216-224), which ExoPlayer runs after the individual callbacks.
|
|
222
|
+
*/
|
|
223
|
+
it('announces the active track before reporting loading', async () => {
|
|
224
|
+
h.browser.load(trackA)
|
|
225
|
+
await h.flush()
|
|
226
|
+
|
|
227
|
+
const active = h.recorded.indexOf('activeTrack')
|
|
228
|
+
const loading = h.recorded.indexOf('state:loading')
|
|
229
|
+
expect(active).toBeGreaterThanOrEqual(0)
|
|
230
|
+
expect(loading).toBeGreaterThan(active)
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Android always passes through STATE_BUFFERING after prepare. Shaka only
|
|
235
|
+
* fires its own `buffering` event when a load actually stalls, so a load
|
|
236
|
+
* served from cache used to skip the state entirely. `Player`'s `loading`
|
|
237
|
+
* listener now dispatches `waiting` alongside `trackLoading` so every load
|
|
238
|
+
* passes through it, as native's does.
|
|
239
|
+
*/
|
|
240
|
+
it('reports buffering between loading and playing', async () => {
|
|
241
|
+
h.browser.setPlayWhenReady(true)
|
|
242
|
+
h.browser.load(trackA)
|
|
243
|
+
await h.flush()
|
|
244
|
+
await h.completeLoad()
|
|
245
|
+
|
|
246
|
+
expect(h.recorded).toContain('state:buffering')
|
|
247
|
+
})
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Android suppresses READY while playWhenReady — "READY is a transient
|
|
251
|
+
* before PLAYING — suppress it so consumers don't flash a settled/non-loading
|
|
252
|
+
* state mid-startup" (PlaybackStateMachine.kt, STATE_READY branch). The web
|
|
253
|
+
* machine now takes `playWhenReady` on the two edges that produce `ready` and
|
|
254
|
+
* suppresses it the same way.
|
|
255
|
+
*
|
|
256
|
+
* The web-only hazard that comes with it: a browser can refuse `play()`.
|
|
257
|
+
* `Player.onPlayRejected` clears the intent on anything but an `AbortError`,
|
|
258
|
+
* so a blocked autoplay settles instead of stranding on `buffering`.
|
|
259
|
+
*/
|
|
260
|
+
it('does not report ready mid-startup while playWhenReady', async () => {
|
|
261
|
+
h.browser.setPlayWhenReady(true)
|
|
262
|
+
h.browser.load(trackA)
|
|
263
|
+
await h.flush()
|
|
264
|
+
h.clear()
|
|
265
|
+
await h.completeLoad()
|
|
266
|
+
|
|
267
|
+
expect(h.recorded).not.toContain('state:ready')
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Android never reports ENDED between tracks: STATE_ENDED is only reached at
|
|
272
|
+
* the end of the playlist, and a mid-playlist advance stays READY/BUFFERING.
|
|
273
|
+
* Web loads one track at a time, so the element's own `ended` used to surface
|
|
274
|
+
* and drop `PlayingState.playing` to false between every pair of tracks.
|
|
275
|
+
* `QueuePlayer.applyState` now advances without emitting it; the true queue
|
|
276
|
+
* end still reports `ended`.
|
|
277
|
+
*/
|
|
278
|
+
it('does not report ended when the queue advances', async () => {
|
|
279
|
+
h.browser.setQueue([trackA, trackB])
|
|
280
|
+
h.browser.setPlayWhenReady(true)
|
|
281
|
+
h.browser.skip(0)
|
|
282
|
+
await h.flush()
|
|
283
|
+
await h.completeLoad()
|
|
284
|
+
h.clear()
|
|
285
|
+
|
|
286
|
+
h.endTrack()
|
|
287
|
+
await h.flush()
|
|
288
|
+
|
|
289
|
+
expect(h.recorded).not.toContain('state:ended')
|
|
290
|
+
expect(h.recorded).not.toContain('playing:false|buffering:false')
|
|
291
|
+
})
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Android's transition cuts the outgoing item and reports LOADING, with no
|
|
295
|
+
* PAUSED in between — and web matches. The teardown inside Shaka's load()
|
|
296
|
+
* fires `emptied` and `loadstart`, never `pause`, even mid-playback.
|
|
297
|
+
* Confirmed in a real browser; reading the HTML load algorithm had suggested
|
|
298
|
+
* otherwise.
|
|
299
|
+
*/
|
|
300
|
+
it('does not report paused when switching tracks', async () => {
|
|
301
|
+
h.browser.setPlayWhenReady(true)
|
|
302
|
+
h.browser.load(trackA)
|
|
303
|
+
await h.flush()
|
|
304
|
+
await h.completeLoad()
|
|
305
|
+
h.clear()
|
|
306
|
+
|
|
307
|
+
h.browser.load(trackB)
|
|
308
|
+
await h.flush()
|
|
309
|
+
|
|
310
|
+
expect(h.recorded).not.toContain('state:paused')
|
|
311
|
+
})
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* A track playing out fires `pause` before `ended` on the element, so web
|
|
315
|
+
* used to report `paused` at the end of every track where native reports
|
|
316
|
+
* nothing. The pause listener now ignores a pause raised once `ended` is
|
|
317
|
+
* already true.
|
|
318
|
+
*/
|
|
319
|
+
it('does not report paused when a track plays out', async () => {
|
|
320
|
+
h.browser.setQueue([trackA, trackB])
|
|
321
|
+
h.browser.setPlayWhenReady(true)
|
|
322
|
+
h.browser.skip(0)
|
|
323
|
+
await h.flush()
|
|
324
|
+
await h.completeLoad()
|
|
325
|
+
h.clear()
|
|
326
|
+
|
|
327
|
+
h.endTrack()
|
|
328
|
+
await h.flush()
|
|
329
|
+
|
|
330
|
+
expect(h.recorded).not.toContain('state:paused')
|
|
331
|
+
})
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Android reports LOADING off the media-item transition, before any network
|
|
335
|
+
* work, so the URL-resolution window has a state. Web now does the same: the
|
|
336
|
+
* announcement and `trackLoading` both happen when `load()` is called, so the
|
|
337
|
+
* pair keeps native's order and the window is no longer silent. Shaka's own
|
|
338
|
+
* `loading` arrives later and the state setter drops it as a no-op.
|
|
339
|
+
*/
|
|
340
|
+
it('reports loading while the url is still resolving', async () => {
|
|
341
|
+
h.browser.load(trackA)
|
|
342
|
+
|
|
343
|
+
expect(h.browser.getPlayback().state).toBe('loading')
|
|
344
|
+
})
|
|
345
|
+
})
|