react-native-audio-browser 0.2.0-next.2 → 0.2.0-next.20
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
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Resolves a media URL that is authenticated by a header.
|
|
5
|
+
*
|
|
6
|
+
* Shaka only routes manifest requests through its networking engine, where a
|
|
7
|
+
* request filter can attach headers. A progressive file is played by assigning
|
|
8
|
+
* `mediaElement.src`, and a media element cannot send custom headers — so such
|
|
9
|
+
* a URL is unplayable that way. Following the redirect here yields the signed,
|
|
10
|
+
* public URL these endpoints hand back, which needs no auth of its own.
|
|
11
|
+
*
|
|
12
|
+
* Best effort and bounded: anything that fails — including taking too long, see
|
|
13
|
+
* {@link PROBE_TIMEOUT_MS} — falls back to the original URL, so the load fails
|
|
14
|
+
* or succeeds on its own terms rather than ours. It must never be the reason a
|
|
15
|
+
* load hangs: `load()` awaits this before Shaka sees the URL at all.
|
|
16
|
+
*
|
|
17
|
+
* Gated, because the probe is not free: a HEAD at a third-party stream host
|
|
18
|
+
* costs a CORS preflight, and most will refuse it, so an app that never
|
|
19
|
+
* authenticates its media would pay a round trip on every play for a result it
|
|
20
|
+
* always discards. It runs only for headers that look like media credentials
|
|
21
|
+
* ({@link isMediaAuth}), on media a media element actually has to play
|
|
22
|
+
* ({@link isManifestUrl}), and never on a URL the browser resolves locally.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/** URLs the browser resolves locally; there is no redirect to follow. */
|
|
26
|
+
const isLocalUrl = url => /^(file|blob|data|mediasource):/i.test(url);
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Extensions Shaka types as a manifest, from its own `EXTENSIONS_TO_MIME_TYPES_`
|
|
30
|
+
* map: HLS, DASH and Smooth Streaming.
|
|
31
|
+
*/
|
|
32
|
+
const MANIFEST_EXTENSIONS = new Set(['m3u8', 'mpd', 'ism']);
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Whether Shaka will parse this as a manifest rather than hand it to the media
|
|
36
|
+
* element — in which case the probe has nothing to offer and something to cost.
|
|
37
|
+
*
|
|
38
|
+
* A manifest goes through Shaka's networking engine, where the request filter
|
|
39
|
+
* attaches the headers to the manifest, its segments and any key requests. The
|
|
40
|
+
* probe cannot improve on that, and it actively breaks it: on a cross-origin
|
|
41
|
+
* redirect the probe clears the headers, so the segments that Android still
|
|
42
|
+
* authenticates would go out bare and 401. So this is a correctness fix as much
|
|
43
|
+
* as it is one fewer round trip.
|
|
44
|
+
*
|
|
45
|
+
* Extension-based, and therefore partial — Shaka guesses the same way
|
|
46
|
+
* (`NetworkingUtils.getExtension`), but plenty of HLS endpoints have no
|
|
47
|
+
* extension at all. Those still get probed, which is the status quo rather than
|
|
48
|
+
* a regression. Nothing on `Track` carries a MIME type to do better with.
|
|
49
|
+
*/
|
|
50
|
+
const isManifestUrl = url => {
|
|
51
|
+
const path = url.split(/[?#]/)[0] ?? '';
|
|
52
|
+
const filename = path.slice(path.lastIndexOf('/') + 1);
|
|
53
|
+
const pieces = filename.split('.');
|
|
54
|
+
return pieces.length > 1 && MANIFEST_EXTENSIONS.has(pieces[pieces.length - 1].toLowerCase());
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* How long the probe may take before the original URL is played instead.
|
|
58
|
+
*
|
|
59
|
+
* The same 8s the Android media client allows a connect or a read
|
|
60
|
+
* (`MediaFactory.mediaHttpClient`), which is generous for a HEAD but errs the
|
|
61
|
+
* safe way: a slow-but-working auth endpoint should not be abandoned, since
|
|
62
|
+
* giving up means playing a URL that will 401.
|
|
63
|
+
*/
|
|
64
|
+
const PROBE_TIMEOUT_MS = 8_000;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* `AbortSignal.timeout` where it exists (Safari 16+, Chrome 103+, Node 17.3+),
|
|
68
|
+
* else a hand-rolled equivalent, else nothing — an environment with neither
|
|
69
|
+
* still gets the deadline below, just without cancelling the request.
|
|
70
|
+
*/
|
|
71
|
+
const timeoutSignal = ms => {
|
|
72
|
+
if (typeof AbortSignal === 'undefined') return undefined;
|
|
73
|
+
if (typeof AbortSignal.timeout === 'function') return AbortSignal.timeout(ms);
|
|
74
|
+
if (typeof AbortController === 'undefined') return undefined;
|
|
75
|
+
const controller = new AbortController();
|
|
76
|
+
setTimeout(() => controller.abort(), ms);
|
|
77
|
+
return controller.signal;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* The probe, with a deadline. `load()` awaits this before Shaka is asked to
|
|
82
|
+
* play anything, so an unreachable host would otherwise stall the load
|
|
83
|
+
* indefinitely — no audio, and no error to show for it.
|
|
84
|
+
*
|
|
85
|
+
* Two mechanisms, each with its own job: the signal cancels the request, so a
|
|
86
|
+
* dead host does not hold a connection open behind us, and the race bounds *us*
|
|
87
|
+
* even where the fetch implementation ignores the signal. Whichever fires, the
|
|
88
|
+
* caller treats it as any other probe failure and plays the original URL.
|
|
89
|
+
*/
|
|
90
|
+
const fetchWithDeadline = async (doFetch, url, headers, timeoutMs) => {
|
|
91
|
+
let timer;
|
|
92
|
+
try {
|
|
93
|
+
return await Promise.race([doFetch(url, {
|
|
94
|
+
method: 'HEAD',
|
|
95
|
+
headers,
|
|
96
|
+
redirect: 'follow',
|
|
97
|
+
signal: timeoutSignal(timeoutMs)
|
|
98
|
+
}), new Promise((_resolve, reject) => {
|
|
99
|
+
timer = setTimeout(() => reject(new Error(`Media redirect probe timed out (${timeoutMs}ms)`)), timeoutMs);
|
|
100
|
+
})]);
|
|
101
|
+
} finally {
|
|
102
|
+
if (timer !== undefined) clearTimeout(timer);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Whether these headers look like a media credential — the only thing the
|
|
108
|
+
* probe can fix, and the only thing worth a preflight.
|
|
109
|
+
*
|
|
110
|
+
* A header the `media` layer set is media-specific by construction. Otherwise
|
|
111
|
+
* only `Authorization` counts: an app authenticating one API for browse and
|
|
112
|
+
* media alike puts it on the shared `request` layer, and that is the common
|
|
113
|
+
* shape. Shared plumbing that also rides browse requests — an `X-Client-Version`
|
|
114
|
+
* — is not a credential and must not trigger the probe.
|
|
115
|
+
*
|
|
116
|
+
* The residual case is a shared layer carrying a custom auth header, say
|
|
117
|
+
* `X-Api-Key`, for media that needs it: move it to the `media` layer and the
|
|
118
|
+
* probe runs.
|
|
119
|
+
*/
|
|
120
|
+
const isMediaAuth = (headers, mediaLayerHeaders) => mediaLayerHeaders || Object.keys(headers).some(key => key.toLowerCase() === 'authorization');
|
|
121
|
+
/**
|
|
122
|
+
* Origin of an http(s) URL, or undefined when it cannot be determined.
|
|
123
|
+
*
|
|
124
|
+
* Relative URLs are resolved against the document, because that is what the
|
|
125
|
+
* probe's own `fetch` does — a `src` of `/api/authed/7` is a request to the
|
|
126
|
+
* page's origin, so the credential went there. Without this a relative `src`
|
|
127
|
+
* has no origin, never matches the absolute URL the response reports, and the
|
|
128
|
+
* headers are dropped from every load that uses one.
|
|
129
|
+
*
|
|
130
|
+
* Parsed rather than pattern-matched so the comparison normalizes the way
|
|
131
|
+
* Android's `CrossOriginHeaderStripper.sameOrigin` does: `URL.host` omits a
|
|
132
|
+
* default port, so `https://a.com` and `https://a.com:443` are one origin, and
|
|
133
|
+
* it excludes userinfo, so `https://user@a.com` is not a third.
|
|
134
|
+
*/
|
|
135
|
+
const originOf = url => {
|
|
136
|
+
try {
|
|
137
|
+
const base = typeof location === 'undefined' ? undefined : location.href;
|
|
138
|
+
const {
|
|
139
|
+
protocol,
|
|
140
|
+
host
|
|
141
|
+
} = new URL(url, base);
|
|
142
|
+
if (protocol !== 'http:' && protocol !== 'https:') return undefined;
|
|
143
|
+
return `${protocol}//${host}`;
|
|
144
|
+
} catch {
|
|
145
|
+
return undefined;
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Whether the redirect left the origin the credential was addressed to.
|
|
151
|
+
*
|
|
152
|
+
* Only when both origins are known and differ. An origin we could not work out
|
|
153
|
+
* — a relative URL with no document base, outside a browser — is not evidence
|
|
154
|
+
* of a hop, and treating it as one is how the headers went missing before.
|
|
155
|
+
*/
|
|
156
|
+
const leftTheOrigin = (from, to) => {
|
|
157
|
+
const origin = originOf(from);
|
|
158
|
+
return origin !== undefined && originOf(to) !== origin;
|
|
159
|
+
};
|
|
160
|
+
export async function followMediaRedirect(url, headers, {
|
|
161
|
+
fetchImpl,
|
|
162
|
+
mediaLayerHeaders = false,
|
|
163
|
+
timeoutMs = PROBE_TIMEOUT_MS
|
|
164
|
+
} = {}) {
|
|
165
|
+
if (!headers || Object.keys(headers).length === 0) return {
|
|
166
|
+
src: url,
|
|
167
|
+
headers
|
|
168
|
+
};
|
|
169
|
+
if (!isMediaAuth(headers, mediaLayerHeaders)) return {
|
|
170
|
+
src: url,
|
|
171
|
+
headers
|
|
172
|
+
};
|
|
173
|
+
if (isManifestUrl(url)) return {
|
|
174
|
+
src: url,
|
|
175
|
+
headers
|
|
176
|
+
};
|
|
177
|
+
if (isLocalUrl(url)) return {
|
|
178
|
+
src: url,
|
|
179
|
+
headers
|
|
180
|
+
};
|
|
181
|
+
const doFetch = fetchImpl ?? globalThis.fetch;
|
|
182
|
+
if (typeof doFetch !== 'function') return {
|
|
183
|
+
src: url,
|
|
184
|
+
headers
|
|
185
|
+
};
|
|
186
|
+
try {
|
|
187
|
+
// HEAD walks the chain without tripping download counting, which keys off
|
|
188
|
+
// ranged GETs. Deadlined, because the load waits on it.
|
|
189
|
+
const response = await fetchWithDeadline(doFetch, url, headers, timeoutMs);
|
|
190
|
+
const src = response.url || url;
|
|
191
|
+
|
|
192
|
+
// The status belongs to the *last* hop, so it only speaks for the
|
|
193
|
+
// authenticating endpoint when there was no redirect. Once one has
|
|
194
|
+
// happened, hop one authenticated and handed us its target, and a refusal
|
|
195
|
+
// past that is routinely about the method rather than the credential:
|
|
196
|
+
// presigned S3 and GCS URLs sign it — SigV4's canonical request opens with
|
|
197
|
+
// HTTPMethod, GCS V4's with HTTP_VERB — so a URL signed for GET answers a
|
|
198
|
+
// HEAD with 403. Keep the signed URL, which is the whole point of the walk,
|
|
199
|
+
// and let a real error surface through the player.
|
|
200
|
+
if (!response.ok && src === url) return {
|
|
201
|
+
src: url,
|
|
202
|
+
headers
|
|
203
|
+
};
|
|
204
|
+
return {
|
|
205
|
+
src,
|
|
206
|
+
headers: leftTheOrigin(url, src) ? undefined : headers
|
|
207
|
+
};
|
|
208
|
+
} catch {
|
|
209
|
+
return {
|
|
210
|
+
src: url,
|
|
211
|
+
headers
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=followMediaRedirect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["isLocalUrl","url","test","MANIFEST_EXTENSIONS","Set","isManifestUrl","path","split","filename","slice","lastIndexOf","pieces","length","has","toLowerCase","PROBE_TIMEOUT_MS","timeoutSignal","ms","AbortSignal","undefined","timeout","AbortController","controller","setTimeout","abort","signal","fetchWithDeadline","doFetch","headers","timeoutMs","timer","Promise","race","method","redirect","_resolve","reject","Error","clearTimeout","isMediaAuth","mediaLayerHeaders","Object","keys","some","key","originOf","base","location","href","protocol","host","URL","leftTheOrigin","from","to","origin","followMediaRedirect","fetchImpl","src","globalThis","fetch","response","ok"],"sourceRoot":"../../../../src","sources":["web/http/followMediaRedirect.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
import { artworkUrl } from '../../utils/artwork';
|
|
4
|
+
import { getTrackIdentity } from '../../utils/getTrackIdentity';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Manages now playing metadata overrides.
|
|
@@ -28,7 +29,7 @@ export class NowPlayingManager {
|
|
|
28
29
|
album: update.album ?? currentTrack.album,
|
|
29
30
|
artwork: artworkUrl(currentTrack.artwork),
|
|
30
31
|
description: currentTrack.description,
|
|
31
|
-
mediaId: currentTrack
|
|
32
|
+
mediaId: getTrackIdentity(currentTrack) ?? currentTrack.path,
|
|
32
33
|
genre: currentTrack.genre,
|
|
33
34
|
duration
|
|
34
35
|
} : {
|
|
@@ -37,7 +38,7 @@ export class NowPlayingManager {
|
|
|
37
38
|
album: currentTrack.album,
|
|
38
39
|
artwork: artworkUrl(currentTrack.artwork),
|
|
39
40
|
description: currentTrack.description,
|
|
40
|
-
mediaId: currentTrack
|
|
41
|
+
mediaId: getTrackIdentity(currentTrack) ?? currentTrack.path,
|
|
41
42
|
genre: currentTrack.genre,
|
|
42
43
|
duration
|
|
43
44
|
};
|
|
@@ -59,7 +60,7 @@ export class NowPlayingManager {
|
|
|
59
60
|
album: this.override?.album ?? currentTrack.album,
|
|
60
61
|
artwork: artworkUrl(currentTrack.artwork),
|
|
61
62
|
description: currentTrack.description,
|
|
62
|
-
mediaId: currentTrack
|
|
63
|
+
mediaId: getTrackIdentity(currentTrack) ?? currentTrack.path,
|
|
63
64
|
genre: currentTrack.genre,
|
|
64
65
|
duration
|
|
65
66
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["artworkUrl","NowPlayingManager","onNowPlayingChanged","updateNowPlaying","update","currentTrack","duration","override","metadata","title","artist","album","artwork","description","mediaId","
|
|
1
|
+
{"version":3,"names":["artworkUrl","getTrackIdentity","NowPlayingManager","onNowPlayingChanged","updateNowPlaying","update","currentTrack","duration","override","metadata","title","artist","album","artwork","description","mediaId","path","genre","getNowPlaying","undefined","clearNowPlayingOverride"],"sourceRoot":"../../../../src","sources":["web/player/NowPlayingManager.ts"],"mappings":";;AAEA,SAASA,UAAU,QAAQ,qBAAqB;AAChD,SAASC,gBAAgB,QAAQ,8BAA8B;;AAE/D;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,iBAAiB,CAAC;EAG7B;EACAC,mBAAmB,GAA2CA,CAAA,KAAM,CAAC,CAAC;;EAEtE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;EACEC,gBAAgBA,CACdC,MAAoC,EACpCC,YAA+B,EAC/BC,QAAgB,EACV;IACN,IAAI,CAACC,QAAQ,GAAGH,MAAM;IAEtB,IAAI,CAACC,YAAY,EAAE;IAEnB,MAAMG,QAA4B,GAAGJ,MAAM,GACvC;MACEK,KAAK,EAAEL,MAAM,CAACK,KAAK,IAAIJ,YAAY,CAACI,KAAK;MACzCC,MAAM,EAAEN,MAAM,CAACM,MAAM,IAAIL,YAAY,CAACK,MAAM;MAC5CC,KAAK,EAAEP,MAAM,CAACO,KAAK,IAAIN,YAAY,CAACM,KAAK;MACzCC,OAAO,EAAEb,UAAU,CAACM,YAAY,CAACO,OAAO,CAAC;MACzCC,WAAW,EAAER,YAAY,CAACQ,WAAW;MACrCC,OAAO,EAAEd,gBAAgB,CAACK,YAAY,CAAC,IAAIA,YAAY,CAACU,IAAI;MAC5DC,KAAK,EAAEX,YAAY,CAACW,KAAK;MACzBV;IACF,CAAC,GACD;MACEG,KAAK,EAAEJ,YAAY,CAACI,KAAK;MACzBC,MAAM,EAAEL,YAAY,CAACK,MAAM;MAC3BC,KAAK,EAAEN,YAAY,CAACM,KAAK;MACzBC,OAAO,EAAEb,UAAU,CAACM,YAAY,CAACO,OAAO,CAAC;MACzCC,WAAW,EAAER,YAAY,CAACQ,WAAW;MACrCC,OAAO,EAAEd,gBAAgB,CAACK,YAAY,CAAC,IAAIA,YAAY,CAACU,IAAI;MAC5DC,KAAK,EAAEX,YAAY,CAACW,KAAK;MACzBV;IACF,CAAC;IAEL,IAAI,CAACJ,mBAAmB,CAACM,QAAQ,CAAC;EACpC;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;EACES,aAAaA,CACXZ,YAA+B,EAC/BC,QAAgB,EACgB;IAChC,IAAI,CAACD,YAAY,EAAE,OAAOa,SAAS;IAEnC,OAAO;MACLT,KAAK,EAAE,IAAI,CAACF,QAAQ,EAAEE,KAAK,IAAIJ,YAAY,CAACI,KAAK;MACjDC,MAAM,EAAE,IAAI,CAACH,QAAQ,EAAEG,MAAM,IAAIL,YAAY,CAACK,MAAM;MACpDC,KAAK,EAAE,IAAI,CAACJ,QAAQ,EAAEI,KAAK,IAAIN,YAAY,CAACM,KAAK;MACjDC,OAAO,EAAEb,UAAU,CAACM,YAAY,CAACO,OAAO,CAAC;MACzCC,WAAW,EAAER,YAAY,CAACQ,WAAW;MACrCC,OAAO,EAAEd,gBAAgB,CAACK,YAAY,CAAC,IAAIA,YAAY,CAACU,IAAI;MAC5DC,KAAK,EAAEX,YAAY,CAACW,KAAK;MACzBV;IACF,CAAC;EACH;;EAEA;AACF;AACA;AACA;EACEa,uBAAuBA,CAAA,EAAS;IAC9B,IAAI,CAACZ,QAAQ,GAAGW,SAAS;EAC3B;AACF","ignoreList":[]}
|
|
@@ -8,8 +8,12 @@
|
|
|
8
8
|
* 1. System paths (prefixed with `/__`): Root, recent, and search paths
|
|
9
9
|
* 2. Contextual URLs: Embed parent context in track identifiers for Media3 integration
|
|
10
10
|
*
|
|
11
|
-
* Contextual URL format: `{parentPath}?__trackId={
|
|
12
|
-
* Example: "/library/radio?__trackId=song.mp3"
|
|
11
|
+
* Contextual URL format: `{parentPath}?__trackId={trackIdentity}&__index={childIndex}`
|
|
12
|
+
* Example: "/library/radio?__trackId=song.mp3&__index=2"
|
|
13
|
+
*
|
|
14
|
+
* `__trackId` is the identity check; `__index` (the child's position on the
|
|
15
|
+
* page at stamp time) is only a tie-breaker between surfaces that carry the
|
|
16
|
+
* same identity — a stale index never selects a different track.
|
|
13
17
|
*
|
|
14
18
|
* This allows:
|
|
15
19
|
* - Media3 to reference playable-only tracks (tracks with `src` but no `url`)
|
|
@@ -21,6 +25,8 @@ export const BrowserPathHelper = {
|
|
|
21
25
|
SEARCH_PATH_PREFIX: '/__search',
|
|
22
26
|
/** Query parameter name for contextual track identifiers */
|
|
23
27
|
CONTEXTUAL_TRACK_PARAM: '__trackId',
|
|
28
|
+
/** Query parameter name for the tapped child's page position (tie-breaker) */
|
|
29
|
+
CONTEXTUAL_INDEX_PARAM: '__index',
|
|
24
30
|
/**
|
|
25
31
|
* Create a search path for a given query
|
|
26
32
|
*/
|
|
@@ -38,13 +44,13 @@ export const BrowserPathHelper = {
|
|
|
38
44
|
return path.includes(`?${this.CONTEXTUAL_TRACK_PARAM}=`) || path.includes(`&${this.CONTEXTUAL_TRACK_PARAM}=`);
|
|
39
45
|
},
|
|
40
46
|
/**
|
|
41
|
-
* Strips the __trackId
|
|
42
|
-
* If the URL is not contextual, returns it unchanged.
|
|
47
|
+
* Strips the contextual parameters (__trackId and __index) from a contextual
|
|
48
|
+
* URL to get the parent path. If the URL is not contextual, returns it unchanged.
|
|
43
49
|
*
|
|
44
50
|
* @param url The URL to process
|
|
45
|
-
* @returns The URL without the
|
|
51
|
+
* @returns The URL without the contextual parameters
|
|
46
52
|
*
|
|
47
|
-
* Example: "/library/radio?__trackId=song.mp3" → "/library/radio"
|
|
53
|
+
* Example: "/library/radio?__trackId=song.mp3&__index=2" → "/library/radio"
|
|
48
54
|
* Example: "/search?q=jazz&__trackId=song.mp3" → "/search?q=jazz"
|
|
49
55
|
*/
|
|
50
56
|
stripTrackId(url) {
|
|
@@ -56,8 +62,9 @@ export const BrowserPathHelper = {
|
|
|
56
62
|
const isFullUrl = url.startsWith('http://') || url.startsWith('https://');
|
|
57
63
|
const urlObj = new URL(url, isFullUrl ? undefined : 'http://placeholder');
|
|
58
64
|
|
|
59
|
-
// Remove the
|
|
65
|
+
// Remove the contextual parameters
|
|
60
66
|
urlObj.searchParams.delete(this.CONTEXTUAL_TRACK_PARAM);
|
|
67
|
+
urlObj.searchParams.delete(this.CONTEXTUAL_INDEX_PARAM);
|
|
61
68
|
|
|
62
69
|
// Return the appropriate format
|
|
63
70
|
if (isFullUrl) {
|
|
@@ -68,7 +75,7 @@ export const BrowserPathHelper = {
|
|
|
68
75
|
}
|
|
69
76
|
} catch {
|
|
70
77
|
// Fallback: simple string manipulation
|
|
71
|
-
const paramPattern = new RegExp(`[?&]
|
|
78
|
+
const paramPattern = new RegExp(`[?&](?:${this.CONTEXTUAL_TRACK_PARAM}|${this.CONTEXTUAL_INDEX_PARAM})=[^&]*`, 'g');
|
|
72
79
|
let result = url.replace(paramPattern, '');
|
|
73
80
|
// Clean up any trailing ? or &
|
|
74
81
|
result = result.replace(/[?&]$/, '');
|
|
@@ -77,6 +84,22 @@ export const BrowserPathHelper = {
|
|
|
77
84
|
return result;
|
|
78
85
|
}
|
|
79
86
|
},
|
|
87
|
+
/**
|
|
88
|
+
* Builds a contextual URL by appending a track identifier — and optionally
|
|
89
|
+
* the tapped child's page position — to a parent path.
|
|
90
|
+
*
|
|
91
|
+
* @param parentPath The parent container path
|
|
92
|
+
* @param trackId The track identity (`id` when non-blank, else `src`)
|
|
93
|
+
* @param index The child's position on the page at stamp time (tie-breaker)
|
|
94
|
+
* @returns A contextual URL combining parent path, track ID, and index
|
|
95
|
+
*
|
|
96
|
+
* Example: build("/library", "song.mp3", 2) → "/library?__trackId=song.mp3&__index=2"
|
|
97
|
+
*/
|
|
98
|
+
build(parentPath, trackId, index) {
|
|
99
|
+
const separator = parentPath.includes('?') ? '&' : '?';
|
|
100
|
+
const indexParam = index === undefined ? '' : `&${this.CONTEXTUAL_INDEX_PARAM}=${index}`;
|
|
101
|
+
return `${parentPath}${separator}${this.CONTEXTUAL_TRACK_PARAM}=${encodeURIComponent(trackId)}${indexParam}`;
|
|
102
|
+
},
|
|
80
103
|
/**
|
|
81
104
|
* Extracts the track ID from a contextual URL.
|
|
82
105
|
* Returns undefined if the URL is not contextual or doesn't contain the track ID parameter.
|
|
@@ -90,14 +113,36 @@ export const BrowserPathHelper = {
|
|
|
90
113
|
if (!this.isContextual(path)) {
|
|
91
114
|
return undefined;
|
|
92
115
|
}
|
|
116
|
+
return this.extractParam(path, this.CONTEXTUAL_TRACK_PARAM);
|
|
117
|
+
},
|
|
118
|
+
/**
|
|
119
|
+
* Extracts the stamped page index from a contextual URL, or undefined when
|
|
120
|
+
* the URL is not contextual or carries no (valid, non-negative) index.
|
|
121
|
+
*
|
|
122
|
+
* Example: "/library/radio?__trackId=song.mp3&__index=2" → 2
|
|
123
|
+
*/
|
|
124
|
+
extractIndex(path) {
|
|
125
|
+
if (!this.isContextual(path)) {
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
const raw = this.extractParam(path, this.CONTEXTUAL_INDEX_PARAM);
|
|
129
|
+
if (raw === undefined || !/^\d+$/.test(raw)) {
|
|
130
|
+
return undefined;
|
|
131
|
+
}
|
|
132
|
+
return Number.parseInt(raw, 10);
|
|
133
|
+
},
|
|
134
|
+
/**
|
|
135
|
+
* Extracts a single query parameter, handling both full URLs and paths,
|
|
136
|
+
* with a regex fallback for input the URL parser rejects.
|
|
137
|
+
*/
|
|
138
|
+
extractParam(path, param) {
|
|
93
139
|
try {
|
|
94
|
-
// Parse the URL - handle both full URLs and paths
|
|
95
140
|
const isFullUrl = path.startsWith('http://') || path.startsWith('https://');
|
|
96
141
|
const urlObj = new URL(path, isFullUrl ? undefined : 'http://placeholder');
|
|
97
|
-
return urlObj.searchParams.get(
|
|
142
|
+
return urlObj.searchParams.get(param) ?? undefined;
|
|
98
143
|
} catch {
|
|
99
144
|
// Fallback: regex extraction
|
|
100
|
-
const match = path.match(new RegExp(`[?&]${
|
|
145
|
+
const match = path.match(new RegExp(`[?&]${param}=([^&]*)`));
|
|
101
146
|
return match?.[1] ? decodeURIComponent(match[1]) : undefined;
|
|
102
147
|
}
|
|
103
148
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["BrowserPathHelper","SEARCH_PATH_PREFIX","CONTEXTUAL_TRACK_PARAM","createSearchPath","query","encodedQuery","encodeURIComponent","isContextual","path","includes","stripTrackId","url","isFullUrl","startsWith","urlObj","URL","undefined","searchParams","delete","toString","search","pathname","paramPattern","RegExp","result","replace","extractTrackId","get","match","decodeURIComponent","buildUrl","baseUrl","normalizedBase","normalizedPath"],"sourceRoot":"../../../../src","sources":["web/util/BrowserPathHelper.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMA,iBAAiB,GAAG;EAC/B;EACAC,kBAAkB,EAAE,WAAW;EAE/B;EACAC,sBAAsB,EAAE,WAAW;EAEnC;AACF;AACA;EACEC,gBAAgBA,CAACC,KAAa,EAAU;IACtC,MAAMC,YAAY,GAAGC,kBAAkB,CAACF,KAAK,CAAC;IAC9C,OAAO,GAAG,IAAI,
|
|
1
|
+
{"version":3,"names":["BrowserPathHelper","SEARCH_PATH_PREFIX","CONTEXTUAL_TRACK_PARAM","CONTEXTUAL_INDEX_PARAM","createSearchPath","query","encodedQuery","encodeURIComponent","isContextual","path","includes","stripTrackId","url","isFullUrl","startsWith","urlObj","URL","undefined","searchParams","delete","toString","search","pathname","paramPattern","RegExp","result","replace","build","parentPath","trackId","index","separator","indexParam","extractTrackId","extractParam","extractIndex","raw","test","Number","parseInt","param","get","match","decodeURIComponent","buildUrl","baseUrl","normalizedBase","normalizedPath"],"sourceRoot":"../../../../src","sources":["web/util/BrowserPathHelper.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"commonjs"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AudioBrowser.d.ts","sourceRoot":"","sources":["../../../src/AudioBrowser.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AudioBrowser.d.ts","sourceRoot":"","sources":["../../../src/AudioBrowser.ts"],"names":[],"mappings":"AACA,cAAc,YAAY,CAAA;AAC1B,cAAc,SAAS,CAAA;AACvB,cAAc,0BAA0B,CAAA;AACxC,cAAc,kBAAkB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-config.d.ts","sourceRoot":"","sources":["../../../../src/features/browser-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,oBAAoB,EAWrB,MAAM,UAAU,CAAA;AACjB,OAAO,KAAK,EACV,0BAA0B,EAE3B,MAAM,yBAAyB,CAAA;
|
|
1
|
+
{"version":3,"file":"browser-config.d.ts","sourceRoot":"","sources":["../../../../src/features/browser-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,oBAAoB,EAWrB,MAAM,UAAU,CAAA;AACjB,OAAO,KAAK,EACV,0BAA0B,EAE3B,MAAM,yBAAyB,CAAA;AA2KhC,eAAO,MAAM,iBAAiB,eAAe,CAAA;AAqC7C;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,oBAAoB,GAC3B,IAAI,CAuCN;AAED,wBAAgB,cAAc,CAC5B,MAAM,EAAE,oBAAoB,GAC3B,0BAA0B,CAqB5B"}
|
|
@@ -33,8 +33,8 @@ import { NativeUpdatedValue } from '../utils/NativeUpdatedValue';
|
|
|
33
33
|
* }
|
|
34
34
|
* },
|
|
35
35
|
* tabs: [
|
|
36
|
-
* { title: 'Home',
|
|
37
|
-
* { title: 'Search',
|
|
36
|
+
* { title: 'Home', path: '/' },
|
|
37
|
+
* { title: 'Search', path: '/search' }
|
|
38
38
|
* ]
|
|
39
39
|
* })
|
|
40
40
|
* ```
|
|
@@ -92,8 +92,16 @@ export declare function hasSearch(): boolean;
|
|
|
92
92
|
/**
|
|
93
93
|
* Searches for tracks using the configured search source.
|
|
94
94
|
*
|
|
95
|
+
* Resolves `[]` only when the source found nothing; a failed search rejects,
|
|
96
|
+
* so a caller can tell "no results" from "the request failed". The rejection's
|
|
97
|
+
* message describes the failure — native platforms reject with the underlying
|
|
98
|
+
* throwable and JS sees only its message. On web the `Error` also carries a
|
|
99
|
+
* `code`, the {@link NavigationErrorType} the browse path reports as a
|
|
100
|
+
* {@link NavigationError} (`'http-error'`, `'network-error'`).
|
|
101
|
+
*
|
|
95
102
|
* @param query - The search query string
|
|
96
103
|
* @returns Promise resolving to an array of matching tracks
|
|
104
|
+
* @throws When the search source or its request fails
|
|
97
105
|
*
|
|
98
106
|
* @see {@link configureBrowser}
|
|
99
107
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../../../src/features/browser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,UAAU,CAAA;AAE1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAA;AAUhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,oBAAoB,GAAG,IAAI,CAO1E;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,IAAI,oBAAoB,GAAG,SAAS,CAE1E;AAED,wBAAgB,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,KAAK,QAMnD;AAED,wBAAgB,OAAO,uBAEtB;AAED,eAAO,MAAM,aAAa,wCAEzB,CAAA;AAED,wBAAgB,OAAO,IAAI,MAAM,GAAG,SAAS,CAE5C;AAED,wBAAgB,UAAU,IAAI,aAAa,GAAG,SAAS,CAEtD;AAED,eAAO,MAAM,gBAAgB,+CAEmB,CAAA;AAEhD,wBAAgB,UAAU,IAAI,aAAa,GAAG,SAAS,CAEtD;AACD,wBAAgB,OAAO,IAAI,KAAK,EAAE,GAAG,SAAS,CAE7C;AAED,eAAO,MAAM,aAAa,yCAEzB,CAAA;AAED,wBAAgB,OAAO,IAAI,KAAK,EAAE,GAAG,SAAS,CAE7C;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,oBAAoB,SAAU,MAAM,KAAG,IAEnD,CAAA;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,oBAAoB,QAAO,IAEvC,CAAA;AAED;;GAEG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAInC;AAED
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../../../src/features/browser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,UAAU,CAAA;AAE1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAA;AAUhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,oBAAoB,GAAG,IAAI,CAO1E;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,IAAI,oBAAoB,GAAG,SAAS,CAE1E;AAED,wBAAgB,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,KAAK,QAMnD;AAED,wBAAgB,OAAO,uBAEtB;AAED,eAAO,MAAM,aAAa,wCAEzB,CAAA;AAED,wBAAgB,OAAO,IAAI,MAAM,GAAG,SAAS,CAE5C;AAED,wBAAgB,UAAU,IAAI,aAAa,GAAG,SAAS,CAEtD;AAED,eAAO,MAAM,gBAAgB,+CAEmB,CAAA;AAEhD,wBAAgB,UAAU,IAAI,aAAa,GAAG,SAAS,CAEtD;AACD,wBAAgB,OAAO,IAAI,KAAK,EAAE,GAAG,SAAS,CAE7C;AAED,eAAO,MAAM,aAAa,yCAEzB,CAAA;AAED,wBAAgB,OAAO,IAAI,KAAK,EAAE,GAAG,SAAS,CAE7C;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,oBAAoB,SAAU,MAAM,KAAG,IAEnD,CAAA;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,oBAAoB,QAAO,IAEvC,CAAA;AAED;;GAEG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAInC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAE5D"}
|
|
@@ -9,7 +9,7 @@ export declare function isCarConnected(): boolean;
|
|
|
9
9
|
* Subscribes to car connection changes (CarPlay on iOS, Android Auto /
|
|
10
10
|
* Android Automotive on Android). Never fires on web.
|
|
11
11
|
* @param callback - Called with the new connection state
|
|
12
|
-
* @returns
|
|
12
|
+
* @returns An emitter — subscribe with `addListener(callback)`, which returns a cleanup function
|
|
13
13
|
*/
|
|
14
14
|
export declare const onCarConnectedChanged: NativeUpdatedValue<boolean>;
|
|
15
15
|
/**
|
|
@@ -24,7 +24,7 @@ export declare function setEqualizerLevels(levels: number[]): void;
|
|
|
24
24
|
/**
|
|
25
25
|
* Subscribes to equalizer settings changes (Android only).
|
|
26
26
|
* @param callback - Called when equalizer settings change
|
|
27
|
-
* @returns
|
|
27
|
+
* @returns An emitter — subscribe with `addListener(callback)`, which returns a cleanup function
|
|
28
28
|
*/
|
|
29
29
|
export declare const onEqualizerChanged: NativeUpdatedValue<EqualizerSettings>;
|
|
30
30
|
/**
|
|
@@ -101,7 +101,7 @@ export declare function getPlaybackError(): PlaybackError | undefined;
|
|
|
101
101
|
/**
|
|
102
102
|
* Subscribes to playback error events.
|
|
103
103
|
* @param callback - Called when a playback error occurs
|
|
104
|
-
* @returns
|
|
104
|
+
* @returns An emitter — subscribe with `addListener(callback)`, which returns a cleanup function
|
|
105
105
|
*/
|
|
106
106
|
export declare const onPlaybackError: NativeUpdatedValue<PlaybackErrorEvent>;
|
|
107
107
|
/**
|
|
@@ -117,7 +117,7 @@ export declare function getNavigationError(): NavigationError | undefined;
|
|
|
117
117
|
/**
|
|
118
118
|
* Subscribes to navigation error events.
|
|
119
119
|
* @param callback - Called when a navigation error occurs
|
|
120
|
-
* @returns
|
|
120
|
+
* @returns An emitter — subscribe with `addListener(callback)`, which returns a cleanup function
|
|
121
121
|
*/
|
|
122
122
|
export declare const onNavigationError: NativeUpdatedValue<NavigationErrorEvent>;
|
|
123
123
|
/**
|
|
@@ -136,7 +136,7 @@ export declare function getFormattedNavigationError(): FormattedNavigationError
|
|
|
136
136
|
/**
|
|
137
137
|
* Subscribes to formatted navigation error changes.
|
|
138
138
|
* @param callback - Called when the formatted navigation error changes
|
|
139
|
-
* @returns
|
|
139
|
+
* @returns An emitter — subscribe with `addListener(callback)`, which returns a cleanup function
|
|
140
140
|
*/
|
|
141
141
|
export declare const onFormattedNavigationError: NativeUpdatedValue<FormattedNavigationError | undefined>;
|
|
142
142
|
/**
|
|
@@ -27,26 +27,29 @@ export declare function setActiveTrackFavorited(favorited: boolean): void;
|
|
|
27
27
|
*/
|
|
28
28
|
export declare function toggleActiveTrackFavorited(): void;
|
|
29
29
|
/**
|
|
30
|
-
* Sets the list of favorited track
|
|
30
|
+
* Sets the list of favorited track identifiers.
|
|
31
31
|
*
|
|
32
32
|
* This syncs your app's favorites with the native favorites cache, enabling
|
|
33
33
|
* the heart button in media controllers (notification, Android Auto, CarPlay)
|
|
34
34
|
* to show the correct state.
|
|
35
35
|
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
36
|
+
* Each identifier is matched **exactly** against a track's *identity* — its
|
|
37
|
+
* `id` when set, falling back to `src`. Store favorites as the same stable
|
|
38
|
+
* identifier you put in `Track.id` (or as the full `src` for id-less tracks).
|
|
39
39
|
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
40
|
+
* A track whose response already carries `favorited` keeps that value on
|
|
41
|
+
* display surfaces — a caller-set flag wins over cache hydration. The cache
|
|
42
|
+
* itself is written only by this call and by heart toggles
|
|
43
|
+
* (`setActiveTrackFavorited()` / media-controller taps), so you only need to
|
|
44
|
+
* call this on app launch — and again whenever the collection changes outside
|
|
45
|
+
* the player (a sync from another device, say).
|
|
43
46
|
*
|
|
44
|
-
* @param favorites - Array of favorited track `src`
|
|
47
|
+
* @param favorites - Array of favorited track identities (`id`, or `src` for id-less tracks)
|
|
45
48
|
*
|
|
46
49
|
* @example
|
|
47
50
|
* ```ts
|
|
48
|
-
* const
|
|
49
|
-
* setFavorites(
|
|
51
|
+
* const favoriteIds = await loadFavoritesFromStorage()
|
|
52
|
+
* setFavorites(favoriteIds)
|
|
50
53
|
* ```
|
|
51
54
|
*/
|
|
52
55
|
export declare function setFavorites(favorites: string[]): void;
|
|
@@ -66,7 +69,7 @@ export interface FavoriteChangedEvent {
|
|
|
66
69
|
* The native side has already updated the track's favorite state and UI.
|
|
67
70
|
*
|
|
68
71
|
* @param callback - Called with the track and its new favorite state
|
|
69
|
-
* @returns
|
|
72
|
+
* @returns An emitter — subscribe with `addListener(callback)`, which returns a cleanup function
|
|
70
73
|
*
|
|
71
74
|
* @example
|
|
72
75
|
* ```ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"favorites.d.ts","sourceRoot":"","sources":["../../../../src/features/favorites.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAA;AAErC,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAA;AAIhE;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CAEhE;AAED;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,IAAI,IAAI,CAEjD;AAED
|
|
1
|
+
{"version":3,"file":"favorites.d.ts","sourceRoot":"","sources":["../../../../src/features/favorites.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAA;AAErC,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAA;AAIhE;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CAEhE;AAED;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,IAAI,IAAI,CAEjD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,CAEtD;AAID;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,8CAA8C;IAC9C,KAAK,EAAE,KAAK,CAAA;IACZ,8BAA8B;IAC9B,SAAS,EAAE,OAAO,CAAA;CACnB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,iBAAiB,0CAG3B,CAAA"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { SearchParams } from '../types/browser';
|
|
2
|
+
import { LazyNativeEmitter } from '../utils/LazyNativeEmitter';
|
|
2
3
|
/** Discriminant for gate requests and events. */
|
|
3
4
|
export type GateReason = 'browse' | 'search';
|
|
4
5
|
/**
|
|
@@ -57,21 +58,36 @@ export type GateResolver = (request: GateRequest) => Gate | boolean;
|
|
|
57
58
|
* some surfaces (CarPlay) any gate change pops pushed navigation back to root,
|
|
58
59
|
* so a page the user had drilled into is reset to the tab root. Set the gate
|
|
59
60
|
* before the car connects and it'll be there the moment it does.
|
|
61
|
+
*
|
|
62
|
+
* @platform ios android
|
|
63
|
+
* A no-op on web, which has no CarPlay or Android Auto surfaces for the gate to
|
|
64
|
+
* cover. Nothing is lost: the gate never covered in-app browse UI on any
|
|
65
|
+
* platform — that stays yours to gate.
|
|
60
66
|
*/
|
|
61
67
|
export declare function setGate(gate: Gate, resolve?: GateResolver): void;
|
|
62
68
|
/**
|
|
63
69
|
* Raises the gate with a resolver only (no default chrome).
|
|
64
70
|
* The resolver must return a {@link Gate} or `true` for gated requests;
|
|
65
71
|
* native uses the built-in fallback chrome when `true` and no default is set.
|
|
72
|
+
*
|
|
73
|
+
* @platform ios android
|
|
74
|
+
* A no-op on web — the resolver is never consulted there.
|
|
66
75
|
*/
|
|
67
76
|
export declare function setGate(resolve: GateResolver): void;
|
|
68
77
|
/**
|
|
69
78
|
* Drops the gate — the real content comes back, and the current tab is kept.
|
|
79
|
+
*
|
|
80
|
+
* @platform ios android
|
|
81
|
+
* A no-op on web, where no gate was ever raised.
|
|
70
82
|
*/
|
|
71
83
|
export declare function clearGate(): void;
|
|
72
84
|
/**
|
|
73
85
|
* Subscribes to gate events (fired when a request is gated).
|
|
74
|
-
*
|
|
86
|
+
*
|
|
87
|
+
* @platform ios android
|
|
88
|
+
* Never fires on web — there are no gated serves to report.
|
|
89
|
+
*
|
|
90
|
+
* @returns An emitter — subscribe with `addListener(callback)`, which returns a cleanup function
|
|
75
91
|
*/
|
|
76
|
-
export declare const onGate:
|
|
92
|
+
export declare const onGate: LazyNativeEmitter<GateEvent>;
|
|
77
93
|
//# sourceMappingURL=gate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../../../../src/features/gate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../../../../src/features/gate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAEpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAI9D,iDAAiD;AACjD,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAmB5C;;;;;;;GAOG;AACH,MAAM,MAAM,SAAS,GAAG;IAAE,MAAM,EAAE,UAAU,CAAA;CAAE,CAAA;AAI9C;;;;;;;;;GASG;AACH,MAAM,MAAM,IAAI,GAAG;IACjB,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAQD;;;;GAIG;AACH,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,CAAA;AAE5C;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,GAAG,OAAO,CAAA;AAoCnE;;;;;;;;;;;;GAYG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI,CAAA;AACjE;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAAA;AAWpD;;;;;GAKG;AACH,wBAAgB,SAAS,IAAI,IAAI,CAGhC;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM,8BAElB,CAAA"}
|