react-native-audio-browser 0.2.0-next.2 → 0.2.0-next.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -21
- package/android/build.gradle +35 -12
- package/android/gradle.properties +2 -2
- package/android/src/main/AndroidManifest.xml +3 -1
- package/android/src/main/java/com/audiobrowser/AudioBrowser.kt +389 -164
- package/android/src/main/java/com/audiobrowser/AudioBrowserLifecycleModule.kt +38 -0
- package/android/src/main/java/com/audiobrowser/AudioBrowserPackage.kt +18 -2
- package/android/src/main/java/com/audiobrowser/ServiceBinding.kt +48 -0
- package/android/src/main/java/com/audiobrowser/browser/BrowserManager.kt +315 -213
- package/android/src/main/java/com/audiobrowser/browser/BrowserUrlResolution.kt +24 -5
- package/android/src/main/java/com/audiobrowser/browser/InertStyleDiagnostic.kt +267 -0
- package/android/src/main/java/com/audiobrowser/browser/JsonModels.kt +97 -58
- package/android/src/main/java/com/audiobrowser/browser/SectionScope.kt +70 -29
- package/android/src/main/java/com/audiobrowser/browser/StyleResolver.kt +60 -0
- package/android/src/main/java/com/audiobrowser/extension/ResolvedTrackExt.kt +20 -7
- package/android/src/main/java/com/audiobrowser/extension/TappedTrack.kt +20 -0
- package/android/src/main/java/com/audiobrowser/extension/TrackIdentity.kt +15 -0
- package/android/src/main/java/com/audiobrowser/http/HttpClient.kt +20 -3
- package/android/src/main/java/com/audiobrowser/model/IcyTitle.kt +24 -0
- package/android/src/main/java/com/audiobrowser/model/PlaybackMetadata.kt +10 -6
- package/android/src/main/java/com/audiobrowser/model/PlayerUpdateOptions.kt +12 -12
- package/android/src/main/java/com/audiobrowser/player/CapabilityControls.kt +111 -58
- package/android/src/main/java/com/audiobrowser/player/CrossOriginHeaderStripper.kt +77 -0
- package/android/src/main/java/com/audiobrowser/player/MediaFactory.kt +28 -10
- package/android/src/main/java/com/audiobrowser/player/MediaSessionCallback.kt +509 -230
- package/android/src/main/java/com/audiobrowser/player/MediaSessionCommandManager.kt +218 -252
- package/android/src/main/java/com/audiobrowser/player/NowPlayingUpdater.kt +21 -25
- package/android/src/main/java/com/audiobrowser/player/PlaybackStateStore.kt +113 -78
- package/android/src/main/java/com/audiobrowser/player/Player.kt +81 -38
- package/android/src/main/java/com/audiobrowser/player/PlayerCapabilitiesExt.kt +2 -15
- package/android/src/main/java/com/audiobrowser/player/PlayerListener.kt +1 -1
- package/android/src/main/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicy.kt +2 -1
- package/android/src/main/java/com/audiobrowser/player/ShuffleOrderLedBy.kt +30 -0
- package/android/src/main/java/com/audiobrowser/tls/AiaCertChaser.kt +67 -11
- package/android/src/main/java/com/audiobrowser/tls/AiaChasingExtendedTrustManager.kt +168 -0
- package/android/src/main/java/com/audiobrowser/tls/AiaChasingTrustManager.kt +58 -14
- package/android/src/main/java/com/audiobrowser/tls/AiaTls.kt +35 -7
- package/android/src/main/java/com/audiobrowser/tls/CachingCertificateFetcher.kt +278 -59
- package/android/src/main/java/com/audiobrowser/util/ArtworkVariant.kt +7 -9
- package/android/src/main/java/com/audiobrowser/util/BrowserPathHelper.kt +56 -40
- package/android/src/main/java/com/audiobrowser/util/MediaExtrasBuilder.kt +28 -23
- package/android/src/main/java/com/audiobrowser/util/StyleWire.kt +108 -0
- package/android/src/main/java/com/audiobrowser/util/TrackFactory.kt +56 -52
- package/android/src/main/res/values/strings.xml +25 -5
- package/android/src/test/java/com/audiobrowser/ServiceBindingTest.kt +87 -0
- package/android/src/test/java/com/audiobrowser/TestFixtures.kt +119 -33
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerFavoritesTest.kt +153 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerLayerResolutionTest.kt +15 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerTest.kt +346 -8
- package/android/src/test/java/com/audiobrowser/browser/BrowserUrlResolutionTest.kt +38 -0
- package/android/src/test/java/com/audiobrowser/browser/InertStyleDiagnosticTest.kt +277 -0
- package/android/src/test/java/com/audiobrowser/browser/JsonArtworkTest.kt +3 -2
- package/android/src/test/java/com/audiobrowser/browser/JsonStyleTest.kt +147 -0
- package/android/src/test/java/com/audiobrowser/browser/SectionScopeTest.kt +128 -55
- package/android/src/test/java/com/audiobrowser/browser/StyleResolverTest.kt +154 -0
- package/android/src/test/java/com/audiobrowser/extension/TappedTrackTest.kt +43 -0
- package/android/src/test/java/com/audiobrowser/extension/TrackIdentityTest.kt +41 -0
- package/android/src/test/java/com/audiobrowser/model/IcyTitleTest.kt +49 -0
- package/android/src/test/java/com/audiobrowser/player/BrowseTilesTest.kt +385 -0
- package/android/src/test/java/com/audiobrowser/player/CapabilityControlsTest.kt +101 -58
- package/android/src/test/java/com/audiobrowser/player/CrossOriginHeaderStripperTest.kt +94 -0
- package/android/src/test/java/com/audiobrowser/player/MediaSessionSlotMappingTest.kt +45 -0
- package/android/src/test/java/com/audiobrowser/player/NowPlayingUpdaterTest.kt +42 -2
- package/android/src/test/java/com/audiobrowser/player/PlaybackErrorClassifierTest.kt +3 -4
- package/android/src/test/java/com/audiobrowser/player/PlaybackStateStoreTrackJsonTest.kt +55 -0
- package/android/src/test/java/com/audiobrowser/player/RetryLoadErrorHandlingPolicyTest.kt +3 -3
- package/android/src/test/java/com/audiobrowser/player/ShuffleOrderLedByTest.kt +79 -0
- package/android/src/test/java/com/audiobrowser/tls/AiaCertChaserTest.kt +197 -7
- package/android/src/test/java/com/audiobrowser/tls/AiaChasingTrustManagerTest.kt +325 -4
- package/android/src/test/java/com/audiobrowser/tls/CachingCertificateFetcherCallSiteTest.kt +322 -0
- package/android/src/test/java/com/audiobrowser/tls/CachingCertificateFetcherTest.kt +83 -0
- package/android/src/test/java/com/audiobrowser/util/BrowserPathHelperTest.kt +41 -16
- package/android/src/test/java/com/audiobrowser/util/MediaExtrasBuilderTest.kt +162 -0
- package/android/src/test/java/com/audiobrowser/util/TrackFactoryMediaIdTest.kt +7 -7
- package/ios/Browser/BrowserConfig.swift +102 -5
- package/ios/Browser/BrowserManager+URLResolution.swift +18 -14
- package/ios/Browser/BrowserManager.swift +230 -205
- package/ios/Browser/BrowserPathHelper.swift +44 -44
- package/ios/Browser/InertStyleDiagnostic.swift +279 -0
- package/ios/Browser/JsonModels.swift +264 -106
- package/ios/Browser/SearchDrillIn.swift +7 -7
- package/ios/Browser/SectionPresentation.swift +64 -0
- package/ios/Browser/SectionScope.swift +58 -24
- package/ios/Browser/StyleResolver.swift +58 -0
- package/ios/Browser/TabBarEntries.swift +9 -3
- package/ios/Browser/TrackIdTemplate.swift +37 -0
- package/ios/CarPlay/CarPlayArtworkResolver.swift +8 -7
- package/ios/CarPlay/CarPlayController.swift +227 -85
- package/ios/CarPlay/CarPlayImageLoader.swift +42 -20
- package/ios/CarPlay/CarPlayListItemFactory.swift +289 -84
- package/ios/CarPlay/CarPlayNowPlayingManager.swift +15 -12
- package/ios/CarPlay/RNABMediaAddHandler.swift +6 -6
- package/ios/CarPlay/RNABMediaAffinityHandler.swift +2 -2
- package/ios/CarPlay/RNABMediaIntentHandler.swift +16 -16
- package/ios/Extension/Capability+RemoteCommand.swift +1 -1
- package/ios/Extension/PlayerCapabilities+Favorite.swift +1 -15
- package/ios/Extension/ResolvedTrack+Copying.swift +13 -15
- package/ios/Extension/Section+Copying.swift +29 -0
- package/ios/Extension/String+IcyCharset.swift +21 -0
- package/ios/Extension/TimedMetadata+AVFoundation.swift +6 -4
- package/ios/Extension/Track+Copying.swift +8 -12
- package/ios/Extension/Track+Identity.swift +18 -0
- package/ios/Extension/UIApplication+ActiveScene.swift +27 -0
- package/ios/Http/HttpClient.swift +8 -2
- package/ios/HybridAudioBrowser.swift +253 -100
- package/ios/Model/NitroTypeStubs.swift +125 -23
- package/ios/Model/PlayerUpdateOptions.swift +7 -0
- package/ios/Model/RemoteCommand.swift +18 -0
- package/ios/Model/TrackPlayerError.swift +2 -2
- package/ios/Option/SessionCategories.swift +3 -2
- package/ios/Player/MediaIntentCriteria.swift +17 -9
- package/ios/Player/MediaLoader.swift +33 -9
- package/ios/Player/NowPlayingUpdater.swift +54 -6
- package/ios/Player/PlaybackCoordinator.swift +13 -6
- package/ios/Player/PlaybackErrorHandler.swift +4 -4
- package/ios/Player/PlaybackTimer.swift +8 -2
- package/ios/Player/QueueManager.swift +46 -13
- package/ios/Player/RetryManager.swift +80 -18
- package/ios/Player/SeekCompletionHandler.swift +3 -1
- package/ios/Player/ShuffleOrder.swift +33 -0
- package/ios/Player/SleepTimerHandling.swift +13 -0
- package/ios/RemoteCommand/RemoteCommandCallbacks.swift +47 -0
- package/ios/RemoteCommand/RemoteCommandController.swift +62 -24
- package/ios/Tests/BrowserPathHelperTests.swift +50 -20
- package/ios/Tests/CarPlayArtworkResolverTests.swift +24 -41
- package/ios/Tests/InertStyleDiagnosticTests.swift +200 -0
- package/ios/Tests/JsonModelsTests.swift +150 -1
- package/ios/Tests/LRUCacheTests.swift +111 -0
- package/ios/Tests/LoadSeekCoordinatorTests.swift +3 -1
- package/ios/Tests/MediaIntentCriteriaTests.swift +2 -2
- package/ios/Tests/PlaybackCoordinatorTests.swift +1 -1
- package/ios/Tests/PlaybackErrorHandlerTests.swift +3 -1
- package/ios/Tests/PlaybackStateStoreTests.swift +4 -3
- package/ios/Tests/PlayerTimeObserverTests.swift +37 -0
- package/ios/Tests/QueueManagerTests.swift +122 -10
- package/ios/Tests/RemoteCommandControllerTests.swift +172 -0
- package/ios/Tests/RemoteCommandTests.swift +67 -0
- package/ios/Tests/ResolvedTrackCopyingTests.swift +39 -35
- package/ios/Tests/RetryManagerTests.swift +89 -0
- package/ios/Tests/SearchDrillInTests.swift +16 -16
- package/ios/Tests/SectionPresentationTests.swift +90 -0
- package/ios/Tests/SectionScopeTests.swift +87 -55
- package/ios/Tests/StyleResolverTests.swift +127 -0
- package/ios/Tests/Support/TestTypes.swift +8 -1
- package/ios/Tests/TabBarEntriesTests.swift +19 -19
- package/ios/Tests/TimedMetadataAVFoundationTests.swift +42 -0
- package/ios/Tests/TrackIdTemplateTests.swift +67 -0
- package/ios/Tests/TrackIdentityTests.swift +20 -0
- package/ios/Tests/TrackSelectorTests.swift +168 -33
- package/ios/TrackPlayer.swift +63 -35
- package/ios/TrackPlayerCallbacks.swift +5 -38
- package/ios/TrackSelector.swift +45 -30
- package/ios/Util/ArtworkImageFetcher.swift +16 -1
- package/ios/Util/LRUCache.swift +4 -1
- package/ios/Util/NetworkMonitor.swift +43 -26
- package/ios/Util/SFSymbolRenderer.swift +24 -2
- package/ios/Util/SVGProcessor.swift +9 -2
- package/lib/commonjs/AudioBrowser.js +8 -8
- package/lib/commonjs/AudioBrowser.js.map +1 -1
- package/lib/commonjs/CLAUDE.md +52 -0
- package/lib/commonjs/features/browser-config.js +12 -8
- package/lib/commonjs/features/browser-config.js.map +1 -1
- package/lib/commonjs/features/browser.js +11 -3
- package/lib/commonjs/features/browser.js.map +1 -1
- package/lib/commonjs/features/carConnection.js +1 -1
- package/lib/commonjs/features/equalizer.js +1 -1
- package/lib/commonjs/features/errors.js +3 -3
- package/lib/commonjs/features/favorites.js +14 -11
- package/lib/commonjs/features/favorites.js.map +1 -1
- package/lib/commonjs/features/gate.js +16 -1
- package/lib/commonjs/features/gate.js.map +1 -1
- package/lib/commonjs/features/metadata.js +20 -3
- package/lib/commonjs/features/metadata.js.map +1 -1
- package/lib/commonjs/features/network.js +1 -1
- package/lib/commonjs/features/nowPlaying.js +1 -1
- package/lib/commonjs/features/output.js +1 -1
- package/lib/commonjs/features/playback/controls.js +4 -2
- package/lib/commonjs/features/playback/controls.js.map +1 -1
- package/lib/commonjs/features/playback/playWhenReady.js +1 -1
- package/lib/commonjs/features/playback/playing.js +1 -1
- package/lib/commonjs/features/playback/progress.js +3 -2
- package/lib/commonjs/features/playback/progress.js.map +1 -1
- package/lib/commonjs/features/playback/rate.js +8 -1
- package/lib/commonjs/features/playback/rate.js.map +1 -1
- package/lib/commonjs/features/playback/state.js +3 -4
- package/lib/commonjs/features/playback/state.js.map +1 -1
- package/lib/commonjs/features/playback/trackPlaybackTime.js +0 -6
- package/lib/commonjs/features/playback/trackPlaybackTime.js.map +1 -1
- package/lib/commonjs/features/playback/volume.js +1 -1
- package/lib/commonjs/features/player/options.js +48 -34
- package/lib/commonjs/features/player/options.js.map +1 -1
- package/lib/commonjs/features/player/setup.js +18 -9
- package/lib/commonjs/features/player/setup.js.map +1 -1
- package/lib/commonjs/features/player/validateOptions.js +23 -0
- package/lib/commonjs/features/player/validateOptions.js.map +1 -0
- package/lib/commonjs/features/queue/activeTrack.js +15 -4
- package/lib/commonjs/features/queue/activeTrack.js.map +1 -1
- package/lib/commonjs/features/queue/queue.js +13 -6
- package/lib/commonjs/features/queue/queue.js.map +1 -1
- package/lib/commonjs/features/queue/repeatMode.js +1 -1
- package/lib/commonjs/features/queue/shuffle.js +1 -1
- package/lib/commonjs/features/remoteControls.js +13 -92
- package/lib/commonjs/features/remoteControls.js.map +1 -1
- package/lib/commonjs/features/sleepTimer.js +13 -1
- package/lib/commonjs/features/sleepTimer.js.map +1 -1
- package/lib/commonjs/test-utils/reactNativeStub.js +65 -0
- package/lib/commonjs/test-utils/reactNativeStub.js.map +1 -0
- package/lib/commonjs/utils/LazyNativeEmitter.js +28 -14
- package/lib/commonjs/utils/LazyNativeEmitter.js.map +1 -1
- package/lib/commonjs/utils/NativeUpdatedValue.js +31 -13
- package/lib/commonjs/utils/NativeUpdatedValue.js.map +1 -1
- package/lib/commonjs/utils/getTrackIdentity.js +24 -0
- package/lib/commonjs/utils/getTrackIdentity.js.map +1 -0
- package/lib/commonjs/utils/useNativeValueRefreshedBy.js +33 -0
- package/lib/commonjs/utils/useNativeValueRefreshedBy.js.map +1 -0
- package/lib/commonjs/web/NativeAudioBrowser.js +200 -75
- package/lib/commonjs/web/NativeAudioBrowser.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/LoadAttempt.js +37 -0
- package/lib/commonjs/web/TrackPlayer/LoadAttempt.js.map +1 -0
- package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js +18 -2
- package/lib/commonjs/web/TrackPlayer/PlaybackStateMachine.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/Player.js +254 -39
- package/lib/commonjs/web/TrackPlayer/Player.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/QueueManager.js +14 -0
- package/lib/commonjs/web/TrackPlayer/QueueManager.js.map +1 -1
- package/lib/commonjs/web/TrackPlayer/QueuePlayer.js +33 -12
- package/lib/commonjs/web/TrackPlayer/QueuePlayer.js.map +1 -1
- package/lib/commonjs/web/browser/BrowserManager.js +175 -100
- package/lib/commonjs/web/browser/BrowserManager.js.map +1 -1
- package/lib/commonjs/web/browser/FavoriteManager.js +30 -21
- package/lib/commonjs/web/browser/FavoriteManager.js.map +1 -1
- package/lib/commonjs/web/browser/SearchManager.js +18 -23
- package/lib/commonjs/web/browser/SearchManager.js.map +1 -1
- package/lib/commonjs/web/browser/assertBrowsePageShape.js +2 -2
- package/lib/commonjs/web/browser/assertBrowsePageShape.js.map +1 -1
- package/lib/commonjs/web/browser/classifyTrackNavigation.js +9 -9
- package/lib/commonjs/web/browser/classifyTrackNavigation.js.map +1 -1
- package/lib/commonjs/web/browser/sections.js +89 -0
- package/lib/commonjs/web/browser/sections.js.map +1 -0
- package/lib/commonjs/web/http/RequestConfigBuilder.js +110 -27
- package/lib/commonjs/web/http/RequestConfigBuilder.js.map +1 -1
- package/lib/commonjs/web/http/followMediaRedirect.js +219 -0
- package/lib/commonjs/web/http/followMediaRedirect.js.map +1 -0
- package/lib/commonjs/web/player/NowPlayingManager.js +4 -3
- package/lib/commonjs/web/player/NowPlayingManager.js.map +1 -1
- package/lib/commonjs/web/util/BrowserPathHelper.js +56 -11
- package/lib/commonjs/web/util/BrowserPathHelper.js.map +1 -1
- package/lib/module/AudioBrowser.js +2 -1
- package/lib/module/AudioBrowser.js.map +1 -1
- package/lib/module/CLAUDE.md +52 -0
- package/lib/module/features/browser-config.js +12 -8
- package/lib/module/features/browser-config.js.map +1 -1
- package/lib/module/features/browser.js +11 -3
- package/lib/module/features/browser.js.map +1 -1
- package/lib/module/features/carConnection.js +1 -1
- package/lib/module/features/equalizer.js +1 -1
- package/lib/module/features/errors.js +3 -3
- package/lib/module/features/favorites.js +14 -11
- package/lib/module/features/favorites.js.map +1 -1
- package/lib/module/features/gate.js +16 -1
- package/lib/module/features/gate.js.map +1 -1
- package/lib/module/features/metadata.js +20 -3
- package/lib/module/features/metadata.js.map +1 -1
- package/lib/module/features/network.js +1 -1
- package/lib/module/features/nowPlaying.js +1 -1
- package/lib/module/features/output.js +1 -1
- package/lib/module/features/playback/controls.js +4 -2
- package/lib/module/features/playback/controls.js.map +1 -1
- package/lib/module/features/playback/playWhenReady.js +1 -1
- package/lib/module/features/playback/playing.js +1 -1
- package/lib/module/features/playback/progress.js +3 -2
- package/lib/module/features/playback/progress.js.map +1 -1
- package/lib/module/features/playback/rate.js +8 -1
- package/lib/module/features/playback/rate.js.map +1 -1
- package/lib/module/features/playback/state.js +3 -4
- package/lib/module/features/playback/state.js.map +1 -1
- package/lib/module/features/playback/trackPlaybackTime.js +0 -5
- package/lib/module/features/playback/trackPlaybackTime.js.map +1 -1
- package/lib/module/features/playback/volume.js +1 -1
- package/lib/module/features/player/options.js +47 -32
- package/lib/module/features/player/options.js.map +1 -1
- package/lib/module/features/player/setup.js +17 -8
- package/lib/module/features/player/setup.js.map +1 -1
- package/lib/module/features/player/validateOptions.js +19 -0
- package/lib/module/features/player/validateOptions.js.map +1 -0
- package/lib/module/features/queue/activeTrack.js +15 -4
- package/lib/module/features/queue/activeTrack.js.map +1 -1
- package/lib/module/features/queue/queue.js +13 -6
- package/lib/module/features/queue/queue.js.map +1 -1
- package/lib/module/features/queue/repeatMode.js +1 -1
- package/lib/module/features/queue/shuffle.js +1 -1
- package/lib/module/features/remoteControls.js +13 -92
- package/lib/module/features/remoteControls.js.map +1 -1
- package/lib/module/features/sleepTimer.js +13 -1
- package/lib/module/features/sleepTimer.js.map +1 -1
- package/lib/module/test-utils/reactNativeStub.js +58 -0
- package/lib/module/test-utils/reactNativeStub.js.map +1 -0
- package/lib/module/utils/LazyNativeEmitter.js +28 -14
- package/lib/module/utils/LazyNativeEmitter.js.map +1 -1
- package/lib/module/utils/NativeUpdatedValue.js +31 -13
- package/lib/module/utils/NativeUpdatedValue.js.map +1 -1
- package/lib/module/utils/getTrackIdentity.js +20 -0
- package/lib/module/utils/getTrackIdentity.js.map +1 -0
- package/lib/module/utils/useNativeValueRefreshedBy.js +29 -0
- package/lib/module/utils/useNativeValueRefreshedBy.js.map +1 -0
- package/lib/module/web/NativeAudioBrowser.js +200 -75
- package/lib/module/web/NativeAudioBrowser.js.map +1 -1
- package/lib/module/web/TrackPlayer/LoadAttempt.js +32 -0
- package/lib/module/web/TrackPlayer/LoadAttempt.js.map +1 -0
- package/lib/module/web/TrackPlayer/PlaybackStateMachine.js +18 -2
- package/lib/module/web/TrackPlayer/PlaybackStateMachine.js.map +1 -1
- package/lib/module/web/TrackPlayer/Player.js +254 -39
- package/lib/module/web/TrackPlayer/Player.js.map +1 -1
- package/lib/module/web/TrackPlayer/QueueManager.js +14 -0
- package/lib/module/web/TrackPlayer/QueueManager.js.map +1 -1
- package/lib/module/web/TrackPlayer/QueuePlayer.js +33 -12
- package/lib/module/web/TrackPlayer/QueuePlayer.js.map +1 -1
- package/lib/module/web/browser/BrowserManager.js +175 -100
- package/lib/module/web/browser/BrowserManager.js.map +1 -1
- package/lib/module/web/browser/FavoriteManager.js +31 -21
- package/lib/module/web/browser/FavoriteManager.js.map +1 -1
- package/lib/module/web/browser/SearchManager.js +18 -23
- package/lib/module/web/browser/SearchManager.js.map +1 -1
- package/lib/module/web/browser/assertBrowsePageShape.js +2 -2
- package/lib/module/web/browser/assertBrowsePageShape.js.map +1 -1
- package/lib/module/web/browser/classifyTrackNavigation.js +9 -9
- package/lib/module/web/browser/classifyTrackNavigation.js.map +1 -1
- package/lib/module/web/browser/sections.js +83 -0
- package/lib/module/web/browser/sections.js.map +1 -0
- package/lib/module/web/http/RequestConfigBuilder.js +110 -27
- package/lib/module/web/http/RequestConfigBuilder.js.map +1 -1
- package/lib/module/web/http/followMediaRedirect.js +215 -0
- package/lib/module/web/http/followMediaRedirect.js.map +1 -0
- package/lib/module/web/player/NowPlayingManager.js +4 -3
- package/lib/module/web/player/NowPlayingManager.js.map +1 -1
- package/lib/module/web/util/BrowserPathHelper.js +56 -11
- package/lib/module/web/util/BrowserPathHelper.js.map +1 -1
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/AudioBrowser.d.ts +1 -1
- package/lib/typescript/src/AudioBrowser.d.ts.map +1 -1
- package/lib/typescript/src/features/browser-config.d.ts.map +1 -1
- package/lib/typescript/src/features/browser.d.ts +10 -2
- package/lib/typescript/src/features/browser.d.ts.map +1 -1
- package/lib/typescript/src/features/carConnection.d.ts +1 -1
- package/lib/typescript/src/features/equalizer.d.ts +1 -1
- package/lib/typescript/src/features/errors.d.ts +3 -3
- package/lib/typescript/src/features/favorites.d.ts +14 -11
- package/lib/typescript/src/features/favorites.d.ts.map +1 -1
- package/lib/typescript/src/features/gate.d.ts +18 -2
- package/lib/typescript/src/features/gate.d.ts.map +1 -1
- package/lib/typescript/src/features/metadata.d.ts +20 -3
- package/lib/typescript/src/features/metadata.d.ts.map +1 -1
- package/lib/typescript/src/features/network.d.ts +1 -1
- package/lib/typescript/src/features/nowPlaying.d.ts +1 -1
- package/lib/typescript/src/features/output.d.ts +1 -1
- package/lib/typescript/src/features/playback/controls.d.ts +4 -2
- package/lib/typescript/src/features/playback/controls.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/playWhenReady.d.ts +1 -1
- package/lib/typescript/src/features/playback/playing.d.ts +1 -1
- package/lib/typescript/src/features/playback/progress.d.ts +1 -1
- package/lib/typescript/src/features/playback/progress.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/rate.d.ts +8 -1
- package/lib/typescript/src/features/playback/rate.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/state.d.ts +3 -4
- package/lib/typescript/src/features/playback/state.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts +1 -1
- package/lib/typescript/src/features/playback/trackPlaybackTime.d.ts.map +1 -1
- package/lib/typescript/src/features/playback/volume.d.ts +1 -1
- package/lib/typescript/src/features/player/options.d.ts +108 -56
- package/lib/typescript/src/features/player/options.d.ts.map +1 -1
- package/lib/typescript/src/features/player/setup.d.ts +14 -4
- package/lib/typescript/src/features/player/setup.d.ts.map +1 -1
- package/lib/typescript/src/features/player/validateOptions.d.ts +2 -0
- package/lib/typescript/src/features/player/validateOptions.d.ts.map +1 -0
- package/lib/typescript/src/features/queue/activeTrack.d.ts +9 -2
- package/lib/typescript/src/features/queue/activeTrack.d.ts.map +1 -1
- package/lib/typescript/src/features/queue/queue.d.ts +7 -4
- package/lib/typescript/src/features/queue/queue.d.ts.map +1 -1
- package/lib/typescript/src/features/queue/repeatMode.d.ts +1 -1
- package/lib/typescript/src/features/queue/shuffle.d.ts +1 -1
- package/lib/typescript/src/features/remoteControls.d.ts +23 -22
- package/lib/typescript/src/features/remoteControls.d.ts.map +1 -1
- package/lib/typescript/src/features/sleepTimer.d.ts +1 -1
- package/lib/typescript/src/features/sleepTimer.d.ts.map +1 -1
- package/lib/typescript/src/test-utils/reactNativeStub.d.ts +36 -0
- package/lib/typescript/src/test-utils/reactNativeStub.d.ts.map +1 -0
- package/lib/typescript/src/types/browser-native.d.ts +3 -2
- package/lib/typescript/src/types/browser-native.d.ts.map +1 -1
- package/lib/typescript/src/types/browser-nodes.d.ts +380 -126
- package/lib/typescript/src/types/browser-nodes.d.ts.map +1 -1
- package/lib/typescript/src/types/browser.d.ts +82 -57
- package/lib/typescript/src/types/browser.d.ts.map +1 -1
- package/lib/typescript/src/utils/LazyNativeEmitter.d.ts +19 -16
- package/lib/typescript/src/utils/LazyNativeEmitter.d.ts.map +1 -1
- package/lib/typescript/src/utils/NativeUpdatedValue.d.ts +24 -19
- package/lib/typescript/src/utils/NativeUpdatedValue.d.ts.map +1 -1
- package/lib/typescript/src/utils/getTrackIdentity.d.ts +18 -0
- package/lib/typescript/src/utils/getTrackIdentity.d.ts.map +1 -0
- package/lib/typescript/src/utils/useNativeValueRefreshedBy.d.ts +21 -0
- package/lib/typescript/src/utils/useNativeValueRefreshedBy.d.ts.map +1 -0
- package/nitrogen/generated/android/AudioBrowser+autolinking.cmake +1 -2
- package/nitrogen/generated/android/AudioBrowserOnLoad.cpp +2 -0
- package/nitrogen/generated/android/c++/JAndroidOptions.hpp +10 -10
- package/nitrogen/generated/android/c++/{JFavoritesMatchMode.hpp → JArtworkRendering.hpp} +15 -15
- package/nitrogen/generated/android/c++/JArtworkRequestConfig.hpp +8 -3
- package/nitrogen/generated/android/c++/JBrowseResult.hpp +16 -4
- package/nitrogen/generated/android/c++/JCarPlayPlayingIndicatorLocation.hpp +58 -0
- package/nitrogen/generated/android/c++/JCardImage.hpp +58 -0
- package/nitrogen/generated/android/c++/JFavoriteChangedEvent.hpp +8 -3
- package/nitrogen/generated/android/c++/JFormatNowPlayingParams.hpp +8 -3
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___Track.hpp +8 -3
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.hpp +8 -3
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_std__string____Track.hpp +8 -3
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____Track.hpp +8 -3
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_Track______SearchParams.hpp +8 -2
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_void_____TrackLoadEvent.hpp +8 -2
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__string__.hpp +102 -0
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.hpp +16 -4
- package/nitrogen/generated/android/c++/JFunc_void_FavoriteChangedEvent.hpp +8 -3
- package/nitrogen/generated/android/c++/JFunc_void_Options.hpp +7 -10
- package/nitrogen/generated/android/c++/JFunc_void_PlaybackActiveTrackChangedEvent.hpp +8 -3
- package/nitrogen/generated/android/c++/JFunc_void_std__optional_ResolvedTrack_.hpp +15 -3
- package/nitrogen/generated/android/c++/JFunc_void_std__vector_Track_.hpp +8 -2
- package/nitrogen/generated/android/c++/JGridTile.hpp +61 -0
- package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.cpp +45 -25
- package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.hpp +1 -1
- package/nitrogen/generated/android/c++/JIOSOptions.hpp +9 -3
- package/nitrogen/generated/android/c++/JImageShape.hpp +58 -0
- package/nitrogen/generated/android/c++/JMediaRequestConfig.hpp +8 -3
- package/nitrogen/generated/android/c++/JNativeBrowserConfiguration.hpp +36 -11
- package/nitrogen/generated/android/c++/JNativeRouteEntry.hpp +14 -2
- package/nitrogen/generated/android/c++/JNativeSetupPlayerOptions.hpp +15 -12
- package/nitrogen/generated/android/c++/JNativeUpdateOptions.hpp +7 -10
- package/nitrogen/generated/android/c++/JNitroAndroidUpdateOptions.hpp +10 -10
- package/nitrogen/generated/android/c++/JNitroIOSUpdateOptions.hpp +9 -3
- package/nitrogen/generated/android/c++/JOptions.hpp +7 -10
- package/nitrogen/generated/android/c++/JPlaybackActiveTrackChangedEvent.hpp +8 -3
- package/nitrogen/generated/android/c++/JPlayerCapabilities.hpp +5 -11
- package/nitrogen/generated/android/c++/{JNotificationButton.hpp → JRemoteButton.hpp} +19 -19
- package/nitrogen/generated/android/c++/JRemoteButtonLayout.hpp +86 -0
- package/nitrogen/generated/android/c++/JResolvedTrack.hpp +57 -49
- package/nitrogen/generated/android/c++/JSection.hpp +116 -0
- package/nitrogen/generated/android/c++/JSectionStyle.hpp +96 -0
- package/nitrogen/generated/android/c++/JStyleDisplay.hpp +58 -0
- package/nitrogen/generated/android/c++/JTrack.hpp +25 -46
- package/nitrogen/generated/android/c++/JTrackLoadEvent.hpp +8 -2
- package/nitrogen/generated/android/c++/JTrackStyle.hpp +46 -18
- package/nitrogen/generated/android/c++/JVariant_NullType_RemoteButtonLayout.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_RemoteButtonLayout.hpp +75 -0
- package/nitrogen/generated/android/c++/JVariant_ResolvedTrack_BrowseError_Promise_BrowseResult_.hpp +16 -4
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/AndroidOptions.kt +3 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{FavoritesMatchMode.kt → ArtworkRendering.kt} +5 -5
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/CarPlayPlayingIndicatorLocation.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/CardImage.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Func_std__shared_ptr_Promise_std__string__.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/GridTile.kt +24 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/HybridAudioBrowserSpec.kt +1 -1
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/IOSOptions.kt +6 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageShape.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeBrowserConfiguration.kt +8 -5
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroAndroidUpdateOptions.kt +3 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NitroIOSUpdateOptions.kt +6 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/PlayerCapabilities.kt +2 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{NotificationButton.kt → RemoteButton.kt} +3 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/RemoteButtonLayout.kt +44 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ResolvedTrack.kt +12 -15
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{FavoriteConfig.kt → Section.kt} +15 -6
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/SectionStyle.kt +59 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/StyleDisplay.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Track.kt +6 -12
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackStyle.kt +35 -5
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{Variant_NullType_NotificationButtonLayout.kt → Variant_NullType_RemoteButtonLayout.kt} +9 -9
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.cpp +9 -0
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.hpp +244 -133
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Umbrella.hpp +31 -16
- package/nitrogen/generated/ios/c++/HybridAudioBrowserSpecSwift.hpp +33 -18
- package/nitrogen/generated/ios/swift/AndroidOptions.swift +12 -12
- package/nitrogen/generated/ios/swift/ArtworkRendering.swift +40 -0
- package/nitrogen/generated/ios/swift/CarPlayPlayingIndicatorLocation.swift +40 -0
- package/nitrogen/generated/ios/swift/CardImage.swift +40 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__string__.swift +54 -0
- package/nitrogen/generated/ios/swift/GridTile.swift +44 -0
- package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec.swift +1 -1
- package/nitrogen/generated/ios/swift/HybridAudioBrowserSpec_cxx.swift +2 -2
- package/nitrogen/generated/ios/swift/IOSOptions.swift +7 -2
- package/nitrogen/generated/ios/swift/ImageShape.swift +40 -0
- package/nitrogen/generated/ios/swift/NativeBrowserConfiguration.swift +52 -5
- package/nitrogen/generated/ios/swift/NitroAndroidUpdateOptions.swift +12 -12
- package/nitrogen/generated/ios/swift/NitroIOSUpdateOptions.swift +12 -1
- package/nitrogen/generated/ios/swift/PlayerCapabilities.swift +8 -27
- package/nitrogen/generated/ios/swift/{NotificationButton.swift → RemoteButton.swift} +6 -6
- package/nitrogen/generated/ios/swift/RemoteButtonLayout.swift +57 -0
- package/nitrogen/generated/ios/swift/ResolvedTrack.swift +62 -73
- package/nitrogen/generated/ios/swift/Section.swift +82 -0
- package/nitrogen/generated/ios/swift/SectionStyle.swift +133 -0
- package/nitrogen/generated/ios/swift/StyleDisplay.swift +40 -0
- package/nitrogen/generated/ios/swift/Track.swift +28 -63
- package/nitrogen/generated/ios/swift/TrackStyle.swift +86 -22
- package/nitrogen/generated/ios/swift/{Variant_NullType_NotificationButtonLayout.swift → Variant_NullType_RemoteButtonLayout.swift} +3 -3
- package/nitrogen/generated/shared/c++/AndroidOptions.hpp +8 -8
- package/nitrogen/generated/shared/c++/{FavoritesMatchMode.hpp → ArtworkRendering.hpp} +17 -17
- package/nitrogen/generated/shared/c++/CarPlayPlayingIndicatorLocation.hpp +76 -0
- package/nitrogen/generated/shared/c++/CardImage.hpp +76 -0
- package/nitrogen/generated/shared/c++/GridTile.hpp +80 -0
- package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.cpp +1 -1
- package/nitrogen/generated/shared/c++/HybridAudioBrowserSpec.hpp +1 -1
- package/nitrogen/generated/shared/c++/IOSOptions.hpp +9 -2
- package/nitrogen/generated/shared/c++/ImageShape.hpp +76 -0
- package/nitrogen/generated/shared/c++/NativeBrowserConfiguration.hpp +10 -6
- package/nitrogen/generated/shared/c++/NitroAndroidUpdateOptions.hpp +8 -8
- package/nitrogen/generated/shared/c++/NitroIOSUpdateOptions.hpp +9 -2
- package/nitrogen/generated/shared/c++/PlayerCapabilities.hpp +6 -9
- package/nitrogen/generated/shared/c++/{NotificationButton.hpp → RemoteButton.hpp} +19 -19
- package/nitrogen/generated/shared/c++/RemoteButtonLayout.hpp +94 -0
- package/nitrogen/generated/shared/c++/ResolvedTrack.hpp +33 -37
- package/nitrogen/generated/shared/c++/Section.hpp +102 -0
- package/nitrogen/generated/shared/c++/SectionStyle.hpp +126 -0
- package/nitrogen/generated/shared/c++/StyleDisplay.hpp +76 -0
- package/nitrogen/generated/shared/c++/Track.hpp +18 -30
- package/nitrogen/generated/shared/c++/TrackStyle.hpp +73 -34
- package/package.json +24 -11
- package/src/AudioBrowser.ts +2 -1
- package/src/CLAUDE.md +52 -0
- package/src/features/battery.test.ts +79 -0
- package/src/features/browser-config.test.ts +21 -6
- package/src/features/browser-config.ts +12 -8
- package/src/features/browser.test.ts +1 -1
- package/src/features/browser.ts +11 -3
- package/src/features/carConnection.ts +1 -1
- package/src/features/equalizer.ts +1 -1
- package/src/features/errors.ts +3 -3
- package/src/features/favorites.ts +14 -11
- package/src/features/gate.ts +16 -1
- package/src/features/hook-wiring.test.ts +302 -0
- package/src/features/metadata.ts +20 -3
- package/src/features/network.ts +1 -1
- package/src/features/nowPlaying.ts +1 -1
- package/src/features/output.ts +1 -1
- package/src/features/playback/controls.ts +4 -2
- package/src/features/playback/playWhenReady.ts +1 -1
- package/src/features/playback/playing.ts +1 -1
- package/src/features/playback/progress.test.ts +169 -0
- package/src/features/playback/progress.ts +3 -2
- package/src/features/playback/rate.ts +8 -1
- package/src/features/playback/state.ts +3 -4
- package/src/features/playback/trackPlaybackTime.test.ts +16 -6
- package/src/features/playback/trackPlaybackTime.ts +1 -6
- package/src/features/playback/volume.ts +1 -1
- package/src/features/player/options.ts +126 -76
- package/src/features/player/setup.test.ts +24 -7
- package/src/features/player/setup.ts +22 -10
- package/src/features/player/validateOptions.ts +21 -0
- package/src/features/queue/activeTrack.ts +15 -4
- package/src/features/queue/queue.ts +13 -6
- package/src/features/queue/repeatMode.ts +1 -1
- package/src/features/queue/shuffle.ts +1 -1
- package/src/features/remoteControls.ts +13 -92
- package/src/features/sleepTimer.test.ts +172 -0
- package/src/features/sleepTimer.ts +9 -1
- package/src/nitro-stub-drift.test.ts +277 -0
- package/src/public-surface.test.ts +147 -0
- package/src/specs/audio-browser.nitro.ts +5 -4
- package/src/style-resolution.test.ts +210 -0
- package/src/test-utils/reactNativeStub.ts +60 -0
- package/src/types/browser-native.ts +7 -3
- package/src/types/browser-nodes.ts +396 -134
- package/src/types/browser.ts +85 -59
- package/src/utils/LazyNativeEmitter.ts +28 -15
- package/src/utils/NativeUpdatedValue.ts +29 -13
- package/src/utils/getTrackIdentity.ts +20 -0
- package/src/utils/useDebug.test.ts +182 -0
- package/src/utils/useNativeUpdatedValue.test.ts +103 -0
- package/src/utils/useNativeValueRefreshedBy.ts +38 -0
- package/src/web/NativeAudioBrowser.playWhenReady.test.ts +232 -2
- package/src/web/NativeAudioBrowser.ts +239 -82
- package/src/web/TrackPlayer/LoadAttempt.ts +29 -0
- package/src/web/TrackPlayer/PlaybackStateMachine.test.ts +60 -13
- package/src/web/TrackPlayer/PlaybackStateMachine.ts +22 -6
- package/src/web/TrackPlayer/Player.dispatch.test.ts +5 -3
- package/src/web/TrackPlayer/Player.load.test.ts +137 -1
- package/src/web/TrackPlayer/Player.ts +284 -37
- package/src/web/TrackPlayer/QueueManager.test.ts +29 -0
- package/src/web/TrackPlayer/QueueManager.ts +14 -0
- package/src/web/TrackPlayer/QueuePlayer.ts +33 -14
- package/src/web/__tests__/lifecycle.test.ts +345 -0
- package/src/web/__tests__/lifecycleHarness.ts +351 -0
- package/src/web/__tests__/loadEdgeCases.test.ts +246 -0
- package/src/web/__tests__/loadSupersession.test.ts +175 -0
- package/src/web/__tests__/retry.test.ts +169 -0
- package/src/web/browser/BrowserManager.ts +209 -111
- package/src/web/browser/FavoriteManager.test.ts +84 -0
- package/src/web/browser/FavoriteManager.ts +28 -23
- package/src/web/browser/SearchManager.test.ts +75 -0
- package/src/web/browser/SearchManager.ts +25 -28
- package/src/web/browser/__tests__/artwork-resolution.test.ts +117 -0
- package/src/web/browser/__tests__/layer-resolver.test.ts +35 -0
- package/src/web/browser/__tests__/search-artwork.test.ts +46 -0
- package/src/web/browser/__tests__/search-navigation.test.ts +76 -0
- package/src/web/browser/assertBrowsePageShape.test.ts +1 -1
- package/src/web/browser/assertBrowsePageShape.ts +5 -3
- package/src/web/browser/classifyTrackNavigation.test.ts +10 -8
- package/src/web/browser/classifyTrackNavigation.ts +9 -9
- package/src/web/browser/parseSearchResponse.test.ts +8 -2
- package/src/web/browser/sections.test.ts +91 -0
- package/src/web/browser/sections.ts +72 -0
- package/src/web/http/RequestConfigBuilder.test.ts +241 -1
- package/src/web/http/RequestConfigBuilder.ts +140 -33
- package/src/web/http/followMediaRedirect.test.ts +289 -0
- package/src/web/http/followMediaRedirect.ts +253 -0
- package/src/web/player/NowPlayingManager.ts +4 -3
- package/src/web/util/BrowserPathHelper.test.ts +52 -0
- package/src/web/util/BrowserPathHelper.ts +61 -13
- package/website/guide/android-auto.md +114 -0
- package/website/guide/android-certificates.md +409 -0
- package/website/guide/artwork.md +255 -0
- package/website/guide/audio-output.md +135 -0
- package/website/guide/automotive.md +86 -0
- package/website/guide/basic-usage.md +151 -0
- package/website/guide/battery.md +115 -0
- package/website/guide/browser.md +581 -0
- package/website/guide/carplay.md +620 -0
- package/website/guide/configuration.md +173 -0
- package/website/guide/equalizer.md +231 -0
- package/website/guide/errors.md +310 -0
- package/website/guide/favorites.md +154 -0
- package/website/guide/gate.md +143 -0
- package/website/guide/getting-started.md +46 -0
- package/website/guide/hooks.md +238 -0
- package/website/guide/live-streams.md +125 -0
- package/website/guide/metadata.md +239 -0
- package/website/guide/migrating-from-track-player.md +244 -0
- package/website/guide/native-callback-fetch.md +127 -0
- package/website/guide/network.md +86 -0
- package/website/guide/now-playing.md +175 -0
- package/website/guide/playback.md +328 -0
- package/website/guide/queue.md +300 -0
- package/website/guide/remote-controls.md +256 -0
- package/website/guide/search.md +255 -0
- package/website/guide/sleep-timer.md +268 -0
- package/website/guide/track.md +247 -0
- package/ios/CarPlay/ImageRowItem+CarPlay.swift +0 -19
- package/ios/Model/MediaURL.swift +0 -67
- package/nitrogen/generated/android/c++/JFavoriteConfig.hpp +0 -58
- package/nitrogen/generated/android/c++/JImageRowItem.hpp +0 -105
- package/nitrogen/generated/android/c++/JNotificationButtonLayout.hpp +0 -94
- package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.cpp +0 -26
- package/nitrogen/generated/android/c++/JVariant_Boolean_FavoriteConfig.hpp +0 -71
- package/nitrogen/generated/android/c++/JVariant_NullType_NotificationButtonLayout.cpp +0 -26
- package/nitrogen/generated/android/c++/JVariant_NullType_NotificationButtonLayout.hpp +0 -75
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/ImageRowItem.kt +0 -68
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NotificationButtonLayout.kt +0 -50
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Variant_Boolean_FavoriteConfig.kt +0 -53
- package/nitrogen/generated/ios/swift/FavoriteConfig.swift +0 -29
- package/nitrogen/generated/ios/swift/FavoritesMatchMode.swift +0 -40
- package/nitrogen/generated/ios/swift/ImageRowItem.swift +0 -195
- package/nitrogen/generated/ios/swift/NotificationButtonLayout.swift +0 -92
- package/nitrogen/generated/ios/swift/Variant_Bool_FavoriteConfig.swift +0 -18
- package/nitrogen/generated/shared/c++/FavoriteConfig.hpp +0 -84
- package/nitrogen/generated/shared/c++/ImageRowItem.hpp +0 -129
- package/nitrogen/generated/shared/c++/NotificationButtonLayout.hpp +0 -102
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
2
|
+
import { dirname, join, relative, resolve } from 'node:path'
|
|
3
|
+
import { describe, it, expect } from 'vitest'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Guard on what `import { … } from 'react-native-audio-browser'` can reach.
|
|
7
|
+
*
|
|
8
|
+
* `@internal` hides a value from the published types but not from the bundle:
|
|
9
|
+
* Metro resolves `"react-native": "src/index"` and compiles the source, where
|
|
10
|
+
* `stripInternal` never ran. Types are exempt — they have no runtime form.
|
|
11
|
+
* `CLAUDE.md` in this directory has the full rule.
|
|
12
|
+
*/
|
|
13
|
+
const SRC = join(process.cwd(), 'src')
|
|
14
|
+
const ENTRY = join(SRC, 'index.ts')
|
|
15
|
+
|
|
16
|
+
const VALUE_KINDS = new Set([
|
|
17
|
+
'const',
|
|
18
|
+
'let',
|
|
19
|
+
'var',
|
|
20
|
+
'function',
|
|
21
|
+
'class',
|
|
22
|
+
'enum'
|
|
23
|
+
])
|
|
24
|
+
|
|
25
|
+
function resolveModule(fromFile: string, spec: string): string | undefined {
|
|
26
|
+
const base = resolve(dirname(fromFile), spec.replace(/\.tsx?$/, ''))
|
|
27
|
+
return [`${base}.ts`, `${base}.tsx`, join(base, 'index.ts')].find(existsSync)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface Export {
|
|
31
|
+
name: string
|
|
32
|
+
file: string
|
|
33
|
+
internal: boolean
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Walks the `export *` graph from `entry`, collecting every reachable value export. */
|
|
37
|
+
function collectValueExports(entry: string): Export[] {
|
|
38
|
+
const found: Export[] = []
|
|
39
|
+
const seen = new Set<string>()
|
|
40
|
+
|
|
41
|
+
const visit = (file: string) => {
|
|
42
|
+
if (seen.has(file)) return
|
|
43
|
+
seen.add(file)
|
|
44
|
+
const source = readFileSync(file, 'utf8')
|
|
45
|
+
|
|
46
|
+
for (const [, spec] of source.matchAll(/^export \* from ['"](.+?)['"]/gm)) {
|
|
47
|
+
const target = resolveModule(file, spec!)
|
|
48
|
+
if (target) visit(target)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const declaration =
|
|
52
|
+
/^export (?:declare )?(?:async )?(?:abstract )?(const|let|var|function|class|enum) (\w+)/gm
|
|
53
|
+
for (const match of source.matchAll(declaration)) {
|
|
54
|
+
if (!VALUE_KINDS.has(match[1]!)) continue
|
|
55
|
+
// The JSDoc block, if any, is whatever sits directly above the export.
|
|
56
|
+
const preceding = source.slice(0, match.index)
|
|
57
|
+
const doc = /\/\*\*(?:(?!\*\/)[\s\S])*\*\/\s*$/.exec(preceding)?.[0] ?? ''
|
|
58
|
+
found.push({
|
|
59
|
+
name: match[2]!,
|
|
60
|
+
file: relative(SRC, file),
|
|
61
|
+
internal: /@internal\b/.test(doc)
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
visit(entry)
|
|
67
|
+
return found
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
describe('public surface', () => {
|
|
71
|
+
const exports = collectValueExports(ENTRY)
|
|
72
|
+
|
|
73
|
+
it('reaches the feature modules at all (the walker still works)', () => {
|
|
74
|
+
// Cheap canary: if the barrel structure changes shape and the walker stops
|
|
75
|
+
// resolving, every other assertion here would pass vacuously.
|
|
76
|
+
expect(exports.map((e) => e.name)).toContain('trackPlaybackTime')
|
|
77
|
+
expect(exports.length).toBeGreaterThan(100)
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
it('exposes no value marked @internal', () => {
|
|
81
|
+
const leaked = exports
|
|
82
|
+
.filter((e) => e.internal)
|
|
83
|
+
.map((e) => `${e.name} (${e.file})`)
|
|
84
|
+
expect(
|
|
85
|
+
leaked,
|
|
86
|
+
'Reachable from the package root at runtime despite @internal. Move each ' +
|
|
87
|
+
'to a module the barrels skip, and import it directly:\n' +
|
|
88
|
+
leaked.join('\n')
|
|
89
|
+
).toEqual([])
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
it('exposes no __-prefixed test hook', () => {
|
|
93
|
+
const hooks = exports
|
|
94
|
+
.filter((e) => e.name.startsWith('__'))
|
|
95
|
+
.map((e) => `${e.name} (${e.file})`)
|
|
96
|
+
expect(
|
|
97
|
+
hooks,
|
|
98
|
+
'Test-only exports ship to consumers. Drive the unit through a seam it ' +
|
|
99
|
+
'already has — a mocked native slot, say:\n' +
|
|
100
|
+
hooks.join('\n')
|
|
101
|
+
).toEqual([])
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
it('does not re-export the raw Nitro object', () => {
|
|
105
|
+
expect(exports.map((e) => e.name)).not.toContain('nativeBrowser')
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
it('every public module is covered by the typedoc entry points', () => {
|
|
109
|
+
// The API reference documents entryPoints, not the export graph — a public
|
|
110
|
+
// module missing from website/typedoc.json ships undocumented.
|
|
111
|
+
const config = JSON.parse(
|
|
112
|
+
readFileSync(join(process.cwd(), 'website', 'typedoc.json'), 'utf8')
|
|
113
|
+
) as { entryPoints: string[] }
|
|
114
|
+
const entries = config.entryPoints.map(
|
|
115
|
+
(glob) =>
|
|
116
|
+
new RegExp(
|
|
117
|
+
'^' +
|
|
118
|
+
glob
|
|
119
|
+
.replace(/^\.\.\/src\//, '')
|
|
120
|
+
.replace(/[.]/g, '\\.')
|
|
121
|
+
.replace(/\*/g, '[^/]+') +
|
|
122
|
+
'$'
|
|
123
|
+
)
|
|
124
|
+
)
|
|
125
|
+
const covered = (file: string): boolean => {
|
|
126
|
+
if (entries.some((e) => e.test(file))) return true
|
|
127
|
+
// A directory barrel entry (…/index.ts) documents what it re-exports.
|
|
128
|
+
const dir = file.split('/').slice(0, -1)
|
|
129
|
+
while (dir.length > 0) {
|
|
130
|
+
if (entries.some((e) => e.test([...dir, 'index.ts'].join('/'))))
|
|
131
|
+
return true
|
|
132
|
+
dir.pop()
|
|
133
|
+
}
|
|
134
|
+
return false
|
|
135
|
+
}
|
|
136
|
+
const uncovered = [...new Set(exports.map((e) => e.file))].filter(
|
|
137
|
+
(file) => !covered(file)
|
|
138
|
+
)
|
|
139
|
+
expect(
|
|
140
|
+
uncovered,
|
|
141
|
+
'Exported to consumers but absent from the API reference. Add each ' +
|
|
142
|
+
'module (or its directory barrel) to website/typedoc.json ' +
|
|
143
|
+
'entryPoints:\n' +
|
|
144
|
+
uncovered.join('\n')
|
|
145
|
+
).toEqual([])
|
|
146
|
+
})
|
|
147
|
+
})
|
|
@@ -115,7 +115,7 @@ export interface AudioBrowser extends HybridObject<{
|
|
|
115
115
|
tabs: Track[] | undefined
|
|
116
116
|
navigatePath(path: string): void
|
|
117
117
|
navigateTrack(track: Track): void
|
|
118
|
-
|
|
118
|
+
search(query: string): Promise<Track[]>
|
|
119
119
|
getContent(): ResolvedTrack | undefined
|
|
120
120
|
onPathChanged: (path: string) => void
|
|
121
121
|
onContentChanged: (content: ResolvedTrack | undefined) => void
|
|
@@ -229,9 +229,10 @@ export interface AudioBrowser extends HybridObject<{
|
|
|
229
229
|
seekTo(position: number): void
|
|
230
230
|
seekBy(offset: number): void
|
|
231
231
|
/**
|
|
232
|
-
* Jump to the live edge of the current track
|
|
233
|
-
*
|
|
234
|
-
* window
|
|
232
|
+
* Jump to the live edge of the current track; no-op unless the track
|
|
233
|
+
* declares `live: true`. A stream with a seekable live window (HLS) seeks
|
|
234
|
+
* to the window's edge; a non-seekable stream (e.g. ICY radio) reconnects
|
|
235
|
+
* to rejoin live — an expired URL re-resolves through `media.resolve`.
|
|
235
236
|
*/
|
|
236
237
|
seekToLiveEdge(): void
|
|
237
238
|
setVolume(level: number): void
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
import { describe, expect, it } from 'vitest'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Completeness guards for the style declaration block (ADR 0011) — the checks
|
|
7
|
+
* Nitro's `extends`-flattening took out of the type system, in two parts:
|
|
8
|
+
* every key must be *resolved* by each platform's `StyleResolver`, and every
|
|
9
|
+
* key must be *accounted for* by each platform's `InertStyleDiagnostic`.
|
|
10
|
+
*
|
|
11
|
+
* Part one — inheritance completeness.
|
|
12
|
+
*
|
|
13
|
+
* `SectionStyle extends TrackStyle` in the spec, but Nitro flattens `extends`
|
|
14
|
+
* into independent structs on every platform — so nothing in any type system
|
|
15
|
+
* forces a platform's `StyleResolver` to read a newly added style key. A key
|
|
16
|
+
* the resolver forgets is silently dead: declared by consumers, decoded on the
|
|
17
|
+
* wire, never rendered. This test is the compile-time check the flattening
|
|
18
|
+
* took away:
|
|
19
|
+
*
|
|
20
|
+
* - every `SectionStyle` key must appear in each platform's
|
|
21
|
+
* `sectionStyle(section, page)` merge;
|
|
22
|
+
* - every inherited `TrackStyle` key must appear in each platform's
|
|
23
|
+
* `trackStyle(track, section)` merge;
|
|
24
|
+
* - `display` is positional (the deny-list): the track merge must resolve it
|
|
25
|
+
* to nil/null and must not read it from any level.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
const ROOT = process.cwd()
|
|
29
|
+
|
|
30
|
+
const RESOLVERS = [
|
|
31
|
+
{
|
|
32
|
+
file: 'ios/Browser/StyleResolver.swift',
|
|
33
|
+
sectionMarker: 'static func sectionStyle',
|
|
34
|
+
trackMarker: 'static func trackStyle',
|
|
35
|
+
positionalNil: 'display: nil'
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
file: 'android/src/main/java/com/audiobrowser/browser/StyleResolver.kt',
|
|
39
|
+
sectionMarker: 'fun sectionStyle',
|
|
40
|
+
trackMarker: 'fun trackStyle',
|
|
41
|
+
positionalNil: 'display = null'
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
/** Keys the spec deliberately excludes from item inheritance. */
|
|
46
|
+
const POSITIONAL = ['display']
|
|
47
|
+
|
|
48
|
+
function interfaceKeys(source: string, name: string): string[] {
|
|
49
|
+
const start = source.indexOf(`export interface ${name} `)
|
|
50
|
+
expect(
|
|
51
|
+
start,
|
|
52
|
+
`interface ${name} not found in browser-nodes.ts`
|
|
53
|
+
).toBeGreaterThan(-1)
|
|
54
|
+
const end = source.indexOf('\n}', start)
|
|
55
|
+
const body = source.slice(start, end)
|
|
56
|
+
return [...body.matchAll(/^ {2}(\w+)\??:/gm)].flatMap((match) =>
|
|
57
|
+
match[1] === undefined ? [] : [match[1]]
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* The function's text from `marker` to the next function declaration (or end
|
|
63
|
+
* of file) — brace-agnostic, since Kotlin expression bodies have no braces.
|
|
64
|
+
*/
|
|
65
|
+
function functionBody(source: string, marker: string, file: string): string {
|
|
66
|
+
const start = source.indexOf(marker)
|
|
67
|
+
expect(start, `${marker} not found in ${file}`).toBeGreaterThan(-1)
|
|
68
|
+
const rest = source.slice(start + marker.length)
|
|
69
|
+
const next = rest.search(/\n\s*(?:static func|func|fun)\s/)
|
|
70
|
+
return marker + (next === -1 ? rest : rest.slice(0, next))
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Comment-free view, so prose about a key doesn't count as reading it. */
|
|
74
|
+
function stripComments(code: string): string {
|
|
75
|
+
return code
|
|
76
|
+
.replace(/\/\*[\s\S]*?\*\//g, '')
|
|
77
|
+
.split('\n')
|
|
78
|
+
.map((line) => line.replace(/\/\/.*$/, ''))
|
|
79
|
+
.join('\n')
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const nodes = readFileSync(
|
|
83
|
+
join(ROOT, 'src', 'types', 'browser-nodes.ts'),
|
|
84
|
+
'utf8'
|
|
85
|
+
)
|
|
86
|
+
const trackKeys = interfaceKeys(nodes, 'TrackStyle')
|
|
87
|
+
const sectionKeys = [...trackKeys, ...interfaceKeys(nodes, 'SectionStyle')]
|
|
88
|
+
const inheritedKeys = trackKeys.filter((key) => !POSITIONAL.includes(key))
|
|
89
|
+
|
|
90
|
+
describe('style block shape', () => {
|
|
91
|
+
it('has the positional key and at least one inherited key', () => {
|
|
92
|
+
expect(trackKeys).toContain('display')
|
|
93
|
+
expect(inheritedKeys.length).toBeGreaterThan(0)
|
|
94
|
+
})
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
for (const resolver of RESOLVERS) {
|
|
98
|
+
describe(resolver.file, () => {
|
|
99
|
+
const source = readFileSync(join(ROOT, resolver.file), 'utf8')
|
|
100
|
+
const sectionBody = stripComments(
|
|
101
|
+
functionBody(source, resolver.sectionMarker, resolver.file)
|
|
102
|
+
)
|
|
103
|
+
const trackBody = stripComments(
|
|
104
|
+
functionBody(source, resolver.trackMarker, resolver.file)
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
// Containment of `holder?.key` for BOTH holders — `display =
|
|
108
|
+
// section?.display` with the page half dropped must fail — AND in
|
|
109
|
+
// precedence order: the narrower holder must be read first, or the
|
|
110
|
+
// scope-override/inheritance direction is inverted (`page ?? section`
|
|
111
|
+
// would pass a bare containment check).
|
|
112
|
+
it.each(sectionKeys)('sectionStyle merges %s (section ?? page)', (key) => {
|
|
113
|
+
const section = sectionBody.indexOf(`section?.${key}`)
|
|
114
|
+
const page = sectionBody.indexOf(`page?.${key}`)
|
|
115
|
+
expect(section, `section?.${key} not read`).toBeGreaterThan(-1)
|
|
116
|
+
expect(page, `page?.${key} not read`).toBeGreaterThan(-1)
|
|
117
|
+
expect(section, `section?.${key} must precede page?.${key}`).toBeLessThan(
|
|
118
|
+
page
|
|
119
|
+
)
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
it.each(inheritedKeys)(
|
|
123
|
+
'trackStyle inherits %s (track ?? section)',
|
|
124
|
+
(key) => {
|
|
125
|
+
const track = trackBody.indexOf(`track?.${key}`)
|
|
126
|
+
const section = trackBody.indexOf(`section?.${key}`)
|
|
127
|
+
expect(track, `track?.${key} not read`).toBeGreaterThan(-1)
|
|
128
|
+
expect(section, `section?.${key} not read`).toBeGreaterThan(-1)
|
|
129
|
+
expect(
|
|
130
|
+
track,
|
|
131
|
+
`track?.${key} must precede section?.${key}`
|
|
132
|
+
).toBeLessThan(section)
|
|
133
|
+
}
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
it('trackStyle excludes the positional display (deny-list)', () => {
|
|
137
|
+
expect(trackBody).toContain(resolver.positionalNil)
|
|
138
|
+
// The nil assignment must be the ONLY mention: reading display from any
|
|
139
|
+
// level here would item-inherit a positional key.
|
|
140
|
+
const mentions = trackBody.match(/display/g) ?? []
|
|
141
|
+
expect(mentions).toHaveLength(1)
|
|
142
|
+
})
|
|
143
|
+
})
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Part two — diagnostic completeness.
|
|
148
|
+
*
|
|
149
|
+
* The block model traded compile-time invalid-combination errors for
|
|
150
|
+
* inertness, and the dev-mode `InertStyleDiagnostic` is the recovery. It is
|
|
151
|
+
* exposed to the same flattening problem as the resolvers, one level up: a
|
|
152
|
+
* key added to the spec has no type-system tie to the diagnostic's rule set,
|
|
153
|
+
* so a property could ship whose inert combinations nobody is warned about.
|
|
154
|
+
*
|
|
155
|
+
* Each platform therefore dispositions the whole vocabulary — every key is a
|
|
156
|
+
* `Property` with an inertness rule, `alwaysRenderable`, or `positional` —
|
|
157
|
+
* and this test reads those three declarations and asserts set equality with
|
|
158
|
+
* the spec, both directions: a new key must be dispositioned, and a key
|
|
159
|
+
* deleted from the spec must not linger in the rule set.
|
|
160
|
+
*/
|
|
161
|
+
const DIAGNOSTICS = [
|
|
162
|
+
{
|
|
163
|
+
file: 'ios/Browser/InertStyleDiagnostic.swift',
|
|
164
|
+
// `case gridWrap`, up to the first member after the case list.
|
|
165
|
+
ruled: (source: string) =>
|
|
166
|
+
keysIn(
|
|
167
|
+
source,
|
|
168
|
+
/enum Property[\s\S]*?var isItemProperty/,
|
|
169
|
+
/^\s*case (\w+)$/gm
|
|
170
|
+
)
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
file: 'android/src/main/java/com/audiobrowser/browser/InertStyleDiagnostic.kt',
|
|
174
|
+
// `GRID_WRAP("gridWrap", …)`, up to the `;` that ends the entry list.
|
|
175
|
+
ruled: (source: string) =>
|
|
176
|
+
keysIn(source, /enum class Property[\s\S]*?;/, /\w+\("(\w+)"/g)
|
|
177
|
+
}
|
|
178
|
+
]
|
|
179
|
+
|
|
180
|
+
/** The capture group of every `pattern` match within the first `region`. */
|
|
181
|
+
function keysIn(source: string, region: RegExp, pattern: RegExp): string[] {
|
|
182
|
+
const found = region.exec(source)
|
|
183
|
+
expect(found, `region ${region} not found`).not.toBeNull()
|
|
184
|
+
return [...found![0].matchAll(pattern)].flatMap((match) =>
|
|
185
|
+
match[1] === undefined ? [] : [match[1]]
|
|
186
|
+
)
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
for (const diagnostic of DIAGNOSTICS) {
|
|
190
|
+
describe(diagnostic.file, () => {
|
|
191
|
+
// Comment-free, so prose naming a key doesn't pass for dispositioning it.
|
|
192
|
+
const source = stripComments(
|
|
193
|
+
readFileSync(join(ROOT, diagnostic.file), 'utf8')
|
|
194
|
+
)
|
|
195
|
+
// The two lists are spelled `alwaysRenderable`/`positional` in Swift and
|
|
196
|
+
// SCREAMING_CASE in Kotlin; both hold bare string literals.
|
|
197
|
+
const listed = [
|
|
198
|
+
...source.matchAll(
|
|
199
|
+
/(?:alwaysRenderable|ALWAYS_RENDERABLE|positional|POSITIONAL)\s*=[^\n]*/gi
|
|
200
|
+
)
|
|
201
|
+
].flatMap((match) =>
|
|
202
|
+
[...match[0].matchAll(/"(\w+)"/g)].map((key) => key[1])
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
it('dispositions every key of the block, and only those', () => {
|
|
206
|
+
const dispositioned = [...diagnostic.ruled(source), ...listed]
|
|
207
|
+
expect(new Set(dispositioned)).toEqual(new Set(sectionKeys))
|
|
208
|
+
})
|
|
209
|
+
})
|
|
210
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stands in for `react-native` under vitest, via the alias in `vitest.config.ts`.
|
|
3
|
+
*
|
|
4
|
+
* Not a convenience: `react-native/index.js` is Flow-typed (`import typeof ...`)
|
|
5
|
+
* and Rollup cannot parse it, so any test that reaches a module importing from
|
|
6
|
+
* `'react-native'` fails to load at all. Jest consumers get this from
|
|
7
|
+
* `@react-native/jest-preset`; vitest has no equivalent.
|
|
8
|
+
*
|
|
9
|
+
* Keep it to the surface the library actually touches. Two symbols so far —
|
|
10
|
+
* `AppState` (usePolledProgress) and `Image.resolveAssetSource`. Anything a test
|
|
11
|
+
* needs to drive should get an explicit control here rather than a cast at the
|
|
12
|
+
* call site.
|
|
13
|
+
*
|
|
14
|
+
* @internal — never imported by production code, only aliased in by the runner.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
export type AppStateStatus = 'active' | 'background' | 'inactive'
|
|
18
|
+
|
|
19
|
+
type ChangeListener = (status: AppStateStatus) => void
|
|
20
|
+
|
|
21
|
+
const changeListeners = new Set<ChangeListener>()
|
|
22
|
+
|
|
23
|
+
export const AppState = {
|
|
24
|
+
currentState: 'active' as AppStateStatus,
|
|
25
|
+
|
|
26
|
+
// `type` is widened to string so the guard stays live: real AppState also
|
|
27
|
+
// emits 'memoryWarning' and 'focus', and silently treating one of those as a
|
|
28
|
+
// 'change' subscription would be a confusing way to find out this stub is thin.
|
|
29
|
+
addEventListener(type: string, listener: ChangeListener) {
|
|
30
|
+
if (type !== 'change') throw new Error(`AppState stub: unhandled "${type}"`)
|
|
31
|
+
changeListeners.add(listener)
|
|
32
|
+
return { remove: () => changeListeners.delete(listener) }
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Move the app to the foreground or background and notify subscribers. */
|
|
37
|
+
export function setAppState(status: AppStateStatus): void {
|
|
38
|
+
AppState.currentState = status
|
|
39
|
+
// Deleting from a Set mid-iteration is safe, so a listener that removes itself
|
|
40
|
+
// during the callback needs no defensive copy.
|
|
41
|
+
for (const listener of changeListeners) listener(status)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Drop every subscription and return to the foreground. Call between tests —
|
|
46
|
+
* the stub is a module singleton, so state outlives an individual test.
|
|
47
|
+
*/
|
|
48
|
+
export function resetAppState(): void {
|
|
49
|
+
changeListeners.clear()
|
|
50
|
+
AppState.currentState = 'active'
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Number of live `change` subscriptions, for asserting cleanup. */
|
|
54
|
+
export function appStateListenerCount(): number {
|
|
55
|
+
return changeListeners.size
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export const Image = {
|
|
59
|
+
resolveAssetSource: (source: unknown) => source
|
|
60
|
+
}
|
|
@@ -9,12 +9,13 @@
|
|
|
9
9
|
import type {
|
|
10
10
|
ArtworkRequestConfig,
|
|
11
11
|
BrowserSourceCallback,
|
|
12
|
-
|
|
12
|
+
ResolveAlbumPathCallback,
|
|
13
13
|
FormatNavigationErrorCallback,
|
|
14
14
|
HandleTrackLoadCallback,
|
|
15
15
|
MediaRequestConfig,
|
|
16
16
|
SearchSourceCallback,
|
|
17
|
-
TransformableRequestConfig
|
|
17
|
+
TransformableRequestConfig,
|
|
18
|
+
ViewMoreTitleCallback
|
|
18
19
|
} from './browser'
|
|
19
20
|
import type { ResolvedTrack } from './browser-nodes'
|
|
20
21
|
|
|
@@ -73,9 +74,12 @@ export interface NativeBrowserConfiguration {
|
|
|
73
74
|
singleTrack?: boolean
|
|
74
75
|
handleTrackLoad?: HandleTrackLoadCallback
|
|
75
76
|
androidControllerOfflineError?: boolean
|
|
77
|
+
// Title of the "view more" row appended to a pathed section where the header
|
|
78
|
+
// can't be tapped (Android Auto). Absent = native's "View more" default.
|
|
79
|
+
viewMoreTitle?: ViewMoreTitleCallback
|
|
76
80
|
|
|
77
81
|
// CarPlay options
|
|
78
82
|
carPlayLoadingTitle?: string
|
|
79
|
-
|
|
83
|
+
resolveAlbumPath?: ResolveAlbumPathCallback
|
|
80
84
|
formatNavigationError?: FormatNavigationErrorCallback
|
|
81
85
|
}
|