react-native-audio-browser 0.2.0-next.11 → 0.2.0-next.13
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 +14 -4
- package/android/build.gradle +20 -1
- package/android/src/main/java/com/audiobrowser/AudioBrowser.kt +115 -26
- package/android/src/main/java/com/audiobrowser/browser/BrowserManager.kt +262 -188
- package/android/src/main/java/com/audiobrowser/browser/BrowserUrlResolution.kt +23 -3
- package/android/src/main/java/com/audiobrowser/browser/InertStyleDiagnostic.kt +267 -0
- package/android/src/main/java/com/audiobrowser/browser/JsonModels.kt +95 -58
- package/android/src/main/java/com/audiobrowser/browser/SectionScope.kt +68 -26
- package/android/src/main/java/com/audiobrowser/browser/StyleResolver.kt +60 -0
- package/android/src/main/java/com/audiobrowser/extension/ResolvedTrackExt.kt +19 -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/model/PlayerUpdateOptions.kt +1 -1
- 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 +109 -74
- package/android/src/main/java/com/audiobrowser/player/Player.kt +51 -30
- package/android/src/main/java/com/audiobrowser/player/PlayerCapabilitiesExt.kt +2 -15
- package/android/src/main/java/com/audiobrowser/player/ShuffleOrderLedBy.kt +30 -0
- 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 +108 -0
- package/android/src/main/java/com/audiobrowser/util/TrackFactory.kt +52 -53
- package/android/src/test/java/com/audiobrowser/TestFixtures.kt +74 -41
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerFavoritesTest.kt +153 -0
- package/android/src/test/java/com/audiobrowser/browser/BrowserManagerTest.kt +229 -50
- 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 +1 -1
- package/android/src/test/java/com/audiobrowser/browser/JsonStyleTest.kt +147 -0
- package/android/src/test/java/com/audiobrowser/browser/SectionScopeTest.kt +128 -53
- 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/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/player/ShuffleOrderLedByTest.kt +79 -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 +229 -180
- package/ios/Browser/BrowserPathHelper.swift +44 -44
- package/ios/Browser/InertStyleDiagnostic.swift +279 -0
- package/ios/Browser/JsonModels.swift +258 -106
- package/ios/Browser/SearchDrillIn.swift +6 -6
- 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 +38 -18
- package/ios/CarPlay/CarPlayListItemFactory.swift +289 -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/Extension/UIApplication+ActiveScene.swift +27 -0
- package/ios/Http/HttpClient.swift +8 -2
- package/ios/HybridAudioBrowser.swift +166 -45
- package/ios/Model/NitroTypeStubs.swift +106 -21
- package/ios/Model/PlayerUpdateOptions.swift +7 -0
- package/ios/Player/MediaIntentCriteria.swift +13 -5
- package/ios/Player/MediaLoader.swift +33 -9
- package/ios/Player/NowPlayingUpdater.swift +54 -6
- package/ios/Player/PlaybackCoordinator.swift +13 -6
- package/ios/Player/PlaybackTimer.swift +8 -2
- package/ios/Player/QueueManager.swift +36 -10
- package/ios/Player/RetryManager.swift +4 -3
- package/ios/Player/ShuffleOrder.swift +23 -0
- package/ios/Player/SleepTimerHandling.swift +13 -0
- package/ios/RemoteCommand/RemoteCommandController.swift +53 -18
- 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/PlaybackStateStoreTests.swift +4 -3
- package/ios/Tests/QueueManagerTests.swift +72 -6
- package/ios/Tests/RemoteCommandControllerTests.swift +16 -0
- package/ios/Tests/ResolvedTrackCopyingTests.swift +37 -35
- 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 +7 -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/TrackPlayer.swift +57 -34
- package/ios/TrackSelector.swift +45 -30
- package/ios/Util/ArtworkImageFetcher.swift +16 -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 +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/progress.js +2 -1
- 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 +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/TrackPlayer/QueueManager.js +14 -0
- package/lib/commonjs/web/TrackPlayer/QueueManager.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/progress.js +2 -1
- 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 +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/TrackPlayer/QueueManager.js +14 -0
- package/lib/module/web/TrackPlayer/QueueManager.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/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 +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 +361 -126
- 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 +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__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 +2 -5
- 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 +33 -14
- 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 +22 -10
- package/nitrogen/generated/android/c++/JNativeRouteEntry.hpp +14 -2
- package/nitrogen/generated/android/c++/JNativeSetupPlayerOptions.hpp +10 -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 +8 -3
- package/nitrogen/generated/android/c++/JPlayerCapabilities.hpp +5 -11
- package/nitrogen/generated/android/c++/JResolvedTrack.hpp +55 -51
- package/nitrogen/generated/android/c++/JSection.hpp +120 -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 +23 -48
- package/nitrogen/generated/android/c++/JTrackLoadEvent.hpp +8 -2
- package/nitrogen/generated/android/c++/JTrackStyle.hpp +46 -18
- package/nitrogen/generated/android/c++/JVariant_ResolvedTrack_BrowseError_Promise_BrowseResult_.hpp +16 -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/CardImage.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/GridTile.kt +24 -0
- 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 +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/{FavoriteConfig.kt → Section.kt} +18 -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 -15
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/audiobrowser/TrackStyle.kt +35 -5
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Bridge.hpp +158 -82
- package/nitrogen/generated/ios/AudioBrowser-Swift-Cxx-Umbrella.hpp +25 -10
- package/nitrogen/generated/ios/c++/HybridAudioBrowserSpecSwift.hpp +25 -10
- 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/GridTile.swift +44 -0
- 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 +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 +133 -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 +86 -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++/CardImage.hpp +76 -0
- package/nitrogen/generated/shared/c++/GridTile.hpp +80 -0
- 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 +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 +126 -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 +73 -34
- package/package.json +7 -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/progress.ts +2 -1
- package/src/features/playback/rate.ts +8 -1
- 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 +40 -0
- package/src/public-surface.test.ts +40 -0
- package/src/specs/audio-browser.nitro.ts +4 -3
- package/src/style-resolution.test.ts +210 -0
- package/src/types/browser-native.ts +2 -2
- package/src/types/browser-nodes.ts +377 -135
- 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/TrackPlayer/QueueManager.test.ts +29 -0
- package/src/web/TrackPlayer/QueueManager.ts +14 -0
- 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/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 +246 -0
- 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
|
@@ -62,41 +62,196 @@ extension JsonArtwork {
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
///
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
65
|
+
/// A style declaration block on the wire (ADR 0011):
|
|
66
|
+
/// `{ display?, gridWrap?, artworkRendering? }`.
|
|
67
|
+
///
|
|
68
|
+
/// One JSON model serves both the `TrackStyle` and `SectionStyle` positions —
|
|
69
|
+
/// keys that don't exist at the narrower position simply don't map.
|
|
70
|
+
///
|
|
71
|
+
/// Decoding is tolerant by design: a stale payload — the retired string
|
|
72
|
+
/// styles, a wrong-typed field, an unknown enum value — must degrade to "no
|
|
73
|
+
/// declaration", never fail the page or the persisted playback state (the
|
|
74
|
+
/// decoders above this are strict, so a throw here would kill the whole
|
|
75
|
+
/// payload). `init(from:)` therefore never throws, and unknown enum values
|
|
76
|
+
/// map to nil at `toNitro` time.
|
|
77
|
+
struct JsonStyle: Codable, Equatable {
|
|
78
|
+
let display: String?
|
|
79
|
+
let gridWrap: Bool?
|
|
80
|
+
let gridTile: String?
|
|
81
|
+
let artworkRendering: String?
|
|
82
|
+
let imageShape: String?
|
|
83
|
+
let accessorySymbol: String?
|
|
84
|
+
let cardTint: String?
|
|
85
|
+
let cardImage: String?
|
|
77
86
|
|
|
78
87
|
init(
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
display: String? = nil,
|
|
89
|
+
gridWrap: Bool? = nil,
|
|
90
|
+
gridTile: String? = nil,
|
|
91
|
+
artworkRendering: String? = nil,
|
|
92
|
+
imageShape: String? = nil,
|
|
93
|
+
accessorySymbol: String? = nil,
|
|
94
|
+
cardTint: String? = nil,
|
|
95
|
+
cardImage: String? = nil,
|
|
96
|
+
) {
|
|
97
|
+
self.display = display
|
|
98
|
+
self.gridWrap = gridWrap
|
|
99
|
+
self.gridTile = gridTile
|
|
100
|
+
self.artworkRendering = artworkRendering
|
|
101
|
+
self.imageShape = imageShape
|
|
102
|
+
self.accessorySymbol = accessorySymbol
|
|
103
|
+
self.cardTint = cardTint
|
|
104
|
+
self.cardImage = cardImage
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
init(from decoder: Decoder) throws {
|
|
108
|
+
// A non-object value (the retired `style: 'grid'` string) decodes as an
|
|
109
|
+
// empty block rather than failing the parent.
|
|
110
|
+
guard let container = try? decoder.container(keyedBy: CodingKeys.self) else {
|
|
111
|
+
self.init()
|
|
112
|
+
return
|
|
113
|
+
}
|
|
114
|
+
self.init(
|
|
115
|
+
display: (try? container.decodeIfPresent(String.self, forKey: .display)) ?? nil,
|
|
116
|
+
gridWrap: (try? container.decodeIfPresent(Bool.self, forKey: .gridWrap)) ?? nil,
|
|
117
|
+
gridTile: (try? container.decodeIfPresent(String.self, forKey: .gridTile)) ?? nil,
|
|
118
|
+
artworkRendering: (try? container.decodeIfPresent(String.self, forKey: .artworkRendering)) ?? nil,
|
|
119
|
+
imageShape: (try? container.decodeIfPresent(String.self, forKey: .imageShape)) ?? nil,
|
|
120
|
+
accessorySymbol: (try? container.decodeIfPresent(String.self, forKey: .accessorySymbol)) ?? nil,
|
|
121
|
+
cardTint: (try? container.decodeIfPresent(String.self, forKey: .cardTint)) ?? nil,
|
|
122
|
+
cardImage: (try? container.decodeIfPresent(String.self, forKey: .cardImage)) ?? nil,
|
|
123
|
+
)
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
extension JsonStyle {
|
|
128
|
+
/// The wire strings map to Nitro enums here, tolerantly: an unknown value
|
|
129
|
+
/// (a future `display` mode, say) is no declaration, not an error. A block
|
|
130
|
+
/// that resolves to no declarations at all — `{}`, the tolerant decoder's
|
|
131
|
+
/// empty result for the retired string vocabulary, or all-unknown values —
|
|
132
|
+
/// maps to nil, so "no declaration" has one shape on every platform
|
|
133
|
+
/// (Android's lenient mapper makes the same collapse).
|
|
134
|
+
func toTrackStyle() -> TrackStyle? {
|
|
135
|
+
let display = display.flatMap { StyleDisplay(fromString: $0.lowercased()) }
|
|
136
|
+
let artworkRendering = artworkRendering.flatMap { ArtworkRendering(fromString: $0.lowercased()) }
|
|
137
|
+
let imageShape = imageShape.flatMap { ImageShape(fromString: $0.lowercased()) }
|
|
138
|
+
// The 'none' sentinel is a legitimate value; only emptiness collapses.
|
|
139
|
+
let accessorySymbol = accessorySymbol?.isEmpty == false ? accessorySymbol : nil
|
|
140
|
+
let cardTint = cardTint?.isEmpty == false ? cardTint : nil
|
|
141
|
+
let cardImage = cardImage.flatMap { CardImage(fromString: $0.lowercased()) }
|
|
142
|
+
guard display != nil || artworkRendering != nil || imageShape != nil
|
|
143
|
+
|| accessorySymbol != nil || cardTint != nil || cardImage != nil
|
|
144
|
+
else { return nil }
|
|
145
|
+
return TrackStyle(
|
|
146
|
+
display: display,
|
|
147
|
+
artworkRendering: artworkRendering,
|
|
148
|
+
imageShape: imageShape,
|
|
149
|
+
accessorySymbol: accessorySymbol,
|
|
150
|
+
cardTint: cardTint,
|
|
151
|
+
cardImage: cardImage,
|
|
152
|
+
)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
func toSectionStyle() -> SectionStyle? {
|
|
156
|
+
let display = display.flatMap { StyleDisplay(fromString: $0.lowercased()) }
|
|
157
|
+
let gridTile = gridTile.flatMap { GridTile(fromString: $0.lowercased()) }
|
|
158
|
+
let artworkRendering = artworkRendering.flatMap { ArtworkRendering(fromString: $0.lowercased()) }
|
|
159
|
+
let imageShape = imageShape.flatMap { ImageShape(fromString: $0.lowercased()) }
|
|
160
|
+
let accessorySymbol = accessorySymbol?.isEmpty == false ? accessorySymbol : nil
|
|
161
|
+
let cardTint = cardTint?.isEmpty == false ? cardTint : nil
|
|
162
|
+
let cardImage = cardImage.flatMap { CardImage(fromString: $0.lowercased()) }
|
|
163
|
+
guard display != nil || artworkRendering != nil || gridWrap != nil
|
|
164
|
+
|| gridTile != nil || imageShape != nil || accessorySymbol != nil
|
|
165
|
+
|| cardTint != nil || cardImage != nil
|
|
166
|
+
else { return nil }
|
|
167
|
+
// Argument order is the generated init's (own properties before
|
|
168
|
+
// inherited ones — Nitro flattens `extends` own-props-first).
|
|
169
|
+
return SectionStyle(
|
|
170
|
+
gridWrap: gridWrap,
|
|
171
|
+
gridTile: gridTile,
|
|
172
|
+
display: display,
|
|
173
|
+
artworkRendering: artworkRendering,
|
|
174
|
+
imageShape: imageShape,
|
|
175
|
+
accessorySymbol: accessorySymbol,
|
|
176
|
+
cardTint: cardTint,
|
|
177
|
+
cardImage: cardImage,
|
|
178
|
+
)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/// Snapshot a live track block back to its JSON model (for persistence).
|
|
182
|
+
/// An all-nil block snapshots as no block — the decoders collapse it to
|
|
183
|
+
/// "no declaration" anyway, so never persist the distinction.
|
|
184
|
+
init?(_ style: TrackStyle?) {
|
|
185
|
+
guard let style,
|
|
186
|
+
style.display != nil || style.artworkRendering != nil
|
|
187
|
+
|| style.imageShape != nil || style.accessorySymbol != nil
|
|
188
|
+
|| style.cardTint != nil || style.cardImage != nil
|
|
189
|
+
else { return nil }
|
|
190
|
+
self.init(
|
|
191
|
+
display: Self.string(style.display),
|
|
192
|
+
artworkRendering: Self.string(style.artworkRendering),
|
|
193
|
+
imageShape: Self.string(style.imageShape),
|
|
194
|
+
accessorySymbol: style.accessorySymbol,
|
|
195
|
+
cardTint: style.cardTint,
|
|
196
|
+
cardImage: Self.string(style.cardImage),
|
|
197
|
+
)
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
private static func string(_ display: StyleDisplay?) -> String? {
|
|
201
|
+
switch display {
|
|
202
|
+
case .list: "list"
|
|
203
|
+
case .grid: "grid"
|
|
204
|
+
case nil: nil
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
private static func string(_ rendering: ArtworkRendering?) -> String? {
|
|
209
|
+
switch rendering {
|
|
210
|
+
case .original: "original"
|
|
211
|
+
case .stencil: "stencil"
|
|
212
|
+
case nil: nil
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
private static func string(_ shape: ImageShape?) -> String? {
|
|
217
|
+
switch shape {
|
|
218
|
+
case .circular: "circular"
|
|
219
|
+
case .roundedRectangle: "rounded-rectangle"
|
|
220
|
+
case nil: nil
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
private static func string(_ mode: CardImage?) -> String? {
|
|
225
|
+
switch mode {
|
|
226
|
+
case .normal: "normal"
|
|
227
|
+
case .background: "background"
|
|
228
|
+
case nil: nil
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/// JSON model for a page section (ADR 0010). Legacy `groupTitle`/`imageRow`
|
|
234
|
+
/// keys in payloads are simply unknown to these models and decode as
|
|
235
|
+
/// ignored dead weight.
|
|
236
|
+
struct JsonSection: Codable {
|
|
237
|
+
let title: String?
|
|
238
|
+
let subtitle: String?
|
|
239
|
+
let style: JsonStyle?
|
|
240
|
+
let path: String?
|
|
241
|
+
let children: [JsonTrack]
|
|
242
|
+
|
|
243
|
+
init(
|
|
244
|
+
title: String? = nil,
|
|
245
|
+
subtitle: String? = nil,
|
|
246
|
+
style: JsonStyle? = nil,
|
|
247
|
+
path: String? = nil,
|
|
248
|
+
children: [JsonTrack],
|
|
89
249
|
) {
|
|
90
|
-
self.id = id
|
|
91
|
-
self.url = url
|
|
92
|
-
self.src = src
|
|
93
|
-
self.artwork = artwork
|
|
94
250
|
self.title = title
|
|
95
|
-
self.
|
|
96
|
-
self.
|
|
97
|
-
self.
|
|
98
|
-
self.
|
|
99
|
-
self.request = request
|
|
251
|
+
self.subtitle = subtitle
|
|
252
|
+
self.style = style
|
|
253
|
+
self.path = path
|
|
254
|
+
self.children = children
|
|
100
255
|
}
|
|
101
256
|
}
|
|
102
257
|
|
|
@@ -116,59 +271,59 @@ struct JsonTrackRequest: Codable {
|
|
|
116
271
|
/// JSON model for resolved track (container with children).
|
|
117
272
|
struct JsonResolvedTrack: Codable {
|
|
118
273
|
let id: String?
|
|
119
|
-
let
|
|
274
|
+
let path: String
|
|
120
275
|
let title: String
|
|
121
276
|
let subtitle: String?
|
|
122
277
|
let artwork: JsonArtwork?
|
|
123
278
|
let artist: String?
|
|
124
|
-
let
|
|
279
|
+
let albumPath: String?
|
|
125
280
|
let album: String?
|
|
126
281
|
let description: String?
|
|
127
282
|
let genre: String?
|
|
128
283
|
let duration: Double?
|
|
284
|
+
let sections: [JsonSection]?
|
|
129
285
|
let children: [JsonTrack]?
|
|
130
286
|
let src: String?
|
|
131
|
-
let style:
|
|
132
|
-
let
|
|
133
|
-
let groupTitle: String?
|
|
287
|
+
let style: JsonStyle?
|
|
288
|
+
let disabled: Bool?
|
|
134
289
|
let live: Bool?
|
|
135
290
|
let carPlaySiriListButton: String?
|
|
136
291
|
|
|
137
292
|
init(
|
|
138
293
|
id: String? = nil,
|
|
139
|
-
|
|
294
|
+
path: String,
|
|
140
295
|
title: String,
|
|
141
296
|
subtitle: String? = nil,
|
|
142
297
|
artwork: JsonArtwork? = nil,
|
|
143
298
|
artist: String? = nil,
|
|
144
|
-
|
|
299
|
+
albumPath: String? = nil,
|
|
145
300
|
album: String? = nil,
|
|
146
301
|
description: String? = nil,
|
|
147
302
|
genre: String? = nil,
|
|
148
303
|
duration: Double? = nil,
|
|
304
|
+
sections: [JsonSection]? = nil,
|
|
149
305
|
children: [JsonTrack]? = nil,
|
|
150
306
|
src: String? = nil,
|
|
151
|
-
style:
|
|
152
|
-
|
|
153
|
-
groupTitle: String? = nil,
|
|
307
|
+
style: JsonStyle? = nil,
|
|
308
|
+
disabled: Bool? = nil,
|
|
154
309
|
live: Bool? = nil,
|
|
155
310
|
carPlaySiriListButton: String? = nil,
|
|
156
311
|
) {
|
|
157
|
-
self.
|
|
312
|
+
self.path = path
|
|
158
313
|
self.title = title
|
|
159
314
|
self.subtitle = subtitle
|
|
160
315
|
self.artwork = artwork
|
|
161
316
|
self.artist = artist
|
|
162
|
-
self.
|
|
317
|
+
self.albumPath = albumPath
|
|
163
318
|
self.album = album
|
|
164
319
|
self.description = description
|
|
165
320
|
self.genre = genre
|
|
166
321
|
self.duration = duration
|
|
322
|
+
self.sections = sections
|
|
167
323
|
self.children = children
|
|
168
324
|
self.src = src
|
|
169
325
|
self.style = style
|
|
170
|
-
self.
|
|
171
|
-
self.groupTitle = groupTitle
|
|
326
|
+
self.disabled = disabled
|
|
172
327
|
self.live = live
|
|
173
328
|
self.carPlaySiriListButton = carPlaySiriListButton
|
|
174
329
|
self.id = id
|
|
@@ -178,50 +333,46 @@ struct JsonResolvedTrack: Codable {
|
|
|
178
333
|
/// JSON model for individual tracks.
|
|
179
334
|
struct JsonTrack: Codable {
|
|
180
335
|
let id: String?
|
|
181
|
-
let
|
|
336
|
+
let path: String?
|
|
182
337
|
let title: String
|
|
183
338
|
let subtitle: String?
|
|
184
339
|
let artwork: JsonArtwork?
|
|
185
340
|
let artist: String?
|
|
186
|
-
let
|
|
341
|
+
let albumPath: String?
|
|
187
342
|
let album: String?
|
|
188
343
|
let description: String?
|
|
189
344
|
let genre: String?
|
|
190
345
|
let duration: Double?
|
|
191
346
|
let src: String?
|
|
192
347
|
let request: JsonTrackRequest?
|
|
193
|
-
let style:
|
|
194
|
-
let
|
|
195
|
-
let groupTitle: String?
|
|
348
|
+
let style: JsonStyle?
|
|
349
|
+
let disabled: Bool?
|
|
196
350
|
let live: Bool?
|
|
197
|
-
let imageRow: [JsonImageRowItem]?
|
|
198
351
|
|
|
199
352
|
init(
|
|
200
353
|
id: String? = nil,
|
|
201
|
-
|
|
354
|
+
path: String? = nil,
|
|
202
355
|
title: String,
|
|
203
356
|
subtitle: String? = nil,
|
|
204
357
|
artwork: JsonArtwork? = nil,
|
|
205
358
|
artist: String? = nil,
|
|
206
|
-
|
|
359
|
+
albumPath: String? = nil,
|
|
207
360
|
album: String? = nil,
|
|
208
361
|
description: String? = nil,
|
|
209
362
|
genre: String? = nil,
|
|
210
363
|
duration: Double? = nil,
|
|
211
364
|
src: String? = nil,
|
|
212
365
|
request: JsonTrackRequest? = nil,
|
|
213
|
-
style:
|
|
214
|
-
|
|
215
|
-
groupTitle: String? = nil,
|
|
366
|
+
style: JsonStyle? = nil,
|
|
367
|
+
disabled: Bool? = nil,
|
|
216
368
|
live: Bool? = nil,
|
|
217
|
-
imageRow: [JsonImageRowItem]? = nil,
|
|
218
369
|
) {
|
|
219
|
-
self.
|
|
370
|
+
self.path = path
|
|
220
371
|
self.title = title
|
|
221
372
|
self.subtitle = subtitle
|
|
222
373
|
self.artwork = artwork
|
|
223
374
|
self.artist = artist
|
|
224
|
-
self.
|
|
375
|
+
self.albumPath = albumPath
|
|
225
376
|
self.album = album
|
|
226
377
|
self.description = description
|
|
227
378
|
self.genre = genre
|
|
@@ -229,10 +380,8 @@ struct JsonTrack: Codable {
|
|
|
229
380
|
self.src = src
|
|
230
381
|
self.request = request
|
|
231
382
|
self.style = style
|
|
232
|
-
self.
|
|
233
|
-
self.groupTitle = groupTitle
|
|
383
|
+
self.disabled = disabled
|
|
234
384
|
self.live = live
|
|
235
|
-
self.imageRow = imageRow
|
|
236
385
|
self.id = id
|
|
237
386
|
}
|
|
238
387
|
}
|
|
@@ -250,26 +399,27 @@ struct JsonTrack: Codable {
|
|
|
250
399
|
|
|
251
400
|
extension JsonTrack {
|
|
252
401
|
/// Snapshot the persistable subset of a live Track (inverse of `toNitro()`).
|
|
402
|
+
/// The track's own declared style block and `disabled` persist (ADR 0011);
|
|
403
|
+
/// section/page-inherited values are never stamped onto tracks and
|
|
404
|
+
/// re-resolve at render, exactly as they do live.
|
|
253
405
|
init(from track: Track) {
|
|
254
406
|
self.init(
|
|
255
407
|
id: track.id,
|
|
256
|
-
|
|
408
|
+
path: track.path,
|
|
257
409
|
title: track.title,
|
|
258
410
|
subtitle: track.subtitle,
|
|
259
411
|
artwork: JsonArtwork(track.artwork),
|
|
260
412
|
artist: track.artist,
|
|
261
|
-
|
|
413
|
+
albumPath: track.albumPath,
|
|
262
414
|
album: track.album,
|
|
263
415
|
description: track.description,
|
|
264
416
|
genre: track.genre,
|
|
265
417
|
duration: track.duration,
|
|
266
418
|
src: track.src,
|
|
267
419
|
request: track.request.map(JsonTrackRequest.init(from:)),
|
|
268
|
-
style:
|
|
269
|
-
|
|
270
|
-
groupTitle: track.groupTitle,
|
|
420
|
+
style: JsonStyle(track.style),
|
|
421
|
+
disabled: track.disabled,
|
|
271
422
|
live: track.live,
|
|
272
|
-
imageRow: nil,
|
|
273
423
|
)
|
|
274
424
|
}
|
|
275
425
|
}
|
|
@@ -289,14 +439,16 @@ struct JsonTrack: Codable {
|
|
|
289
439
|
init(from track: Track) {
|
|
290
440
|
self.init(
|
|
291
441
|
id: track.id,
|
|
292
|
-
|
|
442
|
+
path: track.path,
|
|
293
443
|
title: track.title,
|
|
294
444
|
artwork: JsonArtwork(track.artwork),
|
|
295
445
|
artist: track.artist,
|
|
296
|
-
|
|
446
|
+
albumPath: track.albumPath,
|
|
297
447
|
album: track.album,
|
|
298
448
|
src: track.src,
|
|
299
449
|
request: track.request.map(JsonTrackRequest.init(from:)),
|
|
450
|
+
style: JsonStyle(track.style),
|
|
451
|
+
disabled: track.disabled,
|
|
300
452
|
live: track.live,
|
|
301
453
|
)
|
|
302
454
|
}
|
|
@@ -308,26 +460,14 @@ struct JsonTrack: Codable {
|
|
|
308
460
|
|
|
309
461
|
#if canImport(NitroModules)
|
|
310
462
|
|
|
311
|
-
|
|
312
|
-
func
|
|
313
|
-
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
extension JsonImageRowItem {
|
|
318
|
-
func toNitro() -> ImageRowItem {
|
|
319
|
-
ImageRowItem(
|
|
320
|
-
id: id,
|
|
321
|
-
url: url,
|
|
322
|
-
src: src,
|
|
323
|
-
artwork: artwork,
|
|
324
|
-
artworkSource: nil,
|
|
463
|
+
extension JsonSection {
|
|
464
|
+
func toNitro() -> Section {
|
|
465
|
+
Section(
|
|
325
466
|
title: title,
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
request: request?.toNitro(),
|
|
467
|
+
subtitle: subtitle,
|
|
468
|
+
style: style?.toSectionStyle(),
|
|
469
|
+
path: path,
|
|
470
|
+
children: children.map { $0.toNitro() },
|
|
331
471
|
)
|
|
332
472
|
}
|
|
333
473
|
}
|
|
@@ -335,28 +475,26 @@ struct JsonTrack: Codable {
|
|
|
335
475
|
extension JsonResolvedTrack {
|
|
336
476
|
func toNitro() -> ResolvedTrack {
|
|
337
477
|
ResolvedTrack(
|
|
338
|
-
|
|
478
|
+
path: path,
|
|
479
|
+
style: style?.toSectionStyle(),
|
|
480
|
+
sections: sections?.map { $0.toNitro() },
|
|
339
481
|
children: children?.map { $0.toNitro() },
|
|
340
482
|
carPlaySiriListButton: carPlaySiriListButton.flatMap { CarPlaySiriListButtonPosition(fromString: $0) },
|
|
341
483
|
id: id,
|
|
342
484
|
src: src,
|
|
343
485
|
artwork: artwork?.toNitro(),
|
|
344
486
|
artworkSource: nil, request: nil,
|
|
345
|
-
artworkCarPlayTinted: nil,
|
|
346
487
|
title: title,
|
|
347
488
|
subtitle: subtitle,
|
|
348
489
|
artist: artist,
|
|
349
|
-
|
|
490
|
+
albumPath: albumPath,
|
|
350
491
|
album: album,
|
|
351
492
|
description: description,
|
|
352
493
|
genre: genre,
|
|
353
494
|
duration: duration,
|
|
354
|
-
|
|
355
|
-
childrenStyle: childrenStyle?.toTrackStyle(),
|
|
495
|
+
disabled: disabled,
|
|
356
496
|
favorited: nil,
|
|
357
|
-
groupTitle: groupTitle,
|
|
358
497
|
live: live,
|
|
359
|
-
imageRow: nil,
|
|
360
498
|
)
|
|
361
499
|
}
|
|
362
500
|
}
|
|
@@ -365,26 +503,23 @@ struct JsonTrack: Codable {
|
|
|
365
503
|
func toNitro() -> Track {
|
|
366
504
|
Track(
|
|
367
505
|
id: id,
|
|
368
|
-
|
|
506
|
+
path: path,
|
|
369
507
|
src: src,
|
|
370
508
|
artwork: artwork?.toNitro(),
|
|
371
509
|
artworkSource: nil,
|
|
372
510
|
request: request?.toNitro(),
|
|
373
|
-
artworkCarPlayTinted: nil,
|
|
374
511
|
title: title,
|
|
375
512
|
subtitle: subtitle,
|
|
376
513
|
artist: artist,
|
|
377
|
-
|
|
514
|
+
albumPath: albumPath,
|
|
378
515
|
album: album,
|
|
379
516
|
description: description,
|
|
380
517
|
genre: genre,
|
|
381
518
|
duration: duration,
|
|
382
519
|
style: style?.toTrackStyle(),
|
|
383
|
-
|
|
520
|
+
disabled: disabled,
|
|
384
521
|
favorited: nil,
|
|
385
|
-
groupTitle: groupTitle,
|
|
386
522
|
live: live,
|
|
387
|
-
imageRow: imageRow?.map { $0.toNitro() },
|
|
388
523
|
)
|
|
389
524
|
}
|
|
390
525
|
}
|
|
@@ -396,15 +531,29 @@ struct JsonTrack: Codable {
|
|
|
396
531
|
func toNitro() -> Track {
|
|
397
532
|
Track(
|
|
398
533
|
id: id ?? "",
|
|
399
|
-
|
|
534
|
+
path: path,
|
|
400
535
|
src: src,
|
|
536
|
+
artwork: artwork?.toNitro(),
|
|
401
537
|
request: request.map { TrackRequest(userAgent: $0.userAgent, headers: $0.headers, query: $0.query) },
|
|
402
538
|
title: title,
|
|
403
539
|
artist: artist,
|
|
404
|
-
|
|
540
|
+
albumPath: albumPath,
|
|
405
541
|
album: album,
|
|
542
|
+
style: style?.toTrackStyle(),
|
|
543
|
+
disabled: disabled,
|
|
406
544
|
live: live,
|
|
407
|
-
|
|
545
|
+
)
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
extension JsonSection {
|
|
550
|
+
func toNitro() -> Section {
|
|
551
|
+
Section(
|
|
552
|
+
title: title,
|
|
553
|
+
subtitle: subtitle,
|
|
554
|
+
style: style?.toSectionStyle(),
|
|
555
|
+
path: path,
|
|
556
|
+
children: children.map { $0.toNitro() },
|
|
408
557
|
)
|
|
409
558
|
}
|
|
410
559
|
}
|
|
@@ -412,10 +561,13 @@ struct JsonTrack: Codable {
|
|
|
412
561
|
extension JsonResolvedTrack {
|
|
413
562
|
func toNitro() -> ResolvedTrack {
|
|
414
563
|
ResolvedTrack(
|
|
415
|
-
|
|
564
|
+
path: path,
|
|
565
|
+
style: style?.toSectionStyle(),
|
|
566
|
+
sections: sections?.map { $0.toNitro() },
|
|
416
567
|
children: children?.map { $0.toNitro() },
|
|
417
568
|
artwork: artwork?.toNitro(),
|
|
418
569
|
title: title,
|
|
570
|
+
disabled: disabled,
|
|
419
571
|
)
|
|
420
572
|
}
|
|
421
573
|
}
|
|
@@ -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,64 @@
|
|
|
1
|
+
#if canImport(NitroModules)
|
|
2
|
+
import NitroModules
|
|
3
|
+
#endif
|
|
4
|
+
|
|
5
|
+
/// The rendered form of a section — the single place where (resolved style,
|
|
6
|
+
/// platform capability) maps to what CarPlay draws. Degradation drops
|
|
7
|
+
/// decorations before layout (ADR 0011): a *wrapping* grid can only reach the
|
|
8
|
+
/// tile path where the platform has a wrapping tile container (CarPlay:
|
|
9
|
+
/// iOS 26+'s element API); without one it becomes a list, where every item
|
|
10
|
+
/// stays reachable instead of truncating at an unknowable width. A
|
|
11
|
+
/// single-line grid (`gridWrap: false`) renders everywhere — the legacy image
|
|
12
|
+
/// row IS the single-line presentation.
|
|
13
|
+
enum SectionPresentation: Equatable {
|
|
14
|
+
case list
|
|
15
|
+
case singleLineRow
|
|
16
|
+
case wrappingGrid
|
|
17
|
+
|
|
18
|
+
/// - Parameter supportsWrappingGrid: whether the platform has a wrapping
|
|
19
|
+
/// tile container. Injected (rather than read via `#available` here) so
|
|
20
|
+
/// the mapping is testable off-device.
|
|
21
|
+
init(for style: SectionStyle?, supportsWrappingGrid: Bool) {
|
|
22
|
+
guard style?.display == .grid else {
|
|
23
|
+
self = .list
|
|
24
|
+
return
|
|
25
|
+
}
|
|
26
|
+
if style?.gridWrap == false {
|
|
27
|
+
self = .singleLineRow
|
|
28
|
+
} else if supportsWrappingGrid {
|
|
29
|
+
self = .wrappingGrid
|
|
30
|
+
} else {
|
|
31
|
+
self = .list
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/// The accessory symbol a resolved block actually draws: nil when
|
|
36
|
+
/// undeclared, and nil for the `'none'` sentinel — the inheritance escape
|
|
37
|
+
/// that restores the derived accessory (a browsable row's chevron). Here,
|
|
38
|
+
/// not in the CarPlay factory, so the sentinel rule is testable off-device.
|
|
39
|
+
static func effectiveAccessorySymbol(_ style: TrackStyle?) -> String? {
|
|
40
|
+
guard let symbol = style?.accessorySymbol, symbol != "none" else { return nil }
|
|
41
|
+
return symbol
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/// The element family a tile presentation renders on iOS 26+ — here, not
|
|
45
|
+
/// in the CarPlay factory, so the style→family mapping is testable
|
|
46
|
+
/// off-device. `gridTile` picks the family (plain by default); the plain
|
|
47
|
+
/// single-line shelf keeps row elements, the one plain element with a
|
|
48
|
+
/// subtitle slot. Pre-26 has no element API at all: the treatment drops
|
|
49
|
+
/// with the legacy image row (decorations drop before layout).
|
|
50
|
+
enum TileElementFamily: Equatable {
|
|
51
|
+
case rowElements
|
|
52
|
+
case imageGridElements
|
|
53
|
+
case cardElements
|
|
54
|
+
case condensedElements
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
static func tileFamily(for style: SectionStyle?, singleLine: Bool) -> TileElementFamily {
|
|
58
|
+
switch style?.gridTile {
|
|
59
|
+
case .card: .cardElements
|
|
60
|
+
case .condensed: .condensedElements
|
|
61
|
+
case .plain, nil: singleLine ? .rowElements : .imageGridElements
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|