react-native-audio-browser 0.1.1 → 0.2.0-next.2
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/AudioBrowser.podspec +1 -1
- package/README.md +180 -2
- package/android/build.gradle +10 -0
- package/android/gradle.properties +1 -1
- package/android/src/main/AndroidManifest.xml +15 -0
- package/android/src/main/java/com/audiobrowser/AudioBrowser.kt +401 -141
- package/android/src/main/java/com/audiobrowser/Callbacks.kt +4 -6
- package/android/src/main/java/com/audiobrowser/Service.kt +67 -18
- package/android/src/main/java/com/audiobrowser/browser/ArtworkResolutionRegistry.kt +37 -0
- package/android/src/main/java/com/audiobrowser/browser/BrowseArtworkRegistry.kt +34 -0
- package/android/src/main/java/com/audiobrowser/browser/BrowserManager.kt +443 -178
- package/android/src/main/java/com/audiobrowser/browser/BrowserUrlResolution.kt +300 -0
- package/android/src/main/java/com/audiobrowser/browser/JsonArtwork.kt +79 -0
- package/android/src/main/java/com/audiobrowser/browser/JsonModels.kt +41 -4
- package/android/src/main/java/com/audiobrowser/browser/SectionScope.kt +43 -0
- package/android/src/main/java/com/audiobrowser/browser/TrackLoadHandler.kt +4 -4
- package/android/src/main/java/com/audiobrowser/extension/ResolvedTrackExt.kt +35 -0
- package/android/src/main/java/com/audiobrowser/http/RequestConfigBuilder.kt +109 -97
- package/android/src/main/java/com/audiobrowser/model/PlaybackMetadata.kt +6 -10
- package/android/src/main/java/com/audiobrowser/model/PlayerSetupOptions.kt +40 -8
- package/android/src/main/java/com/audiobrowser/model/PlayerUpdateOptions.kt +31 -37
- package/android/src/main/java/com/audiobrowser/player/AutomaticBufferManager.kt +4 -1
- package/android/src/main/java/com/audiobrowser/player/CapabilityControls.kt +119 -0
- package/android/src/main/java/com/audiobrowser/player/DynamicLoadControl.kt +18 -1
- package/android/src/main/java/com/audiobrowser/player/EqualizerController.kt +153 -0
- package/android/src/main/java/com/audiobrowser/player/InterceptingPlayer.kt +141 -0
- package/android/src/main/java/com/audiobrowser/player/MediaFactory.kt +15 -3
- package/android/src/main/java/com/audiobrowser/player/MediaSessionCallback.kt +415 -131
- package/android/src/main/java/com/audiobrowser/player/MediaSessionCommandManager.kt +154 -276
- package/android/src/main/java/com/audiobrowser/player/NowPlayingUpdater.kt +348 -0
- package/android/src/main/java/com/audiobrowser/player/PlaybackErrorClassifier.kt +129 -0
- package/android/src/main/java/com/audiobrowser/player/PlaybackStateMachine.kt +85 -0
- package/android/src/main/java/com/audiobrowser/player/PlaybackStateStore.kt +27 -5
- package/android/src/main/java/com/audiobrowser/player/PlaybackTimer.kt +56 -0
- package/android/src/main/java/com/audiobrowser/player/Player.kt +452 -576
- package/android/src/main/java/com/audiobrowser/player/PlayerCapabilitiesExt.kt +20 -0
- package/android/src/main/java/com/audiobrowser/player/PlayerEngineFactory.kt +130 -0
- package/android/src/main/java/com/audiobrowser/player/PlayerListener.kt +190 -67
- package/android/src/main/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicy.kt +117 -53
- package/android/src/main/java/com/audiobrowser/player/SleepTimer.kt +37 -3
- package/android/src/main/java/com/audiobrowser/player/SleepTimerManager.kt +80 -0
- package/android/src/main/java/com/audiobrowser/player/StuckRecoveryPolicy.kt +50 -0
- package/android/src/main/java/com/audiobrowser/player/TransformingDataSource.kt +85 -40
- package/android/src/main/java/com/audiobrowser/player/VolumeFader.kt +81 -0
- package/android/src/main/java/com/audiobrowser/tls/AiaCertChaser.kt +141 -0
- package/android/src/main/java/com/audiobrowser/tls/AiaChasingTrustManager.kt +37 -0
- package/android/src/main/java/com/audiobrowser/tls/AiaTls.kt +41 -0
- package/android/src/main/java/com/audiobrowser/tls/CachingCertificateFetcher.kt +209 -0
- package/android/src/main/java/com/audiobrowser/util/ArtworkContentProvider.kt +161 -0
- package/android/src/main/java/com/audiobrowser/util/ArtworkUris.kt +28 -0
- package/android/src/main/java/com/audiobrowser/util/ArtworkVariant.kt +26 -0
- package/android/src/main/java/com/audiobrowser/util/BrowserPathHelper.kt +24 -0
- package/android/src/main/java/com/audiobrowser/util/CoilArtworkLoader.kt +49 -0
- package/android/src/main/java/com/audiobrowser/util/CoilArtworkLoaderHolder.kt +36 -0
- package/android/src/main/java/com/audiobrowser/util/CoilBitmapLoader.kt +23 -300
- package/android/src/main/java/com/audiobrowser/util/EqualizerManager.kt +13 -23
- package/android/src/main/java/com/audiobrowser/util/MediaExtrasBuilder.kt +2 -2
- package/android/src/main/java/com/audiobrowser/util/MetadataAdapter.kt +4 -3
- package/android/src/main/java/com/audiobrowser/util/OutputMonitor.kt +211 -0
- package/android/src/main/java/com/audiobrowser/util/OutputSwitcher.kt +58 -0
- package/android/src/main/java/com/audiobrowser/util/PlayingStateFactory.kt +2 -1
- package/android/src/main/java/com/audiobrowser/util/RatingFavorites.kt +14 -0
- package/android/src/main/java/com/audiobrowser/util/SvgArtworkRenderer.kt +6 -111
- package/android/src/main/java/com/audiobrowser/util/SystemVolumeMonitor.kt +22 -8
- package/android/src/main/java/com/audiobrowser/util/TrackFactory.kt +111 -80
- package/android/src/main/res/values/strings.xml +4 -0
- package/android/src/test/java/com/audiobrowser/TestFixtures.kt +166 -0
- package/android/src/test/java/com/audiobrowser/browser/ArtworkResolutionRegistryTest.kt +46 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowseArtworkRegistryTest.kt +39 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerBuildApiRequestTest.kt +114 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerLayerResolutionTest.kt +141 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerTest.kt +4 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowserUrlResolutionTest.kt +177 -0
- package/android/src/test/java/com/audiobrowser/browser/JsonArtworkTest.kt +54 -0
- package/android/src/test/java/com/audiobrowser/browser/SectionScopeTest.kt +96 -0
- package/android/src/test/java/com/audiobrowser/browser/SimpleRouterTest.kt +1 -2
- package/android/src/test/java/com/audiobrowser/http/RequestConfigBuilderTest.kt +72 -0
- package/android/src/test/java/com/audiobrowser/player/CapabilityControlsTest.kt +159 -0
- package/android/src/test/java/com/audiobrowser/player/DynamicLoadControlTest.kt +56 -0
- package/android/src/test/java/com/audiobrowser/player/EqualizerControllerTest.kt +216 -0
- package/android/src/test/java/com/audiobrowser/player/NowPlayingUpdaterTest.kt +442 -0
- package/android/src/test/java/com/audiobrowser/player/PlaybackErrorClassifierTest.kt +191 -0
- package/android/src/test/java/com/audiobrowser/player/PlaybackStateMachineTest.kt +198 -0
- package/android/src/test/java/com/audiobrowser/player/PlaybackTimerTest.kt +137 -0
- package/android/src/test/java/com/audiobrowser/player/PlayerEngineFactoryTest.kt +36 -0
- package/android/src/test/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicyTest.kt +268 -0
- package/android/src/test/java/com/audiobrowser/player/SessionErrorMaskTest.kt +68 -0
- package/android/src/test/java/com/audiobrowser/player/StuckRecoveryPolicyTest.kt +40 -0
- package/android/src/test/java/com/audiobrowser/player/TransformingDataSourceTest.kt +193 -0
- package/android/src/test/java/com/audiobrowser/tls/AiaCertChaserTest.kt +107 -0
- package/android/src/test/java/com/audiobrowser/tls/AiaChasingTrustManagerTest.kt +73 -0
- package/android/src/test/java/com/audiobrowser/tls/CachingCertificateFetcherTest.kt +75 -0
- package/android/src/test/java/com/audiobrowser/tls/CertFixtures.kt +18 -0
- package/android/src/test/java/com/audiobrowser/util/ArtworkContentProviderTest.kt +163 -0
- package/android/src/test/java/com/audiobrowser/util/ArtworkUrisTest.kt +34 -0
- package/android/src/test/java/com/audiobrowser/util/BrowserPathHelperTest.kt +28 -0
- package/android/src/test/java/com/audiobrowser/util/CoilArtworkLoaderHolderTest.kt +53 -0
- package/android/src/test/java/com/audiobrowser/util/CoilArtworkLoaderTest.kt +58 -0
- package/android/src/test/java/com/audiobrowser/util/FakeImageLoader.kt +57 -0
- package/android/src/test/java/com/audiobrowser/util/PlayingStateFactoryTest.kt +40 -0
- package/android/src/test/java/com/audiobrowser/util/RatingFavoritesTest.kt +34 -0
- package/android/src/test/java/com/audiobrowser/util/TrackFactoryBrowseTest.kt +50 -0
- package/android/src/test/java/com/audiobrowser/util/TrackFactoryMediaIdTest.kt +63 -0
- package/android/src/test/java/com/audiobrowser/util/TrackFactoryRatingTest.kt +35 -0
- package/android/src/test/resources/certs/isrg-root-x1.pem +31 -0
- package/android/src/test/resources/certs/letsencrypt-r13.der +0 -0
- package/android/src/test/resources/certs/letsencrypt-r13.pem +29 -0
- package/android/src/test/resources/certs/stationplaylist-leaf.pem +34 -0
- package/ios/Browser/BrowserConfig.swift +41 -11
- package/ios/Browser/BrowserManager+URLResolution.swift +213 -93
- package/ios/Browser/BrowserManager.swift +303 -110
- package/ios/Browser/BrowserPathHelper.swift +32 -3
- package/ios/Browser/JsonModels.swift +287 -66
- package/ios/Browser/MediaResolveComposer.swift +114 -0
- package/ios/Browser/SearchDrillIn.swift +44 -0
- package/ios/Browser/SectionScope.swift +35 -0
- package/ios/Browser/TabBarEntries.swift +15 -0
- package/ios/CarPlay/CPInterfaceController+Safe.swift +126 -0
- package/ios/CarPlay/CarPlayArtworkResolver.swift +6 -6
- package/ios/CarPlay/CarPlayController.swift +739 -149
- package/ios/CarPlay/CarPlayImageLoader.swift +57 -8
- package/ios/CarPlay/CarPlayListItemFactory.swift +44 -35
- package/ios/CarPlay/CarPlayNowPlayingManager.swift +180 -36
- package/ios/CarPlay/ImageRowItem+CarPlay.swift +19 -0
- package/ios/CarPlay/RNABAudioBrowser.h +15 -10
- package/ios/CarPlay/RNABAudioBrowser.m +15 -14
- package/ios/CarPlay/RNABCarPlaySceneDelegate.m +2 -0
- package/ios/CarPlay/RNABMediaAddHandler.swift +75 -0
- package/ios/CarPlay/RNABMediaAffinityHandler.swift +69 -0
- package/ios/CarPlay/RNABMediaIntentHandler.swift +53 -43
- package/ios/Extension/Capability+RemoteCommand.swift +7 -9
- package/ios/Extension/ChapterMetadata+AVFoundation.swift +1 -1
- package/ios/Extension/NavigationError+Conversion.swift +8 -1
- package/ios/Extension/PlayerCapabilities+Favorite.swift +20 -0
- package/ios/Extension/RequestConfig+Copying.swift +31 -0
- package/ios/Extension/ResolvedTrack+Copying.swift +10 -4
- package/ios/Extension/TimedMetadata+AVFoundation.swift +1 -1
- package/ios/Extension/Track+AVPlayer.swift +4 -4
- package/ios/Extension/Track+Copying.swift +9 -3
- package/ios/Extension/TrackMetadata+AVFoundation.swift +1 -1
- package/ios/Extension/Variant+Artwork.swift +49 -0
- package/ios/HybridAudioBrowser.swift +750 -173
- package/ios/Model/NitroTypeStubs.swift +299 -224
- package/ios/Model/PlayerUpdateOptions.swift +23 -23
- package/ios/Model/RemoteCommand.swift +6 -6
- package/ios/Model/TrackPlayerError.swift +82 -18
- package/ios/NowPlayingInfo/NowPlayingInfoController.swift +99 -121
- package/ios/NowPlayingInfo/SilentAudioPrimer.swift +73 -0
- package/ios/Observer/PlayerItemNotificationObserver.swift +45 -5
- package/ios/Observer/PlayerItemPropertyObserver.swift +27 -4
- package/ios/Observer/PlayerTimeObserver.swift +3 -53
- package/ios/Option/SessionCategories.swift +33 -11
- package/ios/Player/AirPlayStallJudgement.swift +25 -0
- package/ios/Player/EndOfTrackJudgement.swift +32 -0
- package/ios/Player/LoadSeekCoordinator.swift +16 -1
- package/ios/Player/MediaIntentCriteria.swift +139 -0
- package/ios/Player/MediaLoader.swift +31 -11
- package/ios/Player/NowPlayingUpdater.swift +119 -26
- package/ios/Player/PersistedPlaybackState.swift +11 -0
- package/ios/Player/PlaybackCoordinator.swift +285 -51
- package/ios/Player/PlaybackCoordinatorCallbacks.swift +6 -1
- package/ios/Player/PlaybackEffectHandler.swift +19 -9
- package/ios/Player/PlaybackErrorHandler.swift +97 -13
- package/ios/Player/PlaybackStateMachine.swift +18 -13
- package/ios/Player/PlaybackStateStore.swift +27 -0
- package/ios/Player/PlaybackTimer.swift +61 -0
- package/ios/Player/PlayingStateManager.swift +3 -2
- package/ios/Player/QueueManager.swift +67 -61
- package/ios/Player/RetryManager.swift +97 -21
- package/ios/Player/SleepTimerHandling.swift +8 -0
- package/ios/Player/SleepTimerManager.swift +72 -11
- package/ios/Player/VolumeFader.swift +77 -0
- package/ios/RemoteCommand/RemoteCommandController.swift +31 -15
- package/ios/Tests/AirPlayStallJudgementTests.swift +52 -0
- package/ios/Tests/BrowserPathHelperTests.swift +28 -0
- package/ios/Tests/CarPlayArtworkResolverTests.swift +39 -39
- package/ios/Tests/ChapterMetadataAVFoundationTests.swift +2 -2
- package/ios/Tests/EndOfTrackJudgementTests.swift +35 -0
- package/ios/Tests/JsonModelsTests.swift +58 -0
- package/ios/Tests/LoadSeekCoordinatorTests.swift +38 -7
- package/ios/Tests/MediaIntentCriteriaTests.swift +170 -0
- package/ios/Tests/MediaLoaderAssetOptionsTests.swift +46 -0
- package/ios/Tests/MediaLoaderTests.swift +32 -20
- package/ios/Tests/MediaResolveTests.swift +126 -0
- package/ios/Tests/OnceValueTests.swift +79 -0
- package/ios/Tests/PlaybackCoordinatorTests.swift +787 -13
- package/ios/Tests/PlaybackErrorHandlerTests.swift +380 -46
- package/ios/Tests/PlaybackStateMachineTests.swift +33 -8
- package/ios/Tests/PlaybackStateStoreTests.swift +48 -0
- package/ios/Tests/PlaybackTimerTests.swift +55 -0
- package/ios/Tests/PlayingStateManagerTests.swift +57 -0
- package/ios/Tests/QueueManagerTests.swift +149 -18
- package/ios/Tests/ResolvedTrackCopyingTests.swift +15 -8
- package/ios/Tests/RetryManagerTests.swift +89 -0
- package/ios/Tests/SearchDrillInTests.swift +63 -0
- package/ios/Tests/SectionScopeTests.swift +82 -0
- package/ios/Tests/SleepTimerManagerTests.swift +107 -0
- package/ios/Tests/Support/ManualSleepTimerScheduler.swift +47 -0
- package/ios/Tests/Support/TestTypes.swift +61 -20
- package/ios/Tests/TabBarEntriesTests.swift +71 -0
- package/ios/Tests/TrackSelectorTests.swift +15 -15
- package/ios/TrackPlayer.swift +380 -58
- package/ios/TrackPlayerCallbacks.swift +0 -6
- package/ios/TrackSelector.swift +5 -5
- package/ios/Util/ArtworkImageFetcher.swift +4 -2
- package/ios/Util/NetworkMonitor.swift +7 -3
- package/ios/Util/OnceValue.swift +34 -0
- package/lib/commonjs/features/browser-config.js +227 -0
- package/lib/commonjs/features/browser-config.js.map +1 -0
- package/lib/commonjs/features/browser.js +59 -158
- package/lib/commonjs/features/browser.js.map +1 -1
- package/lib/commonjs/features/carConnection.js +42 -0
- package/lib/commonjs/features/carConnection.js.map +1 -0
- package/lib/commonjs/features/errors.js +34 -2
- package/lib/commonjs/features/errors.js.map +1 -1
- package/lib/commonjs/features/gate.js +149 -0
- package/lib/commonjs/features/gate.js.map +1 -0
- package/lib/commonjs/features/index.js +22 -0
- package/lib/commonjs/features/index.js.map +1 -1
- package/lib/commonjs/features/metadata.js.map +1 -1
- package/lib/commonjs/features/nowPlaying.js +35 -0
- package/lib/commonjs/features/nowPlaying.js.map +1 -1
- package/lib/commonjs/features/output.js +37 -23
- package/lib/commonjs/features/output.js.map +1 -1
- package/lib/commonjs/features/playback/controls.js +9 -0
- package/lib/commonjs/features/playback/controls.js.map +1 -1
- package/lib/commonjs/features/playback/index.js +11 -0
- package/lib/commonjs/features/playback/index.js.map +1 -1
- package/lib/commonjs/features/playback/progress.js +28 -12
- package/lib/commonjs/features/playback/progress.js.map +1 -1
- package/lib/commonjs/features/playback/trackPlaybackTime.js +92 -0
- package/lib/commonjs/features/playback/trackPlaybackTime.js.map +1 -0
- package/lib/commonjs/features/playback/volume.js +1 -1
- package/lib/commonjs/features/player/options.js +49 -13
- package/lib/commonjs/features/player/options.js.map +1 -1
- package/lib/commonjs/features/player/setup.js +249 -3
- package/lib/commonjs/features/player/setup.js.map +1 -1
- package/lib/commonjs/features/queue/queue.js +10 -3
- package/lib/commonjs/features/queue/queue.js.map +1 -1
- package/lib/commonjs/features/remoteControls.js +1 -12
- package/lib/commonjs/features/remoteControls.js.map +1 -1
- package/lib/commonjs/features/sleepTimer.js +9 -4
- package/lib/commonjs/features/sleepTimer.js.map +1 -1
- package/lib/commonjs/native.js +5 -0
- package/lib/commonjs/native.js.map +1 -1
- package/lib/commonjs/native.web.js +4 -1
- package/lib/commonjs/native.web.js.map +1 -1
- package/lib/commonjs/utils/LazyNativeEmitter.js +0 -3
- package/lib/commonjs/utils/LazyNativeEmitter.js.map +1 -1
- package/lib/commonjs/utils/NativeUpdatedValue.js +0 -3
- package/lib/commonjs/utils/NativeUpdatedValue.js.map +1 -1
- package/lib/commonjs/utils/artwork.js +31 -0
- package/lib/commonjs/utils/artwork.js.map +1 -0
- package/lib/commonjs/web/NativeAudioBrowser.js +301 -124
- package/lib/commonjs/web/NativeAudioBrowser.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js +71 -0
- package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/PlaybackTimer.js +34 -0
- package/lib/commonjs/web/TrackPlayer/PlaybackTimer.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/Player.js +90 -26
- package/lib/commonjs/web/TrackPlayer/Player.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/PlayingStateFactory.js +21 -0
- package/lib/commonjs/web/TrackPlayer/PlayingStateFactory.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/QueueManager.js +273 -0
- package/lib/commonjs/web/TrackPlayer/QueueManager.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/QueuePlayer.js +158 -0
- package/lib/commonjs/web/TrackPlayer/QueuePlayer.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/RepeatMode.js +1 -1
- package/lib/commonjs/web/TrackPlayer/RepeatMode.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/SleepTimer.js +34 -3
- package/lib/commonjs/web/TrackPlayer/SleepTimer.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/VolumeFader.js +75 -0
- package/lib/commonjs/web/TrackPlayer/VolumeFader.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/index.js +13 -5
- package/lib/commonjs/web/TrackPlayer/index.js.map +1 -1
- package/lib/commonjs/web/browser/BrowserManager.js +176 -50
- package/lib/commonjs/web/browser/BrowserManager.js.map +1 -1
- package/lib/commonjs/web/browser/NavigationErrorManager.js +3 -1
- package/lib/commonjs/web/browser/NavigationErrorManager.js.map +1 -1
- package/lib/commonjs/web/browser/SearchManager.js +11 -9
- package/lib/commonjs/web/browser/SearchManager.js.map +1 -1
- package/lib/commonjs/web/browser/assertBrowsePageShape.js +22 -0
- package/lib/commonjs/web/browser/assertBrowsePageShape.js.map +1 -0
- package/lib/commonjs/web/browser/classifyTrackNavigation.js +41 -0
- package/lib/commonjs/web/browser/classifyTrackNavigation.js.map +1 -0
- package/lib/commonjs/web/browser/parseSearchResponse.js +20 -0
- package/lib/commonjs/web/browser/parseSearchResponse.js.map +1 -0
- package/lib/commonjs/web/http/HttpClient.js +4 -23
- package/lib/commonjs/web/http/HttpClient.js.map +1 -1
- package/lib/commonjs/web/http/RequestConfigBuilder.js +107 -58
- package/lib/commonjs/web/http/RequestConfigBuilder.js.map +1 -1
- package/lib/commonjs/web/playbackErrorKind.js +57 -0
- package/lib/commonjs/web/playbackErrorKind.js.map +1 -0
- package/lib/commonjs/web/player/MediaSessionManager.js +121 -0
- package/lib/commonjs/web/player/MediaSessionManager.js.map +1 -0
- package/lib/commonjs/web/player/NowPlayingManager.js +6 -5
- package/lib/commonjs/web/player/NowPlayingManager.js.map +1 -1
- package/lib/commonjs/web/player/OptionsManager.js +9 -17
- package/lib/commonjs/web/player/OptionsManager.js.map +1 -1
- package/lib/commonjs/web/player/RemoteCommandController.js +96 -0
- package/lib/commonjs/web/player/RemoteCommandController.js.map +1 -0
- package/lib/module/features/browser-config.js +221 -0
- package/lib/module/features/browser-config.js.map +1 -0
- package/lib/module/features/browser.js +53 -156
- package/lib/module/features/browser.js.map +1 -1
- package/lib/module/features/carConnection.js +37 -0
- package/lib/module/features/carConnection.js.map +1 -0
- package/lib/module/features/errors.js +34 -2
- package/lib/module/features/errors.js.map +1 -1
- package/lib/module/features/gate.js +144 -0
- package/lib/module/features/gate.js.map +1 -0
- package/lib/module/features/index.js +2 -0
- package/lib/module/features/index.js.map +1 -1
- package/lib/module/features/metadata.js.map +1 -1
- package/lib/module/features/nowPlaying.js +33 -0
- package/lib/module/features/nowPlaying.js.map +1 -1
- package/lib/module/features/output.js +32 -19
- package/lib/module/features/output.js.map +1 -1
- package/lib/module/features/playback/controls.js +8 -0
- package/lib/module/features/playback/controls.js.map +1 -1
- package/lib/module/features/playback/index.js +1 -0
- package/lib/module/features/playback/index.js.map +1 -1
- package/lib/module/features/playback/progress.js +28 -12
- package/lib/module/features/playback/progress.js.map +1 -1
- package/lib/module/features/playback/trackPlaybackTime.js +88 -0
- package/lib/module/features/playback/trackPlaybackTime.js.map +1 -0
- package/lib/module/features/playback/volume.js +1 -1
- package/lib/module/features/player/options.js +48 -13
- package/lib/module/features/player/options.js.map +1 -1
- package/lib/module/features/player/setup.js +249 -3
- package/lib/module/features/player/setup.js.map +1 -1
- package/lib/module/features/queue/queue.js +10 -3
- package/lib/module/features/queue/queue.js.map +1 -1
- package/lib/module/features/remoteControls.js +0 -11
- package/lib/module/features/remoteControls.js.map +1 -1
- package/lib/module/features/sleepTimer.js +9 -4
- package/lib/module/features/sleepTimer.js.map +1 -1
- package/lib/module/native.js +5 -0
- package/lib/module/native.js.map +1 -1
- package/lib/module/native.web.js +4 -1
- package/lib/module/native.web.js.map +1 -1
- package/lib/module/utils/LazyNativeEmitter.js +0 -3
- package/lib/module/utils/LazyNativeEmitter.js.map +1 -1
- package/lib/module/utils/NativeUpdatedValue.js +0 -3
- package/lib/module/utils/NativeUpdatedValue.js.map +1 -1
- package/lib/module/utils/artwork.js +26 -0
- package/lib/module/utils/artwork.js.map +1 -0
- package/lib/module/web/NativeAudioBrowser.js +302 -125
- package/lib/module/web/NativeAudioBrowser.js.map +1 -1
- package/lib/module/web/TrackPlayer/PlaybackStateMachine.js +67 -0
- package/lib/module/web/TrackPlayer/PlaybackStateMachine.js.map +1 -0
- package/lib/module/web/TrackPlayer/PlaybackTimer.js +29 -0
- package/lib/module/web/TrackPlayer/PlaybackTimer.js.map +1 -0
- package/lib/module/web/TrackPlayer/Player.js +90 -26
- package/lib/module/web/TrackPlayer/Player.js.map +1 -1
- package/lib/module/web/TrackPlayer/PlayingStateFactory.js +17 -0
- package/lib/module/web/TrackPlayer/PlayingStateFactory.js.map +1 -0
- package/lib/module/web/TrackPlayer/QueueManager.js +269 -0
- package/lib/module/web/TrackPlayer/QueueManager.js.map +1 -0
- package/lib/module/web/TrackPlayer/QueuePlayer.js +154 -0
- package/lib/module/web/TrackPlayer/QueuePlayer.js.map +1 -0
- package/lib/module/web/TrackPlayer/RepeatMode.js +1 -1
- package/lib/module/web/TrackPlayer/RepeatMode.js.map +1 -1
- package/lib/module/web/TrackPlayer/SleepTimer.js +34 -3
- package/lib/module/web/TrackPlayer/SleepTimer.js.map +1 -1
- package/lib/module/web/TrackPlayer/VolumeFader.js +70 -0
- package/lib/module/web/TrackPlayer/VolumeFader.js.map +1 -0
- package/lib/module/web/TrackPlayer/index.js +2 -1
- package/lib/module/web/TrackPlayer/index.js.map +1 -1
- package/lib/module/web/browser/BrowserManager.js +176 -50
- package/lib/module/web/browser/BrowserManager.js.map +1 -1
- package/lib/module/web/browser/NavigationErrorManager.js +3 -1
- package/lib/module/web/browser/NavigationErrorManager.js.map +1 -1
- package/lib/module/web/browser/SearchManager.js +11 -9
- package/lib/module/web/browser/SearchManager.js.map +1 -1
- package/lib/module/web/browser/assertBrowsePageShape.js +18 -0
- package/lib/module/web/browser/assertBrowsePageShape.js.map +1 -0
- package/lib/module/web/browser/classifyTrackNavigation.js +38 -0
- package/lib/module/web/browser/classifyTrackNavigation.js.map +1 -0
- package/lib/module/web/browser/parseSearchResponse.js +16 -0
- package/lib/module/web/browser/parseSearchResponse.js.map +1 -0
- package/lib/module/web/http/HttpClient.js +4 -23
- package/lib/module/web/http/HttpClient.js.map +1 -1
- package/lib/module/web/http/RequestConfigBuilder.js +107 -58
- package/lib/module/web/http/RequestConfigBuilder.js.map +1 -1
- package/lib/module/web/playbackErrorKind.js +52 -0
- package/lib/module/web/playbackErrorKind.js.map +1 -0
- package/lib/module/web/player/MediaSessionManager.js +116 -0
- package/lib/module/web/player/MediaSessionManager.js.map +1 -0
- package/lib/module/web/player/NowPlayingManager.js +7 -5
- package/lib/module/web/player/NowPlayingManager.js.map +1 -1
- package/lib/module/web/player/OptionsManager.js +9 -17
- package/lib/module/web/player/OptionsManager.js.map +1 -1
- package/lib/module/web/player/RemoteCommandController.js +92 -0
- package/lib/module/web/player/RemoteCommandController.js.map +1 -0
- package/lib/typescript/src/features/browser-config.d.ts +12 -0
- package/lib/typescript/src/features/browser-config.d.ts.map +1 -0
- package/lib/typescript/src/features/browser.d.ts +40 -1
- package/lib/typescript/src/features/browser.d.ts.map +1 -1
- package/lib/typescript/src/features/carConnection.d.ts +20 -0
- package/lib/typescript/src/features/carConnection.d.ts.map +1 -0
- package/lib/typescript/src/features/errors.d.ts +58 -3
- package/lib/typescript/src/features/errors.d.ts.map +1 -1
- package/lib/typescript/src/features/gate.d.ts +77 -0
- package/lib/typescript/src/features/gate.d.ts.map +1 -0
- package/lib/typescript/src/features/index.d.ts +2 -0
- package/lib/typescript/src/features/index.d.ts.map +1 -1
- package/lib/typescript/src/features/metadata.d.ts +6 -4
- package/lib/typescript/src/features/metadata.d.ts.map +1 -1
- package/lib/typescript/src/features/nowPlaying.d.ts +27 -0
- package/lib/typescript/src/features/nowPlaying.d.ts.map +1 -1
- package/lib/typescript/src/features/output.d.ts +28 -18
- package/lib/typescript/src/features/output.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/controls.d.ts +5 -0
- package/lib/typescript/src/features/playback/controls.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/index.d.ts +1 -0
- package/lib/typescript/src/features/playback/index.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/progress.d.ts +3 -0
- package/lib/typescript/src/features/playback/progress.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts +34 -0
- package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts.map +1 -0
- package/lib/typescript/src/features/playback/volume.d.ts +1 -1
- package/lib/typescript/src/features/player/options.d.ts +92 -93
- package/lib/typescript/src/features/player/options.d.ts.map +1 -1
- package/lib/typescript/src/features/player/setup.d.ts +206 -167
- package/lib/typescript/src/features/player/setup.d.ts.map +1 -1
- package/lib/typescript/src/features/queue/queue.d.ts +9 -2
- package/lib/typescript/src/features/queue/queue.d.ts.map +1 -1
- package/lib/typescript/src/features/remoteControls.d.ts +0 -13
- package/lib/typescript/src/features/remoteControls.d.ts.map +1 -1
- package/lib/typescript/src/features/sleepTimer.d.ts +18 -3
- package/lib/typescript/src/features/sleepTimer.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/native.d.ts +1 -2
- package/lib/typescript/src/native.d.ts.map +1 -1
- package/lib/typescript/src/specs/audio-browser.nitro.d.ts +17 -225
- package/lib/typescript/src/specs/audio-browser.nitro.d.ts.map +1 -1
- package/lib/typescript/src/types/browser-native.d.ts +9 -3
- package/lib/typescript/src/types/browser-native.d.ts.map +1 -1
- package/lib/typescript/src/types/browser-nodes.d.ts +145 -13
- package/lib/typescript/src/types/browser-nodes.d.ts.map +1 -1
- package/lib/typescript/src/types/browser.d.ts +349 -85
- package/lib/typescript/src/types/browser.d.ts.map +1 -1
- package/lib/typescript/src/utils/LazyNativeEmitter.d.ts +0 -2
- package/lib/typescript/src/utils/LazyNativeEmitter.d.ts.map +1 -1
- package/lib/typescript/src/utils/NativeUpdatedValue.d.ts +0 -2
- package/lib/typescript/src/utils/NativeUpdatedValue.d.ts.map +1 -1
- package/lib/typescript/src/utils/artwork.d.ts +19 -0
- package/lib/typescript/src/utils/artwork.d.ts.map +1 -0
- package/lib/typescript/src/utils/resolveAssetSource.d.ts.map +1 -1
- package/nitrogen/generated/android/AudioBrowser+autolinking.cmake +3 -1
- package/nitrogen/generated/android/AudioBrowserOnLoad.cpp +24 -10
- package/nitrogen/generated/android/c++/JAndroidAudioContentType.hpp +6 -6
- package/nitrogen/generated/android/c++/JAndroidOptions.hpp +1 -11
- package/nitrogen/generated/android/c++/JArtworkRequestConfig.hpp +33 -1
- package/nitrogen/generated/android/c++/JArtworkVariants.hpp +61 -0
- package/nitrogen/generated/android/c++/JBrowseResult.hpp +5 -0
- package/nitrogen/generated/android/c++/JCarPlayNowPlayingButton.hpp +3 -3
- package/nitrogen/generated/android/c++/JFavoriteChangedEvent.hpp +6 -0
- package/nitrogen/generated/android/c++/JFavoriteConfig.hpp +58 -0
- package/nitrogen/generated/android/c++/JFavoritesMatchMode.hpp +58 -0
- package/nitrogen/generated/android/c++/JFormatNowPlayingParams.hpp +100 -0
- package/nitrogen/generated/android/c++/JFormattedNavigationError.hpp +3 -2
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.hpp +112 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___RequestConfig_std__optional_std__unordered_map_std__string__std__string__.hpp +121 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___Track.hpp +123 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.hpp +133 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_std__string____Track.hpp +121 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.hpp +139 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____Track.hpp +6 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.hpp +134 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_Track______SearchParams.hpp +8 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_void_____TrackLoadEvent.hpp +6 -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 +131 -0
- package/nitrogen/generated/android/c++/JFunc_void_FavoriteChangedEvent.hpp +6 -0
- package/nitrogen/generated/android/c++/JFunc_void_GateEvent.hpp +79 -0
- package/nitrogen/generated/android/c++/JFunc_void_NowPlayingMetadata.hpp +0 -10
- package/nitrogen/generated/android/c++/JFunc_void_Options.hpp +9 -4
- package/nitrogen/generated/android/c++/JFunc_void_Output.hpp +80 -0
- package/nitrogen/generated/android/c++/JFunc_void_Playback.hpp +2 -0
- package/nitrogen/generated/android/c++/JFunc_void_PlaybackActiveTrackChangedEvent.hpp +6 -0
- package/nitrogen/generated/android/c++/JFunc_void_PlaybackErrorEvent.hpp +2 -0
- package/nitrogen/generated/android/c++/JFunc_void_bool.hpp +10 -10
- package/nitrogen/generated/android/c++/JFunc_void_std__optional_ResolvedTrack_.hpp +6 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__vector_Track_.hpp +6 -0
- package/nitrogen/generated/android/c++/JGate.hpp +62 -0
- package/nitrogen/generated/android/c++/JGateDecision.hpp +64 -0
- package/nitrogen/generated/android/c++/{JThumbsRating.hpp → JGateEvent.hpp} +16 -15
- package/nitrogen/generated/android/c++/JGateReason.hpp +58 -0
- package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.cpp +236 -212
- package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.hpp +25 -22
- package/nitrogen/generated/android/c++/JIOSOptions.hpp +95 -0
- package/nitrogen/generated/android/c++/JImageRowItem.hpp +33 -3
- package/nitrogen/generated/android/c++/JMediaReference.hpp +58 -0
- package/nitrogen/generated/android/c++/JMediaRequestConfig.hpp +33 -1
- package/nitrogen/generated/android/c++/{JPartialAndroidSetupPlayerOptions.hpp → JNativeAndroidSetupOptions.hpp} +10 -10
- package/nitrogen/generated/android/c++/JNativeBrowserConfiguration.hpp +61 -28
- package/nitrogen/generated/android/c++/JNativeGateRequest.hpp +74 -0
- package/nitrogen/generated/android/c++/{JPartialIOSSetupPlayerOptions.hpp → JNativeIOSSetupOptions.hpp} +10 -10
- package/nitrogen/generated/android/c++/JNativeRouteEntry.hpp +20 -9
- package/nitrogen/generated/android/c++/JNativeSetupPlayerOptions.hpp +182 -0
- package/nitrogen/generated/android/c++/JNativeUpdateOptions.hpp +16 -19
- package/nitrogen/generated/android/c++/JNavigationErrorType.hpp +6 -0
- package/nitrogen/generated/android/c++/JNitroAndroidUpdateOptions.hpp +1 -11
- package/nitrogen/generated/android/c++/JNitroIOSUpdateOptions.hpp +96 -0
- package/nitrogen/generated/android/c++/JNotificationButton.hpp +3 -3
- package/nitrogen/generated/android/c++/JNowPlayingMetadata.hpp +3 -17
- package/nitrogen/generated/android/c++/JNowPlayingUpdate.hpp +7 -3
- package/nitrogen/generated/android/c++/JOptions.hpp +14 -9
- package/nitrogen/generated/android/c++/{JIosOutput.hpp → JOutput.hpp} +15 -15
- package/nitrogen/generated/android/c++/JOutputType.hpp +82 -0
- package/nitrogen/generated/android/c++/JPlayback.hpp +2 -0
- package/nitrogen/generated/android/c++/JPlaybackActiveTrackChangedEvent.hpp +6 -0
- package/nitrogen/generated/android/c++/JPlaybackError.hpp +18 -3
- package/nitrogen/generated/android/c++/JPlaybackErrorEvent.hpp +2 -0
- package/nitrogen/generated/android/c++/JPlaybackErrorKind.hpp +76 -0
- package/nitrogen/generated/android/c++/JPlaybackState.hpp +3 -3
- package/nitrogen/generated/android/c++/JPlayerCapabilities.hpp +11 -5
- package/nitrogen/generated/android/c++/JResolvedTrack.hpp +23 -5
- package/nitrogen/generated/android/c++/JRetryConfig.hpp +11 -7
- package/nitrogen/generated/android/c++/JSearchMode.hpp +27 -9
- package/nitrogen/generated/android/c++/JSearchParams.hpp +9 -3
- package/nitrogen/generated/android/c++/JStallReason.hpp +58 -0
- package/nitrogen/generated/android/c++/JTrack.hpp +23 -5
- package/nitrogen/generated/android/c++/JTrackLoadEvent.hpp +6 -0
- package/nitrogen/generated/android/c++/JTrackRequest.hpp +93 -0
- package/nitrogen/generated/android/c++/JTransformableRequestConfig.hpp +14 -1
- package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.hpp +71 -0
- package/nitrogen/generated/android/c++/JVariant_ResolvedTrack_BrowseError_Promise_BrowseResult_.cpp +41 -0
- package/nitrogen/generated/android/c++/JVariant_ResolvedTrack_BrowseError_Promise_BrowseResult_.hpp +121 -0
- package/nitrogen/generated/android/c++/JVariant_String_ArtworkVariants.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_String_ArtworkVariants.hpp +70 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidAudioContentType.kt +4 -4
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidOptions.kt +2 -8
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ArtworkRequestConfig.kt +10 -4
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ArtworkVariants.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/CarPlayNowPlayingButton.kt +3 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{ThumbsRating.kt → FavoriteConfig.kt} +6 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{RatingType.kt → FavoritesMatchMode.kt} +5 -10
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormatNowPlayingParams.kt +50 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/FormattedNavigationError.kt +2 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___RequestConfig_std__optional_std__unordered_map_std__string__std__string__.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_RequestConfig___Track.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__optional_std__string____Track.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.kt → Func_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.kt} +12 -12
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Func_void_RemoteSetRatingEvent.kt → Func_void_GateEvent.kt} +9 -9
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Func_void_IosOutput.kt → Func_void_Output.kt} +9 -9
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_void_bool.kt +9 -9
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{HeartRating.kt → Gate.kt} +9 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{PercentageRating.kt → GateDecision.kt} +9 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{StarRating.kt → GateEvent.kt} +6 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/GateReason.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/HybridAudioBrowserSpec.kt +103 -109
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IOSOptions.kt +44 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageRowItem.kt +24 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaReference.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/MediaRequestConfig.kt +10 -4
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{PartialAndroidSetupPlayerOptions.kt → NativeAndroidSetupOptions.kt} +5 -5
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeBrowserConfiguration.kt +18 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{RemoteSetRatingEvent.kt → NativeGateRequest.kt} +12 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{PartialIOSSetupPlayerOptions.kt → NativeIOSSetupOptions.kt} +5 -5
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeRouteEntry.kt +4 -4
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeSetupPlayerOptions.kt +66 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeUpdateOptions.kt +6 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NavigationErrorType.kt +3 -1
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroAndroidUpdateOptions.kt +2 -8
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroIOSUpdateOptions.kt +44 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NotificationButton.kt +5 -5
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingMetadata.kt +3 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NowPlayingUpdate.kt +6 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Options.kt +3 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{IosOutput.kt → Output.kt} +6 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/OutputType.kt +31 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackError.kt +12 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackErrorKind.kt +29 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlaybackState.kt +6 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlayerCapabilities.kt +2 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ResolvedTrack.kt +12 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RetryConfig.kt +7 -4
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SearchMode.kt +12 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SearchParams.kt +6 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/StallReason.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Track.kt +12 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackRequest.kt +44 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TransformableRequestConfig.kt +7 -4
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_Boolean_FavoriteConfig.kt +53 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_ResolvedTrack_BrowseError_Promise_BrowseResult_.kt +65 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_String_ArtworkVariants.kt +53 -0
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.cpp +139 -28
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.hpp +1098 -447
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Umbrella.hpp +60 -39
- package/nitrogen/generated/ios/c++/HybridAudioBrowserSpecSwift.hpp +170 -112
- package/nitrogen/generated/ios/swift/AndroidAudioContentType.swift +8 -8
- package/nitrogen/generated/ios/swift/AndroidOptions.swift +2 -12
- package/nitrogen/generated/ios/swift/ArtworkRequestConfig.swift +95 -1
- package/nitrogen/generated/ios/swift/ArtworkVariants.swift +34 -0
- package/nitrogen/generated/ios/swift/CarPlayNowPlayingButton.swift +4 -4
- package/nitrogen/generated/ios/swift/FavoriteConfig.swift +29 -0
- package/nitrogen/generated/ios/swift/FavoritesMatchMode.swift +40 -0
- package/nitrogen/generated/ios/swift/FormatNowPlayingParams.swift +67 -0
- package/nitrogen/generated/ios/swift/FormattedNavigationError.swift +17 -4
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_RequestConfig___MediaTransformParams.swift +54 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_RequestConfig___RequestConfig_std__optional_std__unordered_map_std__string__std__string__.swift +69 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_RequestConfig___Track.swift +54 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.swift +60 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__optional_std__string____Track.swift +60 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_GateDecision_____NativeGateRequest.swift +61 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_TransformableRequestConfig____.swift +61 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.swift +77 -0
- package/nitrogen/generated/ios/swift/Func_void_GateDecision.swift +46 -0
- package/nitrogen/generated/ios/swift/{Func_void_RemoteSetRatingEvent.swift → Func_void_GateEvent.swift} +10 -10
- package/nitrogen/generated/ios/swift/{Func_void_IosOutput.swift → Func_void_Output.swift} +10 -10
- package/nitrogen/generated/ios/swift/Func_void_TransformableRequestConfig.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_bool.swift +5 -5
- package/nitrogen/generated/ios/swift/Func_void_std__optional_NowPlayingUpdate_.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_std__optional_std__string_.swift +53 -0
- package/nitrogen/generated/ios/swift/{Func_void_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError___.swift → Func_void_std__shared_ptr_Promise_GateDecision__.swift} +17 -17
- package/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_TransformableRequestConfig__.swift +66 -0
- package/nitrogen/generated/ios/swift/Func_void_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError____.swift +81 -0
- package/nitrogen/generated/ios/swift/Gate.swift +47 -0
- package/nitrogen/generated/ios/swift/GateDecision.swift +40 -0
- package/nitrogen/generated/ios/swift/GateEvent.swift +29 -0
- package/nitrogen/generated/ios/swift/GateReason.swift +40 -0
- package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec.swift +20 -14
- package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec_cxx.swift +230 -197
- package/nitrogen/generated/ios/swift/IOSOptions.swift +51 -0
- package/nitrogen/generated/ios/swift/ImageRowItem.swift +121 -2
- package/nitrogen/generated/ios/swift/MediaReference.swift +40 -0
- package/nitrogen/generated/ios/swift/MediaRequestConfig.swift +107 -1
- package/nitrogen/generated/ios/swift/{PartialAndroidSetupPlayerOptions.swift → NativeAndroidSetupOptions.swift} +5 -5
- package/nitrogen/generated/ios/swift/NativeBrowserConfiguration.swift +161 -22
- package/nitrogen/generated/ios/swift/NativeGateRequest.swift +58 -0
- package/nitrogen/generated/ios/swift/{PartialIOSSetupPlayerOptions.swift → NativeIOSSetupOptions.swift} +5 -5
- package/nitrogen/generated/ios/swift/NativeRouteEntry.swift +19 -19
- package/nitrogen/generated/ios/swift/NativeSetupPlayerOptions.swift +206 -0
- package/nitrogen/generated/ios/swift/NativeUpdateOptions.swift +12 -25
- package/nitrogen/generated/ios/swift/NavigationErrorType.swift +8 -0
- package/nitrogen/generated/ios/swift/NitroAndroidUpdateOptions.swift +1 -30
- package/nitrogen/generated/ios/swift/NitroIOSUpdateOptions.swift +90 -0
- package/nitrogen/generated/ios/swift/NotificationButton.swift +4 -4
- package/nitrogen/generated/ios/swift/NowPlayingMetadata.swift +1 -48
- package/nitrogen/generated/ios/swift/NowPlayingUpdate.swift +19 -1
- package/nitrogen/generated/ios/swift/Options.swift +10 -4
- package/nitrogen/generated/ios/swift/{IosOutput.swift → Output.swift} +7 -7
- package/nitrogen/generated/ios/swift/OutputType.swift +72 -0
- package/nitrogen/generated/ios/swift/PlaybackError.swift +43 -2
- package/nitrogen/generated/ios/swift/PlaybackErrorKind.swift +64 -0
- package/nitrogen/generated/ios/swift/PlaybackState.swift +4 -4
- package/nitrogen/generated/ios/swift/PlayerCapabilities.swift +27 -8
- package/nitrogen/generated/ios/swift/ResolvedTrack.swift +74 -8
- package/nitrogen/generated/ios/swift/RetryConfig.swift +35 -4
- package/nitrogen/generated/ios/swift/SearchMode.swift +36 -12
- package/nitrogen/generated/ios/swift/SearchParams.swift +7 -2
- package/nitrogen/generated/ios/swift/StallReason.swift +40 -0
- package/nitrogen/generated/ios/swift/Track.swift +74 -8
- package/nitrogen/generated/ios/swift/TrackRequest.swift +106 -0
- package/nitrogen/generated/ios/swift/TransformableRequestConfig.swift +60 -1
- package/nitrogen/generated/ios/swift/Variant_Bool_FavoriteConfig.swift +18 -0
- package/nitrogen/generated/ios/swift/Variant_ResolvedTrack_BrowseError_Promise_BrowseResult_.swift +19 -0
- package/nitrogen/generated/ios/swift/Variant_String_ArtworkVariants.swift +18 -0
- package/nitrogen/generated/shared/c++/AndroidAudioContentType.hpp +10 -10
- package/nitrogen/generated/shared/c++/AndroidOptions.hpp +1 -12
- package/nitrogen/generated/shared/c++/ArtworkRequestConfig.hpp +10 -2
- package/nitrogen/generated/shared/c++/ArtworkVariants.hpp +87 -0
- package/nitrogen/generated/shared/c++/CarPlayNowPlayingButton.hpp +6 -6
- package/nitrogen/generated/shared/c++/EqualizerSettings.hpp +0 -2
- package/nitrogen/generated/shared/c++/{StarRating.hpp → FavoriteConfig.hpp} +18 -17
- package/nitrogen/generated/shared/c++/FavoritesMatchMode.hpp +76 -0
- package/nitrogen/generated/shared/c++/FormatNowPlayingParams.hpp +110 -0
- package/nitrogen/generated/shared/c++/FormattedNavigationError.hpp +6 -5
- package/nitrogen/generated/shared/c++/{HeartRating.hpp → Gate.hpp} +21 -16
- package/nitrogen/generated/shared/c++/{ThumbsRating.hpp → GateDecision.hpp} +23 -17
- package/nitrogen/generated/shared/c++/{PercentageRating.hpp → GateEvent.hpp} +18 -17
- package/nitrogen/generated/shared/c++/GateReason.hpp +76 -0
- package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.cpp +21 -18
- package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.hpp +44 -35
- package/nitrogen/generated/shared/c++/IOSOptions.hpp +91 -0
- package/nitrogen/generated/shared/c++/ImageRowItem.hpp +33 -2
- package/nitrogen/generated/shared/c++/MediaReference.hpp +76 -0
- package/nitrogen/generated/shared/c++/MediaRequestConfig.hpp +10 -2
- package/nitrogen/generated/shared/c++/{PartialAndroidSetupPlayerOptions.hpp → NativeAndroidSetupOptions.hpp} +11 -11
- package/nitrogen/generated/shared/c++/NativeBrowserConfiguration.hpp +31 -15
- package/nitrogen/generated/shared/c++/NativeGateRequest.hpp +97 -0
- package/nitrogen/generated/shared/c++/{PartialIOSSetupPlayerOptions.hpp → NativeIOSSetupOptions.hpp} +11 -11
- package/nitrogen/generated/shared/c++/NativeRouteEntry.hpp +5 -5
- package/nitrogen/generated/shared/c++/NativeSetupPlayerOptions.hpp +138 -0
- package/nitrogen/generated/shared/c++/NativeUpdateOptions.hpp +9 -7
- package/nitrogen/generated/shared/c++/NavigationErrorType.hpp +8 -0
- package/nitrogen/generated/shared/c++/NitroAndroidUpdateOptions.hpp +1 -12
- package/nitrogen/generated/shared/c++/NitroIOSUpdateOptions.hpp +92 -0
- package/nitrogen/generated/shared/c++/NotificationButton.hpp +8 -8
- package/nitrogen/generated/shared/c++/NowPlayingMetadata.hpp +3 -19
- package/nitrogen/generated/shared/c++/NowPlayingUpdate.hpp +6 -2
- package/nitrogen/generated/shared/c++/Options.hpp +8 -8
- package/nitrogen/generated/shared/c++/{IosOutput.hpp → Output.hpp} +18 -18
- package/nitrogen/generated/shared/c++/OutputType.hpp +108 -0
- package/nitrogen/generated/shared/c++/PlaybackError.hpp +18 -3
- package/nitrogen/generated/shared/c++/PlaybackErrorKind.hpp +100 -0
- package/nitrogen/generated/shared/c++/PlaybackState.hpp +9 -9
- package/nitrogen/generated/shared/c++/PlayerCapabilities.hpp +9 -6
- package/nitrogen/generated/shared/c++/ResolvedTrack.hpp +24 -5
- package/nitrogen/generated/shared/c++/RetryConfig.hpp +10 -6
- package/nitrogen/generated/shared/c++/SearchMode.hpp +39 -15
- package/nitrogen/generated/shared/c++/SearchParams.hpp +9 -2
- package/nitrogen/generated/shared/c++/StallReason.hpp +76 -0
- package/nitrogen/generated/shared/c++/Track.hpp +24 -5
- package/nitrogen/generated/shared/c++/TrackRequest.hpp +93 -0
- package/nitrogen/generated/shared/c++/TransformableRequestConfig.hpp +6 -2
- package/package.json +11 -6
- package/src/codegen-no-config-variant.test.ts +70 -0
- package/src/features/browser-config.test.ts +110 -0
- package/src/features/browser-config.ts +293 -0
- package/src/features/browser.test.ts +19 -0
- package/src/features/browser.ts +58 -201
- package/src/features/carConnection.ts +36 -0
- package/src/features/errors.ts +68 -2
- package/src/features/gate.test.ts +72 -0
- package/src/features/gate.ts +155 -0
- package/src/features/index.ts +2 -0
- package/src/features/metadata.ts +6 -12
- package/src/features/nowPlaying.ts +36 -0
- package/src/features/output.ts +35 -22
- package/src/features/playback/controls.ts +8 -0
- package/src/features/playback/index.ts +1 -0
- package/src/features/playback/progress.ts +31 -12
- package/src/features/playback/trackPlaybackTime.test.ts +66 -0
- package/src/features/playback/trackPlaybackTime.ts +106 -0
- package/src/features/playback/volume.ts +1 -1
- package/src/features/player/options.test.ts +38 -0
- package/src/features/player/options.ts +140 -75
- package/src/features/player/setup.test.ts +117 -0
- package/src/features/player/setup.ts +390 -175
- package/src/features/queue/queue.test.ts +36 -0
- package/src/features/queue/queue.ts +15 -4
- package/src/features/remoteControls.ts +0 -23
- package/src/features/sleepTimer.ts +23 -4
- package/src/native.ts +5 -0
- package/src/native.web.ts +4 -1
- package/src/specs/audio-browser.nitro.ts +131 -41
- package/src/types/browser-native.ts +19 -6
- package/src/types/browser-nodes.ts +160 -13
- package/src/types/browser.ts +377 -89
- package/src/utils/LazyNativeEmitter.ts +0 -2
- package/src/utils/NativeUpdatedValue.ts +0 -2
- package/src/utils/artwork.ts +30 -0
- package/src/web/NativeAudioBrowser.playWhenReady.test.ts +301 -0
- package/src/web/NativeAudioBrowser.ts +365 -158
- package/src/web/TrackPlayer/PlaybackStateMachine.test.ts +139 -0
- package/src/web/TrackPlayer/PlaybackStateMachine.ts +82 -0
- package/src/web/TrackPlayer/PlaybackTimer.test.ts +67 -0
- package/src/web/TrackPlayer/PlaybackTimer.ts +33 -0
- package/src/web/TrackPlayer/Player.dispatch.test.ts +229 -0
- package/src/web/TrackPlayer/Player.load.test.ts +86 -0
- package/src/web/TrackPlayer/Player.ts +113 -39
- package/src/web/TrackPlayer/PlayingStateFactory.test.ts +51 -0
- package/src/web/TrackPlayer/PlayingStateFactory.ts +24 -0
- package/src/web/TrackPlayer/QueueManager.test.ts +289 -0
- package/src/web/TrackPlayer/QueueManager.ts +302 -0
- package/src/web/TrackPlayer/QueuePlayer.ts +188 -0
- package/src/web/TrackPlayer/RepeatMode.ts +1 -1
- package/src/web/TrackPlayer/SleepTimer.ts +38 -3
- package/src/web/TrackPlayer/VolumeFader.ts +74 -0
- package/src/web/TrackPlayer/index.ts +2 -1
- package/src/web/browser/BrowserManager.ts +231 -62
- package/src/web/browser/NavigationErrorManager.ts +3 -1
- package/src/web/browser/SearchManager.ts +11 -15
- package/src/web/browser/__tests__/layer-resolver.test.ts +69 -0
- package/src/web/browser/assertBrowsePageShape.test.ts +27 -0
- package/src/web/browser/assertBrowsePageShape.ts +27 -0
- package/src/web/browser/classifyTrackNavigation.test.ts +41 -0
- package/src/web/browser/classifyTrackNavigation.ts +35 -0
- package/src/web/browser/parseSearchResponse.test.ts +25 -0
- package/src/web/browser/parseSearchResponse.ts +15 -0
- package/src/web/http/HttpClient.ts +5 -35
- package/src/web/http/RequestConfigBuilder.test.ts +59 -0
- package/src/web/http/RequestConfigBuilder.ts +120 -63
- package/src/web/playbackErrorKind.test.ts +55 -0
- package/src/web/playbackErrorKind.ts +56 -0
- package/src/web/player/MediaSessionManager.test.ts +220 -0
- package/src/web/player/MediaSessionManager.ts +151 -0
- package/src/web/player/NowPlayingManager.test.ts +46 -0
- package/src/web/player/NowPlayingManager.ts +6 -5
- package/src/web/player/OptionsManager.ts +12 -18
- package/src/web/player/RemoteCommandController.test.ts +171 -0
- package/src/web/player/RemoteCommandController.ts +166 -0
- package/android/src/main/java/com/audiobrowser/player/PlaybackProgressUpdateManager.kt +0 -59
- package/android/src/main/java/com/audiobrowser/util/RatingFactory.kt +0 -72
- package/android/src/main/java/com/audiobrowser/util/ResolvedTrackFactory.kt +0 -36
- package/android/src/test/java/com/audiobrowser/player/PlaybackProgressUpdateManagerTest.kt +0 -146
- package/ios/CarPlay/Track+CarPlay.swift +0 -63
- package/ios/NowPlayingInfo/NowPlayingInfoCenter.swift +0 -9
- package/ios/Player/PlaybackProgressUpdateManager.swift +0 -68
- package/ios/Tests/PlaybackProgressUpdateManagerTests.swift +0 -166
- package/lib/commonjs/features/rating.js +0 -2
- package/lib/commonjs/features/rating.js.map +0 -1
- package/lib/commonjs/types/player.js +0 -2
- package/lib/commonjs/types/player.js.map +0 -1
- package/lib/commonjs/web/SimpleRouter.test.js +0 -174
- package/lib/commonjs/web/SimpleRouter.test.js.map +0 -1
- package/lib/commonjs/web/TrackPlayer/PlaylistPlayer.js +0 -293
- package/lib/commonjs/web/TrackPlayer/PlaylistPlayer.js.map +0 -1
- package/lib/module/features/rating.js +0 -2
- package/lib/module/features/rating.js.map +0 -1
- package/lib/module/types/player.js +0 -2
- package/lib/module/types/player.js.map +0 -1
- package/lib/module/web/SimpleRouter.test.js +0 -174
- package/lib/module/web/SimpleRouter.test.js.map +0 -1
- package/lib/module/web/TrackPlayer/PlaylistPlayer.js +0 -288
- package/lib/module/web/TrackPlayer/PlaylistPlayer.js.map +0 -1
- package/lib/typescript/src/features/rating.d.ts +0 -14
- package/lib/typescript/src/features/rating.d.ts.map +0 -1
- package/lib/typescript/src/native.web.d.ts +0 -3
- package/lib/typescript/src/native.web.d.ts.map +0 -1
- package/lib/typescript/src/types/player.d.ts +0 -64
- package/lib/typescript/src/types/player.d.ts.map +0 -1
- package/lib/typescript/src/web/NativeAudioBrowser.d.ts +0 -188
- package/lib/typescript/src/web/NativeAudioBrowser.d.ts.map +0 -1
- package/lib/typescript/src/web/SimpleRouter.d.ts +0 -40
- package/lib/typescript/src/web/SimpleRouter.d.ts.map +0 -1
- package/lib/typescript/src/web/SimpleRouter.test.d.ts +0 -2
- package/lib/typescript/src/web/SimpleRouter.test.d.ts.map +0 -1
- package/lib/typescript/src/web/TrackPlayer/Event.d.ts +0 -11
- package/lib/typescript/src/web/TrackPlayer/Event.d.ts.map +0 -1
- package/lib/typescript/src/web/TrackPlayer/Player.d.ts +0 -59
- package/lib/typescript/src/web/TrackPlayer/Player.d.ts.map +0 -1
- package/lib/typescript/src/web/TrackPlayer/PlaylistPlayer.d.ts +0 -39
- package/lib/typescript/src/web/TrackPlayer/PlaylistPlayer.d.ts.map +0 -1
- package/lib/typescript/src/web/TrackPlayer/RepeatMode.d.ts +0 -6
- package/lib/typescript/src/web/TrackPlayer/RepeatMode.d.ts.map +0 -1
- package/lib/typescript/src/web/TrackPlayer/SetupNotCalledError.d.ts +0 -4
- package/lib/typescript/src/web/TrackPlayer/SetupNotCalledError.d.ts.map +0 -1
- package/lib/typescript/src/web/TrackPlayer/SleepTimer.d.ts +0 -34
- package/lib/typescript/src/web/TrackPlayer/SleepTimer.d.ts.map +0 -1
- package/lib/typescript/src/web/TrackPlayer/State.d.ts +0 -13
- package/lib/typescript/src/web/TrackPlayer/State.d.ts.map +0 -1
- package/lib/typescript/src/web/TrackPlayer/index.d.ts +0 -5
- package/lib/typescript/src/web/TrackPlayer/index.d.ts.map +0 -1
- package/lib/typescript/src/web/browser/BrowserManager.d.ts +0 -154
- package/lib/typescript/src/web/browser/BrowserManager.d.ts.map +0 -1
- package/lib/typescript/src/web/browser/FavoriteManager.d.ts +0 -42
- package/lib/typescript/src/web/browser/FavoriteManager.d.ts.map +0 -1
- package/lib/typescript/src/web/browser/NavigationErrorManager.d.ts +0 -40
- package/lib/typescript/src/web/browser/NavigationErrorManager.d.ts.map +0 -1
- package/lib/typescript/src/web/browser/SearchManager.d.ts +0 -22
- package/lib/typescript/src/web/browser/SearchManager.d.ts.map +0 -1
- package/lib/typescript/src/web/http/HttpClient.d.ts +0 -25
- package/lib/typescript/src/web/http/HttpClient.d.ts.map +0 -1
- package/lib/typescript/src/web/http/RequestConfigBuilder.d.ts +0 -98
- package/lib/typescript/src/web/http/RequestConfigBuilder.d.ts.map +0 -1
- package/lib/typescript/src/web/player/NowPlayingManager.d.ts +0 -34
- package/lib/typescript/src/web/player/NowPlayingManager.d.ts.map +0 -1
- package/lib/typescript/src/web/player/OptionsManager.d.ts +0 -32
- package/lib/typescript/src/web/player/OptionsManager.d.ts.map +0 -1
- package/lib/typescript/src/web/util/BrowserPathHelper.d.ts +0 -69
- package/lib/typescript/src/web/util/BrowserPathHelper.d.ts.map +0 -1
- package/lib/typescript/src/web/util/shuffle.d.ts +0 -8
- package/lib/typescript/src/web/util/shuffle.d.ts.map +0 -1
- package/nitrogen/generated/android/c++/JAndroidUpdateOptions.hpp +0 -86
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.hpp +0 -147
- package/nitrogen/generated/android/c++/JFunc_void_IosOutput.hpp +0 -80
- package/nitrogen/generated/android/c++/JFunc_void_RemoteSetRatingEvent.hpp +0 -87
- package/nitrogen/generated/android/c++/JHeartRating.hpp +0 -57
- package/nitrogen/generated/android/c++/JIosOutputType.hpp +0 -85
- package/nitrogen/generated/android/c++/JPartialSetupPlayerOptions.hpp +0 -96
- package/nitrogen/generated/android/c++/JPercentageRating.hpp +0 -57
- package/nitrogen/generated/android/c++/JRatingType.hpp +0 -73
- package/nitrogen/generated/android/c++/JRemoteSetRatingEvent.hpp +0 -66
- package/nitrogen/generated/android/c++/JStarRating.hpp +0 -57
- package/nitrogen/generated/android/c++/JUpdateOptions.hpp +0 -105
- package/nitrogen/generated/android/c++/JVariant_HeartRating_ThumbsRating_StarRating_PercentageRating.cpp +0 -34
- package/nitrogen/generated/android/c++/JVariant_HeartRating_ThumbsRating_StarRating_PercentageRating.hpp +0 -105
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidUpdateOptions.kt +0 -50
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IosOutputType.kt +0 -32
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PartialSetupPlayerOptions.kt +0 -47
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/UpdateOptions.kt +0 -53
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_HeartRating_ThumbsRating_StarRating_PercentageRating.kt +0 -77
- package/nitrogen/generated/ios/swift/AndroidUpdateOptions.swift +0 -119
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError______BrowserSourceCallbackParam.swift +0 -68
- package/nitrogen/generated/ios/swift/HeartRating.swift +0 -29
- package/nitrogen/generated/ios/swift/IosOutputType.swift +0 -76
- package/nitrogen/generated/ios/swift/PartialSetupPlayerOptions.swift +0 -101
- package/nitrogen/generated/ios/swift/PercentageRating.swift +0 -29
- package/nitrogen/generated/ios/swift/RatingType.swift +0 -60
- package/nitrogen/generated/ios/swift/RemoteSetRatingEvent.swift +0 -58
- package/nitrogen/generated/ios/swift/StarRating.swift +0 -29
- package/nitrogen/generated/ios/swift/ThumbsRating.swift +0 -29
- package/nitrogen/generated/ios/swift/UpdateOptions.swift +0 -143
- package/nitrogen/generated/ios/swift/Variant_HeartRating_ThumbsRating_StarRating_PercentageRating.swift +0 -20
- package/nitrogen/generated/shared/c++/AndroidUpdateOptions.hpp +0 -109
- package/nitrogen/generated/shared/c++/IosOutputType.hpp +0 -112
- package/nitrogen/generated/shared/c++/PartialSetupPlayerOptions.hpp +0 -104
- package/nitrogen/generated/shared/c++/RatingType.hpp +0 -96
- package/nitrogen/generated/shared/c++/RemoteSetRatingEvent.hpp +0 -94
- package/nitrogen/generated/shared/c++/UpdateOptions.hpp +0 -111
- package/src/features/rating.ts +0 -17
- package/src/types/player.ts +0 -69
- package/src/web/TrackPlayer/PlaylistPlayer.ts +0 -346
|
@@ -74,9 +74,19 @@ final class BrowserManager {
|
|
|
74
74
|
private var lastSearchQuery: String?
|
|
75
75
|
private var lastSearchResults: [Track]?
|
|
76
76
|
|
|
77
|
+
// Resolver caching: request/browse thunks resolve once per content generation.
|
|
78
|
+
private var layerGeneration = 0
|
|
79
|
+
private var resolvedLayerGeneration = -1
|
|
80
|
+
var resolvedRequestLayer: TransformableRequestConfig?
|
|
81
|
+
private var resolvedBrowseLayer: TransformableRequestConfig?
|
|
82
|
+
|
|
77
83
|
// Set of favorited track identifiers (src)
|
|
78
84
|
private var favoriteIds: Set<String> = []
|
|
79
85
|
|
|
86
|
+
// Favorite match mode, propagated from the player's `favorite` capability.
|
|
87
|
+
// nil = favoriting disabled (no row hearts). Set via setFavoriteMatch.
|
|
88
|
+
private var favoriteMatch: FavoritesMatchMode?
|
|
89
|
+
|
|
80
90
|
// Navigation tracking to prevent race conditions
|
|
81
91
|
private var currentNavigationId: Int = 0
|
|
82
92
|
|
|
@@ -99,7 +109,11 @@ final class BrowserManager {
|
|
|
99
109
|
|
|
100
110
|
private(set) var tabs: [Track]? {
|
|
101
111
|
didSet {
|
|
102
|
-
|
|
112
|
+
// Emit only on a real change: invalidateAllContent() re-queries the tabs
|
|
113
|
+
// source on every invalidation (a callback source can re-resolve, e.g.
|
|
114
|
+
// titles in a new locale), and an unchanged result must not churn the
|
|
115
|
+
// CarPlay tab bar or reset its selection.
|
|
116
|
+
if let tabs, !TabBarEntries.same(oldValue, tabs) {
|
|
103
117
|
onTabsChanged?(tabs)
|
|
104
118
|
}
|
|
105
119
|
}
|
|
@@ -114,6 +128,8 @@ final class BrowserManager {
|
|
|
114
128
|
var config: BrowserConfig = .init() {
|
|
115
129
|
didSet {
|
|
116
130
|
isConfigured = true
|
|
131
|
+
// New config means the cached resolver results are stale.
|
|
132
|
+
layerGeneration += 1
|
|
117
133
|
onConfigChanged?(config)
|
|
118
134
|
}
|
|
119
135
|
}
|
|
@@ -124,6 +140,11 @@ final class BrowserManager {
|
|
|
124
140
|
var onContentChanged: ((ResolvedTrack?) -> Void)?
|
|
125
141
|
var onTabsChanged: (([Track]) -> Void)?
|
|
126
142
|
var onConfigChanged: ((BrowserConfig) -> Void)?
|
|
143
|
+
/// Fired when the favorite id set changes (e.g. an app/webview-originated
|
|
144
|
+
/// favorite). Lets surfaces like the CarPlay now-playing heart re-render —
|
|
145
|
+
/// they otherwise only learn of their own toggles via favorite/active-track
|
|
146
|
+
/// events, never an external change routed through `setFavorites`.
|
|
147
|
+
var onFavoritesChanged: (() -> Void)?
|
|
127
148
|
|
|
128
149
|
/// Forwards to config.awaitTrackLoadHandler so callers don't need to
|
|
129
150
|
/// cross the MainActor boundary to access `config`.
|
|
@@ -138,25 +159,46 @@ final class BrowserManager {
|
|
|
138
159
|
|
|
139
160
|
/// Sets the favorited track identifiers.
|
|
140
161
|
func setFavorites(_ favorites: [String]) {
|
|
141
|
-
|
|
162
|
+
let newIds = Set(favorites)
|
|
163
|
+
guard newIds != favoriteIds else { return }
|
|
164
|
+
favoriteIds = newIds
|
|
165
|
+
onFavoritesChanged?()
|
|
142
166
|
}
|
|
143
167
|
|
|
144
|
-
///
|
|
145
|
-
|
|
168
|
+
/// Sets the favorite match mode (propagated from the `favorite` capability).
|
|
169
|
+
/// nil disables row-heart hydration.
|
|
170
|
+
func setFavoriteMatch(_ match: FavoritesMatchMode?) {
|
|
171
|
+
favoriteMatch = match
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/// Optimistically reflects a local favorite toggle for `src` in the match set,
|
|
175
|
+
/// needing no consumer-specific id extraction: favoriting inserts `src` (which
|
|
176
|
+
/// matches itself under either mode). Removal mirrors `isFavorite`'s match
|
|
177
|
+
/// semantics — partial drops every id that is a path segment of `src` (the
|
|
178
|
+
/// channel uid, and self-heals stray ids); exact (or disabled) drops only
|
|
179
|
+
/// `src`, so unrelated exact favorites that happen to be a segment of `src`
|
|
180
|
+
/// aren't collaterally lost. The consumer reconciles `favoriteIds` to its
|
|
181
|
+
/// canonical ids on the next `setFavorites`; `isFavorite(src:)` gives the same
|
|
182
|
+
/// answer before and after, so the now-playing heart stays responsive.
|
|
183
|
+
func setFavorited(src: String, favorited: Bool) {
|
|
146
184
|
if favorited {
|
|
147
|
-
favoriteIds.insert(
|
|
185
|
+
favoriteIds.insert(src)
|
|
186
|
+
} else if favoriteMatch == .partial {
|
|
187
|
+
favoriteIds = favoriteIds.filter { !BrowserPathHelper.containsSegment(src, $0) }
|
|
148
188
|
} else {
|
|
149
|
-
favoriteIds.remove(
|
|
189
|
+
favoriteIds.remove(src)
|
|
150
190
|
}
|
|
151
191
|
}
|
|
152
192
|
|
|
153
193
|
/// Hydrates the favorited field on a track based on the favoriteIds set.
|
|
154
|
-
///
|
|
155
|
-
|
|
156
|
-
|
|
194
|
+
/// No-op unless favoriting is enabled (the `favorite` capability). Only
|
|
195
|
+
/// playable (src-bearing) tracks are favoritable; the flag is set to true OR
|
|
196
|
+
/// false so non-favorited tracks still show an (empty) heart. Local
|
|
197
|
+
/// favoriteIds take precedence over API-provided values.
|
|
198
|
+
func hydrateFavorite(_ track: Track) -> Track {
|
|
199
|
+
guard let match = favoriteMatch, let src = track.src else { return track }
|
|
157
200
|
|
|
158
|
-
|
|
159
|
-
let isFavorited = favoriteIds.contains(src)
|
|
201
|
+
let isFavorited = isFavorite(src: src, match: match)
|
|
160
202
|
|
|
161
203
|
// Only create a new track if the favorited state differs
|
|
162
204
|
if track.favorited == isFavorited { return track }
|
|
@@ -164,6 +206,16 @@ final class BrowserManager {
|
|
|
164
206
|
return track.copying(favorited: isFavorited)
|
|
165
207
|
}
|
|
166
208
|
|
|
209
|
+
/// Whether `src` is favorited under the given match mode.
|
|
210
|
+
private func isFavorite(src: String, match: FavoritesMatchMode) -> Bool {
|
|
211
|
+
switch match {
|
|
212
|
+
case .exact:
|
|
213
|
+
favoriteIds.contains(src)
|
|
214
|
+
case .partial:
|
|
215
|
+
favoriteIds.contains { BrowserPathHelper.containsSegment(src, $0) }
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
167
219
|
/// Hydrates favorites on all children of a ResolvedTrack.
|
|
168
220
|
private func hydrateChildren(_ resolvedTrack: ResolvedTrack) -> ResolvedTrack {
|
|
169
221
|
guard let children = resolvedTrack.children else { return resolvedTrack }
|
|
@@ -187,23 +239,6 @@ final class BrowserManager {
|
|
|
187
239
|
resolvedTrack.children?.forEach { cacheTrack($0) }
|
|
188
240
|
}
|
|
189
241
|
|
|
190
|
-
/// Get a cached Track by mediaId (url or src), or nil if not cached.
|
|
191
|
-
func getCachedTrack(_ mediaId: String) -> Track? {
|
|
192
|
-
// Try direct lookup first (matches url or src)
|
|
193
|
-
if let track = trackCache.get(mediaId) {
|
|
194
|
-
return hydrateFavorite(track)
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
// Try extracting src from contextual URL
|
|
198
|
-
if let trackId = BrowserPathHelper.extractTrackId(mediaId) {
|
|
199
|
-
if let track = trackCache.get(trackId) {
|
|
200
|
-
return hydrateFavorite(track)
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
return nil
|
|
205
|
-
}
|
|
206
|
-
|
|
207
242
|
// MARK: - Navigation
|
|
208
243
|
|
|
209
244
|
/// Main navigation method - updates path and resolves content.
|
|
@@ -252,6 +287,13 @@ final class BrowserManager {
|
|
|
252
287
|
contentCache.remove(path)
|
|
253
288
|
}
|
|
254
289
|
|
|
290
|
+
/// Clears the entire content cache (e.g. on a locale change).
|
|
291
|
+
/// Runs from `invalidateAllContent`, so re-resolve the layer thunks too.
|
|
292
|
+
func clearContentCache() {
|
|
293
|
+
contentCache.clear()
|
|
294
|
+
layerGeneration += 1
|
|
295
|
+
}
|
|
296
|
+
|
|
255
297
|
/// Refreshes the current path by invalidating cache and re-resolving.
|
|
256
298
|
///
|
|
257
299
|
/// Uses navigation ID tracking to prevent race conditions.
|
|
@@ -271,21 +313,24 @@ final class BrowserManager {
|
|
|
271
313
|
}
|
|
272
314
|
|
|
273
315
|
private func resolveUncached(_ path: String) async throws -> ResolvedTrack {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
}
|
|
316
|
+
// Match an explicit route (or the '*' default). With no match, fall back to
|
|
317
|
+
// the implicit default: fetch the path via the request + browse config.
|
|
318
|
+
let routeEntry = (config.routes).flatMap { findBestRouteMatch(path: path, routes: $0) }
|
|
277
319
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
320
|
+
let resolvedTrack: ResolvedTrack = if let (entry, routeMatch) = routeEntry {
|
|
321
|
+
try await resolveRouteEntry(entry, path: path, params: routeMatch.params)
|
|
322
|
+
} else {
|
|
323
|
+
// Implicit default — no route config, just request → browse → fetch path.
|
|
324
|
+
try await resolveFromConfig(
|
|
325
|
+
nil, path: path, params: ["path": path],
|
|
326
|
+
)
|
|
281
327
|
}
|
|
282
328
|
|
|
283
|
-
// Resolve the track from the route
|
|
284
|
-
let resolvedTrack = try await resolveRouteEntry(routeEntry, path: path, params: routeMatch.params)
|
|
285
|
-
|
|
286
329
|
// Validate and transform children
|
|
287
330
|
if let children = resolvedTrack.children {
|
|
288
|
-
let transformed = try await transformChildren(
|
|
331
|
+
let transformed = try await transformChildren(
|
|
332
|
+
children, parentPath: path, routeEntry: routeEntry?.0,
|
|
333
|
+
)
|
|
289
334
|
return resolvedTrack.copying(children: transformed)
|
|
290
335
|
}
|
|
291
336
|
|
|
@@ -326,21 +371,29 @@ final class BrowserManager {
|
|
|
326
371
|
// Priority: callback > config > static
|
|
327
372
|
if let callback = entry.browseCallback {
|
|
328
373
|
let callbackParam = BrowserSourceCallbackParam(path: path, routeParams: params)
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
switch result {
|
|
374
|
+
// BrowserSourceCallback may return a BrowseResult synchronously or via a
|
|
375
|
+
// Promise. Nitro flattens (ResolvedTrack | BrowseError) | Promise<BrowseResult>
|
|
376
|
+
// into a 3-arm variant: sync track, sync error, or a Promise resolving to a
|
|
377
|
+
// BrowseResult (which is itself a ResolvedTrack | BrowseError variant).
|
|
378
|
+
switch try await callback(callbackParam).await() {
|
|
335
379
|
case let .first(resolvedTrack):
|
|
336
380
|
return resolvedTrack
|
|
337
381
|
case let .second(browseError):
|
|
338
382
|
throw BrowserError.callbackError(browseError.error)
|
|
383
|
+
case let .third(promise):
|
|
384
|
+
switch try await promise.await() {
|
|
385
|
+
case let .first(resolvedTrack):
|
|
386
|
+
return resolvedTrack
|
|
387
|
+
case let .second(browseError):
|
|
388
|
+
throw BrowserError.callbackError(browseError.error)
|
|
389
|
+
}
|
|
339
390
|
}
|
|
340
391
|
}
|
|
341
392
|
|
|
342
393
|
if let browseConfig = entry.browseConfig {
|
|
343
|
-
return try await resolveFromConfig(
|
|
394
|
+
return try await resolveFromConfig(
|
|
395
|
+
browseConfig, path: path, params: params,
|
|
396
|
+
)
|
|
344
397
|
}
|
|
345
398
|
|
|
346
399
|
if let staticContent = entry.browseStatic {
|
|
@@ -350,37 +403,68 @@ final class BrowserManager {
|
|
|
350
403
|
throw BrowserError.contentNotFound(path: path)
|
|
351
404
|
}
|
|
352
405
|
|
|
353
|
-
|
|
354
|
-
|
|
406
|
+
/// Builds the HTTP request for an API-backed route by layering
|
|
407
|
+
/// request → kind → route configs. `initialQuery` seeds request-level query
|
|
408
|
+
/// params (e.g. search q/mode/…) onto the base before the route layer, so they
|
|
409
|
+
/// survive into `request.query` even when a layer's transform "wins
|
|
410
|
+
/// completely" (it is handed only the base, so the route config's own static
|
|
411
|
+
/// query would otherwise be dropped). `routeConfig` is nil for the implicit
|
|
412
|
+
/// browse default; `kindConfig` is nil for kinds with no per-kind config.
|
|
413
|
+
private func buildApiRequest(
|
|
414
|
+
kind kindConfig: TransformableRequestConfig?,
|
|
415
|
+
_ routeConfig: TransformableRequestConfig?,
|
|
355
416
|
path: String,
|
|
356
|
-
params
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
guard let baseUrl else {
|
|
361
|
-
throw BrowserError.invalidConfiguration("No URL configured for route")
|
|
362
|
-
}
|
|
417
|
+
params: [String: String],
|
|
418
|
+
initialQuery: [String: String]? = nil,
|
|
419
|
+
) async throws -> HttpClient.HttpRequest {
|
|
420
|
+
try await ensureLayersResolved()
|
|
363
421
|
|
|
364
|
-
var
|
|
422
|
+
var merged = RequestConfig(
|
|
423
|
+
method: nil, path: path, baseUrl: nil, headers: nil,
|
|
424
|
+
query: nil, body: nil, contentType: nil, userAgent: nil,
|
|
425
|
+
)
|
|
426
|
+
merged = try await applyLayer(resolvedRequestLayer, to: merged, params: params)
|
|
427
|
+
if let initialQuery, !initialQuery.isEmpty {
|
|
428
|
+
merged = merged.copying(query: mergeDicts(merged.query, initialQuery))
|
|
429
|
+
}
|
|
430
|
+
merged = try await applyLayer(kindConfig, to: merged, params: params)
|
|
431
|
+
merged = try await applyLayer(routeConfig, to: merged, params: params)
|
|
365
432
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
433
|
+
guard let baseUrl = merged.baseUrl else {
|
|
434
|
+
throw BrowserError.invalidConfiguration("No URL configured for route")
|
|
435
|
+
}
|
|
436
|
+
var url = BrowserPathHelper.buildUrl(baseUrl: baseUrl, path: merged.path ?? path)
|
|
437
|
+
if let query = merged.query, !query.isEmpty {
|
|
438
|
+
url = BrowserPathHelper.appendQuery(query, to: url)
|
|
369
439
|
}
|
|
370
440
|
|
|
371
|
-
|
|
372
|
-
let method = (routeConfig.method ?? config.request?.method)?.stringValue ?? "GET"
|
|
373
|
-
let request = HttpClient.HttpRequest(
|
|
441
|
+
return HttpClient.HttpRequest(
|
|
374
442
|
url: url,
|
|
375
|
-
method: method,
|
|
376
|
-
headers:
|
|
443
|
+
method: merged.method?.stringValue ?? "GET",
|
|
444
|
+
headers: merged.headers,
|
|
445
|
+
body: merged.body,
|
|
446
|
+
contentType: merged.contentType ?? HttpClient.defaultContentType,
|
|
447
|
+
userAgent: merged.userAgent ?? HttpClient.defaultUserAgent,
|
|
448
|
+
)
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/// Resolves a browse route: a page object (`{title,url,children:[…]}`).
|
|
452
|
+
/// The browse kind layer is the cached resolved layer (`resolvedBrowseLayer`),
|
|
453
|
+
/// populated by `ensureLayersResolved()` inside `buildApiRequest`.
|
|
454
|
+
private func resolveFromConfig(
|
|
455
|
+
_ routeConfig: TransformableRequestConfig?,
|
|
456
|
+
path: String,
|
|
457
|
+
params: [String: String],
|
|
458
|
+
) async throws -> ResolvedTrack {
|
|
459
|
+
try await ensureLayersResolved()
|
|
460
|
+
let request = try await buildApiRequest(
|
|
461
|
+
kind: resolvedBrowseLayer, routeConfig, path: path, params: params,
|
|
377
462
|
)
|
|
378
463
|
|
|
379
464
|
logger.debug("Resolving content from API")
|
|
380
465
|
logger.debug(" path: \(path)")
|
|
381
|
-
logger.debug(" url: \(url)")
|
|
466
|
+
logger.debug(" url: \(request.url)")
|
|
382
467
|
|
|
383
|
-
// Execute request
|
|
384
468
|
let result: JsonResolvedTrack = try await httpClient.requestJson(request, as: JsonResolvedTrack.self)
|
|
385
469
|
let nitroResult = result.toNitro()
|
|
386
470
|
|
|
@@ -392,14 +476,73 @@ final class BrowserManager {
|
|
|
392
476
|
return nitroResult
|
|
393
477
|
}
|
|
394
478
|
|
|
479
|
+
/// Applies one request-config layer (request / browse / route) onto a base.
|
|
480
|
+
/// A transform (async and/or sync) wins completely: it receives the base and its
|
|
481
|
+
/// result replaces it. When both are set they run as a pipeline — async first,
|
|
482
|
+
/// then sync. Otherwise the layer's static fields merge over the base. `path` is
|
|
483
|
+
/// carried from the base (only a transform may change it).
|
|
484
|
+
func applyLayer(
|
|
485
|
+
_ layer: TransformableRequestConfig?,
|
|
486
|
+
to base: RequestConfig,
|
|
487
|
+
params: [String: String],
|
|
488
|
+
) async throws -> RequestConfig {
|
|
489
|
+
guard let layer else { return base }
|
|
490
|
+
// Run-both transform: async first, then sync (each replaces the running config).
|
|
491
|
+
// The bridge await depth — the bug-prone part — is centralised in awaitAsync/SyncConfig.
|
|
492
|
+
if layer.transform != nil || layer.transformSync != nil {
|
|
493
|
+
var result = base
|
|
494
|
+
if let transform = layer.transform { result = try await awaitAsyncConfig(transform(result, params)) }
|
|
495
|
+
if let transformSync = layer.transformSync { result = try await awaitSyncConfig(transformSync(result, params)) }
|
|
496
|
+
return result
|
|
497
|
+
}
|
|
498
|
+
return RequestConfig(
|
|
499
|
+
method: layer.method ?? base.method,
|
|
500
|
+
path: base.path,
|
|
501
|
+
baseUrl: layer.baseUrl ?? base.baseUrl,
|
|
502
|
+
headers: mergeDicts(base.headers, layer.headers),
|
|
503
|
+
query: mergeDicts(base.query, layer.query),
|
|
504
|
+
body: layer.body ?? base.body,
|
|
505
|
+
contentType: layer.contentType ?? base.contentType,
|
|
506
|
+
userAgent: layer.userAgent ?? base.userAgent,
|
|
507
|
+
)
|
|
508
|
+
}
|
|
509
|
+
|
|
395
510
|
/// Merges two optional dictionaries, with override values taking precedence.
|
|
511
|
+
/// Delegates to the pure, unit-tested `MediaResolveComposer.mergeDicts`.
|
|
396
512
|
func mergeDicts(
|
|
397
513
|
_ base: [String: String]?,
|
|
398
514
|
_ override: [String: String]?,
|
|
399
515
|
) -> [String: String]? {
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
516
|
+
MediaResolveComposer.mergeDicts(base, override)
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// MARK: - Layer Resolvers
|
|
520
|
+
|
|
521
|
+
/// Resolve one layer: invoke its resolver if present, else return the static
|
|
522
|
+
/// layer config unchanged. The resolver is Promise-only (the TS layer wraps a
|
|
523
|
+
/// sync-or-async thunk in Promise.resolve), so its result is the JS promise
|
|
524
|
+
/// behind the bridge promise — a double await.
|
|
525
|
+
private func resolveLayer(
|
|
526
|
+
config staticConfig: TransformableRequestConfig?,
|
|
527
|
+
resolver: (() -> Promise<Promise<TransformableRequestConfig>>)?,
|
|
528
|
+
) async throws -> TransformableRequestConfig? {
|
|
529
|
+
guard let resolver else { return staticConfig }
|
|
530
|
+
return try await resolver().await().await()
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/// Ensure request/browse resolvers are resolved for the current generation,
|
|
534
|
+
/// caching the results. Re-resolves after a generation bump (config change /
|
|
535
|
+
/// invalidateAllContent). Idempotent within a generation.
|
|
536
|
+
func ensureLayersResolved() async throws {
|
|
537
|
+
guard resolvedLayerGeneration != layerGeneration else { return }
|
|
538
|
+
let generation = layerGeneration
|
|
539
|
+
let req = try await resolveLayer(config: config.request, resolver: config.requestResolver)
|
|
540
|
+
let brw = try await resolveLayer(config: config.browse, resolver: config.browseResolver)
|
|
541
|
+
// Only commit if still current (a newer generation may have started during await).
|
|
542
|
+
guard generation == layerGeneration else { return }
|
|
543
|
+
resolvedRequestLayer = req
|
|
544
|
+
resolvedBrowseLayer = brw
|
|
545
|
+
resolvedLayerGeneration = generation
|
|
403
546
|
}
|
|
404
547
|
|
|
405
548
|
// MARK: - Child Transformation
|
|
@@ -407,13 +550,15 @@ final class BrowserManager {
|
|
|
407
550
|
private func transformChildren(
|
|
408
551
|
_ children: [Track],
|
|
409
552
|
parentPath: String,
|
|
410
|
-
routeEntry: NativeRouteEntry
|
|
553
|
+
routeEntry: NativeRouteEntry?,
|
|
411
554
|
) async throws -> [Track] {
|
|
412
555
|
var transformed: [Track] = []
|
|
413
556
|
|
|
414
557
|
for track in children {
|
|
415
|
-
// Validate track has stable identifier
|
|
416
|
-
|
|
558
|
+
// Validate track has stable identifier. A track carrying an imageRow is
|
|
559
|
+
// exempt: a url-less row is a pure preview — never selected, navigated
|
|
560
|
+
// to, or cached (its items carry their own identity).
|
|
561
|
+
if track.url == nil, track.src == nil, track.imageRow?.isEmpty != false {
|
|
417
562
|
throw BrowserError.invalidConfiguration(
|
|
418
563
|
"Track must have either 'url' or 'src' for stable identification: \(track.title)",
|
|
419
564
|
)
|
|
@@ -427,7 +572,7 @@ final class BrowserManager {
|
|
|
427
572
|
}
|
|
428
573
|
|
|
429
574
|
// Resolve artwork URL at browse-time (no size context)
|
|
430
|
-
let artworkConfig = routeEntry
|
|
575
|
+
let artworkConfig = routeEntry?.artwork ?? config.artwork
|
|
431
576
|
if let imageSource = await resolveArtworkUrl(track: transformedTrack, perRouteConfig: artworkConfig) {
|
|
432
577
|
transformedTrack = transformedTrack.copying(artworkSource: imageSource)
|
|
433
578
|
}
|
|
@@ -436,32 +581,25 @@ final class BrowserManager {
|
|
|
436
581
|
if let imageRowItems = transformedTrack.imageRow {
|
|
437
582
|
var resolvedItems: [ImageRowItem] = []
|
|
438
583
|
for item in imageRowItems {
|
|
439
|
-
let
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
subtitle: nil,
|
|
447
|
-
artist: nil,
|
|
448
|
-
album: nil,
|
|
449
|
-
description: nil,
|
|
450
|
-
genre: nil,
|
|
451
|
-
duration: nil,
|
|
452
|
-
style: nil,
|
|
453
|
-
childrenStyle: nil,
|
|
454
|
-
favorited: nil,
|
|
455
|
-
groupTitle: nil,
|
|
456
|
-
live: nil,
|
|
457
|
-
imageRow: nil,
|
|
458
|
-
)
|
|
459
|
-
let itemImageSource = await resolveArtworkUrl(track: itemTrack, perRouteConfig: artworkConfig)
|
|
584
|
+
let itemImageSource = await resolveArtworkUrl(track: item.toTrack(), perRouteConfig: artworkConfig)
|
|
585
|
+
// Playable items get a contextual URL like any list row, so a
|
|
586
|
+
// thumbnail tap expands into its section's queue instead of a
|
|
587
|
+
// queue of one (ADR 0006).
|
|
588
|
+
let itemUrl = item.url ?? item.src.map {
|
|
589
|
+
BrowserPathHelper.build(parentPath: parentPath, trackId: $0)
|
|
590
|
+
}
|
|
460
591
|
resolvedItems.append(ImageRowItem(
|
|
461
|
-
|
|
592
|
+
id: item.id,
|
|
593
|
+
url: itemUrl,
|
|
594
|
+
src: item.src,
|
|
462
595
|
artwork: item.artwork,
|
|
463
596
|
artworkSource: itemImageSource,
|
|
464
597
|
title: item.title,
|
|
598
|
+
artist: item.artist,
|
|
599
|
+
album: item.album,
|
|
600
|
+
albumUrl: item.albumUrl,
|
|
601
|
+
live: item.live,
|
|
602
|
+
request: item.request,
|
|
465
603
|
))
|
|
466
604
|
}
|
|
467
605
|
transformedTrack = transformedTrack.copying(imageRow: resolvedItems)
|
|
@@ -476,7 +614,19 @@ final class BrowserManager {
|
|
|
476
614
|
// MARK: - Search
|
|
477
615
|
|
|
478
616
|
/// Execute a search query.
|
|
617
|
+
/// Plain free-text search — wraps the structured overload with no mode/filters.
|
|
479
618
|
func search(_ query: String) async throws -> ResolvedTrack {
|
|
619
|
+
try await search(
|
|
620
|
+
SearchParams(mode: nil, query: query, genre: nil, artist: nil, album: nil, title: nil, playlist: nil, reference: .unknown),
|
|
621
|
+
)
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
/// Structured search. Emits `q` plus any of `mode`/`genre`/`artist`/`album`/
|
|
625
|
+
/// `title`/`playlist` that are set, mirroring Android's `executeSearchApiRequest`
|
|
626
|
+
/// and the web stub. Cached by `query`.
|
|
627
|
+
func search(_ params: SearchParams) async throws -> ResolvedTrack {
|
|
628
|
+
let query = params.query
|
|
629
|
+
|
|
480
630
|
// Check cache - re-hydrate favorites since they may have changed
|
|
481
631
|
if query == lastSearchQuery, let results = lastSearchResults {
|
|
482
632
|
let hydratedResults = results.map { hydrateFavorite($0) }
|
|
@@ -491,25 +641,36 @@ final class BrowserManager {
|
|
|
491
641
|
throw BrowserError.contentNotFound(path: Self.searchRoutePath)
|
|
492
642
|
}
|
|
493
643
|
|
|
494
|
-
let searchParams = SearchParams(
|
|
495
|
-
mode: nil,
|
|
496
|
-
query: query,
|
|
497
|
-
genre: nil,
|
|
498
|
-
artist: nil,
|
|
499
|
-
album: nil,
|
|
500
|
-
title: nil,
|
|
501
|
-
playlist: nil,
|
|
502
|
-
)
|
|
503
|
-
|
|
504
644
|
var results: [Track]
|
|
505
645
|
|
|
506
646
|
if let callback = searchEntry.searchCallback {
|
|
507
|
-
let outerPromise = callback(
|
|
647
|
+
let outerPromise = callback(params)
|
|
508
648
|
let innerPromise = try await outerPromise.await()
|
|
509
649
|
results = try await innerPromise.await()
|
|
510
650
|
} else if let searchConfig = searchEntry.searchConfig {
|
|
511
|
-
|
|
512
|
-
|
|
651
|
+
// Search is its own kind — request → search route (no browse layer). The
|
|
652
|
+
// endpoint returns a bare Track array (unlike browse's page object). The
|
|
653
|
+
// search params go through `initialQuery` so they land in `request.query`
|
|
654
|
+
// (and the URL); a config with a transform only ever sees the base.
|
|
655
|
+
// Seed the search config's static path onto the base — a layer's static
|
|
656
|
+
// path never applies (carried from the base; only a transform may change
|
|
657
|
+
// it). Matches the web stub's fetchSearchResults and Android.
|
|
658
|
+
var queryParams: [String: String] = ["q": query]
|
|
659
|
+
if let mode = params.mode { queryParams["mode"] = mode.stringValue }
|
|
660
|
+
if params.reference == .my { queryParams["reference"] = "my" }
|
|
661
|
+
if let genre = params.genre { queryParams["genre"] = genre }
|
|
662
|
+
if let artist = params.artist { queryParams["artist"] = artist }
|
|
663
|
+
if let album = params.album { queryParams["album"] = album }
|
|
664
|
+
if let title = params.title { queryParams["title"] = title }
|
|
665
|
+
if let playlist = params.playlist { queryParams["playlist"] = playlist }
|
|
666
|
+
|
|
667
|
+
let request = try await buildApiRequest(
|
|
668
|
+
kind: nil, searchConfig, path: searchConfig.path ?? "", params: ["q": query],
|
|
669
|
+
initialQuery: queryParams,
|
|
670
|
+
)
|
|
671
|
+
logger.debug("Searching via API: \(request.url)")
|
|
672
|
+
let jsonTracks: [JsonTrack] = try await httpClient.requestJson(request, as: [JsonTrack].self)
|
|
673
|
+
results = jsonTracks.map { $0.toNitro() }
|
|
513
674
|
} else {
|
|
514
675
|
throw BrowserError.contentNotFound(path: Self.searchRoutePath)
|
|
515
676
|
}
|
|
@@ -527,18 +688,32 @@ final class BrowserManager {
|
|
|
527
688
|
return makeSearchResult(query: query, results: hydratedResults)
|
|
528
689
|
}
|
|
529
690
|
|
|
691
|
+
/// Search and return playable tracks for "play «X»" voice intents, drilling
|
|
692
|
+
/// into a browsable-only first result (place/genre page) so we play its first
|
|
693
|
+
/// station. Decision in `SearchDrillIn.playable`; mirrors Android's
|
|
694
|
+
/// `searchPlayable`.
|
|
695
|
+
func searchPlayable(_ params: SearchParams) async throws -> [Track]? {
|
|
696
|
+
let children = try await (search(params).children) ?? []
|
|
697
|
+
return try await SearchDrillIn.playable(from: children) { [self] url in
|
|
698
|
+
logger.debug("First search result is browsable-only, resolving: \(url)")
|
|
699
|
+
return try await (resolve(url).children) ?? []
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
|
|
530
703
|
private func makeSearchResult(query: String, results: [Track]) -> ResolvedTrack {
|
|
531
704
|
ResolvedTrack(
|
|
532
705
|
url: BrowserPathHelper.createSearchPath(query),
|
|
533
706
|
children: results,
|
|
534
707
|
carPlaySiriListButton: nil,
|
|
708
|
+
id: nil,
|
|
535
709
|
src: nil,
|
|
536
710
|
artwork: nil,
|
|
537
|
-
artworkSource: nil,
|
|
711
|
+
artworkSource: nil, request: nil,
|
|
538
712
|
artworkCarPlayTinted: nil,
|
|
539
713
|
title: "Search: \(query)",
|
|
540
714
|
subtitle: nil,
|
|
541
715
|
artist: nil,
|
|
716
|
+
albumUrl: nil,
|
|
542
717
|
album: nil,
|
|
543
718
|
description: nil,
|
|
544
719
|
genre: nil,
|
|
@@ -589,8 +764,22 @@ final class BrowserManager {
|
|
|
589
764
|
let resolved = try await resolve(parentPath, useCache: true)
|
|
590
765
|
guard let children = resolved.children else { return nil }
|
|
591
766
|
|
|
767
|
+
// Queue scope is the tapped section, not the whole page (ADR 0006). An
|
|
768
|
+
// id that no longer appears on the page aborts the expansion — the
|
|
769
|
+
// caller falls back to the stored single track (matching Android);
|
|
770
|
+
// silently queueing the changed list would resume the wrong station.
|
|
771
|
+
let sectionTracks: [Track]
|
|
772
|
+
switch SectionScope.section(of: children, containing: trackId) {
|
|
773
|
+
case .imageRow(let items):
|
|
774
|
+
sectionTracks = items.map { $0.toTrack() }
|
|
775
|
+
case .run(let tracks):
|
|
776
|
+
sectionTracks = tracks
|
|
777
|
+
case nil:
|
|
778
|
+
return nil
|
|
779
|
+
}
|
|
780
|
+
|
|
592
781
|
// Filter to playable tracks (have src)
|
|
593
|
-
let playableTracks =
|
|
782
|
+
let playableTracks = sectionTracks.filter { $0.src != nil }
|
|
594
783
|
guard !playableTracks.isEmpty else { return nil }
|
|
595
784
|
|
|
596
785
|
logger.debug("Found \(playableTracks.count) playable tracks")
|
|
@@ -599,7 +788,11 @@ final class BrowserManager {
|
|
|
599
788
|
}
|
|
600
789
|
|
|
601
790
|
// Find selected track index
|
|
602
|
-
|
|
791
|
+
// Unreachable in practice (the section was found BY this id), but a miss
|
|
792
|
+
// must abort rather than silently start the queue at the wrong track.
|
|
793
|
+
guard let selectedIndex = playableTracks.firstIndex(where: { $0.src == trackId }) else {
|
|
794
|
+
return nil
|
|
795
|
+
}
|
|
603
796
|
logger.debug("Selected track index: \(selectedIndex)")
|
|
604
797
|
|
|
605
798
|
// If singleTrack mode, return just the selected track
|
|
@@ -173,18 +173,47 @@ enum BrowserPathHelper {
|
|
|
173
173
|
return path
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
//
|
|
176
|
+
// Strip trailing slashes from the base and leading slashes from the path so
|
|
177
|
+
// they join with exactly one separator.
|
|
177
178
|
var normalizedBase = baseUrl
|
|
178
179
|
while normalizedBase.hasSuffix("/") {
|
|
179
180
|
normalizedBase.removeLast()
|
|
180
181
|
}
|
|
181
|
-
normalizedBase += "/"
|
|
182
182
|
|
|
183
183
|
var normalizedPath = path
|
|
184
184
|
while normalizedPath.hasPrefix("/") {
|
|
185
185
|
normalizedPath.removeFirst()
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
-
|
|
188
|
+
// Empty path → the base IS the full URL (e.g. a search endpoint whose
|
|
189
|
+
// baseUrl already includes the path); don't leave a dangling trailing slash.
|
|
190
|
+
if normalizedPath.isEmpty {
|
|
191
|
+
return normalizedBase
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return "\(normalizedBase)/\(normalizedPath)"
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/// True if `segment` appears in `path` as a complete path segment — bounded on
|
|
198
|
+
/// the left by the string start or `/`, and on the right by the string end or
|
|
199
|
+
/// one of `/`, `?`, `#`.
|
|
200
|
+
static func containsSegment(_ path: String, _ segment: String) -> Bool {
|
|
201
|
+
guard !segment.isEmpty else { return false }
|
|
202
|
+
var searchStart = path.startIndex
|
|
203
|
+
while let range = path.range(of: segment, range: searchStart ..< path.endIndex) {
|
|
204
|
+
let beforeOk =
|
|
205
|
+
range.lowerBound == path.startIndex
|
|
206
|
+
|| path[path.index(before: range.lowerBound)] == "/"
|
|
207
|
+
let afterOk: Bool
|
|
208
|
+
if range.upperBound == path.endIndex {
|
|
209
|
+
afterOk = true
|
|
210
|
+
} else {
|
|
211
|
+
let next = path[range.upperBound]
|
|
212
|
+
afterOk = next == "/" || next == "?" || next == "#"
|
|
213
|
+
}
|
|
214
|
+
if beforeOk, afterOk { return true }
|
|
215
|
+
searchStart = range.upperBound
|
|
216
|
+
}
|
|
217
|
+
return false
|
|
189
218
|
}
|
|
190
219
|
}
|