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
package/ios/TrackPlayer.swift
CHANGED
|
@@ -136,7 +136,7 @@ class TrackPlayer {
|
|
|
136
136
|
var previousTracks: [Track] { coordinator.previousTracks }
|
|
137
137
|
var isLastInPlaybackOrder: Bool { coordinator.isLastInPlaybackOrder }
|
|
138
138
|
var playbackActive: Bool { coordinator.playbackActive }
|
|
139
|
-
var sleepTimerManager:
|
|
139
|
+
var sleepTimerManager: any SleepTimerHandling { coordinator.sleepTimerManager }
|
|
140
140
|
var queue: QueueManager { coordinator.queue }
|
|
141
141
|
var loadSeekCoordinator: LoadSeekCoordinator { coordinator.loadSeekCoordinator }
|
|
142
142
|
var playingStateManager: PlayingStateManager { coordinator.playingStateManager }
|
|
@@ -195,12 +195,14 @@ class TrackPlayer {
|
|
|
195
195
|
return seconds.isNaN ? 0 : seconds
|
|
196
196
|
}
|
|
197
197
|
|
|
198
|
+
/// The current item's duration, or 0 when it has none (a live stream).
|
|
199
|
+
///
|
|
200
|
+
/// Don't reintroduce `item.asset.duration`: it is deprecated as of the iOS 16
|
|
201
|
+
/// minimum and blocks the main actor fetching a remote asset's duration. Read
|
|
202
|
+
/// on every progress tick.
|
|
198
203
|
var duration: Double {
|
|
199
204
|
guard let item = avPlayer.currentItem else { return 0.0 }
|
|
200
205
|
|
|
201
|
-
if !item.asset.duration.seconds.isNaN {
|
|
202
|
-
return item.asset.duration.seconds
|
|
203
|
-
}
|
|
204
206
|
if !item.duration.seconds.isNaN {
|
|
205
207
|
return item.duration.seconds
|
|
206
208
|
}
|
|
@@ -252,8 +254,22 @@ class TrackPlayer {
|
|
|
252
254
|
var rate: Float {
|
|
253
255
|
get { coordinator.rate }
|
|
254
256
|
set {
|
|
257
|
+
// A non-positive rate leaves the player unable to play at all — and would
|
|
258
|
+
// poison the next play() through `defaultRate` below. Rejected here, at
|
|
259
|
+
// the one setter every source funnels through (JS, remote command, CarPlay
|
|
260
|
+
// rate cycling, a restored snapshot), rather than at each of them.
|
|
261
|
+
guard newValue > 0 else { return }
|
|
255
262
|
coordinator.rate = newValue
|
|
256
|
-
|
|
263
|
+
// Assigning a nonzero `AVPlayer.rate` IS `play()` — so setting the speed
|
|
264
|
+
// while paused would start audible playback behind the user's back, with
|
|
265
|
+
// `playWhenReady` still false (the lock screen would read "paused" over
|
|
266
|
+
// sound). On Android and web the speed control is independent of the play
|
|
267
|
+
// intent; this keeps iOS the same.
|
|
268
|
+
avPlayer.defaultRate = newValue
|
|
269
|
+
if playWhenReady { avPlayer.rate = newValue }
|
|
270
|
+
// Same reason as the repeat/shuffle edges below — a speed changed while
|
|
271
|
+
// paused would otherwise not reach the snapshot the cold resume restores.
|
|
272
|
+
persistPlaybackState()
|
|
257
273
|
}
|
|
258
274
|
}
|
|
259
275
|
|
|
@@ -312,17 +328,6 @@ class TrackPlayer {
|
|
|
312
328
|
coordinator.load(track, playWhenReady: playWhenReady)
|
|
313
329
|
}
|
|
314
330
|
|
|
315
|
-
func togglePlaying() {
|
|
316
|
-
switch avPlayer.timeControlStatus {
|
|
317
|
-
case .playing, .waitingToPlayAtSpecifiedRate:
|
|
318
|
-
pause()
|
|
319
|
-
case .paused:
|
|
320
|
-
play()
|
|
321
|
-
@unknown default:
|
|
322
|
-
fatalError("Unknown AVPlayer.timeControlStatus")
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
|
|
326
331
|
func play() { coordinator.play() }
|
|
327
332
|
func pause() { coordinator.pause() }
|
|
328
333
|
func togglePlayback() { coordinator.togglePlayback() }
|
|
@@ -456,13 +461,17 @@ class TrackPlayer {
|
|
|
456
461
|
)
|
|
457
462
|
}
|
|
458
463
|
|
|
464
|
+
/// Empties the queue and the published now-playing info. Unlinking the
|
|
465
|
+
/// session belongs in `destroy()`: `avPlayer` survives a clear, and only
|
|
466
|
+
/// `setupAVPlayer()` re-links.
|
|
459
467
|
func clear() {
|
|
460
468
|
coordinator.clear()
|
|
461
|
-
nowPlayingInfoController.unlinkPlayer()
|
|
462
469
|
}
|
|
463
470
|
|
|
464
471
|
func destroy() {
|
|
465
472
|
clear()
|
|
473
|
+
// The player is going away for good — now the session must go with it.
|
|
474
|
+
nowPlayingInfoController.unlinkPlayer()
|
|
466
475
|
// An AVPlayer retains its time observers: one left registered is still attached when the
|
|
467
476
|
// player is released, and outlives this object.
|
|
468
477
|
playerTimeObserver.unregisterForBoundaryTimeEvents()
|
|
@@ -550,10 +559,12 @@ class TrackPlayer {
|
|
|
550
559
|
|
|
551
560
|
nowPlayingInfoController.linkPlayer(avPlayer)
|
|
552
561
|
|
|
562
|
+
// Stage the rate unconditionally, so a freshly recreated player carries it
|
|
563
|
+
// before anything plays — `rate`'s setter holds the same invariant, and on
|
|
564
|
+
// the playWhenReady branch below `defaultRate` was previously left at 1.0.
|
|
565
|
+
avPlayer.defaultRate = rate
|
|
553
566
|
if playWhenReady {
|
|
554
567
|
startPlayback()
|
|
555
|
-
} else {
|
|
556
|
-
avPlayer.defaultRate = rate
|
|
557
568
|
}
|
|
558
569
|
}
|
|
559
570
|
|
|
@@ -755,13 +766,28 @@ extension TrackPlayer {
|
|
|
755
766
|
PersistedPlaybackState(
|
|
756
767
|
track: JsonTrack(from: track),
|
|
757
768
|
positionMs: positionMs,
|
|
758
|
-
repeatMode: repeatMode.
|
|
769
|
+
repeatMode: repeatMode.stringValue,
|
|
759
770
|
shuffleEnabled: shuffleEnabled,
|
|
760
771
|
playbackSpeed: rate,
|
|
761
772
|
),
|
|
762
773
|
)
|
|
763
774
|
}
|
|
764
775
|
|
|
776
|
+
/// Applies the player settings a snapshot carries — the inverse of
|
|
777
|
+
/// `persistPlaybackState()`, and the twin of the Kotlin store's `restore()`.
|
|
778
|
+
///
|
|
779
|
+
/// Call BEFORE building the queue: `setQueue` rebuilds the shuffle order
|
|
780
|
+
/// pinned to the starting track, so shuffle has to be set for that order to
|
|
781
|
+
/// be the one playback uses (and the mode events then precede the
|
|
782
|
+
/// queue-changed event, as on Android). An unrecognized repeat mode restores
|
|
783
|
+
/// as `.off` rather than failing the whole resume over one field; a
|
|
784
|
+
/// non-positive speed is rejected by `rate`'s own setter.
|
|
785
|
+
func restorePlaybackSettings(from state: PersistedPlaybackState) {
|
|
786
|
+
repeatMode = RepeatMode(fromString: state.repeatMode) ?? .off
|
|
787
|
+
shuffleEnabled = state.shuffleEnabled
|
|
788
|
+
rate = state.playbackSpeed
|
|
789
|
+
}
|
|
790
|
+
|
|
765
791
|
/// Start a 5 s repeating save while playback is active. A previous task is
|
|
766
792
|
/// cancelled first so there is never more than one running at a time.
|
|
767
793
|
private func startPeriodicSave() {
|
|
@@ -781,17 +807,6 @@ extension TrackPlayer {
|
|
|
781
807
|
}
|
|
782
808
|
}
|
|
783
809
|
|
|
784
|
-
private extension RepeatMode {
|
|
785
|
-
/// String representation stored in `PersistedPlaybackState.repeatMode`.
|
|
786
|
-
var persistedString: String {
|
|
787
|
-
switch self {
|
|
788
|
-
case .off: "off"
|
|
789
|
-
case .track: "track"
|
|
790
|
-
case .queue: "queue"
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
}
|
|
794
|
-
|
|
795
810
|
// MARK: - PlaybackEffectHandler
|
|
796
811
|
|
|
797
812
|
extension TrackPlayer: PlaybackEffectHandler {
|
|
@@ -857,15 +872,23 @@ extension TrackPlayer: PlaybackEffectHandler {
|
|
|
857
872
|
}
|
|
858
873
|
|
|
859
874
|
func clearNowPlaying() {
|
|
860
|
-
|
|
875
|
+
nowPlayingUpdater.clearNowPlaying()
|
|
861
876
|
}
|
|
862
877
|
|
|
878
|
+
// Both persist: a snapshot is otherwise only written on track load, on pause,
|
|
879
|
+
// and every 5s while playing, so a mode toggled while paused was lost — the
|
|
880
|
+
// cold-start resume would restore the value from before the toggle. Android
|
|
881
|
+
// persists on every setting change (`PlayerListener.onRepeatModeChanged` /
|
|
882
|
+
// `onShuffleModeEnabledChanged`); these are the same two edges, and the
|
|
883
|
+
// coordinator only calls them on a real change.
|
|
863
884
|
func updateRemoteRepeatMode(_ mode: RepeatMode) {
|
|
864
885
|
remoteCommandController.updateRepeatMode(mode)
|
|
886
|
+
persistPlaybackState()
|
|
865
887
|
}
|
|
866
888
|
|
|
867
889
|
func updateRemoteShuffleMode(_ enabled: Bool) {
|
|
868
890
|
remoteCommandController.updateShuffleMode(enabled)
|
|
891
|
+
persistPlaybackState()
|
|
869
892
|
}
|
|
870
893
|
|
|
871
894
|
func updateSkipAvailability(canNext: Bool, canPrevious: Bool) {
|
|
@@ -884,8 +907,8 @@ extension TrackPlayer: TrackSelectionPlayer {}
|
|
|
884
907
|
// MARK: - Queue Methods (thin forwarders)
|
|
885
908
|
|
|
886
909
|
extension TrackPlayer {
|
|
887
|
-
func replace(_ index: Int, _ track: Track) {
|
|
888
|
-
coordinator.replace(index, track)
|
|
910
|
+
func replace(_ index: Int, _ track: Track) throws {
|
|
911
|
+
try coordinator.replace(index, track)
|
|
889
912
|
}
|
|
890
913
|
|
|
891
914
|
func setQueue(
|
package/ios/TrackSelector.swift
CHANGED
|
@@ -5,7 +5,7 @@ import os.log
|
|
|
5
5
|
|
|
6
6
|
@MainActor protocol TrackSelectionBrowser {
|
|
7
7
|
func awaitTrackLoadHandler(event: TrackLoadEvent) async -> Bool
|
|
8
|
-
func
|
|
8
|
+
func expandQueueFromContextualPath(_ path: String) async throws -> (tracks: [Track], selectedIndex: Int)?
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
@MainActor protocol TrackSelectionPlayer {
|
|
@@ -36,9 +36,9 @@ class TrackSelector {
|
|
|
36
36
|
case play(PlaybackIntent)
|
|
37
37
|
/// JS handleTrackLoad handler intercepted — caller should not play.
|
|
38
38
|
case intercepted
|
|
39
|
-
/// Track is browsable — caller should navigate to this
|
|
40
|
-
case browse(
|
|
41
|
-
/// Nothing to do (no src, no
|
|
39
|
+
/// Track is browsable — caller should navigate to this path.
|
|
40
|
+
case browse(path: String)
|
|
41
|
+
/// Nothing to do (no src, no path).
|
|
42
42
|
case none
|
|
43
43
|
}
|
|
44
44
|
|
|
@@ -54,16 +54,22 @@ class TrackSelector {
|
|
|
54
54
|
// MARK: - Selection
|
|
55
55
|
|
|
56
56
|
/// Resolves a track selection to a concrete action.
|
|
57
|
-
/// Handles contextual
|
|
57
|
+
/// Handles contextual path expansion, queue reuse, and handler interception.
|
|
58
58
|
func select(
|
|
59
59
|
track: Track,
|
|
60
60
|
player: some TrackSelectionPlayer,
|
|
61
61
|
) async -> SelectionResult {
|
|
62
|
-
|
|
62
|
+
// A disabled track is unavailable — it never plays, whichever surface or
|
|
63
|
+
// stale resume path delivered the selection (Track.disabled).
|
|
64
|
+
if track.disabled == true {
|
|
65
|
+
return .none
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let path = track.path
|
|
63
69
|
|
|
64
|
-
// 1. Contextual
|
|
65
|
-
if let
|
|
66
|
-
return await
|
|
70
|
+
// 1. Contextual path (playable-only track with queue context)
|
|
71
|
+
if let path, BrowserPathHelper.isContextual(path) {
|
|
72
|
+
return await handleContextualPath(path, track: track, player: player)
|
|
67
73
|
}
|
|
68
74
|
|
|
69
75
|
// 2. Has src — single playable track
|
|
@@ -71,9 +77,9 @@ class TrackSelector {
|
|
|
71
77
|
return await handlePlayableTrack(track, player: player)
|
|
72
78
|
}
|
|
73
79
|
|
|
74
|
-
// 3. Has
|
|
75
|
-
if let
|
|
76
|
-
return .browse(
|
|
80
|
+
// 3. Has path — browsable
|
|
81
|
+
if let path {
|
|
82
|
+
return .browse(path: path)
|
|
77
83
|
}
|
|
78
84
|
|
|
79
85
|
// 4. Neither
|
|
@@ -82,31 +88,40 @@ class TrackSelector {
|
|
|
82
88
|
|
|
83
89
|
// MARK: - Private Helpers
|
|
84
90
|
|
|
85
|
-
private func
|
|
86
|
-
_
|
|
91
|
+
private func handleContextualPath(
|
|
92
|
+
_ path: String,
|
|
87
93
|
track: Track,
|
|
88
94
|
player: some TrackSelectionPlayer,
|
|
89
95
|
) async -> SelectionResult {
|
|
90
|
-
let parentPath = BrowserPathHelper.stripTrackId(
|
|
91
|
-
let trackId = BrowserPathHelper.extractTrackId(
|
|
92
|
-
|
|
93
|
-
// Check if queue already came from this parent path — just skip to the
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
96
|
+
let parentPath = BrowserPathHelper.stripTrackId(path)
|
|
97
|
+
let trackId = BrowserPathHelper.extractTrackId(path)
|
|
98
|
+
|
|
99
|
+
// Check if queue already came from this parent path — just skip to the
|
|
100
|
+
// track. Exact-surface match first: a contextual path carries the tapped
|
|
101
|
+
// page position (`__index`), so path equality pins the exact copy when
|
|
102
|
+
// the page holds the same identity more than once. The identity match
|
|
103
|
+
// remains for index-less paths (e.g. pre-stamp persisted state); an
|
|
104
|
+
// index-stamped path with no exact match falls through to expansion,
|
|
105
|
+
// which re-scopes the queue to the tapped section.
|
|
106
|
+
if parentPath == player.queueSourcePath {
|
|
107
|
+
var skipIndex = player.tracks.firstIndex(where: { $0.path == path })
|
|
108
|
+
if skipIndex == nil, BrowserPathHelper.extractIndex(path) == nil, let trackId {
|
|
109
|
+
skipIndex = player.tracks.firstIndex(where: { $0.identity == trackId })
|
|
110
|
+
}
|
|
111
|
+
if let index = skipIndex {
|
|
112
|
+
logger.debug("Queue already from \(parentPath), skipping to index \(index)")
|
|
113
|
+
let queue = player.tracks
|
|
114
|
+
let event = TrackLoadEvent(track: track, queue: queue, startIndex: Double(index))
|
|
115
|
+
if await browserManager.awaitTrackLoadHandler(event: event) {
|
|
116
|
+
return .intercepted
|
|
117
|
+
}
|
|
118
|
+
return .play(.skipTo(index: index))
|
|
103
119
|
}
|
|
104
|
-
return .play(.skipTo(index: index))
|
|
105
120
|
}
|
|
106
121
|
|
|
107
|
-
// Expand the queue from the contextual
|
|
122
|
+
// Expand the queue from the contextual path
|
|
108
123
|
do {
|
|
109
|
-
if let expanded = try await browserManager.
|
|
124
|
+
if let expanded = try await browserManager.expandQueueFromContextualPath(path) {
|
|
110
125
|
let (tracks, startIndex) = expanded
|
|
111
126
|
let event = TrackLoadEvent(track: track, queue: tracks, startIndex: Double(startIndex))
|
|
112
127
|
if await browserManager.awaitTrackLoadHandler(event: event) {
|
|
@@ -8,7 +8,11 @@ enum ArtworkImageFetcher {
|
|
|
8
8
|
private static let logger = Logger(subsystem: "com.audiobrowser", category: "ArtworkImageFetcher")
|
|
9
9
|
|
|
10
10
|
@MainActor
|
|
11
|
-
static func fetchImage(
|
|
11
|
+
static func fetchImage(
|
|
12
|
+
from source: ImageSource,
|
|
13
|
+
svgScale: CGFloat? = nil,
|
|
14
|
+
downsampleTo: (size: CGSize, scale: CGFloat)? = nil,
|
|
15
|
+
) async -> UIImage? {
|
|
12
16
|
guard let url = URL(string: source.uri) else { return nil }
|
|
13
17
|
|
|
14
18
|
var options: KingfisherOptionsInfo = []
|
|
@@ -24,6 +28,17 @@ enum ArtworkImageFetcher {
|
|
|
24
28
|
}
|
|
25
29
|
if let svgScale {
|
|
26
30
|
options.append(.processor(SVGProcessor(size: nil, scale: svgScale)))
|
|
31
|
+
} else if let downsampleTo {
|
|
32
|
+
// Downsample rasters at decode time. Any size hint passed upstream (the
|
|
33
|
+
// resolver's ImageContext) is advisory — a CDN can ignore it and return
|
|
34
|
+
// the original — so this is the only sizing that is guaranteed to
|
|
35
|
+
// happen. The processed image is cached under a size-qualified key;
|
|
36
|
+
// cacheOriginalImage keeps the untouched original in the disk cache so
|
|
37
|
+
// the same URL at another target size re-processes instead of
|
|
38
|
+
// re-downloading.
|
|
39
|
+
options.append(.processor(DownsamplingImageProcessor(size: downsampleTo.size)))
|
|
40
|
+
options.append(.scaleFactor(downsampleTo.scale))
|
|
41
|
+
options.append(.cacheOriginalImage)
|
|
27
42
|
}
|
|
28
43
|
|
|
29
44
|
do {
|
|
@@ -11,13 +11,36 @@ final class NetworkMonitor: @unchecked Sendable {
|
|
|
11
11
|
private let monitor: NWPathMonitor
|
|
12
12
|
private let queue = DispatchQueue(label: "com.audiobrowser.networkmonitor")
|
|
13
13
|
|
|
14
|
-
///
|
|
15
|
-
private
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
/// Guards `_isOnline` only. Never held across `onChanged` — see `apply`.
|
|
15
|
+
private let lock = NSLock()
|
|
16
|
+
private var _isOnline = false
|
|
17
|
+
|
|
18
|
+
/// Current network connectivity state. Readable from any thread: the value is
|
|
19
|
+
/// lock-protected rather than confined, so callers on the JS thread (Nitro's
|
|
20
|
+
/// `getOnline`) don't have to block on a main-queue hop to read a Bool.
|
|
21
|
+
///
|
|
22
|
+
/// The broadcast is main-confined even though the value isn't — `onChanged`
|
|
23
|
+
/// fans out to the JS bridge, a now-playing re-render and a player reload, so
|
|
24
|
+
/// it must not run under the lock (reentrancy) or off the main actor.
|
|
25
|
+
var isOnline: Bool {
|
|
26
|
+
lock.lock()
|
|
27
|
+
defer { lock.unlock() }
|
|
28
|
+
return _isOnline
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/// Stores a new status and, if it actually changed, broadcasts on main —
|
|
32
|
+
/// outside the lock.
|
|
33
|
+
private func apply(_ newStatus: Bool) {
|
|
34
|
+
lock.lock()
|
|
35
|
+
let changed = _isOnline != newStatus
|
|
36
|
+
let oldValue = _isOnline
|
|
37
|
+
_isOnline = newStatus
|
|
38
|
+
lock.unlock()
|
|
39
|
+
|
|
40
|
+
guard changed else { return }
|
|
41
|
+
logger.notice("Network status changed: \(oldValue) -> \(newStatus)")
|
|
42
|
+
DispatchQueue.main.async { [weak self] in
|
|
43
|
+
self?.onChanged?(newStatus)
|
|
21
44
|
}
|
|
22
45
|
}
|
|
23
46
|
|
|
@@ -31,29 +54,23 @@ final class NetworkMonitor: @unchecked Sendable {
|
|
|
31
54
|
init() {
|
|
32
55
|
monitor = NWPathMonitor()
|
|
33
56
|
|
|
34
|
-
//
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
// Start monitoring
|
|
43
|
-
monitor.start(queue: queue)
|
|
44
|
-
|
|
45
|
-
// Read initial state after starting (currentPath is now valid)
|
|
57
|
+
// Seed BEFORE `start`. `start` publishes `self` to the monitor queue, so any
|
|
58
|
+
// write after it races the handler's locked write — and would clobber a real
|
|
59
|
+
// update with a `currentPath` the monitor hasn't finished evaluating. Nothing
|
|
60
|
+
// recovers from that: the handler has already fired, `onChanged` isn't wired
|
|
61
|
+
// until setupPlayer, and the stale value then drives `getOnline()`, the JS
|
|
62
|
+
// event, and RetryManager's offline parking until the next genuine path
|
|
63
|
+
// change. Seeding first is a best-effort guess; the handler fires shortly
|
|
64
|
+
// after `start` and is the authoritative last writer.
|
|
46
65
|
let initialStatus = monitor.currentPath.status == .satisfied
|
|
47
66
|
logger.notice("NetworkMonitor initialized, initial isOnline=\(initialStatus)")
|
|
48
|
-
|
|
49
|
-
}
|
|
67
|
+
_isOnline = initialStatus
|
|
50
68
|
|
|
51
|
-
|
|
69
|
+
monitor.pathUpdateHandler = { [weak self] path in
|
|
70
|
+
self?.apply(path.status == .satisfied)
|
|
71
|
+
}
|
|
52
72
|
|
|
53
|
-
|
|
54
|
-
/// - Returns: true if device is online, false otherwise
|
|
55
|
-
func getOnline() -> Bool {
|
|
56
|
-
isOnline
|
|
73
|
+
monitor.start(queue: queue)
|
|
57
74
|
}
|
|
58
75
|
|
|
59
76
|
/// Stops monitoring and cleans up resources.
|
|
@@ -11,13 +11,21 @@ final class SFSymbolRenderer: @unchecked Sendable {
|
|
|
11
11
|
@MainActor static let shared = SFSymbolRenderer()
|
|
12
12
|
static let defaultCanvasSize = CGSize(width: 200, height: 200)
|
|
13
13
|
|
|
14
|
+
/// Bumped whenever the rendering below changes (symbol point-size factor,
|
|
15
|
+
/// centering, tinting, background fill). It is part of the cache filename
|
|
16
|
+
/// because `.cachesDirectory` survives app updates and the existence check is
|
|
17
|
+
/// the only cache validation — without a version key, every device that had
|
|
18
|
+
/// rendered a symbol once would keep serving the OLD pixels forever after a
|
|
19
|
+
/// render change.
|
|
20
|
+
private static let renderVersion = 1
|
|
21
|
+
|
|
14
22
|
private let logger = Logger(subsystem: "com.audiobrowser", category: "SFSymbolRenderer")
|
|
15
23
|
private let scale: CGFloat
|
|
16
24
|
private let cacheDirectory: URL
|
|
17
25
|
|
|
18
26
|
@MainActor
|
|
19
27
|
private init() {
|
|
20
|
-
scale =
|
|
28
|
+
scale = appDisplayScale
|
|
21
29
|
|
|
22
30
|
let caches = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]
|
|
23
31
|
cacheDirectory = caches.appendingPathComponent("sf-symbols", isDirectory: true)
|
|
@@ -45,7 +53,8 @@ final class SFSymbolRenderer: @unchecked Sendable {
|
|
|
45
53
|
let safeArtwork = artworkValue.unicodeScalars
|
|
46
54
|
.filter { CharacterSet.alphanumerics.contains($0) || $0 == "_" }
|
|
47
55
|
.map(String.init).joined()
|
|
48
|
-
let fileName =
|
|
56
|
+
let fileName =
|
|
57
|
+
"\(safeArtwork)_\(Int(canvasSize.width))x\(Int(canvasSize.height))_\(Int(scale))x_v\(Self.renderVersion)"
|
|
49
58
|
let fileURL = cacheDirectory.appendingPathComponent("\(fileName).png")
|
|
50
59
|
|
|
51
60
|
if FileManager.default.fileExists(atPath: fileURL.path) {
|
|
@@ -139,4 +148,17 @@ extension UIColor {
|
|
|
139
148
|
self.init(white: 0, alpha: 1)
|
|
140
149
|
}
|
|
141
150
|
}
|
|
151
|
+
|
|
152
|
+
/// Failable form for *declared* colors (`style.cardTint`): anything but a
|
|
153
|
+
/// 3- or 6-digit hex value is nil, so an unparseable declaration degrades
|
|
154
|
+
/// to "no declaration" (the system default) instead of rendering black —
|
|
155
|
+
/// matching how unknown enum values decode. `init(hex:)` keeps its lenient
|
|
156
|
+
/// black fallback for the `sf:` artwork params it has always served.
|
|
157
|
+
convenience init?(declaredHex hex: String) {
|
|
158
|
+
let digits = hex.trimmingCharacters(in: CharacterSet(charactersIn: "#"))
|
|
159
|
+
guard [3, 6].contains(digits.count),
|
|
160
|
+
digits.allSatisfy(\.isHexDigit)
|
|
161
|
+
else { return nil }
|
|
162
|
+
self.init(hex: hex)
|
|
163
|
+
}
|
|
142
164
|
}
|
|
@@ -4,7 +4,14 @@ import UIKit
|
|
|
4
4
|
|
|
5
5
|
/// Kingfisher processor that renders SVG data to UIImage using SwiftDraw.
|
|
6
6
|
struct SVGProcessor: ImageProcessor {
|
|
7
|
-
|
|
7
|
+
/// Kingfisher keys its cache on `identifier` alone (`ImageCache.computedKey`),
|
|
8
|
+
/// and `.scaleFactor` never enters that key — so the render parameters have to,
|
|
9
|
+
/// or two different rasterizations of the same URL would collide. Today only
|
|
10
|
+
/// CarPlay rasterizes SVGs (one screen, one scale), so this is insurance
|
|
11
|
+
/// against a second call site rather than a live fix.
|
|
12
|
+
var identifier: String {
|
|
13
|
+
"com.audiobrowser.svgprocessor(\(size?.width ?? -1)x\(size?.height ?? -1)@\(scale))"
|
|
14
|
+
}
|
|
8
15
|
|
|
9
16
|
/// Target size for rendering (in points). If nil, uses SVG's intrinsic size.
|
|
10
17
|
let size: CGSize?
|
|
@@ -15,7 +22,7 @@ struct SVGProcessor: ImageProcessor {
|
|
|
15
22
|
@MainActor
|
|
16
23
|
init(size: CGSize? = nil, scale: CGFloat? = nil) {
|
|
17
24
|
self.size = size
|
|
18
|
-
self.scale = scale ??
|
|
25
|
+
self.scale = scale ?? appDisplayScale
|
|
19
26
|
}
|
|
20
27
|
|
|
21
28
|
func process(item: ImageProcessItem, options _: KingfisherParsedOptionsInfo) -> KFCrossPlatformImage? {
|
|
@@ -25,6 +25,17 @@ Object.keys(_types).forEach(function (key) {
|
|
|
25
25
|
}
|
|
26
26
|
});
|
|
27
27
|
});
|
|
28
|
+
var _getTrackIdentity = require("./utils/getTrackIdentity");
|
|
29
|
+
Object.keys(_getTrackIdentity).forEach(function (key) {
|
|
30
|
+
if (key === "default" || key === "__esModule") return;
|
|
31
|
+
if (key in exports && exports[key] === _getTrackIdentity[key]) return;
|
|
32
|
+
Object.defineProperty(exports, key, {
|
|
33
|
+
enumerable: true,
|
|
34
|
+
get: function () {
|
|
35
|
+
return _getTrackIdentity[key];
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
});
|
|
28
39
|
var _useDebug = require("./utils/useDebug");
|
|
29
40
|
Object.keys(_useDebug).forEach(function (key) {
|
|
30
41
|
if (key === "default" || key === "__esModule") return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_features","require","Object","keys","forEach","key","exports","defineProperty","enumerable","get","_types","_useDebug"],"sourceRoot":"../../src","sources":["AudioBrowser.ts"],"mappings":";;;;;AACA,IAAAA,SAAA,GAAAC,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAH,SAAA,EAAAI,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAL,SAAA,CAAAK,GAAA;EAAAH,MAAA,CAAAK,cAAA,CAAAD,OAAA,EAAAD,GAAA;IAAAG,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAT,SAAA,CAAAK,GAAA;IAAA;EAAA;AAAA;AACA,IAAAK,MAAA,GAAAT,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAO,MAAA,EAAAN,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAK,MAAA,CAAAL,GAAA;EAAAH,MAAA,CAAAK,cAAA,CAAAD,OAAA,EAAAD,GAAA;IAAAG,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAC,MAAA,CAAAL,GAAA;IAAA;EAAA;AAAA;AACA,IAAAM,
|
|
1
|
+
{"version":3,"names":["_features","require","Object","keys","forEach","key","exports","defineProperty","enumerable","get","_types","_getTrackIdentity","_useDebug"],"sourceRoot":"../../src","sources":["AudioBrowser.ts"],"mappings":";;;;;AACA,IAAAA,SAAA,GAAAC,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAH,SAAA,EAAAI,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAL,SAAA,CAAAK,GAAA;EAAAH,MAAA,CAAAK,cAAA,CAAAD,OAAA,EAAAD,GAAA;IAAAG,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAT,SAAA,CAAAK,GAAA;IAAA;EAAA;AAAA;AACA,IAAAK,MAAA,GAAAT,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAO,MAAA,EAAAN,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAK,MAAA,CAAAL,GAAA;EAAAH,MAAA,CAAAK,cAAA,CAAAD,OAAA,EAAAD,GAAA;IAAAG,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAC,MAAA,CAAAL,GAAA;IAAA;EAAA;AAAA;AACA,IAAAM,iBAAA,GAAAV,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAQ,iBAAA,EAAAP,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAM,iBAAA,CAAAN,GAAA;EAAAH,MAAA,CAAAK,cAAA,CAAAD,OAAA,EAAAD,GAAA;IAAAG,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAE,iBAAA,CAAAN,GAAA;IAAA;EAAA;AAAA;AACA,IAAAO,SAAA,GAAAX,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAS,SAAA,EAAAR,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAO,SAAA,CAAAP,GAAA;EAAAH,MAAA,CAAAK,cAAA,CAAAD,OAAA,EAAAD,GAAA;IAAAG,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAG,SAAA,CAAAP,GAAA;IAAA;EAAA;AAAA","ignoreList":[]}
|
|
@@ -22,9 +22,12 @@ function isObjectValue(value) {
|
|
|
22
22
|
}
|
|
23
23
|
function isTransformableRequestConfig(source) {
|
|
24
24
|
if (!isObjectValue(source)) return false;
|
|
25
|
-
//
|
|
26
|
-
//
|
|
27
|
-
//
|
|
25
|
+
// A static ResolvedTrack page also carries a top-level `path`, so `path`
|
|
26
|
+
// alone cannot mark a request config. A page is recognised by its required
|
|
27
|
+
// `title` — no RequestConfig field is named `title`.
|
|
28
|
+
if ('title' in source) return false;
|
|
29
|
+
// Any RequestConfig key marks a request config. (A static ResolvedTrack's
|
|
30
|
+
// per-track request override is nested under `request`, not top-level.)
|
|
28
31
|
return 'baseUrl' in source || 'path' in source || 'headers' in source || 'query' in source || 'method' in source || 'body' in source || 'contentType' in source || 'userAgent' in source || 'transform' in source || 'transformSync' in source;
|
|
29
32
|
}
|
|
30
33
|
function isRouteConfig(source) {
|
|
@@ -87,7 +90,7 @@ function searchSourceToRouteEntry(source) {
|
|
|
87
90
|
*/
|
|
88
91
|
function wrapTracksAsResolvedTrack(tracks) {
|
|
89
92
|
return {
|
|
90
|
-
|
|
93
|
+
path: TABS_ROUTE_PATH,
|
|
91
94
|
title: 'Tabs',
|
|
92
95
|
children: tracks
|
|
93
96
|
};
|
|
@@ -191,10 +194,10 @@ function validateBrowserConfiguration(config) {
|
|
|
191
194
|
continue;
|
|
192
195
|
}
|
|
193
196
|
if (!isCallback(source) && !isRouteConfig(source) && !isTransformableRequestConfig(source)) {
|
|
194
|
-
// Falls through to the static-page branch; a page needs
|
|
197
|
+
// Falls through to the static-page branch; a page needs path + title.
|
|
195
198
|
const page = source;
|
|
196
|
-
if (typeof page.
|
|
197
|
-
warn(`route "${path}" matched no source shape — expected a callback, ` + `a request config ({ baseUrl, path, headers, ... }), a ` + `RouteConfig ({ browse, media, artwork }), or a static page ` + `({
|
|
199
|
+
if (typeof page.path !== 'string' || typeof page.title !== 'string') {
|
|
200
|
+
warn(`route "${path}" matched no source shape — expected a callback, ` + `a request config ({ baseUrl, path, headers, ... }), a ` + `RouteConfig ({ browse, media, artwork }), or a static page ` + `({ path, title, children? }). It will be served as static ` + `content and likely render a blank screen.`);
|
|
198
201
|
}
|
|
199
202
|
}
|
|
200
203
|
}
|
|
@@ -220,7 +223,7 @@ function toNativeConfig(config) {
|
|
|
220
223
|
handleTrackLoad: config.handleTrackLoad,
|
|
221
224
|
androidControllerOfflineError: config.androidControllerOfflineError,
|
|
222
225
|
carPlayLoadingTitle: config.carPlayLoadingTitle,
|
|
223
|
-
|
|
226
|
+
resolveAlbumPath: config.resolveAlbumPath,
|
|
224
227
|
formatNavigationError: config.formatNavigationError
|
|
225
228
|
};
|
|
226
229
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["isCallback","source","isObjectValue","value","isTransformableRequestConfig","isRouteConfig","artwork","splitLayer","layer","resolve","resolver","Promise","config","flattenBrowseSource","browseCallback","browseConfig","browseStatic","searchSourceToRouteEntry","path","SEARCH_ROUTE_PATH","searchCallback","searchConfig","wrapTracksAsResolvedTrack","tracks","
|
|
1
|
+
{"version":3,"names":["isCallback","source","isObjectValue","value","isTransformableRequestConfig","isRouteConfig","artwork","splitLayer","layer","resolve","resolver","Promise","config","flattenBrowseSource","browseCallback","browseConfig","browseStatic","searchSourceToRouteEntry","path","SEARCH_ROUTE_PATH","searchCallback","searchConfig","wrapTracksAsResolvedTrack","tracks","TABS_ROUTE_PATH","title","children","tabsSourceToRouteEntry","Array","isArray","wrappedCallback","flattenRouteEntry","browse","media","DEFAULT_ROUTE_PATH","exports","flattenRoutes","routes","tabs","search","entries","Object","push","length","undefined","MAX_TABS","validateBrowserConfiguration","warn","message","console","startsWith","page","toNativeConfig","request","requestResolver","browseResolver","nowPlayingArtwork","singleTrack","handleTrackLoad","androidControllerOfflineError","carPlayLoadingTitle","resolveAlbumPath","formatNavigationError"],"sourceRoot":"../../../src","sources":["features/browser-config.ts"],"mappings":"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","ignoreList":[]}
|