react-native-audio-browser 0.2.0-next.10 → 0.2.0-next.12
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 +4 -4
- package/android/build.gradle +6 -5
- package/android/gradle.properties +1 -1
- package/android/src/main/java/com/audiobrowser/AudioBrowser.kt +110 -25
- package/android/src/main/java/com/audiobrowser/browser/BrowserManager.kt +254 -188
- package/android/src/main/java/com/audiobrowser/browser/BrowserUrlResolution.kt +23 -3
- package/android/src/main/java/com/audiobrowser/browser/JsonModels.kt +77 -58
- package/android/src/main/java/com/audiobrowser/browser/SectionScope.kt +68 -26
- package/android/src/main/java/com/audiobrowser/browser/StyleResolver.kt +49 -0
- package/android/src/main/java/com/audiobrowser/extension/ResolvedTrackExt.kt +9 -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/player/MediaSessionCallback.kt +120 -67
- package/android/src/main/java/com/audiobrowser/player/NowPlayingUpdater.kt +21 -24
- package/android/src/main/java/com/audiobrowser/player/PlaybackStateStore.kt +93 -73
- package/android/src/main/java/com/audiobrowser/player/Player.kt +48 -30
- package/android/src/main/java/com/audiobrowser/player/PlayerCapabilitiesExt.kt +2 -15
- package/android/src/main/java/com/audiobrowser/tls/AiaCertChaser.kt +46 -5
- package/android/src/main/java/com/audiobrowser/tls/AiaChasingExtendedTrustManager.kt +86 -27
- package/android/src/main/java/com/audiobrowser/tls/AiaChasingTrustManager.kt +58 -14
- package/android/src/main/java/com/audiobrowser/tls/AiaTls.kt +20 -6
- package/android/src/main/java/com/audiobrowser/tls/CachingCertificateFetcher.kt +249 -86
- package/android/src/main/java/com/audiobrowser/util/BrowserPathHelper.kt +44 -40
- package/android/src/main/java/com/audiobrowser/util/MediaExtrasBuilder.kt +28 -23
- package/android/src/main/java/com/audiobrowser/util/StyleWire.kt +35 -0
- package/android/src/main/java/com/audiobrowser/util/TrackFactory.kt +45 -53
- package/android/src/test/java/com/audiobrowser/TestFixtures.kt +69 -30
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerFavoritesTest.kt +153 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerLayerResolutionTest.kt +6 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerTest.kt +345 -8
- package/android/src/test/java/com/audiobrowser/browser/BrowserUrlResolutionTest.kt +38 -0
- package/android/src/test/java/com/audiobrowser/browser/JsonArtworkTest.kt +1 -1
- package/android/src/test/java/com/audiobrowser/browser/JsonStyleTest.kt +91 -0
- package/android/src/test/java/com/audiobrowser/browser/SectionScopeTest.kt +128 -53
- package/android/src/test/java/com/audiobrowser/browser/StyleResolverTest.kt +87 -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/player/CapabilityControlsTest.kt +1 -2
- package/android/src/test/java/com/audiobrowser/player/NowPlayingUpdaterTest.kt +42 -2
- package/android/src/test/java/com/audiobrowser/player/PlaybackStateStoreTrackJsonTest.kt +55 -0
- package/android/src/test/java/com/audiobrowser/tls/AiaCertChaserTest.kt +152 -8
- package/android/src/test/java/com/audiobrowser/tls/AiaChasingTrustManagerTest.kt +218 -10
- package/android/src/test/java/com/audiobrowser/tls/CachingCertificateFetcherCallSiteTest.kt +322 -0
- package/android/src/test/java/com/audiobrowser/util/BrowserPathHelperTest.kt +41 -16
- package/android/src/test/java/com/audiobrowser/util/MediaExtrasBuilderTest.kt +161 -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 +131 -143
- package/ios/Browser/BrowserPathHelper.swift +44 -44
- package/ios/Browser/JsonModels.swift +187 -106
- package/ios/Browser/SearchDrillIn.swift +6 -6
- package/ios/Browser/SectionPresentation.swift +34 -0
- package/ios/Browser/SectionScope.swift +58 -24
- package/ios/Browser/StyleResolver.swift +47 -0
- package/ios/Browser/TabBarEntries.swift +2 -2
- package/ios/Browser/TrackIdTemplate.swift +37 -0
- package/ios/CarPlay/CarPlayArtworkResolver.swift +8 -7
- package/ios/CarPlay/CarPlayController.swift +105 -67
- package/ios/CarPlay/CarPlayImageLoader.swift +38 -18
- package/ios/CarPlay/CarPlayListItemFactory.swift +217 -84
- package/ios/CarPlay/CarPlayNowPlayingManager.swift +15 -12
- package/ios/Extension/Capability+RemoteCommand.swift +1 -1
- package/ios/Extension/PlayerCapabilities+Favorite.swift +1 -15
- package/ios/Extension/ResolvedTrack+Copying.swift +11 -15
- package/ios/Extension/Section+Copying.swift +31 -0
- package/ios/Extension/Track+Copying.swift +6 -12
- package/ios/Extension/Track+Identity.swift +18 -0
- package/ios/HybridAudioBrowser.swift +113 -35
- package/ios/Model/NitroTypeStubs.swift +64 -23
- package/ios/Model/PlayerUpdateOptions.swift +7 -0
- package/ios/Player/NowPlayingUpdater.swift +1 -1
- package/ios/Player/PlaybackCoordinator.swift +2 -2
- package/ios/Player/RetryManager.swift +4 -3
- package/ios/Tests/BrowserPathHelperTests.swift +50 -20
- package/ios/Tests/CarPlayArtworkResolverTests.swift +24 -41
- package/ios/Tests/JsonModelsTests.swift +75 -1
- package/ios/Tests/PlaybackStateStoreTests.swift +4 -3
- package/ios/Tests/QueueManagerTests.swift +4 -4
- package/ios/Tests/ResolvedTrackCopyingTests.swift +37 -35
- package/ios/Tests/SearchDrillInTests.swift +16 -16
- package/ios/Tests/SectionPresentationTests.swift +61 -0
- package/ios/Tests/SectionScopeTests.swift +87 -55
- package/ios/Tests/StyleResolverTests.swift +67 -0
- package/ios/Tests/TabBarEntriesTests.swift +18 -18
- package/ios/Tests/TrackIdTemplateTests.swift +67 -0
- package/ios/Tests/TrackIdentityTests.swift +20 -0
- package/ios/Tests/TrackSelectorTests.swift +168 -33
- package/ios/TrackSelector.swift +45 -30
- package/ios/Util/ArtworkImageFetcher.swift +16 -1
- package/lib/commonjs/AudioBrowser.js +11 -0
- package/lib/commonjs/AudioBrowser.js.map +1 -1
- package/lib/commonjs/features/browser-config.js +11 -8
- package/lib/commonjs/features/browser-config.js.map +1 -1
- package/lib/commonjs/features/browser.js +2 -2
- package/lib/commonjs/features/favorites.js +13 -10
- package/lib/commonjs/features/favorites.js.map +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/state.js +2 -3
- package/lib/commonjs/features/playback/state.js.map +1 -1
- package/lib/commonjs/features/player/options.js.map +1 -1
- package/lib/commonjs/features/player/setup.js +3 -1
- package/lib/commonjs/features/player/setup.js.map +1 -1
- package/lib/commonjs/features/player/validateOptions.js +2 -0
- package/lib/commonjs/features/player/validateOptions.js.map +1 -1
- package/lib/commonjs/features/queue/activeTrack.js +14 -3
- package/lib/commonjs/features/queue/activeTrack.js.map +1 -1
- package/lib/commonjs/features/queue/queue.js +11 -4
- package/lib/commonjs/features/queue/queue.js.map +1 -1
- package/lib/commonjs/utils/LazyNativeEmitter.js +21 -10
- 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 +32 -24
- package/lib/commonjs/web/NativeAudioBrowser.js.map +1 -1
- package/lib/commonjs/web/browser/BrowserManager.js +144 -87
- 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/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/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 +1 -0
- package/lib/module/AudioBrowser.js.map +1 -1
- package/lib/module/features/browser-config.js +11 -8
- package/lib/module/features/browser-config.js.map +1 -1
- package/lib/module/features/browser.js +2 -2
- package/lib/module/features/favorites.js +13 -10
- package/lib/module/features/favorites.js.map +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/state.js +2 -3
- package/lib/module/features/playback/state.js.map +1 -1
- package/lib/module/features/player/options.js.map +1 -1
- package/lib/module/features/player/setup.js +3 -1
- package/lib/module/features/player/setup.js.map +1 -1
- package/lib/module/features/player/validateOptions.js +2 -0
- package/lib/module/features/player/validateOptions.js.map +1 -1
- package/lib/module/features/queue/activeTrack.js +14 -3
- package/lib/module/features/queue/activeTrack.js.map +1 -1
- package/lib/module/features/queue/queue.js +11 -4
- package/lib/module/features/queue/queue.js.map +1 -1
- package/lib/module/utils/LazyNativeEmitter.js +21 -10
- 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 +32 -24
- package/lib/module/web/NativeAudioBrowser.js.map +1 -1
- package/lib/module/web/browser/BrowserManager.js +144 -87
- 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/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/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/src/AudioBrowser.d.ts +1 -0
- 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 +2 -2
- package/lib/typescript/src/features/favorites.d.ts +13 -10
- package/lib/typescript/src/features/favorites.d.ts.map +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/state.d.ts +2 -3
- 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/player/options.d.ts +21 -19
- package/lib/typescript/src/features/player/options.d.ts.map +1 -1
- package/lib/typescript/src/features/player/setup.d.ts.map +1 -1
- package/lib/typescript/src/features/player/validateOptions.d.ts +1 -8
- package/lib/typescript/src/features/player/validateOptions.d.ts.map +1 -1
- package/lib/typescript/src/features/queue/activeTrack.d.ts +8 -1
- package/lib/typescript/src/features/queue/activeTrack.d.ts.map +1 -1
- package/lib/typescript/src/features/queue/queue.d.ts +5 -2
- package/lib/typescript/src/features/queue/queue.d.ts.map +1 -1
- package/lib/typescript/src/types/browser-native.d.ts +2 -2
- package/lib/typescript/src/types/browser-native.d.ts.map +1 -1
- package/lib/typescript/src/types/browser-nodes.d.ts +260 -127
- package/lib/typescript/src/types/browser-nodes.d.ts.map +1 -1
- package/lib/typescript/src/types/browser.d.ts +33 -53
- package/lib/typescript/src/types/browser.d.ts.map +1 -1
- package/lib/typescript/src/utils/LazyNativeEmitter.d.ts +16 -17
- 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 +0 -1
- package/nitrogen/generated/android/c++/{JFavoritesMatchMode.hpp → JArtworkRendering.hpp} +15 -15
- package/nitrogen/generated/android/c++/JArtworkRequestConfig.hpp +4 -3
- package/nitrogen/generated/android/c++/JBrowseResult.hpp +10 -4
- package/nitrogen/generated/android/c++/JCarPlayPlayingIndicatorLocation.hpp +58 -0
- package/nitrogen/generated/android/c++/JFavoriteChangedEvent.hpp +4 -3
- package/nitrogen/generated/android/c++/JFormatNowPlayingParams.hpp +4 -3
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_RequestConfig___Track.hpp +4 -3
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_NowPlayingUpdate____FormatNowPlayingParams.hpp +4 -3
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__optional_std__string____Track.hpp +4 -3
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_RequestConfig_____Track.hpp +4 -3
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_std__vector_Track______SearchParams.hpp +4 -2
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_void_____TrackLoadEvent.hpp +4 -2
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError__std__shared_ptr_Promise_std__variant_ResolvedTrack__BrowseError_______BrowserSourceCallbackParam.hpp +10 -4
- package/nitrogen/generated/android/c++/JFunc_void_FavoriteChangedEvent.hpp +4 -3
- package/nitrogen/generated/android/c++/JFunc_void_Options.hpp +2 -5
- package/nitrogen/generated/android/c++/JFunc_void_PlaybackActiveTrackChangedEvent.hpp +4 -3
- package/nitrogen/generated/android/c++/JFunc_void_std__optional_ResolvedTrack_.hpp +9 -3
- package/nitrogen/generated/android/c++/JFunc_void_std__vector_Track_.hpp +4 -2
- package/nitrogen/generated/android/c++/JHybridAudioBrowserSpec.cpp +21 -14
- package/nitrogen/generated/android/c++/JIOSOptions.hpp +9 -3
- package/nitrogen/generated/android/c++/JMediaRequestConfig.hpp +4 -3
- package/nitrogen/generated/android/c++/JNativeBrowserConfiguration.hpp +16 -10
- package/nitrogen/generated/android/c++/JNativeRouteEntry.hpp +8 -2
- package/nitrogen/generated/android/c++/JNativeSetupPlayerOptions.hpp +6 -7
- package/nitrogen/generated/android/c++/JNativeUpdateOptions.hpp +2 -5
- package/nitrogen/generated/android/c++/JNitroIOSUpdateOptions.hpp +9 -3
- package/nitrogen/generated/android/c++/JOptions.hpp +2 -5
- package/nitrogen/generated/android/c++/JPlaybackActiveTrackChangedEvent.hpp +4 -3
- package/nitrogen/generated/android/c++/JPlayerCapabilities.hpp +5 -11
- package/nitrogen/generated/android/c++/JResolvedTrack.hpp +49 -51
- package/nitrogen/generated/android/c++/JSection.hpp +114 -0
- package/nitrogen/generated/android/c++/JSectionStyle.hpp +69 -0
- package/nitrogen/generated/android/c++/JStyleDisplay.hpp +58 -0
- package/nitrogen/generated/android/c++/JTrack.hpp +19 -48
- package/nitrogen/generated/android/c++/JTrackLoadEvent.hpp +4 -2
- package/nitrogen/generated/android/c++/JTrackStyle.hpp +25 -18
- package/nitrogen/generated/android/c++/JVariant_ResolvedTrack_BrowseError_Promise_BrowseResult_.hpp +10 -4
- 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/IOSOptions.kt +6 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/NativeBrowserConfiguration.kt +5 -5
- 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/ResolvedTrack.kt +12 -18
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/Section.kt +50 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/{FavoriteConfig.kt → SectionStyle.kt} +12 -6
- 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 -15
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackStyle.kt +23 -5
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.hpp +104 -82
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Umbrella.hpp +16 -10
- package/nitrogen/generated/ios/c++/HybridAudioBrowserSpecSwift.hpp +16 -10
- package/nitrogen/generated/ios/swift/ArtworkRendering.swift +40 -0
- package/nitrogen/generated/ios/swift/CarPlayPlayingIndicatorLocation.swift +40 -0
- package/nitrogen/generated/ios/swift/IOSOptions.swift +7 -2
- package/nitrogen/generated/ios/swift/NativeBrowserConfiguration.swift +5 -5
- package/nitrogen/generated/ios/swift/NitroIOSUpdateOptions.swift +12 -1
- package/nitrogen/generated/ios/swift/PlayerCapabilities.swift +8 -27
- package/nitrogen/generated/ios/swift/ResolvedTrack.swift +54 -83
- package/nitrogen/generated/ios/swift/Section.swift +100 -0
- package/nitrogen/generated/ios/swift/SectionStyle.swift +64 -0
- package/nitrogen/generated/ios/swift/StyleDisplay.swift +40 -0
- package/nitrogen/generated/ios/swift/Track.swift +20 -73
- package/nitrogen/generated/ios/swift/TrackStyle.swift +28 -22
- 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++/IOSOptions.hpp +9 -2
- package/nitrogen/generated/shared/c++/NativeBrowserConfiguration.hpp +6 -6
- package/nitrogen/generated/shared/c++/NitroIOSUpdateOptions.hpp +9 -2
- package/nitrogen/generated/shared/c++/PlayerCapabilities.hpp +6 -9
- package/nitrogen/generated/shared/c++/ResolvedTrack.hpp +30 -38
- package/nitrogen/generated/shared/c++/Section.hpp +106 -0
- package/nitrogen/generated/shared/c++/SectionStyle.hpp +96 -0
- package/nitrogen/generated/shared/c++/StyleDisplay.hpp +76 -0
- package/nitrogen/generated/shared/c++/Track.hpp +15 -31
- package/nitrogen/generated/shared/c++/TrackStyle.hpp +50 -34
- package/package.json +3 -2
- package/src/AudioBrowser.ts +1 -0
- package/src/features/browser-config.test.ts +21 -6
- package/src/features/browser-config.ts +11 -8
- package/src/features/browser.test.ts +1 -1
- package/src/features/browser.ts +2 -2
- package/src/features/favorites.ts +13 -10
- package/src/features/hook-wiring.test.ts +63 -15
- package/src/features/playback/controls.ts +4 -2
- package/src/features/playback/state.ts +2 -3
- package/src/features/playback/trackPlaybackTime.ts +1 -1
- package/src/features/player/options.ts +27 -19
- package/src/features/player/setup.test.ts +12 -3
- package/src/features/player/setup.ts +3 -1
- package/src/features/player/validateOptions.ts +2 -0
- package/src/features/queue/activeTrack.ts +14 -3
- package/src/features/queue/queue.ts +11 -4
- package/src/nitro-stub-drift.test.ts +277 -0
- package/src/public-surface.test.ts +40 -0
- package/src/specs/audio-browser.nitro.ts +4 -3
- package/src/style-resolution.test.ts +139 -0
- package/src/types/browser-native.ts +2 -2
- package/src/types/browser-nodes.ts +268 -136
- package/src/types/browser.ts +34 -55
- package/src/utils/LazyNativeEmitter.ts +20 -10
- package/src/utils/NativeUpdatedValue.ts +29 -13
- package/src/utils/getTrackIdentity.ts +20 -0
- package/src/utils/useNativeValueRefreshedBy.ts +38 -0
- package/src/web/NativeAudioBrowser.ts +37 -22
- package/src/web/browser/BrowserManager.ts +176 -95
- package/src/web/browser/FavoriteManager.test.ts +84 -0
- package/src/web/browser/FavoriteManager.ts +28 -23
- 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/player/NowPlayingManager.ts +4 -3
- package/src/web/util/BrowserPathHelper.test.ts +52 -0
- package/src/web/util/BrowserPathHelper.ts +61 -13
- package/ios/CarPlay/ImageRowItem+CarPlay.swift +0 -19
- package/nitrogen/generated/android/c++/JFavoriteConfig.hpp +0 -58
- package/nitrogen/generated/android/c++/JImageRowItem.hpp +0 -105
- 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/kotlin/com/margelo/nitro/audiobrowser/ImageRowItem.kt +0 -68
- 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/Variant_Bool_FavoriteConfig.swift +0 -18
- package/nitrogen/generated/shared/c++/FavoriteConfig.hpp +0 -84
- package/nitrogen/generated/shared/c++/ImageRowItem.hpp +0 -129
|
@@ -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
|
|
@@ -25,8 +25,8 @@ enum SearchDrillIn {
|
|
|
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,34 @@
|
|
|
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
|
+
}
|
|
@@ -1,35 +1,69 @@
|
|
|
1
1
|
// Queue scope is the tapped section, not the whole page (ADR 0006): the
|
|
2
2
|
// playback context a listener expects is the list they tapped in — a page
|
|
3
3
|
// aggregating several sections must not leak next/previous across them.
|
|
4
|
+
// Sections are structural (ADR 0010), so scoping is a lookup, not a
|
|
5
|
+
// groupTitle-run derivation.
|
|
4
6
|
enum SectionScope {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
/// The section containing the tapped identity, plus the tapped child's
|
|
8
|
+
/// offset within it — non-nil only when the stamped flat index pinned the
|
|
9
|
+
/// exact copy.
|
|
10
|
+
struct Scoped {
|
|
11
|
+
let section: Section
|
|
12
|
+
let tappedOffset: Int?
|
|
11
13
|
}
|
|
12
14
|
|
|
13
|
-
/// The section of `
|
|
14
|
-
/// when
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
/// The section of `sections` containing the playable `trackId` (a track
|
|
16
|
+
/// identity: id when non-blank, else src), or nil when not found.
|
|
17
|
+
///
|
|
18
|
+
/// `tappedIndex` — the flat page position stamped into the contextual URL
|
|
19
|
+
/// (children concatenated in section order) — is a tie-breaker, never an
|
|
20
|
+
/// identifier: when the child at that position still carries the tapped
|
|
21
|
+
/// identity, it pins which section (and which copy) was tapped; when it
|
|
22
|
+
/// doesn't (the list shifted), resolution falls back to the first section
|
|
23
|
+
/// containing the identity. A stale index can therefore never select a
|
|
24
|
+
/// different track — at worst a different copy of the same one.
|
|
25
|
+
static func scoped(
|
|
26
|
+
in sections: [Section],
|
|
27
|
+
containing trackId: String,
|
|
28
|
+
tappedIndex: Int? = nil,
|
|
29
|
+
) -> Scoped? {
|
|
30
|
+
if let tappedIndex, tappedIndex >= 0 {
|
|
31
|
+
var start = 0
|
|
32
|
+
for section in sections {
|
|
33
|
+
let offset = tappedIndex - start
|
|
34
|
+
if offset < section.children.count {
|
|
35
|
+
if section.children[offset].identity == trackId {
|
|
36
|
+
return Scoped(section: section, tappedOffset: offset)
|
|
37
|
+
}
|
|
38
|
+
break
|
|
39
|
+
}
|
|
40
|
+
start += section.children.count
|
|
19
41
|
}
|
|
20
42
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
var start = index
|
|
26
|
-
while start > 0, children[start - 1].groupTitle == group {
|
|
27
|
-
start -= 1
|
|
28
|
-
}
|
|
29
|
-
var end = index
|
|
30
|
-
while end + 1 < children.count, children[end + 1].groupTitle == group {
|
|
31
|
-
end += 1
|
|
43
|
+
for section in sections {
|
|
44
|
+
if section.children.contains(where: { $0.identity == trackId }) {
|
|
45
|
+
return Scoped(section: section, tappedOffset: nil)
|
|
46
|
+
}
|
|
32
47
|
}
|
|
33
|
-
return
|
|
48
|
+
return nil
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// MARK: - Page shape helpers (ADR 0010)
|
|
53
|
+
|
|
54
|
+
extension ResolvedTrack {
|
|
55
|
+
/// The canonical sectioned shape: `sections` wins when present; plain
|
|
56
|
+
/// `children` is authoring sugar for one untitled section.
|
|
57
|
+
var normalizedSections: [Section]? {
|
|
58
|
+
if let sections { return sections }
|
|
59
|
+
guard let children else { return nil }
|
|
60
|
+
return [.untitled(children)]
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/// The page's children concatenated in section order — the flattening
|
|
64
|
+
/// that defines contextual `__index` positions and the flat views (tabs,
|
|
65
|
+
/// search) of a sectioned page.
|
|
66
|
+
var flattenedChildren: [Track]? {
|
|
67
|
+
normalizedSections.map { $0.flatMap(\.children) }
|
|
34
68
|
}
|
|
35
69
|
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#if canImport(NitroModules)
|
|
2
|
+
import NitroModules
|
|
3
|
+
#endif
|
|
4
|
+
|
|
5
|
+
/// The one place style declarations resolve to effective values (ADR 0011).
|
|
6
|
+
///
|
|
7
|
+
/// Two mechanisms, deliberately distinct:
|
|
8
|
+
/// - **Inherited item properties** resolve `track ?? section ?? page`,
|
|
9
|
+
/// per property — a track's own declaration wins over the blocks that
|
|
10
|
+
/// contain it.
|
|
11
|
+
/// - **Container properties and the positional `display`** resolve by scope
|
|
12
|
+
/// override: `section ?? page` — the page declares for its whole scope, a
|
|
13
|
+
/// section overrides for its own children. `display` is never inherited
|
|
14
|
+
/// item-to-container: each holder describes its own children, and a
|
|
15
|
+
/// track's `display` is the promise for the page *it* opens, not its
|
|
16
|
+
/// rendering inside this section.
|
|
17
|
+
///
|
|
18
|
+
/// Every key of `SectionStyle` must be read by `sectionStyle(section:page:)`
|
|
19
|
+
/// and every inherited key of `TrackStyle` by `trackStyle(track:section:)` —
|
|
20
|
+
/// Nitro flattens the spec's `extends`, so `src/style-resolution.test.ts`
|
|
21
|
+
/// enforces this completeness, not the type system.
|
|
22
|
+
enum StyleResolver {
|
|
23
|
+
/// Folds the page block into a section's block: every `SectionStyle` key
|
|
24
|
+
/// resolves `section ?? page`. The result is the section's effective
|
|
25
|
+
/// block; item resolution then only needs `track ?? section`.
|
|
26
|
+
static func sectionStyle(section: SectionStyle?, page: SectionStyle?) -> SectionStyle {
|
|
27
|
+
// Argument order is the generated init's (own properties before inherited
|
|
28
|
+
// ones — Nitro flattens `extends` own-props-first); the stub mirrors it.
|
|
29
|
+
SectionStyle(
|
|
30
|
+
gridWrap: section?.gridWrap ?? page?.gridWrap,
|
|
31
|
+
display: section?.display ?? page?.display,
|
|
32
|
+
artworkRendering: section?.artworkRendering ?? page?.artworkRendering,
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/// Resolves a track's effective item properties against its (page-folded)
|
|
37
|
+
/// section block.
|
|
38
|
+
static func trackStyle(track: TrackStyle?, section: SectionStyle?) -> TrackStyle {
|
|
39
|
+
TrackStyle(
|
|
40
|
+
// Positional deny-list: `display` is never inherited onto an item —
|
|
41
|
+
// resolved nil, so no renderer can mistake the handle's page promise
|
|
42
|
+
// for this item's own layout.
|
|
43
|
+
display: nil,
|
|
44
|
+
artworkRendering: track?.artworkRendering ?? section?.artworkRendering,
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// Compares the tab-list fields the CarPlay tab bar actually renders.
|
|
2
2
|
enum TabBarEntries {
|
|
3
|
-
/// Whether two tab lists produce identical tab-bar entries — title,
|
|
3
|
+
/// Whether two tab lists produce identical tab-bar entries — title, path,
|
|
4
4
|
/// and the artwork inputs of `applyTabBarEntry`. Used to suppress
|
|
5
5
|
/// `tabsChanged` when a tabs re-query (e.g. from `invalidateAllContent()`)
|
|
6
6
|
/// resolves to the same entries, so an unchanged result never churns the
|
|
@@ -8,7 +8,7 @@ enum TabBarEntries {
|
|
|
8
8
|
static func same(_ old: [Track]?, _ new: [Track]) -> Bool {
|
|
9
9
|
guard let old, old.count == new.count else { return false }
|
|
10
10
|
return zip(old, new).allSatisfy {
|
|
11
|
-
$0.title == $1.title && $0.
|
|
11
|
+
$0.title == $1.title && $0.path == $1.path && $0.artwork == $1.artwork
|
|
12
12
|
&& $0.artworkSource?.uri == $1.artworkSource?.uri
|
|
13
13
|
}
|
|
14
14
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
/// `{id}` template-token substitution for request-config string values (path, query values,
|
|
4
|
+
/// header values), used by artwork URL resolution so a `nowPlayingArtwork` like
|
|
5
|
+
/// `{ path: "/artwork/{id}" }` resolves per track.
|
|
6
|
+
///
|
|
7
|
+
/// A track without a non-blank id leaves the token LITERALLY in place — the request then
|
|
8
|
+
/// visibly 404s, which is intended (garbage in, garbage out with a self-describing error
|
|
9
|
+
/// trail; the caller logs a single warning when `containsToken` still matches after
|
|
10
|
+
/// substitution). Mirrors Android's `substituteTrackId` / `configContainsIdToken` in
|
|
11
|
+
/// `BrowserUrlResolution.kt` — keep the two in sync.
|
|
12
|
+
enum TrackIdTemplate {
|
|
13
|
+
static let token = "{id}"
|
|
14
|
+
|
|
15
|
+
/// Replaces the token when `id` is non-blank; otherwise returns the value unchanged
|
|
16
|
+
/// (token left literal).
|
|
17
|
+
static func substitute(_ value: String?, id: String?) -> String? {
|
|
18
|
+
guard let id, !id.isEmpty else { return value }
|
|
19
|
+
return value?.replacingOccurrences(of: token, with: id)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/// Dictionary-value variant of `substitute` (query / header values).
|
|
23
|
+
static func substitute(_ values: [String: String]?, id: String?) -> [String: String]? {
|
|
24
|
+
guard let id, !id.isEmpty else { return values }
|
|
25
|
+
return values?.mapValues { $0.replacingOccurrences(of: token, with: id) }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/// Whether the value still carries the token (an unfilled `{id}`).
|
|
29
|
+
static func containsToken(_ value: String?) -> Bool {
|
|
30
|
+
value?.contains(token) == true
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/// Whether any dictionary value still carries the token.
|
|
34
|
+
static func containsToken(_ values: [String: String]?) -> Bool {
|
|
35
|
+
values?.values.contains { $0.contains(token) } == true
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -29,7 +29,8 @@ enum CarPlayArtworkResolver {
|
|
|
29
29
|
/// - Parameters:
|
|
30
30
|
/// - artwork: The track's `artwork` field (may be an SF Symbol string or URL)
|
|
31
31
|
/// - artworkSourceUri: The track's `artworkSource?.uri` field
|
|
32
|
-
/// -
|
|
32
|
+
/// - stencil: Whether the artwork renders as a monochrome glyph tinted to
|
|
33
|
+
/// the surface appearance (`style.artworkRendering: 'stencil'`)
|
|
33
34
|
/// - targetWidth: Target width in points
|
|
34
35
|
/// - targetHeight: Target height in points
|
|
35
36
|
/// - displayScale: The CarPlay display scale factor
|
|
@@ -37,7 +38,7 @@ enum CarPlayArtworkResolver {
|
|
|
37
38
|
static func resolve(
|
|
38
39
|
artwork: String?,
|
|
39
40
|
artworkSourceUri: String?,
|
|
40
|
-
|
|
41
|
+
stencil: Bool,
|
|
41
42
|
targetWidth: Double,
|
|
42
43
|
targetHeight: Double,
|
|
43
44
|
displayScale: Double,
|
|
@@ -57,7 +58,7 @@ enum CarPlayArtworkResolver {
|
|
|
57
58
|
return resolveDirectFallback(
|
|
58
59
|
artwork: artwork,
|
|
59
60
|
artworkSourceUri: artworkSourceUri,
|
|
60
|
-
|
|
61
|
+
stencil: stencil,
|
|
61
62
|
targetWidth: targetWidth,
|
|
62
63
|
targetHeight: targetHeight,
|
|
63
64
|
)
|
|
@@ -66,7 +67,7 @@ enum CarPlayArtworkResolver {
|
|
|
66
67
|
return .fetch(
|
|
67
68
|
uri: resolved.uri,
|
|
68
69
|
headers: resolved.headers,
|
|
69
|
-
shouldTint:
|
|
70
|
+
shouldTint: stencil,
|
|
70
71
|
isSvg: isSvg,
|
|
71
72
|
)
|
|
72
73
|
}
|
|
@@ -76,7 +77,7 @@ enum CarPlayArtworkResolver {
|
|
|
76
77
|
return resolveDirectFallback(
|
|
77
78
|
artwork: artwork,
|
|
78
79
|
artworkSourceUri: artworkSourceUri,
|
|
79
|
-
|
|
80
|
+
stencil: stencil,
|
|
80
81
|
targetWidth: targetWidth,
|
|
81
82
|
targetHeight: targetHeight,
|
|
82
83
|
)
|
|
@@ -85,7 +86,7 @@ enum CarPlayArtworkResolver {
|
|
|
85
86
|
private static func resolveDirectFallback(
|
|
86
87
|
artwork: String?,
|
|
87
88
|
artworkSourceUri: String?,
|
|
88
|
-
|
|
89
|
+
stencil: Bool,
|
|
89
90
|
targetWidth: Double,
|
|
90
91
|
targetHeight: Double,
|
|
91
92
|
) -> ArtworkLoadAction {
|
|
@@ -100,7 +101,7 @@ enum CarPlayArtworkResolver {
|
|
|
100
101
|
return .fetch(
|
|
101
102
|
uri: directUri,
|
|
102
103
|
headers: nil,
|
|
103
|
-
shouldTint:
|
|
104
|
+
shouldTint: stencil,
|
|
104
105
|
isSvg: isSvg,
|
|
105
106
|
)
|
|
106
107
|
}
|