react-native-audio-browser 0.2.0-next.2 → 0.2.0-next.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -21
- package/android/build.gradle +35 -12
- package/android/gradle.properties +2 -2
- package/android/src/main/AndroidManifest.xml +3 -1
- package/android/src/main/java/com/audiobrowser/AudioBrowser.kt +389 -164
- package/android/src/main/java/com/audiobrowser/AudioBrowserLifecycleModule.kt +38 -0
- package/android/src/main/java/com/audiobrowser/AudioBrowserPackage.kt +18 -2
- package/android/src/main/java/com/audiobrowser/ServiceBinding.kt +48 -0
- package/android/src/main/java/com/audiobrowser/browser/BrowserManager.kt +315 -213
- package/android/src/main/java/com/audiobrowser/browser/BrowserUrlResolution.kt +24 -5
- package/android/src/main/java/com/audiobrowser/browser/InertStyleDiagnostic.kt +267 -0
- package/android/src/main/java/com/audiobrowser/browser/JsonModels.kt +97 -58
- package/android/src/main/java/com/audiobrowser/browser/SectionScope.kt +70 -29
- package/android/src/main/java/com/audiobrowser/browser/StyleResolver.kt +60 -0
- package/android/src/main/java/com/audiobrowser/extension/ResolvedTrackExt.kt +20 -7
- package/android/src/main/java/com/audiobrowser/extension/TappedTrack.kt +20 -0
- package/android/src/main/java/com/audiobrowser/extension/TrackIdentity.kt +15 -0
- package/android/src/main/java/com/audiobrowser/http/HttpClient.kt +20 -3
- package/android/src/main/java/com/audiobrowser/model/IcyTitle.kt +24 -0
- package/android/src/main/java/com/audiobrowser/model/PlaybackMetadata.kt +10 -6
- package/android/src/main/java/com/audiobrowser/model/PlayerUpdateOptions.kt +12 -12
- package/android/src/main/java/com/audiobrowser/player/CapabilityControls.kt +111 -58
- package/android/src/main/java/com/audiobrowser/player/CrossOriginHeaderStripper.kt +77 -0
- package/android/src/main/java/com/audiobrowser/player/MediaFactory.kt +28 -10
- package/android/src/main/java/com/audiobrowser/player/MediaSessionCallback.kt +509 -230
- package/android/src/main/java/com/audiobrowser/player/MediaSessionCommandManager.kt +218 -252
- package/android/src/main/java/com/audiobrowser/player/NowPlayingUpdater.kt +21 -25
- package/android/src/main/java/com/audiobrowser/player/PlaybackStateStore.kt +113 -78
- package/android/src/main/java/com/audiobrowser/player/Player.kt +81 -38
- package/android/src/main/java/com/audiobrowser/player/PlayerCapabilitiesExt.kt +2 -15
- package/android/src/main/java/com/audiobrowser/player/PlayerListener.kt +1 -1
- package/android/src/main/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicy.kt +2 -1
- package/android/src/main/java/com/audiobrowser/player/ShuffleOrderLedBy.kt +30 -0
- package/android/src/main/java/com/audiobrowser/tls/AiaCertChaser.kt +67 -11
- package/android/src/main/java/com/audiobrowser/tls/AiaChasingExtendedTrustManager.kt +168 -0
- package/android/src/main/java/com/audiobrowser/tls/AiaChasingTrustManager.kt +58 -14
- package/android/src/main/java/com/audiobrowser/tls/AiaTls.kt +35 -7
- package/android/src/main/java/com/audiobrowser/tls/CachingCertificateFetcher.kt +278 -59
- package/android/src/main/java/com/audiobrowser/util/ArtworkVariant.kt +7 -9
- package/android/src/main/java/com/audiobrowser/util/BrowserPathHelper.kt +56 -40
- package/android/src/main/java/com/audiobrowser/util/MediaExtrasBuilder.kt +28 -23
- package/android/src/main/java/com/audiobrowser/util/StyleWire.kt +108 -0
- package/android/src/main/java/com/audiobrowser/util/TrackFactory.kt +56 -52
- package/android/src/main/res/values/strings.xml +25 -5
- package/android/src/test/java/com/audiobrowser/ServiceBindingTest.kt +87 -0
- package/android/src/test/java/com/audiobrowser/TestFixtures.kt +119 -33
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerFavoritesTest.kt +153 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerLayerResolutionTest.kt +15 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerTest.kt +346 -8
- package/android/src/test/java/com/audiobrowser/browser/BrowserUrlResolutionTest.kt +38 -0
- package/android/src/test/java/com/audiobrowser/browser/InertStyleDiagnosticTest.kt +277 -0
- package/android/src/test/java/com/audiobrowser/browser/JsonArtworkTest.kt +3 -2
- package/android/src/test/java/com/audiobrowser/browser/JsonStyleTest.kt +147 -0
- package/android/src/test/java/com/audiobrowser/browser/SectionScopeTest.kt +128 -55
- package/android/src/test/java/com/audiobrowser/browser/StyleResolverTest.kt +154 -0
- package/android/src/test/java/com/audiobrowser/extension/TappedTrackTest.kt +43 -0
- package/android/src/test/java/com/audiobrowser/extension/TrackIdentityTest.kt +41 -0
- package/android/src/test/java/com/audiobrowser/model/IcyTitleTest.kt +49 -0
- package/android/src/test/java/com/audiobrowser/player/BrowseTilesTest.kt +385 -0
- package/android/src/test/java/com/audiobrowser/player/CapabilityControlsTest.kt +101 -58
- package/android/src/test/java/com/audiobrowser/player/CrossOriginHeaderStripperTest.kt +94 -0
- package/android/src/test/java/com/audiobrowser/player/MediaSessionSlotMappingTest.kt +45 -0
- package/android/src/test/java/com/audiobrowser/player/NowPlayingUpdaterTest.kt +42 -2
- package/android/src/test/java/com/audiobrowser/player/PlaybackErrorClassifierTest.kt +3 -4
- package/android/src/test/java/com/audiobrowser/player/PlaybackStateStoreTrackJsonTest.kt +55 -0
- package/android/src/test/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicyTest.kt +3 -3
- package/android/src/test/java/com/audiobrowser/player/ShuffleOrderLedByTest.kt +79 -0
- package/android/src/test/java/com/audiobrowser/tls/AiaCertChaserTest.kt +197 -7
- package/android/src/test/java/com/audiobrowser/tls/AiaChasingTrustManagerTest.kt +325 -4
- package/android/src/test/java/com/audiobrowser/tls/CachingCertificateFetcherCallSiteTest.kt +322 -0
- package/android/src/test/java/com/audiobrowser/tls/CachingCertificateFetcherTest.kt +83 -0
- package/android/src/test/java/com/audiobrowser/util/BrowserPathHelperTest.kt +41 -16
- package/android/src/test/java/com/audiobrowser/util/MediaExtrasBuilderTest.kt +162 -0
- package/android/src/test/java/com/audiobrowser/util/TrackFactoryMediaIdTest.kt +7 -7
- package/ios/Browser/BrowserConfig.swift +102 -5
- package/ios/Browser/BrowserManager+URLResolution.swift +18 -14
- package/ios/Browser/BrowserManager.swift +230 -205
- package/ios/Browser/BrowserPathHelper.swift +44 -44
- package/ios/Browser/InertStyleDiagnostic.swift +279 -0
- package/ios/Browser/JsonModels.swift +264 -106
- package/ios/Browser/SearchDrillIn.swift +7 -7
- package/ios/Browser/SectionPresentation.swift +64 -0
- package/ios/Browser/SectionScope.swift +58 -24
- package/ios/Browser/StyleResolver.swift +58 -0
- package/ios/Browser/TabBarEntries.swift +9 -3
- package/ios/Browser/TrackIdTemplate.swift +37 -0
- package/ios/CarPlay/CarPlayArtworkResolver.swift +8 -7
- package/ios/CarPlay/CarPlayController.swift +227 -85
- package/ios/CarPlay/CarPlayImageLoader.swift +42 -20
- package/ios/CarPlay/CarPlayListItemFactory.swift +289 -84
- package/ios/CarPlay/CarPlayNowPlayingManager.swift +15 -12
- package/ios/CarPlay/RNABMediaAddHandler.swift +6 -6
- package/ios/CarPlay/RNABMediaAffinityHandler.swift +2 -2
- package/ios/CarPlay/RNABMediaIntentHandler.swift +16 -16
- package/ios/Extension/Capability+RemoteCommand.swift +1 -1
- package/ios/Extension/PlayerCapabilities+Favorite.swift +1 -15
- package/ios/Extension/ResolvedTrack+Copying.swift +13 -15
- package/ios/Extension/Section+Copying.swift +29 -0
- package/ios/Extension/String+IcyCharset.swift +21 -0
- package/ios/Extension/TimedMetadata+AVFoundation.swift +6 -4
- package/ios/Extension/Track+Copying.swift +8 -12
- package/ios/Extension/Track+Identity.swift +18 -0
- package/ios/Extension/UIApplication+ActiveScene.swift +27 -0
- package/ios/Http/HttpClient.swift +8 -2
- package/ios/HybridAudioBrowser.swift +253 -100
- package/ios/Model/NitroTypeStubs.swift +125 -23
- package/ios/Model/PlayerUpdateOptions.swift +7 -0
- package/ios/Model/RemoteCommand.swift +18 -0
- package/ios/Model/TrackPlayerError.swift +2 -2
- package/ios/Option/SessionCategories.swift +3 -2
- package/ios/Player/MediaIntentCriteria.swift +17 -9
- package/ios/Player/MediaLoader.swift +33 -9
- package/ios/Player/NowPlayingUpdater.swift +54 -6
- package/ios/Player/PlaybackCoordinator.swift +13 -6
- package/ios/Player/PlaybackErrorHandler.swift +4 -4
- package/ios/Player/PlaybackTimer.swift +8 -2
- package/ios/Player/QueueManager.swift +46 -13
- package/ios/Player/RetryManager.swift +80 -18
- package/ios/Player/SeekCompletionHandler.swift +3 -1
- package/ios/Player/ShuffleOrder.swift +33 -0
- package/ios/Player/SleepTimerHandling.swift +13 -0
- package/ios/RemoteCommand/RemoteCommandCallbacks.swift +47 -0
- package/ios/RemoteCommand/RemoteCommandController.swift +62 -24
- package/ios/Tests/BrowserPathHelperTests.swift +50 -20
- package/ios/Tests/CarPlayArtworkResolverTests.swift +24 -41
- package/ios/Tests/InertStyleDiagnosticTests.swift +200 -0
- package/ios/Tests/JsonModelsTests.swift +150 -1
- package/ios/Tests/LRUCacheTests.swift +111 -0
- package/ios/Tests/LoadSeekCoordinatorTests.swift +3 -1
- package/ios/Tests/MediaIntentCriteriaTests.swift +2 -2
- package/ios/Tests/PlaybackCoordinatorTests.swift +1 -1
- package/ios/Tests/PlaybackErrorHandlerTests.swift +3 -1
- package/ios/Tests/PlaybackStateStoreTests.swift +4 -3
- package/ios/Tests/PlayerTimeObserverTests.swift +37 -0
- package/ios/Tests/QueueManagerTests.swift +122 -10
- package/ios/Tests/RemoteCommandControllerTests.swift +172 -0
- package/ios/Tests/RemoteCommandTests.swift +67 -0
- package/ios/Tests/ResolvedTrackCopyingTests.swift +39 -35
- package/ios/Tests/RetryManagerTests.swift +89 -0
- package/ios/Tests/SearchDrillInTests.swift +16 -16
- package/ios/Tests/SectionPresentationTests.swift +90 -0
- package/ios/Tests/SectionScopeTests.swift +87 -55
- package/ios/Tests/StyleResolverTests.swift +127 -0
- package/ios/Tests/Support/TestTypes.swift +8 -1
- package/ios/Tests/TabBarEntriesTests.swift +19 -19
- package/ios/Tests/TimedMetadataAVFoundationTests.swift +42 -0
- package/ios/Tests/TrackIdTemplateTests.swift +67 -0
- package/ios/Tests/TrackIdentityTests.swift +20 -0
- package/ios/Tests/TrackSelectorTests.swift +168 -33
- package/ios/TrackPlayer.swift +63 -35
- package/ios/TrackPlayerCallbacks.swift +5 -38
- package/ios/TrackSelector.swift +45 -30
- package/ios/Util/ArtworkImageFetcher.swift +16 -1
- package/ios/Util/LRUCache.swift +4 -1
- package/ios/Util/NetworkMonitor.swift +43 -26
- package/ios/Util/SFSymbolRenderer.swift +24 -2
- package/ios/Util/SVGProcessor.swift +9 -2
- package/lib/commonjs/AudioBrowser.js +8 -8
- package/lib/commonjs/AudioBrowser.js.map +1 -1
- package/lib/commonjs/CLAUDE.md +52 -0
- package/lib/commonjs/features/browser-config.js +12 -8
- package/lib/commonjs/features/browser-config.js.map +1 -1
- package/lib/commonjs/features/browser.js +11 -3
- package/lib/commonjs/features/browser.js.map +1 -1
- package/lib/commonjs/features/carConnection.js +1 -1
- package/lib/commonjs/features/equalizer.js +1 -1
- package/lib/commonjs/features/errors.js +3 -3
- package/lib/commonjs/features/favorites.js +14 -11
- package/lib/commonjs/features/favorites.js.map +1 -1
- package/lib/commonjs/features/gate.js +16 -1
- package/lib/commonjs/features/gate.js.map +1 -1
- package/lib/commonjs/features/metadata.js +20 -3
- package/lib/commonjs/features/metadata.js.map +1 -1
- package/lib/commonjs/features/network.js +1 -1
- package/lib/commonjs/features/nowPlaying.js +1 -1
- package/lib/commonjs/features/output.js +1 -1
- package/lib/commonjs/features/playback/controls.js +4 -2
- package/lib/commonjs/features/playback/controls.js.map +1 -1
- package/lib/commonjs/features/playback/playWhenReady.js +1 -1
- package/lib/commonjs/features/playback/playing.js +1 -1
- package/lib/commonjs/features/playback/progress.js +3 -2
- package/lib/commonjs/features/playback/progress.js.map +1 -1
- package/lib/commonjs/features/playback/rate.js +8 -1
- package/lib/commonjs/features/playback/rate.js.map +1 -1
- package/lib/commonjs/features/playback/state.js +3 -4
- package/lib/commonjs/features/playback/state.js.map +1 -1
- package/lib/commonjs/features/playback/trackPlaybackTime.js +0 -6
- package/lib/commonjs/features/playback/trackPlaybackTime.js.map +1 -1
- package/lib/commonjs/features/playback/volume.js +1 -1
- package/lib/commonjs/features/player/options.js +48 -34
- package/lib/commonjs/features/player/options.js.map +1 -1
- package/lib/commonjs/features/player/setup.js +18 -9
- package/lib/commonjs/features/player/setup.js.map +1 -1
- package/lib/commonjs/features/player/validateOptions.js +23 -0
- package/lib/commonjs/features/player/validateOptions.js.map +1 -0
- package/lib/commonjs/features/queue/activeTrack.js +15 -4
- package/lib/commonjs/features/queue/activeTrack.js.map +1 -1
- package/lib/commonjs/features/queue/queue.js +13 -6
- package/lib/commonjs/features/queue/queue.js.map +1 -1
- package/lib/commonjs/features/queue/repeatMode.js +1 -1
- package/lib/commonjs/features/queue/shuffle.js +1 -1
- package/lib/commonjs/features/remoteControls.js +13 -92
- package/lib/commonjs/features/remoteControls.js.map +1 -1
- package/lib/commonjs/features/sleepTimer.js +13 -1
- package/lib/commonjs/features/sleepTimer.js.map +1 -1
- package/lib/commonjs/test-utils/reactNativeStub.js +65 -0
- package/lib/commonjs/test-utils/reactNativeStub.js.map +1 -0
- package/lib/commonjs/utils/LazyNativeEmitter.js +28 -14
- package/lib/commonjs/utils/LazyNativeEmitter.js.map +1 -1
- package/lib/commonjs/utils/NativeUpdatedValue.js +31 -13
- package/lib/commonjs/utils/NativeUpdatedValue.js.map +1 -1
- package/lib/commonjs/utils/getTrackIdentity.js +24 -0
- package/lib/commonjs/utils/getTrackIdentity.js.map +1 -0
- package/lib/commonjs/utils/useNativeValueRefreshedBy.js +33 -0
- package/lib/commonjs/utils/useNativeValueRefreshedBy.js.map +1 -0
- package/lib/commonjs/web/NativeAudioBrowser.js +200 -75
- package/lib/commonjs/web/NativeAudioBrowser.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/LoadAttempt.js +37 -0
- package/lib/commonjs/web/TrackPlayer/LoadAttempt.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js +18 -2
- package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/Player.js +254 -39
- package/lib/commonjs/web/TrackPlayer/Player.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/QueueManager.js +14 -0
- package/lib/commonjs/web/TrackPlayer/QueueManager.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/QueuePlayer.js +33 -12
- package/lib/commonjs/web/TrackPlayer/QueuePlayer.js.map +1 -1
- package/lib/commonjs/web/browser/BrowserManager.js +175 -100
- package/lib/commonjs/web/browser/BrowserManager.js.map +1 -1
- package/lib/commonjs/web/browser/FavoriteManager.js +30 -21
- package/lib/commonjs/web/browser/FavoriteManager.js.map +1 -1
- package/lib/commonjs/web/browser/SearchManager.js +18 -23
- package/lib/commonjs/web/browser/SearchManager.js.map +1 -1
- package/lib/commonjs/web/browser/assertBrowsePageShape.js +2 -2
- package/lib/commonjs/web/browser/assertBrowsePageShape.js.map +1 -1
- package/lib/commonjs/web/browser/classifyTrackNavigation.js +9 -9
- package/lib/commonjs/web/browser/classifyTrackNavigation.js.map +1 -1
- package/lib/commonjs/web/browser/sections.js +89 -0
- package/lib/commonjs/web/browser/sections.js.map +1 -0
- package/lib/commonjs/web/http/RequestConfigBuilder.js +110 -27
- package/lib/commonjs/web/http/RequestConfigBuilder.js.map +1 -1
- package/lib/commonjs/web/http/followMediaRedirect.js +219 -0
- package/lib/commonjs/web/http/followMediaRedirect.js.map +1 -0
- package/lib/commonjs/web/player/NowPlayingManager.js +4 -3
- package/lib/commonjs/web/player/NowPlayingManager.js.map +1 -1
- package/lib/commonjs/web/util/BrowserPathHelper.js +56 -11
- package/lib/commonjs/web/util/BrowserPathHelper.js.map +1 -1
- package/lib/module/AudioBrowser.js +2 -1
- package/lib/module/AudioBrowser.js.map +1 -1
- package/lib/module/CLAUDE.md +52 -0
- package/lib/module/features/browser-config.js +12 -8
- package/lib/module/features/browser-config.js.map +1 -1
- package/lib/module/features/browser.js +11 -3
- package/lib/module/features/browser.js.map +1 -1
- package/lib/module/features/carConnection.js +1 -1
- package/lib/module/features/equalizer.js +1 -1
- package/lib/module/features/errors.js +3 -3
- package/lib/module/features/favorites.js +14 -11
- package/lib/module/features/favorites.js.map +1 -1
- package/lib/module/features/gate.js +16 -1
- package/lib/module/features/gate.js.map +1 -1
- package/lib/module/features/metadata.js +20 -3
- package/lib/module/features/metadata.js.map +1 -1
- package/lib/module/features/network.js +1 -1
- package/lib/module/features/nowPlaying.js +1 -1
- package/lib/module/features/output.js +1 -1
- package/lib/module/features/playback/controls.js +4 -2
- package/lib/module/features/playback/controls.js.map +1 -1
- package/lib/module/features/playback/playWhenReady.js +1 -1
- package/lib/module/features/playback/playing.js +1 -1
- package/lib/module/features/playback/progress.js +3 -2
- package/lib/module/features/playback/progress.js.map +1 -1
- package/lib/module/features/playback/rate.js +8 -1
- package/lib/module/features/playback/rate.js.map +1 -1
- package/lib/module/features/playback/state.js +3 -4
- package/lib/module/features/playback/state.js.map +1 -1
- package/lib/module/features/playback/trackPlaybackTime.js +0 -5
- package/lib/module/features/playback/trackPlaybackTime.js.map +1 -1
- package/lib/module/features/playback/volume.js +1 -1
- package/lib/module/features/player/options.js +47 -32
- package/lib/module/features/player/options.js.map +1 -1
- package/lib/module/features/player/setup.js +17 -8
- package/lib/module/features/player/setup.js.map +1 -1
- package/lib/module/features/player/validateOptions.js +19 -0
- package/lib/module/features/player/validateOptions.js.map +1 -0
- package/lib/module/features/queue/activeTrack.js +15 -4
- package/lib/module/features/queue/activeTrack.js.map +1 -1
- package/lib/module/features/queue/queue.js +13 -6
- package/lib/module/features/queue/queue.js.map +1 -1
- package/lib/module/features/queue/repeatMode.js +1 -1
- package/lib/module/features/queue/shuffle.js +1 -1
- package/lib/module/features/remoteControls.js +13 -92
- package/lib/module/features/remoteControls.js.map +1 -1
- package/lib/module/features/sleepTimer.js +13 -1
- package/lib/module/features/sleepTimer.js.map +1 -1
- package/lib/module/test-utils/reactNativeStub.js +58 -0
- package/lib/module/test-utils/reactNativeStub.js.map +1 -0
- package/lib/module/utils/LazyNativeEmitter.js +28 -14
- package/lib/module/utils/LazyNativeEmitter.js.map +1 -1
- package/lib/module/utils/NativeUpdatedValue.js +31 -13
- package/lib/module/utils/NativeUpdatedValue.js.map +1 -1
- package/lib/module/utils/getTrackIdentity.js +20 -0
- package/lib/module/utils/getTrackIdentity.js.map +1 -0
- package/lib/module/utils/useNativeValueRefreshedBy.js +29 -0
- package/lib/module/utils/useNativeValueRefreshedBy.js.map +1 -0
- package/lib/module/web/NativeAudioBrowser.js +200 -75
- package/lib/module/web/NativeAudioBrowser.js.map +1 -1
- package/lib/module/web/TrackPlayer/LoadAttempt.js +32 -0
- package/lib/module/web/TrackPlayer/LoadAttempt.js.map +1 -0
- package/lib/module/web/TrackPlayer/PlaybackStateMachine.js +18 -2
- package/lib/module/web/TrackPlayer/PlaybackStateMachine.js.map +1 -1
- package/lib/module/web/TrackPlayer/Player.js +254 -39
- package/lib/module/web/TrackPlayer/Player.js.map +1 -1
- package/lib/module/web/TrackPlayer/QueueManager.js +14 -0
- package/lib/module/web/TrackPlayer/QueueManager.js.map +1 -1
- package/lib/module/web/TrackPlayer/QueuePlayer.js +33 -12
- package/lib/module/web/TrackPlayer/QueuePlayer.js.map +1 -1
- package/lib/module/web/browser/BrowserManager.js +175 -100
- package/lib/module/web/browser/BrowserManager.js.map +1 -1
- package/lib/module/web/browser/FavoriteManager.js +31 -21
- package/lib/module/web/browser/FavoriteManager.js.map +1 -1
- package/lib/module/web/browser/SearchManager.js +18 -23
- package/lib/module/web/browser/SearchManager.js.map +1 -1
- package/lib/module/web/browser/assertBrowsePageShape.js +2 -2
- package/lib/module/web/browser/assertBrowsePageShape.js.map +1 -1
- package/lib/module/web/browser/classifyTrackNavigation.js +9 -9
- package/lib/module/web/browser/classifyTrackNavigation.js.map +1 -1
- package/lib/module/web/browser/sections.js +83 -0
- package/lib/module/web/browser/sections.js.map +1 -0
- package/lib/module/web/http/RequestConfigBuilder.js +110 -27
- package/lib/module/web/http/RequestConfigBuilder.js.map +1 -1
- package/lib/module/web/http/followMediaRedirect.js +215 -0
- package/lib/module/web/http/followMediaRedirect.js.map +1 -0
- package/lib/module/web/player/NowPlayingManager.js +4 -3
- package/lib/module/web/player/NowPlayingManager.js.map +1 -1
- package/lib/module/web/util/BrowserPathHelper.js +56 -11
- package/lib/module/web/util/BrowserPathHelper.js.map +1 -1
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/AudioBrowser.d.ts +1 -1
- package/lib/typescript/src/AudioBrowser.d.ts.map +1 -1
- package/lib/typescript/src/features/browser-config.d.ts.map +1 -1
- package/lib/typescript/src/features/browser.d.ts +10 -2
- package/lib/typescript/src/features/browser.d.ts.map +1 -1
- package/lib/typescript/src/features/carConnection.d.ts +1 -1
- package/lib/typescript/src/features/equalizer.d.ts +1 -1
- package/lib/typescript/src/features/errors.d.ts +3 -3
- package/lib/typescript/src/features/favorites.d.ts +14 -11
- package/lib/typescript/src/features/favorites.d.ts.map +1 -1
- package/lib/typescript/src/features/gate.d.ts +18 -2
- package/lib/typescript/src/features/gate.d.ts.map +1 -1
- package/lib/typescript/src/features/metadata.d.ts +20 -3
- package/lib/typescript/src/features/metadata.d.ts.map +1 -1
- package/lib/typescript/src/features/network.d.ts +1 -1
- package/lib/typescript/src/features/nowPlaying.d.ts +1 -1
- package/lib/typescript/src/features/output.d.ts +1 -1
- package/lib/typescript/src/features/playback/controls.d.ts +4 -2
- package/lib/typescript/src/features/playback/controls.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/playWhenReady.d.ts +1 -1
- package/lib/typescript/src/features/playback/playing.d.ts +1 -1
- package/lib/typescript/src/features/playback/progress.d.ts +1 -1
- package/lib/typescript/src/features/playback/progress.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/rate.d.ts +8 -1
- package/lib/typescript/src/features/playback/rate.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/state.d.ts +3 -4
- package/lib/typescript/src/features/playback/state.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts +1 -1
- package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/volume.d.ts +1 -1
- package/lib/typescript/src/features/player/options.d.ts +108 -56
- package/lib/typescript/src/features/player/options.d.ts.map +1 -1
- package/lib/typescript/src/features/player/setup.d.ts +14 -4
- package/lib/typescript/src/features/player/setup.d.ts.map +1 -1
- package/lib/typescript/src/features/player/validateOptions.d.ts +2 -0
- package/lib/typescript/src/features/player/validateOptions.d.ts.map +1 -0
- package/lib/typescript/src/features/queue/activeTrack.d.ts +9 -2
- package/lib/typescript/src/features/queue/activeTrack.d.ts.map +1 -1
- package/lib/typescript/src/features/queue/queue.d.ts +7 -4
- package/lib/typescript/src/features/queue/queue.d.ts.map +1 -1
- package/lib/typescript/src/features/queue/repeatMode.d.ts +1 -1
- package/lib/typescript/src/features/queue/shuffle.d.ts +1 -1
- package/lib/typescript/src/features/remoteControls.d.ts +23 -22
- package/lib/typescript/src/features/remoteControls.d.ts.map +1 -1
- package/lib/typescript/src/features/sleepTimer.d.ts +1 -1
- package/lib/typescript/src/features/sleepTimer.d.ts.map +1 -1
- package/lib/typescript/src/test-utils/reactNativeStub.d.ts +36 -0
- package/lib/typescript/src/test-utils/reactNativeStub.d.ts.map +1 -0
- package/lib/typescript/src/types/browser-native.d.ts +3 -2
- package/lib/typescript/src/types/browser-native.d.ts.map +1 -1
- package/lib/typescript/src/types/browser-nodes.d.ts +380 -126
- package/lib/typescript/src/types/browser-nodes.d.ts.map +1 -1
- package/lib/typescript/src/types/browser.d.ts +82 -57
- package/lib/typescript/src/types/browser.d.ts.map +1 -1
- package/lib/typescript/src/utils/LazyNativeEmitter.d.ts +19 -16
- package/lib/typescript/src/utils/LazyNativeEmitter.d.ts.map +1 -1
- package/lib/typescript/src/utils/NativeUpdatedValue.d.ts +24 -19
- package/lib/typescript/src/utils/NativeUpdatedValue.d.ts.map +1 -1
- package/lib/typescript/src/utils/getTrackIdentity.d.ts +18 -0
- package/lib/typescript/src/utils/getTrackIdentity.d.ts.map +1 -0
- package/lib/typescript/src/utils/useNativeValueRefreshedBy.d.ts +21 -0
- package/lib/typescript/src/utils/useNativeValueRefreshedBy.d.ts.map +1 -0
- package/nitrogen/generated/android/AudioBrowser+autolinking.cmake +1 -2
- package/nitrogen/generated/android/AudioBrowserOnLoad.cpp +2 -0
- package/nitrogen/generated/android/c++/JAndroidOptions.hpp +10 -10
- package/nitrogen/generated/android/c++/{JFavoritesMatchMode.hpp → JArtworkRendering.hpp} +15 -15
- package/nitrogen/generated/android/c++/JArtworkRequestConfig.hpp +8 -3
- package/nitrogen/generated/android/c++/JBrowseResult.hpp +16 -4
- package/nitrogen/generated/android/c++/JCarPlayPlayingIndicatorLocation.hpp +58 -0
- package/nitrogen/generated/android/c++/JCardImage.hpp +58 -0
- package/nitrogen/generated/android/c++/JFavoriteChangedEvent.hpp +8 -3
- package/nitrogen/generated/android/c++/JFormatNowPlayingParams.hpp +8 -3
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___Track.hpp +8 -3
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.hpp +8 -3
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_std__string____Track.hpp +8 -3
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____Track.hpp +8 -3
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_Track______SearchParams.hpp +8 -2
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_void_____TrackLoadEvent.hpp +8 -2
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__string__.hpp +102 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.hpp +16 -4
- package/nitrogen/generated/android/c++/JFunc_void_FavoriteChangedEvent.hpp +8 -3
- package/nitrogen/generated/android/c++/JFunc_void_Options.hpp +7 -10
- package/nitrogen/generated/android/c++/JFunc_void_PlaybackActiveTrackChangedEvent.hpp +8 -3
- package/nitrogen/generated/android/c++/JFunc_void_std__optional_ResolvedTrack_.hpp +15 -3
- package/nitrogen/generated/android/c++/JFunc_void_std__vector_Track_.hpp +8 -2
- package/nitrogen/generated/android/c++/JGridTile.hpp +61 -0
- package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.cpp +45 -25
- package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.hpp +1 -1
- package/nitrogen/generated/android/c++/JIOSOptions.hpp +9 -3
- package/nitrogen/generated/android/c++/JImageShape.hpp +58 -0
- package/nitrogen/generated/android/c++/JMediaRequestConfig.hpp +8 -3
- package/nitrogen/generated/android/c++/JNativeBrowserConfiguration.hpp +36 -11
- package/nitrogen/generated/android/c++/JNativeRouteEntry.hpp +14 -2
- package/nitrogen/generated/android/c++/JNativeSetupPlayerOptions.hpp +15 -12
- package/nitrogen/generated/android/c++/JNativeUpdateOptions.hpp +7 -10
- package/nitrogen/generated/android/c++/JNitroAndroidUpdateOptions.hpp +10 -10
- package/nitrogen/generated/android/c++/JNitroIOSUpdateOptions.hpp +9 -3
- package/nitrogen/generated/android/c++/JOptions.hpp +7 -10
- package/nitrogen/generated/android/c++/JPlaybackActiveTrackChangedEvent.hpp +8 -3
- package/nitrogen/generated/android/c++/JPlayerCapabilities.hpp +5 -11
- package/nitrogen/generated/android/c++/{JNotificationButton.hpp → JRemoteButton.hpp} +19 -19
- package/nitrogen/generated/android/c++/JRemoteButtonLayout.hpp +86 -0
- package/nitrogen/generated/android/c++/JResolvedTrack.hpp +57 -49
- package/nitrogen/generated/android/c++/JSection.hpp +116 -0
- package/nitrogen/generated/android/c++/JSectionStyle.hpp +96 -0
- package/nitrogen/generated/android/c++/JStyleDisplay.hpp +58 -0
- package/nitrogen/generated/android/c++/JTrack.hpp +25 -46
- package/nitrogen/generated/android/c++/JTrackLoadEvent.hpp +8 -2
- package/nitrogen/generated/android/c++/JTrackStyle.hpp +46 -18
- package/nitrogen/generated/android/c++/JVariant_NullType_RemoteButtonLayout.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_RemoteButtonLayout.hpp +75 -0
- package/nitrogen/generated/android/c++/JVariant_ResolvedTrack_BrowseError_Promise_BrowseResult_.hpp +16 -4
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidOptions.kt +3 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{FavoritesMatchMode.kt → ArtworkRendering.kt} +5 -5
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/CarPlayPlayingIndicatorLocation.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/CardImage.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__string__.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/GridTile.kt +24 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/HybridAudioBrowserSpec.kt +1 -1
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IOSOptions.kt +6 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageShape.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeBrowserConfiguration.kt +8 -5
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroAndroidUpdateOptions.kt +3 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroIOSUpdateOptions.kt +6 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlayerCapabilities.kt +2 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{NotificationButton.kt → RemoteButton.kt} +3 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteButtonLayout.kt +44 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ResolvedTrack.kt +12 -15
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{FavoriteConfig.kt → Section.kt} +15 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SectionStyle.kt +59 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/StyleDisplay.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Track.kt +6 -12
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackStyle.kt +35 -5
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Variant_NullType_NotificationButtonLayout.kt → Variant_NullType_RemoteButtonLayout.kt} +9 -9
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.cpp +9 -0
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.hpp +244 -133
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Umbrella.hpp +31 -16
- package/nitrogen/generated/ios/c++/HybridAudioBrowserSpecSwift.hpp +33 -18
- package/nitrogen/generated/ios/swift/AndroidOptions.swift +12 -12
- package/nitrogen/generated/ios/swift/ArtworkRendering.swift +40 -0
- package/nitrogen/generated/ios/swift/CarPlayPlayingIndicatorLocation.swift +40 -0
- package/nitrogen/generated/ios/swift/CardImage.swift +40 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__string__.swift +54 -0
- package/nitrogen/generated/ios/swift/GridTile.swift +44 -0
- package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec.swift +1 -1
- package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec_cxx.swift +2 -2
- package/nitrogen/generated/ios/swift/IOSOptions.swift +7 -2
- package/nitrogen/generated/ios/swift/ImageShape.swift +40 -0
- package/nitrogen/generated/ios/swift/NativeBrowserConfiguration.swift +52 -5
- package/nitrogen/generated/ios/swift/NitroAndroidUpdateOptions.swift +12 -12
- package/nitrogen/generated/ios/swift/NitroIOSUpdateOptions.swift +12 -1
- package/nitrogen/generated/ios/swift/PlayerCapabilities.swift +8 -27
- package/nitrogen/generated/ios/swift/{NotificationButton.swift → RemoteButton.swift} +6 -6
- package/nitrogen/generated/ios/swift/RemoteButtonLayout.swift +57 -0
- package/nitrogen/generated/ios/swift/ResolvedTrack.swift +62 -73
- package/nitrogen/generated/ios/swift/Section.swift +82 -0
- package/nitrogen/generated/ios/swift/SectionStyle.swift +133 -0
- package/nitrogen/generated/ios/swift/StyleDisplay.swift +40 -0
- package/nitrogen/generated/ios/swift/Track.swift +28 -63
- package/nitrogen/generated/ios/swift/TrackStyle.swift +86 -22
- package/nitrogen/generated/ios/swift/{Variant_NullType_NotificationButtonLayout.swift → Variant_NullType_RemoteButtonLayout.swift} +3 -3
- package/nitrogen/generated/shared/c++/AndroidOptions.hpp +8 -8
- package/nitrogen/generated/shared/c++/{FavoritesMatchMode.hpp → ArtworkRendering.hpp} +17 -17
- package/nitrogen/generated/shared/c++/CarPlayPlayingIndicatorLocation.hpp +76 -0
- package/nitrogen/generated/shared/c++/CardImage.hpp +76 -0
- package/nitrogen/generated/shared/c++/GridTile.hpp +80 -0
- package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.cpp +1 -1
- package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.hpp +1 -1
- package/nitrogen/generated/shared/c++/IOSOptions.hpp +9 -2
- package/nitrogen/generated/shared/c++/ImageShape.hpp +76 -0
- package/nitrogen/generated/shared/c++/NativeBrowserConfiguration.hpp +10 -6
- package/nitrogen/generated/shared/c++/NitroAndroidUpdateOptions.hpp +8 -8
- package/nitrogen/generated/shared/c++/NitroIOSUpdateOptions.hpp +9 -2
- package/nitrogen/generated/shared/c++/PlayerCapabilities.hpp +6 -9
- package/nitrogen/generated/shared/c++/{NotificationButton.hpp → RemoteButton.hpp} +19 -19
- package/nitrogen/generated/shared/c++/RemoteButtonLayout.hpp +94 -0
- package/nitrogen/generated/shared/c++/ResolvedTrack.hpp +33 -37
- package/nitrogen/generated/shared/c++/Section.hpp +102 -0
- package/nitrogen/generated/shared/c++/SectionStyle.hpp +126 -0
- package/nitrogen/generated/shared/c++/StyleDisplay.hpp +76 -0
- package/nitrogen/generated/shared/c++/Track.hpp +18 -30
- package/nitrogen/generated/shared/c++/TrackStyle.hpp +73 -34
- package/package.json +24 -11
- package/src/AudioBrowser.ts +2 -1
- package/src/CLAUDE.md +52 -0
- package/src/features/battery.test.ts +79 -0
- package/src/features/browser-config.test.ts +21 -6
- package/src/features/browser-config.ts +12 -8
- package/src/features/browser.test.ts +1 -1
- package/src/features/browser.ts +11 -3
- package/src/features/carConnection.ts +1 -1
- package/src/features/equalizer.ts +1 -1
- package/src/features/errors.ts +3 -3
- package/src/features/favorites.ts +14 -11
- package/src/features/gate.ts +16 -1
- package/src/features/hook-wiring.test.ts +302 -0
- package/src/features/metadata.ts +20 -3
- package/src/features/network.ts +1 -1
- package/src/features/nowPlaying.ts +1 -1
- package/src/features/output.ts +1 -1
- package/src/features/playback/controls.ts +4 -2
- package/src/features/playback/playWhenReady.ts +1 -1
- package/src/features/playback/playing.ts +1 -1
- package/src/features/playback/progress.test.ts +169 -0
- package/src/features/playback/progress.ts +3 -2
- package/src/features/playback/rate.ts +8 -1
- package/src/features/playback/state.ts +3 -4
- package/src/features/playback/trackPlaybackTime.test.ts +16 -6
- package/src/features/playback/trackPlaybackTime.ts +1 -6
- package/src/features/playback/volume.ts +1 -1
- package/src/features/player/options.ts +126 -76
- package/src/features/player/setup.test.ts +24 -7
- package/src/features/player/setup.ts +22 -10
- package/src/features/player/validateOptions.ts +21 -0
- package/src/features/queue/activeTrack.ts +15 -4
- package/src/features/queue/queue.ts +13 -6
- package/src/features/queue/repeatMode.ts +1 -1
- package/src/features/queue/shuffle.ts +1 -1
- package/src/features/remoteControls.ts +13 -92
- package/src/features/sleepTimer.test.ts +172 -0
- package/src/features/sleepTimer.ts +9 -1
- package/src/nitro-stub-drift.test.ts +277 -0
- package/src/public-surface.test.ts +147 -0
- package/src/specs/audio-browser.nitro.ts +5 -4
- package/src/style-resolution.test.ts +210 -0
- package/src/test-utils/reactNativeStub.ts +60 -0
- package/src/types/browser-native.ts +7 -3
- package/src/types/browser-nodes.ts +396 -134
- package/src/types/browser.ts +85 -59
- package/src/utils/LazyNativeEmitter.ts +28 -15
- package/src/utils/NativeUpdatedValue.ts +29 -13
- package/src/utils/getTrackIdentity.ts +20 -0
- package/src/utils/useDebug.test.ts +182 -0
- package/src/utils/useNativeUpdatedValue.test.ts +103 -0
- package/src/utils/useNativeValueRefreshedBy.ts +38 -0
- package/src/web/NativeAudioBrowser.playWhenReady.test.ts +232 -2
- package/src/web/NativeAudioBrowser.ts +239 -82
- package/src/web/TrackPlayer/LoadAttempt.ts +29 -0
- package/src/web/TrackPlayer/PlaybackStateMachine.test.ts +60 -13
- package/src/web/TrackPlayer/PlaybackStateMachine.ts +22 -6
- package/src/web/TrackPlayer/Player.dispatch.test.ts +5 -3
- package/src/web/TrackPlayer/Player.load.test.ts +137 -1
- package/src/web/TrackPlayer/Player.ts +284 -37
- package/src/web/TrackPlayer/QueueManager.test.ts +29 -0
- package/src/web/TrackPlayer/QueueManager.ts +14 -0
- package/src/web/TrackPlayer/QueuePlayer.ts +33 -14
- package/src/web/__tests__/lifecycle.test.ts +345 -0
- package/src/web/__tests__/lifecycleHarness.ts +351 -0
- package/src/web/__tests__/loadEdgeCases.test.ts +246 -0
- package/src/web/__tests__/loadSupersession.test.ts +175 -0
- package/src/web/__tests__/retry.test.ts +169 -0
- package/src/web/browser/BrowserManager.ts +209 -111
- package/src/web/browser/FavoriteManager.test.ts +84 -0
- package/src/web/browser/FavoriteManager.ts +28 -23
- package/src/web/browser/SearchManager.test.ts +75 -0
- package/src/web/browser/SearchManager.ts +25 -28
- package/src/web/browser/__tests__/artwork-resolution.test.ts +117 -0
- package/src/web/browser/__tests__/layer-resolver.test.ts +35 -0
- package/src/web/browser/__tests__/search-artwork.test.ts +46 -0
- package/src/web/browser/__tests__/search-navigation.test.ts +76 -0
- package/src/web/browser/assertBrowsePageShape.test.ts +1 -1
- package/src/web/browser/assertBrowsePageShape.ts +5 -3
- package/src/web/browser/classifyTrackNavigation.test.ts +10 -8
- package/src/web/browser/classifyTrackNavigation.ts +9 -9
- package/src/web/browser/parseSearchResponse.test.ts +8 -2
- package/src/web/browser/sections.test.ts +91 -0
- package/src/web/browser/sections.ts +72 -0
- package/src/web/http/RequestConfigBuilder.test.ts +241 -1
- package/src/web/http/RequestConfigBuilder.ts +140 -33
- package/src/web/http/followMediaRedirect.test.ts +289 -0
- package/src/web/http/followMediaRedirect.ts +253 -0
- package/src/web/player/NowPlayingManager.ts +4 -3
- package/src/web/util/BrowserPathHelper.test.ts +52 -0
- package/src/web/util/BrowserPathHelper.ts +61 -13
- package/website/guide/android-auto.md +114 -0
- package/website/guide/android-certificates.md +409 -0
- package/website/guide/artwork.md +255 -0
- package/website/guide/audio-output.md +135 -0
- package/website/guide/automotive.md +86 -0
- package/website/guide/basic-usage.md +151 -0
- package/website/guide/battery.md +115 -0
- package/website/guide/browser.md +581 -0
- package/website/guide/carplay.md +620 -0
- package/website/guide/configuration.md +173 -0
- package/website/guide/equalizer.md +231 -0
- package/website/guide/errors.md +310 -0
- package/website/guide/favorites.md +154 -0
- package/website/guide/gate.md +143 -0
- package/website/guide/getting-started.md +46 -0
- package/website/guide/hooks.md +238 -0
- package/website/guide/live-streams.md +125 -0
- package/website/guide/metadata.md +239 -0
- package/website/guide/migrating-from-track-player.md +244 -0
- package/website/guide/native-callback-fetch.md +127 -0
- package/website/guide/network.md +86 -0
- package/website/guide/now-playing.md +175 -0
- package/website/guide/playback.md +328 -0
- package/website/guide/queue.md +300 -0
- package/website/guide/remote-controls.md +256 -0
- package/website/guide/search.md +255 -0
- package/website/guide/sleep-timer.md +268 -0
- package/website/guide/track.md +247 -0
- package/ios/CarPlay/ImageRowItem+CarPlay.swift +0 -19
- package/ios/Model/MediaURL.swift +0 -67
- package/nitrogen/generated/android/c++/JFavoriteConfig.hpp +0 -58
- package/nitrogen/generated/android/c++/JImageRowItem.hpp +0 -105
- package/nitrogen/generated/android/c++/JNotificationButtonLayout.hpp +0 -94
- package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.cpp +0 -26
- package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.hpp +0 -71
- package/nitrogen/generated/android/c++/JVariant_NullType_NotificationButtonLayout.cpp +0 -26
- package/nitrogen/generated/android/c++/JVariant_NullType_NotificationButtonLayout.hpp +0 -75
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageRowItem.kt +0 -68
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NotificationButtonLayout.kt +0 -50
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_Boolean_FavoriteConfig.kt +0 -53
- package/nitrogen/generated/ios/swift/FavoriteConfig.swift +0 -29
- package/nitrogen/generated/ios/swift/FavoritesMatchMode.swift +0 -40
- package/nitrogen/generated/ios/swift/ImageRowItem.swift +0 -195
- package/nitrogen/generated/ios/swift/NotificationButtonLayout.swift +0 -92
- package/nitrogen/generated/ios/swift/Variant_Bool_FavoriteConfig.swift +0 -18
- package/nitrogen/generated/shared/c++/FavoriteConfig.hpp +0 -84
- package/nitrogen/generated/shared/c++/ImageRowItem.hpp +0 -129
- package/nitrogen/generated/shared/c++/NotificationButtonLayout.hpp +0 -102
|
@@ -62,41 +62,193 @@ extension JsonArtwork {
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
///
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
65
|
+
/// A style declaration block on the wire (ADR 0011):
|
|
66
|
+
/// `{ display?, gridWrap?, artworkRendering? }`.
|
|
67
|
+
///
|
|
68
|
+
/// One JSON model serves both the `TrackStyle` and `SectionStyle` positions —
|
|
69
|
+
/// keys that don't exist at the narrower position simply don't map.
|
|
70
|
+
///
|
|
71
|
+
/// Decoding is tolerant by design: a stale payload — the retired string
|
|
72
|
+
/// styles, a wrong-typed field, an unknown enum value — must degrade to "no
|
|
73
|
+
/// declaration", never fail the page or the persisted playback state (the
|
|
74
|
+
/// decoders above this are strict, so a throw here would kill the whole
|
|
75
|
+
/// payload). `init(from:)` therefore never throws, and unknown enum values
|
|
76
|
+
/// map to nil at `toNitro` time.
|
|
77
|
+
struct JsonStyle: Codable, Equatable {
|
|
78
|
+
let display: String?
|
|
79
|
+
let gridWrap: Bool?
|
|
80
|
+
let gridTile: String?
|
|
81
|
+
let artworkRendering: String?
|
|
82
|
+
let imageShape: String?
|
|
83
|
+
let accessorySymbol: String?
|
|
84
|
+
let cardTint: String?
|
|
85
|
+
let cardImage: String?
|
|
77
86
|
|
|
78
87
|
init(
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
display: String? = nil,
|
|
89
|
+
gridWrap: Bool? = nil,
|
|
90
|
+
gridTile: String? = nil,
|
|
91
|
+
artworkRendering: String? = nil,
|
|
92
|
+
imageShape: String? = nil,
|
|
93
|
+
accessorySymbol: String? = nil,
|
|
94
|
+
cardTint: String? = nil,
|
|
95
|
+
cardImage: String? = nil,
|
|
96
|
+
) {
|
|
97
|
+
self.display = display
|
|
98
|
+
self.gridWrap = gridWrap
|
|
99
|
+
self.gridTile = gridTile
|
|
100
|
+
self.artworkRendering = artworkRendering
|
|
101
|
+
self.imageShape = imageShape
|
|
102
|
+
self.accessorySymbol = accessorySymbol
|
|
103
|
+
self.cardTint = cardTint
|
|
104
|
+
self.cardImage = cardImage
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
init(from decoder: Decoder) throws {
|
|
108
|
+
// A non-object value (the retired `style: 'grid'` string) decodes as an
|
|
109
|
+
// empty block rather than failing the parent.
|
|
110
|
+
guard let container = try? decoder.container(keyedBy: CodingKeys.self) else {
|
|
111
|
+
self.init()
|
|
112
|
+
return
|
|
113
|
+
}
|
|
114
|
+
self.init(
|
|
115
|
+
display: (try? container.decodeIfPresent(String.self, forKey: .display)) ?? nil,
|
|
116
|
+
gridWrap: (try? container.decodeIfPresent(Bool.self, forKey: .gridWrap)) ?? nil,
|
|
117
|
+
gridTile: (try? container.decodeIfPresent(String.self, forKey: .gridTile)) ?? nil,
|
|
118
|
+
artworkRendering: (try? container.decodeIfPresent(String.self, forKey: .artworkRendering)) ?? nil,
|
|
119
|
+
imageShape: (try? container.decodeIfPresent(String.self, forKey: .imageShape)) ?? nil,
|
|
120
|
+
accessorySymbol: (try? container.decodeIfPresent(String.self, forKey: .accessorySymbol)) ?? nil,
|
|
121
|
+
cardTint: (try? container.decodeIfPresent(String.self, forKey: .cardTint)) ?? nil,
|
|
122
|
+
cardImage: (try? container.decodeIfPresent(String.self, forKey: .cardImage)) ?? nil,
|
|
123
|
+
)
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
extension JsonStyle {
|
|
128
|
+
/// The wire strings map to Nitro enums here, tolerantly: an unknown value
|
|
129
|
+
/// (a future `display` mode, say) is no declaration, not an error. A block
|
|
130
|
+
/// that resolves to no declarations at all — `{}`, the tolerant decoder's
|
|
131
|
+
/// empty result for the retired string vocabulary, or all-unknown values —
|
|
132
|
+
/// maps to nil, so "no declaration" has one shape on every platform
|
|
133
|
+
/// (Android's lenient mapper makes the same collapse).
|
|
134
|
+
func toTrackStyle() -> TrackStyle? {
|
|
135
|
+
let display = display.flatMap { StyleDisplay(fromString: $0.lowercased()) }
|
|
136
|
+
let artworkRendering = artworkRendering.flatMap { ArtworkRendering(fromString: $0.lowercased()) }
|
|
137
|
+
let imageShape = imageShape.flatMap { ImageShape(fromString: $0.lowercased()) }
|
|
138
|
+
// The 'none' sentinel is a legitimate value; only emptiness collapses.
|
|
139
|
+
let accessorySymbol = accessorySymbol?.isEmpty == false ? accessorySymbol : nil
|
|
140
|
+
let cardTint = cardTint?.isEmpty == false ? cardTint : nil
|
|
141
|
+
let cardImage = cardImage.flatMap { CardImage(fromString: $0.lowercased()) }
|
|
142
|
+
guard display != nil || artworkRendering != nil || imageShape != nil
|
|
143
|
+
|| accessorySymbol != nil || cardTint != nil || cardImage != nil
|
|
144
|
+
else { return nil }
|
|
145
|
+
return TrackStyle(
|
|
146
|
+
display: display,
|
|
147
|
+
artworkRendering: artworkRendering,
|
|
148
|
+
imageShape: imageShape,
|
|
149
|
+
accessorySymbol: accessorySymbol,
|
|
150
|
+
cardTint: cardTint,
|
|
151
|
+
cardImage: cardImage,
|
|
152
|
+
)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
func toSectionStyle() -> SectionStyle? {
|
|
156
|
+
let display = display.flatMap { StyleDisplay(fromString: $0.lowercased()) }
|
|
157
|
+
let gridTile = gridTile.flatMap { GridTile(fromString: $0.lowercased()) }
|
|
158
|
+
let artworkRendering = artworkRendering.flatMap { ArtworkRendering(fromString: $0.lowercased()) }
|
|
159
|
+
let imageShape = imageShape.flatMap { ImageShape(fromString: $0.lowercased()) }
|
|
160
|
+
let accessorySymbol = accessorySymbol?.isEmpty == false ? accessorySymbol : nil
|
|
161
|
+
let cardTint = cardTint?.isEmpty == false ? cardTint : nil
|
|
162
|
+
let cardImage = cardImage.flatMap { CardImage(fromString: $0.lowercased()) }
|
|
163
|
+
guard display != nil || artworkRendering != nil || gridWrap != nil
|
|
164
|
+
|| gridTile != nil || imageShape != nil || accessorySymbol != nil
|
|
165
|
+
|| cardTint != nil || cardImage != nil
|
|
166
|
+
else { return nil }
|
|
167
|
+
// Argument order is the generated init's (own properties before
|
|
168
|
+
// inherited ones — Nitro flattens `extends` own-props-first).
|
|
169
|
+
return SectionStyle(
|
|
170
|
+
gridWrap: gridWrap,
|
|
171
|
+
gridTile: gridTile,
|
|
172
|
+
display: display,
|
|
173
|
+
artworkRendering: artworkRendering,
|
|
174
|
+
imageShape: imageShape,
|
|
175
|
+
accessorySymbol: accessorySymbol,
|
|
176
|
+
cardTint: cardTint,
|
|
177
|
+
cardImage: cardImage,
|
|
178
|
+
)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/// Snapshot a live track block back to its JSON model (for persistence).
|
|
182
|
+
/// An all-nil block snapshots as no block — the decoders collapse it to
|
|
183
|
+
/// "no declaration" anyway, so never persist the distinction.
|
|
184
|
+
init?(_ style: TrackStyle?) {
|
|
185
|
+
guard let style,
|
|
186
|
+
style.display != nil || style.artworkRendering != nil
|
|
187
|
+
|| style.imageShape != nil || style.accessorySymbol != nil
|
|
188
|
+
|| style.cardTint != nil || style.cardImage != nil
|
|
189
|
+
else { return nil }
|
|
190
|
+
self.init(
|
|
191
|
+
display: Self.string(style.display),
|
|
192
|
+
artworkRendering: Self.string(style.artworkRendering),
|
|
193
|
+
imageShape: Self.string(style.imageShape),
|
|
194
|
+
accessorySymbol: style.accessorySymbol,
|
|
195
|
+
cardTint: style.cardTint,
|
|
196
|
+
cardImage: Self.string(style.cardImage),
|
|
197
|
+
)
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
private static func string(_ display: StyleDisplay?) -> String? {
|
|
201
|
+
switch display {
|
|
202
|
+
case .list: "list"
|
|
203
|
+
case .grid: "grid"
|
|
204
|
+
case nil: nil
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
private static func string(_ rendering: ArtworkRendering?) -> String? {
|
|
209
|
+
switch rendering {
|
|
210
|
+
case .original: "original"
|
|
211
|
+
case .stencil: "stencil"
|
|
212
|
+
case nil: nil
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
private static func string(_ shape: ImageShape?) -> String? {
|
|
217
|
+
switch shape {
|
|
218
|
+
case .circular: "circular"
|
|
219
|
+
case .roundedRectangle: "rounded-rectangle"
|
|
220
|
+
case nil: nil
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
private static func string(_ mode: CardImage?) -> String? {
|
|
225
|
+
switch mode {
|
|
226
|
+
case .normal: "normal"
|
|
227
|
+
case .background: "background"
|
|
228
|
+
case nil: nil
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/// JSON model for a page section (ADR 0010). Legacy `groupTitle`/`imageRow`
|
|
234
|
+
/// keys in payloads are simply unknown to these models and decode as
|
|
235
|
+
/// ignored dead weight.
|
|
236
|
+
struct JsonSection: Codable {
|
|
237
|
+
let title: String?
|
|
238
|
+
let style: JsonStyle?
|
|
239
|
+
let path: String?
|
|
240
|
+
let children: [JsonTrack]
|
|
241
|
+
|
|
242
|
+
init(
|
|
243
|
+
title: String? = nil,
|
|
244
|
+
style: JsonStyle? = nil,
|
|
245
|
+
path: String? = nil,
|
|
246
|
+
children: [JsonTrack],
|
|
89
247
|
) {
|
|
90
|
-
self.id = id
|
|
91
|
-
self.url = url
|
|
92
|
-
self.src = src
|
|
93
|
-
self.artwork = artwork
|
|
94
248
|
self.title = title
|
|
95
|
-
self.
|
|
96
|
-
self.
|
|
97
|
-
self.
|
|
98
|
-
self.live = live
|
|
99
|
-
self.request = request
|
|
249
|
+
self.style = style
|
|
250
|
+
self.path = path
|
|
251
|
+
self.children = children
|
|
100
252
|
}
|
|
101
253
|
}
|
|
102
254
|
|
|
@@ -116,60 +268,63 @@ struct JsonTrackRequest: Codable {
|
|
|
116
268
|
/// JSON model for resolved track (container with children).
|
|
117
269
|
struct JsonResolvedTrack: Codable {
|
|
118
270
|
let id: String?
|
|
119
|
-
let
|
|
271
|
+
let path: String
|
|
120
272
|
let title: String
|
|
121
273
|
let subtitle: String?
|
|
122
274
|
let artwork: JsonArtwork?
|
|
123
275
|
let artist: String?
|
|
124
|
-
let
|
|
276
|
+
let albumPath: String?
|
|
125
277
|
let album: String?
|
|
126
278
|
let description: String?
|
|
127
279
|
let genre: String?
|
|
128
280
|
let duration: Double?
|
|
281
|
+
let sections: [JsonSection]?
|
|
129
282
|
let children: [JsonTrack]?
|
|
130
283
|
let src: String?
|
|
131
|
-
let style:
|
|
132
|
-
let
|
|
133
|
-
let groupTitle: String?
|
|
284
|
+
let style: JsonStyle?
|
|
285
|
+
let disabled: Bool?
|
|
134
286
|
let live: Bool?
|
|
287
|
+
let icyCharset: String?
|
|
135
288
|
let carPlaySiriListButton: String?
|
|
136
289
|
|
|
137
290
|
init(
|
|
138
291
|
id: String? = nil,
|
|
139
|
-
|
|
292
|
+
path: String,
|
|
140
293
|
title: String,
|
|
141
294
|
subtitle: String? = nil,
|
|
142
295
|
artwork: JsonArtwork? = nil,
|
|
143
296
|
artist: String? = nil,
|
|
144
|
-
|
|
297
|
+
albumPath: String? = nil,
|
|
145
298
|
album: String? = nil,
|
|
146
299
|
description: String? = nil,
|
|
147
300
|
genre: String? = nil,
|
|
148
301
|
duration: Double? = nil,
|
|
302
|
+
sections: [JsonSection]? = nil,
|
|
149
303
|
children: [JsonTrack]? = nil,
|
|
150
304
|
src: String? = nil,
|
|
151
|
-
style:
|
|
152
|
-
|
|
153
|
-
groupTitle: String? = nil,
|
|
305
|
+
style: JsonStyle? = nil,
|
|
306
|
+
disabled: Bool? = nil,
|
|
154
307
|
live: Bool? = nil,
|
|
308
|
+
icyCharset: String? = nil,
|
|
155
309
|
carPlaySiriListButton: String? = nil,
|
|
156
310
|
) {
|
|
157
|
-
self.
|
|
311
|
+
self.path = path
|
|
158
312
|
self.title = title
|
|
159
313
|
self.subtitle = subtitle
|
|
160
314
|
self.artwork = artwork
|
|
161
315
|
self.artist = artist
|
|
162
|
-
self.
|
|
316
|
+
self.albumPath = albumPath
|
|
163
317
|
self.album = album
|
|
164
318
|
self.description = description
|
|
165
319
|
self.genre = genre
|
|
166
320
|
self.duration = duration
|
|
321
|
+
self.sections = sections
|
|
167
322
|
self.children = children
|
|
168
323
|
self.src = src
|
|
169
324
|
self.style = style
|
|
170
|
-
self.
|
|
171
|
-
self.groupTitle = groupTitle
|
|
325
|
+
self.disabled = disabled
|
|
172
326
|
self.live = live
|
|
327
|
+
self.icyCharset = icyCharset
|
|
173
328
|
self.carPlaySiriListButton = carPlaySiriListButton
|
|
174
329
|
self.id = id
|
|
175
330
|
}
|
|
@@ -178,50 +333,48 @@ struct JsonResolvedTrack: Codable {
|
|
|
178
333
|
/// JSON model for individual tracks.
|
|
179
334
|
struct JsonTrack: Codable {
|
|
180
335
|
let id: String?
|
|
181
|
-
let
|
|
336
|
+
let path: String?
|
|
182
337
|
let title: String
|
|
183
338
|
let subtitle: String?
|
|
184
339
|
let artwork: JsonArtwork?
|
|
185
340
|
let artist: String?
|
|
186
|
-
let
|
|
341
|
+
let albumPath: String?
|
|
187
342
|
let album: String?
|
|
188
343
|
let description: String?
|
|
189
344
|
let genre: String?
|
|
190
345
|
let duration: Double?
|
|
191
346
|
let src: String?
|
|
192
347
|
let request: JsonTrackRequest?
|
|
193
|
-
let style:
|
|
194
|
-
let
|
|
195
|
-
let groupTitle: String?
|
|
348
|
+
let style: JsonStyle?
|
|
349
|
+
let disabled: Bool?
|
|
196
350
|
let live: Bool?
|
|
197
|
-
let
|
|
351
|
+
let icyCharset: String?
|
|
198
352
|
|
|
199
353
|
init(
|
|
200
354
|
id: String? = nil,
|
|
201
|
-
|
|
355
|
+
path: String? = nil,
|
|
202
356
|
title: String,
|
|
203
357
|
subtitle: String? = nil,
|
|
204
358
|
artwork: JsonArtwork? = nil,
|
|
205
359
|
artist: String? = nil,
|
|
206
|
-
|
|
360
|
+
albumPath: String? = nil,
|
|
207
361
|
album: String? = nil,
|
|
208
362
|
description: String? = nil,
|
|
209
363
|
genre: String? = nil,
|
|
210
364
|
duration: Double? = nil,
|
|
211
365
|
src: String? = nil,
|
|
212
366
|
request: JsonTrackRequest? = nil,
|
|
213
|
-
style:
|
|
214
|
-
|
|
215
|
-
groupTitle: String? = nil,
|
|
367
|
+
style: JsonStyle? = nil,
|
|
368
|
+
disabled: Bool? = nil,
|
|
216
369
|
live: Bool? = nil,
|
|
217
|
-
|
|
370
|
+
icyCharset: String? = nil,
|
|
218
371
|
) {
|
|
219
|
-
self.
|
|
372
|
+
self.path = path
|
|
220
373
|
self.title = title
|
|
221
374
|
self.subtitle = subtitle
|
|
222
375
|
self.artwork = artwork
|
|
223
376
|
self.artist = artist
|
|
224
|
-
self.
|
|
377
|
+
self.albumPath = albumPath
|
|
225
378
|
self.album = album
|
|
226
379
|
self.description = description
|
|
227
380
|
self.genre = genre
|
|
@@ -229,10 +382,9 @@ struct JsonTrack: Codable {
|
|
|
229
382
|
self.src = src
|
|
230
383
|
self.request = request
|
|
231
384
|
self.style = style
|
|
232
|
-
self.
|
|
233
|
-
self.groupTitle = groupTitle
|
|
385
|
+
self.disabled = disabled
|
|
234
386
|
self.live = live
|
|
235
|
-
self.
|
|
387
|
+
self.icyCharset = icyCharset
|
|
236
388
|
self.id = id
|
|
237
389
|
}
|
|
238
390
|
}
|
|
@@ -250,26 +402,28 @@ struct JsonTrack: Codable {
|
|
|
250
402
|
|
|
251
403
|
extension JsonTrack {
|
|
252
404
|
/// Snapshot the persistable subset of a live Track (inverse of `toNitro()`).
|
|
405
|
+
/// The track's own declared style block and `disabled` persist (ADR 0011);
|
|
406
|
+
/// section/page-inherited values are never stamped onto tracks and
|
|
407
|
+
/// re-resolve at render, exactly as they do live.
|
|
253
408
|
init(from track: Track) {
|
|
254
409
|
self.init(
|
|
255
410
|
id: track.id,
|
|
256
|
-
|
|
411
|
+
path: track.path,
|
|
257
412
|
title: track.title,
|
|
258
413
|
subtitle: track.subtitle,
|
|
259
414
|
artwork: JsonArtwork(track.artwork),
|
|
260
415
|
artist: track.artist,
|
|
261
|
-
|
|
416
|
+
albumPath: track.albumPath,
|
|
262
417
|
album: track.album,
|
|
263
418
|
description: track.description,
|
|
264
419
|
genre: track.genre,
|
|
265
420
|
duration: track.duration,
|
|
266
421
|
src: track.src,
|
|
267
422
|
request: track.request.map(JsonTrackRequest.init(from:)),
|
|
268
|
-
style:
|
|
269
|
-
|
|
270
|
-
groupTitle: track.groupTitle,
|
|
423
|
+
style: JsonStyle(track.style),
|
|
424
|
+
disabled: track.disabled,
|
|
271
425
|
live: track.live,
|
|
272
|
-
|
|
426
|
+
icyCharset: track.icyCharset,
|
|
273
427
|
)
|
|
274
428
|
}
|
|
275
429
|
}
|
|
@@ -289,15 +443,18 @@ struct JsonTrack: Codable {
|
|
|
289
443
|
init(from track: Track) {
|
|
290
444
|
self.init(
|
|
291
445
|
id: track.id,
|
|
292
|
-
|
|
446
|
+
path: track.path,
|
|
293
447
|
title: track.title,
|
|
294
448
|
artwork: JsonArtwork(track.artwork),
|
|
295
449
|
artist: track.artist,
|
|
296
|
-
|
|
450
|
+
albumPath: track.albumPath,
|
|
297
451
|
album: track.album,
|
|
298
452
|
src: track.src,
|
|
299
453
|
request: track.request.map(JsonTrackRequest.init(from:)),
|
|
454
|
+
style: JsonStyle(track.style),
|
|
455
|
+
disabled: track.disabled,
|
|
300
456
|
live: track.live,
|
|
457
|
+
icyCharset: track.icyCharset,
|
|
301
458
|
)
|
|
302
459
|
}
|
|
303
460
|
}
|
|
@@ -308,26 +465,13 @@ struct JsonTrack: Codable {
|
|
|
308
465
|
|
|
309
466
|
#if canImport(NitroModules)
|
|
310
467
|
|
|
311
|
-
|
|
312
|
-
func
|
|
313
|
-
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
extension JsonImageRowItem {
|
|
318
|
-
func toNitro() -> ImageRowItem {
|
|
319
|
-
ImageRowItem(
|
|
320
|
-
id: id,
|
|
321
|
-
url: url,
|
|
322
|
-
src: src,
|
|
323
|
-
artwork: artwork,
|
|
324
|
-
artworkSource: nil,
|
|
468
|
+
extension JsonSection {
|
|
469
|
+
func toNitro() -> Section {
|
|
470
|
+
Section(
|
|
325
471
|
title: title,
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
live: live,
|
|
330
|
-
request: request?.toNitro(),
|
|
472
|
+
style: style?.toSectionStyle(),
|
|
473
|
+
path: path,
|
|
474
|
+
children: children.map { $0.toNitro() },
|
|
331
475
|
)
|
|
332
476
|
}
|
|
333
477
|
}
|
|
@@ -335,28 +479,27 @@ struct JsonTrack: Codable {
|
|
|
335
479
|
extension JsonResolvedTrack {
|
|
336
480
|
func toNitro() -> ResolvedTrack {
|
|
337
481
|
ResolvedTrack(
|
|
338
|
-
|
|
482
|
+
path: path,
|
|
483
|
+
style: style?.toSectionStyle(),
|
|
484
|
+
sections: sections?.map { $0.toNitro() },
|
|
339
485
|
children: children?.map { $0.toNitro() },
|
|
340
486
|
carPlaySiriListButton: carPlaySiriListButton.flatMap { CarPlaySiriListButtonPosition(fromString: $0) },
|
|
341
487
|
id: id,
|
|
342
488
|
src: src,
|
|
343
489
|
artwork: artwork?.toNitro(),
|
|
344
490
|
artworkSource: nil, request: nil,
|
|
345
|
-
artworkCarPlayTinted: nil,
|
|
346
491
|
title: title,
|
|
347
492
|
subtitle: subtitle,
|
|
348
493
|
artist: artist,
|
|
349
|
-
|
|
494
|
+
albumPath: albumPath,
|
|
350
495
|
album: album,
|
|
351
496
|
description: description,
|
|
352
497
|
genre: genre,
|
|
353
498
|
duration: duration,
|
|
354
|
-
|
|
355
|
-
childrenStyle: childrenStyle?.toTrackStyle(),
|
|
499
|
+
disabled: disabled,
|
|
356
500
|
favorited: nil,
|
|
357
|
-
groupTitle: groupTitle,
|
|
358
501
|
live: live,
|
|
359
|
-
|
|
502
|
+
icyCharset: icyCharset,
|
|
360
503
|
)
|
|
361
504
|
}
|
|
362
505
|
}
|
|
@@ -365,26 +508,24 @@ struct JsonTrack: Codable {
|
|
|
365
508
|
func toNitro() -> Track {
|
|
366
509
|
Track(
|
|
367
510
|
id: id,
|
|
368
|
-
|
|
511
|
+
path: path,
|
|
369
512
|
src: src,
|
|
370
513
|
artwork: artwork?.toNitro(),
|
|
371
514
|
artworkSource: nil,
|
|
372
515
|
request: request?.toNitro(),
|
|
373
|
-
artworkCarPlayTinted: nil,
|
|
374
516
|
title: title,
|
|
375
517
|
subtitle: subtitle,
|
|
376
518
|
artist: artist,
|
|
377
|
-
|
|
519
|
+
albumPath: albumPath,
|
|
378
520
|
album: album,
|
|
379
521
|
description: description,
|
|
380
522
|
genre: genre,
|
|
381
523
|
duration: duration,
|
|
382
524
|
style: style?.toTrackStyle(),
|
|
383
|
-
|
|
525
|
+
disabled: disabled,
|
|
384
526
|
favorited: nil,
|
|
385
|
-
groupTitle: groupTitle,
|
|
386
527
|
live: live,
|
|
387
|
-
|
|
528
|
+
icyCharset: icyCharset,
|
|
388
529
|
)
|
|
389
530
|
}
|
|
390
531
|
}
|
|
@@ -396,15 +537,29 @@ struct JsonTrack: Codable {
|
|
|
396
537
|
func toNitro() -> Track {
|
|
397
538
|
Track(
|
|
398
539
|
id: id ?? "",
|
|
399
|
-
|
|
540
|
+
path: path,
|
|
400
541
|
src: src,
|
|
542
|
+
artwork: artwork?.toNitro(),
|
|
401
543
|
request: request.map { TrackRequest(userAgent: $0.userAgent, headers: $0.headers, query: $0.query) },
|
|
402
544
|
title: title,
|
|
403
545
|
artist: artist,
|
|
404
|
-
|
|
546
|
+
albumPath: albumPath,
|
|
405
547
|
album: album,
|
|
548
|
+
style: style?.toTrackStyle(),
|
|
549
|
+
disabled: disabled,
|
|
406
550
|
live: live,
|
|
407
|
-
|
|
551
|
+
icyCharset: icyCharset,
|
|
552
|
+
)
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
extension JsonSection {
|
|
557
|
+
func toNitro() -> Section {
|
|
558
|
+
Section(
|
|
559
|
+
title: title,
|
|
560
|
+
style: style?.toSectionStyle(),
|
|
561
|
+
path: path,
|
|
562
|
+
children: children.map { $0.toNitro() },
|
|
408
563
|
)
|
|
409
564
|
}
|
|
410
565
|
}
|
|
@@ -412,10 +567,13 @@ struct JsonTrack: Codable {
|
|
|
412
567
|
extension JsonResolvedTrack {
|
|
413
568
|
func toNitro() -> ResolvedTrack {
|
|
414
569
|
ResolvedTrack(
|
|
415
|
-
|
|
570
|
+
path: path,
|
|
571
|
+
style: style?.toSectionStyle(),
|
|
572
|
+
sections: sections?.map { $0.toNitro() },
|
|
416
573
|
children: children?.map { $0.toNitro() },
|
|
417
574
|
artwork: artwork?.toNitro(),
|
|
418
575
|
title: title,
|
|
576
|
+
disabled: disabled,
|
|
419
577
|
)
|
|
420
578
|
}
|
|
421
579
|
}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import Foundation
|
|
2
2
|
|
|
3
3
|
/// A search result that may or may not be directly playable. `src` is the
|
|
4
|
-
/// playable stream; `
|
|
4
|
+
/// playable stream; `path` is a browsable container path. Abstracting these two
|
|
5
5
|
/// fields keeps the drill-in decision free of the Nitro `Track` type so it can
|
|
6
6
|
/// be unit-tested.
|
|
7
7
|
protocol PlayableSearchItem {
|
|
8
8
|
var src: String? { get }
|
|
9
|
-
var
|
|
9
|
+
var path: String? { get }
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
enum SearchDrillIn {
|
|
13
13
|
/// Picks the playable items for a "play «X»" voice search.
|
|
14
14
|
///
|
|
15
|
-
/// If the first result is browsable-only (a `
|
|
15
|
+
/// If the first result is browsable-only (a `path` container with no `src` — a
|
|
16
16
|
/// place/genre page), drills into it via `resolveChildren` and uses its
|
|
17
17
|
/// playable children, so we play the first station *inside* the page rather
|
|
18
18
|
/// than skipping the page for a later inline station. Falls back to the flat
|
|
@@ -20,13 +20,13 @@ enum SearchDrillIn {
|
|
|
20
20
|
/// yields nothing. Returns nil when nothing is playable.
|
|
21
21
|
static func playable<Item: PlayableSearchItem>(
|
|
22
22
|
from children: [Item],
|
|
23
|
-
resolveChildren: sending (String) async throws -> [Item]
|
|
23
|
+
resolveChildren: sending (String) async throws -> [Item],
|
|
24
24
|
) async throws -> [Item]? {
|
|
25
25
|
guard !children.isEmpty else { return nil }
|
|
26
26
|
|
|
27
27
|
let candidates: [Item]
|
|
28
|
-
if let first = children.first, first.src == nil, let
|
|
29
|
-
let drilled = try await resolveChildren(
|
|
28
|
+
if let first = children.first, first.src == nil, let path = first.path {
|
|
29
|
+
let drilled = try await resolveChildren(path).filter { $0.src != nil }
|
|
30
30
|
candidates = drilled.isEmpty ? children : drilled
|
|
31
31
|
} else {
|
|
32
32
|
candidates = children
|
|
@@ -37,7 +37,7 @@ enum SearchDrillIn {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
// The real Nitro `Track` already carries `src`/`
|
|
40
|
+
// The real Nitro `Track` already carries `src`/`path`; conform it for the app
|
|
41
41
|
// build. (The testable target builds without NitroModules and uses a stub item.)
|
|
42
42
|
#if canImport(NitroModules)
|
|
43
43
|
extension Track: PlayableSearchItem {}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
#if canImport(NitroModules)
|
|
2
|
+
import NitroModules
|
|
3
|
+
#endif
|
|
4
|
+
|
|
5
|
+
/// The rendered form of a section — the single place where (resolved style,
|
|
6
|
+
/// platform capability) maps to what CarPlay draws. Degradation drops
|
|
7
|
+
/// decorations before layout (ADR 0011): a *wrapping* grid can only reach the
|
|
8
|
+
/// tile path where the platform has a wrapping tile container (CarPlay:
|
|
9
|
+
/// iOS 26+'s element API); without one it becomes a list, where every item
|
|
10
|
+
/// stays reachable instead of truncating at an unknowable width. A
|
|
11
|
+
/// single-line grid (`gridWrap: false`) renders everywhere — the legacy image
|
|
12
|
+
/// row IS the single-line presentation.
|
|
13
|
+
enum SectionPresentation: Equatable {
|
|
14
|
+
case list
|
|
15
|
+
case singleLineRow
|
|
16
|
+
case wrappingGrid
|
|
17
|
+
|
|
18
|
+
/// - Parameter supportsWrappingGrid: whether the platform has a wrapping
|
|
19
|
+
/// tile container. Injected (rather than read via `#available` here) so
|
|
20
|
+
/// the mapping is testable off-device.
|
|
21
|
+
init(for style: SectionStyle?, supportsWrappingGrid: Bool) {
|
|
22
|
+
guard style?.display == .grid else {
|
|
23
|
+
self = .list
|
|
24
|
+
return
|
|
25
|
+
}
|
|
26
|
+
if style?.gridWrap == false {
|
|
27
|
+
self = .singleLineRow
|
|
28
|
+
} else if supportsWrappingGrid {
|
|
29
|
+
self = .wrappingGrid
|
|
30
|
+
} else {
|
|
31
|
+
self = .list
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/// The accessory symbol a resolved block actually draws: nil when
|
|
36
|
+
/// undeclared, and nil for the `'none'` sentinel — the inheritance escape
|
|
37
|
+
/// that restores the derived accessory (a browsable row's chevron). Here,
|
|
38
|
+
/// not in the CarPlay factory, so the sentinel rule is testable off-device.
|
|
39
|
+
static func effectiveAccessorySymbol(_ style: TrackStyle?) -> String? {
|
|
40
|
+
guard let symbol = style?.accessorySymbol, symbol != "none" else { return nil }
|
|
41
|
+
return symbol
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/// The element family a tile presentation renders on iOS 26+ — here, not
|
|
45
|
+
/// in the CarPlay factory, so the style→family mapping is testable
|
|
46
|
+
/// off-device. `gridTile` picks the family (plain by default); the plain
|
|
47
|
+
/// single-line shelf keeps row elements, the one plain element with a
|
|
48
|
+
/// subtitle slot. Pre-26 has no element API at all: the treatment drops
|
|
49
|
+
/// with the legacy image row (decorations drop before layout).
|
|
50
|
+
enum TileElementFamily: Equatable {
|
|
51
|
+
case rowElements
|
|
52
|
+
case imageGridElements
|
|
53
|
+
case cardElements
|
|
54
|
+
case condensedElements
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
static func tileFamily(for style: SectionStyle?, singleLine: Bool) -> TileElementFamily {
|
|
58
|
+
switch style?.gridTile {
|
|
59
|
+
case .card: .cardElements
|
|
60
|
+
case .condensed: .condensedElements
|
|
61
|
+
case .plain, nil: singleLine ? .rowElements : .imageGridElements
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|